(* Copyright (C) 1990, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last modified on Thu Sep 19 18:51:58 1991 by kalsow *) (* modified on Tue Jan 30 10:57:23 1990 by muller *) (* modified on Thu Jan 25 22:46:15 PST 1990 by stolfi *) UNSAFE MODULE RandomReal EXPORTS Random; IMPORT Word; (* Implements Random.Real and Random.LongReal for IEEE floating-point format, as available on the following little-endian machines: Acorn RISC, Apollo DN3000, DN4000, DECstation 3100 (pmax), Encore Multimax, IBM PC/386, PC/RT, R6000, HP 9000/300, Sun 3, *) PROCEDURE Real (self: T := Default): REAL = CONST ExponentBias = 127; (* Exponent bias for REAL *) FractionBits = 23; (* Number of explicit fraction bits *) WordSize = 32; (* Size of INTEGER in bits *) VAR frac, exp: INTEGER; BEGIN (* Generate a random fraction and get its first non-zero word: *) exp := ExponentBias - 1; frac := Integer (self); WHILE (frac = 0) AND (exp >= WordSize) DO (* This loop is (almost) never executed: *) DEC (exp, WordSize); frac := Integer (self); END; (* Normalize: *) WHILE (frac > 0) AND (exp > 0) DO (* This loop is executed about once on the average. *) frac := Word.Shift (frac, 1); DEC (exp); END; IF ((ExponentBias - 1 - exp) MOD WordSize) > WordSize - FractionBits THEN (* Needs more random bits *) frac := Integer (self) END; (* Repack as REAL: *) RETURN LOOPHOLE ( Word.Or ( Word.Shift (exp, FractionBits), Word.Shift ( Word.And (frac, 16_7fffffff), -(WordSize - 1 - FractionBits) ) ), REAL ); END Real; PROCEDURE LongReal (self: T := Default): LONGREAL = CONST ExponentBias = 1023; (* Exponent bias for LONGREAL *) FractionBits = 20; (* Number of fraction bits in high half *) WordSize = 32; (* Size of INTEGER in bits *) VAR frac, exp: INTEGER; dbl: ARRAY [0..1] OF Word.T; BEGIN (* Generate a random fraction and get the first non-zero word: *) exp := ExponentBias - 1; frac := Integer (self); WHILE (frac = 0) AND (exp >= WordSize) DO (* This loop is (almost) never executed: *) DEC (exp, WordSize); frac := Integer (self); END; (* Normalize: *) WHILE (frac > 0) AND (exp > 0) DO (* This loop is executed about once on the average. *) frac := Word.Shift (frac, 1); DEC (exp); END; IF ((ExponentBias - 1 - exp) MOD WordSize) > WordSize - FractionBits THEN (* Needs more random bits *) frac := Integer (self); END; (* Repack as LONGREAL: *) dbl[0] := Integer (self);(* Low-order fraction bits *) dbl[1] := Word.Or ( Word.Shift (exp, FractionBits), Word.Shift (Word.And (frac, 16_7fffffff), -(WordSize - 1 - FractionBits)) ); RETURN LOOPHOLE(dbl, LONGREAL) END LongReal; BEGIN END RandomReal.