Transparent Z.of_nat.

(* Specifications: *)
Lemma In_Znth : forall {A} {d: Inhabitant A} (l : list A) x,
In x l ->
exists i, 0 <= i < Zlength l /\ Znth i l = x.
Lemma In_upd_Znth_old : forall {A}{d: Inhabitant A} i (x y : A) l, In x l -> x <> Znth i l -> 0 <= i <= Zlength l ->
In x (upd_Znth i l y).
Lemma Znth_combine : forall {A B} {a: Inhabitant A} {b: Inhabitant B} i (l1: list A) (l2: list B),
Zlength l1 = Zlength l2 ->
Znth i (combine l1 l2) = (Znth i l1, Znth i l2).
Lemma Zlength_combine : forall {A B} (l : list A) (l' : list B),
Zlength (combine l l') = Z.min (Zlength l) (Zlength l').
Lemma nth_Znth : forall {A}{d: Inhabitant A} i l, nth i l default = Znth (Z.of_nat i) l.
Lemma upd_Znth_cons : forall {A} i a l (x : A), i > 0 ->
upd_Znth i (a :: l) x = a :: upd_Znth (i - 1) l x.
Lemma upd_Znth_triv : forall {A}{d: Inhabitant A} i (l : list A) x (Hi : 0 <= i < Zlength l),
Znth i l = x -> upd_Znth i l x = l.
Lemma combine_upd_Znth : forall {A B} (l1 : list A) (l2 : list B) i x1 x2, 0 <= i < Zlength l1 ->
Zlength l1 = Zlength l2 -> combine (upd_Znth i l1 x1) (upd_Znth i l2 x2) = upd_Znth i (combine l1 l2) (x1, x2).
Corollary combine_upd_Znth1 : forall {A B}{d: Inhabitant B} (l1 : list A) (l2 : list B) i x,
0 <= i < Zlength l1 ->
Zlength l1 = Zlength l2 ->
combine (upd_Znth i l1 x) l2 = upd_Znth i (combine l1 l2) (x, Znth i l2).
Corollary combine_upd_Znth2 : forall {A B}{d: Inhabitant A} (l1 : list A) (l2 : list B) i x, 0 <= i < Zlength l1 ->
Zlength l1 = Zlength l2 -> combine l1 (upd_Znth i l2 x) = upd_Znth i (combine l1 l2) (Znth i l1, x).
Lemma in_concat : forall {A} (l : list (list A)) x, In x (concat l) <-> exists l1, In x l1 /\ In l1 l.
Lemma length_concat : forall {A} (l : list (list A)), length (concat l) = fold_right plus O (map (@length A) l).
Lemma length_concat_min : forall {A}{d: Inhabitant A} (l : list (list A)) i (Hi : 0 <= i < Zlength l),
(length (Znth i l) <= length (concat l))%nat.
Lemma length_concat_upd : forall {A} {d: Inhabitant A} l i (l' : list A) (Hi : 0 <= i < Zlength l),
length (concat (upd_Znth i l l')) = (length (concat l) + length l' - length (Znth i l))%nat.
Lemma sepcon_rev : forall l, fold_right sepcon emp (rev l) = fold_right sepcon emp l.
Lemma incl_nil : forall {A} (l : list A), incl [] l.
Hint Resolve incl_nil.
Lemma incl_cons_out : forall {A} (a : A) l1 l2, incl l1 (a :: l2) -> ~In a l1 -> incl l1 l2.
Lemma In_upto : forall n i, In i (upto n) <-> 0 <= i < Z.of_nat n.
Lemma combine_fst : forall {A B} (l : list A) (l' : list B), length l = length l' ->
map fst (combine l l') = l.
Lemma combine_snd : forall {A B} (l : list A) (l' : list B), length l = length l' ->
map snd (combine l l') = l'.
Lemma rev_combine : forall {A B} (l1 : list A) (l2 : list B), length l1 = length l2 ->
rev (combine l1 l2) = combine (rev l1) (rev l2).
Lemma combine_map_snd : forall {A B C} (l1 : list A) (l2 : list B) (f : B -> C),
combine l1 (map f l2) = map (fun x => let '(a, b) := x in (a, f b)) (combine l1 l2).
Lemma combine_const1 : forall {A B} (l1 : list A) (x : B) n, Z.of_nat n >= Zlength l1 ->
combine l1 (repeat x n) = map (fun a => (a, x)) l1.
Lemma combine_const2 : forall {A B} (x : A) n (l2 : list B), Z.of_nat n >= Zlength l2 ->
combine (repeat x n) l2 = map (fun b => (x, b)) l2.
Lemma map_const: forall {A B} (c : A) (l : list B), map (fun _ => c) l = repeat c (length l).
Lemma In_upd_Znth : forall {A} i l (x y : A), In x (upd_Znth i l y) -> x = y \/ In x l.
Lemma upd_Znth_In : forall {A} i l (x : A), In x (upd_Znth i l x).
Lemma NoDup_Znth_iff : forall {A}{d: Inhabitant A} (l : list A),
NoDup l <-> forall i j (Hi : 0 <= i < Zlength l)
(Hj : 0 <= j < Zlength l), Znth i l = Znth j l -> i = j.
Lemma concat_less_incl : forall {A} l i (l1 l2 : list A) (Hi : 0 <= i < Zlength l)
(Hless : Znth i l = l1 ++ l2), incl (concat (upd_Znth i l l1)) (concat l).
Lemma NoDup_app : forall {A} (l1 l2 : list A), NoDup (l1 ++ l2) ->
NoDup l1 /\ NoDup l2 /\ forall x, In x l1 -> ~In x l2.
Lemma NoDup_app_iff : forall {A} (l1 l2 : list A), NoDup (l1 ++ l2) <->
NoDup l1 /\ NoDup l2 /\ forall x, In x l1 -> ~In x l2.
Corollary NoDup_app_swap : forall {A} (l1 l2 : list A), NoDup (l1 ++ l2) <-> NoDup (l2 ++ l1).
Lemma NoDup_concat_less : forall {A} l i (l1 l2 : list A) (Hl : NoDup (concat l))
(Hi : 0 <= i < Zlength l) (Hless : Znth i l = l1 ++ l2),
NoDup (concat (upd_Znth i l l1)).
Lemma Forall2_Znth : forall {A B}{d1: Inhabitant A}{d2: Inhabitant B} (P : A -> B -> Prop) l1 l2 (Hall : Forall2 P l1 l2) i
(Hi : 0 <= i < Zlength l1), P (Znth i l1) (Znth i l2).
Lemma Forall2_app_inv : forall {A B} (P : A -> B -> Prop) l1 l2 l3 l4 (Hlen : length l1 = length l3),
Forall2 P (l1 ++ l2) (l3 ++ l4) -> Forall2 P l1 l3 /\ Forall2 P l2 l4.
Lemma Forall2_firstn : forall {A B} (P : A -> B -> Prop) l1 l2 n, Forall2 P l1 l2 ->
Forall2 P (firstn n l1) (firstn n l2).
Lemma Forall2_upd_Znth : forall {A B} (P : A -> B -> Prop) l1 l2 i x1 x2, Forall2 P l1 l2 ->
P x1 x2 -> 0 <= i <= Zlength l1 -> Forall2 P (upd_Znth i l1 x1) (upd_Znth i l2 x2).
Lemma Forall2_impl' : forall {A B} (P Q : A -> B -> Prop) l1 l2,
(forall a b, In a l1 -> In b l2 -> P a b -> Q a b) -> Forall2 P l1 l2 -> Forall2 Q l1 l2.
Lemma Forall2_impl : forall {A B} (P Q : A -> B -> Prop), (forall a b, P a b -> Q a b) ->
forall l1 l2, Forall2 P l1 l2 -> Forall2 Q l1 l2.
Lemma map_id_eq : forall {A} (l : list A), map (@id A) l = l.
Lemma Forall2_map : forall {A B C D} (P : A -> B -> Prop) (f1 : C -> A) (f2 : D -> B) l1 l2,
Forall2 P (map f1 l1) (map f2 l2) <-> Forall2 (fun a b => P (f1 a) (f2 b)) l1 l2.
Corollary Forall2_map1 : forall {A B C} (P : A -> B -> Prop) (f : C -> A) l1 l2, Forall2 P (map f l1) l2 <->
Forall2 (fun a b => P (f a) b) l1 l2.
Corollary Forall2_map2 : forall {A B C} (P : A -> B -> Prop) (f : C -> B) l1 l2, Forall2 P l1 (map f l2) <->
Forall2 (fun a b => P a (f b)) l1 l2.
Lemma sublist_max_length : forall {A} i j (al : list A), Zlength (sublist i j al) <= Zlength al.
Lemma Forall2_sublist : forall {A B} (P : A -> B -> Prop) l1 l2 i j, Forall2 P l1 l2 -> 0 <= i ->
Forall2 P (sublist i j l1) (sublist i j l2).
Lemma Forall_last : forall {A} (P : A -> Prop) d l, Forall P l -> P d -> P (last l d).
Lemma last_map : forall {A B} (f : A -> B) d l, f (last l d) = last (map f l) (f d).
Lemma In_removelast : forall {A} (l : list A) x, In x (removelast l) -> In x l.
Definition nil_dec {A} (l : list A) : {l = []} + {l <> []}.
Lemma Forall2_upd_Znth_l : forall {A B}{d: Inhabitant B} (P : A -> B -> Prop) l1 l2 i x, Forall2 P l1 l2 ->
P x (Znth i l2) -> 0 <= i < Zlength l1 -> Forall2 P (upd_Znth i l1 x) l2.
Lemma Forall2_upd_Znth_r : forall {A B}{d: Inhabitant A} (P : A -> B -> Prop) l1 l2 i x, Forall2 P l1 l2 ->
P (Znth i l1) x -> 0 <= i < Zlength l1 -> Forall2 P l1 (upd_Znth i l2 x).
Lemma Forall2_eq_upto : forall {A B}{d1: Inhabitant A}{d2: Inhabitant B} (P : A -> B -> Prop) l1 l2, Forall2 P l1 l2 <->
Zlength l1 = Zlength l2 /\ Forall (fun i => P (Znth i l1) (Znth i l2)) (upto (Z.to_nat (Zlength l1))).
Lemma Forall2_forall_Znth : forall {A B}{d1: Inhabitant A}{d2: Inhabitant B}  (P : A -> B -> Prop) l1 l2,
Forall2 P l1 l2 <->
Zlength l1 = Zlength l2 /\ (forall i, 0 <= i < Zlength l1 -> P (Znth i l1) (Znth i l2)).
Lemma Znth_inbounds : forall {A}{d: Inhabitant A} i (l : list A),
Znth i l <> default -> 0 <= i < Zlength l.
Lemma sublist_next : forall {A}{d: Inhabitant A} i j l,
0 <= i < j -> j <= Zlength l ->
sublist i j l = Znth i l :: sublist (i + 1) j l.
Lemma upd_init : forall {A} (l : list A) i b v v', i < b -> Zlength l = i ->
upd_Znth i (l ++ repeat v (Z.to_nat (b - i))) v' = l ++ v' :: repeat v (Z.to_nat (b - (i + 1))).
Corollary upd_init_const : forall {A} i b (v v' : A), 0 <= i < b ->
upd_Znth i (repeat v' (Z.to_nat i) ++ repeat v (Z.to_nat (b - i))) v' =
repeat v' (Z.to_nat (i + 1)) ++ repeat v (Z.to_nat (b - (i + 1))).
Lemma list_Znth_eq : forall {A}{d: Inhabitant A} (l : list A),
l = map (fun j => Znth j l) (upto (length l)).