package bitgenerators

  1. Overview
  2. Docs
PRNG bitgenerators for OCaml users

Install

Dune Dependency

Authors

Maintainers

Sources

v0.1.0.tar.gz
md5=46965587a11aa08c1e1a891f9fb12221
sha512=49423a091b05d67ee90b19d997da48f41eddabb285acdd04e1ab22f0bd6e8bccd47fe69e5b185813cc3b1c03627020d2dabd703b9c1de92869f0de118847d577

README.md.html

bitgenerators

This library provides a port of numpy's random module bitgenerator interface for working with pseudo-random number generation. Several PRNG algorithms are implemented and exposed using numpy's bitgenerator interface in a purely functional manner for Ocaml users.

Documentation

Comprehensive documentation of available features is available at the project's site.

Usage

A SeedSequence module based on these ideas is available to providing a high quality seed sequence that can be used to initialize any of the supported PRNG's:

open Bitgen
open Stdint

let seedseq = SeedSequence.initialize [Uint128.of_int 123456789]
let rng = PCG64.initialize seedseq 

It can also be used to initialize any custom PRNG using the module's generate_64bit_state and generate_32bit_state functions:

SeedSequence.generate_64bit_state 4 seedseq |> Array.map Uint64.to_string 
(* - : string array =
   [|"5976902797103608158"; "11230215241436205182"; "1766494744865860250";
     "7661475472903581292"|] *)

Below is an example of using an initialized PCG64 bitgenerator to generate 10 random floats:

let rec compute t acc = function
    | 0 -> List.rev acc, t
    | i -> let u, t' = PCG64.next_uint64 t in compute t' (Uint64.to_string u :: acc) (i - 1)
in compute rng [] 10 |> fst
(* - : string list =
   ["511209809126027580"; "16725663875132018381"; "16258841331763118777";
    "11527320112047894150"; "14586113755615299794"; "15235313769381631730";
    "15526732141789886995"; "8701844723981253752"; "17657754321871037678";
    "17461531751233692673"] *)

One can use SeedSequence.spawn to generate many independent bitgenerators that can be used in parallel computations in a reproducible manner:

let next_float t = Some (PCG64.next_double t) in
let compute t = Seq.unfold next_float t |> Seq.take 6 |> List.of_seq in
SeedSequence.spawn 4 seedseq
|> fst
|> List.map PCG64.initialize
|> List.map (fun x -> Domain.spawn (fun () -> compute x))
|> List.map Domain.join
(* - : float list list =
[[0.407206833679825242; 0.189731803785485376; 0.564081542309661343;
  0.88682304196963746; 0.45229844727129942; 0.701372920128140565];
 [0.580212874721654503; 0.0892784737148068; 0.511665172650789257;
  0.931271866226736411; 0.928633846357239; 0.173606152636579414];
 [0.171815817392286574; 0.585509477690361213; 0.837844400599859318;
  0.569340928519763145; 0.680737776645169879; 0.620841051213270267];
 [0.736203907003532887; 0.479879743687943505; 0.506036578793879;
  0.596207202439843376; 0.792829648424435; 0.540970530700028429]] *)

Another pattern to generate independent non-overlapping instances of a bitgenerator for parallel applications is to use jump or advance functions for PRNG's that support such functions:

Philox4x64.initialize seedseq |> Seq.iterate Philox4x64.jump |> Seq.take 5 |> List.of_seq 
(* - : Philox4x64.t list = [<abstr>; <abstr>; <abstr>; <abstr>; <abstr>] *)

The resulting list of bitgenerators produce non-overlapping streams of random numbers.

Supported bitgenerators include: PCG64, Philox4x64, Xoshiro256, ChaCha and SFC64. More coming soon!

Empirical Randomness Testing

Running the test suite provided by TestU01 on the supported generators is supported. To build the test executable one needs to run dune build bin. To see the available command options run dune exec -- crush -help. Below is a sample output from running dune exec -- crush pcg64 to test PCG64 on the Small Crush test suite:

$ dune exec -- crush pcg64

========= Summary results of SmallCrush =========

 Version:          TestU01 1.2.3
 Generator:        pcg64
 Number of statistics:  15
 Total CPU time:   00:01:40.64

 All tests were passed

Benchmarks

A utility to compare the performance of each bitgenerator's next_uint64 function is provided. To compile the benchmark executor run dune build bin, and then run it using dune exec -- bench. Once the benchmark run has completed, a summary table will be displayed in stdout.

OCaml

Innovation. Community. Security.