(** * Greatest common divisor (gcd). *)
(** There is no unicity of the gcd; hence we define the predicate [Zis_gcd a b g] expressing that [g] is a gcd of [a] and [b]. (We show later that the [gcd] is actually unique if we discard its sign.) *)
Inductive Zis_gcd (a b g:Z) : Prop :=
Zis_gcd_intro :
(g | a) ->
(g | b) ->
(forall x, (x | a) -> (x | b) -> (x | g)) ->
Zis_gcd a b g.

(* Specifications: *)
Lemma Zgcd_is_gcd : forall a b, Zis_gcd a b (Z.gcd a b).
(** Trivial properties of [gcd] *)
Lemma Zis_gcd_sym : forall a b d, Zis_gcd a b d -> Zis_gcd b a d.
Lemma Zis_gcd_0 : forall a, Zis_gcd a 0 a.
Lemma Zis_gcd_1 : forall a, Zis_gcd a 1 1.
Lemma Zis_gcd_refl : forall a, Zis_gcd a a a.
Lemma Zis_gcd_minus : forall a b d, Zis_gcd a (- b) d -> Zis_gcd b a d.
Lemma Zis_gcd_opp : forall a b d, Zis_gcd a b d -> Zis_gcd b a (- d).
Lemma Zis_gcd_0_abs a : Zis_gcd 0 a (Z.abs a).
#[global]
Hint Resolve Zis_gcd_sym Zis_gcd_0 Zis_gcd_minus Zis_gcd_opp: zarith.
Theorem Zis_gcd_unique: forall a b c d : Z,
Zis_gcd a b c -> Zis_gcd a b d ->  c = d \/ c = (- d).