~/bend-docscommunity

rng.bend source

rng.bend on the hub · documented module

# RandomProvider surface — C# Unsga3.Utilities.RandomProvider.# Seed + NextDouble in [0, 1) + Next / NextExcept for tournament.# Portable Numerical Recipes LCG (not .NET System.Random). Algorithm# A/B fronts will not match C# bit-for-bit because of this RNG delta.## Affine API: `next_double` / `next_nat` return the advanced state;# `last_double` / `last_nat` are that draw. Callers use lets, not# pair-destructure.import Basetype State is Data:  MkState{    s0: U32    u: U32    z: F32    k: Nat  }def new(+s0: U32) -> State:  MkState{s0, s0, 0.0, 0n}def from_nat(seed: Nat) -> State:  new(U32.from_nat(seed))def seed_of(s: State) -> U32:  match s:    case MkState{s0, u, z, k}:      s0def last_double(s: State) -> F32:  match s:    case MkState{s0, u, z, k}:      zdef last_nat(s: State) -> Nat:  match s:    case MkState{s0, u, z, k}:      kdef step(u: U32) -> U32:  U32.add(U32.mul(1664525, u), 1013904223)# Top 24 bits / 2^24 so the F32 mantissa is exact and the value is in [0, 1).def to_unit(u: U32) -> F32:  F32.div(U32.to_f32(U32.shrn(u, 8n)), 16777216.0)def next_double(s: State) -> State:  match s:    case MkState{s0, u, z, k}:      +n = step(u)      MkState{s0, n, to_unit(n), k}def pred_or_zero(n: Nat) -> Nat:  match n:    case 0n:      0n    case 1n+p:      pdef clamp_lt.fin(+i: Nat, +n: Nat, ok: Bool) -> Nat:  match ok:    case True{}:      i    case False{}:      pred_or_zero(n)def clamp_lt(+i: Nat, +n: Nat) -> Nat:  clamp_lt.fin(i, n, Nat.is_lt(i, n))def idx_from(+z: F32, n: Nat) -> Nat:  match n:    case 0n:      0n    case 1n++p:      clamp_lt(F32.to_nat(F32.trunc(F32.mul(z, F32.from_nat(1n+p)))), 1n+p)def with_k(s: State, k2: Nat) -> State:  match s:    case MkState{s0, u, z, k}:      MkState{s0, u, z, k2}# Uniform integer in [0, n). n == 0n → 0n.def next_nat(s: State, n: Nat) -> State:  +s2 = next_double(s)  with_k(s2, idx_from(last_double(s2), n))def bump_except(+v: Nat, +exclude: Nat, below: Bool) -> Nat:  match below:    case True{}:      v    case False{}:      1n+v# C# NextExcept: uniform in [0, n) distinct from exclude when n > 1.def next_except.go(s: State, +exclude: Nat, n: Nat) -> State:  match n:    case 0n:      with_k(s, 0n)    case 1n:      with_k(s, 0n)    case 1n+m:      +s2 = next_nat(s, m)      +v = last_nat(s2)      with_k(s2, bump_except(v, exclude, Nat.is_lt(v, exclude)))def next_except(s: State, n: Nat, exclude: Nat) -> State:  next_except.go(s, exclude, n)