(** * Greatest common divisor. *)

Definition common_div (x y : Z) (d : nat) :=
  Divides d (Zabs_nat x) /\ Divides d (Zabs_nat y).Definition gcd (x y : Z) (d : nat) :=
  common_div x y d /\ (forall e : nat, common_div x y e -> e <= d).

(* Specifications: *)
Lemma gcd_unq : forall (d1 d2 : nat) (x y : Z), gcd x y d1 -> gcd x y d2 -> d1 = d2.
Lemma gcd_sym : forall (d : nat) (x y : Z), gcd x y d -> gcd y x d.
Lemma gcd_opp_l : forall (d : nat) (x y : Z), gcd x y d -> gcd (- x) y d.
Lemma gcd_opp_r : forall (d : nat) (x y : Z), gcd x y d -> gcd x (- y) d.
Lemma gcd_0_l : forall d : nat, d > 0 -> gcd 0 (Z_of_nat d) d.
Lemma gcd_0_r : forall d : nat, d > 0 -> gcd (Z_of_nat d) 0 d.
Lemma euclid_gcd1 : forall (d : nat) (x y q r : Z), gcd x y d -> x = (q * y + r)%Z -> gcd r y d.
Theorem euclid_gcd : forall (d1 d2 : nat) (x y q r : Z), x = (q * y + r)%Z -> gcd x y d1 -> gcd r y d2 -> d1 = d2.
Lemma gcd_lincomb_nat : forall x y d : nat, x > 0 -> gcd (Z_of_nat x) (Z_of_nat y) d -> LinComb (Z_of_nat d) (Z_of_nat x) (Z_of_nat y).
Lemma gcd_lincomb_pos : forall (x y : Z) (d : nat), (x > 0)%Z -> gcd x y d -> LinComb (Z_of_nat d) x y.
Theorem gcd_lincomb : forall (x y : Z) (d : nat), x <> 0%Z -> gcd x y d -> LinComb (Z_of_nat d) x y.