arithmetic/src/misc/stochastic/RandomBayesDurham.m3


MODULE RandomBayesDurham;
Arithmetic for Modula-3, see doc for details

IMPORT LongRealBasic AS R;

FROM RandomBasic IMPORT Min, Max;
IMPORT RandomRep, RandomBasic;

CONST Module = "RandomBayesDurham.";

REVEAL
  T = TPublic BRANDED OBJECT
        z1: INTEGER;
      OVERRIDES
        init   := Init;
        engine := Engine;
      END;

PROCEDURE Init (SELF: T; seed: [1 .. LAST(INTEGER)] := 1; ): T =
  BEGIN
    SELF.z1 := seed;
    EVAL SELF.engine();
    RETURN SELF;
  END Init;

PROCEDURE Engine (SELF: T; ): R.T =
  <* UNUSED *>
  CONST
    ftn = Module & "Engine";
  CONST
    (* use Park/Miller alternatives (NR92, pg279) *)
    m       = 2147483647;
    m_recip = R.One / FLOAT(m, R.T);
    a       = 48271;
    q       = 44488;
    r       = 3399;

  VAR
    z1, tmp: INTEGER;
    result : R.T;
  BEGIN
    z1 := SELF.z1;
    tmp := z1 DIV q;
    z1 := a * (z1 - tmp * q) - r * tmp;
    IF z1 < 0 THEN INC(z1, m) END;

    (*---convert and check for out of bounds---*)
    result := FLOAT(z1, R.T) * m_recip;
    IF result < Min THEN
      result := Min;
    ELSIF result > Max THEN
      result := Max;
    END;

    (*---save data and close---*)
    SELF.z1 := z1;
    RETURN result;
  END Engine;

BEGIN
END RandomBayesDurham.