66open Stdint
77
88
9- module PCG64 : sig
9+ module type PCG_TYPE = sig
1010 (* * PCG-64 is a 128-bit implementation of O'Neill's permutation congruential
1111 generator. PCG-64 has a period of {m 2^{128}} and supports advancing an arbitrary
1212 number of steps as well as {m 2^{127}} streams.
@@ -27,7 +27,19 @@ module PCG64 : sig
2727 val next_bounded_uint64 : uint64 -> t -> uint64 * t
2828 (* * [next_bounded_uint64 bound t] returns an unsigned 64bit integers in the range
2929 (0, bound) as well as the state of the generator advanced one step forward. *)
30- end = struct
30+ end
31+
32+
33+ module type FUNCTOR_SIG = sig
34+ type t = {s : setseq ; ustore : uint32 option }
35+ and setseq = {state : uint128 ; increment : uint128 }
36+ val multiplier : uint128
37+ val output : uint128 -> uint64
38+ val next : setseq -> uint64 * setseq
39+ end
40+
41+
42+ module PCG64Impl = struct
3143 type t = {s : setseq ; ustore : uint32 option }
3244 and setseq = {state : uint128 ; increment : uint128 }
3345
@@ -45,11 +57,38 @@ end = struct
4557 let next {state; increment} =
4658 let state' = Uint128. (state * multiplier + increment) in
4759 output state', {state = state'; increment}
60+ end
61+
62+
63+ module PCG64DXSMImpl = struct
64+ type t = {s : setseq ; ustore : uint32 option }
65+ and setseq = {state : uint128 ; increment : uint128 }
66+
67+ let cheap_multiplier = Uint64. of_string " 0xda942042e4dd58b5"
68+ let const128bit hi lo = Uint128. (shift_left (of_uint64 hi) 64 + of_uint64 lo)
69+ let multiplier = const128bit Uint64. zero cheap_multiplier
70+
71+
72+ let output state =
73+ let hi0 = Uint128. (shift_right state 64 |> to_uint64) in
74+ let hi1 = Uint64. (shift_right hi0 32 |> logxor hi0) in
75+ let hi2 = Uint64. (hi1 * cheap_multiplier) in
76+ let hi3 = Uint64. (shift_right hi2 48 |> logxor hi2) in
77+ Uint64. (Uint128. (logor state one |> to_uint64) * hi3)
78+
79+
80+ let next {state; increment} =
81+ output state, {state = Uint128. (state * multiplier + increment); increment}
82+ end
83+
84+
85+ module Make (M : FUNCTOR_SIG ) = struct
86+ include M
4887
4988
5089 let next_uint64 t = match next t.s with
5190 | u , s -> u, {t with s}
52-
91+
5392
5493 let next_uint32 t =
5594 match Common. next_uint32 ~next: next t.s t.ustore with
@@ -83,3 +122,7 @@ end = struct
83122 let initialize seed =
84123 {s = set_seed (Seed.SeedSequence. generate_64bit_state 4 seed); ustore = None }
85124end
125+
126+
127+ module PCG64DXSM : PCG_TYPE = Make (PCG64DXSMImpl )
128+ module PCG64 : PCG_TYPE = Make (PCG64Impl )
0 commit comments