package bitgenerators
PRNG bitgenerators for OCaml users
Install
Dune Dependency
Authors
Maintainers
Sources
v0.1.0.tar.gz
md5=46965587a11aa08c1e1a891f9fb12221
sha512=49423a091b05d67ee90b19d997da48f41eddabb285acdd04e1ab22f0bd6e8bccd47fe69e5b185813cc3b1c03627020d2dabd703b9c1de92869f0de118847d577
doc/src/bitgenerators/pcg.ml.html
Source file pcg.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
(* Copyright 2014 Melissa O'Neill <oneill@pcg-random.org> Copyright 2015 Robert Kern <robert.kern@gmail Copyright (c) 2024, Zolisa Bleki SPDX-License-Identifier: BSD-3-Clause *) open Stdint module PCG64 : sig (** PCG-64 is a 128-bit implementation of O'Neill's permutation congruential generator. PCG-64 has a period of {m 2^{128}} and supports advancing an arbitrary number of steps as well as {m 2^{127}} streams. The specific member of the PCG family that we use is PCG XSL RR 128/64. The PCG64 state vector consists of 2 unsigned 128-bit values. One is the state of the PRNG, which is advanced by a linear congruential generator (LCG). The second is a fixed odd increment used in the LCG. The input seed is processed by {!SeedSequence} to generate both values. *) include Common.BITGEN val advance : int128 -> t -> t (** [advance delta] Advances the underlying RNG as if [delta] draws have been made. The returned state is that of the generator [delta] steps forward. *) val next_bounded_uint64 : uint64 -> t -> uint64 * t (** [next_bounded_uint64 bound t] returns an unsigned 64bit integers in the range (0, bound) as well as the state of the generator advanced one step forward. *) end = struct type t = {s : setseq; ustore : uint32 option} and setseq = {state : uint128; increment : uint128} let multiplier = Uint128.of_string "0x2360ed051fc65da44385df649fccf645" let sixtythree = Uint32.of_int 63 (* Uses the XSL-RR output function *) let output state = let v = Uint128.(shift_right state 64 |> logxor state |> to_uint64) and r = Uint128.(shift_right state 122 |> to_int) in let nr = Uint32.(of_int r |> neg |> logand sixtythree |> to_int) in Uint64.(logor (shift_left v nr) (shift_right v r)) let next {state; increment} = let state' = Uint128.(state * multiplier + increment) in output state', {state = state'; increment} let next_uint64 t = match next t.s with | u, s -> 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 advance delta {s = {state; increment}; _} = let open Uint128 in let rec lcg d am ap cm cp = (* advance state using LCG method *) match d = zero, logand d one = one with | true, _ -> am * state + ap | false, true -> lcg (shift_right d 1) (am * cm) (ap * cm + cp) (cm * cm) (cp * (cm + one)) | false, false -> lcg (shift_right d 1) am ap (cm * cm) (cp * (cm + one)) in {s = {state = lcg (Uint128.of_int128 delta) one zero multiplier increment; increment}; ustore = None} let set_seed seed = let open Uint128 in let s = logor (shift_left (of_uint64 seed.(0)) 64) (of_uint64 seed.(1)) and i = logor (shift_left (of_uint64 seed.(2)) 64) (of_uint64 seed.(3)) in let increment = logor (shift_left i 1) one in {state = (increment + s) * multiplier + increment; increment} let next_bounded_uint64 bound t = Common.next_bounded_uint64 bound ~nextu64:next_uint64 t let initialize seed = {s = set_seed (Seed.SeedSequence.generate_64bit_state 4 seed); ustore = None} end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>