(************************************************************************)
(*         *   The Coq Proof Assistant / The Coq Development Team       *)
(*  v      *   INRIA, CNRS and contributors - Copyright 1999-2018       *)
(* <O___,, *       (see CREDITS file for the list of authors)           *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
(** For compatibility reasons, this Open Scope isn't local as it should *)
Open Scope Z_scope.
(** This file contains some notions of number theory upon Z numbers: - a divisibility predicate [Z.divide] - a gcd predicate [gcd] - Euclid algorithm [euclid] - a relatively prime predicate [rel_prime] - a prime predicate [prime] - properties of the efficient [Z.gcd] function *)
(** The former specialized inductive predicate [Z.divide] is now a generic existential predicate. *)
(** Its former constructor is now a pseudo-constructor. *)
Definition Zdivide_intro a b q (H:b=q*a) : Z.divide a b := ex_intro _ q H.
(** Results concerning divisibility*)
Notation Zone_divide := Z.divide_1_l (only parsing).
Notation Zdivide_0 := Z.divide_0_r (only parsing).
Notation Zmult_divide_compat_l := Z.mul_divide_mono_l (only parsing).
Notation Zmult_divide_compat_r := Z.mul_divide_mono_r (only parsing).
Notation Zdivide_plus_r := Z.divide_add_r (only parsing).
Notation Zdivide_minus_l := Z.divide_sub_r (only parsing).
Notation Zdivide_mult_l := Z.divide_mul_l (only parsing).
Notation Zdivide_mult_r := Z.divide_mul_r (only parsing).
Notation Zdivide_factor_r := Z.divide_factor_l (only parsing).
Notation Zdivide_factor_l := Z.divide_factor_r (only parsing).
(** Only [1] and [-1] divide [1]. *)
Notation Zdivide_1 := Z.divide_1_r (only parsing).
(** If [a] divides [b] and [b<>0] then [|a| <= |b|]. *)
(** [Z.divide] can be expressed using [Z.modulo]. *)
(** [Z.divide] is hence decidable *)
(** * 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.
(** Trivial properties of [gcd] *)
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).