proofs/math/random/lemire.bend checks
raw source on the hub · import bend-collections-laws-crypto@1.0.0.0/proofs/math/random/lemire.bend as Lemire
10 imports
import Base import ../../../spec/lib/common.bend as C import ../../../spec/math/random/rand.bend as SR import ../../lib/logic.bend as L import ../../lib/nat.bend as N import ../typed/width.bend as WI import ../natural/arith.bend as AR import ../../lib/arith.bend as LA import ../../lib/u32alg.bend as UA import ../../lib/lemmas/proofs/nat_algebra.bend as NA
Definitions
def b2n source · line 25 · raw
@b:Bool -> Nat
def and_false source · line 30 · raw
@+b:Bool -> {Bool.and(b, False{}) == False{} : Bool}
def and_lt source · line 38 · raw
@+lo:Nat -> @+n:Nat -> @+t:Nat -> @+ht:{Nat.is_lt(t, n) == True{} : Bool} -> @+c:Bool -> @+hc:{Nat.is_lt(lo, t) == c : Bool} -> {Bool.and(Nat.is_lt(lo, n), Nat.is_lt(lo, t)) == c : Bool}lo < n and lo < t is lo < t, when t < n
def hit_acc source · line 48 · raw
@+hi:Nat -> @+k:Nat -> @+ok:Bool -> Nat
the hit of an accepted or rejected hi
def le_plus source · line 52 · raw
@+t:Nat -> @+s:Nat -> {Nat.is_le(s, Nat.add(t, s)) == True{} : Bool}s <= t + s
def fin_lt source · line 58 · raw
@+hi:Nat -> @+k:Nat -> @+ok:Bool -> @+h:{Nat.is_lt(hi, k) == True{} : Bool} -> {Nat.add(hit_acc(hi, k, ok), 1n) == 1n : Nat}
def term_lt source · line 67 · raw
@+w:Nat -> @+k:Nat -> @+t:Nat -> @+lo:Nat -> @+hi:Nat -> @+ok:Bool -> @+hlo:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.fits(w, lo) == True{} : Bool} -> @+hab:{Nat.is_le(Nat.add(t, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k)) == True{} : Bool} -> @+h:{Nat.is_lt(hi, k) == True{} : Bool} -> {Nat.add(hit_acc(hi, k, ok), b2n(Nat.is_lt(Nat.add(lo, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, hi)), Nat.add(t, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k))))) == b2n(Nat.is_lt(Nat.add(lo, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, hi)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k))) : Nat}hi < k: rejected or not, x n lies below both thresholds
def fin_eq source · line 76 · raw
@+k:Nat -> @+c:Bool -> {Nat.add(hit_acc(k, k, Bool.not(c)), b2n(c)) == 1n : Nat}
def term_eq source · line 86 · raw
@+w:Nat -> @+k:Nat -> @+t:Nat -> @+lo:Nat -> @+hlo:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.fits(w, lo) == True{} : Bool} -> {Nat.add(hit_acc(k, k, Bool.not(Nat.is_lt(lo, t))), b2n(Nat.is_lt(Nat.add(lo, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), Nat.add(t, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k))))) == b2n(Nat.is_lt(Nat.add(lo, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k))) : Nat}hi == k: x n is below the upper threshold, and below the lower one exactly when it is rejected
def fin_gt source · line 91 · raw
@+hi:Nat -> @+k:Nat -> @+ok:Bool -> @+h:{Nat.is_lt(k, hi) == True{} : Bool} -> {Nat.add(hit_acc(hi, k, ok), 0n) == 0n : Nat}
def term_gt source · line 100 · raw
@+w:Nat -> @+k:Nat -> @+t:Nat -> @+lo:Nat -> @+hi:Nat -> @+ok:Bool -> @+hab:{Nat.is_le(Nat.add(t, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k)) == True{} : Bool} -> @+h:{Nat.is_lt(k, hi) == True{} : Bool} -> {Nat.add(hit_acc(hi, k, ok), b2n(Nat.is_lt(Nat.add(lo, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, hi)), Nat.add(t, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k))))) == b2n(Nat.is_lt(Nat.add(lo, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, hi)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k))) : Nat}hi > k: x n is at or above both thresholds
def term_cases source · line 108 · raw
@+w:Nat -> @+n:Nat -> @+k:Nat -> @+t:Nat -> @+lo:Nat -> @+hi:Nat -> @+hlo:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.fits(w, lo) == True{} : Bool} -> @+ht:{Nat.is_lt(t, n) == True{} : Bool} -> @+hab:{Nat.is_le(Nat.add(t, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k)) == True{} : Bool} -> @+lt:Bool -> @+eq:Bool -> @+hlt:{Nat.is_lt(hi, k) == lt : Bool} -> @+heq:{Nat.is_eq(hi, k) == eq : Bool} -> {Nat.add(hit_acc(hi, k, Bool.not(Bool.and(Nat.is_lt(lo, n), Nat.is_lt(lo, t)))), b2n(Nat.is_lt(Nat.add(lo, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, hi)), Nat.add(t, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k))))) == b2n(Nat.is_lt(Nat.add(lo, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, hi)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k))) : Nat}
def term source · line 122 · raw
@+w:Nat -> @+n:Nat -> @+k:Nat -> @+y:Nat -> @+ht:{Nat.is_lt(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.pow2mod(w, n), n) == True{} : Bool} -> @+hab:{Nat.is_le(Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.pow2mod(w, n), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k)) == True{} : Bool} -> {Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.hit(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.lemire(w, n, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.high(w, y), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.low(w, y)), k), b2n(Nat.is_lt(y, Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.pow2mod(w, n), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k))))) == b2n(Nat.is_lt(y, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k))) : Nat}THEOREM (one output, Lemire's branch): with t = 2^w mod n < n and k 2^w + t <= (k + 1) 2^w, y = x n draws k exactly when k 2^w + t <= y < (k + 1) 2^w
def cnt_lt source · line 132 · raw
@+n:Nat -> @+c:Nat -> @N:Nat -> Nat
#{x < N : x n < c}
def draw_lemire source · line 140 · raw
@+w:Nat -> @+m:Nat -> @+x:Nat -> @+hp:{Nat.is_eq(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, 1n+m, m), 0n) == False{} : Bool} -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.draw(w, x, 1n+m) == 0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.lemire(w, 1n+m, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.high(w, Nat.mul(x, 1n+m)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.low(w, Nat.mul(x, 1n+m))) : Maybe<&2, Nat>}the draw is Lemire's when n is not a power of two
def add4 source · line 145 · raw
@+a:Nat -> @+h:Nat -> @+b:Nat -> @+e:Nat -> {Nat.add(Nat.add(a, h), Nat.add(b, e)) == Nat.add(Nat.add(a, b), Nat.add(h, e)) : Nat}(a + h) + (b + e) == (a + b) + (h + e)
def sum_lemire source · line 159 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> @+N:Nat -> @+hp:{Nat.is_eq(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, 1n+m, m), 0n) == False{} : Bool} -> @+ht:{Nat.is_lt(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.pow2mod(w, 1n+m), 1n+m) == True{} : Bool} -> @+hab:{Nat.is_le(Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.pow2mod(w, 1n+m), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k)) == True{} : Bool} -> {Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.count(w, 1n+m, k, N), cnt_lt(1n+m, Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.pow2mod(w, 1n+m), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), N)) == cnt_lt(1n+m, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k), N) : Nat}the Lemire outputs below N plus those with x n below the lower threshold are those with x n below the upper one
def le_succ_lt source · line 179 · raw
@+a:Nat -> @+b:Nat -> {Nat.is_le(1n+a, b) == Nat.is_lt(a, b) : Bool}a + 1 <= b is a < b
def lt_ceil source · line 191 · raw
@+bp:Nat -> @+x:Nat -> @+c:Nat -> {Nat.is_lt(Nat.mul(x, 1n+bp), c) == Nat.is_lt(x, Nat.div(Nat.add(c, bp), 1n+bp)) : Bool}x n < c is x < ceil(c / n) = (c + n - 1) / n, n = 1 + bp
def min_zero source · line 206 · raw
@+n:Nat -> {Nat.min(n, 0n) == 0n : Nat}
def min_succ source · line 214 · raw
@+n:Nat -> @+c:Nat -> {Nat.min(1n+n, c) == Nat.add(Nat.min(n, c), b2n(Nat.is_lt(n, c))) : Nat}min(N + 1, C) = min(N, C) + [N < C]
def cnt_min source · line 226 · raw
@+bp:Nat -> @+c:Nat -> @+N:Nat -> {cnt_lt(1n+bp, c, N) == Nat.min(N, Nat.div(Nat.add(c, bp), 1n+bp)) : Nat}THEOREM: #{x < N : x n < c} = min(N, ceil(c / n))
def dbl_add source · line 240 · raw
@+z:Nat -> {Nat.double(z) == Nat.add(z, z) : Nat}
def pm source · line 249 · raw
@+w:Nat -> @+m:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.pow2mod(w, 1n+m) == Nat.mod(0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n), 1n+m) : Nat}Go's -n % n: 2^w mod n
def div_add_mul source · line 263 · raw
@+q:Nat -> @+m:Nat -> @+r:Nat -> {Nat.div(Nat.add(Nat.mul(q, 1n+m), r), 1n+m) == Nat.add(q, Nat.div(r, 1n+m)) : Nat}(q n + r) / n = q + r / n
def min_le source · line 271 · raw
@+n:Nat -> @+c:Nat -> @+h:{Nat.is_le(c, n) == True{} : Bool} -> {Nat.min(n, c) == c : Nat}
def lt_add2 source · line 281 · raw
@+a:Nat -> @+b:Nat -> @+c:Nat -> @+d:Nat -> @+hab:{Nat.is_le(a, b) == True{} : Bool} -> @+hcd:{Nat.is_lt(c, d) == True{} : Bool} -> {Nat.is_lt(Nat.add(a, c), Nat.add(b, d)) == True{} : Bool}a <= b and c < d give a + c < b + d
def cb_le source · line 285 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> @+hk:{Nat.is_lt(k, 1n+m) == True{} : Bool} -> {Nat.is_le(Nat.div(Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k), m), 1n+m), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n)) == True{} : Bool}ceil((k + 1) 2^w / n) <= 2^w for k < n
def hab_of source · line 304 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> @+hw:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.fits(w, 1n+m) == True{} : Bool} -> {Nat.is_le(Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.pow2mod(w, 1n+m), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k)) == True{} : Bool}t <= 2^w for t < n <= 2^w
def bm_eq source · line 315 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> {Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n+k), m) == Nat.add(Nat.mul(Nat.div(0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n), 1n+m), 1n+m), Nat.add(Nat.add(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.pow2mod(w, 1n+m), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, k)), m)) : Nat}(k + 1) 2^w + m = q n + (t + k 2^w + m), q n + t = 2^w
def lemire_count source · line 327 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> @+hp:{Nat.is_eq(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, 1n+m, m), 0n) == False{} : Bool} -> @+hw:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.fits(w, 1n+m) == True{} : Bool} -> @+hk:{Nat.is_lt(k, 1n+m) == True{} : Bool} -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.count(w, 1n+m, k, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n)) == Nat.div(0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n), 1n+m) : Nat}THEOREM (Lemire's branch): floor(2^w / n) outputs draw k
def cm source · line 358 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> @N:Nat -> Nat
#{x < N : and_bits(w, x, m) == k}
def cm2 source · line 366 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> @N:Nat -> Nat
the same count taken over the pairs 2y, 2y + 1 with y < N
def split source · line 373 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> @+N:Nat -> {cm(w, m, k, Nat.double(N)) == cm2(w, m, k, N) : Nat}
def pair_eq source · line 385 · raw
@+a:Nat -> @+k:Nat -> {Nat.add(b2n(Nat.is_eq(Nat.double(a), k)), b2n(Nat.is_eq(1n+Nat.double(a), k))) == b2n(Nat.is_eq(a, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.half(k))) : Nat}[2a == k] + [2a + 1 == k] == [a == k / 2]
def bit_dbl0 source · line 400 · raw
@+y:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.bit(Nat.double(y)) == 0n : Nat}
def half_dbl0 source · line 403 · raw
@+y:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.half(Nat.double(y)) == y : Nat}
def bit_dbl1 source · line 406 · raw
@+y:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.bit(1n+Nat.double(y)) == 1n : Nat}
def half_dbl1 source · line 409 · raw
@+y:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.half(1n+Nat.double(y)) == y : Nat}
def pair_and source · line 414 · raw
@+v:Nat -> @+h:Nat -> @+k:Nat -> @+y:Nat -> {Nat.add(b2n(Nat.is_eq(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(1n+v, Nat.double(y), 1n+Nat.double(h)), k)), b2n(Nat.is_eq(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(1n+v, 1n+Nat.double(y), 1n+Nat.double(h)), k))) == b2n(Nat.is_eq(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(v, y, h), 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.half(k))) : Nat}with m = 2h + 1: the pair 2y, 2y + 1 draws k once exactly when y draws k / 2 one width lower with h
def pairs source · line 425 · raw
@+v:Nat -> @+h:Nat -> @+k:Nat -> @+N:Nat -> {cm2(1n+v, 1n+Nat.double(h), k, N) == cm(v, h, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.half(k), N) : Nat}the pairs one width up count what the lower width counts
def and0 source · line 435 · raw
@+w:Nat -> @+x:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, x, 0n) == 0n : Nat}x & 0 == 0
def cm0 source · line 445 · raw
@+w:Nat -> @+N:Nat -> {cm(w, 0n, 0n, N) == N : Nat}n = 1: every output draws 0
def cm0k source · line 454 · raw
@+w:Nat -> @+k:Nat -> @+N:Nat -> @+hk:{Nat.is_lt(k, 1n) == True{} : Bool} -> {cm(w, 0n, k, N) == N : Nat}
def div_one source · line 461 · raw
@+N:Nat -> {Nat.div(N, 1n) == N : Nat}
def div_double source · line 466 · raw
@+a:Nat -> @+h:Nat -> {Nat.div(Nat.double(a), 2n+Nat.double(h)) == Nat.div(a, 1n+h) : Nat}2a / 2n = a / n
def bitsq_b source · line 475 · raw
@+b:Nat -> @+h:{Nat.is_le(b, 1n) == True{} : Bool} -> {Nat.mul(b, b) == b : Nat}bit * bit == bit
def and_self source · line 485 · raw
@+w:Nat -> @+x:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, x, x) == 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.low(w, x) : Nat}x & x is the low w bits of x
def dbl0 source · line 493 · raw
@+z:Nat -> @+h:{Nat.double(z) == 0n : Nat} -> {z == 0n : Nat}
def decomp source · line 501 · raw
@+m:Nat -> @+b:Nat -> @+h:Nat -> @+hb:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.bit(m) == b : Nat} -> @+hh:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.half(m) == h : Nat} -> {m == Nat.add(b, Nat.double(h)) : Nat}m = bit(m) + 2 half(m)
def and_even source · line 508 · raw
@+w:Nat -> @+h:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(1n+w, 2n+Nat.double(h), 1n+Nat.double(h)) == Nat.double(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, 1n+h, h)) : Nat}n = 2h + 2, m = 2h + 1: n & m is twice (h + 1) & h one width lower
def and_odd source · line 515 · raw
@+w:Nat -> @+g:Nat -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(1n+w, 3n+Nat.double(g), 2n+Nat.double(g)) == Nat.double(0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.low(w, 1n+g)) : Nat}n = 2g + 3, m = 2g + 2: n & m is twice the low bits of g + 1
def mask source · line 524 · raw
@+v:Nat -> @+m:Nat -> @+k:Nat -> @+b:Nat -> @+h:Nat -> @+hb:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.bit(m) == b : Nat} -> @+hh:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.half(m) == h : Nat} -> @+hp:{0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(v, 1n+m, m) == 0n : Nat} -> @+hw:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.fits(v, 1n+m) == True{} : Bool} -> @+hk:{Nat.is_lt(k, 1n+m) == True{} : Bool} -> {cm(v, m, k, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(v, 1n)) == Nat.div(0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(v, 1n), 1n+m) : Nat}THEOREM (the mask branch): with n = 1 + m, n & m == 0 and n < 2^v, each k < n is the low bits of floor(2^v / n) outputs
def draw_mask source · line 576 · raw
@+w:Nat -> @+m:Nat -> @+x:Nat -> @+hp:{Nat.is_eq(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, 1n+m, m), 0n) == True{} : Bool} -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.draw(w, x, 1n+m) == Some{0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, x, m)} : Maybe<&2, Nat>}the draw is the mask when n is a power of two
def count_mask source · line 580 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> @+N:Nat -> @+hp:{Nat.is_eq(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, 1n+m, m), 0n) == True{} : Bool} -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.count(w, 1n+m, k, N) == cm(w, m, k, N) : Nat}
def unbiased_c source · line 589 · raw
@+w:Nat -> @+m:Nat -> @+k:Nat -> @+hw:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.fits(w, 1n+m) == True{} : Bool} -> @+hk:{Nat.is_lt(k, 1n+m) == True{} : Bool} -> @+c:Bool -> @+hc:{Nat.is_eq(0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.and_bits(w, 1n+m, m), 0n) == c : Bool} -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.count(w, 1n+m, k, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n)) == Nat.div(0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n), 1n+m) : Nat}
def unbiased source · line 600 · raw
@+w:Nat -> @+n:Nat -> @+k:Nat -> @+hn:{Nat.is_lt(0n, n) == True{} : Bool} -> @+hw:{0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.fits(w, n) == True{} : Bool} -> @+hk:{Nat.is_lt(k, n) == True{} : Bool} -> {0xa7e654f9780078ca65bf9e187da99d3e/spec/math/random/rand.count(w, n, k, 0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n)) == Nat.div(0xa7e654f9780078ca65bf9e187da99d3e/spec/lib/common.shift(w, 1n), n) : Nat}THEOREM (Lemire.unbiased): for every width w, bound 0 < n < 2^w and k < n, exactly floor(2^w / n) of the 2^w outputs draw k