IMPLEMENTATION MODULE Numbers; (* * REPERTOIRE * Release 1.6 * By Charles Bradford and Cole Brecheen * (c) Copyright 1985-1992 PMI * Green Bay, Wisconsin * All rights reserved * (414) 468-6040 * * $Header: D:/logfiles/mods/numbers.mov 1.5 10 Mar 1991 15:31:10 coleb $ * *) IMPORT NumTypes; VAR Initialized : BOOLEAN; PROCEDURE Init(); BEGIN IF Initialized THEN RETURN; ELSE Initialized := TRUE; END; NumTypes.Init(); END Init; TYPE LongConverter = RECORD CASE : BOOLEAN OF TRUE: long: LONGINT; | FALSE: locard, hicard: CARDINAL; END; END; PROCEDURE Between(min, x, max : CARDINAL) : CARDINAL; BEGIN IF min > max THEN max := min; END; IF x > max THEN RETURN max; ELSIF x < min THEN RETURN min; ELSE RETURN x; END; END Between; PROCEDURE C( num: LONGINT ): CARDINAL; BEGIN RETURN VAL( CARDINAL, num ); END C; PROCEDURE I( num: LONGINT ): INTEGER; BEGIN RETURN VAL( INTEGER, num ); END I; PROCEDURE CardIsBetween(min, x, max: CARDINAL): BOOLEAN; BEGIN RETURN (x >= min) AND (x <= max); END CardIsBetween; PROCEDURE CardSqrt( n: CARDINAL ): CARDINAL; VAR a2,b2,ab,t: CARDINAL; BEGIN a2 := 0; ab :=0; b2 := 1; WHILE b2 <= n DO b2 := 4*b2 END; WHILE b2 # 1 DO ab := ab DIV 2; b2 := b2 DIV 4; t := a2 + 2*ab + b2; IF t <= n THEN a2 := t; ab := ab+b2; END END; RETURN ab; END CardSqrt; PROCEDURE IntIsBetween(min, x, max: INTEGER): BOOLEAN; BEGIN RETURN (x >= min) AND (x <= max); END IntIsBetween; PROCEDURE IntMin(first, second : INTEGER) : INTEGER; BEGIN IF firstsecond THEN RETURN (first); ELSE RETURN (second); END; END IntMax; PROCEDURE Lc( num: CARDINAL ): LONGINT; BEGIN RETURN VAL( LONGINT, num ); END Lc; PROCEDURE Li( num: INTEGER ): LONGINT; BEGIN RETURN VAL( LONGINT, num ); END Li; PROCEDURE LowestCommonDenom(n1, n2 : INTEGER) : INTEGER; BEGIN n1 := ABS(n1); n2 := ABS(n2); WHILE n1#n2 DO IF n1 > n2 THEN n1 := n1-n2; ELSE n2 := n2-n1; END; END; RETURN n1; END LowestCommonDenom; PROCEDURE Min(first, second : CARDINAL) : CARDINAL; BEGIN IF firstsecond THEN RETURN (first); ELSE RETURN (second); END; END Max; PROCEDURE Power(x, n : CARDINAL) : CARDINAL; (*Returns x raised to the nth power.*) VAR w, z, i : CARDINAL; BEGIN w := x; i := n; z := 1; WHILE i<>0 DO IF ODD(i) THEN z := z*w; END; i := i DIV 2; IF i<>0 THEN w := w*w; END; END; RETURN (z); END Power; (*These two procedures look stupid, but the compilers are inconsistent about whether you can use VAL, TRUNC, and FLOAT to convert between reals, integers and longints. This conversion method works with all M2 compilers.*) PROCEDURE R8ToL( x: NumTypes.Real8 ): LONGINT; BEGIN IF x <= 65535.0 THEN RETURN Lc( TRUNC(x) ); ELSE RETURN Lc(TRUNC(x / 65535.0)) * NumTypes.L65535; END END R8ToL; PROCEDURE LToR8( TheLong: LONGINT ): NumTypes.Real8; VAR tmpreal: REAL; tmpr8: NumTypes.Real8; BEGIN IF TheLong <= NumTypes.L65535 THEN tmpreal := FLOAT( C(TheLong) ); ELSE TheLong := TheLong DIV NumTypes.L65535; tmpreal := FLOAT( C(TheLong) ) * 65535.0; END; tmpr8 := NumTypes.REALToReal8(tmpreal); RETURN tmpr8; END LToR8; PROCEDURE R8ToInt( x: NumTypes.Real8 ): INTEGER; BEGIN (*Let the RTS worry about errors here.*) RETURN TRUNC(x); END R8ToInt; PROCEDURE IntToR8( TheInt: INTEGER ): NumTypes.Real8; VAR tmpreal: REAL; tmpr8: NumTypes.Real8; BEGIN tmpreal := FLOAT( TheInt ); tmpr8 := NumTypes.REALToReal8(tmpreal); RETURN tmpr8; END IntToR8; BEGIN Initialized := FALSE; Init(); END Numbers.