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!