Fixpoint countLeadingZerosWord ni no: word ni -> word no :=
match ni return word ni -> word no with
| 0 => fun _ => $ 0
| S m => fun e =>
if (weq (split2 m 1 (nat_cast (fun n => word n) (eq_sym (Nat.add_1_r m)) e)) WO~0)
then $ 1 ^+ @countLeadingZerosWord m no (split1 m 1 (nat_cast (fun n => word n) (eq_sym (Nat.add_1_r m)) e))
else $ 0
end.

(* Specifications: *)
Lemma countLeadingZerosWord_le_len no ni:
ni < pow2 no ->
forall w: word ni, (countLeadingZerosWord no w <= natToWord _ ni)%word.
Lemma countLeadingZerosWord_le_len_nat no ni:
ni < pow2 no ->
forall w: word ni, #(countLeadingZerosWord no w) <= ni.
Lemma wordToNat_zero sz: forall (w: word sz), #w = 0 -> w = natToWord _ 0.
Lemma wordToNat_notZero sz: forall (w: word sz), #w <> 0 -> w <> natToWord _ 0.
Lemma natToWord_nzero sz x:
0 < x ->
x < pow2 sz ->
natToWord sz x <> natToWord sz 0.
Lemma pow2_lt_pow2_S:
forall n, pow2 n < pow2 (n+1).
Lemma combine_shiftl_plus_n n x:
x < pow2 n ->
(combine (natToWord n x) WO~1) = (natToWord (n + 1) (pow2 n)) ^+ natToWord (n + 1) x.
Lemma combine_natToWord_wzero n:
forall x,
x < pow2 n ->
combine (natToWord n x) (natToWord 1 0) = natToWord (n+1) x.
Lemma word_cancel_l sz (a b c: word sz):
a = b -> c ^+ a = c ^+ b.
Lemma word_cancel_r sz (a b c: word sz):
a = b -> a ^+ c = b ^+ c.
Lemma word_cancel_m sz (a b c a' b': word sz):
a ^+ a' = b ^+ b'-> a ^+ c ^+ a' = b ^+ c ^+ b'.
Lemma move_wplus_wminus sz (a b c: word sz):
a ^+ b = c <-> a = c ^- b.
Lemma move_wplus_pow2 sz (w1 w2: word (S sz)):
w1 = w2 ^+ $(pow2 sz) <->
w1 ^+ $(pow2 sz) = w2.
Lemma move_wminus_pow2 sz (w1 w2: word (S sz)):
w1 = w2 ^- $(pow2 sz) <->
w1 ^- $(pow2 sz) = w2.
Lemma pow2_wzero sz :
$(pow2 sz) = wzero sz.
Lemma pow2_wplus_wzero sz:
$(pow2 sz) ^+ $(pow2 sz) = wzero (sz + 1).
Lemma wplus_wplus_pow2 sz (x1 x2 y1 y2: word (sz + 1)):
x1 = y1 ^+ $(pow2 sz) ->
x2 = y2 ^+ $(pow2 sz) ->
x1 ^+ x2 = y1 ^+ y2.
Lemma wlt_meaning sz (w1 w2: word sz):
(w1 < w2)%word <-> #w1 < #w2.
Lemma combine_wplus sz (w1 w2: word sz):
#w1 + #w2 < pow2 sz ->
forall sz' (w': word sz'),
combine (w1 ^+ w2) w' = combine w1 w' ^+ combine w2 ($ 0).
Lemma word1_neq (w: word 1):
w <> WO~0 ->
w <> WO~1 ->
False.
Lemma combine_1 sz:
sz > 1 ->
natToWord (sz + 1) 1 = combine ($ 1) WO~0.
Lemma wordToNat_cast ni no (pf: ni = no):
forall w,
#w = #(match pf in _ = Y return _ Y with
| eq_refl => w
end).
Lemma countLeadingZerosWord_lt_len no ni:
ni < pow2 no ->
forall w: word ni,
w <> wzero ni ->
(countLeadingZerosWord no w < natToWord _ ni)%word.