-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support to run generators through TestU01 test suites
- Loading branch information
Pass Automated Testing Suite
authored and
Pass Automated Testing Suite
committed
Apr 18, 2024
1 parent
51bc732
commit 1678ce7
Showing
5 changed files
with
124 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
open Stdint | ||
open Bitgen | ||
|
||
|
||
module type S = sig | ||
type t | ||
val next_uint32 : t -> uint32 * t | ||
val initialize : SeedSequence.t -> t | ||
end | ||
|
||
|
||
let mask1, mask2, mask3, mask4 = | ||
Uint32.(of_int 0x55555555, of_int 0x33333333, of_int 0x0F0F0F0F, of_int 0x00FF00FF) | ||
|
||
|
||
(* https://graphics.stanford.edu/~seander/bithacks.html | ||
https://www.pcg-random.org/posts/how-to-test-with-testu01.html *) | ||
let rev_bits v = | ||
let open Uint32 in | ||
(* swap odd and even bits *) | ||
let v = logor (logand (shift_right v 1) mask1) (shift_left (logand v mask1) 1) in | ||
(* swap consecutive pairs *) | ||
let v = logor (logand (shift_right v 2) mask2) (shift_left (logand v mask2) 2) in | ||
(* swap nibbles *) | ||
let v = logor (logand (shift_right v 4) mask3) (shift_left (logand v mask3) 4) in | ||
(* swap bytes *) | ||
let v = logor (logand (shift_right v 8) mask4) (shift_left (logand v mask4) 8) in | ||
(* swap 2-byte-long pairs *) | ||
logor (shift_right v 16) (shift_left v 16) | ||
|
||
|
||
(* TestU01 can only be used for 32bit input and thus causes it to be more sensitive | ||
to flaws in the most-significant bits than the least significant bits. | ||
It is important to test general-purpose generators in bit-reversed form, | ||
to verify their suitability for applications which use the low-order bits. | ||
Thankfully, the bitgenerator interface provide a next_uint32 function for | ||
all the 64-bit PRNG's which outputs the the high and then low 32 bits of the | ||
unsigned random 64 bits. *) | ||
let make_int32 (module M : S) ~rev = | ||
let ss = SeedSequence.initialize [] in | ||
let t = ref (M.initialize ss) in | ||
let bits () = match M.next_uint32 !t, rev with | ||
| (u, t'), false -> t := t'; Uint32.to_int32 u | ||
| (u, t'), true -> t := t'; rev_bits u |> Uint32.to_int32 | ||
in | ||
bits | ||
|
||
|
||
let to_module = function | ||
| "xoshiro256" -> (module Xoshiro256 : S) | ||
| "pcg64" -> (module PCG64 : S) | ||
| "philox64" -> (module Philox64 : S) | ||
| "sfc64" -> (module SFC64 : S) | ||
| _ -> failwith "Unknown PRNG" | ||
|
||
|
||
let testsuite = function | ||
| "smallcrush" -> TestU01.Bbattery.small_crush | ||
| "crush" -> TestU01.Bbattery.crush | ||
| "bigcrush" -> TestU01.Bbattery.big_crush | ||
| _ -> failwith "Unknown test name" | ||
|
||
|
||
let is_rev name = function | ||
| false -> name | ||
| true -> name ^ "-rev" | ||
|
||
|
||
let usage = " | ||
Run TestU01's test suite on the supported bitgenerators. | ||
It offers several batteries of tests including 'Small Crush' | ||
(which consists of 10 tests), 'Crush' (96 tests), and 'Big Crush' (106 tests). | ||
Bitgenerators to select from include: sfc64, philox64, pcg64 and xoshiro256. | ||
crush [-name] [-pvalue] [-rev] [-verbose] <bitgen> | ||
E.g `crush -name bigcrush -rev pcg64` (which runs Big Crush on the reversed bits of PCG64 generator). | ||
" | ||
|
||
|
||
let () = | ||
let pvalue = ref 0.01 | ||
and test = ref "smallcrush" | ||
and prng = ref "" | ||
and verbose = ref false | ||
and rev = ref false in | ||
let spec = [ | ||
("-pvalue", Arg.Set_float pvalue, "Threshold for suspect p-values. Defaults to 0.01"); | ||
("-name", Arg.Set_string test, "Name of the test to run. Should be one of {smallcrush, crush, bigcrush}.\n Defaults to 'smallcrush'"); | ||
("-rev", Arg.Set rev, "Run tests on reversed bits of the input."); | ||
("-verbose", Arg.Set verbose, "In addition to the summary report, write the result of each test to stdout."); | ||
] in | ||
Arg.parse spec (fun x -> prng := x) usage; | ||
TestU01.Swrite.set_basic !verbose; | ||
Probdist.Gofw.set_suspectp !pvalue; | ||
TestU01.Unif01.create_extern_gen_int32 (is_rev !prng !rev) (to_module !prng |> make_int32 ~rev:!rev) | ||
|> testsuite !test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
(executable | ||
(public_name crush) | ||
(name crush) | ||
(ocamlopt_flags (:standard -O3)) | ||
(libraries bitgenerators testu01)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters