@@ -22,14 +22,15 @@ let mixhashmix x y const =
22
22
const', Uint32. (logxor (shift_right res xshift) res)
23
23
24
24
25
- let mask32 = Uint128. of_int 0xffffffff
25
+ let mask32 = Uint32. max_int |> Uint128. of_uint32
26
26
(* Convert a list of unsigned 128bit integers into an array of unsigned 32 bit integers
27
27
by splitting each 128bit integer into a sequence of 32bit ints and concatenating the result.*)
28
28
let to_u32_array l =
29
- let f n = Some Uint128. (logand n mask32 |> to_uint32, shift_right n 32 ) in
30
- let split n = Seq. unfold f n |> Seq. take_while (fun x -> Uint32. (x > zero))
31
- |> (fun s -> if Seq. is_empty s then Seq. (return Uint32. zero) else s)
32
- in List. to_seq l |> Seq. concat_map split |> Array. of_seq
29
+ let open Uint128 in
30
+ Seq. concat_map (fun n -> if n = zero then Seq. return Uint32. zero else
31
+ Seq. unfold (function
32
+ | n when n > zero -> Some (logand n mask32 |> to_uint32, shift_right n 32 )
33
+ | _ -> None ) n) (List. to_seq l) |> Array. of_seq
33
34
34
35
35
36
(* Return an integer with 128 random bits by combining 2 integers with 64 random bits. *)
@@ -91,24 +92,30 @@ module SeedSequence : sig
91
92
the bit stream of [t]. *)
92
93
end = struct
93
94
94
- type t = {
95
- entropy : uint128 list ;
96
- spawn_key : uint128 list ;
97
- children_spawned : int ;
98
- pool : uint32 array ;
99
- }
95
+ type t = {entropy : uint128 list ; spawn_key : uint128 list ;
96
+ children_spawned : int ; pool : uint32 array }
100
97
101
98
let entropy t = t.entropy
102
99
100
+
103
101
let children_spawned t = t.children_spawned
104
102
105
103
106
- let mix_entropy pool_size entropy =
104
+ let assembled_entropy ~entropy ~spawn_key pool_size =
105
+ let run, spawn = to_u32_array entropy, to_u32_array spawn_key in
106
+ if Array. (length spawn > 0 && length run < pool_size) then
107
+ Array. concat [run; Array. make (pool_size - Array. length run) Uint32. zero; spawn]
108
+ else Array. concat [run; spawn]
109
+
110
+
111
+ let mix ~entropy ~spawn_key pool_size =
112
+ let entropy' = assembled_entropy ~entropy ~spawn_key pool_size in
113
+
107
114
(* Add in entropy up to the pool size. *)
108
- let values, leftover = match Array. length entropy, pool_size with
109
- | le , lp when le > lp -> entropy, le - lp
110
- | le , lp -> Array. append entropy (Array. init (lp - le) (fun _ -> Uint32. zero)), 0 in
111
- let hash, pool = Array. fold_left_map hashmix (Uint32. of_int 0x43b0d7e5 ) values in
115
+ let values, leftover = match Array. length entropy' , pool_size with
116
+ | le , lp when le > lp -> entropy' , le - lp
117
+ | le , lp -> Array. append entropy' (Array. init (lp - le) (fun _ -> Uint32. zero)), 0 in
118
+ let hash, pool = Array. fold_left_map hashmix (Uint32. of_int32 0x43b0d7e5l ) values in
112
119
113
120
(* mix all bits together so later bits can affect earlier bits *)
114
121
let indices = Array. init pool_size (fun x -> x) in
@@ -120,47 +127,36 @@ end = struct
120
127
if leftover > 0 then
121
128
let leftover_indices = (Array. init leftover (fun i -> pool_size + i)) in
122
129
let f (acc0 , acc1 ) j = Array. fold_left_map
123
- (fun c i -> mixhashmix entropy.(j) acc1.(i) c) acc0 indices in
130
+ (fun c i -> mixhashmix entropy' .(j) acc1.(i) c) acc0 indices in
124
131
Array. fold_left f (hash', pool') leftover_indices |> snd
125
132
else pool'
126
133
127
134
128
- let assembled_entropy entropy spawn_key pool_size =
129
- let run_entropy = to_u32_array entropy
130
- and spawn_entropy = to_u32_array spawn_key in
131
- let l = match Array. (length spawn_entropy > 0 && length run_entropy < pool_size) with
132
- | true -> Array. init (pool_size - Array. length run_entropy) (fun _ -> Uint32. zero)
133
- | false -> [||]
134
- in Array. concat [run_entropy; l; spawn_entropy]
135
-
136
-
137
135
let initialize ?(spawn_key =[] ) ?(pool_size =4 ) entropy =
138
136
(* 128 bits of system entropy are used when entropy is not provided *)
139
- let entropy' = if List. compare_length_with entropy 0 = 0 then [randbits128 () ] else entropy in
140
- let assembled = assembled_entropy entropy' spawn_key pool_size in
141
- {spawn_key; entropy = entropy'; children_spawned = 0 ; pool = mix_entropy pool_size assembled}
137
+ let entropy = if List. compare_length_with entropy 0 = 0 then [randbits128 () ] else entropy in
138
+ {spawn_key; entropy; children_spawned = 0 ; pool = mix pool_size ~entropy ~spawn_key }
142
139
143
140
144
141
let spawn n t =
145
- let f i =
146
- let psize = Array. length t.pool
147
- and spawn_key = t.spawn_key @ [i] in
148
- let pool = assembled_entropy t.entropy spawn_key psize |> mix_entropy psize in
149
- Some ({t with pool; spawn_key; children_spawned = 0 }, Uint128. (i + one))
150
- in Seq. unfold f Uint128. (of_int n) |> Seq. take n |> List. of_seq,
142
+ List. init n (fun x -> Uint128. of_int x)
143
+ |> List. map (fun i -> match t.spawn_key @ [i] with
144
+ | spawn_key -> {t with spawn_key; children_spawned = 0 ;
145
+ pool = Array. length t.pool |> mix ~entropy: t.entropy ~spawn_key }),
151
146
{t with children_spawned = t.children_spawned + n}
152
147
153
148
154
- let init_b, mult_b = Uint32. (of_int 0x8b51f9dd , of_int 0x58f38ded )
149
+ let init_b, mult_b = Uint32. (of_int 0x8b51f9dd , of_int32 0x58f38dedl )
150
+
155
151
156
152
let generate_32bit_state n_words t =
157
- let f acc a =
158
- let a' = Uint32. (logxor a acc)
159
- and acc ' = Uint32. (acc * mult_b ) in
160
- let a'' = Uint32. (a' * acc') in
161
- acc', Uint32. (shift_right a'' xshift |> logxor a'' )
162
- in Array. to_seq t.pool |> Seq. cycle |> Seq. take n_words
163
- |> Array. of_seq |> Array. fold_left_map f init_b |> snd
153
+ Seq. unfold ( fun ( seq , acc ) -> match Seq. uncons seq, Uint32. (acc * mult_b) with
154
+ | Some ( a , seq' ), acc' ->
155
+ let a ' = Uint32. (logxor a acc |> mul acc' ) in
156
+ Some Uint32. (shift_right a' xshift |> logxor a', (seq', acc'))
157
+ | None , _ -> None ) ( Array. to_seq t.pool |> Seq. cycle |> Seq. take n_words, init_b )
158
+ |> Array. of_seq
159
+
164
160
165
161
(* 64 bit state array is obtained by combining elements i and (i + 1) of the [o] array
166
162
to create a 64 bit integer using the formula o.(k + 1) << 32 | o.(k), where k = i * 2
0 commit comments