Definition lnztail l :=
  let fix aux l_rev :=
    match l_rev with
    | cons d0 l_rev => let (r, n) := aux l_rev in pair r (S n)
    | _ => pair l_rev O
    end in
  let (r, n) := aux (List.rev l) in pair (List.rev r) n.

(* Specifications: *)
Lemma nztail_spec d : let (r, n) := nztail d in let (r', n') := lnztail (to_list d) in to_list r = r' /\ n = n'.
Lemma del_head_spec_0 d : del_head 0 d = d.
Lemma del_head_spec_small n d : n <= length (to_list d) -> to_list (del_head n d) = List.skipn n (to_list d).
Lemma del_head_spec_large n d : length (to_list d) < n -> del_head n d = zero.
Lemma nb_digits_0 d : nb_digits d = 0 -> d = Nil.
Lemma nb_digits_n0 d : nb_digits d <> 0 -> d <> Nil.
Lemma nb_digits_iter_D0 n d : nb_digits (Nat.iter n D0 d) = n + nb_digits d.
Lemma length_lnzhead l : length (lnzhead l) <= length l.
Lemma nb_digits_nzhead u : nb_digits (nzhead u) <= nb_digits u.
Lemma unorm_nzhead u : nzhead u <> Nil -> unorm u = nzhead u.
Lemma nb_digits_unorm u : u <> Nil -> nb_digits (unorm u) <= nb_digits u.
Lemma nb_digits_rev d : nb_digits (rev d) = nb_digits d.
Lemma nb_digits_del_head_sub d n : n <= nb_digits d -> nb_digits (del_head (nb_digits d - n) d) = n.
Lemma unorm_D0 u : unorm (D0 u) = unorm u.
Lemma app_nil_l d : app Nil d = d.
Lemma app_nil_r d : app d Nil = d.
Lemma abs_app_int d d' : abs (app_int d d') = app (abs d) d'.
Lemma abs_norm d : abs (norm d) = unorm (abs d).
Lemma iter_D0_nzhead d : Nat.iter (nb_digits d - nb_digits (nzhead d)) D0 (nzhead d) = d.
Lemma iter_D0_unorm d : d <> Nil -> Nat.iter (nb_digits d - nb_digits (unorm d)) D0 (unorm d) = d.
Lemma nzhead_app_l d d' : nb_digits d' < nb_digits (nzhead (app d d')) -> nzhead (app d d') = app (nzhead d) d'.
Lemma nzhead_app_r d d' : nb_digits (nzhead (app d d')) <= nb_digits d' -> nzhead (app d d') = nzhead d'.
Lemma nzhead_app_nil_r d d' : nzhead (app d d') = Nil -> nzhead d' = Nil.
Lemma nzhead_app_nil d d' : nb_digits (nzhead (app d d')) <= nb_digits d' -> nzhead d = Nil.
Lemma nzhead_app_nil_l d d' : nzhead (app d d') = Nil -> nzhead d = Nil.
Lemma unorm_app_zero d d' : nb_digits (unorm (app d d')) <= nb_digits d' -> unorm d = zero.
Lemma app_int_nil_r d : app_int d Nil = d.
Lemma unorm_app_l d d' : nb_digits d' < nb_digits (unorm (app d d')) -> unorm (app d d') = app (unorm d) d'.
Lemma unorm_app_r d d' : nb_digits (unorm (app d d')) <= nb_digits d' -> unorm (app d d') = unorm d'.
Lemma norm_app_int d d' : nb_digits d' < nb_digits (unorm (app (abs d) d')) -> norm (app_int d d') = app_int (norm d) d'.
Lemma del_head_nb_digits d : del_head (nb_digits d) d = Nil.
Lemma del_tail_nb_digits d : del_tail (nb_digits d) d = Nil.
Lemma del_head_app n d d' : n <= nb_digits d -> del_head n (app d d') = app (del_head n d) d'.
Lemma del_tail_app n d d' : n <= nb_digits d' -> del_tail n (app d d') = app d (del_tail n d').
Lemma del_tail_app_int n d d' : n <= nb_digits d' -> del_tail_int n (app_int d d') = app_int d (del_tail n d').
Lemma app_del_tail_head n (d:uint) : n <= nb_digits d -> app (del_tail n d) (del_head (nb_digits d - n) d) = d.
Lemma app_int_del_tail_head n (d:int) : n <= nb_digits (abs d) -> app_int (del_tail_int n d) (del_head (nb_digits (abs d) - n) (abs d)) = d.
Lemma del_head_app_int_exact i f : nb_digits f < nb_digits (unorm (app (abs i) f)) -> del_head (nb_digits (unorm (app (abs i) f)) - nb_digits f) (unorm (app (abs i) f)) = f.
Lemma del_tail_app_int_exact i f : nb_digits f < nb_digits (unorm (app (abs i) f)) -> del_tail_int (nb_digits f) (norm (app_int i f)) = norm i.
Lemma nztail_spec d : let (r, n) := nztail d in let (r', n') := lnztail (to_list d) in to_list r = r' /\ n = n'.
Lemma del_head_spec_0 d : del_head 0 d = d.
Lemma del_head_spec_small n d : n <= length (to_list d) -> to_list (del_head n d) = List.skipn n (to_list d).
Lemma del_head_spec_large n d : length (to_list d) < n -> del_head n d = zero.
Lemma nb_digits_0 d : nb_digits d = 0 -> d = Nil.
Lemma nb_digits_n0 d : nb_digits d <> 0 -> d <> Nil.
Lemma nb_digits_iter_D0 n d : nb_digits (Nat.iter n D0 d) = n + nb_digits d.
Lemma length_lnzhead l : length (lnzhead l) <= length l.
Lemma nb_digits_nzhead u : nb_digits (nzhead u) <= nb_digits u.
Lemma unorm_nzhead u : nzhead u <> Nil -> unorm u = nzhead u.
Lemma nb_digits_unorm u : u <> Nil -> nb_digits (unorm u) <= nb_digits u.
Lemma nb_digits_rev d : nb_digits (rev d) = nb_digits d.
Lemma nb_digits_del_head_sub d n : n <= nb_digits d -> nb_digits (del_head (nb_digits d - n) d) = n.
Lemma unorm_D0 u : unorm (D0 u) = unorm u.
Lemma app_nil_l d : app Nil d = d.
Lemma app_nil_r d : app d Nil = d.
Lemma abs_app_int d d' : abs (app_int d d') = app (abs d) d'.
Lemma abs_norm d : abs (norm d) = unorm (abs d).
Lemma iter_D0_nzhead d : Nat.iter (nb_digits d - nb_digits (nzhead d)) D0 (nzhead d) = d.
Lemma iter_D0_unorm d : d <> Nil -> Nat.iter (nb_digits d - nb_digits (unorm d)) D0 (unorm d) = d.
Lemma nzhead_app_l d d' : nb_digits d' < nb_digits (nzhead (app d d')) -> nzhead (app d d') = app (nzhead d) d'.
Lemma nzhead_app_r d d' : nb_digits (nzhead (app d d')) <= nb_digits d' -> nzhead (app d d') = nzhead d'.
Lemma nzhead_app_nil_r d d' : nzhead (app d d') = Nil -> nzhead d' = Nil.
Lemma nzhead_app_nil d d' : nb_digits (nzhead (app d d')) <= nb_digits d' -> nzhead d = Nil.
Lemma nzhead_app_nil_l d d' : nzhead (app d d') = Nil -> nzhead d = Nil.
Lemma unorm_app_zero d d' : nb_digits (unorm (app d d')) <= nb_digits d' -> unorm d = zero.
Lemma app_int_nil_r d : app_int d Nil = d.
Lemma unorm_app_l d d' : nb_digits d' < nb_digits (unorm (app d d')) -> unorm (app d d') = app (unorm d) d'.
Lemma unorm_app_r d d' : nb_digits (unorm (app d d')) <= nb_digits d' -> unorm (app d d') = unorm d'.
Lemma norm_app_int d d' : nb_digits d' < nb_digits (unorm (app (abs d) d')) -> norm (app_int d d') = app_int (norm d) d'.
Lemma del_head_nb_digits d : del_head (nb_digits d) d = Nil.
Lemma del_tail_nb_digits d : del_tail (nb_digits d) d = Nil.
Lemma del_head_app n d d' : n <= nb_digits d -> del_head n (app d d') = app (del_head n d) d'.
Lemma del_tail_app n d d' : n <= nb_digits d' -> del_tail n (app d d') = app d (del_tail n d').
Lemma del_tail_app_int n d d' : n <= nb_digits d' -> del_tail_int n (app_int d d') = app_int d (del_tail n d').
Lemma app_del_tail_head n (d:uint) : n <= nb_digits d -> app (del_tail n d) (del_head (nb_digits d - n) d) = d.
Lemma app_int_del_tail_head n (d:int) : n <= nb_digits (abs d) -> app_int (del_tail_int n d) (del_head (nb_digits (abs d) - n) (abs d)) = d.
Lemma del_head_app_int_exact i f : nb_digits f < nb_digits (unorm (app (abs i) f)) -> del_head (nb_digits (unorm (app (abs i) f)) - nb_digits f) (unorm (app (abs i) f)) = f.
Lemma del_tail_app_int_exact i f : nb_digits f < nb_digits (unorm (app (abs i) f)) -> del_tail_int (nb_digits f) (norm (app_int i f)) = norm i.