~/bend-docscommunity

proofs/math/typed/w64mul.bend checks

raw source on the hub · import bend-collections-laws-math@1.0.0.0/proofs/math/typed/w64mul.bend as W64mul

17 imports
import Base
import ../../../spec/lib/common.bend as C
import ../../../spec/math/w64.bend as SW
import ../../../src/math/w64.bend as X
import ../../../src/math/u64.bend as WU
import ../../lib/nat.bend as N
import ../../lib/logic.bend as L
import ../../lib/u32div.bend as UD
import ../../lib/word.bend as WD
import ../../lib/arith.bend as AR
import ../../lib/u32alg.bend as A
import ../../lib/lemmas/proofs/nat_algebra.bend as NA
import ../../lib/lemmas/proofs/word_multiplication.bend as WM
import ../../lib/lemmas/spec/numeric.bend as S
import ../u64/u64div.bend as PD
import ../u64/u64.bend as P64
import ./shrn.bend as SR

Definitions

def v source · line 31 · raw

@+x:U32 -> Nat

def le_mul_r source · line 36 · raw

@+a:Nat -> @+b:Nat -> @+c:Nat -> @+h:{Nat.is_le(b, c) == True{} : Bool} -> {Nat.is_le(Nat.mul(a, b), Nat.mul(a, c)) == True{} : Bool}

def mul_lt_sq source · line 42 · raw

@+x:Nat -> @+y:Nat -> @+s:Nat -> @+hx:{Nat.is_lt(x, s) == True{} : Bool} -> @+hy:{Nat.is_lt(y, s) == True{} : Bool} -> {Nat.is_lt(Nat.mul(x, y), Nat.mul(s, s)) == True{} : Bool}

x, y < s gives x * y < s * s

def sq_sc source · line 54 · raw

@+k:Nat -> @+one:Nat -> @+h1:{one == 1n : Nat} -> {Nat.mul(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, one), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, one)) == 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(Nat.add(k, k), one) : Nat}

def mul_sc1 source · line 57 · raw

@+k:Nat -> @+one:Nat -> @+h1:{one == 1n : Nat} -> @+x:Nat -> {Nat.mul(x, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, one)) == 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, x) : Nat}

def nz16 source · line 62 · raw

@+c:U32 -> @+pc:{c == U32{0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.pw(32n, 16n)} : U32} -> {U32.is_zero(c) == False{} : Bool}

def h16 source · line 65 · raw

@+one:Nat -> @+h1:{one == 1n : Nat} -> @+c:U32 -> @+pc:{c == U32{0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.pw(32n, 16n)} : U32} -> {v(c) == 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, one) : Nat}

def lo16 source · line 68 · raw

@+x:U32 -> @+m:U32 -> Nat

def hi16 source · line 71 · raw

@+x:U32 -> @+c:U32 -> Nat

def lo16_lt source · line 74 · raw

@+one:Nat -> @+h1:{one == 1n : Nat} -> @+x:U32 -> @+m:U32 -> @+pm:{m == U32{0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.mask(32n, 16n)} : U32} -> {Nat.is_lt(lo16(x, m), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, one)) == True{} : Bool}

def dm16 source · line 78 · raw

@+one:Nat -> @+h1:{one == 1n : Nat} -> @+x:U32 -> @+c:U32 -> @+pc:{c == U32{0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.pw(32n, 16n)} : U32} -> {Nat.add(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, hi16(x, c)), v(U32.mod(x, c))) == v(x) : Nat}

v(x) == 2^16 hi + (x mod 2^16)

def hi16_lt source · line 83 · raw

@+one:Nat -> @+h1:{one == 1n : Nat} -> @+x:U32 -> @+c:U32 -> @+pc:{c == U32{0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.pw(32n, 16n)} : U32} -> {Nat.is_lt(hi16(x, c), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, one)) == True{} : Bool}

def split16 source · line 89 · raw

@+one:Nat -> @+h1:{one == 1n : Nat} -> @+x:U32 -> @+c:U32 -> @+pc:{c == U32{0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.pw(32n, 16n)} : U32} -> @+m:U32 -> @+pm:{m == U32{0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.mask(32n, 16n)} : U32} -> {v(x) == Nat.add(lo16(x, m), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, hi16(x, c))) : Nat}

v(x) == lo + 2^16 hi

def cong_l source · line 100 · raw

@+x:Nat -> @+y:Nat -> @+z:Nat -> @+e:{x == y : Nat} -> {Nat.add(x, z) == Nat.add(y, z) : Nat}

def cong_r source · line 103 · raw

@+z:Nat -> @+x:Nat -> @+y:Nat -> @+e:{x == y : Nat} -> {Nat.add(z, x) == Nat.add(z, y) : Nat}

def cong_sc source · line 106 · raw

@+k:Nat -> @+x:Nat -> @+y:Nat -> @+e:{x == y : Nat} -> {0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, x) == 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, y) : Nat}

def mul_sc_r source · line 110 · raw

@+k:Nat -> @+q:Nat -> @+d:Nat -> {Nat.mul(q, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, d)) == 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, Nat.mul(q, d)) : Nat}

q * 2^k d == 2^k (q d)

def mul_sc_l source · line 114 · raw

@+k:Nat -> @+q:Nat -> @+d:Nat -> {Nat.mul(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, q), d) == 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, Nat.mul(q, d)) : Nat}

2^k q * d == 2^k (q d)

def sc_sc source · line 118 · raw

@+j:Nat -> @+k:Nat -> @+x:Nat -> {0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(j, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, x)) == 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(Nat.add(j, k), x) : Nat}

2^j (2^k x) == 2^(j+k) x

def sc_add2 source · line 121 · raw

@+k:Nat -> @+x:Nat -> @+y:Nat -> {0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, Nat.add(x, y)) == Nat.add(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, x), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, y)) : Nat}

def add4 source · line 125 · raw

@+a:Nat -> @+b:Nat -> @+c:Nat -> @+d:Nat -> {Nat.add(Nat.add(a, b), Nat.add(c, d)) == Nat.add(Nat.add(a, c), Nat.add(b, d)) : Nat}

(a + b) + (c + d) == (a + c) + (b + d)

def expand16 source · line 131 · raw

@+al:Nat -> @+ah:Nat -> @+bl:Nat -> @+bh:Nat -> {Nat.mul(Nat.add(al, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, ah)), Nat.add(bl, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, bh))) == Nat.add(Nat.add(Nat.mul(al, bl), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, Nat.mul(al, bh))), Nat.add(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, Nat.mul(ah, bl)), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(32n, Nat.mul(ah, bh)))) : Nat}

(al + 2^16 ah)(bl + 2^16 bh) == (al bl + 2^16 al bh) + (2^16 ah bl + 2^32 ah bh)

def mid_eq source · line 149 · raw

@+m:Nat -> @+k:Nat -> @+mlo:Nat -> @+mhi:Nat -> @+lh:Nat -> @+hl:Nat -> @+e3:{Nat.add(m, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(32n, k)) == Nat.add(lh, hl) : Nat} -> @+e5:{m == Nat.add(mlo, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, mhi)) : Nat} -> {Nat.add(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, mlo), Nat.add(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(32n, mhi), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(48n, k))) == Nat.add(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, lh), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, hl)) : Nat}

2^16 Mlo + (2^32 Mhi + 2^48 K) == 2^16 LH + 2^16 HL, from M == Mlo + 2^16 Mhi and M + 2^32 K == LH + HL

def assemble source · line 166 · raw

@+al:Nat -> @+ah:Nat -> @+bl:Nat -> @+bh:Nat -> @+m:Nat -> @+k:Nat -> @+mlo:Nat -> @+mhi:Nat -> @+vl:Nat -> @+c2:Nat -> @+e3:{Nat.add(m, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(32n, k)) == Nat.add(Nat.mul(al, bh), Nat.mul(ah, bl)) : Nat} -> @+e5:{m == Nat.add(mlo, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, mhi)) : Nat} -> @+e8:{Nat.add(vl, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(32n, c2)) == Nat.add(Nat.mul(al, bl), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, mlo)) : Nat} -> {Nat.add(vl, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(32n, Nat.add(Nat.add(Nat.mul(ah, bh), Nat.add(mhi, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, k))), c2))) == Nat.mul(Nat.add(al, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, ah)), Nat.add(bl, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, bh))) : Nat}

the value equation of the product: low word, carries and high digits

def shift_sc source · line 195 · raw

@+k:Nat -> @+x:Nat -> {0xf86f5f1d9a594d5a5cff999100e01d03/spec/lib/common.shift(k, x) == 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(k, x) : Nat}

def mex source · line 202 · raw

@x:U32 -> @y:U32 -> Nat

def mul_cons source · line 208 · raw

@+x:U32 -> @+y:U32 -> {Nat.add(v(U32.mul(x, y)), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(32n, mex(x, y))) == Nat.mul(v(x), v(y)) : Nat}

a wrapping product and its lost high part

def b32_v source · line 218 · raw

@+c:Bool -> {v(0xf86f5f1d9a594d5a5cff999100e01d03/src/math/w64.b32(c)) == 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/lemmas/spec/numeric.bit_value(c) : Nat}

def bit_le1 source · line 225 · raw

@+c:Bool -> {Nat.is_le(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/lemmas/spec/numeric.bit_value(c), 1n) == True{} : Bool}

def one_lt_sc source · line 232 · raw

@+k:Nat -> @+one:Nat -> @+h1:{one == 1n : Nat} -> {Nat.is_lt(1n, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(1n+k, one)) == True{} : Bool}

def bit_lt16 source · line 236 · raw

@+one:Nat -> @+h1:{one == 1n : Nat} -> @+c:Bool -> {Nat.is_lt(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/lemmas/spec/numeric.bit_value(c), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, one)) == True{} : Bool}

def prod_lt source · line 239 · raw

@+one:Nat -> @+h1:{one == 1n : Nat} -> @+x:Nat -> @+y:Nat -> @+hx:{Nat.is_lt(x, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, one)) == True{} : Bool} -> @+hy:{Nat.is_lt(y, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, one)) == True{} : Bool} -> {Nat.is_lt(Nat.mul(x, y), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(32n, one)) == True{} : Bool}

def sc16_lt source · line 243 · raw

@+one:Nat -> @+x:Nat -> @+hx:{Nat.is_lt(x, 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, one)) == True{} : Bool} -> {Nat.is_lt(0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(16n, x), 0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.sc(32n, one)) == True{} : Bool}

2^16 x < 2^32 for x < 2^16

def fin_g source · line 248 · raw

@+ll:U32 -> @+mid:U32 -> @+hh:U32 -> @mc:Bool -> @+c:U32 -> 0xf86f5f1d9a594d5a5cff999100e01d03/src/math/u64.U64

def mid_g source · line 251 · raw

@+ll:U32 -> @+lh:U32 -> @+hl:U32 -> @+hh:U32 -> @+c:U32 -> 0xf86f5f1d9a594d5a5cff999100e01d03/src/math/u64.U64

def h_g source · line 254 · raw

@+al:U32 -> @+ah:U32 -> @+bl:U32 -> @+bh:U32 -> @+c:U32 -> 0xf86f5f1d9a594d5a5cff999100e01d03/src/math/u64.U64

def mul32g source · line 257 · raw

@+a:U32 -> @+b:U32 -> @+c:U32 -> @+m:U32 -> 0xf86f5f1d9a594d5a5cff999100e01d03/src/math/u64.U64

def fin_eq source · line 262 · raw

@+ll:U32 -> @+mid:U32 -> @+hh:U32 -> @+mc:Bool -> {0xf86f5f1d9a594d5a5cff999100e01d03/src/math/w64.mul32_fin(ll, mid, hh, mc) == fin_g(ll, mid, hh, mc, 65536) : 0xf86f5f1d9a594d5a5cff999100e01d03/src/math/u64.U64}

the implementation splits by U32.shrn(_, 16), a shift; the generalised product by U32.div(_, 65536): the same words (SR.shr16)

def h_eq source · line 266 · raw

@+al:U32 -> @+ah:U32 -> @+bl:U32 -> @+bh:U32 -> {0xf86f5f1d9a594d5a5cff999100e01d03/src/math/w64.mul32_h(al, ah, bl, bh) == h_g(al, ah, bl, bh, 65536) : 0xf86f5f1d9a594d5a5cff999100e01d03/src/math/u64.U64}

def impl source · line 269 · raw

@+a:U32 -> @+b:U32 -> {0xf86f5f1d9a594d5a5cff999100e01d03/src/math/w64.mul32(a, b) == mul32g(a, b, 65536, 65535) : 0xf86f5f1d9a594d5a5cff999100e01d03/src/math/u64.U64}

def mulval source · line 275 · raw

@+one:Nat -> @+h1:{one == 1n : Nat} -> @+a:U32 -> @+b:U32 -> @+c:U32 -> @+pc:{c == U32{0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.pw(32n, 16n)} : U32} -> @+m:U32 -> @+pm:{m == U32{0xf86f5f1d9a594d5a5cff999100e01d03/proofs/lib/word.mask(32n, 16n)} : U32} -> {0xf86f5f1d9a594d5a5cff999100e01d03/spec/math/w64.value(mul32g(a, b, c, m)) == Nat.mul(v(a), v(b)) : Nat}

the value of the generalised product, constants symbolic

def mul32_value source · line 348 · raw

@+a:U32 -> @+b:U32 -> 0xf86f5f1d9a594d5a5cff999100e01d03/spec/math/w64.Mul32.value(a, b)

Mul32.value: the full product of two U32