1 import Base 2 import ../../../spec/lib/common.bend as C 3 import ../../../spec/math/f64.bend as SF 4 import ../../../spec/math/w64.bend as SW 5 import ../../../src/math/f64.bend as F 6 import ../../../src/math/w64.bend as X 7 import ../../../src/math/u64.bend as WU 8 import ../../../src/math/natural.bend as M 9 import ../../lib/nat.bend as N 10 import ../../lib/logic.bend as L 11 import ../../lib/lemmas/proofs/nat_algebra.bend as NA 12 import ./w64sh.bend as SH 13 import ./f64round.bend as FR 14 import ./f64rtools.bend as RT 15 import ./f64bl.bend as BL 16 import ./f64norm.bend as NM 17 import ./f64nrp.bend as NP 18 import ./f64addc.bend as AC 19 20 # subMagsF64 with equal exponents: the exact difference d (0 < d < 2^52) at 21 # the exponent field e1 + 1 is normalized without rounding. 22 23 def lt_add_sub(+a: Nat, +b: Nat, +c: Nat, +h: {Nat.is_lt(a, Nat.sub(c, b)) == True{} : Bool}, +hb: {Nat.is_le(b, c) == True{} : Bool}) -> {Nat.is_le(1n+Nat.add(a, b), c) == True{} : Bool}: 24 +h1 = N.lt_succ_le_succ(a, Nat.sub(c, b), h) 25 +h2 = Equal.trans(Bool, Nat.is_le(Nat.add(1n+a, b), Nat.add(Nat.sub(c, b), b)), Nat.is_le(1n+a, Nat.sub(c, b)), True{}, FR.le_cancel_r(1n+a, Nat.sub(c, b), b), h1) 26 +ec = Equal.trans(Nat, Nat.add(Nat.sub(c, b), b), Nat.add(b, Nat.sub(c, b)), c, NA.add_comm(Nat.sub(c, b), b), N.sub_add(c, b, hb)) 27 L.subst(Nat, z => {Nat.is_le(Nat.add(1n+a, b), z) == True{} : Bool}, Nat.add(Nat.sub(c, b), b), c, ec, h2) 28 29 def smx_c(+one: Nat, +h1: {one == 1n : Nat}, +s: Bool, +e1: Nat, +d: WU.U64, +D: Nat, +hd: {SW.value(d) == D : Nat}, +hD: {C.fits(52n, D) == True{} : Bool}, +hz: {Nat.is_eq(D, 0n) == False{} : Bool}, +hov: {Nat.is_lt(Nat.add(e1, 1n), 2047n) == True{} : Bool}, +u: Bool, +hu: {Nat.is_lt(e1, Nat.sub(X.clz(d), 11n)) == u : Bool}) -> {F.sm_exact3(s, e1, d, Nat.sub(X.clz(d), 11n), u) == SF.round(s, D, Nat.add(1926n, e1)) : F.F64}: 30 match u: 31 case True{}: 32 +hb = BL.bl_le(52n, D, hD, Nat.is_le(M.bit_length(D), 52n), {==}) 33 +eb = NM.clz_t(d, D, hd, hb) 34 +hlt = L.subst(Nat, z => {Nat.is_lt(e1, z) == True{} : Bool}, Nat.sub(X.clz(d), 11n), Nat.sub(53n, M.bit_length(D)), eb, hu) 35 +h53 = N.le_trans(M.bit_length(D), 52n, 53n, hb, {==}) 36 +hl = lt_add_sub(e1, M.bit_length(D), 53n, hlt, h53) 37 +fK = SH.fits_mono(Nat.add(e1, M.bit_length(D)), 52n, C.shift(e1, D), hl, Equal.trans(Bool, C.fits(Nat.add(e1, M.bit_length(D)), C.shift(e1, D)), C.fits(M.bit_length(D), D), True{}, RT.fits_sh(e1, M.bit_length(D), D), RT.bl_fit(D))) 38 +hj = N.le_trans(Nat.add(e1, M.bit_length(D)), 52n, 64n, hl, {==}) 39 +hk = N.le_lt_trans(e1, Nat.add(e1, M.bit_length(D)), 64n, N.le_add_right(e1, M.bit_length(D)), N.le_lt_trans(Nat.add(e1, M.bit_length(D)), 52n, 64n, hl, {==})) 40 +ha = L.subst(Nat, z => {C.fits(M.bit_length(D), z) == True{} : Bool}, D, SW.value(d), Equal.sym(Nat, SW.value(d), D, hd), RT.bl_fit(D)) 41 +ev = Equal.trans(Nat, SW.value(X.shl(d, e1)), C.shift(e1, SW.value(d)), C.shift(e1, D), AC.shl_v(d, e1, M.bit_length(D), hk, hj, ha), Equal.cong(Nat, Nat, z => C.shift(e1, z), SW.value(d), D, hd)) 42 +f53 = SH.fits_mono(52n, 53n, C.shift(e1, D), {==}, fK) 43 +f63 = L.subst(Nat, z => {C.fits(63n, z) == True{} : Bool}, C.shift(e1, D), Nat.add(C.shift(e1, D), C.shift(52n, 0n)), Equal.sym(Nat, Nat.add(C.shift(e1, D), C.shift(52n, 0n)), C.shift(e1, D), N.add_zero(C.shift(e1, D))), SH.fits_mono(52n, 63n, C.shift(e1, D), {==}, fK)) 44 +hn = L.subst(Nat, z => {C.fits(63n, Nat.add(z, C.shift(52n, 0n))) == True{} : Bool}, C.shift(e1, D), SW.value(X.shl(d, e1)), Equal.sym(Nat, SW.value(X.shl(d, e1)), C.shift(e1, D), ev), f63) 45 +i1 = FR.pack_v(s, 0n, {==}, X.shl(d, e1), hn) 46 +i2 = Equal.cong(Nat, F.F64, z => FR.bits(s, Nat.add(z, C.shift(52n, 0n))), SW.value(X.shl(d, e1)), C.shift(e1, D), ev) 47 +r1 = AC.r1926(one, h1, s, C.shift(e1, D), f53, 1926n, {==}, Nat.is_eq(C.shift(e1, D), 0n), {==}) 48 +r0 = RT.round_shift(s, e1, D, 1926n) 49 Equal.trans(F.F64, F.pack(s, 0n, X.shl(d, e1)), FR.bits(s, Nat.add(SW.value(X.shl(d, e1)), C.shift(52n, 0n))), SF.round(s, D, Nat.add(1926n, e1)), i1, Equal.trans(F.F64, FR.bits(s, Nat.add(SW.value(X.shl(d, e1)), C.shift(52n, 0n))), FR.bits(s, Nat.add(C.shift(e1, D), C.shift(52n, 0n))), SF.round(s, D, Nat.add(1926n, e1)), i2, Equal.trans(F.F64, FR.bits(s, Nat.add(C.shift(e1, D), C.shift(52n, 0n))), SF.round(s, C.shift(e1, D), 1926n), SF.round(s, D, Nat.add(1926n, e1)), Equal.sym(F.F64, SF.round(s, C.shift(e1, D), 1926n), FR.bits(s, Nat.add(C.shift(e1, D), C.shift(52n, 0n))), r1), r0))) 50 case False{}: 51 +hle = N.not_lt_le(e1, Nat.sub(X.clz(d), 11n), hu) 52 +eEs = Equal.trans(Nat, Nat.add(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), Nat.sub(X.clz(d), 11n)), Nat.add(Nat.sub(X.clz(d), 11n), Nat.sub(e1, Nat.sub(X.clz(d), 11n))), e1, NA.add_comm(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), Nat.sub(X.clz(d), 11n)), N.sub_add(e1, Nat.sub(X.clz(d), 11n), hle)) 53 +hEe = L.subst(Nat, z => {Nat.is_le(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), z) == True{} : Bool}, Nat.add(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), Nat.sub(X.clz(d), 11n)), e1, eEs, N.le_add_right(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), Nat.sub(X.clz(d), 11n))) 54 +hovE = N.le_lt_trans(Nat.add(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), 1n), Nat.add(e1, 1n), 2047n, Equal.trans(Bool, Nat.is_le(Nat.add(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), 1n), Nat.add(e1, 1n)), Nat.is_le(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), e1), True{}, FR.le_cancel_r(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), e1, 1n), hEe), hov) 55 +fM = NM.sub_fit(d, D, hd, hD, hz) 56 +nM = NM.sub_nfit(d, D, hd, hD, hz) 57 +ev = NM.sub_val(d, D, hd, hD, hz) 58 +hq = N.lt_le(C.shift(Nat.sub(X.clz(d), 11n), D), C.shift(53n, one), Equal.trans(Bool, Nat.is_lt(C.shift(Nat.sub(X.clz(d), 11n), D), C.shift(53n, one)), C.fits(53n, C.shift(Nat.sub(X.clz(d), 11n), D)), True{}, FR.lt_fit(53n, one, h1, C.shift(Nat.sub(X.clz(d), 11n), D)), fM)) 59 +hovq = L.subst(Bool, t => {Nat.is_lt(Nat.add(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), SF.pick(Nat, t, 1n, 2n)), 2047n) == True{} : Bool}, True{}, C.fits(53n, C.shift(Nat.sub(X.clz(d), 11n), D)), Equal.sym(Bool, C.fits(53n, C.shift(Nat.sub(X.clz(d), 11n), D)), True{}, fM), hovE) 60 +q63 = FR.qfit(one, h1, C.shift(Nat.sub(X.clz(d), 11n), D), Nat.sub(e1, Nat.sub(X.clz(d), 11n)), hq, nM, hovq) 61 +hn = L.subst(Nat, z => {C.fits(63n, Nat.add(z, C.shift(52n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))))) == True{} : Bool}, C.shift(Nat.sub(X.clz(d), 11n), D), SW.value(X.shl(d, Nat.sub(X.clz(d), 11n))), Equal.sym(Nat, SW.value(X.shl(d, Nat.sub(X.clz(d), 11n))), C.shift(Nat.sub(X.clz(d), 11n), D), ev), q63) 62 +i1 = FR.pack_v(s, Nat.sub(e1, Nat.sub(X.clz(d), 11n)), FR.ef11(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), 1n, hovE), X.shl(d, Nat.sub(X.clz(d), 11n)), hn) 63 +i2 = Equal.cong(Nat, F.F64, z => FR.bits(s, Nat.add(z, C.shift(52n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))))), SW.value(X.shl(d, Nat.sub(X.clz(d), 11n))), C.shift(Nat.sub(X.clz(d), 11n), D), ev) 64 +XQ = Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))) 65 +ek = Equal.trans(Nat, Nat.sub(Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), 1926n), Nat.sub(Nat.add(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), 1926n), 1926n), Nat.sub(e1, Nat.sub(X.clz(d), 11n)), Equal.cong(Nat, Nat, z => Nat.sub(z, 1926n), Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), Nat.add(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), 1926n), NA.add_comm(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n)))), FR.sub_add_l(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), 1926n)) 66 +hovx = L.subst(Nat, z => {Nat.is_lt(Nat.add(z, 1n), 2047n) == True{} : Bool}, Nat.sub(e1, Nat.sub(X.clz(d), 11n)), Nat.sub(Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), 1926n), Equal.sym(Nat, Nat.sub(Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), 1926n), Nat.sub(e1, Nat.sub(X.clz(d), 11n)), ek), hovE) 67 +r1 = NP.rq(one, h1, s, C.shift(Nat.sub(X.clz(d), 11n), D), Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), fM, nM, N.le_add_right(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), hovx) 68 +r2 = Equal.cong(Nat, F.F64, z => FR.bits(s, Nat.add(C.shift(Nat.sub(X.clz(d), 11n), D), C.shift(52n, z))), Nat.sub(Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), 1926n), Nat.sub(e1, Nat.sub(X.clz(d), 11n)), ek) 69 +r0 = RT.round_shift(s, Nat.sub(X.clz(d), 11n), D, Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n)))) 70 +ex = Equal.trans(Nat, Nat.add(Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), Nat.sub(X.clz(d), 11n)), Nat.add(1926n, Nat.add(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), Nat.sub(X.clz(d), 11n))), Nat.add(1926n, e1), NA.add_assoc(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n)), Nat.sub(X.clz(d), 11n)), Equal.cong(Nat, Nat, z => Nat.add(1926n, z), Nat.add(Nat.sub(e1, Nat.sub(X.clz(d), 11n)), Nat.sub(X.clz(d), 11n)), e1, eEs)) 71 +r3 = Equal.cong(Nat, F.F64, z => SF.round(s, D, z), Nat.add(Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), Nat.sub(X.clz(d), 11n)), Nat.add(1926n, e1), ex) 72 +lhs = Equal.trans(F.F64, F.pack(s, Nat.sub(e1, Nat.sub(X.clz(d), 11n)), X.shl(d, Nat.sub(X.clz(d), 11n))), FR.bits(s, Nat.add(SW.value(X.shl(d, Nat.sub(X.clz(d), 11n))), C.shift(52n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))))), FR.bits(s, Nat.add(C.shift(Nat.sub(X.clz(d), 11n), D), C.shift(52n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))))), i1, i2) 73 +rhs = Equal.trans(F.F64, SF.round(s, C.shift(Nat.sub(X.clz(d), 11n), D), Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n)))), FR.bits(s, Nat.add(C.shift(Nat.sub(X.clz(d), 11n), D), C.shift(52n, Nat.sub(Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), 1926n)))), FR.bits(s, Nat.add(C.shift(Nat.sub(X.clz(d), 11n), D), C.shift(52n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))))), r1, r2) 74 +sp = Equal.trans(F.F64, SF.round(s, C.shift(Nat.sub(X.clz(d), 11n), D), Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n)))), SF.round(s, D, Nat.add(Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))), Nat.sub(X.clz(d), 11n))), SF.round(s, D, Nat.add(1926n, e1)), r0, r3) 75 Equal.trans(F.F64, F.pack(s, Nat.sub(e1, Nat.sub(X.clz(d), 11n)), X.shl(d, Nat.sub(X.clz(d), 11n))), FR.bits(s, Nat.add(C.shift(Nat.sub(X.clz(d), 11n), D), C.shift(52n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))))), SF.round(s, D, Nat.add(1926n, e1)), lhs, Equal.trans(F.F64, FR.bits(s, Nat.add(C.shift(Nat.sub(X.clz(d), 11n), D), C.shift(52n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))))), SF.round(s, C.shift(Nat.sub(X.clz(d), 11n), D), Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n)))), SF.round(s, D, Nat.add(1926n, e1)), Equal.sym(F.F64, SF.round(s, C.shift(Nat.sub(X.clz(d), 11n), D), Nat.add(1926n, Nat.sub(e1, Nat.sub(X.clz(d), 11n)))), FR.bits(s, Nat.add(C.shift(Nat.sub(X.clz(d), 11n), D), C.shift(52n, Nat.sub(e1, Nat.sub(X.clz(d), 11n))))), rhs), sp)) 76 77 # SoftFloat's exact equal-exponent difference is the rounded difference 78 def smx(+one: Nat, +h1: {one == 1n : Nat}, +s: Bool, +e1: Nat, +d: WU.U64, +D: Nat, +hd: {SW.value(d) == D : Nat}, +hD: {C.fits(52n, D) == True{} : Bool}, +hz: {Nat.is_eq(D, 0n) == False{} : Bool}, +hov: {Nat.is_lt(Nat.add(e1, 1n), 2047n) == True{} : Bool}) -> {F.sm_exact(s, e1, d) == SF.round(s, D, Nat.add(1926n, e1)) : F.F64}: 79 smx_c(one, h1, s, e1, d, D, hd, hD, hz, hov, Nat.is_lt(e1, Nat.sub(X.clz(d), 11n)), {==})