diff --git a/c/.gitignore b/c/.gitignore deleted file mode 100644 index dba0160..0000000 --- a/c/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/testocamlrandom -/testxoshiro -/testsplitmix diff --git a/c/Makefile b/c/Makefile deleted file mode 100644 index 691c63f..0000000 --- a/c/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -all: testxoshiro testocamlrandom testsplitmix - -testsplitmix: testsplitmix.c splitmix64.c splitmix64.h - cc -o $@ $< splitmix64.c - -testxoshiro: testxoshiro.c xoshiro256pp.c xoshiro256pp.h - cc -o $@ $< xoshiro256pp.c - -testocamlrandom: testocamlrandom.c ocamlrandom.c ocamlrandom.h - cc -o $@ $< ocamlrandom.c - -clean: - rm -f testxoshiro testocamlrandom testsplitmix - -.PHONY: all clean diff --git a/c/ocamlrandom.c b/c/ocamlrandom.c deleted file mode 100644 index 6c90d48..0000000 --- a/c/ocamlrandom.c +++ /dev/null @@ -1,24 +0,0 @@ -static int s[55] = { - 0x3ae2522b, 0x1d8d4634, 0x15b4fad0, 0x18b14ace, 0x12f8a3c4, 0x3b086c47, - 0x16d467d6, 0x101d91c7, 0x321df177, 0x0176c193, 0x1ff72bf1, 0x1e889109, - 0x0b464b18, 0x2b86b97c, 0x0891da48, 0x03137463, 0x085ac5a1, 0x15d61f2f, - 0x3bced359, 0x29c1c132, 0x3a86766e, 0x366d8c86, 0x1f5b6222, 0x3ce1b59f, - 0x2ebf78e1, 0x27cd1b86, 0x258f3dc3, 0x389a8194, 0x02e4c44c, 0x18c43f7d, - 0x0f6e534f, 0x1e7df359, 0x055d0b7e, 0x10e84e7e, 0x126198e4, 0x0e7722cb, - 0x1cbede28, 0x3391b964, 0x3d40e92a, 0x0c59933d, 0x0b8cd0b7, 0x24efff1c, - 0x2803fdaa, 0x08ebc72e, 0x0f522e32, 0x05398edc, 0x2144a04c, 0x0aef3cbd, - 0x01ad4719, 0x35b93cd6, 0x2a559d4f, 0x1e6fd768, 0x26e27f36, 0x186f18c3, - 0x2fbf967a, -}; - -static int idx = 0; - -int bits() { - idx = (idx + 1) % 55; - int curval = s[idx]; - int newval = s[(idx + 24) % 55] + (curval ^ ((curval >> 25) & 0x1F)); - int newval30 = newval & 0x3FFFFFFF; - s[idx] = newval30; - return newval30; -} - diff --git a/c/ocamlrandom.h b/c/ocamlrandom.h deleted file mode 100644 index 6ca5c74..0000000 --- a/c/ocamlrandom.h +++ /dev/null @@ -1 +0,0 @@ -int bits(); diff --git a/c/splitmix64.h b/c/splitmix64.h deleted file mode 100644 index 9b48294..0000000 --- a/c/splitmix64.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -uint64_t next(); diff --git a/c/testocamlrandom.c b/c/testocamlrandom.c deleted file mode 100644 index 77bce0c..0000000 --- a/c/testocamlrandom.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include "ocamlrandom.h" - -int main(int argc, char* argv[]) { - int n = 10; - if (argc == 2) n = atoi(argv[1]); - - for (int i = 0; i < n; i++) - printf("%08x\n", bits()); - - return 0; -} - diff --git a/c/testsplitmix.c b/c/testsplitmix.c deleted file mode 100644 index 2aa6e34..0000000 --- a/c/testsplitmix.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include -#include -#include "splitmix64.h" - - -int main(int argc, char* argv[]) { - int n = 10; - if (argc == 2) n = atoi(argv[1]); - - for (int i = 0; i < n; i++) - printf("%016lx\n", next()); - - return 0; -} - diff --git a/c/testxoshiro.c b/c/testxoshiro.c deleted file mode 100644 index 39bdb2d..0000000 --- a/c/testxoshiro.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include -#include -#include "xoshiro256pp.h" - -int main(int argc, const char* argv[]) { - int n = 10; - if (argc == 2) n = atoi(argv[1]); - - for (int i = 0; i < n; i++) - printf("%016lx\n", next()); - - return 0; -} diff --git a/compare.sh b/compare.sh deleted file mode 100755 index 4904341..0000000 --- a/compare.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -set -e - -compare () { - echo "Comparing '$1' and '$2'..." - tmp="$(mktemp)" - "$1" 1000 > "$tmp" - test -z "$("$2" 1000 | diff "$tmp" -)" - rm -f "$tmp" -} - -make -C ocaml tests -make -C c all - -compare ocaml/_build/default/tests/splitmix.exe c/testsplitmix -echo OK! diff --git a/dune b/dune new file mode 100644 index 0000000..75bd9a5 --- /dev/null +++ b/dune @@ -0,0 +1,2 @@ +(env + (_ (c_flags :standard -Werror -Wall -Wextra -pedantic))) diff --git a/ocaml/dune-project b/dune-project similarity index 100% rename from ocaml/dune-project rename to dune-project diff --git a/ocaml/Makefile b/ocaml/Makefile deleted file mode 100644 index 1c48a5c..0000000 --- a/ocaml/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -all: tests bench - -tests: - dune build ./tests/ocamlrandom.exe - dune build ./tests/xoshiro.exe - dune build ./tests/splitmix.exe - -bench: - dune build ./bench.exe - -clean: - dune clean - -.PHONY: all clean bench tests diff --git a/ocaml/bench.ml b/ocaml/bench.ml deleted file mode 100644 index 1ed8f82..0000000 --- a/ocaml/bench.ml +++ /dev/null @@ -1,57 +0,0 @@ -open Xoshiro -module B = Core_bench.Bench -module Command = Core.Command - -module Random_Stdlib = MakeRandom.Basic(Random) -module Random_X256pp_Int = MakeRandom.Basic(X256pp.Int) -module Random_X256pp_Int64 = MakeRandom.Basic(X256pp.Int64) -module Random_X256pp_C = MakeRandom.Basic(X256pp.C) - -let bits () = - Command.run @@ B.make_command [ - B.Test.create ~name:"Random.bits" (fun () -> - Random.bits ()); - B.Test.create ~name:"X256pp.Int.bits" (fun () -> - X256pp.Int.bits ()); - B.Test.create ~name:"X256pp.Int64.bits" (fun () -> - X256pp.Int64.bits ()); - B.Test.create ~name:"X256pp.Int64.bits62" (fun () -> - X256pp.Int64.bits62 ()); - B.Test.create ~name:"X256pp.C.bits" (fun () -> - X256pp.C.bits ()); - B.Test.create ~name:"X256pp.C.bits62" (fun () -> - X256pp.C.bits62 ()); - ] - -let float () = - Command.run @@ B.make_command [ - B.Test.create ~name:"Random.float" (fun () -> - Random.float 1.); - B.Test.create ~name:"X256pp.Int64.float" (fun () -> - X256pp.Int64.float 1.); - B.Test.create ~name:"X256pp.C.float" (fun () -> - X256pp.C.float 1.); - B.Test.create ~name:"MakeRandom(X256pp.Int).float" (fun () -> - Random_X256pp_Int.float 1.); - B.Test.create ~name:"MakeRandom(X256pp.Int64).float" (fun () -> - Random_X256pp_Int64.float 1.); - B.Test.create ~name:"MakeRandom(X256pp.C).float" (fun () -> - Random_X256pp_C.float 1.); - ] - -let int64 () = - Command.run @@ B.make_command [ - B.Test.create ~name:"MakeRandom(Random).int64" (fun () -> - Random_Stdlib.int64 Int64.max_int); - B.Test.create ~name:"MakeRandom(X256pp.Int).int64" (fun () -> - Random_X256pp_Int.int64 Int64.max_int); - B.Test.create ~name:"MakeRandom(X256pp.Int64).int64" (fun () -> - Random_X256pp_Int64.int64 Int64.max_int); - B.Test.create ~name:"MakeRandom(X256pp.C).int64" (fun () -> - Random_X256pp_C.int64 Int64.max_int); - ] - -let () = - bits (); - float (); - int64 () diff --git a/ocaml/dune b/ocaml/dune deleted file mode 100644 index 094d9f8..0000000 --- a/ocaml/dune +++ /dev/null @@ -1,4 +0,0 @@ -(executable - (name bench) - (libraries xoshiro makeRandom core_bench) - (modules Bench)) diff --git a/ocaml/tests/dune b/ocaml/tests/dune deleted file mode 100644 index 5189e02..0000000 --- a/ocaml/tests/dune +++ /dev/null @@ -1,13 +0,0 @@ -(executable - (name xoshiro) - (modules xoshiro) - (libraries xoshiro)) - -(executable - (name ocamlrandom) - (modules ocamlrandom)) - -(executable - (name splitmix) - (modules splitmix) - (libraries splitmix)) diff --git a/ocaml/tests/ocamlrandom.ml b/ocaml/tests/ocamlrandom.ml deleted file mode 100644 index 00344a3..0000000 --- a/ocaml/tests/ocamlrandom.ml +++ /dev/null @@ -1,10 +0,0 @@ -let () = - let n = - if Array.length Sys.argv = 2 - then int_of_string Sys.argv.(1) - else 10 - in - - for _ = 1 to n do - Format.printf "%08x\n" (Random.bits ()) - done diff --git a/ocaml/tests/splitmix.ml b/ocaml/tests/splitmix.ml deleted file mode 100644 index eb3e35a..0000000 --- a/ocaml/tests/splitmix.ml +++ /dev/null @@ -1,13 +0,0 @@ -open Splitmix - -let () = - let n = - if Array.length Sys.argv = 2 - then int_of_string Sys.argv.(1) - else 10 - in - - let state = ref 0xdead42beef37ca7aL in - for _ = 1 to n do - Format.printf "%016Lx@." (Sm64.next state) - done diff --git a/ocaml/tests/xoshiro.ml b/ocaml/tests/xoshiro.ml deleted file mode 100644 index e615baa..0000000 --- a/ocaml/tests/xoshiro.ml +++ /dev/null @@ -1,15 +0,0 @@ -open Xoshiro - -let () = - let n = - if Array.length Sys.argv = 2 - then int_of_string Sys.argv.(1) - else 10 - in - - for _ = 1 to n do - let hi, lo = X256pp.Int.next () in - Format.printf "%08x%08x " hi lo; - Format.printf "%016Lx " (X256pp.Int64.next ()); - Format.printf "%08x@." (X256pp.C.bits ()) - done diff --git a/ocaml/xoshiro/dune b/ocaml/xoshiro/dune deleted file mode 100644 index baefbf5..0000000 --- a/ocaml/xoshiro/dune +++ /dev/null @@ -1,5 +0,0 @@ -(include_subdirs unqualified) - -(library - (name xoshiro) - (foreign_stubs (language c) (names x256pp))) diff --git a/ocaml/xoshiro/x256pp_c/x256pp.c b/ocaml/xoshiro/x256pp_c/x256pp.c deleted file mode 100644 index c768a4d..0000000 --- a/ocaml/xoshiro/x256pp_c/x256pp.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "x256pp.h" -#include -#include - -static inline uint64_t rotl(const uint64_t x, int k) { - return (x << k) | (x >> (64 - k)); -} - -static uint64_t s[4] = { - 0xdeadbeefdeadbeef, - 0x4242424242424242, - 0x3737373737373737, - 0xca7aca7aca7aca7a -}; - -static uint64_t next(void) { - const uint64_t result = rotl(s[0] + s[3], 23) + s[0]; - - const uint64_t t = s[1] << 17; - - s[2] ^= s[0]; - s[3] ^= s[1]; - s[1] ^= s[2]; - s[0] ^= s[3]; - - s[2] ^= t; - - s[3] = rotl(s[3], 45); - - return result; -} - -static long int buf = 0; -static int buf_len = 0; -static const uint64_t mask30 = (1 << 30) - 1; - -CAMLprim value x256pp_bits() { - if (buf_len == 0) { - buf = next(); - buf_len = 2; - } - long int res = buf & mask30; - buf_len--; - buf = buf >> 32; - return Val_long(res); -} - -CAMLprim value x256pp_bits62() { - return Val_long(next() >> 2); -} - -CAMLprim value x256pp_double(value f) { - double d = (next() >> 11) * 0x1.0p-53 * Double_val(f); - return caml_copy_double(d); -} diff --git a/ocaml/xoshiro/x256pp_c/x256pp.h b/ocaml/xoshiro/x256pp_c/x256pp.h deleted file mode 100644 index 77d8b8a..0000000 --- a/ocaml/xoshiro/x256pp_c/x256pp.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef X256PP_H -#define X256PP_H 1 - -#define CAML_NAME_SPACE -#include -#include - -CAMLprim value x256pp_bits(); -CAMLprim value x256pp_bits62(); -CAMLprim value x256pp_double(value); - -#endif diff --git a/ocaml/.gitignore b/prng/src/.gitignore similarity index 100% rename from ocaml/.gitignore rename to prng/src/.gitignore diff --git a/ocaml/make-random/bench.ml b/prng/src/make-random/bench.ml similarity index 100% rename from ocaml/make-random/bench.ml rename to prng/src/make-random/bench.ml diff --git a/ocaml/make-random/dune b/prng/src/make-random/dune similarity index 100% rename from ocaml/make-random/dune rename to prng/src/make-random/dune diff --git a/ocaml/make-random/makeRandom.ml b/prng/src/make-random/makeRandom.ml similarity index 100% rename from ocaml/make-random/makeRandom.ml rename to prng/src/make-random/makeRandom.ml diff --git a/ocaml/make-random/test.ml b/prng/src/make-random/test.ml similarity index 100% rename from ocaml/make-random/test.ml rename to prng/src/make-random/test.ml diff --git a/ocaml/splitmix/dune b/prng/src/splitmix/dune similarity index 100% rename from ocaml/splitmix/dune rename to prng/src/splitmix/dune diff --git a/ocaml/splitmix/sm64.ml b/prng/src/splitmix/sm64.ml similarity index 100% rename from ocaml/splitmix/sm64.ml rename to prng/src/splitmix/sm64.ml diff --git a/prng/src/splitmix/tests/dune b/prng/src/splitmix/tests/dune new file mode 100644 index 0000000..58d28fa --- /dev/null +++ b/prng/src/splitmix/tests/dune @@ -0,0 +1,13 @@ +(executable + (name sm64_ocaml) + (libraries splitmix testutils)) + +(rule + (target sm64_c.exe) + (deps reference.h (:codedeps sm64_c.c reference.c %{lib-private:testutils:libtestutils.a})) + (action + (run %{cc} -o %{target} %{codedeps}))) + +(rule (with-stdout-to sm64_ocaml.output (run ./sm64_ocaml.exe --nb=1000))) +(rule (with-stdout-to sm64_c.output (run ./sm64_c.exe --nb=1000))) +(rule (alias runtest) (action (diff sm64_ocaml.output sm64_c.output))) diff --git a/c/splitmix64.c b/prng/src/splitmix/tests/reference.c similarity index 72% rename from c/splitmix64.c rename to prng/src/splitmix/tests/reference.c index 6dcbad8..b99dbeb 100644 --- a/c/splitmix64.c +++ b/prng/src/splitmix/tests/reference.c @@ -9,13 +9,13 @@ See . */ #include /* This is a fixed-increment version of Java 8's SplittableRandom generator - See http://dx.doi.org/10.1145/2714064.2660195 and + See http://dx.doi.org/10.1145/2714064.2660195 and http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html It is a very fast generator passing BigCrush, and it can be useful if for some reason you absolutely want 64 bits of state. */ -static uint64_t x = 0xdead42beef37ca7a; /* The state can be seeded with any value. */ +static uint64_t x; /* The state can be seeded with any value. */ uint64_t next() { uint64_t z = (x += 0x9e3779b97f4a7c15); @@ -24,3 +24,10 @@ uint64_t next() { return z ^ (z >> 31); } +// -------------------------------- +// Above this line: verbatim copy of http://prng.di.unimi.it/splitmix64.c +// Below: added by us for testing purpose + +void seed(uint64_t s) { + x = s; +} diff --git a/prng/src/splitmix/tests/reference.h b/prng/src/splitmix/tests/reference.h new file mode 100644 index 0000000..536a2b9 --- /dev/null +++ b/prng/src/splitmix/tests/reference.h @@ -0,0 +1,9 @@ +#ifndef SPLITMIX64_H +#define SPLITMIX64_H 1 + +#include + +uint64_t next(); +void seed(uint64_t); + +#endif diff --git a/prng/src/splitmix/tests/sm64_c.c b/prng/src/splitmix/tests/sm64_c.c new file mode 100644 index 0000000..24bdbb3 --- /dev/null +++ b/prng/src/splitmix/tests/sm64_c.c @@ -0,0 +1,6 @@ +#include "reference.h" // seed, next +#include "../../testutils/testutils.h" // testutils_run + +int main(int argc, char* argv[]) { + return testutils_run(argc, argv, seed, next); +} diff --git a/prng/src/splitmix/tests/sm64_ocaml.ml b/prng/src/splitmix/tests/sm64_ocaml.ml new file mode 100644 index 0000000..8cd0e97 --- /dev/null +++ b/prng/src/splitmix/tests/sm64_ocaml.ml @@ -0,0 +1,7 @@ +open Splitmix + +let () = + let state = ref 0L in + Testutils.run + ~seed_f:(fun s -> state := s) + ~next:(fun () -> Sm64.next state) diff --git a/prng/src/testutils/dune b/prng/src/testutils/dune new file mode 100644 index 0000000..ef7ee52 --- /dev/null +++ b/prng/src/testutils/dune @@ -0,0 +1,7 @@ +(foreign_library + (archive_name testutils) + (language c) + (names testutils)) + +(library + (name testutils)) diff --git a/prng/src/testutils/testutils.c b/prng/src/testutils/testutils.c new file mode 100644 index 0000000..9b7b233 --- /dev/null +++ b/prng/src/testutils/testutils.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +int usage(const char* prog_name) { + fprintf(stderr, "%s [--seed=SEED] [--nb=N]\n", prog_name); + return 1; +} + +int testutils_run( + int argc, char* argv[], void(*seed_func)(uint64_t), uint64_t(*next)(void) +) { + long nb_iterations = -1; + uint64_t seed = 0xdd6d0e2e849e51ad; + + struct option long_options[] = { + {"seed", optional_argument, NULL, 's'}, + {"nb", optional_argument, NULL, 'n'}, + }; + + while (1) { + int option_index = 0; + int c = getopt_long(argc, argv, "", long_options, &option_index); + char* endptr; + if (c == -1) break; + switch (c) { + case 's': + if (optarg == NULL) return usage(argv[0]); + seed = strtoull(optarg, &endptr, 10); + if (endptr == optarg || *endptr != '\0') return usage(argv[0]); + break; + case 'n': + if (optarg == NULL) return usage(argv[0]); + nb_iterations = strtol(optarg, &endptr, 10); + if (endptr == optarg || *endptr != '\0') return usage(argv[0]); + break; + default: + return usage(argv[0]); + } + } + + if (optind < argc) return usage(argv[0]); + + seed_func(seed); + for (long i = 0; i != nb_iterations; i++) { + printf("%lx\n", next()); + } + + return 0; +} + diff --git a/prng/src/testutils/testutils.h b/prng/src/testutils/testutils.h new file mode 100644 index 0000000..d60fcc4 --- /dev/null +++ b/prng/src/testutils/testutils.h @@ -0,0 +1,7 @@ +#ifndef TESTUTILS_H +#define TESTUTILS_H 1 + +#include +int testutils_run(int, char**, void(*)(uint64_t), uint64_t(*)(void)); + +#endif diff --git a/prng/src/testutils/testutils.ml b/prng/src/testutils/testutils.ml new file mode 100644 index 0000000..1f1dc5f --- /dev/null +++ b/prng/src/testutils/testutils.ml @@ -0,0 +1,28 @@ +let run ~seed_f ~next = + let seed = ref 0xdd6d0e2e849e51adL in + let nb_iterations = ref (-1) in + + let speclist = [ + ( + "--nb", + Arg.Set_int nb_iterations, + "Number of random integers to generate" + ); + ( + "--seed", + Arg.String (fun n -> seed := Int64.of_string n), + "64-bit seed"); + ] |> Arg.align + in + + let usage = + Format.sprintf "%s [--seed=SEED] [--nb=N]" Sys.argv.(0) + in + + Arg.parse speclist (fun _ -> invalid_arg "run") usage; + seed_f !seed; + let i = ref 0 in + while !i <> !nb_iterations do + Format.printf "%Lx@." (next ()); + incr i + done diff --git a/prng/src/xoshiro/dune b/prng/src/xoshiro/dune new file mode 100644 index 0000000..fa217cc --- /dev/null +++ b/prng/src/xoshiro/dune @@ -0,0 +1,3 @@ +(library + (name xoshiro) + (libraries splitmix)) diff --git a/prng/src/xoshiro/tests/dune b/prng/src/xoshiro/tests/dune new file mode 100644 index 0000000..9794944 --- /dev/null +++ b/prng/src/xoshiro/tests/dune @@ -0,0 +1,17 @@ +(executables + (names int64 int) + (libraries xoshiro testutils splitmix)) + +(rule + (target x256pp_c.exe) + (deps reference.h (:codedeps x256pp_c.c reference.c %{lib-private:testutils:libtestutils.a})) + (action + (run %{cc} -o %{target} %{codedeps}))) + + +(rule (with-stdout-to x256pp_int.output (run ./int.exe --nb=1000))) +(rule (with-stdout-to x256pp_int64.output (run ./int64.exe --nb=1000))) +(rule (with-stdout-to x256pp_c.output (run ./x256pp_c.exe --nb=1000))) + +(rule (alias runtest) (action (diff x256pp_int.output x256pp_c.output))) +(rule (alias runtest) (action (diff x256pp_int64.output x256pp_c.output))) diff --git a/prng/src/xoshiro/tests/int.ml b/prng/src/xoshiro/tests/int.ml new file mode 100644 index 0000000..dbe2568 --- /dev/null +++ b/prng/src/xoshiro/tests/int.ml @@ -0,0 +1,24 @@ +open Xoshiro + +let int_int_to_int64 (hi, lo) = + let open Stdlib.Int64 in + logxor (shift_left (of_int hi) 32) (of_int lo) + +let int64_to_int_int n = + let open Stdlib.Int64 in + let hi = to_int (shift_right_logical n 32) in + let lo = to_int (logand n 0xFFFFFFFFL) in + (hi, lo) + +let ocaml_seed seed = + let s = ref seed in + for i = 0 to 3 do + let hi, lo = Splitmix.Sm64.next s |> int64_to_int_int in + X256pp.Int.state.(2 * i) <- hi; + X256pp.Int.state.(2 * i + 1) <- lo + done + +let () = + Testutils.run + ~seed_f:ocaml_seed + ~next:(fun () -> X256pp.Int.next () |> int_int_to_int64) diff --git a/prng/src/xoshiro/tests/int64.ml b/prng/src/xoshiro/tests/int64.ml new file mode 100644 index 0000000..cf247e8 --- /dev/null +++ b/prng/src/xoshiro/tests/int64.ml @@ -0,0 +1,10 @@ +open Xoshiro + +let () = + Testutils.run + ~seed_f:(fun seed -> + let s = ref seed in + for i = 0 to 3 do + X256pp.Int64.s.(i) <- Splitmix.Sm64.next s + done) + ~next:X256pp.Int64.next diff --git a/c/xoshiro256pp.c b/prng/src/xoshiro/tests/reference.c similarity index 64% rename from c/xoshiro256pp.c rename to prng/src/xoshiro/tests/reference.c index 30685eb..29d78f8 100644 --- a/c/xoshiro256pp.c +++ b/prng/src/xoshiro/tests/reference.c @@ -7,7 +7,6 @@ worldwide. This software is distributed without any warranty. See . */ #include -#include /* This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators. It has excellent (sub-ns) speed, a state (256 bits) that is large @@ -25,12 +24,7 @@ static inline uint64_t rotl(const uint64_t x, int k) { } -static uint64_t s[4] = { - 0xdeadbeefdeadbeef, - 0x4242424242424242, - 0x3737373737373737, - 0xca7aca7aca7aca7a -}; +static uint64_t s[4]; uint64_t next(void) { const uint64_t result = rotl(s[0] + s[3], 23) + s[0]; @@ -48,3 +42,23 @@ uint64_t next(void) { return result; } + +// -------------------------------- +// Above this line: verbatim copy of http://prng.di.unimi.it/xoshiro256plusplus.c +// without the `jump` and `long_jump` functions. +// Below: added by us for testing purpose + +// Use splitmix64 to seed xoshiro as suggested by Vigna. +uint64_t splitmix64_stateless(uint64_t* state) { + uint64_t z = (*state += 0x9e3779b97f4a7c15); + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; + z = (z ^ (z >> 27)) * 0x94d049bb133111eb; + return z ^ (z >> 31); +} + +void seed(uint64_t x) { + uint64_t splitmix_state = x; + for (int i = 0; i < 4; i++) { + s[i] = splitmix64_stateless(&splitmix_state); + } +} diff --git a/c/xoshiro256pp.h b/prng/src/xoshiro/tests/reference.h similarity index 81% rename from c/xoshiro256pp.h rename to prng/src/xoshiro/tests/reference.h index 4f24453..1995ec0 100644 --- a/c/xoshiro256pp.h +++ b/prng/src/xoshiro/tests/reference.h @@ -4,5 +4,7 @@ #include uint64_t next(); +void seed(uint64_t); #endif + diff --git a/prng/src/xoshiro/tests/x256pp_c.c b/prng/src/xoshiro/tests/x256pp_c.c new file mode 100644 index 0000000..24bdbb3 --- /dev/null +++ b/prng/src/xoshiro/tests/x256pp_c.c @@ -0,0 +1,6 @@ +#include "reference.h" // seed, next +#include "../../testutils/testutils.h" // testutils_run + +int main(int argc, char* argv[]) { + return testutils_run(argc, argv, seed, next); +} diff --git a/ocaml/xoshiro/x256pp.ml b/prng/src/xoshiro/x256pp.ml similarity index 96% rename from ocaml/xoshiro/x256pp.ml rename to prng/src/xoshiro/x256pp.ml index 44a8ed5..23dbaca 100644 --- a/ocaml/xoshiro/x256pp.ml +++ b/prng/src/xoshiro/x256pp.ml @@ -162,9 +162,3 @@ module Int64 = struct let float x = Int64.(to_float (shift_right_logical (next ()) 11)) *. 0x1.0p-53 *. x end - -module C = struct - external bits: unit -> int = "x256pp_bits" - external bits62: unit -> int = "x256pp_bits62" - external float: float -> float = "x256pp_double" -end diff --git a/testu01/testu01/bbattery_stubs.c b/testu01/testu01/bbattery_stubs.c index acc5ab7..3e6f627 100644 --- a/testu01/testu01/bbattery_stubs.c +++ b/testu01/testu01/bbattery_stubs.c @@ -37,7 +37,7 @@ value caml_bbattery_SmallCrush(value bgen) { value caml_bbattery_SmallCrushFile(value filename) { CAMLparam1(filename); - bbattery_SmallCrushFile(Bytes_val(filename)); + bbattery_SmallCrushFile((char*)Bytes_val(filename)); CAMLreturn(Val_unit); } @@ -97,7 +97,7 @@ value caml_bbattery_Rabbit(value bgen, value nb) { value caml_bbattery_RabbitFile(value filename, value nb) { CAMLparam2(filename, nb); - bbattery_RabbitFile (Bytes_val(filename), Double_val(nb)); + bbattery_RabbitFile ((char*)Bytes_val(filename), Double_val(nb)); CAMLreturn(Val_unit); } @@ -121,7 +121,7 @@ value caml_bbattery_Alphabit(value bgen, value nb, value r, value s) { value caml_bbattery_AlphabitFile(value filename, value nb) { CAMLparam2(filename, nb); - bbattery_AlphabitFile (Bytes_val(filename), Double_val(nb)); + bbattery_AlphabitFile ((char*)Bytes_val(filename), Double_val(nb)); CAMLreturn(Val_unit); } @@ -143,7 +143,7 @@ value caml_bbattery_BlockAlphabit(value bgen, value nb, value r, value s) { value caml_bbattery_BlockAlphabitFile(value filename, value nb) { CAMLparam2(filename, nb); - bbattery_BlockAlphabitFile (Bytes_val(filename), Double_val(nb)); + bbattery_BlockAlphabitFile ((char*)Bytes_val(filename), Double_val(nb)); CAMLreturn(Val_unit); } @@ -156,6 +156,7 @@ value caml_bbattery_RepeatBlockAlphabit(value bgen, value nb, value r, value s, CAMLreturn(Val_unit); } value camlbytecode_bbattery_RepeatBlockAlphabit(value * argv, int argn) { + IGNORE(argn); return caml_bbattery_RepeatBlockAlphabit(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } @@ -179,6 +180,6 @@ value caml_bbattery_FIPS_140_2(value bgen) { value caml_bbattery_FIPS_140_2File(value filename) { CAMLparam1(filename); - bbattery_FIPS_140_2File(Bytes_val(filename)); + bbattery_FIPS_140_2File((char*)Bytes_val(filename)); CAMLreturn(Val_unit); } diff --git a/testu01/testu01/unif01_stubs.h b/testu01/testu01/unif01_stubs.h index 09e07a0..91af9f7 100644 --- a/testu01/testu01/unif01_stubs.h +++ b/testu01/testu01/unif01_stubs.h @@ -12,8 +12,6 @@ #include -static struct custom_operations unif01_Gen_boxed; - #define IGNORE(x) (void)(x) #define unif01_Gen_unbox(bgen) (* (unif01_Gen**) Data_custom_val(bgen))