|
1 (* Title: HOL/Mirabelle/Tools/mirabelle_util.ML |
|
2 Author: Martin Desharnais, MPI-INF Saarbruecken |
|
3 *) |
|
4 |
|
5 (* Pseudorandom number generator *) |
|
6 signature PRNG = sig |
|
7 type state |
|
8 val initialize : int -> state |
|
9 val next : state -> int * state |
|
10 end |
|
11 |
|
12 (* Pseudorandom algorithms *) |
|
13 signature PRNG_ALGORITHMS = sig |
|
14 include PRNG |
|
15 val shuffle : state -> 'a list -> 'a list * state |
|
16 end |
|
17 |
|
18 functor PRNG_Algorithms(PRNG : PRNG) : PRNG_ALGORITHMS = struct |
|
19 |
|
20 open PRNG |
|
21 |
|
22 fun shuffle prng_state xs = |
|
23 fold_map (fn x => fn prng_state => |
|
24 let |
|
25 val (n, prng_state') = next prng_state |
|
26 in ((n, x), prng_state') end) xs prng_state |
|
27 |> apfst (sort (int_ord o apply2 fst)) |
|
28 |> apfst (map snd) |
|
29 |
|
30 end |
|
31 |
|
32 (* multiplicative linear congruential generator *) |
|
33 structure MLCG_PRNG : PRNG = struct |
|
34 (* The modulus is implicitly 2^64 through using Word64. |
|
35 The multiplier and increment are the same as Newlib and Musl according to Wikipedia. |
|
36 See: https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use |
|
37 *) |
|
38 val multiplier = Word64.fromInt 6364136223846793005 |
|
39 val increment = Word64.fromInt 1 |
|
40 |
|
41 type state = Word64.word |
|
42 |
|
43 val initialize = Word64.fromInt |
|
44 |
|
45 fun next s = |
|
46 let |
|
47 open Word64 |
|
48 val s' = multiplier * s + increment |
|
49 in |
|
50 (toInt s', s') |
|
51 end |
|
52 end |
|
53 |
|
54 structure MLCG = PRNG_Algorithms(MLCG_PRNG) |