~/bend-docscommunity

src/math/random.bend source

src/math/random.bend on the hub · documented module

import Baseimport ./u64.bend as Wimport ./f64.bend as Fimport ./random/rand.bend as Rimport ./random/chacha8.bend as C8import ./random/pcg.bend as P# Pseudorandom numbers, shaped like Go's math/rand/v2: a generator is a value# built from a seed the caller chooses (the same seed gives the same# sequence, bit for bit Go's), threaded explicitly: every call returns its# value next to the advanced generator.##   import ./src/math/random.bend as R#   import ./src/math/random/pcg.bend as PCG           (the state types:#   import ./src/math/random/chacha8.bend as C8         PCG.PCG, C8.ChaCha8)##   R.pcg(W.U64{1, 0}, W.U64{2, 0})                   Go: rand.NewPCG(1, 2)#   R.uint64n(~PCG.PCG, ~R.pcg_next, g, n)            Go: r.Uint64N(n)#   R.shuffle(~U32, ~PCG.PCG, ~R.pcg_next, g, xs)     Go: r.Shuffle## (each call returns the value next to the advanced generator: a pair, taken# apart in a helper def, as Bend matches only parameters)## Sources (the Source interface of random/rand.bend: a state type S and# ~next: S -> W.U64 & S, passed as templates):##   chacha8(seed), chacha8_next   Go's ChaCha8 = C2SP chacha8rand, a 32-byte#                                 seed (None unless 32 bytes < 256); a CSPRNG#                                 (for secrets use src/crypto/random.bend)#   pcg(seed1, seed2), pcg_next   Go's PCG (128-bit LCG, DXSM output); fast,#                                 not cryptographic## Functions over any source (random/rand.bend has the details):##   uint64 uint32 int64 int32     raw words#   uint64n / uint_below, uint32n, intn, int_range#                                 uniform bounded integers (Lemire, unbiased)#   float64                       uniform in [0, 1), 53 random bits#   shuffle, perm                 Fisher-Yates## Laws (spec/math/random/, proved in proofs/math/random/): the ChaCha8# stream is C2SP's for every seed, one PCG step is the 128-bit LCG and DXSM# on naturals, uint64n(n) < n, Lemire's acceptance is exactly unbiased# (every k < n has floor(2^64 / n) accepted inputs), shuffle and perm return# permutations, float64 < 1.def chacha8(+seed: List<&2, U32>) -> Maybe<&2, C8.ChaCha8>:  C8.new(seed)def chacha8_next(g: C8.ChaCha8) -> W.U64 & C8.ChaCha8:  C8.next(g)def pcg(+seed1: W.U64, +seed2: W.U64) -> P.PCG:  P.new(seed1, seed2)def pcg_next(p: P.PCG) -> W.U64 & P.PCG:  P.next(p)def uint64(~S: Data, ~next: S -> W.U64 & S, s: S) -> W.U64 & S:  R.uint64(~S, ~next, s)def uint32(~S: Data, ~next: S -> W.U64 & S, s: S) -> U32 & S:  R.uint32(~S, ~next, s)def int64(~S: Data, ~next: S -> W.U64 & S, s: S) -> W.U64 & S:  R.int64(~S, ~next, s)def int32(~S: Data, ~next: S -> W.U64 & S, s: S) -> U32 & S:  R.int32(~S, ~next, s)def uint64n(~S: Data, ~next: S -> W.U64 & S, s: S, +n: W.U64) -> W.U64 & S:  R.uint64n(~S, ~next, s, n)def uint_below(~S: Data, ~next: S -> W.U64 & S, s: S, +n: W.U64) -> W.U64 & S:  R.uint64n(~S, ~next, s, n)def uint32n(~S: Data, ~next: S -> W.U64 & S, s: S, +n: U32) -> U32 & S:  R.uint32n(~S, ~next, s, n)def intn(~S: Data, ~next: S -> W.U64 & S, s: S, +n: Nat) -> Nat & S:  R.intn(~S, ~next, s, n)def int_range(~S: Data, ~next: S -> W.U64 & S, s: S, +lo: Nat, +hi: Nat) -> Nat & S:  R.int_range(~S, ~next, s, lo, hi)def float64(~S: Data, ~next: S -> W.U64 & S, s: S) -> F.F64 & S:  R.float64(~S, ~next, s)def shuffle(~A: Data, ~S: Data, ~next: S -> W.U64 & S, s: S, +xs: List<&2, A>) -> List<&2, A> & S:  R.shuffle(~A, ~S, ~next, s, xs)def perm(~S: Data, ~next: S -> W.U64 & S, s: S, +n: Nat) -> List<&2, Nat> & S:  R.perm(~S, ~next, s, n)