Definition recursion {A} : A -> (N -> A -> A) -> N -> A :=
  peano_rect (fun _ => A).#[global]
Instance recursion_wd {A} (Aeq : relation A) :
 Proper (Aeq==>(Logic.eq==>Aeq==>Aeq)==>Logic.eq==>Aeq) recursion.

(* Specifications: *)
Theorem recursion_0 {A} (a:A) (f:N->A->A) : recursion a f 0 = a.
Theorem recursion_succ {A} (Aeq : relation A) (a : A) (f : N -> A -> A): Aeq a a -> Proper (Logic.eq==>Aeq==>Aeq) f -> forall n : N, Aeq (recursion a f (succ n)) (f n (recursion a f n)).
Lemma one_succ : 1 = succ 0.
Lemma two_succ : 2 = succ 1.
Lemma pred_0 : pred 0 = 0.
Lemma pos_pred_spec p : Pos.pred_N p = pred (pos p).
Lemma succ_pos_spec n : pos (succ_pos n) = succ n.
Lemma pos_pred_succ n : Pos.pred_N (succ_pos n) = n.
Lemma succ_pos_pred p : succ (Pos.pred_N p) = pos p.
Theorem pred_succ n : pred (succ n) = n.
Theorem pred_sub n : pred n = sub n 1.
Theorem succ_0_discr n : succ n <> 0.
Theorem add_0_l n : 0 + n = n.
Theorem add_succ_l n m : succ n + m = succ (n + m).
Theorem sub_0_r n : n - 0 = n.
Theorem sub_succ_r n m : n - succ m = pred (n - m).
Theorem mul_0_l n : 0 * n = 0.
Theorem mul_succ_l n m : (succ n) * m = n * m + m.
Lemma eqb_eq n m : eqb n m = true <-> n=m.
Lemma ltb_lt n m : (n <? m) = true <-> n < m.
Lemma leb_le n m : (n <=? m) = true <-> n <= m.
Theorem compare_eq_iff n m : (n ?= m) = Eq <-> n = m.
Theorem compare_lt_iff n m : (n ?= m) = Lt <-> n < m.
Theorem compare_le_iff n m : (n ?= m) <> Gt <-> n <= m.
Theorem compare_antisym n m : (m ?= n) = CompOpp (n ?= m).
Theorem min_l n m : n <= m -> min n m = n.
Theorem min_r n m : m <= n -> min n m = m.
Theorem max_l n m : m <= n -> max n m = n.
Theorem max_r n m : n <= m -> max n m = m.
Lemma lt_succ_r n m : n < succ m <-> n<=m.
Lemma strong_induction_le (A : N -> Prop) : A 0 -> (forall n, (forall m, m <= n -> A m) -> A (succ n)) -> forall n, A n.
Lemma double_spec n : double n = 2 * n.
Lemma succ_double_spec n : succ_double n = 2 * n + 1.
Lemma double_add n m : double (n+m) = double n + double m.
Lemma succ_double_add n m : succ_double (n+m) = double n + succ_double m.
Lemma double_mul n m : double (n*m) = double n * m.
Lemma succ_double_mul n m : succ_double n * m = double n * m + m.
Lemma div2_double n : div2 (double n) = n.
Lemma div2_succ_double n : div2 (succ_double n) = n.
Lemma double_inj n m : double n = double m -> n = m.
Lemma succ_double_inj n m : succ_double n = succ_double m -> n = m.
Lemma succ_double_lt n m : n<m -> succ_double n < double m.
Lemma double_lt_mono n m : n < m -> double n < double m.
Lemma double_le_mono n m : n <= m -> double n <= double m.
Lemma succ_double_lt_mono n m : n < m -> succ_double n < succ_double m.
Lemma succ_double_le_mono n m : n <= m -> succ_double n <= succ_double m.
Theorem compare_0_r n : (n ?= 0) <> Lt.
Lemma pow_0_r n : n ^ 0 = 1.
Lemma pow_succ_r n p : 0<=p -> n^(succ p) = n * n^p.
Lemma pow_neg_r n p : p<0 -> n^p = 0.
Lemma square_spec n : square n = n * n.
Lemma size_log2 n : n<>0 -> size n = succ (log2 n).
Lemma size_gt n : n < 2^(size n).
Lemma size_le n : 2^(size n) <= succ_double n.
Lemma log2_spec n : 0 < n -> 2^(log2 n) <= n < 2^(succ (log2 n)).
Lemma log2_nonpos n : n<=0 -> log2 n = 0.
Lemma even_spec n : even n = true <-> Even n.
Lemma odd_spec n : odd n = true <-> Odd n.
Theorem pos_div_eucl_spec (a:positive)(b:N) : let (q,r) := pos_div_eucl a b in pos a = q * b + r.
Theorem div_eucl_spec a b : let (q,r) := div_eucl a b in a = b * q + r.
Theorem div_mod' a b : a = b * (a/b) + (a mod b).
Theorem div_mod a b : b<>0 -> a = b * (a/b) + (a mod b).
Theorem pos_div_eucl_remainder (a:positive) (b:N) : b<>0 -> snd (pos_div_eucl a b) < b.
Theorem mod_lt a b : b<>0 -> a mod b < b.
Theorem mod_bound_pos a b : 0<=a -> 0<b -> 0 <= a mod b < b.
Lemma sqrtrem_sqrt n : fst (sqrtrem n) = sqrt n.
Lemma sqrtrem_spec n : let (s,r) := sqrtrem n in n = s*s + r /\ r <= 2*s.
Lemma sqrt_spec n : 0<=n -> let s := sqrt n in s*s <= n < (succ s)*(succ s).
Lemma sqrt_neg n : n<0 -> sqrt n = 0.
Lemma ggcd_gcd a b : fst (ggcd a b) = gcd a b.
Lemma ggcd_correct_divisors a b : let '(g,(aa,bb)) := ggcd a b in a=g*aa /\ b=g*bb.
Lemma gcd_divide_l a b : (gcd a b | a).
Lemma gcd_divide_r a b : (gcd a b | b).
Lemma gcd_greatest a b c : (c|a) -> (c|b) -> (c|gcd a b).
Lemma gcd_nonneg a b : 0 <= gcd a b.
Lemma testbit_even_0 a : testbit (2*a) 0 = false.
Lemma testbit_odd_0 a : testbit (2*a+1) 0 = true.
Lemma testbit_succ_r_div2 a n : 0<=n -> testbit a (succ n) = testbit (div2 a) n.
Lemma testbit_odd_succ a n : 0<=n -> testbit (2*a+1) (succ n) = testbit a n.
Lemma testbit_even_succ a n : 0<=n -> testbit (2*a) (succ n) = testbit a n.
Lemma testbit_neg_r a n : n<0 -> testbit a n = false.
Lemma shiftr_succ_r a n : shiftr a (succ n) = div2 (shiftr a n).
Lemma shiftl_succ_r a n : shiftl a (succ n) = double (shiftl a n).
Lemma shiftr_spec a n m : 0<=m -> testbit (shiftr a n) m = testbit a (m+n).
Lemma shiftl_spec_high a n m : 0<=m -> n<=m -> testbit (shiftl a n) m = testbit a (m-n).
Lemma shiftl_spec_low a n m : m<n -> testbit (shiftl a n) m = false.
Lemma div2_spec a : div2 a = shiftr a 1.
Lemma pos_lxor_spec p p' n : testbit (Pos.lxor p p') n = xorb (Pos.testbit p n) (Pos.testbit p' n).
Lemma lxor_spec a a' n : testbit (lxor a a') n = xorb (testbit a n) (testbit a' n).
Lemma pos_lor_spec p p' n : Pos.testbit (Pos.lor p p') n = (Pos.testbit p n) || (Pos.testbit p' n).
Lemma lor_spec a a' n : testbit (lor a a') n = (testbit a n) || (testbit a' n).
Lemma pos_land_spec p p' n : testbit (Pos.land p p') n = (Pos.testbit p n) && (Pos.testbit p' n).
Lemma land_spec a a' n : testbit (land a a') n = (testbit a n) && (testbit a' n).
Lemma pos_ldiff_spec p p' n : testbit (Pos.ldiff p p') n = (Pos.testbit p n) && negb (Pos.testbit p' n).
Lemma ldiff_spec a a' n : testbit (ldiff a a') n = (testbit a n) && negb (testbit a' n).
Lemma div_0_r a : a / 0 = 0.
Lemma mod_0_r a : a mod 0 = a.
Lemma binary_induction (A : N -> Prop) : A 0 -> (forall n, A n -> A (2 * n)) -> (forall n, A n -> A (2 * n + 1)) -> forall n, A n.
Lemma gt_lt_iff n m : n > m <-> m < n.
Lemma gt_lt n m : n > m -> m < n.
Lemma lt_gt n m : n < m -> m > n.
Lemma ge_le_iff n m : n >= m <-> m <= n.
Lemma ge_le n m : n >= m -> m <= n.
Lemma le_ge n m : n <= m -> m >= n.
Lemma pos_pred_shiftl_low : forall p n m, m<n -> testbit (Pos.pred_N (Pos.shiftl p n)) m = true.
Lemma pos_pred_shiftl_high : forall p n m, n<=m -> testbit (Pos.pred_N (Pos.shiftl p n)) m = testbit (shiftl (Pos.pred_N p) n) m.
Lemma pred_div2_up p : Pos.pred_N (Pos.div2_up p) = div2 (Pos.pred_N p).
Lemma iter_swap_gen A B (f:A -> B) (g:A -> A) (h:B -> B) : (forall a, f (g a) = h (f a)) -> forall n a, f (iter n g a) = iter n h (f a).
Theorem iter_swap : forall n (A:Type) (f:A -> A) (x:A), iter n f (f x) = f (iter n f x).
Theorem iter_succ : forall n (A:Type) (f:A -> A) (x:A), iter (succ n) f x = f (iter n f x).
Theorem iter_succ_r : forall n (A:Type) (f:A -> A) (x:A), iter (succ n) f x = iter n f (f x).
Theorem iter_add : forall p q (A:Type) (f:A -> A) (x:A), iter (p+q) f x = iter p f (iter q f x).
Theorem iter_ind (A:Type) (f:A -> A) (a:A) (P:N -> A -> Prop) : P 0 a -> (forall n a', P n a' -> P (succ n) (f a')) -> forall n, P n (iter n f a).
Theorem iter_invariant : forall (n:N) (A:Type) (f:A -> A) (Inv:A -> Prop), (forall x:A, Inv x -> Inv (f x)) -> forall x:A, Inv x -> Inv (iter n f x).