summaryrefslogtreecommitdiff
path: root/theories/ZArith/Znumtheory.v
diff options
context:
space:
mode:
Diffstat (limited to 'theories/ZArith/Znumtheory.v')
-rw-r--r--theories/ZArith/Znumtheory.v810
1 files changed, 151 insertions, 659 deletions
diff --git a/theories/ZArith/Znumtheory.v b/theories/ZArith/Znumtheory.v
index 26ff4251..6eb1a709 100644
--- a/theories/ZArith/Znumtheory.v
+++ b/theories/ZArith/Znumtheory.v
@@ -1,19 +1,20 @@
(************************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011 *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2010 *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-(*i $Id: Znumtheory.v 14641 2011-11-06 11:59:10Z herbelin $ i*)
-
Require Import ZArith_base.
Require Import ZArithRing.
Require Import Zcomplements.
Require Import Zdiv.
Require Import Wf_nat.
-Open Local Scope Z_scope.
+
+(** 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 [Zdivide]
@@ -21,308 +22,173 @@ Open Local Scope Z_scope.
- Euclid algorithm [euclid]
- a relatively prime predicate [rel_prime]
- a prime predicate [prime]
- - an efficient [Zgcd] function
+ - properties of the efficient [Z.gcd] function
*)
-(** * Divisibility *)
+Notation Zgcd := Z.gcd (only parsing).
+Notation Zggcd := Z.ggcd (only parsing).
+Notation Zggcd_gcd := Z.ggcd_gcd (only parsing).
+Notation Zggcd_correct_divisors := Z.ggcd_correct_divisors (only parsing).
+Notation Zgcd_divide_l := Z.gcd_divide_l (only parsing).
+Notation Zgcd_divide_r := Z.gcd_divide_r (only parsing).
+Notation Zgcd_greatest := Z.gcd_greatest (only parsing).
+Notation Zgcd_nonneg := Z.gcd_nonneg (only parsing).
+Notation Zggcd_opp := Z.ggcd_opp (only parsing).
-Inductive Zdivide (a b:Z) : Prop :=
- Zdivide_intro : forall q:Z, b = q * a -> Zdivide a b.
+(** The former specialized inductive predicate [Zdivide] is now
+ a generic existential predicate. *)
-(** Syntax for divisibility *)
+Notation Zdivide := Z.divide (only parsing).
-Notation "( a | b )" := (Zdivide a b) (at level 0) : Z_scope.
+(** Its former constructor is now a pseudo-constructor. *)
-(** Results concerning divisibility*)
+Definition Zdivide_intro a b q (H:b=q*a) : Z.divide a b := ex_intro _ q H.
-Lemma Zdivide_refl : forall a:Z, (a | a).
-Proof.
- intros; apply Zdivide_intro with 1; ring.
-Qed.
-
-Lemma Zone_divide : forall a:Z, (1 | a).
-Proof.
- intros; apply Zdivide_intro with a; ring.
-Qed.
-
-Lemma Zdivide_0 : forall a:Z, (a | 0).
-Proof.
- intros; apply Zdivide_intro with 0; ring.
-Qed.
-
-Hint Resolve Zdivide_refl Zone_divide Zdivide_0: zarith.
-
-Lemma Zmult_divide_compat_l : forall a b c:Z, (a | b) -> (c * a | c * b).
-Proof.
- simple induction 1; intros; apply Zdivide_intro with q.
- rewrite H0; ring.
-Qed.
-
-Lemma Zmult_divide_compat_r : forall a b c:Z, (a | b) -> (a * c | b * c).
-Proof.
- intros a b c; rewrite (Zmult_comm a c); rewrite (Zmult_comm b c).
- apply Zmult_divide_compat_l; trivial.
-Qed.
-
-Hint Resolve Zmult_divide_compat_l Zmult_divide_compat_r: zarith.
-
-Lemma Zdivide_plus_r : forall a b c:Z, (a | b) -> (a | c) -> (a | b + c).
-Proof.
- simple induction 1; intros q Hq; simple induction 1; intros q' Hq'.
- apply Zdivide_intro with (q + q').
- rewrite Hq; rewrite Hq'; ring.
-Qed.
-
-Lemma Zdivide_opp_r : forall a b:Z, (a | b) -> (a | - b).
-Proof.
- simple induction 1; intros; apply Zdivide_intro with (- q).
- rewrite H0; ring.
-Qed.
-
-Lemma Zdivide_opp_r_rev : forall a b:Z, (a | - b) -> (a | b).
-Proof.
- intros; replace b with (- - b). apply Zdivide_opp_r; trivial. ring.
-Qed.
+(** Results concerning divisibility*)
-Lemma Zdivide_opp_l : forall a b:Z, (a | b) -> (- a | b).
-Proof.
- simple induction 1; intros; apply Zdivide_intro with (- q).
- rewrite H0; ring.
-Qed.
+Notation Zdivide_refl := Z.divide_refl (only parsing).
+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).
-Lemma Zdivide_opp_l_rev : forall a b:Z, (- a | b) -> (a | b).
-Proof.
- intros; replace a with (- - a). apply Zdivide_opp_l; trivial. ring.
-Qed.
+Lemma Zdivide_opp_r a b : (a | b) -> (a | - b).
+Proof. apply Z.divide_opp_r. Qed.
-Lemma Zdivide_minus_l : forall a b c:Z, (a | b) -> (a | c) -> (a | b - c).
-Proof.
- simple induction 1; intros q Hq; simple induction 1; intros q' Hq'.
- apply Zdivide_intro with (q - q').
- rewrite Hq; rewrite Hq'; ring.
-Qed.
+Lemma Zdivide_opp_r_rev a b : (a | - b) -> (a | b).
+Proof. apply Z.divide_opp_r. Qed.
-Lemma Zdivide_mult_l : forall a b c:Z, (a | b) -> (a | b * c).
-Proof.
- simple induction 1; intros q Hq; apply Zdivide_intro with (q * c).
- rewrite Hq; ring.
-Qed.
+Lemma Zdivide_opp_l a b : (a | b) -> (- a | b).
+Proof. apply Z.divide_opp_l. Qed.
-Lemma Zdivide_mult_r : forall a b c:Z, (a | c) -> (a | b * c).
-Proof.
- simple induction 1; intros q Hq; apply Zdivide_intro with (q * b).
- rewrite Hq; ring.
-Qed.
+Lemma Zdivide_opp_l_rev a b : (- a | b) -> (a | b).
+Proof. apply Z.divide_opp_l. Qed.
-Lemma Zdivide_factor_r : forall a b:Z, (a | a * b).
-Proof.
- intros; apply Zdivide_intro with b; ring.
-Qed.
+Theorem Zdivide_Zabs_l a b : (Z.abs a | b) -> (a | b).
+Proof. apply Z.divide_abs_l. Qed.
-Lemma Zdivide_factor_l : forall a b:Z, (a | b * a).
-Proof.
- intros; apply Zdivide_intro with b; ring.
-Qed.
+Theorem Zdivide_Zabs_inv_l a b : (a | b) -> (Z.abs a | b).
+Proof. apply Z.divide_abs_l. Qed.
+Hint Resolve Zdivide_refl Zone_divide Zdivide_0: zarith.
+Hint Resolve Zmult_divide_compat_l Zmult_divide_compat_r: zarith.
Hint Resolve Zdivide_plus_r Zdivide_opp_r Zdivide_opp_r_rev Zdivide_opp_l
Zdivide_opp_l_rev Zdivide_minus_l Zdivide_mult_l Zdivide_mult_r
Zdivide_factor_r Zdivide_factor_l: zarith.
(** Auxiliary result. *)
-Lemma Zmult_one : forall x y:Z, x >= 0 -> x * y = 1 -> x = 1.
+Lemma Zmult_one x y : x >= 0 -> x * y = 1 -> x = 1.
Proof.
- intros x y H H0; destruct (Zmult_1_inversion_l _ _ H0) as [Hpos| Hneg].
- assumption.
- rewrite Hneg in H; simpl in H.
- contradiction (Zle_not_lt 0 (-1)).
- apply Zge_le; assumption.
- apply Zorder.Zlt_neg_0.
+ Z.swap_greater. apply Z.eq_mul_1_nonneg.
Qed.
(** Only [1] and [-1] divide [1]. *)
-Lemma Zdivide_1 : forall x:Z, (x | 1) -> x = 1 \/ x = -1.
-Proof.
- simple induction 1; intros.
- elim (Z_lt_ge_dec 0 x); [ left | right ].
- apply Zmult_one with q; auto with zarith; rewrite H0; ring.
- assert (- x = 1); auto with zarith.
- apply Zmult_one with (- q); auto with zarith; rewrite H0; ring.
-Qed.
+Notation Zdivide_1 := Z.divide_1_r (only parsing).
(** If [a] divides [b] and [b] divides [a] then [a] is [b] or [-b]. *)
-Lemma Zdivide_antisym : forall a b:Z, (a | b) -> (b | a) -> a = b \/ a = - b.
-Proof.
- simple induction 1; intros.
- inversion H1.
- rewrite H0 in H2; clear H H1.
- case (Z_zerop a); intro.
- left; rewrite H0; rewrite e; ring.
- assert (Hqq0 : q0 * q = 1).
- apply Zmult_reg_l with a.
- assumption.
- ring_simplify.
- pattern a at 2 in |- *; rewrite H2; ring.
- assert (q | 1).
- rewrite <- Hqq0; auto with zarith.
- elim (Zdivide_1 q H); intros.
- rewrite H1 in H0; left; omega.
- rewrite H1 in H0; right; omega.
-Qed.
-
-Theorem Zdivide_trans: forall a b c, (a | b) -> (b | c) -> (a | c).
-Proof.
- intros a b c [d H1] [e H2]; exists (d * e); auto with zarith.
- rewrite H2; rewrite H1; ring.
-Qed.
+Notation Zdivide_antisym := Z.divide_antisym (only parsing).
+Notation Zdivide_trans := Z.divide_trans (only parsing).
(** If [a] divides [b] and [b<>0] then [|a| <= |b|]. *)
-Lemma Zdivide_bounds : forall a b:Z, (a | b) -> b <> 0 -> Zabs a <= Zabs b.
+Lemma Zdivide_bounds a b : (a | b) -> b <> 0 -> Z.abs a <= Z.abs b.
Proof.
- simple induction 1; intros.
- assert (Zabs b = Zabs q * Zabs a).
- subst; apply Zabs_Zmult.
- rewrite H2.
- assert (H3 := Zabs_pos q).
- assert (H4 := Zabs_pos a).
- assert (Zabs q * Zabs a >= 1 * Zabs a); auto with zarith.
- apply Zmult_ge_compat; auto with zarith.
- elim (Z_lt_ge_dec (Zabs q) 1); [ intros | auto with zarith ].
- assert (Zabs q = 0).
- omega.
- assert (q = 0).
- rewrite <- (Zabs_Zsgn q).
- rewrite H5; auto with zarith.
- subst q; omega.
+ intros H Hb.
+ rewrite <- Z.divide_abs_l, <- Z.divide_abs_r in H.
+ apply Z.abs_pos in Hb.
+ now apply Z.divide_pos_le.
Qed.
(** [Zdivide] can be expressed using [Zmod]. *)
Lemma Zmod_divide : forall a b, b<>0 -> a mod b = 0 -> (b | a).
Proof.
- intros a b NZ EQ.
- apply Zdivide_intro with (a/b).
- rewrite (Z_div_mod_eq_full a b NZ) at 1.
- rewrite EQ; ring.
+ apply Z.mod_divide.
Qed.
Lemma Zdivide_mod : forall a b, (b | a) -> a mod b = 0.
Proof.
- intros a b (c,->); apply Z_mod_mult.
+ intros a b (c,->); apply Z_mod_mult.
Qed.
(** [Zdivide] is hence decidable *)
-Lemma Zdivide_dec : forall a b:Z, {(a | b)} + {~ (a | b)}.
-Proof.
- intros a b; elim (Ztrichotomy_inf a 0).
- (* a<0 *)
- intros H; elim H; intros.
- case (Z_eq_dec (b mod - a) 0).
- left; apply Zdivide_opp_l_rev; apply Zmod_divide; auto with zarith.
- intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith.
- (* a=0 *)
- case (Z_eq_dec b 0); intro.
- left; subst; auto with zarith.
- right; subst; intro H0; inversion H0; omega.
- (* a>0 *)
- intro H; case (Z_eq_dec (b mod a) 0).
- left; apply Zmod_divide; auto with zarith.
- intro H1; right; intro; elim H1; apply Zdivide_mod; auto with zarith.
-Qed.
-
-Theorem Zdivide_Zdiv_eq: forall a b : Z,
- 0 < a -> (a | b) -> b = a * (b / a).
+Lemma Zdivide_dec a b : {(a | b)} + {~ (a | b)}.
Proof.
- intros a b Hb Hc.
- pattern b at 1; rewrite (Z_div_mod_eq b a); auto with zarith.
- rewrite (Zdivide_mod b a); auto with zarith.
-Qed.
-
-Theorem Zdivide_Zdiv_eq_2: forall a b c : Z,
- 0 < a -> (a | b) -> (c * b)/a = c * (b / a).
-Proof.
- intros a b c H1 H2.
- inversion H2 as [z Hz].
- rewrite Hz; rewrite Zmult_assoc.
- repeat rewrite Z_div_mult; auto with zarith.
-Qed.
+ destruct (Z.eq_dec a 0) as [Ha|Ha].
+ destruct (Z.eq_dec b 0) as [Hb|Hb].
+ left; subst; apply Z.divide_0_r.
+ right. subst. contradict Hb. now apply Z.divide_0_l.
+ destruct (Z.eq_dec (b mod a) 0).
+ left. now apply Z.mod_divide.
+ right. now rewrite <- Z.mod_divide.
+Defined.
-Theorem Zdivide_Zabs_l: forall a b, (Zabs a | b) -> (a | b).
+Theorem Zdivide_Zdiv_eq a b : 0 < a -> (a | b) -> b = a * (b / a).
Proof.
- intros a b [x H]; subst b.
- pattern (Zabs a); apply Zabs_intro.
- exists (- x); ring.
- exists x; ring.
+ intros Ha H.
+ rewrite (Z.div_mod b a) at 1; auto with zarith.
+ rewrite Zdivide_mod; auto with zarith.
Qed.
-Theorem Zdivide_Zabs_inv_l: forall a b, (a | b) -> (Zabs a | b).
+Theorem Zdivide_Zdiv_eq_2 a b c :
+ 0 < a -> (a | b) -> (c * b) / a = c * (b / a).
Proof.
- intros a b [x H]; subst b.
- pattern (Zabs a); apply Zabs_intro.
- exists (- x); ring.
- exists x; ring.
+ intros. apply Z.divide_div_mul_exact; auto with zarith.
Qed.
Theorem Zdivide_le: forall a b : Z,
0 <= a -> 0 < b -> (a | b) -> a <= b.
Proof.
- intros a b H1 H2 [q H3]; subst b.
- case (Zle_lt_or_eq 0 a); auto with zarith; intros H3.
- case (Zle_lt_or_eq 0 q); auto with zarith.
- apply (Zmult_le_0_reg_r a); auto with zarith.
- intros H4; apply Zle_trans with (1 * a); auto with zarith.
- intros H4; subst q; omega.
+ intros. now apply Z.divide_pos_le.
Qed.
-Theorem Zdivide_Zdiv_lt_pos: forall a b : Z,
+Theorem Zdivide_Zdiv_lt_pos a b :
1 < a -> 0 < b -> (a | b) -> 0 < b / a < b .
Proof.
- intros a b H1 H2 H3; split.
- apply Zmult_lt_reg_r with a; auto with zarith.
- rewrite (Zmult_comm (Zdiv b a)); rewrite <- Zdivide_Zdiv_eq; auto with zarith.
- apply Zmult_lt_reg_r with a; auto with zarith.
- repeat rewrite (fun x => Zmult_comm x a); auto with zarith.
+ intros H1 H2 H3; split.
+ apply Z.mul_pos_cancel_l with a; auto with zarith.
rewrite <- Zdivide_Zdiv_eq; auto with zarith.
- pattern b at 1; replace b with (1 * b); auto with zarith.
- apply Zmult_lt_compat_r; auto with zarith.
+ now apply Z.div_lt.
Qed.
-Lemma Zmod_div_mod: forall n m a, 0 < n -> 0 < m ->
- (n | m) -> a mod n = (a mod m) mod n.
+Lemma Zmod_div_mod n m a:
+ 0 < n -> 0 < m -> (n | m) -> a mod n = (a mod m) mod n.
Proof.
- intros n m a H1 H2 H3.
- pattern a at 1; rewrite (Z_div_mod_eq a m); auto with zarith.
- case H3; intros q Hq; pattern m at 1; rewrite Hq.
- rewrite (Zmult_comm q).
- rewrite Zplus_mod; auto with zarith.
- rewrite <- Zmult_assoc; rewrite Zmult_mod; auto with zarith.
- rewrite Z_mod_same; try rewrite Zmult_0_l; auto with zarith.
- rewrite (Zmod_small 0); auto with zarith.
- rewrite Zplus_0_l; rewrite Zmod_mod; auto with zarith.
+ intros H1 H2 (p,Hp).
+ rewrite (Z.div_mod a m) at 1; auto with zarith.
+ rewrite Hp at 1.
+ rewrite Z.mul_shuffle0, Z.add_comm, Z.mod_add; auto with zarith.
Qed.
-Lemma Zmod_divide_minus: forall a b c : Z, 0 < b ->
- a mod b = c -> (b | a - c).
+Lemma Zmod_divide_minus a b c:
+ 0 < b -> a mod b = c -> (b | a - c).
Proof.
- intros a b c H H1; apply Zmod_divide; auto with zarith.
+ intros H H1. apply Z.mod_divide; auto with zarith.
rewrite Zminus_mod; auto with zarith.
- rewrite H1; pattern c at 1; rewrite <- (Zmod_small c b); auto with zarith.
- rewrite Zminus_diag; apply Zmod_small; auto with zarith.
- subst; apply Z_mod_lt; auto with zarith.
+ rewrite H1. rewrite <- (Z.mod_small c b) at 1.
+ rewrite Z.sub_diag, Z.mod_0_l; auto with zarith.
+ subst. now apply Z.mod_pos_bound.
Qed.
-Lemma Zdivide_mod_minus: forall a b c : Z, 0 <= c < b ->
- (b | a - c) -> a mod b = c.
+Lemma Zdivide_mod_minus a b c:
+ 0 <= c < b -> (b | a - c) -> a mod b = c.
Proof.
- intros a b c (H1, H2) H3; assert (0 < b); try apply Zle_lt_trans with c; auto.
+ intros (H1, H2) H3.
+ assert (0 < b) by Z.order.
replace a with ((a - c) + c); auto with zarith.
- rewrite Zplus_mod; auto with zarith.
- rewrite (Zdivide_mod (a -c) b); try rewrite Zplus_0_l; auto with zarith.
- rewrite Zmod_mod; try apply Zmod_small; auto with zarith.
+ rewrite Z.add_mod; auto with zarith.
+ rewrite (Zdivide_mod (a-c) b); try rewrite Z.add_0_l; auto with zarith.
+ rewrite Z.mod_mod; try apply Zmod_small; auto with zarith.
Qed.
(** * Greatest common divisor (gcd). *)
@@ -338,12 +204,12 @@ Inductive Zis_gcd (a b d:Z) : Prop :=
(** Trivial properties of [gcd] *)
-Lemma Zis_gcd_sym : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a d.
+Lemma Zis_gcd_sym : forall a b d, Zis_gcd a b d -> Zis_gcd b a d.
Proof.
- simple induction 1; constructor; intuition.
+ induction 1; constructor; intuition.
Qed.
-Lemma Zis_gcd_0 : forall a:Z, Zis_gcd a 0 a.
+Lemma Zis_gcd_0 : forall a, Zis_gcd a 0 a.
Proof.
constructor; auto with zarith.
Qed.
@@ -358,19 +224,18 @@ Proof.
constructor; auto with zarith.
Qed.
-Lemma Zis_gcd_minus : forall a b d:Z, Zis_gcd a (- b) d -> Zis_gcd b a d.
+Lemma Zis_gcd_minus : forall a b d, Zis_gcd a (- b) d -> Zis_gcd b a d.
Proof.
- simple induction 1; constructor; intuition.
+ induction 1; constructor; intuition.
Qed.
-Lemma Zis_gcd_opp : forall a b d:Z, 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).
Proof.
- simple induction 1; constructor; intuition.
+ induction 1; constructor; intuition.
Qed.
-Lemma Zis_gcd_0_abs : forall a:Z, Zis_gcd 0 a (Zabs a).
+Lemma Zis_gcd_0_abs a : Zis_gcd 0 a (Z.abs a).
Proof.
- intros a.
apply Zabs_ind.
intros; apply Zis_gcd_sym; apply Zis_gcd_0; auto.
intros; apply Zis_gcd_opp; apply Zis_gcd_0; auto.
@@ -429,7 +294,7 @@ Section extended_euclid_algorithm.
(** The recursive part of Euclid's algorithm uses well-founded
recursion of non-negative integers. It maintains 6 integers
[u1,u2,u3,v1,v2,v3] such that the following invariant holds:
- [u1*a+u2*b=u3] and [v1*a+v2*b=v3] and [gcd(u2,v3)=gcd(a,b)].
+ [u1*a+u2*b=u3] and [v1*a+v2*b=v3] and [gcd(u3,v3)=gcd(a,b)].
*)
Lemma euclid_rec :
@@ -519,14 +384,15 @@ Qed.
Lemma Zis_gcd_mult :
forall a b c d:Z, Zis_gcd a b d -> Zis_gcd (c * a) (c * b) (c * d).
Proof.
- intros a b c d; simple induction 1; constructor; intuition.
- elim (Zis_gcd_bezout a b d H). intros.
- elim H3; intros.
- elim H4; intros.
- apply Zdivide_intro with (u * q + v * q0).
- rewrite <- H5.
+ intros a b c d; simple induction 1. constructor; auto with zarith.
+ intros x Ha Hb.
+ elim (Zis_gcd_bezout a b d H). intros u v Huv.
+ elim Ha; intros a' Ha'.
+ elim Hb; intros b' Hb'.
+ apply Zdivide_intro with (u * a' + v * b').
+ rewrite <- Huv.
replace (c * (u * a + v * b)) with (u * (c * a) + v * (c * b)).
- rewrite H6; rewrite H7; ring.
+ rewrite Ha'; rewrite Hb'; ring.
ring.
Qed.
@@ -625,14 +491,14 @@ Proof.
exists a'; auto with zarith.
exists b'; auto with zarith.
intros x (xa,H5) (xb,H6).
- destruct (H4 (x*g)).
+ destruct (H4 (x*g)) as (x',Hx').
exists xa; rewrite Zmult_assoc; rewrite <- H5; auto.
exists xb; rewrite Zmult_assoc; rewrite <- H6; auto.
- replace g with (1*g) in H7; auto with zarith.
- do 2 rewrite Zmult_assoc in H7.
- generalize (Zmult_reg_r _ _ _ H2 H7); clear H7; intros.
- rewrite Zmult_1_r in H7.
- exists q; auto with zarith.
+ replace g with (1*g) in Hx'; auto with zarith.
+ do 2 rewrite Zmult_assoc in Hx'.
+ apply Zmult_reg_r in Hx'; trivial.
+ rewrite Zmult_1_r in Hx'.
+ exists x'; auto with zarith.
Qed.
Theorem rel_prime_sym: forall a b, rel_prime a b -> rel_prime b a.
@@ -875,249 +741,62 @@ Proof.
contradict Hp; auto with zarith.
Qed.
+(** we now prove that [Z.gcd] is indeed a gcd in
+ the sense of [Zis_gcd]. *)
-(** We could obtain a [Zgcd] function via Euclid algorithm. But we propose
- here a binary version of [Zgcd], faster and executable within Coq.
-
- Algorithm:
-
- gcd 0 b = b
- gcd a 0 = a
- gcd (2a) (2b) = 2(gcd a b)
- gcd (2a+1) (2b) = gcd (2a+1) b
- gcd (2a) (2b+1) = gcd a (2b+1)
- gcd (2a+1) (2b+1) = gcd (b-a) (2*a+1)
- or gcd (a-b) (2*b+1), depending on whether a<b
-*)
+Notation Zgcd_is_pos := Z.gcd_nonneg (only parsing).
-Open Scope positive_scope.
-
-Fixpoint Pgcdn (n: nat) (a b : positive) : positive :=
- match n with
- | O => 1
- | S n =>
- match a,b with
- | xH, _ => 1
- | _, xH => 1
- | xO a, xO b => xO (Pgcdn n a b)
- | a, xO b => Pgcdn n a b
- | xO a, b => Pgcdn n a b
- | xI a', xI b' =>
- match Pcompare a' b' Eq with
- | Eq => a
- | Lt => Pgcdn n (b'-a') a
- | Gt => Pgcdn n (a'-b') b
- end
- end
- end.
-
-Definition Pgcd (a b: positive) := Pgcdn (Psize a + Psize b)%nat a b.
-
-Close Scope positive_scope.
-
-Definition Zgcd (a b : Z) : Z :=
- match a,b with
- | Z0, _ => Zabs b
- | _, Z0 => Zabs a
- | Zpos a, Zpos b => Zpos (Pgcd a b)
- | Zpos a, Zneg b => Zpos (Pgcd a b)
- | Zneg a, Zpos b => Zpos (Pgcd a b)
- | Zneg a, Zneg b => Zpos (Pgcd a b)
- end.
-
-Lemma Zgcd_is_pos : forall a b, 0 <= Zgcd a b.
+Lemma Zgcd_is_gcd : forall a b, Zis_gcd a b (Z.gcd a b).
Proof.
- unfold Zgcd; destruct a; destruct b; auto with zarith.
-Qed.
-
-Lemma Zis_gcd_even_odd : forall a b g, Zis_gcd (Zpos a) (Zpos (xI b)) g ->
- Zis_gcd (Zpos (xO a)) (Zpos (xI b)) g.
-Proof.
- intros.
- destruct H.
- constructor; auto.
- destruct H as (e,H2); exists (2*e); auto with zarith.
- rewrite Zpos_xO; rewrite H2; ring.
- intros.
- apply H1; auto.
- rewrite Zpos_xO in H2.
- rewrite Zpos_xI in H3.
- apply Gauss with 2; auto.
- apply bezout_rel_prime.
- destruct H3 as (bb, H3).
- apply Bezout_intro with bb (-Zpos b).
- omega.
-Qed.
-
-Lemma Pgcdn_correct : forall n a b, (Psize a + Psize b<=n)%nat ->
- Zis_gcd (Zpos a) (Zpos b) (Zpos (Pgcdn n a b)).
-Proof.
- intro n; pattern n; apply lt_wf_ind; clear n; intros.
- destruct n.
- simpl.
- destruct a; simpl in *; try inversion H0.
- destruct a.
- destruct b; simpl.
- case_eq (Pcompare a b Eq); intros.
- (* a = xI, b = xI, compare = Eq *)
- rewrite (Pcompare_Eq_eq _ _ H1); apply Zis_gcd_refl.
- (* a = xI, b = xI, compare = Lt *)
- apply Zis_gcd_sym.
- apply Zis_gcd_for_euclid with 1.
- apply Zis_gcd_sym.
- replace (Zpos (xI b) - 1 * Zpos (xI a)) with (Zpos(xO (b - a))).
- apply Zis_gcd_even_odd.
- apply H; auto.
- simpl in *.
- assert (Psize (b-a) <= Psize b)%nat.
- apply Psize_monotone.
- change (Zpos (b-a) < Zpos b).
- rewrite (Zpos_minus_morphism _ _ H1).
- assert (0 < Zpos a) by (compute; auto).
- omega.
- omega.
- rewrite Zpos_xO; do 2 rewrite Zpos_xI.
- rewrite Zpos_minus_morphism; auto.
- omega.
- (* a = xI, b = xI, compare = Gt *)
- apply Zis_gcd_for_euclid with 1.
- replace (Zpos (xI a) - 1 * Zpos (xI b)) with (Zpos(xO (a - b))).
- apply Zis_gcd_sym.
- apply Zis_gcd_even_odd.
- apply H; auto.
- simpl in *.
- assert (Psize (a-b) <= Psize a)%nat.
- apply Psize_monotone.
- change (Zpos (a-b) < Zpos a).
- rewrite (Zpos_minus_morphism b a).
- assert (0 < Zpos b) by (compute; auto).
- omega.
- rewrite ZC4; rewrite H1; auto.
- omega.
- rewrite Zpos_xO; do 2 rewrite Zpos_xI.
- rewrite Zpos_minus_morphism; auto.
- omega.
- rewrite ZC4; rewrite H1; auto.
- (* a = xI, b = xO *)
- apply Zis_gcd_sym.
- apply Zis_gcd_even_odd.
- apply Zis_gcd_sym.
- apply H; auto.
- simpl in *; omega.
- (* a = xI, b = xH *)
- apply Zis_gcd_1.
- destruct b; simpl.
- (* a = xO, b = xI *)
- apply Zis_gcd_even_odd.
- apply H; auto.
- simpl in *; omega.
- (* a = xO, b = xO *)
- rewrite (Zpos_xO a); rewrite (Zpos_xO b); rewrite (Zpos_xO (Pgcdn n a b)).
- apply Zis_gcd_mult.
- apply H; auto.
- simpl in *; omega.
- (* a = xO, b = xH *)
- apply Zis_gcd_1.
- (* a = xH *)
- simpl; apply Zis_gcd_sym; apply Zis_gcd_1.
-Qed.
-
-Lemma Pgcd_correct : forall a b, Zis_gcd (Zpos a) (Zpos b) (Zpos (Pgcd a b)).
-Proof.
- unfold Pgcd; intros.
- apply Pgcdn_correct; auto.
-Qed.
-
-Lemma Zgcd_is_gcd : forall a b, Zis_gcd a b (Zgcd a b).
-Proof.
- destruct a.
- intros.
- simpl.
- apply Zis_gcd_0_abs.
- destruct b; simpl.
- apply Zis_gcd_0.
- apply Pgcd_correct.
- apply Zis_gcd_sym.
- apply Zis_gcd_minus; simpl.
- apply Pgcd_correct.
- destruct b; simpl.
- apply Zis_gcd_minus; simpl.
- apply Zis_gcd_sym.
- apply Zis_gcd_0.
- apply Zis_gcd_minus; simpl.
- apply Zis_gcd_sym.
- apply Pgcd_correct.
- apply Zis_gcd_sym.
- apply Zis_gcd_minus; simpl.
- apply Zis_gcd_minus; simpl.
- apply Zis_gcd_sym.
- apply Pgcd_correct.
+ constructor.
+ apply Z.gcd_divide_l.
+ apply Z.gcd_divide_r.
+ apply Z.gcd_greatest.
Qed.
Theorem Zgcd_spec : forall x y : Z, {z : Z | Zis_gcd x y z /\ 0 <= z}.
Proof.
- intros x y; exists (Zgcd x y).
- split; [apply Zgcd_is_gcd | apply Zgcd_is_pos].
+ intros x y; exists (Z.gcd x y).
+ split; [apply Zgcd_is_gcd | apply Z.gcd_nonneg].
Qed.
Theorem Zdivide_Zgcd: forall p q r : Z,
- (p | q) -> (p | r) -> (p | Zgcd q r).
+ (p | q) -> (p | r) -> (p | Z.gcd q r).
Proof.
- intros p q r H1 H2.
- assert (H3: (Zis_gcd q r (Zgcd q r))).
- apply Zgcd_is_gcd.
- inversion_clear H3; auto.
+ intros. now apply Z.gcd_greatest.
Qed.
Theorem Zis_gcd_gcd: forall a b c : Z,
- 0 <= c -> Zis_gcd a b c -> Zgcd a b = c.
+ 0 <= c -> Zis_gcd a b c -> Z.gcd a b = c.
Proof.
intros a b c H1 H2.
case (Zis_gcd_uniqueness_apart_sign a b c (Zgcd a b)); auto.
apply Zgcd_is_gcd; auto.
- case Zle_lt_or_eq with (1 := H1); clear H1; intros H1; subst; auto.
- intros H3; subst.
- generalize (Zgcd_is_pos a b); auto with zarith.
- case (Zgcd a b); simpl; auto; intros; discriminate.
-Qed.
-
-Theorem Zgcd_inv_0_l: forall x y, Zgcd x y = 0 -> x = 0.
-Proof.
- intros x y H.
- assert (F1: Zdivide 0 x).
- rewrite <- H.
- generalize (Zgcd_is_gcd x y); intros HH; inversion HH; auto.
- inversion F1 as [z H1].
- rewrite H1; ring.
+ Z.le_elim H1.
+ generalize (Z.gcd_nonneg a b); auto with zarith.
+ subst. now case (Z.gcd a b).
Qed.
-Theorem Zgcd_inv_0_r: forall x y, Zgcd x y = 0 -> y = 0.
-Proof.
- intros x y H.
- assert (F1: Zdivide 0 y).
- rewrite <- H.
- generalize (Zgcd_is_gcd x y); intros HH; inversion HH; auto.
- inversion F1 as [z H1].
- rewrite H1; ring.
-Qed.
+Notation Zgcd_inv_0_l := Z.gcd_eq_0_l (only parsing).
+Notation Zgcd_inv_0_r := Z.gcd_eq_0_r (only parsing).
Theorem Zgcd_div_swap0 : forall a b : Z,
- 0 < Zgcd a b ->
+ 0 < Z.gcd a b ->
0 < b ->
- (a / Zgcd a b) * b = a * (b/Zgcd a b).
+ (a / Z.gcd a b) * b = a * (b/Z.gcd a b).
Proof.
intros a b Hg Hb.
assert (F := Zgcd_is_gcd a b); inversion F as [F1 F2 F3].
- pattern b at 2; rewrite (Zdivide_Zdiv_eq (Zgcd a b) b); auto.
+ pattern b at 2; rewrite (Zdivide_Zdiv_eq (Z.gcd a b) b); auto.
repeat rewrite Zmult_assoc; f_equal.
rewrite Zmult_comm.
rewrite <- Zdivide_Zdiv_eq; auto.
Qed.
Theorem Zgcd_div_swap : forall a b c : Z,
- 0 < Zgcd a b ->
+ 0 < Z.gcd a b ->
0 < b ->
- (c * a) / Zgcd a b * b = c * a * (b/Zgcd a b).
+ (c * a) / Z.gcd a b * b = c * a * (b/Z.gcd a b).
Proof.
intros a b c Hg Hb.
assert (F := Zgcd_is_gcd a b); inversion F as [F1 F2 F3].
@@ -1129,44 +808,21 @@ Proof.
rewrite <- Zdivide_Zdiv_eq; auto.
Qed.
-Lemma Zgcd_comm : forall a b, Zgcd a b = Zgcd b a.
-Proof.
- intros.
- apply Zis_gcd_gcd.
- apply Zgcd_is_pos.
- apply Zis_gcd_sym.
- apply Zgcd_is_gcd.
-Qed.
-
-Lemma Zgcd_ass : forall a b c, Zgcd (Zgcd a b) c = Zgcd a (Zgcd b c).
-Proof.
- intros.
- apply Zis_gcd_gcd.
- apply Zgcd_is_pos.
- destruct (Zgcd_is_gcd a b).
- destruct (Zgcd_is_gcd b c).
- destruct (Zgcd_is_gcd a (Zgcd b c)).
- constructor; eauto using Zdivide_trans.
-Qed.
+Notation Zgcd_comm := Z.gcd_comm (only parsing).
-Lemma Zgcd_Zabs : forall a b, Zgcd (Zabs a) b = Zgcd a b.
+Lemma Zgcd_ass a b c : Zgcd (Zgcd a b) c = Zgcd a (Zgcd b c).
Proof.
- destruct a; simpl; auto.
+ symmetry. apply Z.gcd_assoc.
Qed.
-Lemma Zgcd_0 : forall a, Zgcd a 0 = Zabs a.
-Proof.
- destruct a; simpl; auto.
-Qed.
+Notation Zgcd_Zabs := Z.gcd_abs_l (only parsing).
+Notation Zgcd_0 := Z.gcd_0_r (only parsing).
+Notation Zgcd_1 := Z.gcd_1_r (only parsing).
-Lemma Zgcd_1 : forall a, Zgcd a 1 = 1.
-Proof.
- intros; apply Zis_gcd_gcd; auto with zarith; apply Zis_gcd_1.
-Qed.
Hint Resolve Zgcd_0 Zgcd_1 : zarith.
Theorem Zgcd_1_rel_prime : forall a b,
- Zgcd a b = 1 <-> rel_prime a b.
+ Z.gcd a b = 1 <-> rel_prime a b.
Proof.
unfold rel_prime; split; intro H.
rewrite <- H; apply Zgcd_is_gcd.
@@ -1249,167 +905,3 @@ Proof.
absurd (n = 0); auto with zarith.
case Hr1; auto with zarith.
Qed.
-
-(** A Generalized Gcd that also computes Bezout coefficients.
- The algorithm is the same as for Zgcd. *)
-
-Open Scope positive_scope.
-
-Fixpoint Pggcdn (n: nat) (a b : positive) : (positive*(positive*positive)) :=
- match n with
- | O => (1,(a,b))
- | S n =>
- match a,b with
- | xH, b => (1,(1,b))
- | a, xH => (1,(a,1))
- | xO a, xO b =>
- let (g,p) := Pggcdn n a b in
- (xO g,p)
- | a, xO b =>
- let (g,p) := Pggcdn n a b in
- let (aa,bb) := p in
- (g,(aa, xO bb))
- | xO a, b =>
- let (g,p) := Pggcdn n a b in
- let (aa,bb) := p in
- (g,(xO aa, bb))
- | xI a', xI b' =>
- match Pcompare a' b' Eq with
- | Eq => (a,(1,1))
- | Lt =>
- let (g,p) := Pggcdn n (b'-a') a in
- let (ba,aa) := p in
- (g,(aa, aa + xO ba))
- | Gt =>
- let (g,p) := Pggcdn n (a'-b') b in
- let (ab,bb) := p in
- (g,(bb+xO ab, bb))
- end
- end
- end.
-
-Definition Pggcd (a b: positive) := Pggcdn (Psize a + Psize b)%nat a b.
-
-Open Scope Z_scope.
-
-Definition Zggcd (a b : Z) : Z*(Z*Z) :=
- match a,b with
- | Z0, _ => (Zabs b,(0, Zsgn b))
- | _, Z0 => (Zabs a,(Zsgn a, 0))
- | Zpos a, Zpos b =>
- let (g,p) := Pggcd a b in
- let (aa,bb) := p in
- (Zpos g, (Zpos aa, Zpos bb))
- | Zpos a, Zneg b =>
- let (g,p) := Pggcd a b in
- let (aa,bb) := p in
- (Zpos g, (Zpos aa, Zneg bb))
- | Zneg a, Zpos b =>
- let (g,p) := Pggcd a b in
- let (aa,bb) := p in
- (Zpos g, (Zneg aa, Zpos bb))
- | Zneg a, Zneg b =>
- let (g,p) := Pggcd a b in
- let (aa,bb) := p in
- (Zpos g, (Zneg aa, Zneg bb))
- end.
-
-
-Lemma Pggcdn_gcdn : forall n a b,
- fst (Pggcdn n a b) = Pgcdn n a b.
-Proof.
- induction n.
- simpl; auto.
- destruct a; destruct b; simpl; auto.
- destruct (Pcompare a b Eq); simpl; auto.
- rewrite <- IHn; destruct (Pggcdn n (b-a) (xI a)) as (g,(aa,bb)); simpl; auto.
- rewrite <- IHn; destruct (Pggcdn n (a-b) (xI b)) as (g,(aa,bb)); simpl; auto.
- rewrite <- IHn; destruct (Pggcdn n (xI a) b) as (g,(aa,bb)); simpl; auto.
- rewrite <- IHn; destruct (Pggcdn n a (xI b)) as (g,(aa,bb)); simpl; auto.
- rewrite <- IHn; destruct (Pggcdn n a b) as (g,(aa,bb)); simpl; auto.
-Qed.
-
-Lemma Pggcd_gcd : forall a b, fst (Pggcd a b) = Pgcd a b.
-Proof.
- intros; exact (Pggcdn_gcdn (Psize a+Psize b)%nat a b).
-Qed.
-
-Lemma Zggcd_gcd : forall a b, fst (Zggcd a b) = Zgcd a b.
-Proof.
- destruct a; destruct b; simpl; auto; rewrite <- Pggcd_gcd;
- destruct (Pggcd p p0) as (g,(aa,bb)); simpl; auto.
-Qed.
-
-Open Scope positive_scope.
-
-Lemma Pggcdn_correct_divisors : forall n a b,
- let (g,p) := Pggcdn n a b in
- let (aa,bb):=p in
- (a=g*aa) /\ (b=g*bb).
-Proof.
- induction n.
- simpl; auto.
- destruct a; destruct b; simpl; auto.
- case_eq (Pcompare a b Eq); intros.
- (* Eq *)
- rewrite Pmult_comm; simpl; auto.
- rewrite (Pcompare_Eq_eq _ _ H); auto.
- (* Lt *)
- generalize (IHn (b-a) (xI a)); destruct (Pggcdn n (b-a) (xI a)) as (g,(ba,aa)); simpl.
- intros (H0,H1); split; auto.
- rewrite Pmult_plus_distr_l.
- rewrite Pmult_xO_permute_r.
- rewrite <- H1; rewrite <- H0.
- simpl; f_equal; symmetry.
- apply Pplus_minus; auto.
- rewrite ZC4; rewrite H; auto.
- (* Gt *)
- generalize (IHn (a-b) (xI b)); destruct (Pggcdn n (a-b) (xI b)) as (g,(ab,bb)); simpl.
- intros (H0,H1); split; auto.
- rewrite Pmult_plus_distr_l.
- rewrite Pmult_xO_permute_r.
- rewrite <- H1; rewrite <- H0.
- simpl; f_equal; symmetry.
- apply Pplus_minus; auto.
- (* Then... *)
- generalize (IHn (xI a) b); destruct (Pggcdn n (xI a) b) as (g,(ab,bb)); simpl.
- intros (H0,H1); split; auto.
- rewrite Pmult_xO_permute_r; rewrite H1; auto.
- generalize (IHn a (xI b)); destruct (Pggcdn n a (xI b)) as (g,(ab,bb)); simpl.
- intros (H0,H1); split; auto.
- rewrite Pmult_xO_permute_r; rewrite H0; auto.
- generalize (IHn a b); destruct (Pggcdn n a b) as (g,(ab,bb)); simpl.
- intros (H0,H1); split; subst; auto.
-Qed.
-
-Lemma Pggcd_correct_divisors : forall a b,
- let (g,p) := Pggcd a b in
- let (aa,bb):=p in
- (a=g*aa) /\ (b=g*bb).
-Proof.
- intros a b; exact (Pggcdn_correct_divisors (Psize a + Psize b)%nat a b).
-Qed.
-
-Close Scope positive_scope.
-
-Lemma Zggcd_correct_divisors : forall a b,
- let (g,p) := Zggcd a b in
- let (aa,bb):=p in
- (a=g*aa) /\ (b=g*bb).
-Proof.
- destruct a; destruct b; simpl; auto; try solve [rewrite Pmult_comm; simpl; auto];
- generalize (Pggcd_correct_divisors p p0); destruct (Pggcd p p0) as (g,(aa,bb));
- destruct 1; subst; auto.
-Qed.
-
-Theorem Zggcd_opp: forall x y,
- Zggcd (-x) y = let (p1,p) := Zggcd x y in
- let (p2,p3) := p in
- (p1,(-p2,p3)).
-Proof.
-intros [|x|x] [|y|y]; unfold Zggcd, Zopp; auto.
-case Pggcd; intros p1 (p2, p3); auto.
-case Pggcd; intros p1 (p2, p3); auto.
-case Pggcd; intros p1 (p2, p3); auto.
-case Pggcd; intros p1 (p2, p3); auto.
-Qed.