1(*  Title:      Tools/random_word.ML
2    Author:     Makarius
3
4Simple generator for pseudo-random numbers, using unboxed word
5arithmetic only.  Unprotected concurrency introduces some true
6randomness.
7*)
8
9structure Random :> Random =
10struct
11
12(* random words: 0w0 <= result <= max_word *)
13
14(*minimum length of unboxed words on all supported ML platforms*)
15val _ = Word.wordSize >= 30
16  orelse raise Fail ("Bad platform word size");
17
18val max_word = 0wx3FFFFFFF;
19val top_bit = 0wx20000000;
20
21(*multiplier according to Borosh and Niederreiter (for modulus = 2^30),
22  see http://random.mat.sbg.ac.at/~charly/server/server.html*)
23val a = 0w777138309;
24fun step x = Word.andb (a * x + 0w1, max_word);
25
26fun change r f = r := f (!r);
27local val rand = (*Unsynchronized.*)ref 0w1
28in fun nextWord () = ((*Unsynchronized.*)change rand step; ! rand) end;
29
30(*NB: higher bits are more random than lower ones*)
31fun nextBool () = Word.andb (nextWord (), top_bit) = 0w0;
32
33
34(* random integers: 0 <= result < k *)
35
36val max_int = Word.toInt max_word;
37
38fun nextInt k =
39  if k <= 0 orelse k > max_int then raise Fail ("next_int: out of range")
40  else if k = max_int then Word.toInt (nextWord ())
41  else Word.toInt (Word.mod (nextWord (), Word.fromInt k));
42
43(* random reals: 0.0 <= result < 1.0 *)
44
45val scaling = real max_int + 1.0;
46fun nextReal () = real (Word.toInt (nextWord ())) / scaling;
47
48end;
49