author | wenzelm |
Mon, 13 Apr 2020 22:08:14 +0200 | |
changeset 71751 | abf3e80bd815 |
parent 39429 | 126b879df319 |
permissions | -rw-r--r-- |
39348 | 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 |
|
39426
c551ce5f614a
make "Unprotected concurrency introduces some true randomness." be true;
blanchet
parents:
39408
diff
changeset
|
28 |
in fun nextWord () = ((*Unsynchronized.*)change rand step; ! rand) end; |
39348 | 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; |