bend-kit-random Releases (2): 0.1.0.1 0x46b9429cbffa7a8c1111ce19c60a3d6a indexed https://jend.leeeet.dev/files.txt?path=bend-kit-random@0.1.0.1 0.1.0.0 0x0fab7442f5a423ac9ee7dc17899842b0 unindexed https://jend.leeeet.dev/files.txt?path=bend-kit-random@0.1.0.0 Definitions (26): Random.Rng (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=Rng) # xoshiro128** state (https://prng.di.unimi.it/xoshiro128starstar.c). It is never all zero. type Rng is Data: Rng{a: U32, b: U32, c: U32, d: U32} Random.rotl (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=rotl) def rotl(+x: U32, l: Nat, r: Nat) -> U32: Random.mix (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=mix) # splitmix32's output mixer, a bijection on U32. def mix(+z: U32) -> U32: Random.seed (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=seed) # The first four splitmix32 outputs from s. Distinct seeds give distinct states. def seed(+s: U32) -> Rng: Random.from_state.if (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=from_state.if) def from_state.if(zero: Bool, a: U32, b: U32, c: U32, d: U32) -> Rng: Random.from_state (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=from_state) # The state (a, b, c, d) as is, to replay a reference stream. All zero gives seed(0). def from_state(+a: U32, +b: U32, +c: U32, +d: U32) -> Rng: Random.next (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=next) # One xoshiro128** step: a uniform U32 and the next state. def next(r: Rng) -> U32 & Rng: Random.Bool.case (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=Bool.case) def Bool.case(-A: Type, b: Bool, t: Unit -> A, f: Unit -> A) -> A: Random.below.go (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=below.go) # Rejects draws below t = 2^32 mod n, as OpenBSD's arc4random_uniform does. def below.go(fuel: Nat, +n: U32, +t: U32, xr: U32 & Rng) -> U32 & Rng: Random.below.if (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=below.if) def below.if(small: Bool, +n: U32, r: Rng) -> U32 & Rng: Random.below (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=below) # A uniform U32 in [0, n). Each draw is rejected with odds under 1/2, so after # 64 rejections, odds 2^-64, it takes x mod n. For n < 2 it is 0 and r is unchanged. def below(+n: U32, r: Rng) -> U32 & Rng: Random.range.fin (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=range.fin) def range.fin(lo: U32, xr: U32 & Rng) -> U32 & Rng: Random.range (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=range) # A uniform U32 in [lo, hi). For hi <= lo + 1 it is lo and r is unchanged. def range(+lo: U32, hi: U32, r: Rng) -> U32 & Rng: Random.unit.fin (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=unit.fin) def unit.fin(xr: U32 & Rng) -> F32 & Rng: Random.unit (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=unit) # A uniform F32 in [0, 1), from the draw's top 24 bits. def unit(r: Rng) -> F32 & Rng: Random.shuffle.fill (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=shuffle.fill) def shuffle.fill(~T: Data, xs: List<&2, T>, +i: U32, a: Array) -> Array: Random.shuffle.swap.set (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=shuffle.swap.set) def shuffle.swap.set(~T: Data, +i: U32, +j: U32, xi: T, ax: Array & T) -> Array: Random.shuffle.swap (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=shuffle.swap) def shuffle.swap(~T: Data, +i: U32, +j: U32, ax: Array & T) -> Array: Random.shuffle.go (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=shuffle.go) # Fisher-Yates: at slot i, jr is below(i + 1); slot i swaps with slot j. # At k = 0, i is 0 and below(1) drew nothing. def shuffle.go(~T: Data, k: Nat, +i: U32, a: Array, jr: U32 & Rng) -> Array & Rng: Random.shuffle.read (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=shuffle.read) # Slots [0, k] of the array, with ax the read of slot k, prepended to acc. def shuffle.read(~T: Data, k: Nat, ax: Array & T, acc: List<&2, T>) -> List<&2, T>: Random.shuffle.fin (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=shuffle.fin) def shuffle.fin(~T: Data, +m: U32, ar: Array & Rng) -> List<&2, T> & Rng: Random.shuffle.run (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=shuffle.run) def shuffle.run(~T: Data, +h: T, +xs: List<&2, T>, r: Rng) -> List<&2, T> & Rng: Random.shuffle (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=shuffle) # A uniform permutation of xs. Every draw is below(i + 1), so a list of n # items uses n - 1 draws. def shuffle(~T: Data, xs: List<&2, T>, r: Rng) -> List<&2, T> & Rng: Random.entropy (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=entropy) # 16 bytes from the OS (getentropy, or crypto.getRandomValues in JS). def entropy() -> IO(Result<&1, &1, U32 & String, U32 & U32 & U32 & U32>): Random.from_os.fin (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=from_os.fin) def from_os.fin(e: Result<&1, &1, U32 & String, U32 & U32 & U32 & U32>) -> Result<&1, &1, U32 & String, Rng>: Random.from_os (https://jend.leeeet.dev/definition.txt?path=bend-kit-random@0.1.0.1/random.bend&name=from_os) # A generator seeded from OS entropy, for when runs need not repeat. def from_os() -> IO(Result<&1, &1, U32 & String, Rng>):