{$N+,E+} {use math coprocessor if present} UNIT RandomNumbers; {32-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. 3) was split into an integer "Random" function and the real "Uniform" function below. The algorithm "works as long as the machine can represent all integers in the range [-2^31 + 85, 2^31 - 85]. The integer variables s1 and s2 ... must be initialized to values in the range [1, 2147483562] and [1, 2147483398] respectively. Notice the function will never return 0.0 or 1.0, as long as REAL variables have at least [a] 23-bit mantissa." efg, 12 Aug 1988; modified for math coprocessor 10 Oct 1990} INTERFACE TYPE RealType = DOUBLE; PROCEDURE SetSeeds (a1,a2: LongINT); FUNCTION Random: LongINT; FUNCTION RandomInteger (maxval: LongINT): LongINT; {0..maxval } FUNCTION Uniform: RealType; {0.0 .. 1.0 } IMPLEMENTATION VAR k : LongINT; s1: LongINT; {1..2147483562} s2: LongINT; {1..2147483398} z : LongINT; PROCEDURE SetSeeds (a1,a2: LongINT); BEGIN s1 := a1; s2 := a2 END {SetSeeds}; FUNCTION Random: LongINT; BEGIN k := s1 DIV 53668; s1 := 40014 * (s1 - k * 53668) - k * 12211; IF s1 < 0 THEN s1 := s1 + 2147483563; k := s2 DIV 52774; s2 := 40692 * (s2 - k * 52774) - k * 3791; IF s2 < 0 THEN s2 := s2 + 2147483399; z := s1 - s2; Random := z END {Random}; FUNCTION RandomInteger (maxval: LongINT): LongINT; {Returns LongINT in range 0..maxval} BEGIN RandomInteger := ABS(Random) MOD (maxval + 1) END {RandomInteger}; FUNCTION Uniform: RealType; {Returns real in range 0.0 .. 1.0} BEGIN k := Random; IF k < 1 THEN k := k + 2147483562; Uniform := k * 4.656613E-10 END {Uniform}; BEGIN SetSeeds (12345,67890) {see p. 748, C. ACM, June 1988} END {RandomNumbers}.