MODULE; RandomParkMiller
Arithmetic for Modula-3, see doc for detailsAbstract: <describe>
1/1/96 <name> Initial version
IMPORT LongRealBasic AS R; FROM RandomBasic IMPORT Min, Max; IMPORT RandomRep, RandomBasic; CONST Module = "RandomParkMiller."; CONST TableSize = 32; (* for Bayes-Durham shuffle *) REVEAL T = TPublic BRANDED OBJECT z1, table_z: INTEGER; table : ARRAY [0 .. TableSize - 1] OF INTEGER; OVERRIDES init := Init; engine := Engine; END; CONST m = 2147483647; m_recip = R.One / FLOAT(m, R.T); a = 48271; q = 44488; r = 3399; PROCEDUREInit (SELF: T; seed: [1 .. LAST(INTEGER)] := 1; ): T = VAR z1, tmp: INTEGER; BEGIN SELF.z1 := seed; z1 := SELF.z1; FOR i := FIRST(SELF.table) TO LAST(SELF.table) DO tmp := z1 DIV q; z1 := a * (z1 - tmp * q) - r * tmp; IF z1 < 0 THEN INC(z1, m) END; SELF.table[i] := z1; END; SELF.z1 := z1; SELF.table_z := SELF.table[2]; RETURN SELF; END Init; PROCEDUREEngine (SELF: T; ): R.T = <* UNUSED *> CONST ftn = Module & "Engine"; VAR z1, table_z, tmp, ndx: INTEGER; result : R.T; BEGIN (*---get the raw result---*) z1 := SELF.z1; tmp := z1 DIV q; z1 := a * (z1 - tmp * q) - r * tmp; IF z1 < 0 THEN INC(z1, m) END; (*---do the shuffle---*) table_z := SELF.table_z; ndx := table_z - (table_z DIV TableSize) * TableSize; table_z := SELF.table[ndx]; SELF.table[ndx] := z1; (*---convert and check for out of bounds---*) result := FLOAT(table_z, R.T) * m_recip; IF result < Min THEN result := Min; ELSIF result > Max THEN result := Max; END; (*---save data and close---*) SELF.z1 := z1; SELF.table_z := table_z; RETURN result; END Engine; BEGIN END RandomParkMiller.