dan@CASEUS.WISC.EDU (Daniel M. Frank) (05/13/86)
Here is a random number generator my partner and I used for a simulation
project last spring. It's not terribly good, but the distributions seemed
adequate for what we were doing (and we did run some tests). Actually, we
built a pretty nifty simulation system using processes, with interprocess
communication via mailboxes. Worked fine, although a bit slow (on an XT).
#!/bin/sh ----cut here-----cut here-----cut here-----cut here-----
# This is a shell archive.
# Run the following text with /bin/sh to extract.
YASASTART=`pwd`
cat - << \Funky!Stuff! > rand.def
DEFINITION MODULE Rand;
EXPORT QUALIFIED
Random ;
PROCEDURE Random (): REAL;
END Rand.
Funky!Stuff!
cat - << \Funky!Stuff! > rand.mod
IMPLEMENTATION MODULE Rand;
CONST
MAXINT = 32767; (* ? *)
DEFAULTSEED = 7321;
NUMCALLS = 4;
VAR
a : ARRAY[0..54] OF INTEGER;
seed, maxRand: INTEGER;
p, range: INTEGER; (* p indexes into array a of random #'s, range
is range of numbers in array *)
(***************************************************************)
PROCEDURE RandGen();
VAR
i, ran: INTEGER;
BEGIN
FOR i := 0 TO 23 DO
ran := a[i] - a[i + 31];
IF ran < 0 THEN
INC(ran,maxRand);
END;
a[i] := ran;
END;
FOR i := 24 TO 54 DO
ran := a[i] - a[i - 24];
IF ran < 0 THEN
INC(ran,maxRand);
END;
a[i] := ran;
END;
END RandGen;
(*******************************************************************)
PROCEDURE InitRandom(VAR iRange, iSeed: INTEGER): INTEGER;
VAR
m, i, j, minSeed, maxSeed: INTEGER;
f, fPrev, fTmp: INTEGER; (* for computing Fibonacci numbers *)
BEGIN
(* Set the range and the window for legal seed values *)
IF iRange <= 0 THEN
iRange := MAXINT;
END;
minSeed := iRange DIV 10;
maxSeed := iRange - minSeed;
maxRand := iRange;
(* Set the first seed value *)
iSeed := DEFAULTSEED;
WHILE (iSeed < minSeed) DO
iSeed := iSeed * 3;
END;
WHILE (iSeed > maxSeed) DO
iSeed := iSeed DIV 3;
END;
(* Scatter other values through the array to get things started.
The values are (-1)^i * (iSeed*F(i-1) - F(i)) MOD MAXINT, 0<i<55,
where F(i) is the ith Fibonacci number. Scale the results to lie in
[0,maxRand). Then bake a few batches of random numbers to make things
even more random. *)
fPrev := iSeed;
a[0] := iSeed MOD maxRand;
f := 1;
FOR i := 1 TO 54 DO
j := (21 * i) MOD 55;
a[j] := f MOD maxRand;
m := a[j];
fTmp := f; f:= fPrev - f; fPrev := fTmp;
IF (f < 0) THEN
INC(f, MAXINT);
END;
END;
FOR i:= 1 TO NUMCALLS DO
RandGen();
END;
p := 54;
RETURN (iSeed);
END InitRandom;
(***************************************************************)
PROCEDURE RandomInt(seed: INTEGER): INTEGER;
BEGIN
DEC(p);
IF p < 0 THEN
RandGen();
p := 54;
END;
RETURN (a[p]) ;
END RandomInt;
(*******************************************************************)
PROCEDURE Random(): REAL;
VAR
rNum: REAL;
i: INTEGER;
BEGIN
i := RandomInt(seed);
rNum := FLOAT(i) / FLOAT(MAXINT) ;
RETURN (rNum);
END Random ;
BEGIN
range := 0; seed := 0;
seed := InitRandom(range, seed);
END Rand .
Funky!Stuff!