Skip to content

Commit 6cc863a

Browse files
Pass Automated Testing SuitePass Automated Testing Suite
authored andcommitted
Add PCG64DXSM variant of the PCG64 bitgenerator.
1 parent f2f0a3a commit 6cc863a

File tree

3 files changed

+54
-4
lines changed

3 files changed

+54
-4
lines changed

lib/bitgen.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ module SeedSequence = Seed.SeedSequence
2929

3030
module SFC64 = Sfc.SFC64
3131
module PCG64 = Pcg.PCG64
32+
module PCG64DXSM = Pcg.PCG64DXSM
3233
module Xoshiro256 = Xoshiro.Xoshiro256StarStar
3334
module Philox4x64 = Philox.Philox
3435
module ChaCha = Chacha.ChaCha128Counter

lib/pcg.ml

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
open 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}
85124
end
125+
126+
127+
module PCG64DXSM : PCG_TYPE = Make (PCG64DXSMImpl)
128+
module PCG64 : PCG_TYPE = Make (PCG64Impl)

test/test_pcg.ml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ let test_pcg_datasets _ =
1818
(Sys.getcwd () ^ "/../../../test/data/pcg64-testset-1.csv");
1919
Testconf.bitgen_groundtruth
2020
(module PCG64)
21-
(Sys.getcwd () ^ "/../../../test/data/pcg64-testset-2.csv")
21+
(Sys.getcwd () ^ "/../../../test/data/pcg64-testset-2.csv");
22+
Testconf.bitgen_groundtruth
23+
(module PCG64DXSM)
24+
(Sys.getcwd () ^ "/../../../test/data/pcg64dxsm-testset-1.csv");
25+
Testconf.bitgen_groundtruth
26+
(module PCG64DXSM)
27+
(Sys.getcwd () ^ "/../../../test/data/pcg64dxsm-testset-2.csv")
2228

2329

2430
let test_bounded_u64 _ = Testconf.test_bounded_u64 (module PCG64)

0 commit comments

Comments
 (0)