(** ** Gcd *)
Definition divide x y := exists z, y=z*x.
Notation "( x | y )" := (divide x y) (at level 0) : nat_scope.

(* Specifications: *)
Lemma gcd_divide : forall a b, (gcd a b | a) /\ (gcd a b | b).
Lemma gcd_divide_l : forall a b, (gcd a b | a).
Lemma gcd_nonneg a b : 0<=gcd a b.
Lemma div2_succ_double n : div2 (S (2*n)) = n.
Lemma le_div2 n : div2 (S n) <= n.
Lemma lt_div2 n : 0 < n -> div2 n < n.
Lemma div2_decr a n : a <= S n -> div2 a <= n.
(* needed to implement Stdlib.Numbers.NatInt.NZBitsSpec *)
Lemma testbit_0_l : forall n, testbit 0 n = false.
Lemma testbit_odd_succ' a n : testbit (2*a+1) (S n) = testbit a n.
Lemma testbit_even_succ' a n : testbit (2*a) (S n) = testbit a n.
Lemma shiftl_specif_high : forall a n m, n<=m ->
testbit (shiftl a n) m = testbit a (m-n).
(* needed to implement Stdlib.Numbers.NatInt.NZBitsSpec *)
Lemma shiftl_spec_low : forall a n m, m<n ->
testbit (shiftl a n) m = false.
(* not yet generalized, part of the interface at this point *)
Lemma div2_bitwise : forall op n a b,
div2 (bitwise op (S n) a b) = bitwise op n (div2 a) (div2 b).
(* not yet generalized, part of the interface at this point *)
Lemma odd_bitwise : forall op n a b,
odd (bitwise op (S n) a b) = op (odd a) (odd b).
(* not yet generalized, part of the interface at this point *)
Lemma testbit_bitwise_1 : forall op, (forall b, op false b = false) ->
forall n m a b, a<=n ->
testbit (bitwise op n a b) m = op (testbit a m) (testbit b m).
(* not yet generalized, part of the interface at this point *)
Lemma testbit_bitwise_2 : forall op, op false false = false ->
forall n m a b, a<=n -> b<=n ->
testbit (bitwise op n a b) m = op (testbit a m) (testbit b m).
(* needed to implement Stdlib.Numbers.NatInt.NZBitsSpec *)
Lemma land_spec a b n :
testbit (land a b) n = testbit a n && testbit b n.
(* needed to implement Stdlib.Numbers.NatInt.NZBitsSpec *)
Lemma lxor_spec a b n :
testbit (lxor a b) n = xorb (testbit a n) (testbit b n).
(* needed to implement Stdlib.Numbers.NatInt.NZBitsSpec *)
Lemma div2_spec a : div2 a = shiftr a 1.
Lemma tail_addmul_spec r n m : tail_addmul r n m = r + n * m.
Lemma tail_mul_spec n m : tail_mul n m = n * m.
Lemma Odd_add_split n m :
Odd (n + m) -> Odd n /\ Even m \/ Even n /\ Odd m.
Lemma Even_Even_add n m: Even n -> Even m -> Even (n + m).
Lemma Odd_add_r n m : Even n -> Odd m -> Odd (n + m).
Lemma Odd_Odd_add n m : Odd n -> Odd m -> Even (n + m).
Lemma Even_add_aux n m :
(Odd (n + m) <-> Odd n /\ Even m \/ Even n /\ Odd m) /\
(Even (n + m) <-> Even n /\ Even m \/ Odd n /\ Odd m).
Lemma Even_add_Even_inv_r n m : Even (n + m) -> Even n -> Even m.
Lemma Even_add_Odd_inv_l n m : Even (n + m) -> Odd m -> Odd n.
Lemma Odd_add_Even_inv_l n m : Odd (n + m) -> Odd m -> Even n.
Lemma Odd_add_Even_inv_r n m : Odd (n + m) -> Odd n -> Even m.
Lemma Odd_add_Odd_inv_l n m : Odd (n + m) -> Even m -> Odd n.
Lemma Odd_add_Odd_inv_r n m : Odd (n + m) -> Even n -> Odd m.
Lemma Even_mul_aux n m :
(Odd (n * m) <-> Odd n /\ Odd m) /\ (Even (n * m) <-> Even n \/ Even m).
Lemma Even_mul_l n m : Even n -> Even (n * m).
Lemma Even_mul_inv_l n m : Even (n * m) -> Odd m -> Even n.
Lemma Odd_mul n m : Odd n -> Odd m -> Odd (n * m).
Lemma div2_Even n : div2 n = div2 (S n) -> Even n.
Lemma div2_Odd n : S (div2 n) = div2 (S n) -> Odd n.
Lemma Even_Odd_div2 n :
(Even n <-> div2 n = div2 (S n)) /\ (Odd n <-> S (div2 n) = div2 (S n)).
Lemma Even_Odd_double n :
(Even n <-> n = double (div2 n)) /\ (Odd n <-> n = S (double (div2 n))).
Lemma Even_double n : Even n -> n = double (div2 n).
Proof proj1 (proj1 (Even_Odd_double n)).
Lemma double_Even n : n = double (div2 n) -> Even n.
Proof proj2 (proj1 (Even_Odd_double n)).
Lemma Odd_double n : Odd n -> n = S (double (div2 n)).
Proof proj1 (proj2 (Even_Odd_double n)).
Lemma double_Odd n : n = S (double (div2 n)) -> Odd n.
Proof proj2 (proj2 (Even_Odd_double n)).