MODULE; RandomIteratedSquaring
Gnu CopyLefted.
Abstract: Pseudo-random number generator by Warren D. Smith.
IMPORT LongRealBasic AS R, LongRealTrans AS RT, Word, Tick, TimeStamp; IMPORT RandomRep; <* UNUSED *> CONST Module = "RandomIteratedSquaring."; CONST moduis = 9739.0D0 * 9719.0D0; (* = 94653341. Factors are each primes, 3 mod 4. *) DefaultSeed1 = 3145981; DefaultSeed2 = 2718280; DefaultXis = 243213.0D0; REVEAL T = TPublic BRANDED OBJECT xis : R.T; seedbitind : INTEGER := 3; seed1, seed2: Word.T; OVERRIDES init := Init; engine := Engine; END; PROCEDURE* Note: period of the bit sequence this produces is * only 23658471. However, that should be adequate for its * intended purpose, which is to initialize the state of * the other generators to something interesting. * (And if the seeds are nonzero, period will * generally be 2*Word.Size*23658471.) * If seed1 or seed2 are nonzero, then will add a perturbation to output * according to the bits of the seed words. ********************************************Init (SELF: T; fixed: BOOLEAN; ): T = BEGIN IF NOT fixed THEN SELF.seed1 := TimeStamp.Hash(TimeStamp.New()); SELF.seed2 := Tick.Now(); SELF.xis := ABS(DefaultXis + FLOAT(SELF.seed1, R.T) + FLOAT(SELF.seed1, R.T)) MOD moduis; ELSE SELF.seed1 := DefaultSeed1; SELF.seed2 := DefaultSeed2; SELF.xis := DefaultXis; END; RETURN SELF; END Init;
PROCEDUREEngine (SELF: T; ): BOOLEAN = VAR perturb: Word.T; BEGIN DEC(SELF.seedbitind); IF SELF.seedbitind < 0 THEN SELF.seedbitind := Word.Size * 2 - 1; END; IF SELF.seedbitind < Word.Size THEN perturb := Word.And(Word.RightShift(SELF.seed1, SELF.seedbitind), 2_1); ELSE perturb := Word.And(Word.RightShift( SELF.seed2, SELF.seedbitind - Word.Size), 2_1); END; SELF.xis := (SELF.xis * SELF.xis) MOD moduis; RETURN ((SELF.xis < (moduis - R.One) * RT.Half) = (perturb # 0)); END Engine; BEGIN END RandomIteratedSquaring.