Section Iteration.
Variable T : Type.
Implicit Types m n : nat.
Implicit Types x y : T.
Definition iter n f x :=
let fix loop m := if m is i.+1 then f (loop i) else x in loop n.
Definition iteri n f x :=
let fix loop m := if m is i.+1 then f i (loop i) else x in loop n.
Definition iterop n op x :=
let f i y := if i is 0 then x else op x y in iteri n f.

(* Specifications: *)
Lemma iterSr n f x : iter n.+1 f x = iter n f (f x).
Lemma mulnDl : left_distributive muln addn.
Lemma mulnBr : right_distributive muln subn.
Lemma eqn_mul2l m n1 n2 : (m * n1 == m * n2) = (m == 0) || (n1 == n2).
Lemma maxn_mulr : right_distributive muln maxn.
Lemma expnAC m n1 n2 : (m ^ n1) ^ n2 = (m ^ n2) ^ n1.
Lemma expn_eq0 m e : (m ^ e == 0) = (m == 0) && (e > 0).
Lemma leq_exp2l m n1 n2 : 1 < m -> (m ^ n1 <= m ^ n2) = (n1 <= n2).
Lemma ltn_exp2l m n1 n2 : 1 < m -> (m ^ n1 < m ^ n2) = (n1 < n2).
Lemma leq_exp2r m n e : e > 0 -> (m ^ e <= n ^ e) = (m <= n).
Lemma odd_opp i m : odd m = false -> i <= m -> odd (m - i) = odd i.
Lemma half_bit_double n (b : bool) : (b + n.*2)./2 = n.
Lemma half_leq m n : m <= n -> m./2 <= n./2.
Lemma odd_ltn m n : odd n -> (n < m) = (n < m./2.*2).
Lemma sqrn_sub m n : n <= m -> (m - n) ^ 2 = m ^ 2 + n ^ 2 - 2 * (m * n).
Lemma sqrnD_sub m n : n <= m -> (m + n) ^ 2 - 4 * (m * n) = (m - n) ^ 2.
Lemma subn_sqr m n : m ^ 2 - n ^ 2 = (m - n) * (m + n).
Lemma leqif_refl m C : reflect (m <= m ?= iff C) C.
Lemma mono_leqif f : {mono f : m n / m <= n} ->
forall m n C, (f m <= f n ?= iff C) = (m <= n ?= iff C).
Lemma leqif_mul m1 n1 C1 m2 n2 C2 :
m1 <= n1 ?= iff C1 -> m2 <= n2 ?= iff C2 ->
m1 * m2 <= n1 * n2 ?= iff (n1 * n2 == 0) || (C1 && C2).
Lemma nat_Cauchy m n : 2 * (m * n) <= m ^ 2 + n ^ 2 ?= iff (m == n).
Lemma nat_AGM2 m n : 4 * (m * n) <= (m + n) ^ 2 ?= iff (m == n).
Section Monotonicity.