(** We can now derive all properties of basic functions and orders, and use these properties for proving the specs of more advanced functions. *)

(* Specifications: *)
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 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.
(** 0 is the least natural number *)
Theorem compare_0_r n : (n ?= 0) <> Lt.
(** Specifications of power *)
Lemma pow_0_r n : n ^ 0 = 1.
Lemma pow_neg_r n p : p<0 -> n^p = 0.
(** Specification of square *)
Lemma square_spec n : square n = n * n.
(** Specification of Base-2 logarithm *)
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.
(** Specification of parity functions *)
Lemma even_spec n : even n = true <-> Even n.
Lemma odd_spec n : odd n = true <-> Odd n.
(** Specification of the euclidean division *)
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.
(** Specification of square root *)
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.
(** Specification of gcd *)
(** The first component of ggcd is gcd *)
Lemma ggcd_gcd a b : fst (ggcd a b) = gcd a b.
(** The other components of ggcd are indeed the correct factors. *)
Lemma ggcd_correct_divisors a b :
let '(g,(aa,bb)) := ggcd a b in
a=g*aa /\ b=g*bb.