(* Contribution to the Coq Library   V6.3 (July 1999)                    *)
(****************************************************************************)
(*                 The Calculus of Inductive Constructions                  *)
(*                                                                          *)
(*                                Projet Coq                                *)
(*                                                                          *)
(*                     INRIA                        ENS-CNRS                *)
(*              Rocquencourt                        Lyon                    *)
(*                                                                          *)
(*                                Coq V5.10                                 *)
(*                              Nov 25th 1994                               *)
(*                                                                          *)
(****************************************************************************)
(*                                  Zgcd.v                                  *)
(****************************************************************************)
Require Export misc.
Require Export Zadd.
Require Export Zle.
Require Export Euclid.
Require Export Peano_dec.
Require Export Zrec.
Require Export Zmult.
Require Export Zdiv.
Unset Standard Proposition Elimination Names.
intros.
elim
(gcd_unicity_apart_unities Z IdZ addZ multZ OZ IZ oppZ
Z_unitary_commutative_ring integrityZ a b d1 d2 H H0).
intros.
elim (inversibleZ x); intros.
left. elim H1; intros; elim H4; intros. rewrite H6. rewrite H2.
exact (mult_IZ d1).
right. elim H1; intros; elim H4; intros. rewrite H6. rewrite H2.
simpl in |- *; exact (mult_mIZ d1).
elim H1; intros; exact H2.
Qed.
intros. elim (abs_eq_or_oppZ b); intro y.
(* |b|=b *)
rewrite y.
unfold is_gcd in |- *; split.
unfold divide in |- *; unfold IdZ in |- *; split. exact I. split. exact I. left; reflexivity.
split; unfold divide in |- *; unfold IdZ in |- *. split. exact I. split. exact I.
elim (eq_OZ_dec b); intro y0.
left; exact y0.
right. split. exact y0. exists IZ. split. exact I. symmetry  in |- *; exact (mult_IZ b).
intros; exact H0.
(* |b|=(-b) *)
rewrite y.
unfold is_gcd in |- *; split.
unfold divide in |- *; unfold IdZ in |- *; split. exact I. split. exact I. left; reflexivity.
split; unfold divide in |- *; unfold IdZ in |- *; split. exact I. split. exact I.
elim (eq_OZ_dec b); intro y0.
left; exact y0.
right. split.
unfold not in |- *; intros; elim y0.
exact (opp_O Z IdZ addZ multZ OZ oppZ Z_ring b I H).
exists (oppZ IZ); split. exact I.
rewrite (mult_opp_opp Z IdZ addZ multZ OZ oppZ Z_ring b IZ I I).
symmetry  in |- *; exact (mult_IZ b). exact I. split. exact I.
elim H0; intros; elim H2; intros; elim H4; intros. rewrite H5.
left; reflexivity.
right; split. elim H5; intros; exact H6. elim H5; intros; elim H7; intros.
exists (oppZ x). split. exact I. elim H8; intros; rewrite H10.
symmetry  in |- *; exact (mult_opp_r Z IdZ addZ multZ OZ oppZ Z_ring q x I I).
Qed.
(******************)
Inductive is_gcdZ : Z -> Z -> Z -> Prop :=
| gcd_OZ : forall b : Z, is_gcdZ OZ b (absZ b)
| gcd_mod :
forall b a d q r : Z,
b <> OZ -> is_diveuclZ a b q r -> is_gcdZ r b d -> is_gcdZ b a d.
(******************)
Definition have_gcdZ (a b : Z) := {d : Z | is_gcdZ a b d}.
Definition gcdZ_i (a b : Z) := exist (is_gcdZ a b).
(* Inductive have_gcdZ [a, b: Z]: Set := gcdZ_i: (d: Z) (is_gcdZ a b d) -> (have_gcdZ a b). *)
(*******************)
Definition P (a : Z) := forall b : Z, have_gcdZ a b.
intros. elim H; intros. apply (gcd_OZ_absZ b0). unfold is_gcd in |- *.
split. elim H3; intros; elim H5; intros; exact H6.
split. elim H1; intros; elim H5; intros; elim H7; intros; rewrite H9.
apply (div_add Z IdZ addZ multZ OZ oppZ Z_ring (multZ b0 q) r d0).
elim H3; intros; elim H11; intros.
exact (div_mult Z IdZ addZ multZ OZ oppZ Z_ring b0 q d0 H12 I).
elim H3; intros; exact H10.
intros. elim H3; intros; elim H7; intros. apply (H9 q0).
cut (r = addZ a0 (oppZ (multZ b0 q))); intros. rewrite H10.
apply (div_add Z IdZ addZ multZ OZ oppZ Z_ring a0 (oppZ (multZ b0 q)) q0 H5).
apply (div_opp Z IdZ addZ multZ OZ oppZ Z_ring (multZ b0 q) q0).
exact (div_mult Z IdZ addZ multZ OZ oppZ Z_ring b0 q q0 H4 I).
elim H1; intros; elim H11; intros; elim H13; intros; rewrite H15.
elim (addZ_commutativity r (multZ b0 q)).
elim (addZ_associativity r (multZ b0 q) (oppZ (multZ b0 q))).
elim (addZ_opposite (multZ b0 q) I); intros.
elim H17; intros. elim H19; intros. rewrite H20. symmetry  in |- *. exact (add_OZ r).
exact H4.
Qed.
(*************)
Definition gcdZ (a b : Z) := pi1 Z (is_gcdZ a b) (gcdZ_exists a b).

(*******************)
Theorem gcdZ_correct : forall a b : Z, is_gcdZ a b (gcdZ a b).