Section POSITIVE_ITERATION.
Variable A: Type.
Variable v1: A.
Variable f: positive -> A -> A.
Let iter (x: positive) (P: forall y, Plt y x -> A) : A :=
match peq x xH with
| left EQ => v1
| right NOTEQ => f (Pos.pred x) (P (Pos.pred x) (Ppred_Plt x NOTEQ))
end.
Definition positive_rec : positive -> A :=
Fix Plt_wf (fun _ => A) iter.
End POSITIVE_ITERATION.
(** * Definitions and theorems over the type [Z] *)
Definition zeq: forall (x y: Z), {x = y} + {x <> y} := Z.eq_dec.
Open Scope Z_scope.
Definition zlt: forall (x y: Z), {x < y} + {x >= y} := Z_lt_dec.
Definition zle: forall (x y: Z), {x <= y} + {x > y} := Z_le_gt_dec.
(** Properties of powers of two. *)
(** Properties of [Zmin] and [Zmax] *)
(** Properties of Euclidean division and modulus. *)
(** Properties of divisibility. *)
(** Conversion from [Z] to [nat]. *)
(** Alignment: [align n amount] returns the smallest multiple of [amount] greater than or equal to [n]. *)
Definition align (n: Z) (amount: Z) :=
((n + amount - 1) / amount) * amount.
(** * Definitions and theorems on the data types [option], [sum] and [list] *)
Set Implicit Arguments.
(** Comparing option types. *)
Definition option_eq (A: Type) (eqA: forall (x y: A), {x=y} + {x<>y}):
forall (x y: option A), {x=y} + {x<>y}.
Hint Resolve nth_error_in: coqlib.
Hint Resolve nth_error_nil: coqlib.
(** Compute the length of a list, with result in [Z]. *)
Fixpoint list_length_z_aux (A: Type) (l: list A) (acc: Z) {struct l}: Z :=
match l with
| nil => acc
| hd :: tl => list_length_z_aux tl (Z.succ acc)
end.
Remark list_length_z_aux_shift:
forall (A: Type) (l: list A) n m,
list_length_z_aux l n = list_length_z_aux l m + (n - m).
Definition list_length_z (A: Type) (l: list A) : Z :=
list_length_z_aux l 0.
(** Extract the n-th element of a list, as [List.nth_error] does, but the index [n] is of type [Z]. *)
Fixpoint list_nth_z (A: Type) (l: list A) (n: Z) {struct l}: option A :=
match l with
| nil => None
| hd :: tl => if zeq n 0 then Some hd else list_nth_z tl (Z.pred n)
end.
(** Properties of [List.incl] (list inclusion). *)
Hint Resolve incl_cons_inv: coqlib.
Hint Resolve  incl_tl incl_refl incl_app_inv_l incl_app_inv_r: coqlib.
(** Properties of [List.map] (mapping a function over a list). *)

Lemma list_append_map_inv:
forall (A B: Type) (f: A -> B) (m1 m2: list B) (l: list A),
List.map f l = m1 ++ m2 ->
exists l1, exists l2, List.map f l1 = m1 /\ List.map f l2 = m2 /\ l = l1 ++ l2.