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