Murus : Random.def
In order to set a random colour (for some obscure reason) the random number generator was necessary. Dr Maurer used one made by Donald Knuth. I think I would have preferred the one from 'Programming in Oberon' (Reiser and Wirth).
DEFINITION MODULE Random;
(* (c) Christian Maurer v. 12. Februar 2006 *)
(* Edited by Jan Verhoeven, Aug 2008 *)
PROCEDURE init;
PROCEDURE Number (n : CARDINAL) : CARDINAL;
(* Returns a random number as follows:
CASE n OF
0 : number between 1 and MAX (CARDINAL)
ELSE
number between 1 and n
END *)
PROCEDURE realNumber () : REAL;
(* Returns a random number r as follows: 0 <= r < 1. *)
PROCEDURE longrealNumber (): LONGREAL;
(* Returns a random number r as follows: 0 <= r < 1. *)
END Random.
Murus : Random.mod
IMPLEMENTATION MODULE Random;
(* (c) Christian Maurer v. 6. November 2007
Nutzungsbedingungen siehe Murus.mod *)
(* Edited by Jan Verhoeven, Aug 2008 *)
(* ### Literature:
D. E. Knuth, The Art of Computer Programming, 3.2.1.1-2, 3.6 i)-vi) *)
IMPORT LREAL, Cardinals, Time;
CONST Billion = 1000 * 1000 * 1000;
ModulusI = MAX (INTEGER); (* = 2^31 - 1, Prime number! *)
A = 314159261;
C = 453816692; (* M * (1/2 - 1/6 * sqrt 3 (3.6 v), 3.3.4 (41) *)
VAR ModulusR, BillionR, MaxCardinalR : LONGREAL;
Modulus, Randomnumber : CARDINAL;
PROCEDURE init;
VAR h, m, s, us : CARDINAL;
BEGIN
Time.relativeUpdate (s, us);
Randomnumber := 1000 * 1000 * (s MOD 60) + us
END init;
PROCEDURE ProduktModM (a, x: CARDINAL): CARDINAL;
BEGIN
Cardinals.Multiply (a, x); (* a * x |-> 2^32 * x + a = M * 2 * x + a + 2 * x *)
IF a >= Modulus THEN DEC (a, Modulus) END;
IF x >= Modulus THEN DEC (x, Modulus) END;
x:= 2 * x;
IF x >= Modulus THEN DEC (x, Modulus) END;
INC (a, x);
IF a >= Modulus THEN DEC (a, Modulus) END;
RETURN a
END ProduktModM;
PROCEDURE Number (n: CARDINAL): CARDINAL;
VAR r : LONGREAL;
BEGIN
Randomnumber := ProduktModM (Randomnumber, A);
INC (Randomnumber, C);
IF Randomnumber >= Modulus THEN
DEC (Randomnumber, Modulus)
END;
IF n = 0 THEN
n := MAX (CARDINAL)
END;
IF n = MAX (CARDINAL) THEN
r := MaxCardinalR
ELSIF n <= Modulus THEN
r := LREAL.LFLOAT (n)
ELSE
DEC (n, Modulus);
r := LREAL.LFLOAT (n) + ModulusR
END;
r := (LREAL.LFLOAT (Randomnumber) / ModulusR) * r;
IF r <= ModulusR THEN
RETURN LREAL.LTRUNC (r)
ELSE
r := r - ModulusR;
RETURN CARDINAL (LREAL.LTRUNC (r)) + Modulus
END
END Number;
PROCEDURE realNumber () : REAL;
BEGIN
RETURN FLOAT (Number (Billion)) / FLOAT (Billion)
END realNumber;
PROCEDURE longrealNumber (): LONGREAL;
BEGIN
RETURN (LREAL.LFLOAT (Number (Billion)) + LREAL.LFLOAT (Number (Billion)) / BillionR) / BillionR
END longrealNumber;
BEGIN
Modulus := CARDINAL (ModulusI);
ModulusR := LREAL.LFLOAT (ModulusI);
MaxCardinalR := 2.0 * ModulusR + 1.0;
BillionR := LREAL.LFLOAT (Billion);
init
END Random.
Page created 28 August 2008,
Page equipped with FroogleBuster technology