Class Inhabitant (A: Type) := default : A.
Instance Inhabitant_Z : Inhabitant Z := 0.
Instance Inhabitant_nat : Inhabitant nat := O.
Instance Inhabitant_positive : Inhabitant positive := 1%positive.
Instance Inhabitant_list {T: Type} : Inhabitant (list T) := @nil T.
Instance Inhabitant_fun {T1 T2: Type} {H: Inhabitant T2} : Inhabitant (T1->T2) := fun _ => H.
Instance Inhabitant_Prop : Inhabitant Prop := False.
Instance Inhabitant_bool : Inhabitant bool := false.
Instance Inhabitant_pair {T1 T2 : Type} {x1: Inhabitant T1} {x2: Inhabitant T2} : Inhabitant (T1*T2)%type := (x1,x2).
Hint Rewrite @ZtoNat_Zlength : norm.
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.
Hint Rewrite
(@Znth_map Z _) (@Znth_map nat _) (@Znth_map positive _)
using (auto; rewrite ?Zlength_map in *; omega) : sublist.
(* Add these in a later file where things are in scope ... Hint Rewrite (Znth_map Int.zero) (Znth_map Vundef) using (auto; rewrite ?Zlength_map in *; omega) : sublist. *)
Hint Rewrite @app_nil_l @app_nil_r : sublist.
(*****   SUBLIST  ******)
Definition sublist {A} (lo hi: Z) (al: list A) : list A :=
firstn (Z.to_nat (hi-lo)) (skipn (Z.to_nat lo) al).
Definition upd_Znth {A} (i: Z) (al: list A) (x: A): list A :=
sublist 0 i al ++ x :: sublist (i+1) (Zlength al) al.
(* not this version! Lemma sublist_list_repeat {A} i j k (v:A) (I: 0<=i) (IJK: (Z.to_nat i <= Z.to_nat j <= k)%nat): sublist i j (list_repeat k v) = list_repeat (Z.to_nat (j-i)) v. *)
Hint Rewrite @sublist_nil' using list_solve: sublist.
Hint Rewrite @app_nil_l : sublist.
Hint Rewrite @Zlength_rev : sublist.
Hint Rewrite @sublist_rejoin' using list_solve : sublist.

Lemma upd_Znth_lookup K {A}{d: Inhabitant A}: forall l (L:Zlength l = K) i j (v:A) (I: 0<=i<K) (J: 0<=j<K),
(i=j /\ Znth i (upd_Znth j l v) = v) \/
(i<>j /\ Znth i (upd_Znth j l v) = Znth i l).