diff options
| author | letouzey | 2007-11-10 19:51:14 +0000 |
|---|---|---|
| committer | letouzey | 2007-11-10 19:51:14 +0000 |
| commit | d79c32b352e8df2380eed4dde4253dd3530e94e4 (patch) | |
| tree | 20b83138892ac2c5e23835b9488032a1567da1f1 | |
| parent | a2c53cc24077ec911877d9c12e22819b27c516c8 (diff) | |
First reasonably complete version of ZOdiv, including some properties
that aren't so nice after all. For instance, ((a+b*c) mod c) might differ
from (a mod c), due to sign issues.
Minor improvements to Zdiv
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@10312 85f007b7-540e-0410-9357-904b9bb8a0f7
| -rw-r--r-- | theories/ZArith/ZOdiv.v | 415 | ||||
| -rw-r--r-- | theories/ZArith/Zdiv.v | 24 |
2 files changed, 284 insertions, 155 deletions
diff --git a/theories/ZArith/ZOdiv.v b/theories/ZArith/ZOdiv.v index 937a05dcad..d0f3682f42 100644 --- a/theories/ZArith/ZOdiv.v +++ b/theories/ZArith/ZOdiv.v @@ -143,7 +143,20 @@ Proof. simpl; destruct n0; simpl; auto with zarith. Qed. -(** Reformulation of the last two general statements in 2 +(** This can also be said in a simplier way: *) + +Theorem Zsgn_pos_iff : forall z, 0 <= Zsgn z <-> 0 <= z. +Proof. + destruct z; simpl; intuition auto with zarith. +Qed. + +Theorem ZOmod_sgn2 : forall a b:Z, + 0 <= (a mod b) * a. +Proof. + intros; rewrite <-Zsgn_pos_iff, Zsgn_Zmult; apply ZOmod_sgn. +Qed. + +(** Reformulation of [ZOdiv_lt] and [ZOmod_sgn] in 2 then 4 particular cases. *) Theorem ZOmod_lt_pos : forall a b:Z, 0<=a -> b<>0 -> @@ -236,22 +249,17 @@ Definition Remainder a b r := (0 <= a /\ 0 <= r < Zabs b) \/ (a <= 0 /\ -Zabs b < r <= 0). Definition Remainder_alt a b r := - Zabs r < Zabs b /\ 0 <= Zsgn r * Zsgn a. + Zabs r < Zabs b /\ 0 <= r * a. Lemma Remainder_equiv : forall a b r, Remainder a b r <-> Remainder_alt a b r. Proof. unfold Remainder, Remainder_alt; intuition. romega with *. - destruct (Zle_lt_or_eq _ _ H). - rewrite <- Zsgn_pos in H1; rewrite H1. - romega with *. - subst; simpl; romega. - rewrite Zabs_non_eq; auto with *. - destruct (Zle_lt_or_eq _ _ H). - rewrite <- Zsgn_neg in H1; rewrite H1. romega with *. - subst; simpl; romega. + rewrite <-(Zmult_opp_opp). + apply Zmult_le_0_compat; romega. + assert (0 <= Zsgn r * Zsgn a) by (rewrite <-Zsgn_Zmult, Zsgn_pos_iff; auto). destruct r; simpl Zsgn in *; romega with *. Qed. @@ -429,7 +437,7 @@ Qed. (** [Zge] is compatible with a positive division. *) -Lemma ZO_div_pos_monotone : forall a b c:Z, 0<=c -> 0 <= a <= b -> a/c <= b/c. +Lemma ZO_div_monotone_pos : forall a b c:Z, 0<=c -> 0<=a<=b -> a/c <= b/c. Proof. intros. destruct H0. @@ -455,11 +463,11 @@ Proof. omega. Qed. -Lemma ZO_div_monotone : forall a b c, 0 <= c -> a <= b -> a/c <= b/c. +Lemma ZO_div_monotone : forall a b c, 0<=c -> a<=b -> a/c <= b/c. Proof. intros. destruct (Z_le_gt_dec 0 a). - apply ZO_div_pos_monotone; auto with zarith. + apply ZO_div_monotone_pos; auto with zarith. destruct (Z_le_gt_dec 0 b). apply Zle_trans with 0. apply Zle_left_rev. @@ -469,7 +477,7 @@ Proof. apply ZO_div_pos; auto with zarith. rewrite <-(Zopp_involutive a), (ZOdiv_opp_l (-a)). rewrite <-(Zopp_involutive b), (ZOdiv_opp_l (-b)). - generalize (ZO_div_pos_monotone (-b) (-a) c H). + generalize (ZO_div_monotone_pos (-b) (-a) c H). romega. Qed. @@ -570,214 +578,299 @@ Proof. auto with zarith. Qed. -(* NOT FINISHED YET ... - (** * Relations between usual operations and Zmod and Zdiv *) -Eval compute in ((10-4*3) mod 3). +(** First, a result that used to be always valid with Zdiv, + but must be restricted here. + For instance, now (9+(-5)*2) mod 2 = -1 <> 1 = 9 mod 2 *) -Lemma ZO_mod_plus : forall a b c:Z, (a + b * c) mod c = a mod c. (*FAUX*) +Lemma ZO_mod_plus : forall a b c:Z, + 0 <= (a+b*c) * a -> + (a + b * c) mod c = a mod c. Proof. + intros; destruct (Z_eq_dec a 0) as [Ha|Ha]. + subst; simpl; rewrite ZOmod_0_l; apply ZO_mod_mult. intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. subst; do 2 rewrite ZOmod_0_r; romega. symmetry; apply ZOmod_unique_full with (a/c+b); auto with zarith. rewrite Remainder_equiv; split. apply ZOmod_lt; auto. - generalize (ZOmod_sgn a c); intros. - admit. + apply Zmult_le_0_reg_r with (a*a); eauto. + destruct a; simpl; auto with zarith. + replace ((a mod c)*(a+b*c)*(a*a)) with (((a mod c)*a)*((a+b*c)*a)) by ring. + apply Zmult_le_0_compat; auto. + apply ZOmod_sgn2. rewrite Zmult_plus_distr_r, Zmult_comm. generalize (ZO_div_mod_eq a c); romega. Qed. -Lemma ZO_div_plus : forall a b c:Z, c<>0 -> (a + b * c) / c = a / c + b. +Lemma ZO_div_plus : forall a b c:Z, + 0 <= (a+b*c) * a -> c<>0 -> + (a + b * c) / c = a / c + b. Proof. - intro; symmetry. + intros; destruct (Z_eq_dec a 0) as [Ha|Ha]. + subst; simpl; apply ZO_div_mult; auto. + symmetry. apply ZOdiv_unique_full with (a mod c); auto with zarith. rewrite Remainder_equiv; split. apply ZOmod_lt; auto. - generalize (ZOmod_sgn a c); intros. - admit. + apply Zmult_le_0_reg_r with (a*a); eauto. + destruct a; simpl; auto with zarith. + replace ((a mod c)*(a+b*c)*(a*a)) with (((a mod c)*a)*((a+b*c)*a)) by ring. + apply Zmult_le_0_compat; auto. + apply ZOmod_sgn2. rewrite Zmult_plus_distr_r, Zmult_comm. generalize (ZO_div_mod_eq a c); romega. Qed. -Theorem ZO_div_plus_l: forall a b c : Z, b <> 0 -> (a * b + c) / b = a + c / b. +Theorem ZO_div_plus_l: forall a b c : Z, + 0 <= (a*b+c)*c -> b<>0 -> + b<>0 -> (a * b + c) / b = a + c / b. Proof. - intros a b c H; rewrite Zplus_comm; rewrite ZO_div_plus; + intros a b c; rewrite Zplus_comm; intros; rewrite ZO_div_plus; try apply Zplus_comm; auto with zarith. Qed. (** Cancellations. *) -Lemma Zdiv_mult_cancel_r : forall a b c:Z, - c <> 0 -> (a*c)/(b*c) = a/b. +Lemma ZOdiv_mult_cancel_r : forall a b c:Z, + c<>0 -> (a*c)/(b*c) = a/b. Proof. -assert (X: forall a b c, b > 0 -> c > 0 -> (a*c) / (b*c) = a / b). - intros a b c Hb Hc. + intros a b c Hc. + destruct (Z_eq_dec b 0). + subst; simpl; do 2 rewrite ZOdiv_0_r; auto. symmetry. - apply Zdiv_unique with ((a mod b)*c); auto with zarith. - destruct (Z_mod_lt a b Hb); split. - apply Zmult_le_0_compat; auto with zarith. - apply Zmult_lt_compat_r; auto with zarith. - pattern a at 1; rewrite (Z_div_mod_eq a b Hb); ring. -intros a b c Hc. -destruct (Z_dec b 0) as [Hb|Hb]. -destruct Hb as [Hb|Hb]; destruct (not_Zeq_inf _ _ Hc); auto with *. -rewrite <- (Zdiv_opp_opp a), <- (Zmult_opp_opp b), <-(Zmult_opp_opp a); - auto with *. -rewrite <- (Zdiv_opp_opp a), <- Zdiv_opp_opp, Zopp_mult_distr_l, - Zopp_mult_distr_l; auto with *. -rewrite <- Zdiv_opp_opp, Zopp_mult_distr_r, Zopp_mult_distr_r; auto with *. -rewrite Hb; simpl; do 2 rewrite Zdiv_0_r; auto. -Qed. - -Lemma Zdiv_mult_cancel_l : forall a b c:Z, + apply ZOdiv_unique_full with ((a mod b)*c); auto with zarith. + rewrite Remainder_equiv. + split. + do 2 rewrite Zabs_Zmult. + apply Zmult_lt_compat_r. + romega with *. + apply ZOmod_lt; auto. + replace ((a mod b)*c*(a*c)) with (((a mod b)*a)*(c*c)) by ring. + apply Zmult_le_0_compat. + apply ZOmod_sgn2. + destruct c; simpl; auto with zarith. + pattern a at 1; rewrite (ZO_div_mod_eq a b); ring. +Qed. + +Lemma ZOdiv_mult_cancel_l : forall a b c:Z, c<>0 -> (c*a)/(c*b) = a/b. Proof. intros. rewrite (Zmult_comm c a); rewrite (Zmult_comm c b). - apply Zdiv_mult_cancel_r; auto. + apply ZOdiv_mult_cancel_r; auto. Qed. -Lemma Zmult_mod_distr_l: forall a b c, +Lemma ZOmult_mod_distr_l: forall a b c, (c*a) mod (c*b) = c * (a mod b). Proof. intros; destruct (Z_eq_dec c 0) as [Hc|Hc]. - subst; simpl; rewrite Zmod_0_r; auto. + subst; simpl; rewrite ZOmod_0_r; auto. destruct (Z_eq_dec b 0) as [Hb|Hb]. - subst; repeat rewrite Zmult_0_r || rewrite Zmod_0_r; auto. + subst; repeat rewrite Zmult_0_r || rewrite ZOmod_0_r; auto. assert (c*b <> 0). contradict Hc; eapply Zmult_integral_l; eauto. - rewrite (Zplus_minus_eq _ _ _ (Z_div_mod_eq_full (c*a) (c*b) H)). - rewrite (Zplus_minus_eq _ _ _ (Z_div_mod_eq_full a b Hb)). - rewrite Zdiv_mult_cancel_l; auto with zarith. + rewrite (Zplus_minus_eq _ _ _ (ZO_div_mod_eq (c*a) (c*b))). + rewrite (Zplus_minus_eq _ _ _ (ZO_div_mod_eq a b)). + rewrite ZOdiv_mult_cancel_l; auto with zarith. ring. Qed. -Lemma Zmult_mod_distr_r: forall a b c, +Lemma ZOmult_mod_distr_r: forall a b c, (a*c) mod (b*c) = (a mod b) * c. Proof. intros; repeat rewrite (fun x => (Zmult_comm x c)). - apply Zmult_mod_distr_l; auto. + apply ZOmult_mod_distr_l; auto. Qed. (** Operations modulo. *) -Theorem Zmod_mod: forall a n, (a mod n) mod n = a mod n. +Theorem ZOmod_mod: forall a n, (a mod n) mod n = a mod n. Proof. - intros; destruct (Z_eq_dec n 0) as [Hb|Hb]. - subst; do 2 rewrite Zmod_0_r; auto. - pattern a at 2; rewrite (Z_div_mod_eq_full a n); auto with zarith. - rewrite Zplus_comm; rewrite Zmult_comm. - apply sym_equal; apply Z_mod_plus_full; auto with zarith. + intros. + generalize (ZOmod_sgn2 a n). + pattern a at 2 4; rewrite (ZO_div_mod_eq a n); auto with zarith. + rewrite Zplus_comm; rewrite (Zmult_comm n). + intros. + apply sym_equal; apply ZO_mod_plus; auto with zarith. + rewrite Zmult_comm; auto. Qed. -Theorem Zmult_mod: forall a b n, +Theorem ZOmult_mod: forall a b n, (a * b) mod n = ((a mod n) * (b mod n)) mod n. Proof. - intros; destruct (Z_eq_dec n 0) as [Hb|Hb]. - subst; do 2 rewrite Zmod_0_r; auto. - pattern a at 1; rewrite (Z_div_mod_eq_full a n); auto with zarith. - pattern b at 1; rewrite (Z_div_mod_eq_full b n); auto with zarith. + intros. + generalize (Zmult_le_0_compat _ _ (ZOmod_sgn2 a n) (ZOmod_sgn2 b n)). + pattern a at 2 3; rewrite (ZO_div_mod_eq a n); auto with zarith. + pattern b at 2 3; rewrite (ZO_div_mod_eq b n); auto with zarith. set (A:=a mod n); set (B:=b mod n); set (A':=a/n); set (B':=b/n). + replace (A*(n*A'+A)*(B*(n*B'+B))) with (((n*A' + A) * (n*B' + B))*(A*B)) + by ring. replace ((n*A' + A) * (n*B' + B)) with (A*B + (A'*B+B'*A+n*A'*B')*n) by ring. - apply Z_mod_plus_full; auto with zarith. + intros. + apply ZO_mod_plus; auto with zarith. Qed. -Theorem Zplus_mod: forall a b n, +(** addition and modulo + + Generally speaking, unlike with Zdiv, we don't have + (a+b) mod n = (a mod n + b mod n) mod n + for any a and b. + For instance, take (8 + (-10)) mod 3 = -2 whereas + (8 mod 3 + (-10 mod 3)) mod 3 = 1. *) + +Theorem ZOplus_mod: forall a b n, + 0 <= a * b -> (a + b) mod n = (a mod n + b mod n) mod n. Proof. - intros; destruct (Z_eq_dec n 0) as [Hb|Hb]. - subst; do 2 rewrite Zmod_0_r; auto. - pattern a at 1; rewrite (Z_div_mod_eq_full a n); auto with zarith. - pattern b at 1; rewrite (Z_div_mod_eq_full b n); auto with zarith. + assert (forall a b n, 0<a -> 0<b -> + (a + b) mod n = (a mod n + b mod n) mod n). + intros a b n Ha Hb. + assert (H : 0<=a+b) by (romega with * ); revert H. + pattern a at 1 2; rewrite (ZO_div_mod_eq a n); auto with zarith. + pattern b at 1 2; rewrite (ZO_div_mod_eq b n); auto with zarith. replace ((n * (a / n) + a mod n) + (n * (b / n) + b mod n)) with ((a mod n + b mod n) + (a / n + b / n) * n) by ring. - apply Z_mod_plus_full; auto with zarith. -Qed. - -Theorem Zminus_mod: forall a b n, - (a - b) mod n = (a mod n - b mod n) mod n. -Proof. intros. - replace (a - b) with (a + (-1) * b); auto with zarith. - replace (a mod n - b mod n) with (a mod n + (-1) * (b mod n)); auto with zarith. - rewrite Zplus_mod. - rewrite Zmult_mod. - rewrite Zplus_mod with (b:=(-1) * (b mod n)). - rewrite Zmult_mod. - rewrite Zmult_mod with (b:= b mod n). - repeat rewrite Zmod_mod; auto. -Qed. - -Lemma Zplus_mod_idemp_l: forall a b n, (a mod n + b) mod n = (a + b) mod n. -Proof. - intros; rewrite Zplus_mod, Zmod_mod, <- Zplus_mod; auto. + apply ZO_mod_plus; auto with zarith. + apply Zmult_le_0_compat; auto with zarith. + apply Zplus_le_0_compat. + apply Zmult_le_reg_r with a; auto with zarith. + simpl; apply ZOmod_sgn2; auto. + apply Zmult_le_reg_r with b; auto with zarith. + simpl; apply ZOmod_sgn2; auto. + (* general situation *) + intros a b n Hab. + destruct (Z_eq_dec a 0). + subst; simpl; symmetry; apply ZOmod_mod. + destruct (Z_eq_dec b 0). + subst; simpl; do 2 rewrite Zplus_0_r; symmetry; apply ZOmod_mod. + assert (0<a /\ 0<b \/ a<0 /\ b<0). + destruct a; destruct b; simpl in *; intuition; romega with *. + destruct H0. + apply H; intuition. + rewrite <-(Zopp_involutive a), <-(Zopp_involutive b). + rewrite <- Zopp_plus_distr; rewrite ZOmod_opp_l. + rewrite (ZOmod_opp_l (-a)),(ZOmod_opp_l (-b)). + match goal with |- _ = (-?x+-?y) mod n => + rewrite <-(Zopp_plus_distr x y), ZOmod_opp_l end. + f_equal; apply H; auto with zarith. Qed. -Lemma Zplus_mod_idemp_r: forall a b n, (b + a mod n) mod n = (b + a) mod n. +Lemma ZOplus_mod_idemp_l: forall a b n, + 0 <= a * b -> + (a mod n + b) mod n = (a + b) mod n. Proof. - intros; rewrite Zplus_mod, Zmod_mod, <- Zplus_mod; auto. + intros. + rewrite ZOplus_mod. + rewrite ZOmod_mod. + symmetry. + apply ZOplus_mod; auto. + destruct (Z_eq_dec a 0). + subst; rewrite ZOmod_0_l; auto. + destruct (Z_eq_dec b 0). + subst; rewrite Zmult_0_r; auto with zarith. + apply Zmult_le_reg_r with (a*b). + assert (a*b <> 0). + intro Hab. + rewrite (Zmult_integral_l _ _ n1 Hab) in n0; auto with zarith. + auto with zarith. + simpl. + replace (a mod n * b * (a*b)) with ((a mod n * a)*(b*b)) by ring. + apply Zmult_le_0_compat. + apply ZOmod_sgn2. + destruct b; simpl; auto with zarith. Qed. -Lemma Zminus_mod_idemp_l: forall a b n, (a mod n - b) mod n = (a - b) mod n. +Lemma ZOplus_mod_idemp_r: forall a b n, + 0 <= a*b -> + (b + a mod n) mod n = (b + a) mod n. Proof. - intros; rewrite Zminus_mod, Zmod_mod, <- Zminus_mod; auto. + intros. + rewrite Zplus_comm, (Zplus_comm b a). + apply ZOplus_mod_idemp_l; auto. Qed. -Lemma Zminus_mod_idemp_r: forall a b n, (a - b mod n) mod n = (a - b) mod n. +Lemma ZOmult_mod_idemp_l: forall a b n, (a mod n * b) mod n = (a * b) mod n. Proof. - intros; rewrite Zminus_mod, Zmod_mod, <- Zminus_mod; auto. + intros; rewrite ZOmult_mod, ZOmod_mod, <- ZOmult_mod; auto. Qed. -Lemma Zmult_mod_idemp_l: forall a b n, (a mod n * b) mod n = (a * b) mod n. +Lemma ZOmult_mod_idemp_r: forall a b n, (b * (a mod n)) mod n = (b * a) mod n. Proof. - intros; rewrite Zmult_mod, Zmod_mod, <- Zmult_mod; auto. + intros; rewrite ZOmult_mod, ZOmod_mod, <- ZOmult_mod; auto. Qed. -Lemma Zmult_mod_idemp_r: forall a b n, (b * (a mod n)) mod n = (b * a) mod n. -Proof. - intros; rewrite Zmult_mod, Zmod_mod, <- Zmult_mod; auto. -Qed. +(** Unlike with Zdiv, the following result is true without restrictions. *) -Lemma Zdiv_Zdiv : forall a b c, b>0 -> c>0 -> (a/b)/c = a/(b*c). +Lemma ZOdiv_ZOdiv : forall a b c, (a/b)/c = a/(b*c). Proof. - intros a b c H H0. - pattern a at 2;rewrite (Z_div_mod_eq_full a b);auto with zarith. - pattern (a/b) at 2;rewrite (Z_div_mod_eq_full (a/b) c);auto with zarith. - replace (b * (c * (a / b / c) + (a / b) mod c) + a mod b) with + (* particular case: a, b, c positive *) + assert (forall a b c, a>0 -> b>0 -> c>0 -> (a/b)/c = a/(b*c)). + intros a b c H H0 H1. + pattern a at 2;rewrite (ZO_div_mod_eq a b). + pattern (a/b) at 2;rewrite (ZO_div_mod_eq (a/b) c). + replace (b * (c * (a / b / c) + (a / b) mod c) + a mod b) with ((a / b / c)*(b * c) + (b * ((a / b) mod c) + a mod b)) by ring. - rewrite Z_div_plus_full_l; auto with zarith. - rewrite (Zdiv_small (b * ((a / b) mod c) + a mod b)). - ring. - split. - apply Zplus_le_0_compat;auto with zarith. - apply Zmult_le_0_compat;auto with zarith. - destruct (Z_mod_lt (a/b) c);auto with zarith. - destruct (Z_mod_lt a b);auto with zarith. - apply Zle_lt_trans with (b * ((a / b) mod c) + (b-1)). - destruct (Z_mod_lt a b);auto with zarith. - apply Zle_lt_trans with (b * (c-1) + (b - 1)). - apply Zplus_le_compat;auto with zarith. - destruct (Z_mod_lt (a/b) c);auto with zarith. - replace (b * (c - 1) + (b - 1)) with (b*c-1);try ring;auto with zarith. - intro H1; - assert (H2: c <> 0) by auto with zarith; - rewrite (Zmult_integral_l _ _ H2 H1) in H; auto with zarith. -Qed. - -(** Unfortunately, the previous result isn't always true on negative numbers. - For instance: 3/(-2)/(-2) = 1 <> 0 = 3 / (-2*-2) *) + assert (b*c<>0). + intro H2; + assert (H3: c <> 0) by auto with zarith; + rewrite (Zmult_integral_l _ _ H3 H2) in H0; auto with zarith. + assert (0<=a/b) by (apply (ZO_div_pos a b); auto with zarith). + assert (0<=a mod b < b) by (apply ZOmod_lt_pos_pos; auto with zarith). + assert (0<=(a/b) mod c < c) by + (apply ZOmod_lt_pos_pos; auto with zarith). + rewrite ZO_div_plus_l; auto with zarith. + rewrite (ZOdiv_small (b * ((a / b) mod c) + a mod b)). + ring. + split. + apply Zplus_le_0_compat;auto with zarith. + apply Zle_lt_trans with (b * ((a / b) mod c) + (b-1)). + apply Zplus_le_compat;auto with zarith. + apply Zle_lt_trans with (b * (c-1) + (b - 1)). + apply Zplus_le_compat;auto with zarith. + replace (b * (c - 1) + (b - 1)) with (b*c-1);try ring;auto with zarith. + repeat (apply Zmult_le_0_compat || apply Zplus_le_0_compat); auto with zarith. + apply (ZO_div_pos (a/b) c); auto with zarith. + (* b c positive, a general *) + assert (forall a b c, b>0 -> c>0 -> (a/b)/c = a/(b*c)). + intros; destruct a as [ |a|a]; try reflexivity. + apply H; auto with zarith. + change (Zneg a) with (-Zpos a); repeat rewrite ZOdiv_opp_l. + f_equal; apply H; auto with zarith. + (* c positive, a b general *) + assert (forall a b c, c>0 -> (a/b)/c = a/(b*c)). + intros; destruct b as [ |b|b]. + repeat rewrite ZOdiv_0_r; reflexivity. + apply H0; auto with zarith. + change (Zneg b) with (-Zpos b); + repeat (rewrite ZOdiv_opp_r || rewrite ZOdiv_opp_l || rewrite <- Zopp_mult_distr_l). + f_equal; apply H0; auto with zarith. + (* a b c general *) + intros; destruct c as [ |c|c]. + rewrite Zmult_0_r; repeat rewrite ZOdiv_0_r; reflexivity. + apply H1; auto with zarith. + change (Zneg c) with (-Zpos c); + rewrite <- Zopp_mult_distr_r; do 2 rewrite ZOdiv_opp_r. + f_equal; apply H1; auto with zarith. +Qed. (** A last inequality: *) -Theorem Zdiv_mult_le: - forall a b c, 0 <= a -> 0 < b -> 0 <= c -> c*(a/b) <= (c*a)/b. -Proof. - intros a b c H1 H2 H3. - case (Z_mod_lt a b); auto with zarith; intros Hu1 Hu2. - case (Z_mod_lt c b); auto with zarith; intros Hv1 Hv2. +Theorem ZOdiv_mult_le: + forall a b c, 0<=a -> 0<=b -> 0<=c -> c*(a/b) <= (c*a)/b. +Proof. + intros a b c Ha Hb Hc. + destruct (Zle_lt_or_eq _ _ Ha); + [ | subst; rewrite ZOdiv_0_l, Zmult_0_r, ZOdiv_0_l; auto]. + destruct (Zle_lt_or_eq _ _ Hb); + [ | subst; rewrite ZOdiv_0_r, ZOdiv_0_r, Zmult_0_r; auto]. + destruct (Zle_lt_or_eq _ _ Hc); + [ | subst; rewrite ZOdiv_0_l; auto]. + case (ZOmod_lt_pos_pos a b); auto with zarith; intros Hu1 Hu2. + case (ZOmod_lt_pos_pos c b); auto with zarith; intros Hv1 Hv2. apply Zmult_le_reg_r with b; auto with zarith. rewrite <- Zmult_assoc. replace (a / b * b) with (a - a mod b). @@ -786,13 +879,30 @@ Proof. unfold Zminus; apply Zplus_le_compat_l. match goal with |- - ?X <= -?Y => assert (Y <= X); auto with zarith end. apply Zle_trans with ((c mod b) * (a mod b)); auto with zarith. - rewrite Zmult_mod; auto with zarith. - apply (Zmod_le ((c mod b) * (a mod b)) b); auto with zarith. + rewrite ZOmult_mod; auto with zarith. + apply (ZOmod_le ((c mod b) * (a mod b)) b); auto with zarith. apply Zmult_le_compat_r; auto with zarith. - apply (Zmod_le c b); auto. - pattern (c * a) at 1; rewrite (Z_div_mod_eq (c * a) b); try ring; + apply (ZOmod_le c b); auto. + pattern (c * a) at 1; rewrite (ZO_div_mod_eq (c * a) b); try ring; auto with zarith. - pattern a at 1; rewrite (Z_div_mod_eq a b); try ring; auto with zarith. + pattern a at 1; rewrite (ZO_div_mod_eq a b); try ring; auto with zarith. +Qed. + +(** ZOmod is related to divisibility (see more in Znumtheory) *) + +Lemma ZOmod_divides : forall a b, + a mod b = 0 <-> exists c, a = b*c. +Proof. + split; intros. + exists (a/b). + pattern a at 1; rewrite (ZO_div_mod_eq a b). + rewrite H; auto with zarith. + destruct H as [c Hc]. + destruct (Z_eq_dec b 0). + subst b; simpl in *; subst a; auto. + symmetry. + apply ZOmod_unique_full with c; auto with zarith. + red; romega with *. Qed. (** * Interaction with "historic" Zdiv *) @@ -810,12 +920,14 @@ Proof. symmetry; apply ZO_div_mod_eq; auto with *. Qed. -Theorem ZOdiv_Zdiv_pos : forall a b, 0 <= a -> 0 < b -> +Theorem ZOdiv_Zdiv_pos : forall a b, 0 <= a -> 0 <= b -> a/b = Zdiv.Zdiv a b. Proof. - intros a b Ha Hb; generalize (ZOdiv_eucl_Zdiv_eucl_pos a b Ha Hb); - intuition. -Qed. + intros a b Ha Hb. + destruct (Zle_lt_or_eq _ _ Hb). + generalize (ZOdiv_eucl_Zdiv_eucl_pos a b Ha H); intuition. + subst; rewrite ZOdiv_0_r, Zdiv.Zdiv_0_r; reflexivity. +Qed. Theorem ZOmod_Zmod_pos : forall a b, 0 <= a -> 0 < b -> a mod b = Zdiv.Zmod a b. @@ -824,12 +936,11 @@ Proof. intuition. Qed. -(* NOT FINISHED YET !! - -(** Modulo are null at the same places *) +(** Modulos are null at the same places *) Theorem ZOmod_Zmod_zero : forall a b, b<>0 -> - a mod b = 0 <-> Zdiv.Zmod a b = 0. - -*) -*)
\ No newline at end of file + (a mod b = 0 <-> Zdiv.Zmod a b = 0). +Proof. + intros. + rewrite ZOmod_divides, Zdiv.Zmod_divides; intuition. +Qed. diff --git a/theories/ZArith/Zdiv.v b/theories/ZArith/Zdiv.v index 780413610e..85eac3c307 100644 --- a/theories/ZArith/Zdiv.v +++ b/theories/ZArith/Zdiv.v @@ -922,9 +922,11 @@ Module EqualityModulo (M:SomeNumber). End EqualityModulo. -Lemma Zdiv_Zdiv : forall a b c, b>0 -> c>0 -> (a/b)/c = a/(b*c). +Lemma Zdiv_Zdiv : forall a b c, 0<=b -> 0<=c -> (a/b)/c = a/(b*c). Proof. - intros a b c H H0. + intros a b c Hb Hc. + destruct (Zle_lt_or_eq _ _ Hb); [ | subst; rewrite Zdiv_0_r, Zdiv_0_r, Zdiv_0_l; auto]. + destruct (Zle_lt_or_eq _ _ Hc); [ | subst; rewrite Zmult_0_r, Zdiv_0_r, Zdiv_0_r; auto]. pattern a at 2;rewrite (Z_div_mod_eq_full a b);auto with zarith. pattern (a/b) at 2;rewrite (Z_div_mod_eq_full (a/b) c);auto with zarith. replace (b * (c * (a / b / c) + (a / b) mod c) + a mod b) with @@ -954,9 +956,11 @@ Qed. (** A last inequality: *) Theorem Zdiv_mult_le: - forall a b c, 0 <= a -> 0 < b -> 0 <= c -> c*(a/b) <= (c*a)/b. + forall a b c, 0<=a -> 0<=b -> 0<=c -> c*(a/b) <= (c*a)/b. Proof. intros a b c H1 H2 H3. + destruct (Zle_lt_or_eq _ _ H2); + [ | subst; rewrite Zdiv_0_r, Zdiv_0_r, Zmult_0_r; auto]. case (Z_mod_lt a b); auto with zarith; intros Hu1 Hu2. case (Z_mod_lt c b); auto with zarith; intros Hv1 Hv2. apply Zmult_le_reg_r with b; auto with zarith. @@ -976,6 +980,20 @@ Proof. pattern a at 1; rewrite (Z_div_mod_eq a b); try ring; auto with zarith. Qed. +(** Zmod is related to divisibility (see more in Znumtheory) *) + +Lemma Zmod_divides : forall a b, b<>0 -> + (a mod b = 0 <-> exists c, a = b*c). +Proof. + split; intros. + exists (a/b). + pattern a at 1; rewrite (Z_div_mod_eq_full a b); auto with zarith. + destruct H0 as [c Hc]. + symmetry. + apply Zmod_unique_full with c; auto with zarith. + red; omega with *. +Qed. + (** * Compatibility *) (** Weaker results kept only for compatibility *) |
