|
1 (* Title: Tools/random_word.ML |
|
2 Author: Makarius |
|
3 |
|
4 Simple generator for pseudo-random numbers, using unboxed word |
|
5 arithmetic only. Unprotected concurrency introduces some true |
|
6 randomness. |
|
7 *) |
|
8 |
|
9 structure Random :> Random = |
|
10 struct |
|
11 |
|
12 (* random words: 0w0 <= result <= max_word *) |
|
13 |
|
14 (*minimum length of unboxed words on all supported ML platforms*) |
|
15 val _ = Word.wordSize >= 30 |
|
16 orelse raise Fail ("Bad platform word size"); |
|
17 |
|
18 val max_word = 0wx3FFFFFFF; |
|
19 val 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*) |
|
23 val a = 0w777138309; |
|
24 fun step x = Word.andb (a * x + 0w1, max_word); |
|
25 |
|
26 fun change r f = r := f (!r); |
|
27 local val rand = (*Unsynchronized.*)ref 0w1 |
|
28 in fun nextWord () = ((*Unsynchronized.*)change rand step; ! rand) end; |
|
29 |
|
30 (*NB: higher bits are more random than lower ones*) |
|
31 fun nextBool () = Word.andb (nextWord (), top_bit) = 0w0; |
|
32 |
|
33 |
|
34 (* random integers: 0 <= result < k *) |
|
35 |
|
36 val max_int = Word.toInt max_word; |
|
37 |
|
38 fun 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 |
|
45 val scaling = real max_int + 1.0; |
|
46 fun nextReal () = real (Word.toInt (nextWord ())) / scaling; |
|
47 |
|
48 end; |