Skip to content

Commit

Permalink
Add EFIIX64x48 bitgenerator.
Browse files Browse the repository at this point in the history
  • Loading branch information
Pass Automated Testing Suite authored and Pass Automated Testing Suite committed May 5, 2024
1 parent 2bf8c23 commit 07c1941
Show file tree
Hide file tree
Showing 8 changed files with 2,120 additions and 1 deletion.
1 change: 1 addition & 0 deletions bin/bench.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ let pairs = [
"Xoshiro256", (module Xoshiro256: S);
"Philox4x64", (module Philox4x64: S);
"ChaCha", (module ChaCha: S);
"EFIIX64x48", (module EFIIX64x48: S);
]


Expand Down
1 change: 1 addition & 0 deletions bin/crush.ml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ let to_module = function
| "philox4x64" -> (module Philox4x64 : S)
| "sfc64" -> (module SFC64 : S)
| "chacha" -> (module ChaCha : S)
| "efiix64x48" -> (module EFIIX64x48 : S)
| _ -> failwith "Unknown PRNG"


Expand Down
1 change: 1 addition & 0 deletions lib/bitgen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ module PCG64 = Pcg.PCG64
module Xoshiro256 = Xoshiro.Xoshiro256StarStar
module Philox4x64 = Philox.Philox
module ChaCha = Chacha.ChaCha128Counter
module EFIIX64x48 = Efiix.EFIIX64
97 changes: 97 additions & 0 deletions lib/efiix.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
open Stdint


module EFIIX64 : sig
include Common.BITGEN
end = struct
type t = {s : state; ustore : uint32 option}
and state = {ind_table : uint64 array; iter_table : uint64 array;
i : uint64; a : uint64; b : uint64; c : uint64}
type arbee = {a : uint64; b : uint64; c : uint64; d : uint64; i : uint64}


let rotate x k =
let y = 64 - k in Uint64.(logor (shift_left x k) (shift_right x y))


let iter_size, ind_size = Uint64.(of_int 32, of_int 16)

let next (s : state) =
let open Uint64 in
let iter_rem = rem s.i iter_size |> to_int in
let ind_rem = rem s.c ind_size |> to_int in
let iterated = s.iter_table.(iter_rem) in
let indirect = s.ind_table.(ind_rem) in
let ind_table = Array.mapi (fun i -> function
| v when i <> ind_rem -> v
| _ -> iterated + s.a) s.ind_table in
let iter_table = Array.mapi (fun i -> function
| v when i <> iter_rem -> v
| _ -> indirect) s.iter_table in
let b = s.c + indirect in
logxor b iterated,
{ind_table; iter_table; b; a = s.b + s.i; c = logxor s.a s.b + rotate s.c 25; i = s.i + one}


let next_uint64 t = let u, s = next t.s in u, {t with s}


let next_uint32 t = match Common.next_uint32 ~next:next t.s t.ustore with
| u, s, ustore -> u, {s; ustore}


let next_double t = Common.next_double ~nextu64:next_uint64 t


let next_bounded_uint64 bound t = Common.next_bounded_uint64 bound ~nextu64:next_uint64 t


let arbee_next (s : arbee) =
let open Uint64 in
let e = s.a + rotate s.b 45 in
let a = logxor s.b (rotate s.c 13) in
let d = e + a in
{a; b = s.c + rotate s.d 37; c = e + s.d + s.i; d; i = s.i + one}, d


let rec mix (s : arbee) = function
| 0 -> s
| i -> mix (arbee_next s |> fst) (i - 1)


let rec discard (s : state) = function
| 0 -> s
| i -> discard (next s |> snd) (i - 1)


let arbee_seed seed =
mix {a = seed.(0); b = seed.(1); c = seed.(2); d = seed.(3); i = Uint64.one} 12


let set_seed seed =
let seeder, ind_table = Array.fold_left_map
(fun acc _ -> arbee_next acc) (arbee_seed seed) (Array.make 16 0) in
let seeder, i = arbee_next seeder in
let iter_table = (Array.make 32 Uint64.zero) in
let seeder, iter_values = Array.fold_left_map
(fun acc _ -> arbee_next acc) seeder iter_table in
Array.iteri
(fun idx v -> iter_table.(Uint64.(rem (of_int idx + i) iter_size |> to_int)) <- v) iter_values;
let seeder, a = arbee_next seeder in
let seeder, b = arbee_next seeder in
let seeder, c = arbee_next seeder in
let s = discard {ind_table; iter_table; i; a; b; c} 64 in

let seeder = arbee_next seeder |> fst in
let seeder, s1 = arbee_next seeder in
let seeder, s2 = arbee_next seeder in
let seeder = arbee_seed Uint64.[|s1 + seed.(0) |> logxor s.a; s2 + seed.(1) |> logxor s.b;
(arbee_next seeder |> snd) + seed.(2) |> logxor s.c; lognot seed.(3)|] in
let ind_table = Array.fold_left_map
(fun acc y -> let acc', x = arbee_next acc in acc', Uint64.logxor x y) seeder s.ind_table |> snd in
discard {s with ind_table} 48


let initialize seed =
{s = Seed.SeedSequence.generate_64bit_state 4 seed |> set_seed; ustore = None}
end
Loading

0 comments on commit 07c1941

Please sign in to comment.