Definition Zlength' := @Zlength.Ltac pose_Zlength_nonneg1 T A :=
     lazymatch goal with
      | H:  0 <= @Zlength T A |- _ => idtac
      | H:  0 <= @Zlength T A /\ _ |- _ => idtac
      | |- _ => pose proof (@Zlength_nonneg T A)
     end;
     (* the next three lines are to avoid blowups in the change command *)
     let x := fresh "x" in set (x:= @Zlength T A) in *;
     let y := fresh "y" in set (y := @Zlength) in x;
     fold @Zlength' in y; subst y; subst x.Ltac pose_Zlength_nonneg :=
 repeat
  match goal with
  | |- context [@Zlength ?T ?A] => pose_Zlength_nonneg1 T A
  | H: context [@Zlength ?T ?A] |- _ => pose_Zlength_nonneg1 T A
 end;
  unfold Zlength' in *.Ltac list_solve := autorewrite with sublist; pose_Zlength_nonneg; omega.Definition Znth {X}{d: Inhabitant X} n (xs: list X) :=
  if (zlt n 0) then default else nth (Z.to_nat n) xs d.

(* Specifications: *)
Lemma Znth_map: forall {A:Type} {da: Inhabitant A}{B:Type}{db: Inhabitant B} i (f: A -> B) (al: list A), 0 <= i < Zlength al -> Znth i (map f al) = f (Znth i al).
Lemma Znth_succ: forall {A}{a: Inhabitant A} i lo (v: list A), Z.succ lo <= i -> Znth (i - lo) v = Znth (i - (Z.succ lo)) (skipn 1 v).
Lemma Znth_0_cons {A}{a: Inhabitant A} l (v:A): Znth 0 (v::l) = v.
Lemma Znth_pos_cons {A}{a: Inhabitant A} i l (v:A): 0<i -> Znth i (v::l) = Znth (i-1) l.
Lemma Znth_In : forall {A}{a: Inhabitant A} i l, 0 <= i < Zlength l -> In (Znth i l) l.
Lemma split3_full_length_list: forall {A}{a: Inhabitant A} lo mid hi (ct: list A), lo <= mid < hi -> Zlength ct = hi - lo -> ct = firstn (Z.to_nat (mid - lo)) ct ++ (Znth (mid - lo) ct :: nil) ++ skipn (Z.to_nat (mid - lo + 1)) ct.
Lemma Forall_Znth: forall {A}{a: Inhabitant A} (F: A -> Prop) (al: list A) i, 0 <= i < Zlength al -> Forall F al -> F (Znth i al).
Lemma app_Znth1: forall A (a: Inhabitant A) (l l': list A) (i:Z), i < Zlength l -> Znth i (l++l') = Znth i l.
Lemma app_Znth2: forall A (a: Inhabitant A) (l l': list A) (i:Z), i >= Zlength l -> Znth i (l++l') = Znth (i-Zlength l) l'.
Lemma Znth_firstn: forall {A}{a: Inhabitant A} (al: list A) (n m : Z), n<m -> Znth n (firstn (Z.to_nat m) al) = Znth n al.
Lemma Znth_skipn: forall {A}{a: Inhabitant A} i n xs, 0 <= i -> 0 <= n -> Znth i (skipn (nat_of_Z n) xs) = Znth (i+n) xs.
Lemma Z2Nat_neg: forall i, i < 0 -> Z.to_nat i = 0%nat.
Lemma Zlength_firstn: forall {A} n (v: list A), Zlength (firstn (Z.to_nat n) v) = Z.min (Z.max 0 n) (Zlength v).
Lemma Zlength_skipn: forall {A} n (v: list A), Zlength (skipn (Z.to_nat n) v) = Z.max 0 (Zlength v - (Z.max 0n)).
Lemma Znth_cons: forall {A}(a: Inhabitant A) i (al: list A) bl, 0 <= i < Zlength al -> Znth i al :: bl = firstn (Z.to_nat 1) (skipn (Z.to_nat i) al) ++ bl.
Lemma Zfirstn_app1: forall A n (al bl: list A), n <= Zlength al -> firstn (Z.to_nat n) (al++bl) = firstn (Z.to_nat n) al.
Lemma Zfirstn_same: forall A n (b: list A), n >= Zlength b -> firstn (Z.to_nat n) b = b.
Lemma Zfirstn_app2: forall {A} n (al bl: list A), n >= Zlength al -> firstn (Z.to_nat n) (al++bl) = al ++ firstn (Z.to_nat (n - Zlength al)) bl.
Lemma Zfirstn_firstn: forall {A} (contents: list A) n m, n <= m -> firstn (Z.to_nat n) (firstn (Z.to_nat m) contents) = firstn (Z.to_nat n) contents.
Lemma Zskipn_app1: forall A n (al bl: list A), n <= Zlength al -> skipn (Z.to_nat n) (al++bl) = skipn (Z.to_nat n) al ++ bl.
Lemma Zskipn_app2: forall A n (al bl: list A), n >= Zlength al -> skipn (Z.to_nat n) (al++bl) = skipn (Z.to_nat (n-Zlength al)) bl.
Lemma Znth_rev: forall {A}{d: Inhabitant A} i (al:list A), 0 <= i < Zlength al -> Znth i (rev al) = Znth (Zlength al - i - 1) al.
Lemma Zskipn_firstn: forall {A} n m (xs: list A), 0 <= n -> skipn (Z.to_nat n) (firstn (Z.to_nat m) xs) = firstn (Z.to_nat (m-n)) (skipn (Z.to_nat n) xs).
Lemma Zskipn_skipn: forall {A} n m (xs: list A), 0 <= n -> 0 <= m -> skipn (Z.to_nat n) (skipn (Z.to_nat m) xs) = skipn (Z.to_nat (m + n)) xs.
Lemma Zfirstn_app: forall {A} n m (al: list A), 0 <= n -> 0 <= m -> firstn (Z.to_nat n) al ++ firstn (Z.to_nat m) (skipn (Z.to_nat n) al) = firstn (Z.to_nat (n+m)) al.
Lemma Zfirstn_exact_length: forall {A} n (al: list A), n = Zlength al -> firstn (Z.to_nat n) al = al.