aboutsummaryrefslogtreecommitdiff
path: root/theories/Ints/Z/ZDivModAux.v
diff options
context:
space:
mode:
authoraspiwack2007-05-11 17:00:58 +0000
committeraspiwack2007-05-11 17:00:58 +0000
commit2dbe106c09b60690b87e31e58d505b1f4e05b57f (patch)
tree4476a715b796769856e67f6eb5bb6eb60ce6fb57 /theories/Ints/Z/ZDivModAux.v
parent95f043a4aa63630de133e667f3da1f48a8f9c4f3 (diff)
Processor integers + Print assumption (see coqdev mailing list for the
details). git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@9821 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'theories/Ints/Z/ZDivModAux.v')
-rw-r--r--theories/Ints/Z/ZDivModAux.v452
1 files changed, 452 insertions, 0 deletions
diff --git a/theories/Ints/Z/ZDivModAux.v b/theories/Ints/Z/ZDivModAux.v
new file mode 100644
index 0000000000..d07b92d80e
--- /dev/null
+++ b/theories/Ints/Z/ZDivModAux.v
@@ -0,0 +1,452 @@
+
+(*************************************************************)
+(* This file is distributed under the terms of the *)
+(* GNU Lesser General Public License Version 2.1 *)
+(*************************************************************)
+(* Benjamin.Gregoire@inria.fr Laurent.Thery@inria.fr *)
+(*************************************************************)
+
+(**********************************************************************
+ ZDivModAux.v
+
+ Auxillary functions & Theorems for Zdiv and Zmod
+ **********************************************************************)
+
+Require Export ZArith.
+Require Export Znumtheory.
+Require Export Tactic.
+Require Import ZAux.
+Require Import ZPowerAux.
+
+Open Local Scope Z_scope.
+
+Hint Extern 2 (Zle _ _) =>
+ (match goal with
+ |- Zpos _ <= Zpos _ => exact (refl_equal _)
+ | H: _ <= ?p |- _ <= ?p => apply Zle_trans with (2 := H)
+ | H: _ < ?p |- _ <= ?p =>
+ apply Zlt_le_weak; apply Zle_lt_trans with (2 := H)
+ end).
+
+Hint Extern 2 (Zlt _ _) =>
+ (match goal with
+ |- Zpos _ < Zpos _ => exact (refl_equal _)
+| H: _ <= ?p |- _ <= ?p => apply Zlt_le_trans with (2 := H)
+| H: _ < ?p |- _ <= ?p => apply Zle_lt_trans with (2 := H)
+ end).
+
+Hint Resolve Zlt_gt Zle_ge: zarith.
+
+(**************************************
+ Properties Zmod
+**************************************)
+
+ Theorem Zmod_mult:
+ forall a b n, 0 < n -> (a * b) mod n = ((a mod n) * (b mod n)) mod n.
+ Proof.
+ intros a b n H.
+ pattern a at 1; rewrite (Z_div_mod_eq a n); auto with zarith.
+ pattern b at 1; rewrite (Z_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) +
+ (((n*(a/n)) * (b/n) + (b mod n)*(a / n)) + (a mod n) * (b / n)) * n);
+ auto with zarith.
+ apply Z_mod_plus; auto with zarith.
+ ring.
+ Qed.
+
+ Theorem Zmod_plus:
+ forall a b n, 0 < n -> (a + b) mod n = (a mod n + b mod n) mod n.
+ Proof.
+ intros a b n H.
+ pattern a at 1; rewrite (Z_div_mod_eq a n); auto with zarith.
+ pattern b at 1; rewrite (Z_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); auto with zarith.
+ apply Z_mod_plus; auto with zarith.
+ ring.
+ Qed.
+
+ Theorem Zmod_mod: forall a n, 0 < n -> (a mod n) mod n = a mod n.
+ Proof.
+ intros a n H.
+ pattern a at 2; rewrite (Z_div_mod_eq a n); auto with zarith.
+ rewrite Zplus_comm; rewrite Zmult_comm.
+ apply sym_equal; apply Z_mod_plus; auto with zarith.
+ Qed.
+
+ Theorem Zmod_def_small: forall a n, 0 <= a < n -> a mod n = a.
+ Proof.
+ intros a n [H1 H2]; unfold Zmod.
+ generalize (Z_div_mod a n); case (Zdiv_eucl a n).
+ intros q r H3; case H3; clear H3; auto with zarith.
+ intros H4 [H5 H6].
+ case (Zle_or_lt q (- 1)); intros H7.
+ contradict H1; apply Zlt_not_le.
+ subst a.
+ apply Zle_lt_trans with (n * - 1 + r); auto with zarith.
+ case (Zle_lt_or_eq 0 q); auto with zarith; intros H8.
+ contradict H2; apply Zle_not_lt.
+ apply Zle_trans with (n * 1 + r); auto with zarith.
+ rewrite H4; auto with zarith.
+ subst a; subst q; auto with zarith.
+ Qed.
+
+ Theorem Zmod_minus:
+ forall a b n, 0 < n -> (a - b) mod n = (a mod n - b mod n) mod n.
+ Proof.
+ intros a b n H; 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 Zmod_plus; auto with zarith.
+ rewrite Zmod_mult; auto with zarith.
+ rewrite (fun x y => Zmod_plus x ((-1) * y)); auto with zarith.
+ rewrite Zmod_mult; auto with zarith.
+ rewrite (fun x => Zmod_mult x (b mod n)); auto with zarith.
+ repeat rewrite Zmod_mod; auto.
+ Qed.
+
+ Theorem Zmod_le: forall a n, 0 < n -> 0 <= a -> (Zmod a n) <= a.
+ Proof.
+ intros a n H1 H2; case (Zle_or_lt n a); intros H3.
+ case (Z_mod_lt a n); auto with zarith.
+ rewrite Zmod_def_small; auto with zarith.
+ Qed.
+
+ Theorem Zmod_le_first: forall a b, 0 <= a -> 0 < b -> 0 <= a mod b <= a.
+ Proof.
+ intros a b H H1;case (Z_mod_lt a b);auto with zarith;intros H2 H3;split;auto.
+ case (Zle_or_lt b a); intros H4; auto with zarith.
+ rewrite Zmod_def_small; auto with zarith.
+ Qed.
+
+
+(**************************************
+ Properties of Zdivide
+**************************************)
+
+ Theorem Zdiv_pos: forall a b, 0 < b -> 0 <= a -> 0 <= a / b.
+ Proof.
+ intros; apply Zge_le; apply Z_div_ge0; auto with zarith.
+ Qed.
+ Hint Resolve Zdiv_pos: zarith.
+
+ 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.
+ apply Zmult_le_reg_r with b; auto with zarith.
+ rewrite <- Zmult_assoc.
+ replace (a / b * b) with (a - a mod b).
+ replace (c * a / b * b) with (c * a - (c * a) mod b).
+ rewrite Zmult_minus_distr_l.
+ 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 Zmod_mult; case (Zmod_le_first ((c mod b) * (a mod b)) b);
+ auto with zarith.
+ apply Zmult_le_compat_r; auto with zarith.
+ case (Zmod_le_first c b); auto.
+ pattern (c * a) at 1; rewrite (Z_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.
+ Qed.
+
+ Theorem Zdiv_unique:
+ forall n d q r, 0 < d -> ( 0 <= r < d ) -> n = d * q + r -> q = n / d.
+ Proof.
+ intros n d q r H H0 H1.
+ assert (H2: n = d * (n / d) + n mod d).
+ apply Z_div_mod_eq; auto with zarith.
+ assert (H3: 0 <= n mod d < d ).
+ apply Z_mod_lt; auto with zarith.
+ case (Ztrichotomy q (n / d)); auto.
+ intros H4.
+ absurd (n < n); auto with zarith.
+ pattern n at 1; rewrite H1; rewrite H2.
+ apply Zlt_le_trans with (d * (q + 1)); auto with zarith.
+ rewrite Zmult_plus_distr_r; auto with zarith.
+ apply Zle_trans with (d * (n / d)); auto with zarith.
+ intros tmp; case tmp; auto; intros H4; clear tmp.
+ absurd (n < n); auto with zarith.
+ pattern n at 2; rewrite H1; rewrite H2.
+ apply Zlt_le_trans with (d * (n / d + 1)); auto with zarith.
+ rewrite Zmult_plus_distr_r; auto with zarith.
+ apply Zle_trans with (d * q); auto with zarith.
+ Qed.
+
+ Theorem Zmod_unique:
+ forall n d q r, 0 < d -> ( 0 <= r < d ) -> n = d * q + r -> r = n mod d.
+ Proof.
+ intros n d q r H H0 H1.
+ assert (H2: n = d * (n / d) + n mod d).
+ apply Z_div_mod_eq; auto with zarith.
+ rewrite (Zdiv_unique n d q r) in H1; auto.
+ apply (Zplus_reg_l (d * (n / d))); auto with zarith.
+ Qed.
+
+ Theorem Zmod_Zmult_compat_l: forall a b c,
+ 0 < b -> 0 < c -> c * a mod (c * b) = c * (a mod b).
+ Proof.
+ intros a b c H2 H3.
+ pattern a at 1; rewrite (Z_div_mod_eq a b); auto with zarith.
+ rewrite Zplus_comm; rewrite Zmult_plus_distr_r.
+ rewrite Zmult_assoc; rewrite (Zmult_comm (c * b)).
+ rewrite Z_mod_plus; auto with zarith.
+ apply Zmod_def_small; split; auto with zarith.
+ apply Zmult_le_0_compat; auto with zarith.
+ destruct (Z_mod_lt a b);auto with zarith.
+ apply Zmult_lt_compat_l; auto with zarith.
+ destruct (Z_mod_lt a b);auto with zarith.
+ Qed.
+
+ Theorem Zdiv_Zmult_compat_l:
+ forall a b c, 0 <= a -> 0 < b -> 0 < c -> c * a / (c * b) = a / b.
+ Proof.
+ intros a b c H1 H2 H3; case (Z_mod_lt a b); auto with zarith; intros H4 H5.
+ apply Zdiv_unique with (a mod b); auto with zarith.
+ apply Zmult_reg_l with c; auto with zarith.
+ rewrite Zmult_plus_distr_r; rewrite <- Zmod_Zmult_compat_l; auto with zarith.
+ rewrite Zmult_assoc; apply Z_div_mod_eq; auto with zarith.
+ Qed.
+
+ Theorem Zdiv_0: forall a, 0 < a -> 0 / a = 0.
+ Proof.
+ intros a H;apply sym_equal;apply Zdiv_unique with (r := 0); auto with zarith.
+ Qed.
+
+ Theorem Zdiv_le_upper_bound:
+ forall a b q, 0 <= a -> 0 < b -> a <= q * b -> a / b <= q.
+ Proof.
+ intros a b q H1 H2 H3.
+ apply Zmult_le_reg_r with b; auto with zarith.
+ apply Zle_trans with (2 := H3).
+ pattern a at 2; rewrite (Z_div_mod_eq a b); auto with zarith.
+ rewrite (Zmult_comm b); case (Z_mod_lt a b); auto with zarith.
+ Qed.
+
+ Theorem Zdiv_lt_upper_bound:
+ forall a b q, 0 <= a -> 0 < b -> a < q * b -> a / b < q.
+ Proof.
+ intros a b q H1 H2 H3.
+ apply Zmult_lt_reg_r with b; auto with zarith.
+ apply Zle_lt_trans with (2 := H3).
+ pattern a at 2; rewrite (Z_div_mod_eq a b); auto with zarith.
+ rewrite (Zmult_comm b); case (Z_mod_lt a b); auto with zarith.
+ Qed.
+
+ Theorem Zdiv_le_lower_bound:
+ forall a b q, 0 <= a -> 0 < b -> q * b <= a -> q <= a / b.
+ Proof.
+ intros a b q H1 H2 H3.
+ assert (q < a / b + 1); auto with zarith.
+ apply Zmult_lt_reg_r with b; auto with zarith.
+ apply Zle_lt_trans with (1 := H3).
+ pattern a at 1; rewrite (Z_div_mod_eq a b); auto with zarith.
+ rewrite Zmult_plus_distr_l; rewrite (Zmult_comm b); case (Z_mod_lt a b);
+ auto with zarith.
+ Qed.
+
+ Theorem Zmult_mod_distr_l:
+ forall a b c, 0 < a -> 0 < c -> (a * b) mod (a * c) = a * (b mod c).
+ Proof.
+ intros a b c H Hc.
+ apply sym_equal; apply Zmod_unique with (b / c); auto with zarith.
+ apply Zmult_lt_0_compat; auto.
+ case (Z_mod_lt b c); auto with zarith; intros; split; auto with zarith.
+ apply Zmult_lt_compat_l; auto.
+ rewrite <- Zmult_assoc; rewrite <- Zmult_plus_distr_r.
+ rewrite <- Z_div_mod_eq; auto with zarith.
+ Qed.
+
+
+ Theorem Zmod_distr: forall a b r t, 0 <= a <= b -> 0 <= r -> 0 <= t < 2 ^a ->
+ (2 ^a * r + t) mod (2 ^ b) = (2 ^a * r) mod (2 ^ b) + t.
+ Proof.
+ intros a b r t (H1, H2) H3 (H4, H5).
+ assert (t < 2 ^ b).
+ apply Zlt_le_trans with (1:= H5); auto with zarith.
+ apply Zpower_le_monotone; auto with zarith.
+ rewrite Zmod_plus; auto with zarith.
+ rewrite Zmod_def_small with (a := t); auto with zarith.
+ apply Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ assert (0 <= 2 ^a * r); auto with zarith.
+ apply Zplus_le_0_compat; auto with zarith.
+ match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end;
+ auto with zarith.
+ pattern (2 ^ b) at 2; replace (2 ^ b) with ((2 ^ b - 2 ^a) + 2 ^ a);
+ try ring.
+ apply Zplus_le_lt_compat; auto with zarith.
+ replace b with ((b - a) + a); try ring.
+ rewrite Zpower_exp; auto with zarith.
+ pattern (2 ^a) at 4; rewrite <- (Zmult_1_l (2 ^a));
+ try rewrite <- Zmult_minus_distr_r.
+ rewrite (Zmult_comm (2 ^(b - a))); rewrite Zmult_mod_distr_l;
+ auto with zarith.
+ rewrite (Zmult_comm (2 ^a)); apply Zmult_le_compat_r; auto with zarith.
+ match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end;
+ auto with zarith.
+ Qed.
+
+ Theorem Zmult_mod_distr_r:
+ forall a b c : Z, 0 < a -> 0 < c -> (b * a) mod (c * a) = (b mod c) * a.
+ Proof.
+ intros; repeat rewrite (fun x => (Zmult_comm x a)).
+ apply Zmult_mod_distr_l; auto.
+ Qed.
+
+ Theorem Z_div_plus_l: forall a b c : Z, 0 < b -> (a * b + c) / b = a + c / b.
+ Proof.
+ intros a b c H; rewrite Zplus_comm; rewrite Z_div_plus;
+ try apply Zplus_comm; auto with zarith.
+ Qed.
+
+ Theorem Zmod_shift_r:
+ forall a b r t, 0 <= a <= b -> 0 <= r -> 0 <= t < 2 ^a ->
+ (r * 2 ^a + t) mod (2 ^ b) = (r * 2 ^a) mod (2 ^ b) + t.
+ Proof.
+ intros a b r t (H1, H2) H3 (H4, H5).
+ assert (t < 2 ^ b).
+ apply Zlt_le_trans with (1:= H5); auto with zarith.
+ apply Zpower_le_monotone; auto with zarith.
+ rewrite Zmod_plus; auto with zarith.
+ rewrite Zmod_def_small with (a := t); auto with zarith.
+ apply Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ assert (0 <= 2 ^a * r); auto with zarith.
+ apply Zplus_le_0_compat; auto with zarith.
+ match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end;
+ auto with zarith.
+ pattern (2 ^ b) at 2;replace (2 ^ b) with ((2 ^ b - 2 ^a) + 2 ^ a); try ring.
+ apply Zplus_le_lt_compat; auto with zarith.
+ replace b with ((b - a) + a); try ring.
+ rewrite Zpower_exp; auto with zarith.
+ pattern (2 ^a) at 4; rewrite <- (Zmult_1_l (2 ^a));
+ try rewrite <- Zmult_minus_distr_r.
+ repeat rewrite (fun x => Zmult_comm x (2 ^ a)); rewrite Zmult_mod_distr_l;
+ auto with zarith.
+ apply Zmult_le_compat_l; auto with zarith.
+ match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end;
+ auto with zarith.
+ Qed.
+
+ Theorem Zdiv_lt_0: forall a b, 0 <= a < b -> a / b = 0.
+ intros a b H; apply sym_equal; apply Zdiv_unique with a; auto with zarith.
+ Qed.
+
+ Theorem Zmod_mult_0: forall a b, 0 < b -> (a * b) mod b = 0.
+ Proof.
+ intros a b H; rewrite <- (Zplus_0_l (a * b)); rewrite Z_mod_plus;
+ auto with zarith.
+ Qed.
+
+ Theorem Zdiv_shift_r:
+ forall a b r t, 0 <= a <= b -> 0 <= r -> 0 <= t < 2 ^a ->
+ (r * 2 ^a + t) / (2 ^ b) = (r * 2 ^a) / (2 ^ b).
+ Proof.
+ intros a b r t (H1, H2) H3 (H4, H5).
+ assert (Eq: t < 2 ^ b); auto with zarith.
+ apply Zlt_le_trans with (1 := H5); auto with zarith.
+ apply Zpower_le_monotone; auto with zarith.
+ pattern (r * 2 ^ a) at 1; rewrite Z_div_mod_eq with (b := 2 ^ b);
+ auto with zarith.
+ rewrite <- Zplus_assoc.
+ rewrite <- Zmod_shift_r; auto with zarith.
+ rewrite (Zmult_comm (2 ^ b)); rewrite Z_div_plus_l; auto with zarith.
+ rewrite (fun x y => @Zdiv_lt_0 (x mod y)); auto with zarith.
+ match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end;
+ auto with zarith.
+ Qed.
+
+
+ Theorem Zpos_minus:
+ forall a b, Zpos a < Zpos b -> Zpos (b- a) = Zpos b - Zpos a.
+ Proof.
+ intros a b H.
+ repeat rewrite Zpos_eq_Z_of_nat_o_nat_of_P; autorewrite with pos_morph;
+ auto with zarith.
+ rewrite inj_minus1; auto with zarith.
+ match goal with |- (?X <= ?Y)%nat =>
+ case (le_or_lt X Y); auto; intro tmp; absurd (Z_of_nat X < Z_of_nat Y);
+ try apply Zle_not_lt; auto with zarith
+ end.
+ repeat rewrite <- Zpos_eq_Z_of_nat_o_nat_of_P; auto with zarith.
+ generalize (Zlt_gt _ _ H); auto.
+ Qed.
+
+ Theorem Zdiv_Zmult_compat_r:
+ forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> a * c / (b * c) = a / b.
+ Proof.
+ intros a b c H H1 H2; repeat rewrite (fun x => Zmult_comm x c);
+ apply Zdiv_Zmult_compat_l; auto.
+ Qed.
+
+
+ Lemma shift_unshift_mod : forall n p a,
+ 0 <= a < 2^n ->
+ 0 < p < n ->
+ a * 2^p = a / 2^(n - p) * 2^n + (a*2^p) mod 2^n.
+ Proof.
+ intros n p a H1 H2.
+ pattern (a*2^p) at 1;replace (a*2^p) with
+ (a*2^p/2^n * 2^n + a*2^p mod 2^n).
+ 2:symmetry;rewrite (Zmult_comm (a*2^p/2^n));apply Z_div_mod_eq.
+ replace (a * 2 ^ p / 2 ^ n) with (a / 2 ^ (n - p));trivial.
+ replace (2^n) with (2^(n-p)*2^p).
+ symmetry;apply Zdiv_Zmult_compat_r.
+ destruct H1;trivial.
+ apply Zpower_lt_0;auto with zarith.
+ apply Zpower_lt_0;auto with zarith.
+ rewrite <- Zpower_exp.
+ replace (n-p+p) with n;trivial. ring.
+ omega. omega.
+ apply Zlt_gt. apply Zpower_lt_0;auto with zarith.
+ Qed.
+
+ Lemma Zdiv_Zdiv : forall a b c, 0 < b -> 0 < c -> (a/b)/c = a / (b*c).
+ Proof.
+ intros a b c H H0.
+ pattern a at 2;rewrite (Z_div_mod_eq a b);auto with zarith.
+ pattern (a/b) at 2;rewrite (Z_div_mod_eq (a/b) c);auto with zarith.
+ 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));try ring.
+ rewrite Z_div_plus_l;auto with zarith.
+ rewrite (Zdiv_lt_0 (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.
+ apply Zmult_lt_0_compat;auto with zarith.
+ Qed.
+
+ Lemma div_le_0 : forall p x, 0 <= x -> 0 <= x / 2 ^ p.
+ Proof.
+ intros p x Hle;destruct (Z_le_gt_dec 0 p).
+ apply Zdiv_le_lower_bound;auto with zarith.
+ replace (2^p) with 0.
+ destruct x;compute;intro;discriminate.
+ destruct p;trivial;discriminate z.
+ Qed.
+
+ Lemma div_lt : forall p x y, 0 <= x < y -> x / 2^p < y.
+ Proof.
+ intros p x y H;destruct (Z_le_gt_dec 0 p).
+ apply Zdiv_lt_upper_bound;auto with zarith.
+ apply Zlt_le_trans with y;auto with zarith.
+ rewrite <- (Zmult_1_r y);apply Zmult_le_compat;auto with zarith.
+ assert (0 < 2^p);auto with zarith.
+ replace (2^p) with 0.
+ destruct x;change (0<y);auto with zarith.
+ destruct p;trivial;discriminate z.
+ Qed.
+