Ltac wlt_ind :=
  match goal with
  | [ |- forall (n: word ?len), ?P ] =>
    refine (well_founded_ind (@wlt_wf len) (fun n => P) _)
  end.

(* Specifications: *)
Theorem wordToNat_minus_one': forall sz n, n <> natToWord sz 0 -> S (wordToNat (n ^- natToWord sz 1)) = wordToNat n.
Theorem wordToNat_minus_one: forall sz n, n <> natToWord sz 0 -> wordToNat (n ^- natToWord sz 1) = wordToNat n - 1.
Lemma lt_minus : forall a b c, (b <= a -> b < c -> a < c -> a - b < c)%nat.
Lemma wminus_minus : forall sz (a b : word sz), b <= a -> wordToNat (a ^- b) = wordToNat a - wordToNat b.
Lemma wordToNat_neq_inj: forall sz (a b : word sz), a <> b <-> wordToNat a <> wordToNat b.
Lemma natToWord_discriminate: forall sz, (sz > 0)%nat -> natToWord sz 0 <> natToWord sz 1.
Theorem wlshift_0 : forall sz (w : word sz), @wlshift sz w 0 = w.
Theorem wrshift_0 : forall sz (w : word sz), @wrshift sz w 0 = w.
Theorem wlshift_gt : forall sz n (w : word sz), (n > sz)%nat -> wlshift w n = wzero sz.
Theorem wrshift_gt : forall sz n (w : word sz), (n > sz)%nat -> wrshift w n = wzero sz.
Theorem wlshift_bitwp : forall sz (w1 w2 : word sz) f n, wlshift (bitwp f w1 w2) n = split1 sz n ( eq_rec _ word (combine (wzero n) (bitwp f w1 w2)) _ (eq_sym (Nat.add_comm sz n))).
Theorem wrshift_bitwp : forall sz (w1 w2 : word sz) f n, wrshift (bitwp f w1 w2) n = split2 n sz ( eq_rect _ word (combine (bitwp f w1 w2) (wzero n)) _ (eq_sym (Nat.add_comm n sz))).
Theorem wnot_wlshift : forall sz (w : word sz) n, wnot (wlshift w n) = split1 sz n (eq_rect _ word (combine (wones n) (wnot w)) _ (eq_sym (Nat.add_comm sz n))).
Theorem wnot_wrshift : forall sz (w : word sz) n, wnot (wrshift w n) = split2 n sz (eq_rect _ word (combine (wnot w) (wones n)) _ (eq_sym (Nat.add_comm n sz))).
Lemma wlshift_alt: forall sz n (a: word sz), wlshift' a n = wlshift a n.
Theorem div2_pow2_twice: forall n, Nat.div2 (pow2 n + (pow2 n + 0)) = pow2 n.
Lemma wordToNat_wzero: forall sz, wordToNat (wzero sz) = 0.
Lemma wordToN_wzero: forall sz, wordToN (wzero sz) = 0%N.
Lemma combine_zero: forall n m, combine (natToWord n 0) (natToWord m 0) = natToWord _ 0.
Lemma combine_one: forall n m, combine (natToWord (S n) 1) (natToWord m 0) = natToWord _ 1.
Lemma wmsb_wzero': forall sz, wmsb (wzero' sz) false = false.
Lemma wmsb_wzero: forall sz, wmsb (wzero sz) false = false.
Lemma wmsb_wones: forall sz, wmsb (wones (S sz)) false = true.
Lemma wmsb_0_natToWord: forall sz n default, (2 * n < pow2 (S sz))%nat -> @wmsb (S sz) (natToWord (S sz) n) default = false.
Lemma wmsb_1_natToWord: forall sz n default, pow2 sz <= n < 2 * pow2 sz -> @wmsb (S sz) (natToWord (S sz) n) default = true.
Lemma wordToN_wzero': forall sz, wordToN (wzero' sz) = 0%N.
Lemma wordToZ_wzero': forall sz, wordToZ (wzero' sz) = 0%Z.
Lemma wordToZ_wzero: forall sz, wordToZ (wzero sz) = 0%Z.
Lemma wmsb_existT: (* Note: not axiom free *) forall sz1 (w1: word sz1) sz2 (w2: word sz2), existT word _ w1 = existT word _ w2 -> forall b, wmsb w1 b = wmsb w2 b.
Lemma destruct_word_S: forall sz (w: word (S sz)), exists v b, w = WS b v.
Lemma induct_word_S: forall (P : forall n : nat, word (S n) -> Prop), (forall b, P 0 (WS b WO)) -> (forall b b0 n (w : word n), P n (WS b0 w) -> P (S n) (WS b (WS b0 w))) -> forall (n : nat) (w : word (S n)), P n w.
Lemma wmsb_ws: forall sz (w: word (S sz)) b a, wmsb (WS b w) a = wmsb w a.
Lemma wmsb_extz: forall sz (w: word sz) n, wmsb (extz w n) false = wmsb w false.
Lemma wmsb_default: forall sz (w: word sz) b1 b2, sz <> 0 -> wmsb w b1 = wmsb w b2.
Lemma wmsb_nat_cast: forall sz1 (w: word sz1) sz2 (Hsz: sz1 = sz2) b, wmsb w b = wmsb (nat_cast word Hsz w) b.
Lemma wmsb_eq_rect: forall sz1 (w: word sz1) sz2 (Hsz: sz1 = sz2) b, wmsb w b = wmsb (eq_rect _ word w _ Hsz) b.
Lemma nat_cast_inj: forall sz sz' (p: sz = sz') (w1 w2: word sz), nat_cast word p w1 = nat_cast word p w2 -> w1 = w2.
Lemma wtl_nat_cast_WS: forall n m (q: n = m) (p: S n = S m) (w: word n) (b: bool), wtl (nat_cast word p (WS b w)) = nat_cast word q w.
Lemma wmsb_split2': forall sz (w: word (S sz)) b, wmsb w b = negb (weqb (split2 sz 1 (nat_cast _ (eq_sym (Nat.add_1_r sz)) w)) (natToWord _ 0)).
Lemma wmsb_split2: forall sz (w: word (sz + 1)) b, wmsb w b = if weq (split2 _ 1 w) (natToWord _ 0) then false else true.
Lemma wmsb_true_split2_wones: forall sz (w: word (sz + 1)) b, wmsb w b = true -> wones 1 = split2 sz 1 w.
Lemma wmsb_false_split2_wzero: forall sz (w: word (sz + 1)) b, wmsb w b = false -> wzero 1 = split2 sz 1 w.
Lemma wmsb_split1_sext: forall sz (w: word (sz + 1)), wmsb w false = wmsb (split1 _ 1 w) false -> exists sw, sext sw 1 = w.
Lemma wmsb_combine_WO: forall sz (w: word sz) b, wmsb (combine w WO) b = wmsb w b.
Lemma wmsb_combine: forall sz1 sz2 (w1: word sz1) (w2: word sz2) b1 b2, sz2 <> 0 -> wmsb (combine w1 w2) b1 = wmsb w2 b2.
Lemma wmsb_combine_existT: (* Note: not axiom free *) forall sz (w: word sz) sz1 (w1: word sz1) sz2 (w2: word sz2) b1 b2, sz2 <> 0 -> existT word _ w = existT word _ (combine w1 w2) -> wmsb w b1 = wmsb w2 b2.
Lemma wmsb_zext: forall sz (w: word sz) b n, n <> 0 -> wmsb (zext w n) b = false.
Lemma wordToN_zext: forall sz (w: word sz) n, wordToN (zext w n) = wordToN w.
Lemma wordToNat_zext: forall sz (w: word sz) n, wordToNat (zext w n) = wordToNat w.
Lemma zext_wordToNat_equal_Z: forall sz (w: word sz) n, n <> 0 -> wordToZ (zext w n) = Z.of_nat (wordToNat w).
Lemma wordToN_WS_0: forall sz (w: word sz), wordToN w~0 = (2 * wordToN w)%N.
Lemma wordToN_WS_1: forall sz (w: word sz), wordToN w~1 = (2 * wordToN w + 1)%N.
Lemma NToWord_WS_0: forall sz n, NToWord (S sz) (2 * n) = (NToWord sz n)~0.
Lemma NToWord_WS_1: forall sz n, NToWord (S sz) (2 * n + 1) = (NToWord sz n)~1.
Lemma wneg_WS_0: forall sz (w: word sz), wneg w~0 = (wneg w)~0.
Lemma NToWord_wordToN: forall sz (w: word sz), NToWord sz (wordToN w) = w.
Lemma roundTripN_0: forall sz, wordToN (NToWord sz 0) = 0%N.
Lemma wordToN_NToWord: forall sz n, exists k, wordToN (NToWord sz n) = (n - k * Npow2 sz)%N /\ (k * Npow2 sz <= n)%N.
Lemma wordToN_NToWord_2: forall sz n, (n < Npow2 sz)%N -> wordToN (NToWord sz n) = n.
Lemma wordToN_bound: forall sz (w: word sz), (wordToN w < Npow2 sz)%N.
Lemma wnot_def: forall sz (w: word sz), wnot w = NToWord sz (Npow2 sz - wordToN w - 1).
Lemma wneg_wnot: forall sz (w: word sz), wnot w = wneg w ^- (natToWord _ 1).
Lemma wzero_wneg: forall n, wneg (wzero n) = wzero n.
Lemma pow2_wneg: forall sz, wneg (natToWord (S sz) (pow2 sz)) = natToWord (S sz) (pow2 sz).
Lemma wneg_WS_1: forall sz (w: word sz), wneg w~1 = (wnot w)~1.
Lemma wordToZ_WS_0: forall sz (w: word sz), wordToZ w~0 = (2 * wordToZ w)%Z.
Lemma wordToZ_WS_1: forall sz (w: word (S sz)), wordToZ w~1 = (2 * wordToZ w + 1)%Z.
Lemma wordToZ_WS_1': forall sz (w: word (sz + 1)), wordToZ w~1 = (2 * wordToZ w + 1)%Z.
Lemma wordToZ_inj: forall sz (w1 w2: word sz), wordToZ w1 = wordToZ w2 -> w1 = w2.
Lemma wordToZ_wones: forall sz, sz <> 0 -> wordToZ (wones sz) = (-1)%Z.
Lemma wordToNat_eq_rect: forall sz (w: word sz) nsz Hsz, wordToNat (eq_rect _ word w nsz Hsz) = wordToNat w.
Lemma wordToNat_existT: forall sz1 (w1: word sz1) sz2 (w2: word sz2) (Hsz: sz1 = sz2), wordToNat w1 = wordToNat w2 -> existT word _ w1 = existT word _ w2.
Lemma existT_wordToNat: (* Note: not axiom free *) forall sz1 (w1: word sz1) sz2 (w2: word sz2), existT word _ w1 = existT word _ w2 -> wordToNat w1 = wordToNat w2.
Lemma wordToZ_eq_rect: forall sz (w: word sz) nsz Hsz, wordToZ (eq_rect _ word w nsz Hsz) = wordToZ w.
Lemma wordToZ_existT: forall sz1 (w1: word sz1) sz2 (w2: word sz2) (Hsz: sz1 = sz2), wordToZ w1 = wordToZ w2 -> existT word _ w1 = existT word _ w2.
Lemma existT_wordToZ: (* Note: not axiom free *) forall sz1 (w1: word sz1) sz2 (w2: word sz2), existT word _ w1 = existT word _ w2 -> wordToZ w1 = wordToZ w2.
Lemma wpow2_pow2: forall sz, wordToNat (wpow2 sz) = pow2 sz.
Lemma wpow2_Npow2: forall sz, wordToN (wpow2 sz) = Npow2 sz.
Lemma wpow2_wneg: forall sz, wneg (wpow2 sz) = wpow2 sz.
Lemma wpow2_wmsb: forall sz, wmsb (wpow2 sz) false = true.
Lemma wmsb_wnot: forall sz (w: word (S sz)) b1 b2, wmsb (wnot w) b1 = negb (wmsb w b2).
Lemma wmsb_wneg_true: forall sz (w: word (S sz)), w <> wpow2 sz -> forall b1 b2, wmsb w b1 = true -> wmsb (wneg w) b2 = false.
Lemma wmsb_wneg_false: forall sz (w: word (S sz)), wordToNat w <> 0 -> forall b1 b2, wmsb w b1 = false -> wmsb (wneg w) b2 = true.
Lemma zext_WO_wzero: forall n, zext WO n = wzero n.
Lemma wmsb_wneg_zext: (* Note: not axiom free *) forall sz (w: word sz) b n, n <> 0 -> wordToNat w <> 0 -> wmsb (wneg (zext w n)) b = true.
Lemma wminus_WS_pos: forall sz (w1 w2: word (S sz)), wordToZ (WS true w1 ^- WS false w2) = (2 * wordToZ (w1 ^- w2) + 1)%Z.
Lemma wminus_WS_pos': forall sz (w1 w2: word (sz + 1)), wordToZ (WS true w1 ^- WS false w2) = (2 * wordToZ (w1 ^- w2) + 1)%Z.
Lemma wtl_combine: forall (x: word 1) sz (y: word sz), wtl (combine x y) = y.
Lemma extz_combine: forall sz (w: word sz) n, extz w n = combine (natToWord n 0) w.
Lemma combine_assoc_existT: forall sz1 (w1: word sz1) sz2 (w2: word sz2) sz3 (w3: word sz3), existT word (sz1 + (sz2 + sz3)) (combine w1 (combine w2 w3)) = existT word (sz1 + sz2 + sz3) (combine (combine w1 w2) w3).
Lemma sext_combine: (* Note: not axiom free *) forall sz n (w: word (sz + n)) sz1 (w1: word sz1) sz2 (Hsz2: sz2 <> 0) (w2: word sz2), existT word _ w = existT word _ (combine w1 (sext w2 n)) -> exists sw, w = sext sw n /\ existT word _ sw = existT word _ (combine w1 w2).
Lemma existT_wminus: forall sz (w1 w2: word sz) sz' (w3 w4: word sz'), existT word _ w1 = existT word _ w3 -> existT word _ w2 = existT word _ w4 -> existT word _ (w1 ^- w2) = existT word _ (w3 ^- w4).
Lemma existT_sext: forall sz1 (w1: word sz1) sz2 (w2: word sz2) n, existT word _ w1 = existT word _ w2 -> existT word _ (sext w1 n) = existT word _ (sext w2 n).
Lemma existT_extz: forall sz1 (w1: word sz1) sz2 (w2: word sz2) n, existT word _ w1 = existT word _ w2 -> existT word _ (extz w1 n) = existT word _ (extz w2 n).
Lemma existT_wrshifta: forall sz1 (w1: word sz1) sz2 (w2: word sz2) n, existT word _ w1 = existT word _ w2 -> existT word _ (wrshifta w1 n) = existT word _ (wrshifta w2 n).
Lemma existT_wlshift: forall sz1 (w1: word sz1) sz2 (w2: word sz2) n, existT word _ w1 = existT word _ w2 -> existT word _ (wlshift w1 n) = existT word _ (wlshift w2 n).
Lemma eq_rect_2: forall sz (pa: word sz) sz' Heq1 Heq2, eq_rect sz' word (eq_rect sz word pa sz' Heq1) sz Heq2 = pa.
Lemma wzero_eq_rect: forall sz1 sz2 Heq, eq_rect sz1 word (wzero sz1) sz2 Heq = wzero sz2.
Lemma wrshifta_0: forall sz (w: word sz), wrshifta w 0 = w.
Lemma wrshifta_WO: forall n, wrshifta WO n = WO.
Lemma split2_WO: forall n w, split2 n 0 w = WO.
Lemma sext_wzero: forall sz n, sext (wzero sz) n = wzero (sz + n).
Lemma wrshifta_wzero: forall sz n, wrshifta (wzero sz) n = wzero _.
Lemma extz_sext: forall sz (w: word sz) n1 n2, existT word _ (extz (sext w n1) n2) = existT word _ (sext (extz w n2) n1).
Lemma sext_WS: forall sz (w: word (S sz)) b n, sext (WS b w) n = WS b (sext w n).
Lemma sext_wordToZ: forall sz n (w: word sz), wordToZ (sext w n) = wordToZ w.
Lemma sext_natToWord': forall sz1 sz2 n, (2 * n < pow2 sz1)%nat -> sext (natToWord sz1 n) sz2 = natToWord (sz1 + sz2) n.
Lemma sext_natToWord: forall sz2 sz1 sz n (e: sz1 + sz2 = sz), (2 * n < pow2 sz1)%nat -> eq_rect (sz1 + sz2) word (sext (natToWord sz1 n) sz2) sz e = natToWord sz n.
Lemma sext_wneg_natToWord'': forall sz1 sz2 n, pow2 sz1 <= 2 * n < pow2 (S sz1) -> sext (natToWord sz1 n) sz2 = natToWord (sz1 + sz2) (pow2 (sz1+sz2) - (pow2 sz1 - n)).
Lemma sext_wneg_natToWord': forall sz1 sz2 n, (2 * n < pow2 sz1)%nat -> sext (wneg (natToWord sz1 n)) sz2 = wneg (natToWord (sz1 + sz2) n).
Lemma sext_wneg_natToWord: forall sz2 sz1 sz n (e: sz1 + sz2 = sz), (2 * n < pow2 sz1)%nat -> eq_rect (sz1 + sz2) word (sext (wneg (natToWord sz1 n)) sz2) sz e = wneg (natToWord sz n).
Lemma wordToNat_split1: forall sz1 sz2 (w: word (sz1 + sz2)), wordToNat (split1 _ _ w) = Nat.modulo (wordToNat w) (pow2 sz1).
Lemma wordToNat_split2: forall sz1 sz2 (w: word (sz1 + sz2)), wordToNat (split2 _ _ w) = Nat.div (wordToNat w) (pow2 sz1).
Lemma wordToNat_wrshifta: forall sz (w: word sz) n, wordToNat (wrshifta w n) = Nat.div (wordToNat (sext w n)) (pow2 n).
Lemma wordToNat_combine: forall sz1 (w1: word sz1) sz2 (w2: word sz2), wordToNat (combine w1 w2) = wordToNat w1 + pow2 sz1 * wordToNat w2.
Lemma wordToNat_wlshift: forall sz (w: word sz) n, wordToNat (wlshift w n) = Nat.mul (Nat.modulo (wordToNat w) (pow2 (sz - n))) (pow2 n).
Lemma wordToNat_extz: forall sz (w: word sz) n, wordToNat (extz w n) = pow2 n * wordToNat w.
Lemma extz_is_mult_pow2: forall sz n d, extz (natToWord sz n) d = natToWord (d + sz) (pow2 d * n).
Lemma extz_is_mult_pow2_neg: forall sz n d, extz (wneg (natToWord sz n)) d = wneg (natToWord (d + sz) (pow2 d * n)).
Lemma wordToNat_sext_bypass: forall sz1 (w1: word sz1) sz2 (w2: word sz2) (Hsz: sz1 = sz2) n, wordToNat w1 = wordToNat w2 -> wordToNat (sext w1 n) = wordToNat (sext w2 n).
Lemma combine_sext: forall sz1 (w1: word sz1) sz2 (w2: word (S sz2)) n, existT word _ (combine w1 (sext w2 n)) = existT word _ (sext (combine w1 w2) n).
Lemma extz_extz: forall sz (w: word sz) n1 n2, existT word _ (extz (extz w n1) n2) = existT word _ (extz w (n2 + n1)).
Lemma wrshifta_extz_sext: (* Note: not axiom free *) forall sz (w: word sz) n1 n2, existT word _ (wrshifta (extz w (n1 + n2)) n1) = existT word _ (sext (extz w n2) n1).
Lemma wordToNat_sext_modulo: forall sz (w: word sz) n, Nat.modulo (wordToNat (sext w n)) (pow2 sz) = wordToNat w.
Lemma wlshift_sext_extz: forall sz (w: word sz) n, existT word _ (wlshift (sext w n) n) = existT word _ (extz w n).
Lemma wlshift_combine_extz: forall sn sl (wl: word sl) ssu (wu: word (ssu + sn)), existT word (sl + (ssu + sn)) (wlshift (combine wl wu) sn) = existT word (sn + (sl + ssu)) (extz (combine wl (split1 ssu _ wu)) sn).
Lemma extz_sext_eq_rect: forall sz (w: word sz) n1 n2 nsz Hnsz1, exists Hnsz2, eq_rect (n2 + (sz + n1)) word (extz (sext w n1) n2) nsz Hnsz1 = eq_rect (n2 + sz + n1) word (sext (extz w n2) n1) nsz Hnsz2.
Lemma sext_zero: forall n m, sext (natToWord n 0) m = natToWord _ 0.
Lemma sext_split1: forall sz (w: word sz) n, split1 sz _ (sext w n) = w.
Lemma sext_sext: forall sz (w: word sz) n1 n2, existT word _ (sext w (n1 + n2)) = existT word _ (sext (sext w n1) n2).
Lemma wneg_wordToN: forall sz (w: word sz), wordToN w <> 0%N -> wordToN (wneg w) = (Npow2 sz - wordToN w)%N.
Lemma Nmul_two: forall n, (n + n = 2 * n)%N.
Lemma wmsb_false_bound: forall sz (w: word (S sz)), wmsb w false = false -> (wordToN w < Npow2 sz)%N.
Lemma wmsb_true_bound: forall sz (w: word (S sz)), wmsb w false = true -> (Npow2 sz <= wordToN w)%N.
Lemma ZToWord_wordToZ: forall sz (w: word sz), ZToWord sz (wordToZ w) = w.
Lemma wordToZ_ZToWord: forall z sz, (- Z.of_nat (pow2 sz) <= z < Z.of_nat (pow2 sz))%Z -> wordToZ (ZToWord (S sz) z) = z.
Lemma wordToZ_ZToWord'': forall (sz: nat), (0 < sz)%nat -> forall n: Z, (- 2 ^ (Z.of_nat sz - 1) <= n < 2 ^ (Z.of_nat sz - 1))%Z -> wordToZ (ZToWord sz n) = n.
Lemma wordToZ_wordToN: forall sz (w: word sz), wordToZ w = (Z.of_N (wordToN w) - Z.of_N (if wmsb w false then Npow2 sz else 0))%Z.
Lemma ZToWord_Z_of_N: forall sz n, ZToWord sz (Z.of_N n) = NToWord sz n.
Lemma ZToWord_Z_of_nat: forall sz x, ZToWord sz (Z.of_nat x) = natToWord sz x.
Lemma natToWord_Z_to_nat: forall sz n, (0 <= n)%Z -> natToWord sz (Z.to_nat n) = ZToWord sz n.
Lemma ZToWord_0: forall sz, ZToWord sz 0 = wzero sz.
Lemma ZToWord_1{sz : nat}: ZToWord sz 1 = wone sz.
Lemma natToWord_pow2_add: forall sz n, natToWord sz (n + pow2 sz) = natToWord sz n.
Lemma ZToWord_Npow2_sub: forall sz z, ZToWord sz (z - Z.of_N (Npow2 sz)) = ZToWord sz z.
Lemma ZToWord_Npow2_sub_k : forall (sz : nat) (z : Z) (k: nat), ZToWord sz (z - Z.of_nat k * Z.of_N (Npow2 sz)) = ZToWord sz z.
Lemma ZToWord_Npow2_add_k : forall (sz : nat) (z : Z) (k: nat), ZToWord sz (z + Z.of_nat k * Z.of_N (Npow2 sz)) = ZToWord sz z.
Lemma ZToWord_Npow2_sub_z : forall (sz : nat) (z : Z) (k: Z), ZToWord sz (z - k * Z.of_N (Npow2 sz)) = ZToWord sz z.
Lemma ZToWord_Npow2_add_k': forall sz z k, ZToWord sz (z + k * Z.of_N (Npow2 sz)) = ZToWord sz z.
Lemma wordToZ_ZToWord': forall sz w, exists k, wordToZ (ZToWord sz w) = (w - k * Z.of_N (Npow2 sz))%Z.
Lemma else_0_to_ex_N: forall (b: bool) (a: N), exists k, (if b then a else 0%N) = (k * a)%N.
Local Lemma wmultZ_helper: forall a b k1 k2 p, ((a - k1 * p) * (b - k2 * p) = a * b - (k1 * b + k2 * a - k1 * k2 * p) * p)%Z.
Lemma wordToZ_size': forall sz (w: word (S sz)), (- Z.of_nat (pow2 sz) <= wordToZ w < Z.of_nat (pow2 sz))%Z.
Lemma wordToZ_size: forall sz (w: word (S sz)), (Z.abs (wordToZ w) <= Z.of_nat (pow2 sz))%Z.
Lemma wordToZ_size'': forall (sz : nat), (0 < sz)%nat -> forall w : word sz, (- 2 ^ (Z.of_nat sz - 1) <= wordToZ w < 2 ^ (Z.of_nat sz - 1))%Z.
Lemma wneg_wzero: forall sz (w: word sz), wneg w = wzero sz -> w = wzero sz.
Lemma wmsb_false_pos: forall sz (w: word sz), wmsb w false = false <-> (wordToZ w >= 0)%Z.
Lemma wmsb_true_neg: forall sz (w: word sz), wmsb w false = true <-> (wordToZ w < 0)%Z.
Lemma split1_existT: (* Note: not axiom free *) forall n sz1 (w1: word (n + sz1)) sz2 (w2: word (n + sz2)), existT word _ w1 = existT word _ w2 -> split1 n _ w1 = split1 n _ w2.
Lemma word_combinable: forall sz1 sz2 (w: word (sz1 + sz2)), exists w1 w2, w = combine w1 w2.
Lemma split1_combine_existT: (* Note: not axiom free *) forall sz n (w: word (n + sz)) sl (wl: word (n + sl)) su (wu: word su), existT word _ w = existT word _ (combine wl wu) -> split1 n _ w = split1 n _ wl.
Lemma extz_pow2_wordToZ: forall sz (w: word sz) n, wordToZ (extz w n) = (wordToZ w * Z.of_nat (pow2 n))%Z.
Lemma extz_wneg: forall sz (w: word sz) n, extz (wneg w) n = wneg (extz w n).
Lemma wneg_wordToZ: forall sz (w: word (S sz)), w <> wpow2 sz -> wordToZ (wneg w) = (- wordToZ w)%Z.
Lemma wneg_wordToZ': forall sz (w: word (S sz)) z, w <> wpow2 sz -> (z + wordToZ (wneg w))%Z = (z - wordToZ w)%Z.
Lemma wminus_wneg: forall sz (w1 w2: word sz), wneg (w1 ^- w2) = w2 ^- w1.
Lemma wminus_wordToZ: forall sz (w1 w2: word (S sz)), w2 ^- w1 <> wpow2 sz -> wordToZ (w1 ^- w2) = (- wordToZ (w2 ^- w1))%Z.
Lemma wminus_wordToZ': forall sz (w1 w2: word (sz + 1)), existT word _ (w2 ^- w1) <> existT word _ (wpow2 sz) -> wordToZ (w1 ^- w2) = (- wordToZ (w2 ^- w1))%Z.
Lemma wminus_wminusZ: forall (sz : nat) (w1 w2 : word sz), w1 ^- w2 = wminusZ w1 w2.
Local Lemma wminusZ_helper: forall a b k1 k2 p, ((a - k1 * p) - (b - k2 * p) = a - b - (k1 - k2) * p)%Z.
Lemma ZToWord_minus: forall sz a b, ZToWord sz (a - b) = ZToWord sz a ^- ZToWord sz b.
Lemma wminus_Z: forall sz (a b : word sz), a ^- b = ZToWord sz (wordToZ a - wordToZ b).
Lemma Zeqb_true_ZToWord: forall {sz: nat} (x y: Z), (x =? y)%Z = true -> ZToWord sz x = ZToWord sz y.
Lemma word_ring_theory_Z: forall (sz: nat), ring_theory (ZToWord sz 0) (ZToWord sz 1) (@wplus sz) (@wmult sz) (@wminus sz) (@wneg sz) eq.
Lemma word_ring_morph_Z: forall (sz: nat), ring_morph (ZToWord sz 0) (ZToWord sz 1) (@wplus sz) (@wmult sz) (@wminus sz) (@wneg sz) eq 0%Z 1%Z Z.add Z.mul Z.sub Z.opp Z.eqb (ZToWord sz).
Lemma extz_zero: forall sz n, extz (natToWord sz 0) n = wzero _.
Lemma sext_eq_rect: forall sz (w: word sz) n nsz Hsz1, exists Hsz2, eq_rect (sz + n) word (sext w n) (nsz + n) Hsz1 = sext (eq_rect sz word w nsz Hsz2) n.
Lemma wmsb_sext: forall sz (w: word sz) n, wmsb (sext w n) false = wmsb w false.
Lemma wmsb_wlshift_sext: (* Note: not axiom free *) forall sz (w: word sz) n, wmsb (sext w n) false = wmsb (wlshift (sext w n) n) false.
Lemma wordToZ_wordToNat_pos: forall sz (w: word sz), wmsb w false = false -> Z.of_nat (wordToNat w) = wordToZ w.