diff options
author | Samuel Mimram <smimram@debian.org> | 2006-11-21 21:38:49 +0000 |
---|---|---|
committer | Samuel Mimram <smimram@debian.org> | 2006-11-21 21:38:49 +0000 |
commit | 208a0f7bfa5249f9795e6e225f309cbe715c0fad (patch) | |
tree | 591e9e512063e34099782e2518573f15ffeac003 /theories/ZArith/Znumtheory.v | |
parent | de0085539583f59dc7c4bf4e272e18711d565466 (diff) |
Imported Upstream version 8.1~gammaupstream/8.1.gamma
Diffstat (limited to 'theories/ZArith/Znumtheory.v')
-rw-r--r-- | theories/ZArith/Znumtheory.v | 1066 |
1 files changed, 534 insertions, 532 deletions
diff --git a/theories/ZArith/Znumtheory.v b/theories/ZArith/Znumtheory.v index e722b679..d89ec052 100644 --- a/theories/ZArith/Znumtheory.v +++ b/theories/ZArith/Znumtheory.v @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(*i $Id: Znumtheory.v 8990 2006-06-26 13:57:44Z notin $ i*) +(*i $Id: Znumtheory.v 9245 2006-10-17 12:53:34Z notin $ i*) Require Import ZArith_base. Require Import ZArithRing. @@ -38,91 +38,91 @@ Notation "( a | b )" := (Zdivide a b) (at level 0) : Z_scope. Lemma Zdivide_refl : forall a:Z, (a | a). Proof. -intros; apply Zdivide_intro with 1; ring. + intros; apply Zdivide_intro with 1; ring. Qed. Lemma Zone_divide : forall a:Z, (1 | a). Proof. -intros; apply Zdivide_intro with a; ring. + intros; apply Zdivide_intro with a; ring. Qed. Lemma Zdivide_0 : forall a:Z, (a | 0). Proof. -intros; apply Zdivide_intro with 0; ring. + 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. + 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. + 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. + 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. + 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. + intros; replace b with (- - b). apply Zdivide_opp_r; trivial. ring. Qed. 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. + simple induction 1; intros; apply Zdivide_intro with (- q). + rewrite H0; ring. Qed. 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. + intros; replace a with (- - a). apply Zdivide_opp_l; trivial. ring. 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. + 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_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. + simple induction 1; intros q Hq; apply Zdivide_intro with (q * c). + rewrite Hq; ring. 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. + simple induction 1; intros q Hq; apply Zdivide_intro with (q * b). + rewrite Hq; ring. Qed. Lemma Zdivide_factor_r : forall a b:Z, (a | a * b). Proof. -intros; apply Zdivide_intro with b; ring. + intros; apply Zdivide_intro with b; ring. Qed. Lemma Zdivide_factor_l : forall a b:Z, (a | b * a). Proof. -intros; apply Zdivide_intro with b; ring. + intros; apply Zdivide_intro with b; ring. Qed. Hint Resolve Zdivide_plus_r Zdivide_opp_r Zdivide_opp_r_rev Zdivide_opp_l @@ -133,7 +133,7 @@ Hint Resolve Zdivide_plus_r Zdivide_opp_r Zdivide_opp_r_rev Zdivide_opp_l Lemma Zmult_one : forall x y:Z, x >= 0 -> x * y = 1 -> x = 1. Proof. -intros x y H H0; destruct (Zmult_1_inversion_l _ _ H0) as [Hpos| Hneg]. + 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)). @@ -145,11 +145,11 @@ Qed. 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. + 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. (** If [a] divides [b] and [b] divides [a] then [a] is [b] or [-b]. *) @@ -164,7 +164,7 @@ left; rewrite H0; rewrite e; ring. assert (Hqq0 : q0 * q = 1). apply Zmult_reg_l with a. assumption. -ring. +ring_simplify. pattern a at 2 in |- *; rewrite H2; ring. assert (q | 1). rewrite <- Hqq0; auto with zarith. @@ -177,21 +177,21 @@ Qed. Lemma Zdivide_bounds : forall a b:Z, (a | b) -> b <> 0 -> Zabs a <= Zabs 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. + 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. Qed. (** * Greatest common divisor (gcd). *) @@ -201,48 +201,48 @@ Qed. (We show later that the [gcd] is actually unique if we discard its sign.) *) Inductive Zis_gcd (a b d:Z) : Prop := - Zis_gcd_intro : - (d | a) -> - (d | b) -> (forall x:Z, (x | a) -> (x | b) -> (x | d)) -> Zis_gcd a b d. + Zis_gcd_intro : + (d | a) -> + (d | b) -> (forall x:Z, (x | a) -> (x | b) -> (x | d)) -> Zis_gcd a b d. (** Trivial properties of [gcd] *) Lemma Zis_gcd_sym : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a d. Proof. -simple induction 1; constructor; intuition. + simple induction 1; constructor; intuition. Qed. Lemma Zis_gcd_0 : forall a:Z, Zis_gcd a 0 a. Proof. -constructor; auto with zarith. + constructor; auto with zarith. Qed. Lemma Zis_gcd_1 : forall a, Zis_gcd a 1 1. Proof. -constructor; auto with zarith. + constructor; auto with zarith. Qed. Lemma Zis_gcd_refl : forall a, Zis_gcd a a a. Proof. -constructor; auto with zarith. + constructor; auto with zarith. Qed. Lemma Zis_gcd_minus : forall a b d:Z, Zis_gcd a (- b) d -> Zis_gcd b a d. Proof. -simple induction 1; constructor; intuition. + simple induction 1; constructor; intuition. Qed. Lemma Zis_gcd_opp : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a (- d). Proof. -simple induction 1; constructor; intuition. + simple induction 1; constructor; intuition. Qed. Lemma Zis_gcd_0_abs : forall a:Z, Zis_gcd 0 a (Zabs 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. + 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. Qed. Hint Resolve Zis_gcd_sym Zis_gcd_0 Zis_gcd_minus Zis_gcd_opp: zarith. @@ -253,18 +253,18 @@ Hint Resolve Zis_gcd_sym Zis_gcd_0 Zis_gcd_minus Zis_gcd_opp: zarith. the following property. *) Lemma Zis_gcd_for_euclid : - forall a b d q:Z, Zis_gcd b (a - q * b) d -> Zis_gcd a b d. + forall a b d q:Z, Zis_gcd b (a - q * b) d -> Zis_gcd a b d. Proof. -simple induction 1; constructor; intuition. -replace a with (a - q * b + q * b). auto with zarith. ring. + simple induction 1; constructor; intuition. + replace a with (a - q * b + q * b). auto with zarith. ring. Qed. Lemma Zis_gcd_for_euclid2 : - forall b d q r:Z, Zis_gcd r b d -> Zis_gcd b (b * q + r) d. + forall b d q r:Z, Zis_gcd r b d -> Zis_gcd b (b * q + r) d. Proof. -simple induction 1; constructor; intuition. -apply H2; auto. -replace r with (b * q + r - b * q). auto with zarith. ring. + simple induction 1; constructor; intuition. + apply H2; auto. + replace r with (b * q + r - b * q). auto with zarith. ring. Qed. (** We implement the extended version of Euclid's algorithm, @@ -274,117 +274,117 @@ Qed. Section extended_euclid_algorithm. -Variables a b : Z. + Variables a b : Z. -(** The specification of Euclid's algorithm is the existence of - [u], [v] and [d] such that [ua+vb=d] and [(gcd a b d)]. *) + (** The specification of Euclid's algorithm is the existence of + [u], [v] and [d] such that [ua+vb=d] and [(gcd a b d)]. *) -Inductive Euclid : Set := + Inductive Euclid : Set := Euclid_intro : - forall u v d:Z, u * a + v * b = d -> Zis_gcd a b d -> Euclid. - -(** 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)]. - *) - -Lemma euclid_rec : - forall v3:Z, - 0 <= v3 -> - forall u1 u2 u3 v1 v2:Z, - u1 * a + u2 * b = u3 -> - v1 * a + v2 * b = v3 -> - (forall d:Z, Zis_gcd u3 v3 d -> Zis_gcd a b d) -> Euclid. -Proof. -intros v3 Hv3; generalize Hv3; pattern v3 in |- *. -apply Zlt_0_rec. -clear v3 Hv3; intros. -elim (Z_zerop x); intro. -apply Euclid_intro with (u := u1) (v := u2) (d := u3). -assumption. -apply H3. -rewrite a0; auto with zarith. -set (q := u3 / x) in *. -assert (Hq : 0 <= u3 - q * x < x). -replace (u3 - q * x) with (u3 mod x). -apply Z_mod_lt; omega. -assert (xpos : x > 0). omega. -generalize (Z_div_mod_eq u3 x xpos). -unfold q in |- *. -intro eq; pattern u3 at 2 in |- *; rewrite eq; ring. -apply (H (u3 - q * x) Hq (proj1 Hq) v1 v2 x (u1 - q * v1) (u2 - q * v2)). -tauto. -replace ((u1 - q * v1) * a + (u2 - q * v2) * b) with - (u1 * a + u2 * b - q * (v1 * a + v2 * b)). -rewrite H1; rewrite H2; trivial. -ring. -intros; apply H3. -apply Zis_gcd_for_euclid with q; assumption. -assumption. -Qed. - -(** We get Euclid's algorithm by applying [euclid_rec] on - [1,0,a,0,1,b] when [b>=0] and [1,0,a,0,-1,-b] when [b<0]. *) - -Lemma euclid : Euclid. -Proof. -case (Z_le_gt_dec 0 b); intro. -intros; - apply euclid_rec with - (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := 1) (v3 := b); - auto with zarith; ring. -intros; - apply euclid_rec with - (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := -1) (v3 := - b); - auto with zarith; try ring. -Qed. + forall u v d:Z, u * a + v * b = d -> Zis_gcd a b d -> Euclid. + + (** 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)]. + *) + + Lemma euclid_rec : + forall v3:Z, + 0 <= v3 -> + forall u1 u2 u3 v1 v2:Z, + u1 * a + u2 * b = u3 -> + v1 * a + v2 * b = v3 -> + (forall d:Z, Zis_gcd u3 v3 d -> Zis_gcd a b d) -> Euclid. + Proof. + intros v3 Hv3; generalize Hv3; pattern v3 in |- *. + apply Zlt_0_rec. + clear v3 Hv3; intros. + elim (Z_zerop x); intro. + apply Euclid_intro with (u := u1) (v := u2) (d := u3). + assumption. + apply H3. + rewrite a0; auto with zarith. + set (q := u3 / x) in *. + assert (Hq : 0 <= u3 - q * x < x). + replace (u3 - q * x) with (u3 mod x). + apply Z_mod_lt; omega. + assert (xpos : x > 0). omega. + generalize (Z_div_mod_eq u3 x xpos). + unfold q in |- *. + intro eq; pattern u3 at 2 in |- *; rewrite eq; ring. + apply (H (u3 - q * x) Hq (proj1 Hq) v1 v2 x (u1 - q * v1) (u2 - q * v2)). + tauto. + replace ((u1 - q * v1) * a + (u2 - q * v2) * b) with + (u1 * a + u2 * b - q * (v1 * a + v2 * b)). + rewrite H1; rewrite H2; trivial. + ring. + intros; apply H3. + apply Zis_gcd_for_euclid with q; assumption. + assumption. + Qed. + + (** We get Euclid's algorithm by applying [euclid_rec] on + [1,0,a,0,1,b] when [b>=0] and [1,0,a,0,-1,-b] when [b<0]. *) + + Lemma euclid : Euclid. + Proof. + case (Z_le_gt_dec 0 b); intro. + intros; + apply euclid_rec with + (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := 1) (v3 := b); + auto with zarith; ring. + intros; + apply euclid_rec with + (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := -1) (v3 := - b); + auto with zarith; try ring. + Qed. End extended_euclid_algorithm. Theorem Zis_gcd_uniqueness_apart_sign : - forall a b d d':Z, Zis_gcd a b d -> Zis_gcd a b d' -> d = d' \/ d = - d'. + forall a b d d':Z, Zis_gcd a b d -> Zis_gcd a b d' -> d = d' \/ d = - d'. Proof. -simple induction 1. -intros H1 H2 H3; simple induction 1; intros. -generalize (H3 d' H4 H5); intro Hd'd. -generalize (H6 d H1 H2); intro Hdd'. -exact (Zdivide_antisym d d' Hdd' Hd'd). + simple induction 1. + intros H1 H2 H3; simple induction 1; intros. + generalize (H3 d' H4 H5); intro Hd'd. + generalize (H6 d H1 H2); intro Hdd'. + exact (Zdivide_antisym d d' Hdd' Hd'd). Qed. (** * Bezout's coefficients *) Inductive Bezout (a b d:Z) : Prop := - Bezout_intro : forall u v:Z, u * a + v * b = d -> Bezout a b d. + Bezout_intro : forall u v:Z, u * a + v * b = d -> Bezout a b d. (** Existence of Bezout's coefficients for the [gcd] of [a] and [b] *) Lemma Zis_gcd_bezout : forall a b d:Z, Zis_gcd a b d -> Bezout a b d. Proof. -intros a b d Hgcd. -elim (euclid a b); intros u v d0 e g. -generalize (Zis_gcd_uniqueness_apart_sign a b d d0 Hgcd g). -intro H; elim H; clear H; intros. -apply Bezout_intro with u v. -rewrite H; assumption. -apply Bezout_intro with (- u) (- v). -rewrite H; rewrite <- e; ring. + intros a b d Hgcd. + elim (euclid a b); intros u v d0 e g. + generalize (Zis_gcd_uniqueness_apart_sign a b d d0 Hgcd g). + intro H; elim H; clear H; intros. + apply Bezout_intro with u v. + rewrite H; assumption. + apply Bezout_intro with (- u) (- v). + rewrite H; rewrite <- e; ring. Qed. (** gcd of [ca] and [cb] is [c gcd(a,b)]. *) 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. -replace (c * (u * a + v * b)) with (u * (c * a) + v * (c * b)). -rewrite H6; rewrite H7; ring. -ring. + 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. + replace (c * (u * a + v * b)) with (u * (c * a) + v * (c * b)). + rewrite H6; rewrite H7; ring. + ring. Qed. @@ -397,13 +397,13 @@ Definition rel_prime (a b:Z) : Prop := Zis_gcd a b 1. Lemma rel_prime_bezout : forall a b:Z, rel_prime a b -> Bezout a b 1. Proof. -intros a b; exact (Zis_gcd_bezout a b 1). + intros a b; exact (Zis_gcd_bezout a b 1). Qed. Lemma bezout_rel_prime : forall a b:Z, Bezout a b 1 -> rel_prime a b. Proof. -simple induction 1; constructor; auto with zarith. -intros. rewrite <- H0; auto with zarith. + simple induction 1; constructor; auto with zarith. + intros. rewrite <- H0; auto with zarith. Qed. (** Gauss's theorem: if [a] divides [bc] and if [a] and [b] are @@ -411,134 +411,134 @@ Qed. Theorem Gauss : forall a b c:Z, (a | b * c) -> rel_prime a b -> (a | c). Proof. -intros. elim (rel_prime_bezout a b H0); intros. -replace c with (c * 1); [ idtac | ring ]. -rewrite <- H1. -replace (c * (u * a + v * b)) with (c * u * a + v * (b * c)); - [ eauto with zarith | ring ]. + intros. elim (rel_prime_bezout a b H0); intros. + replace c with (c * 1); [ idtac | ring ]. + rewrite <- H1. + replace (c * (u * a + v * b)) with (c * u * a + v * (b * c)); + [ eauto with zarith | ring ]. Qed. (** If [a] is relatively prime to [b] and [c], then it is to [bc] *) Lemma rel_prime_mult : - forall a b c:Z, rel_prime a b -> rel_prime a c -> rel_prime a (b * c). + forall a b c:Z, rel_prime a b -> rel_prime a c -> rel_prime a (b * c). Proof. -intros a b c Hb Hc. -elim (rel_prime_bezout a b Hb); intros. -elim (rel_prime_bezout a c Hc); intros. -apply bezout_rel_prime. -apply Bezout_intro with - (u := u * u0 * a + v0 * c * u + u0 * v * b) (v := v * v0). -rewrite <- H. -replace (u * a + v * b) with ((u * a + v * b) * 1); [ idtac | ring ]. -rewrite <- H0. -ring. + intros a b c Hb Hc. + elim (rel_prime_bezout a b Hb); intros. + elim (rel_prime_bezout a c Hc); intros. + apply bezout_rel_prime. + apply Bezout_intro with + (u := u * u0 * a + v0 * c * u + u0 * v * b) (v := v * v0). + rewrite <- H. + replace (u * a + v * b) with ((u * a + v * b) * 1); [ idtac | ring ]. + rewrite <- H0. + ring. Qed. Lemma rel_prime_cross_prod : - forall a b c d:Z, - rel_prime a b -> - rel_prime c d -> b > 0 -> d > 0 -> a * d = b * c -> a = c /\ b = d. -Proof. -intros a b c d; intros. -elim (Zdivide_antisym b d). -split; auto with zarith. -rewrite H4 in H3. -rewrite Zmult_comm in H3. -apply Zmult_reg_l with d; auto with zarith. -intros; omega. -apply Gauss with a. -rewrite H3. -auto with zarith. -red in |- *; auto with zarith. -apply Gauss with c. -rewrite Zmult_comm. -rewrite <- H3. -auto with zarith. -red in |- *; auto with zarith. + forall a b c d:Z, + rel_prime a b -> + rel_prime c d -> b > 0 -> d > 0 -> a * d = b * c -> a = c /\ b = d. +Proof. + intros a b c d; intros. + elim (Zdivide_antisym b d). + split; auto with zarith. + rewrite H4 in H3. + rewrite Zmult_comm in H3. + apply Zmult_reg_l with d; auto with zarith. + intros; omega. + apply Gauss with a. + rewrite H3. + auto with zarith. + red in |- *; auto with zarith. + apply Gauss with c. + rewrite Zmult_comm. + rewrite <- H3. + auto with zarith. + red in |- *; auto with zarith. Qed. (** After factorization by a gcd, the original numbers are relatively prime. *) Lemma Zis_gcd_rel_prime : - forall a b g:Z, - b > 0 -> g >= 0 -> Zis_gcd a b g -> rel_prime (a / g) (b / g). -intros a b g; intros. -assert (g <> 0). - intro. - elim H1; intros. - elim H4; intros. - rewrite H2 in H6; subst b; omega. -unfold rel_prime in |- *. -destruct H1. -destruct H1 as (a',H1). -destruct H3 as (b',H3). -replace (a/g) with a'; - [|rewrite H1; rewrite Z_div_mult; auto with zarith]. -replace (b/g) with b'; - [|rewrite H3; rewrite Z_div_mult; auto with zarith]. -constructor. -exists a'; auto with zarith. -exists b'; auto with zarith. -intros x (xa,H5) (xb,H6). -destruct (H4 (x*g)). -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. + forall a b g:Z, + b > 0 -> g >= 0 -> Zis_gcd a b g -> rel_prime (a / g) (b / g). + intros a b g; intros. + assert (g <> 0). + intro. + elim H1; intros. + elim H4; intros. + rewrite H2 in H6; subst b; omega. + unfold rel_prime in |- *. + destruct H1. + destruct H1 as (a',H1). + destruct H3 as (b',H3). + replace (a/g) with a'; + [|rewrite H1; rewrite Z_div_mult; auto with zarith]. + replace (b/g) with b'; + [|rewrite H3; rewrite Z_div_mult; auto with zarith]. + constructor. + exists a'; auto with zarith. + exists b'; auto with zarith. + intros x (xa,H5) (xb,H6). + destruct (H4 (x*g)). + 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. Qed. (** * Primality *) Inductive prime (p:Z) : Prop := - prime_intro : - 1 < p -> (forall n:Z, 1 <= n < p -> rel_prime n p) -> prime p. + prime_intro : + 1 < p -> (forall n:Z, 1 <= n < p -> rel_prime n p) -> prime p. (** The sole divisors of a prime number [p] are [-1], [1], [p] and [-p]. *) Lemma prime_divisors : - forall p:Z, - prime p -> forall a:Z, (a | p) -> a = -1 \/ a = 1 \/ a = p \/ a = - p. -Proof. -simple induction 1; intros. -assert - (a = - p \/ - p < a < -1 \/ a = -1 \/ a = 0 \/ a = 1 \/ 1 < a < p \/ a = p). -assert (Zabs a <= Zabs p). apply Zdivide_bounds; [ assumption | omega ]. -generalize H3. -pattern (Zabs a) in |- *; apply Zabs_ind; pattern (Zabs p) in |- *; - apply Zabs_ind; intros; omega. -intuition idtac. -(* -p < a < -1 *) -absurd (rel_prime (- a) p); intuition. -inversion H3. -assert (- a | - a); auto with zarith. -assert (- a | p); auto with zarith. -generalize (H8 (- a) H9 H10); intuition idtac. -generalize (Zdivide_1 (- a) H11); intuition. -(* a = 0 *) -inversion H2. subst a; omega. -(* 1 < a < p *) -absurd (rel_prime a p); intuition. -inversion H3. -assert (a | a); auto with zarith. -assert (a | p); auto with zarith. -generalize (H8 a H9 H10); intuition idtac. -generalize (Zdivide_1 a H11); intuition. + forall p:Z, + prime p -> forall a:Z, (a | p) -> a = -1 \/ a = 1 \/ a = p \/ a = - p. +Proof. + simple induction 1; intros. + assert + (a = - p \/ - p < a < -1 \/ a = -1 \/ a = 0 \/ a = 1 \/ 1 < a < p \/ a = p). + assert (Zabs a <= Zabs p). apply Zdivide_bounds; [ assumption | omega ]. + generalize H3. + pattern (Zabs a) in |- *; apply Zabs_ind; pattern (Zabs p) in |- *; + apply Zabs_ind; intros; omega. + intuition idtac. + (* -p < a < -1 *) + absurd (rel_prime (- a) p); intuition. + inversion H3. + assert (- a | - a); auto with zarith. + assert (- a | p); auto with zarith. + generalize (H8 (- a) H9 H10); intuition idtac. + generalize (Zdivide_1 (- a) H11); intuition. + (* a = 0 *) + inversion H2. subst a; omega. + (* 1 < a < p *) + absurd (rel_prime a p); intuition. + inversion H3. + assert (a | a); auto with zarith. + assert (a | p); auto with zarith. + generalize (H8 a H9 H10); intuition idtac. + generalize (Zdivide_1 a H11); intuition. Qed. (** A prime number is relatively prime with any number it does not divide *) Lemma prime_rel_prime : - forall p:Z, prime p -> forall a:Z, ~ (p | a) -> rel_prime p a. + forall p:Z, prime p -> forall a:Z, ~ (p | a) -> rel_prime p a. Proof. -simple induction 1; intros. -constructor; intuition. -elim (prime_divisors p H x H3); intuition; subst; auto with zarith. -absurd (p | a); auto with zarith. -absurd (p | a); intuition. + simple induction 1; intros. + constructor; intuition. + elim (prime_divisors p H x H3); intuition; subst; auto with zarith. + absurd (p | a); auto with zarith. + absurd (p | a); intuition. Qed. Hint Resolve prime_rel_prime: zarith. @@ -546,46 +546,48 @@ Hint Resolve prime_rel_prime: zarith. (** [Zdivide] can be expressed using [Zmod]. *) Lemma Zmod_divide : forall a b:Z, b > 0 -> a mod b = 0 -> (b | a). -intros a b H H0. -apply Zdivide_intro with (a / b). -pattern a at 1 in |- *; rewrite (Z_div_mod_eq a b H). -rewrite H0; ring. +Proof. + intros a b H H0. + apply Zdivide_intro with (a / b). + pattern a at 1 in |- *; rewrite (Z_div_mod_eq a b H). + rewrite H0; ring. Qed. Lemma Zdivide_mod : forall a b:Z, b > 0 -> (b | a) -> a mod b = 0. -intros a b; simple destruct 2; intros; subst. -change (q * b) with (0 + q * b) in |- *. -rewrite Z_mod_plus; auto. +Proof. + intros a b; simple destruct 2; intros; subst. + change (q * b) with (0 + q * b) in |- *. + rewrite Z_mod_plus; auto. 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. + 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. (** If a prime [p] divides [ab] then it divides either [a] or [b] *) Lemma prime_mult : - forall p:Z, prime p -> forall a b:Z, (p | a * b) -> (p | a) \/ (p | b). + forall p:Z, prime p -> forall a b:Z, (p | a * b) -> (p | a) \/ (p | b). Proof. -intro p; simple induction 1; intros. -case (Zdivide_dec p a); intuition. -right; apply Gauss with a; auto with zarith. + intro p; simple induction 1; intros. + case (Zdivide_dec p a); intuition. + right; apply Gauss with a; auto with zarith. Qed. @@ -606,53 +608,53 @@ Qed. Open Scope positive_scope. Fixpoint Pgcdn (n: nat) (a b : positive) { struct n } : 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 + 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. Fixpoint Pggcdn (n: nat) (a b : positive) { struct n } : (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 + 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 Pgcd (a b: positive) := Pgcdn (Psize a + Psize b)%nat a b. @@ -661,269 +663,269 @@ Definition Pggcd (a b: positive) := Pggcdn (Psize a + Psize b)%nat a b. Open Scope Z_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. + | 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. 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. + | 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 Zgcd_is_pos : forall a b, 0 <= Zgcd a b. Proof. -unfold Zgcd; destruct a; destruct b; auto with zarith. + unfold Zgcd; destruct a; destruct b; auto with zarith. Qed. Lemma Psize_monotone : forall p q, Pcompare p q Eq = Lt -> (Psize p <= Psize q)%nat. Proof. -induction p; destruct q; simpl; auto with arith; intros; try discriminate. -intros; generalize (Pcompare_Gt_Lt _ _ H); auto with arith. -intros; destruct (Pcompare_Lt_Lt _ _ H); auto with arith; subst; auto. + induction p; destruct q; simpl; auto with arith; intros; try discriminate. + intros; generalize (Pcompare_Gt_Lt _ _ H); auto with arith. + intros; destruct (Pcompare_Lt_Lt _ _ H); auto with arith; subst; auto. Qed. Lemma Pminus_Zminus : forall a b, Pcompare a b Eq = Lt -> - Zpos (b-a) = Zpos b - Zpos a. + Zpos (b-a) = Zpos b - Zpos a. Proof. -intros. -repeat rewrite Zpos_eq_Z_of_nat_o_nat_of_P. -rewrite nat_of_P_minus_morphism. -apply inj_minus1. -apply lt_le_weak. -apply nat_of_P_lt_Lt_compare_morphism; auto. -rewrite ZC4; rewrite H; auto. + intros. + repeat rewrite Zpos_eq_Z_of_nat_o_nat_of_P. + rewrite nat_of_P_minus_morphism. + apply inj_minus1. + apply lt_le_weak. + apply nat_of_P_lt_Lt_compare_morphism; auto. + rewrite ZC4; rewrite H; auto. 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. + 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 (Pminus_Zminus _ _ H1). - assert (0 < Zpos a) by (compute; auto). - omega. -omega. -rewrite Zpos_xO; do 2 rewrite Zpos_xI. -rewrite Pminus_Zminus; 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 (Pminus_Zminus 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 Pminus_Zminus; 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. + 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 (Pminus_Zminus _ _ H1). + assert (0 < Zpos a) by (compute; auto). + omega. + omega. + rewrite Zpos_xO; do 2 rewrite Zpos_xI. + rewrite Pminus_Zminus; 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 (Pminus_Zminus 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 Pminus_Zminus; 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. + 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. + 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. Qed. Lemma Pggcdn_gcdn : forall n a b, - fst (Pggcdn n a b) = Pgcdn 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. + 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). + 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. + 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. + 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). + 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). + intros a b; exact (Pggcdn_correct_divisors (Psize a + Psize b)%nat a b). Qed. Open Scope Z_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). + 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. + 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 Zgcd_spec : forall x y : Z, {z : Z | Zis_gcd x y z /\ 0 <= z}. |