diff options
Diffstat (limited to 'theories/ZArith/Znumtheory.v')
| -rw-r--r-- | theories/ZArith/Znumtheory.v | 846 |
1 files changed, 429 insertions, 417 deletions
diff --git a/theories/ZArith/Znumtheory.v b/theories/ZArith/Znumtheory.v index dfe1c31fda..ed6272c445 100644 --- a/theories/ZArith/Znumtheory.v +++ b/theories/ZArith/Znumtheory.v @@ -8,11 +8,10 @@ (*i $Id$ i*) -Require ZArith_base. -Require ZArithRing. -Require Zcomplements. -Require Zdiv. -V7only [Import Z_scope.]. +Require Import ZArith_base. +Require Import ZArithRing. +Require Import Zcomplements. +Require Import Zdiv. Open Local Scope Z_scope. (** This file contains some notions of number theory upon Z numbers: @@ -26,176 +25,173 @@ Open Local Scope Z_scope. (** * Divisibility *) -Inductive Zdivide [a,b:Z] : Prop := - Zdivide_intro : (q:Z) `b = q * a` -> (Zdivide a b). +Inductive Zdivide (a b:Z) : Prop := + Zdivide_intro : forall q:Z, b = q * a -> Zdivide a b. (** Syntax for divisibility *) -Notation "( a | b )" := (Zdivide a b) - (at level 0, a,b at level 10) : Z_scope - V8only (at level 0, a,b at level 250). +Notation "( a | b )" := (Zdivide a b) (at level 0, a, b at level 250) : + Z_scope. (** Results concerning divisibility*) -Lemma Zdivide_refl : (a:Z) (a|a). +Lemma Zdivide_refl : forall a:Z, (a | a). Proof. -Intros; Apply Zdivide_intro with `1`; Ring. -Save. +intros; apply Zdivide_intro with 1; ring. +Qed. -Lemma Zone_divide : (a:Z) (1|a). +Lemma Zone_divide : forall a:Z, (1 | a). Proof. -Intros; Apply Zdivide_intro with `a`; Ring. -Save. +intros; apply Zdivide_intro with a; ring. +Qed. -Lemma Zdivide_0 : (a:Z) (a|0). +Lemma Zdivide_0 : forall a:Z, (a | 0). Proof. -Intros; Apply Zdivide_intro with `0`; Ring. -Save. +intros; apply Zdivide_intro with 0; ring. +Qed. -Hints Resolve Zdivide_refl Zone_divide Zdivide_0 : zarith. +Hint Resolve Zdivide_refl Zone_divide Zdivide_0: zarith. -Lemma Zdivide_mult_left : (a,b,c:Z) (a|b) -> (`c*a`|`c*b`). +Lemma Zmult_divide_compat_l : forall a b c:Z, (a | b) -> (c * a | c * b). Proof. -Induction 1; Intros; Apply Zdivide_intro with q. -Rewrite H0; Ring. -Save. +simple induction 1; intros; apply Zdivide_intro with q. +rewrite H0; ring. +Qed. -Lemma Zdivide_mult_right : (a,b,c:Z) (a|b) -> (`a*c`|`b*c`). +Lemma Zmult_divide_compat_r : forall a b c:Z, (a | b) -> (a * c | b * c). Proof. -Intros a b c; Rewrite (Zmult_sym a c); Rewrite (Zmult_sym b c). -Apply Zdivide_mult_left; Trivial. -Save. +intros a b c; rewrite (Zmult_comm a c); rewrite (Zmult_comm b c). +apply Zmult_divide_compat_l; trivial. +Qed. -Hints Resolve Zdivide_mult_left Zdivide_mult_right : zarith. +Hint Resolve Zmult_divide_compat_l Zmult_divide_compat_r: zarith. -Lemma Zdivide_plus : (a,b,c:Z) (a|b) -> (a|c) -> (a|`b+c`). +Lemma Zdivide_plus_r : forall a b c:Z, (a | b) -> (a | c) -> (a | b + c). Proof. -Induction 1; Intros q Hq; Induction 1; Intros q' Hq'. -Apply Zdivide_intro with `q+q'`. -Rewrite Hq; Rewrite Hq'; Ring. -Save. +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 : (a,b:Z) (a|b) -> (a|`-b`). +Lemma Zdivide_opp_r : forall a b:Z, (a | b) -> (a | - b). Proof. -Induction 1; Intros; Apply Zdivide_intro with `-q`. -Rewrite H0; Ring. -Save. +simple induction 1; intros; apply Zdivide_intro with (- q). +rewrite H0; ring. +Qed. -Lemma Zdivide_opp_rev : (a,b:Z) (a|`-b`) -> (a| b). +Lemma Zdivide_opp_r_rev : forall a b:Z, (a | - b) -> (a | b). Proof. -Intros; Replace b with `-(-b)`. Apply Zdivide_opp; Trivial. Ring. -Save. +intros; replace b with (- - b). apply Zdivide_opp_r; trivial. ring. +Qed. -Lemma Zdivide_opp_left : (a,b:Z) (a|b) -> (`-a`|b). +Lemma Zdivide_opp_l : forall a b:Z, (a | b) -> (- a | b). Proof. -Induction 1; Intros; Apply Zdivide_intro with `-q`. -Rewrite H0; Ring. -Save. +simple induction 1; intros; apply Zdivide_intro with (- q). +rewrite H0; ring. +Qed. -Lemma Zdivide_opp_left_rev : (a,b:Z) (`-a`|b) -> (a|b). +Lemma Zdivide_opp_l_rev : forall a b:Z, (- a | b) -> (a | b). Proof. -Intros; Replace a with `-(-a)`. Apply Zdivide_opp_left; Trivial. Ring. -Save. +intros; replace a with (- - a). apply Zdivide_opp_l; trivial. ring. +Qed. -Lemma Zdivide_minus : (a,b,c:Z) (a|b) -> (a|c) -> (a|`b-c`). +Lemma Zdivide_minus_l : forall a b c:Z, (a | b) -> (a | c) -> (a | b - c). Proof. -Induction 1; Intros q Hq; Induction 1; Intros q' Hq'. -Apply Zdivide_intro with `q-q'`. -Rewrite Hq; Rewrite Hq'; Ring. -Save. +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_left : (a,b,c:Z) (a|b) -> (a|`b*c`). +Lemma Zdivide_mult_l : forall a b c:Z, (a | b) -> (a | b * c). Proof. -Induction 1; Intros q Hq; Apply Zdivide_intro with `q*c`. -Rewrite Hq; Ring. -Save. +simple induction 1; intros q Hq; apply Zdivide_intro with (q * c). +rewrite Hq; ring. +Qed. -Lemma Zdivide_right : (a,b,c:Z) (a|c) -> (a|`b*c`). +Lemma Zdivide_mult_r : forall a b c:Z, (a | c) -> (a | b * c). Proof. -Induction 1; Intros q Hq; Apply Zdivide_intro with `q*b`. -Rewrite Hq; Ring. -Save. +simple induction 1; intros q Hq; apply Zdivide_intro with (q * b). +rewrite Hq; ring. +Qed. -Lemma Zdivide_a_ab : (a,b:Z) (a|`a*b`). +Lemma Zdivide_factor_r : forall a b:Z, (a | a * b). Proof. -Intros; Apply Zdivide_intro with b; Ring. -Save. +intros; apply Zdivide_intro with b; ring. +Qed. -Lemma Zdivide_a_ba : (a,b:Z) (a|`b*a`). +Lemma Zdivide_factor_l : forall a b:Z, (a | b * a). Proof. -Intros; Apply Zdivide_intro with b; Ring. -Save. +intros; apply Zdivide_intro with b; ring. +Qed. -Hints Resolve Zdivide_plus Zdivide_opp Zdivide_opp_rev - Zdivide_opp_left Zdivide_opp_left_rev - Zdivide_minus Zdivide_left Zdivide_right - Zdivide_a_ab Zdivide_a_ba : 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 : - (x,y:Z) `x>=0` -> `x*y=1` -> `x=1`. +Lemma Zmult_one : forall x y:Z, x >= 0 -> x * y = 1 -> x = 1. Proof. -Intros x y H H0; NewDestruct (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 NEG_lt_ZERO. -Save. +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. +Qed. (** Only [1] and [-1] divide [1]. *) -Lemma Zdivide_1 : (x:Z) (x|1) -> `x=1` \/ `x=-1`. +Lemma Zdivide_1 : forall x:Z, (x | 1) -> x = 1 \/ x = -1. Proof. -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. -Save. +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]. *) -Lemma Zdivide_antisym : (a,b:Z) (a|b) -> (b|a) -> `a=b` \/ `a=-b`. -Proof. -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_left with a. -Assumption. -Ring. -Pattern 2 a; 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. -Save. +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. +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. (** If [a] divides [b] and [b<>0] then [|a| <= |b|]. *) -Lemma Zdivide_bounds : (a,b:Z) (a|b) -> `b<>0` -> `|a| <= |b|`. -Proof. -Induction 1; Intros. -Assert `|b|=|q|*|a|`. - Subst; Apply Zabs_Zmult. -Rewrite H2. -Assert H3 := (Zabs_pos q). -Assert H4 := (Zabs_pos a). -Assert `|q|*|a|>=1*|a|`; Auto with zarith. -Apply Zge_Zmult_pos_compat; Auto with zarith. -Elim (Z_lt_ge_dec `|q|` `1`); [ Intros | Auto with zarith ]. -Assert `|q|=0`. - Omega. -Assert `q=0`. - Rewrite <- (Zabs_Zsgn q). -Rewrite H5; Auto with zarith. -Subst q; Omega. -Save. +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. +Qed. (** * Greatest common divisor (gcd). *) @@ -203,53 +199,54 @@ Save. expressing that [d] is a gcd of [a] and [b]. (We show later that the [gcd] is actually unique if we discard its sign.) *) -Inductive gcd [a,b,d:Z] : Prop := - gcd_intro : - (d|a) -> (d|b) -> ((x:Z) (x|a) -> (x|b) -> (x|d)) -> (gcd a b d). +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. (** Trivial properties of [gcd] *) -Lemma gcd_sym : (a,b,d:Z)(gcd a b d) -> (gcd b a d). +Lemma Zis_gcd_sym : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a d. Proof. -Induction 1; Constructor; Intuition. -Save. +simple induction 1; constructor; intuition. +Qed. -Lemma gcd_0 : (a:Z)(gcd a `0` a). +Lemma Zis_gcd_0 : forall a:Z, Zis_gcd a 0 a. Proof. -Constructor; Auto with zarith. -Save. +constructor; auto with zarith. +Qed. -Lemma gcd_minus :(a,b,d:Z)(gcd a `-b` d) -> (gcd b a d). +Lemma Zis_gcd_minus : forall a b d:Z, Zis_gcd a (- b) d -> Zis_gcd b a d. Proof. -Induction 1; Constructor; Intuition. -Save. +simple induction 1; constructor; intuition. +Qed. -Lemma gcd_opp :(a,b,d:Z)(gcd a b d) -> (gcd b a `-d`). +Lemma Zis_gcd_opp : forall a b d:Z, Zis_gcd a b d -> Zis_gcd b a (- d). Proof. -Induction 1; Constructor; Intuition. -Save. +simple induction 1; constructor; intuition. +Qed. -Hints Resolve gcd_sym gcd_0 gcd_minus gcd_opp : zarith. +Hint Resolve Zis_gcd_sym Zis_gcd_0 Zis_gcd_minus Zis_gcd_opp: zarith. (** * Extended Euclid algorithm. *) (** Euclid's algorithm to compute the [gcd] mainly relies on the following property. *) -Lemma gcd_for_euclid : - (a,b,d,q:Z) (gcd b `a-q*b` d) -> (gcd a b d). +Lemma Zis_gcd_for_euclid : + forall a b d q:Z, Zis_gcd b (a - q * b) d -> Zis_gcd a b d. Proof. -Induction 1; Constructor; Intuition. -Replace a with `a-q*b+q*b`. Auto with zarith. Ring. -Save. +simple induction 1; constructor; intuition. +replace a with (a - q * b + q * b). auto with zarith. ring. +Qed. -Lemma gcd_for_euclid2 : - (b,d,q,r:Z) (gcd r b d) -> (gcd b `b*q+r` d). +Lemma Zis_gcd_for_euclid2 : + forall b d q r:Z, Zis_gcd r b d -> Zis_gcd b (b * q + r) d. Proof. -Induction 1; Constructor; Intuition. -Apply H2; Auto. -Replace r with `b*q+r-b*q`. Auto with zarith. Ring. -Save. +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, i.e. the one computing Bezout's coefficients as it computes @@ -258,14 +255,14 @@ Save. Section extended_euclid_algorithm. -Variable 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)]. *) Inductive Euclid : Set := - Euclid_intro : - (u,v,d:Z) `u*a+v*b=d` -> (gcd a b d) -> Euclid. + 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 @@ -274,356 +271,371 @@ Inductive Euclid : Set := *) Lemma euclid_rec : - (v3:Z) `0 <= v3` -> (u1,u2,u3,v1,v2:Z) `u1*a+u2*b=u3` -> `v1*a+v2*b=v3` -> - ((d:Z)(gcd u3 v3 d) -> (gcd a b d)) -> Euclid. -Proof. -Intros v3 Hv3; Generalize Hv3; Pattern v3. -Apply Z_lt_rec. -Clear v3 Hv3; Intros. -Elim (Z_zerop x); Intro. -Apply Euclid_intro with u:=u1 v:=u2 d:=u3. -Assumption. -Apply H2. -Rewrite a0; Auto with zarith. -LetTac q := (Zdiv u3 x). -Assert Hq: `0 <= u3-q*x < x`. -Replace `u3-q*x` with `u3%x`. -Apply Z_mod_lt; Omega. -Assert xpos : `x > 0`. Omega. -Generalize (Z_div_mod_eq u3 x xpos). -Unfold q. -Intro eq; Pattern 2 u3; 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 H0; Rewrite H1; Trivial. -Ring. -Intros; Apply H2. -Apply gcd_for_euclid with q; Assumption. -Assumption. -Save. + 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 Z_lt_rec. +clear v3 Hv3; intros. +elim (Z_zerop x); intro. +apply Euclid_intro with (u := u1) (v := u2) (d := u3). +assumption. +apply H2. +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 H0; rewrite H1; trivial. +ring. +intros; apply H2. +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. -Save. +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 gcd_uniqueness_apart_sign : - (a,b,d,d':Z) (gcd a b d) -> (gcd a b d') -> `d = d'` \/ `d = -d'`. +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'. Proof. -Induction 1. -Intros H1 H2 H3; 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). -Save. +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 : (u,v:Z) `u*a + v*b = d` -> (Bezout a b d). +Inductive Bezout (a b d:Z) : Prop := + 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 gcd_bezout : (a,b,d:Z) (gcd a b d) -> (Bezout a b d). +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 (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. -Save. +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 gcd_mult : (a,b,c,d:Z) (gcd a b d) -> (gcd `c*a` `c*b` `c*d`). -Proof. -Intros a b c d; Induction 1; Constructor; Intuition. -Elim (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. -Save. +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. +Qed. (** We could obtain a [Zgcd] function via [euclid]. But we propose here a more direct version of a [Zgcd], with better extraction (no bezout coeffs). *) -Definition Zgcd_pos : (a:Z)`0<=a` -> (b:Z) - { g:Z | `0<=a` -> (gcd a b g) /\ `g>=0` }. -Proof. -Intros a Ha. -Apply (Z_lt_rec [a:Z](b:Z) { g:Z | `0<=a` -> (gcd a b g) /\`g>=0` }); Try Assumption. -Intro x; Case x. -Intros _ b; Exists (Zabs b). - Elim (Z_le_lt_eq_dec ? ? (Zabs_pos b)). - Intros H0; Split. - Apply Zabs_ind. - Intros; Apply gcd_sym; Apply gcd_0; Auto. - Intros; Apply gcd_opp; Apply gcd_0; Auto. - Auto with zarith. +Definition Zgcd_pos : + forall a:Z, + 0 <= a -> forall b:Z, {g : Z | 0 <= a -> Zis_gcd a b g /\ g >= 0}. +Proof. +intros a Ha. +apply + (Z_lt_rec + (fun a:Z => forall b:Z, {g : Z | 0 <= a -> Zis_gcd a b g /\ g >= 0})); + try assumption. +intro x; case x. +intros _ b; exists (Zabs b). + elim (Z_le_lt_eq_dec _ _ (Zabs_pos b)). + intros H0; split. + apply Zabs_ind. + intros; apply Zis_gcd_sym; apply Zis_gcd_0; auto. + intros; apply Zis_gcd_opp; apply Zis_gcd_0; auto. + auto with zarith. - Intros H0; Rewrite <- H0. - Rewrite <- (Zabs_Zsgn b); Rewrite <- H0; Simpl. - Split; [Apply gcd_0|Idtac];Auto with zarith. + intros H0; rewrite <- H0. + rewrite <- (Zabs_Zsgn b); rewrite <- H0; simpl in |- *. + split; [ apply Zis_gcd_0 | idtac ]; auto with zarith. -Intros p Hrec b. -Generalize (Z_div_mod b (POS p)). -Case (Zdiv_eucl b (POS p)); Intros q r Hqr. -Elim Hqr; Clear Hqr; Intros; Auto with zarith. -Elim (Hrec r H0 (POS p)); Intros g Hgkl. -Inversion_clear H0. -Elim (Hgkl H1); Clear Hgkl; Intros H3 H4. -Exists g; Intros. -Split; Auto. -Rewrite H. -Apply gcd_for_euclid2; Auto. - -Intros p Hrec b. -Exists `0`; Intros. -Elim H; Auto. +intros p Hrec b. +generalize (Z_div_mod b (Zpos p)). +case (Zdiv_eucl b (Zpos p)); intros q r Hqr. +elim Hqr; clear Hqr; intros; auto with zarith. +elim (Hrec r H0 (Zpos p)); intros g Hgkl. +inversion_clear H0. +elim (Hgkl H1); clear Hgkl; intros H3 H4. +exists g; intros. +split; auto. +rewrite H. +apply Zis_gcd_for_euclid2; auto. + +intros p Hrec b. +exists 0; intros. +elim H; auto. Defined. -Definition Zgcd_spec : (a,b:Z){ g : Z | (gcd a b g) /\ `g>=0` }. +Definition Zgcd_spec : forall a b:Z, {g : Z | Zis_gcd a b g /\ g >= 0}. Proof. -Intros a; Case (Z_gt_le_dec `0` a). -Intros; Assert `0 <= -a`. -Omega. -Elim (Zgcd_pos `-a` H b); Intros g Hgkl. -Exists g. -Intuition. -Intros Ha b; Elim (Zgcd_pos a Ha b); Intros g; Exists g; Intuition. +intros a; case (Z_gt_le_dec 0 a). +intros; assert (0 <= - a). +omega. +elim (Zgcd_pos (- a) H b); intros g Hgkl. +exists g. +intuition. +intros Ha b; elim (Zgcd_pos a Ha b); intros g; exists g; intuition. Defined. -Definition Zgcd := [a,b:Z](let (g,_) = (Zgcd_spec a b) in g). +Definition Zgcd (a b:Z) := let (g, _) := Zgcd_spec a b in g. -Lemma Zgcd_is_pos : (a,b:Z)`(Zgcd a b) >=0`. -Intros a b; Unfold Zgcd; Case (Zgcd_spec a b); Tauto. +Lemma Zgcd_is_pos : forall a b:Z, Zgcd a b >= 0. +intros a b; unfold Zgcd in |- *; case (Zgcd_spec a b); tauto. Qed. -Lemma Zgcd_is_gcd : (a,b:Z)(gcd a b (Zgcd a b)). -Intros a b; Unfold Zgcd; Case (Zgcd_spec a b); Tauto. +Lemma Zgcd_is_gcd : forall a b:Z, Zis_gcd a b (Zgcd a b). +intros a b; unfold Zgcd in |- *; case (Zgcd_spec a b); tauto. Qed. (** * Relative primality *) -Definition rel_prime [a,b:Z] : Prop := (gcd a b `1`). +Definition rel_prime (a b:Z) : Prop := Zis_gcd a b 1. (** Bezout's theorem: [a] and [b] are relatively prime if and only if there exist [u] and [v] such that [ua+vb = 1]. *) -Lemma rel_prime_bezout : - (a,b:Z) (rel_prime a b) -> (Bezout a b `1`). +Lemma rel_prime_bezout : forall a b:Z, rel_prime a b -> Bezout a b 1. Proof. -Intros a b; Exact (gcd_bezout a b `1`). -Save. +intros a b; exact (Zis_gcd_bezout a b 1). +Qed. -Lemma bezout_rel_prime : - (a,b:Z) (Bezout a b `1`) -> (rel_prime a b). +Lemma bezout_rel_prime : forall a b:Z, Bezout a b 1 -> rel_prime a b. Proof. -Induction 1; Constructor; Auto with zarith. -Intros. Rewrite <- H0; Auto with zarith. -Save. +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 relatively prime, then [a] divides [c]. *) -Theorem Gauss : (a,b,c:Z) (a |`b*c`) -> (rel_prime a b) -> (a | c). +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 ]. -Save. +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 : - (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. -Save. +Lemma rel_prime_mult : + 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. +Qed. Lemma rel_prime_cross_prod : - (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_sym in H3. -Apply Zmult_reg_left with d; Auto with zarith. -Intros; Omega. -Apply Gauss with a. -Rewrite H3. -Auto with zarith. -Red; Auto with zarith. -Apply Gauss with c. -Rewrite Zmult_sym. -Rewrite <- H3. -Auto with zarith. -Red; Auto with zarith. -Save. + 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 gcd_rel_prime : - (a,b,g:Z)`b>0` -> `g>=0`-> (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. -Elim (Zgcd_spec `a/g` `b/g`); Intros g' (H3,H4). -Assert H5 := (gcd_mult ? ? g ? H3). -Rewrite <- Z_div_exact_2 in H5; Auto with zarith. -Rewrite <- Z_div_exact_2 in H5; Auto with zarith. -Elim (gcd_uniqueness_apart_sign ? ? ? ? H1 H5). -Intros; Rewrite (!Zmult_reg_left `1` g' g); Auto with zarith. -Intros; Rewrite (!Zmult_reg_left `1` `-g'` g); Auto with zarith. -Pattern 1 g; Rewrite H6; Ring. - -Elim H1; Intros. -Elim H7; Intros. -Rewrite H9. -Replace `q*g` with `0+q*g`. -Rewrite Z_mod_plus. -Compute; Auto. -Omega. -Ring. - -Elim H1; Intros. -Elim H6; Intros. -Rewrite H9. -Replace `q*g` with `0+q*g`. -Rewrite Z_mod_plus. -Compute; Auto. -Omega. -Ring. -Save. +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 |- *. +elim (Zgcd_spec (a / g) (b / g)); intros g' [H3 H4]. +assert (H5 := Zis_gcd_mult _ _ g _ H3). +rewrite <- Z_div_exact_2 in H5; auto with zarith. +rewrite <- Z_div_exact_2 in H5; auto with zarith. +elim (Zis_gcd_uniqueness_apart_sign _ _ _ _ H1 H5). +intros; rewrite (Zmult_reg_l 1 g' g); auto with zarith. +intros; rewrite (Zmult_reg_l 1 (- g') g); auto with zarith. +pattern g at 1 in |- *; rewrite H6; ring. + +elim H1; intros. +elim H7; intros. +rewrite H9. +replace (q * g) with (0 + q * g). +rewrite Z_mod_plus. +compute in |- *; auto. +omega. +ring. + +elim H1; intros. +elim H6; intros. +rewrite H9. +replace (q * g) with (0 + q * g). +rewrite Z_mod_plus. +compute in |- *; auto. +omega. +ring. +Qed. (** * Primality *) -Inductive prime [p:Z] : Prop := - prime_intro : - `1 < p` -> ((n:Z) `1 <= n < p` -> (rel_prime n p)) -> (prime p). +Inductive prime (p:Z) : Prop := + 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 : - (p:Z) (prime p) -> - (a:Z) (a|p) -> `a = -1` \/ `a = 1` \/ a = p \/ `a = -p`. -Proof. -Induction 1; Intros. -Assert `a = (-p)`\/`-p<a< -1`\/`a = -1`\/`a=0`\/`a = 1`\/`1<a<p`\/`a = p`. -Assert `|a| <= |p|`. Apply Zdivide_bounds; [ Assumption | Omega ]. -Generalize H3. -Pattern `|a|`; Apply Zabs_ind; Pattern `|p|`; Apply Zabs_ind; Intros; Omega. -Intuition Idtac. +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. +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. +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. -Save. +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 : - (p:Z) (prime p) -> (a:Z) ~ (p|a) -> (rel_prime p a). +Lemma prime_rel_prime : + forall p:Z, prime p -> forall a:Z, ~ (p | a) -> rel_prime p a. Proof. -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. -Save. +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. -Hints Resolve prime_rel_prime : zarith. +Hint Resolve prime_rel_prime: zarith. (** [Zdivide] can be expressed using [Zmod]. *) -Lemma Zmod_Zdivide : (a,b:Z) `b>0` -> `a%b = 0` -> (b|a). -Intros a b H H0. -Apply Zdivide_intro with `(a/b)`. -Pattern 1 a; Rewrite (Z_div_mod_eq a b H). -Rewrite H0; Ring. -Save. +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. +Qed. -Lemma Zdivide_Zmod : (a,b:Z) `b>0` -> (b|a) -> `a%b = 0`. -Intros a b; Destruct 2; Intros; Subst. -Change `q*b` with `0+q*b`. -Rewrite Z_mod_plus; Auto. -Save. +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. +Qed. (** [Zdivide] is hence decidable *) -Lemma Zdivide_dec : (a,b:Z) { (a|b) } + { ~ (a|b) }. +Lemma Zdivide_dec : forall a b:Z, {(a | b)} + {~ (a | b)}. Proof. -Intros a b; Elim (Ztrichotomy_inf a `0`). +intros a b; elim (Ztrichotomy_inf a 0). (* a<0 *) -Intros H; Elim H; Intros. -Case (Z_eq_dec `b%(-a)` `0`). -Left; Apply Zdivide_opp_left_rev; Apply Zmod_Zdivide; Auto with zarith. -Intro H1; Right; Intro; Elim H1; Apply Zdivide_Zmod; Auto with zarith. +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. +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%a` `0`). -Left; Apply Zmod_Zdivide; Auto with zarith. -Intro H1; Right; Intro; Elim H1; Apply Zdivide_Zmod; Auto with zarith. -Save. +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 : - (p:Z) (prime p) -> (a,b:Z) (p | `a*b`) -> (p | a) \/ (p | b). +Lemma prime_mult : + forall p:Z, prime p -> forall a b:Z, (p | a * b) -> (p | a) \/ (p | b). Proof. -Intro p; Induction 1; Intros. -Case (Zdivide_dec p a); Intuition. -Right; Apply Gauss with a; Auto with zarith. -Save. - +intro p; simple induction 1; intros. +case (Zdivide_dec p a); intuition. +right; apply Gauss with a; auto with zarith. +Qed. |
