A Better BETWEEN

2008-12-02

Background

Forth-94 WITHIN was intended to replace BETWEEN but it hasn't been a comfortable fit.

A characteristic of  WITHIN is that the upper limit is not included in the range.  This is useful when comparing memory addresses. In other situations it is less appropriate, leading to clumsy or obfuscated code e.g.

    ( char )  CHAR a  CHAR z 1+  WITHIN  ( flag )

BETWEEN is better suited to this application as its limits are inclusive:

    ( char )  CHAR a  CHAR z  BETWEEN  ( flag )

Since WITHIN and BETWEEN each have their uses, some forth systems elect to provide both.

Implementation

Early versions of BETWEEN used only signed arguments. Today BETWEEN is commonly implemented as:

: BETWEEN  ( n1|u1 n2|u2 n3|u3 -- flag )  1+ WITHIN ;

This is simple and works with either signed or unsigned numbers. Unfortunately it has a problem - it fails when  u1 = u3 = MAX-U .

There is an alternative implementation available which does not have this limitation.

: BETWEEN  ( n1|u1 n2|u2 n3|u3 -- flag )  OVER - -ROT - U< 0= ;

This works over the entire number range and is based on the same algorithm most forths use to implement WITHIN.

Note: As with the algorithm for WITHIN (A.6.2.2440), this implementation is restricted to 2's complement machines.

Formal definition

BETWEEN
 
( n1|u1 n2|u2 n3|u3 -- flag )
 
Perform a comparison of a test value n1|u1 with a lower limit n2|u2 and an upper limit n3|u3, returning true if either (n2|u2 <= n3|u3 and (n2|u2 <= n1|u1 and n1|u1 < n3|u3)) or (n2|u2 >= n3|u3 and (n2|u2 <= n1|u1 or n1|u1 < n3|u3)) is true, returning false otherwise. An ambiguous condition exists if n1|u1, n2|u2, and n3|u3 are not all the same type.

Sample machine-code implementation

\ Intel 80386 (32-bit native-code forth)

code BETWEEN  ( n1|u1 n2|u2 n3|u3 -- flag )
   sub ebx, 0 [ebp]
   mov ecx, 4 [ebp]
   sub ecx, 0 [ebp]
   cmp ebx, ecx
   sbb ebx, ebx
   not ebx
   lea ebp, 8 [ebp]
   ret
end-code
\ Intel 8086 (16-bit DTC/ITC forth)

code BETWEEN  ( n1|u1 n2|u2 n3|u3 -- flag )
   bx pop  ax pop  cx pop
   ax bx sub  ax cx sub  cx bx cmp
   bx bx sbb  bx not  bx push  next
end-code
Top    Home    Forth

em.gif (457 bytes)


web analytics

Page updated: 04 Dec 2008