{$N+,E+} {use math coprocessor if present} UNIT RandomNumbers; {16-bit random number generator from C. ACM, June 1988, "Efficient and Portable Combined Random Number Generators", pp. 742-749, 774. The "Uniform" function in the article (Fig. 4) was split into an integer "Random" function and the real "Uniform" function below. "It assumes that integers in the range [-32363, 32363] are well represented. The (global) integer variables s1, s2 and s3 must be initialized to values in the range [1, 32362], [1, 31726] and [1, 31656] respectively." efg, 12 Aug 1988; modified for math coprocessor 11 Oct 1990} INTERFACE TYPE RealType = DOUBLE; PROCEDURE SetSeeds (a1,a2,a3: INTEGER); FUNCTION Random: INTEGER; FUNCTION RandomInteger (maxval: INTEGER): INTEGER; {0..maxval } FUNCTION Uniform: REAL; {0.0 .. 1.0 } IMPLEMENTATION VAR k : INTEGER; s1: INTEGER; {1..32362} s2: INTEGER; {1..31726} s3: INTEGER; {1..31656} z : INTEGER; PROCEDURE SetSeeds (a1,a2,a3: INTEGER); BEGIN s1 := a1; s2 := a2; s3 := a3 END {SetSeeds}; FUNCTION Random: INTEGER; {see p. 748, Fig. 4, C. ACM, June 1988} BEGIN k := s1 DIV 206; s1 := 157 * (s1 - k * 206) - k * 21; IF s1 < 0 THEN s1 := s1 + 32363; k := s2 DIV 217; s2 := 146 * (s2 - k * 217) - k * 45; IF s2 < 0 THEN s2 := s2 + 31727; k := s3 DIV 222; s3 := 142 * (s3 - k * 222) - k * 133; IF s3 < 0 THEN s3 := s3 + 31657; {fixed error, 28 Aug 2000} z := s1 - s2; IF z > 706 THEN z := z - 32362; z := z + s3; Random := z END {Random}; FUNCTION RandomInteger (maxval: INTEGER): INTEGER; {Returns INTEGER in range 0..maxval} BEGIN RandomInteger := ABS(Random) MOD (maxval + 1) END {RandomInteger}; FUNCTION Uniform: REAL; {Returns REAL in range 0.0 .. 1.0} BEGIN k := Random; IF k < 1 THEN k := k + 32362; Uniform := k * 3.0899E-5 END {Uniform}; BEGIN SetSeeds (12,23,34) {see p.748, C. ACM, June 1988} END {RandomNumbers}.