author | haftmann |
Sun, 11 Sep 2022 16:21:20 +0000 | |
changeset 76120 | 3ae579092045 |
parent 76106 | 98cab94326d4 |
child 76141 | e7497a1de8b9 |
permissions | -rw-r--r-- |
3366 | 1 |
(* Title: HOL/Divides.thy |
2 |
Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
|
6865
5577ffe4c2f1
now div and mod are overloaded; dvd is polymorphic
paulson
parents:
3366
diff
changeset
|
3 |
Copyright 1999 University of Cambridge |
18154 | 4 |
*) |
3366 | 5 |
|
64785 | 6 |
section \<open>More on quotient and remainder\<close> |
3366 | 7 |
|
15131 | 8 |
theory Divides |
66817 | 9 |
imports Parity |
15131 | 10 |
begin |
3366 | 11 |
|
66817 | 12 |
subsection \<open>More on division\<close> |
60758 | 13 |
|
75875
48d032035744
streamlined primitive definitions for integer division
haftmann
parents:
75669
diff
changeset
|
14 |
subsubsection \<open>Monotonicity in the First Argument (Dividend)\<close> |
48d032035744
streamlined primitive definitions for integer division
haftmann
parents:
75669
diff
changeset
|
15 |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
16 |
lemma unique_quotient_lemma: |
68626 | 17 |
assumes "b * q' + r' \<le> b * q + r" "0 \<le> r'" "r' < b" "r < b" shows "q' \<le> (q::int)" |
18 |
proof - |
|
19 |
have "r' + b * (q'-q) \<le> r" |
|
20 |
using assms by (simp add: right_diff_distrib) |
|
21 |
moreover have "0 < b * (1 + q - q') " |
|
22 |
using assms by (simp add: right_diff_distrib distrib_left) |
|
23 |
moreover have "b * q' < b * (1 + q)" |
|
24 |
using assms by (simp add: right_diff_distrib distrib_left) |
|
25 |
ultimately show ?thesis |
|
26 |
using assms by (simp add: mult_less_cancel_left) |
|
27 |
qed |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
28 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
29 |
lemma unique_quotient_lemma_neg: |
60868
dd18c33c001e
direct bootstrap of integer division from natural division
haftmann
parents:
60867
diff
changeset
|
30 |
"b * q' + r' \<le> b*q + r \<Longrightarrow> r \<le> 0 \<Longrightarrow> b < r \<Longrightarrow> b < r' \<Longrightarrow> q \<le> (q'::int)" |
75669
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
31 |
using unique_quotient_lemma[where b = "-b" and r = "-r'" and r'="-r"] by auto |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
32 |
|
68631 | 33 |
lemma zdiv_mono1: |
75875
48d032035744
streamlined primitive definitions for integer division
haftmann
parents:
75669
diff
changeset
|
34 |
\<open>a div b \<le> a' div b\<close> |
48d032035744
streamlined primitive definitions for integer division
haftmann
parents:
75669
diff
changeset
|
35 |
if \<open>a \<le> a'\<close> \<open>0 < b\<close> |
48d032035744
streamlined primitive definitions for integer division
haftmann
parents:
75669
diff
changeset
|
36 |
for a b b' :: int |
68631 | 37 |
proof (rule unique_quotient_lemma) |
38 |
show "b * (a div b) + a mod b \<le> b * (a' div b) + a' mod b" |
|
75875
48d032035744
streamlined primitive definitions for integer division
haftmann
parents:
75669
diff
changeset
|
39 |
using \<open>a \<le> a'\<close> by auto |
48d032035744
streamlined primitive definitions for integer division
haftmann
parents:
75669
diff
changeset
|
40 |
qed (use that in auto) |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
41 |
|
68631 | 42 |
lemma zdiv_mono1_neg: |
43 |
fixes b::int |
|
44 |
assumes "a \<le> a'" "b < 0" shows "a' div b \<le> a div b" |
|
45 |
proof (rule unique_quotient_lemma_neg) |
|
46 |
show "b * (a div b) + a mod b \<le> b * (a' div b) + a' mod b" |
|
47 |
using assms(1) by auto |
|
48 |
qed (use assms in auto) |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
49 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
50 |
|
60758 | 51 |
subsubsection \<open>Monotonicity in the Second Argument (Divisor)\<close> |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
52 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
53 |
lemma q_pos_lemma: |
68631 | 54 |
fixes q'::int |
55 |
assumes "0 \<le> b'*q' + r'" "r' < b'" "0 < b'" |
|
56 |
shows "0 \<le> q'" |
|
57 |
proof - |
|
58 |
have "0 < b'* (q' + 1)" |
|
59 |
using assms by (simp add: distrib_left) |
|
60 |
with assms show ?thesis |
|
61 |
by (simp add: zero_less_mult_iff) |
|
62 |
qed |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
63 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
64 |
lemma zdiv_mono2_lemma: |
68631 | 65 |
fixes q'::int |
66 |
assumes eq: "b*q + r = b'*q' + r'" and le: "0 \<le> b'*q' + r'" and "r' < b'" "0 \<le> r" "0 < b'" "b' \<le> b" |
|
67 |
shows "q \<le> q'" |
|
68 |
proof - |
|
69 |
have "0 \<le> q'" |
|
70 |
using q_pos_lemma le \<open>r' < b'\<close> \<open>0 < b'\<close> by blast |
|
71 |
moreover have "b*q = r' - r + b'*q'" |
|
72 |
using eq by linarith |
|
73 |
ultimately have "b*q < b* (q' + 1)" |
|
74 |
using mult_right_mono assms unfolding distrib_left by fastforce |
|
75 |
with assms show ?thesis |
|
76 |
by (simp add: mult_less_cancel_left_pos) |
|
77 |
qed |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
78 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
79 |
lemma zdiv_mono2: |
68631 | 80 |
fixes a::int |
81 |
assumes "0 \<le> a" "0 < b'" "b' \<le> b" shows "a div b \<le> a div b'" |
|
82 |
proof (rule zdiv_mono2_lemma) |
|
83 |
have "b \<noteq> 0" |
|
84 |
using assms by linarith |
|
85 |
show "b * (a div b) + a mod b = b' * (a div b') + a mod b'" |
|
86 |
by simp |
|
87 |
qed (use assms in auto) |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
88 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
89 |
lemma zdiv_mono2_neg_lemma: |
68631 | 90 |
fixes q'::int |
91 |
assumes "b*q + r = b'*q' + r'" "b'*q' + r' < 0" "r < b" "0 \<le> r'" "0 < b'" "b' \<le> b" |
|
92 |
shows "q' \<le> q" |
|
93 |
proof - |
|
94 |
have "b'*q' < 0" |
|
95 |
using assms by linarith |
|
96 |
with assms have "q' \<le> 0" |
|
97 |
by (simp add: mult_less_0_iff) |
|
98 |
have "b*q' \<le> b'*q'" |
|
99 |
by (simp add: \<open>q' \<le> 0\<close> assms(6) mult_right_mono_neg) |
|
100 |
then have "b*q' < b* (q + 1)" |
|
101 |
using assms by (simp add: distrib_left) |
|
102 |
then show ?thesis |
|
103 |
using assms by (simp add: mult_less_cancel_left) |
|
104 |
qed |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
105 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
106 |
lemma zdiv_mono2_neg: |
68631 | 107 |
fixes a::int |
108 |
assumes "a < 0" "0 < b'" "b' \<le> b" shows "a div b' \<le> a div b" |
|
109 |
proof (rule zdiv_mono2_neg_lemma) |
|
110 |
have "b \<noteq> 0" |
|
111 |
using assms by linarith |
|
112 |
show "b * (a div b) + a mod b = b' * (a div b') + a mod b'" |
|
113 |
by simp |
|
114 |
qed (use assms in auto) |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
115 |
|
75881 | 116 |
|
60758 | 117 |
subsubsection \<open>Quotients of Signs\<close> |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
118 |
|
67083 | 119 |
lemma div_eq_minus1: "0 < b \<Longrightarrow> - 1 div b = - 1" for b :: int |
120 |
by (simp add: divide_int_def) |
|
60868
dd18c33c001e
direct bootstrap of integer division from natural division
haftmann
parents:
60867
diff
changeset
|
121 |
|
67083 | 122 |
lemma zmod_minus1: "0 < b \<Longrightarrow> - 1 mod b = b - 1" for b :: int |
123 |
by (auto simp add: modulo_int_def) |
|
60868
dd18c33c001e
direct bootstrap of integer division from natural division
haftmann
parents:
60867
diff
changeset
|
124 |
|
71991 | 125 |
lemma minus_mod_int_eq: |
126 |
\<open>- k mod l = l - 1 - (k - 1) mod l\<close> if \<open>l \<ge> 0\<close> for k l :: int |
|
127 |
proof (cases \<open>l = 0\<close>) |
|
128 |
case True |
|
129 |
then show ?thesis |
|
130 |
by simp |
|
131 |
next |
|
132 |
case False |
|
133 |
with that have \<open>l > 0\<close> |
|
134 |
by simp |
|
135 |
then show ?thesis |
|
136 |
proof (cases \<open>l dvd k\<close>) |
|
137 |
case True |
|
138 |
then obtain j where \<open>k = l * j\<close> .. |
|
139 |
moreover have \<open>(l * j mod l - 1) mod l = l - 1\<close> |
|
140 |
using \<open>l > 0\<close> by (simp add: zmod_minus1) |
|
141 |
then have \<open>(l * j - 1) mod l = l - 1\<close> |
|
142 |
by (simp only: mod_simps) |
|
143 |
ultimately show ?thesis |
|
144 |
by simp |
|
145 |
next |
|
146 |
case False |
|
75669
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
147 |
moreover have 1: \<open>0 < k mod l\<close> |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
148 |
using \<open>0 < l\<close> False le_less by fastforce |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
149 |
moreover have 2: \<open>k mod l < 1 + l\<close> |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
150 |
using \<open>0 < l\<close> pos_mod_bound[of l k] by linarith |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
151 |
from 1 2 \<open>l > 0\<close> have \<open>(k mod l - 1) mod l = k mod l - 1\<close> |
72610 | 152 |
by (simp add: zmod_trivial_iff) |
71991 | 153 |
ultimately show ?thesis |
75669
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
154 |
by (simp only: zmod_zminus1_eq_if) |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
155 |
(simp add: mod_eq_0_iff_dvd algebra_simps mod_simps) |
71991 | 156 |
qed |
157 |
qed |
|
158 |
||
68631 | 159 |
lemma div_neg_pos_less0: |
160 |
fixes a::int |
|
161 |
assumes "a < 0" "0 < b" |
|
162 |
shows "a div b < 0" |
|
163 |
proof - |
|
164 |
have "a div b \<le> - 1 div b" |
|
68644
242d298526a3
de-applying and simplifying proofs
paulson <lp15@cam.ac.uk>
parents:
68631
diff
changeset
|
165 |
using zdiv_mono1 assms by auto |
68631 | 166 |
also have "... \<le> -1" |
167 |
by (simp add: assms(2) div_eq_minus1) |
|
168 |
finally show ?thesis |
|
169 |
by force |
|
170 |
qed |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
171 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
172 |
lemma div_nonneg_neg_le0: "[| (0::int) \<le> a; b < 0 |] ==> a div b \<le> 0" |
68631 | 173 |
by (drule zdiv_mono1_neg, auto) |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
174 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
175 |
lemma div_nonpos_pos_le0: "[| (a::int) \<le> 0; b > 0 |] ==> a div b \<le> 0" |
68631 | 176 |
by (drule zdiv_mono1, auto) |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
177 |
|
61799 | 178 |
text\<open>Now for some equivalences of the form \<open>a div b >=< 0 \<longleftrightarrow> \<dots>\<close> |
179 |
conditional upon the sign of \<open>a\<close> or \<open>b\<close>. There are many more. |
|
60758 | 180 |
They should all be simp rules unless that causes too much search.\<close> |
33804 | 181 |
|
68631 | 182 |
lemma pos_imp_zdiv_nonneg_iff: |
183 |
fixes a::int |
|
184 |
assumes "0 < b" |
|
185 |
shows "(0 \<le> a div b) = (0 \<le> a)" |
|
186 |
proof |
|
187 |
show "0 \<le> a div b \<Longrightarrow> 0 \<le> a" |
|
188 |
using assms |
|
189 |
by (simp add: linorder_not_less [symmetric]) (blast intro: div_neg_pos_less0) |
|
190 |
next |
|
191 |
assume "0 \<le> a" |
|
192 |
then have "0 div b \<le> a div b" |
|
193 |
using zdiv_mono1 assms by blast |
|
194 |
then show "0 \<le> a div b" |
|
195 |
by auto |
|
196 |
qed |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
197 |
|
60868
dd18c33c001e
direct bootstrap of integer division from natural division
haftmann
parents:
60867
diff
changeset
|
198 |
lemma pos_imp_zdiv_pos_iff: |
dd18c33c001e
direct bootstrap of integer division from natural division
haftmann
parents:
60867
diff
changeset
|
199 |
"0<k \<Longrightarrow> 0 < (i::int) div k \<longleftrightarrow> k \<le> i" |
68631 | 200 |
using pos_imp_zdiv_nonneg_iff[of k i] zdiv_eq_0_iff[of i k] by arith |
201 |
||
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
202 |
lemma neg_imp_zdiv_nonneg_iff: |
68631 | 203 |
fixes a::int |
204 |
assumes "b < 0" |
|
205 |
shows "(0 \<le> a div b) = (a \<le> 0)" |
|
206 |
using assms by (simp add: div_minus_minus [of a, symmetric] pos_imp_zdiv_nonneg_iff del: div_minus_minus) |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
207 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
208 |
(*But not (a div b \<le> 0 iff a\<le>0); consider a=1, b=2 when a div b = 0.*) |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
209 |
lemma pos_imp_zdiv_neg_iff: "(0::int) < b ==> (a div b < 0) = (a < 0)" |
68631 | 210 |
by (simp add: linorder_not_le [symmetric] pos_imp_zdiv_nonneg_iff) |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
211 |
|
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
212 |
(*Again the law fails for \<le>: consider a = -1, b = -2 when a div b = 0*) |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
213 |
lemma neg_imp_zdiv_neg_iff: "b < (0::int) ==> (a div b < 0) = (0 < a)" |
68631 | 214 |
by (simp add: linorder_not_le [symmetric] neg_imp_zdiv_nonneg_iff) |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
215 |
|
33804 | 216 |
lemma nonneg1_imp_zdiv_pos_iff: |
68631 | 217 |
fixes a::int |
218 |
assumes "0 \<le> a" |
|
219 |
shows "a div b > 0 \<longleftrightarrow> a \<ge> b \<and> b>0" |
|
220 |
proof - |
|
221 |
have "0 < a div b \<Longrightarrow> b \<le> a" |
|
222 |
using div_pos_pos_trivial[of a b] assms by arith |
|
223 |
moreover have "0 < a div b \<Longrightarrow> b > 0" |
|
224 |
using assms div_nonneg_neg_le0[of a b] by(cases "b=0"; force) |
|
225 |
moreover have "b \<le> a \<and> 0 < b \<Longrightarrow> 0 < a div b" |
|
226 |
using int_one_le_iff_zero_less[of "a div b"] zdiv_mono1[of b a b] by simp |
|
227 |
ultimately show ?thesis |
|
228 |
by blast |
|
229 |
qed |
|
33804 | 230 |
|
68631 | 231 |
lemma zmod_le_nonneg_dividend: "(m::int) \<ge> 0 \<Longrightarrow> m mod k \<le> m" |
232 |
by (rule split_zmod[THEN iffD2]) (fastforce dest: q_pos_lemma intro: split_mult_pos_le) |
|
60930 | 233 |
|
75876 | 234 |
lemma sgn_div_eq_sgn_mult: |
235 |
\<open>sgn (k div l) = of_bool (k div l \<noteq> 0) * sgn (k * l)\<close> |
|
236 |
for k l :: int |
|
237 |
proof (cases \<open>k div l = 0\<close>) |
|
238 |
case True |
|
239 |
then show ?thesis |
|
240 |
by simp |
|
241 |
next |
|
242 |
case False |
|
243 |
have \<open>0 \<le> \<bar>k\<bar> div \<bar>l\<bar>\<close> |
|
244 |
by (cases \<open>l = 0\<close>) (simp_all add: pos_imp_zdiv_nonneg_iff) |
|
245 |
then have \<open>\<bar>k\<bar> div \<bar>l\<bar> \<noteq> 0 \<longleftrightarrow> 0 < \<bar>k\<bar> div \<bar>l\<bar>\<close> |
|
246 |
by (simp add: less_le) |
|
247 |
also have \<open>\<dots> \<longleftrightarrow> \<bar>k\<bar> \<ge> \<bar>l\<bar>\<close> |
|
248 |
using False nonneg1_imp_zdiv_pos_iff by auto |
|
249 |
finally have *: \<open>\<bar>k\<bar> div \<bar>l\<bar> \<noteq> 0 \<longleftrightarrow> \<bar>l\<bar> \<le> \<bar>k\<bar>\<close> . |
|
250 |
show ?thesis |
|
251 |
using \<open>0 \<le> \<bar>k\<bar> div \<bar>l\<bar>\<close> False |
|
252 |
by (auto simp add: div_eq_div_abs [of k l] div_eq_sgn_abs [of k l] |
|
253 |
sgn_mult sgn_1_pos sgn_1_neg sgn_eq_0_iff nonneg1_imp_zdiv_pos_iff * dest: sgn_not_eq_imp) |
|
254 |
qed |
|
255 |
||
76053 | 256 |
lemma |
257 |
fixes a b q r :: int |
|
258 |
assumes \<open>a = b * q + r\<close> \<open>0 \<le> r\<close> \<open>r < b\<close> |
|
259 |
shows int_div_pos_eq: |
|
260 |
\<open>a div b = q\<close> (is ?Q) |
|
261 |
and int_mod_pos_eq: |
|
262 |
\<open>a mod b = r\<close> (is ?R) |
|
263 |
proof - |
|
264 |
from assms have \<open>(a div b, a mod b) = (q, r)\<close> |
|
265 |
by (cases b q r a rule: euclidean_relationI) |
|
266 |
(auto simp add: division_segment_int_def ac_simps dvd_add_left_iff dest: zdvd_imp_le) |
|
267 |
then show ?Q and ?R |
|
268 |
by simp_all |
|
269 |
qed |
|
270 |
||
271 |
lemma int_div_neg_eq: |
|
272 |
\<open>a div b = q\<close> if \<open>a = b * q + r\<close> \<open>r \<le> 0\<close> \<open>b < r\<close> for a b q r :: int |
|
273 |
using that int_div_pos_eq [of a \<open>- b\<close> \<open>- q\<close> \<open>- r\<close>] by simp_all |
|
274 |
||
275 |
lemma int_mod_neg_eq: |
|
276 |
\<open>a mod b = r\<close> if \<open>a = b * q + r\<close> \<open>r \<le> 0\<close> \<open>b < r\<close> for a b q r :: int |
|
277 |
using that int_div_neg_eq [of a b q r] by simp |
|
278 |
||
60868
dd18c33c001e
direct bootstrap of integer division from natural division
haftmann
parents:
60867
diff
changeset
|
279 |
|
dd18c33c001e
direct bootstrap of integer division from natural division
haftmann
parents:
60867
diff
changeset
|
280 |
subsubsection \<open>Further properties\<close> |
dd18c33c001e
direct bootstrap of integer division from natural division
haftmann
parents:
60867
diff
changeset
|
281 |
|
66817 | 282 |
lemma div_int_pos_iff: |
283 |
"k div l \<ge> 0 \<longleftrightarrow> k = 0 \<or> l = 0 \<or> k \<ge> 0 \<and> l \<ge> 0 |
|
284 |
\<or> k < 0 \<and> l < 0" |
|
285 |
for k l :: int |
|
68631 | 286 |
proof (cases "k = 0 \<or> l = 0") |
287 |
case False |
|
75669
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
288 |
then have *: "k \<noteq> 0" "l \<noteq> 0" |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
289 |
by auto |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
290 |
then have "0 \<le> k div l \<Longrightarrow> \<not> k < 0 \<Longrightarrow> 0 \<le> l" |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
291 |
by (meson neg_imp_zdiv_neg_iff not_le not_less_iff_gr_or_eq) |
68631 | 292 |
then show ?thesis |
75669
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
293 |
using * by (auto simp add: pos_imp_zdiv_nonneg_iff neg_imp_zdiv_nonneg_iff) |
68631 | 294 |
qed auto |
66817 | 295 |
|
296 |
lemma mod_int_pos_iff: |
|
297 |
"k mod l \<ge> 0 \<longleftrightarrow> l dvd k \<or> l = 0 \<and> k \<ge> 0 \<or> l > 0" |
|
298 |
for k l :: int |
|
68631 | 299 |
proof (cases "l > 0") |
300 |
case False |
|
301 |
then show ?thesis |
|
69695 | 302 |
by (simp add: dvd_eq_mod_eq_0) (use neg_mod_sign [of l k] in \<open>auto simp add: le_less not_less\<close>) |
68631 | 303 |
qed auto |
66817 | 304 |
|
68631 | 305 |
text \<open>Simplify expressions in which div and mod combine numerical constants\<close> |
60868
dd18c33c001e
direct bootstrap of integer division from natural division
haftmann
parents:
60867
diff
changeset
|
306 |
|
61944 | 307 |
lemma abs_div: "(y::int) dvd x \<Longrightarrow> \<bar>x div y\<bar> = \<bar>x\<bar> div \<bar>y\<bar>" |
68631 | 308 |
unfolding dvd_def by (cases "y=0") (auto simp add: abs_mult) |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
309 |
|
60758 | 310 |
text\<open>Suggested by Matthias Daum\<close> |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
311 |
lemma int_power_div_base: |
68631 | 312 |
fixes k :: int |
313 |
assumes "0 < m" "0 < k" |
|
314 |
shows "k ^ m div k = (k::int) ^ (m - Suc 0)" |
|
315 |
proof - |
|
316 |
have eq: "k ^ m = k ^ ((m - Suc 0) + Suc 0)" |
|
317 |
by (simp add: assms) |
|
318 |
show ?thesis |
|
319 |
using assms by (simp only: power_add eq) auto |
|
320 |
qed |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
321 |
|
60758 | 322 |
text\<open>Suggested by Matthias Daum\<close> |
68631 | 323 |
lemma int_div_less_self: |
324 |
fixes x::int |
|
325 |
assumes "0 < x" "1 < k" |
|
326 |
shows "x div k < x" |
|
327 |
proof - |
|
328 |
have "nat x div nat k < nat x" |
|
329 |
by (simp add: assms) |
|
330 |
with assms show ?thesis |
|
331 |
by (simp add: nat_div_distrib [symmetric]) |
|
332 |
qed |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
333 |
|
66837 | 334 |
lemma mod_eq_dvd_iff_nat: |
335 |
"m mod q = n mod q \<longleftrightarrow> q dvd m - n" if "m \<ge> n" for m n q :: nat |
|
336 |
proof - |
|
337 |
have "int m mod int q = int n mod int q \<longleftrightarrow> int q dvd int m - int n" |
|
338 |
by (simp add: mod_eq_dvd_iff) |
|
339 |
with that have "int (m mod q) = int (n mod q) \<longleftrightarrow> int q dvd int (m - n)" |
|
340 |
by (simp only: of_nat_mod of_nat_diff) |
|
341 |
then show ?thesis |
|
67118 | 342 |
by simp |
66837 | 343 |
qed |
344 |
||
345 |
lemma mod_eq_nat1E: |
|
346 |
fixes m n q :: nat |
|
347 |
assumes "m mod q = n mod q" and "m \<ge> n" |
|
348 |
obtains s where "m = n + q * s" |
|
349 |
proof - |
|
350 |
from assms have "q dvd m - n" |
|
351 |
by (simp add: mod_eq_dvd_iff_nat) |
|
352 |
then obtain s where "m - n = q * s" .. |
|
353 |
with \<open>m \<ge> n\<close> have "m = n + q * s" |
|
354 |
by simp |
|
355 |
with that show thesis . |
|
356 |
qed |
|
357 |
||
358 |
lemma mod_eq_nat2E: |
|
359 |
fixes m n q :: nat |
|
360 |
assumes "m mod q = n mod q" and "n \<ge> m" |
|
361 |
obtains s where "n = m + q * s" |
|
362 |
using assms mod_eq_nat1E [of n q m] by (auto simp add: ac_simps) |
|
363 |
||
364 |
lemma nat_mod_eq_lemma: |
|
365 |
assumes "(x::nat) mod n = y mod n" and "y \<le> x" |
|
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
366 |
shows "\<exists>q. x = y + n * q" |
75669
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
367 |
using assms by (rule mod_eq_nat1E) (rule exI) |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
368 |
|
60562
24af00b010cf
Amalgamation of the class comm_semiring_1_diff_distrib into comm_semiring_1_cancel. Moving axiom le_add_diff_inverse2 from semiring_numeral_div to linordered_semidom.
paulson <lp15@cam.ac.uk>
parents:
60517
diff
changeset
|
369 |
lemma nat_mod_eq_iff: "(x::nat) mod n = y mod n \<longleftrightarrow> (\<exists>q1 q2. x + n * q1 = y + n * q2)" |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
370 |
(is "?lhs = ?rhs") |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
371 |
proof |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
372 |
assume H: "x mod n = y mod n" |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
373 |
{assume xy: "x \<le> y" |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
374 |
from H have th: "y mod n = x mod n" by simp |
60562
24af00b010cf
Amalgamation of the class comm_semiring_1_diff_distrib into comm_semiring_1_cancel. Moving axiom le_add_diff_inverse2 from semiring_numeral_div to linordered_semidom.
paulson <lp15@cam.ac.uk>
parents:
60517
diff
changeset
|
375 |
from nat_mod_eq_lemma[OF th xy] have ?rhs |
75669
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
376 |
proof |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
377 |
fix q |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
378 |
assume "y = x + n * q" |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
379 |
then have "x + n * q = y + n * 0" |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
380 |
by simp |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
381 |
then show "\<exists>q1 q2. x + n * q1 = y + n * q2" |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
382 |
by blast |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
383 |
qed} |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
384 |
moreover |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
385 |
{assume xy: "y \<le> x" |
60562
24af00b010cf
Amalgamation of the class comm_semiring_1_diff_distrib into comm_semiring_1_cancel. Moving axiom le_add_diff_inverse2 from semiring_numeral_div to linordered_semidom.
paulson <lp15@cam.ac.uk>
parents:
60517
diff
changeset
|
386 |
from nat_mod_eq_lemma[OF H xy] have ?rhs |
75669
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
387 |
proof |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
388 |
fix q |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
389 |
assume "x = y + n * q" |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
390 |
then have "x + n * 0 = y + n * q" |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
391 |
by simp |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
392 |
then show "\<exists>q1 q2. x + n * q1 = y + n * q2" |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
393 |
by blast |
43f5dfb7fa35
tuned (some HOL lints, by Yecine Megdiche);
Fabian Huch <huch@in.tum.de>
parents:
74101
diff
changeset
|
394 |
qed} |
60562
24af00b010cf
Amalgamation of the class comm_semiring_1_diff_distrib into comm_semiring_1_cancel. Moving axiom le_add_diff_inverse2 from semiring_numeral_div to linordered_semidom.
paulson <lp15@cam.ac.uk>
parents:
60517
diff
changeset
|
395 |
ultimately show ?rhs using linear[of x y] by blast |
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
396 |
next |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
397 |
assume ?rhs then obtain q1 q2 where q12: "x + n * q1 = y + n * q2" by blast |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
398 |
hence "(x + n * q1) mod n = (y + n * q2) mod n" by simp |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
399 |
thus ?lhs by simp |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
400 |
qed |
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
401 |
|
66808
1907167b6038
elementary definition of division on natural numbers
haftmann
parents:
66806
diff
changeset
|
402 |
|
76053 | 403 |
subsubsection \<open>Uniqueness rules\<close> |
404 |
||
76106 | 405 |
lemma euclidean_relation_intI [case_names by0 divides euclidean_relation]: |
406 |
\<open>(k div l, k mod l) = (q, r)\<close> |
|
407 |
if by0': \<open>l = 0 \<Longrightarrow> q = 0 \<and> r = k\<close> |
|
408 |
and divides': \<open>l \<noteq> 0 \<Longrightarrow> l dvd k \<Longrightarrow> r = 0 \<and> k = q * l\<close> |
|
409 |
and euclidean_relation': \<open>l \<noteq> 0 \<Longrightarrow> \<not> l dvd k \<Longrightarrow> sgn r = sgn l |
|
410 |
\<and> \<bar>r\<bar> < \<bar>l\<bar> \<and> k = q * l + r\<close> for k l :: int |
|
411 |
proof (cases l q r k rule: euclidean_relationI) |
|
412 |
case by0 |
|
413 |
then show ?case |
|
414 |
by (rule by0') |
|
76053 | 415 |
next |
76106 | 416 |
case divides |
417 |
then show ?case |
|
418 |
by (rule divides') |
|
76053 | 419 |
next |
76106 | 420 |
case euclidean_relation |
421 |
with euclidean_relation' have \<open>sgn r = sgn l\<close> \<open>\<bar>r\<bar> < \<bar>l\<bar>\<close> \<open>k = q * l + r\<close> |
|
422 |
by simp_all |
|
423 |
from \<open>sgn r = sgn l\<close> \<open>l \<noteq> 0\<close> have \<open>division_segment r = division_segment l\<close> |
|
424 |
by (simp add: division_segment_int_def sgn_if split: if_splits) |
|
425 |
with \<open>\<bar>r\<bar> < \<bar>l\<bar>\<close> \<open>k = q * l + r\<close> |
|
426 |
show ?case |
|
427 |
by simp |
|
76053 | 428 |
qed |
429 |
||
430 |
||
431 |
subsubsection \<open>Computing \<open>div\<close> and \<open>mod\<close> with shifting\<close> |
|
432 |
||
433 |
lemma div_pos_geq: |
|
434 |
fixes k l :: int |
|
435 |
assumes "0 < l" and "l \<le> k" |
|
436 |
shows "k div l = (k - l) div l + 1" |
|
437 |
proof - |
|
438 |
have "k = (k - l) + l" by simp |
|
439 |
then obtain j where k: "k = j + l" .. |
|
440 |
with assms show ?thesis by (simp add: div_add_self2) |
|
441 |
qed |
|
442 |
||
443 |
lemma mod_pos_geq: |
|
444 |
fixes k l :: int |
|
445 |
assumes "0 < l" and "l \<le> k" |
|
446 |
shows "k mod l = (k - l) mod l" |
|
447 |
proof - |
|
448 |
have "k = (k - l) + l" by simp |
|
449 |
then obtain j where k: "k = j + l" .. |
|
450 |
with assms show ?thesis by simp |
|
451 |
qed |
|
452 |
||
453 |
text\<open>computing div by shifting\<close> |
|
454 |
||
76106 | 455 |
lemma pos_zdiv_mult_2: \<open>(1 + 2 * b) div (2 * a) = b div a\<close> (is ?Q) |
456 |
and pos_zmod_mult_2: \<open>(1 + 2 * b) mod (2 * a) = 1 + 2 * (b mod a)\<close> (is ?R) |
|
457 |
if \<open>0 \<le> a\<close> for a b :: int |
|
458 |
proof - |
|
459 |
have \<open>((1 + 2 * b) div (2 * a), (1 + 2 * b) mod (2 * a)) = (b div a, 1 + 2 * (b mod a))\<close> |
|
76120 | 460 |
proof (cases \<open>2 * a\<close> \<open>b div a\<close> \<open>1 + 2 * (b mod a)\<close> \<open>1 + 2 * b\<close> rule: euclidean_relation_intI) |
76106 | 461 |
case by0 |
462 |
then show ?case |
|
463 |
by simp |
|
464 |
next |
|
76120 | 465 |
case divides |
466 |
have \<open>even (2 * a)\<close> |
|
467 |
by simp |
|
468 |
then have \<open>even (1 + 2 * b)\<close> |
|
469 |
using \<open>2 * a dvd 1 + 2 * b\<close> by (rule dvd_trans) |
|
470 |
then show ?case |
|
471 |
by simp |
|
472 |
next |
|
473 |
case euclidean_relation |
|
474 |
with that have \<open>a > 0\<close> |
|
76106 | 475 |
by simp |
476 |
moreover have \<open>b mod a < a\<close> |
|
477 |
using \<open>a > 0\<close> by simp |
|
478 |
then have \<open>1 + 2 * (b mod a) < 2 * a\<close> |
|
479 |
by simp |
|
480 |
moreover have \<open>2 * (b mod a) + a * (2 * (b div a)) = 2 * (b div a * a + b mod a)\<close> |
|
481 |
by (simp only: algebra_simps) |
|
76120 | 482 |
moreover have \<open>0 \<le> 2 * (b mod a)\<close> |
483 |
using \<open>a > 0\<close> by simp |
|
76106 | 484 |
ultimately show ?case |
485 |
by (simp add: algebra_simps) |
|
486 |
qed |
|
487 |
then show ?Q and ?R |
|
488 |
by simp_all |
|
489 |
qed |
|
76053 | 490 |
|
76106 | 491 |
lemma neg_zdiv_mult_2: \<open>(1 + 2 * b) div (2 * a) = (b + 1) div a\<close> (is ?Q) |
492 |
and neg_zmod_mult_2: \<open>(1 + 2 * b) mod (2 * a) = 2 * ((b + 1) mod a) - 1\<close> (is ?R) |
|
493 |
if \<open>a \<le> 0\<close> for a b :: int |
|
494 |
proof - |
|
495 |
have \<open>((1 + 2 * b) div (2 * a), (1 + 2 * b) mod (2 * a)) = ((b + 1) div a, 2 * ((b + 1) mod a) - 1)\<close> |
|
76120 | 496 |
proof (cases \<open>2 * a\<close> \<open>(b + 1) div a\<close> \<open>2 * ((b + 1) mod a) - 1\<close> \<open>1 + 2 * b\<close> rule: euclidean_relation_intI) |
76106 | 497 |
case by0 |
498 |
then show ?case |
|
499 |
by simp |
|
500 |
next |
|
76120 | 501 |
case divides |
502 |
have \<open>even (2 * a)\<close> |
|
503 |
by simp |
|
504 |
then have \<open>even (1 + 2 * b)\<close> |
|
505 |
using \<open>2 * a dvd 1 + 2 * b\<close> by (rule dvd_trans) |
|
506 |
then show ?case |
|
76106 | 507 |
by simp |
508 |
next |
|
76120 | 509 |
case euclidean_relation |
510 |
with that have \<open>a < 0\<close> |
|
76106 | 511 |
by simp |
512 |
moreover have \<open>(b + 1) mod a > a\<close> |
|
513 |
using \<open>a < 0\<close> by simp |
|
514 |
then have \<open>2 * ((b + 1) mod a) > 1 + 2 * a\<close> |
|
515 |
by simp |
|
516 |
moreover have \<open>((1 + b) mod a) \<le> 0\<close> |
|
517 |
using \<open>a < 0\<close> by simp |
|
518 |
then have \<open>2 * ((1 + b) mod a) \<le> 0\<close> |
|
519 |
by simp |
|
520 |
moreover have \<open>2 * ((1 + b) mod a) + a * (2 * ((1 + b) div a)) = |
|
521 |
2 * ((1 + b) div a * a + (1 + b) mod a)\<close> |
|
522 |
by (simp only: algebra_simps) |
|
523 |
ultimately show ?case |
|
76120 | 524 |
by (simp add: algebra_simps sgn_mult abs_mult) |
76106 | 525 |
qed |
526 |
then show ?Q and ?R |
|
527 |
by simp_all |
|
528 |
qed |
|
76053 | 529 |
|
530 |
lemma zdiv_numeral_Bit0 [simp]: |
|
531 |
"numeral (Num.Bit0 v) div numeral (Num.Bit0 w) = |
|
532 |
numeral v div (numeral w :: int)" |
|
533 |
unfolding numeral.simps unfolding mult_2 [symmetric] |
|
534 |
by (rule div_mult_mult1, simp) |
|
535 |
||
536 |
lemma zdiv_numeral_Bit1 [simp]: |
|
537 |
"numeral (Num.Bit1 v) div numeral (Num.Bit0 w) = |
|
538 |
(numeral v div (numeral w :: int))" |
|
539 |
unfolding numeral.simps |
|
540 |
unfolding mult_2 [symmetric] add.commute [of _ 1] |
|
541 |
by (rule pos_zdiv_mult_2, simp) |
|
542 |
||
543 |
lemma zmod_numeral_Bit0 [simp]: |
|
544 |
"numeral (Num.Bit0 v) mod numeral (Num.Bit0 w) = |
|
545 |
(2::int) * (numeral v mod numeral w)" |
|
546 |
unfolding numeral_Bit0 [of v] numeral_Bit0 [of w] |
|
547 |
unfolding mult_2 [symmetric] by (rule mod_mult_mult1) |
|
548 |
||
549 |
lemma zmod_numeral_Bit1 [simp]: |
|
550 |
"numeral (Num.Bit1 v) mod numeral (Num.Bit0 w) = |
|
551 |
2 * (numeral v mod numeral w) + (1::int)" |
|
552 |
unfolding numeral_Bit1 [of v] numeral_Bit0 [of w] |
|
553 |
unfolding mult_2 [symmetric] add.commute [of _ 1] |
|
554 |
by (rule pos_zmod_mult_2, simp) |
|
555 |
||
556 |
||
52435
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
haftmann
parents:
52398
diff
changeset
|
557 |
code_identifier |
6646bb548c6b
migration from code_(const|type|class|instance) to code_printing and from code_module to code_identifier
haftmann
parents:
52398
diff
changeset
|
558 |
code_module Divides \<rightharpoonup> (SML) Arith and (OCaml) Arith and (Haskell) Arith |
33364 | 559 |
|
64246 | 560 |
|
68253 | 561 |
subsection \<open>Lemmas of doubtful value\<close> |
66808
1907167b6038
elementary definition of division on natural numbers
haftmann
parents:
66806
diff
changeset
|
562 |
|
75936 | 563 |
class unique_euclidean_semiring_numeral = unique_euclidean_semiring_with_nat + linordered_semidom + |
564 |
assumes div_less: "0 \<le> a \<Longrightarrow> a < b \<Longrightarrow> a div b = 0" |
|
565 |
and mod_less: " 0 \<le> a \<Longrightarrow> a < b \<Longrightarrow> a mod b = a" |
|
566 |
and div_positive: "0 < b \<Longrightarrow> b \<le> a \<Longrightarrow> a div b > 0" |
|
567 |
and mod_less_eq_dividend: "0 \<le> a \<Longrightarrow> a mod b \<le> a" |
|
568 |
and pos_mod_bound: "0 < b \<Longrightarrow> a mod b < b" |
|
569 |
and pos_mod_sign: "0 < b \<Longrightarrow> 0 \<le> a mod b" |
|
570 |
and mod_mult2_eq: "0 \<le> c \<Longrightarrow> a mod (b * c) = b * (a div b mod c) + a mod b" |
|
571 |
and div_mult2_eq: "0 \<le> c \<Longrightarrow> a div (b * c) = a div b div c" |
|
572 |
assumes discrete: "a < b \<longleftrightarrow> a + 1 \<le> b" |
|
573 |
begin |
|
574 |
||
575 |
lemma divmod_digit_1: |
|
576 |
assumes "0 \<le> a" "0 < b" and "b \<le> a mod (2 * b)" |
|
577 |
shows "2 * (a div (2 * b)) + 1 = a div b" (is "?P") |
|
578 |
and "a mod (2 * b) - b = a mod b" (is "?Q") |
|
579 |
proof - |
|
580 |
from assms mod_less_eq_dividend [of a "2 * b"] have "b \<le> a" |
|
581 |
by (auto intro: trans) |
|
582 |
with \<open>0 < b\<close> have "0 < a div b" by (auto intro: div_positive) |
|
583 |
then have [simp]: "1 \<le> a div b" by (simp add: discrete) |
|
584 |
with \<open>0 < b\<close> have mod_less: "a mod b < b" by (simp add: pos_mod_bound) |
|
585 |
define w where "w = a div b mod 2" |
|
586 |
then have w_exhaust: "w = 0 \<or> w = 1" by auto |
|
587 |
have mod_w: "a mod (2 * b) = a mod b + b * w" |
|
588 |
by (simp add: w_def mod_mult2_eq ac_simps) |
|
589 |
from assms w_exhaust have "w = 1" |
|
590 |
using mod_less by (auto simp add: mod_w) |
|
591 |
with mod_w have mod: "a mod (2 * b) = a mod b + b" by simp |
|
592 |
have "2 * (a div (2 * b)) = a div b - w" |
|
593 |
by (simp add: w_def div_mult2_eq minus_mod_eq_mult_div ac_simps) |
|
594 |
with \<open>w = 1\<close> have div: "2 * (a div (2 * b)) = a div b - 1" by simp |
|
595 |
then show ?P and ?Q |
|
596 |
by (simp_all add: div mod add_implies_diff [symmetric]) |
|
597 |
qed |
|
598 |
||
599 |
lemma divmod_digit_0: |
|
600 |
assumes "0 < b" and "a mod (2 * b) < b" |
|
601 |
shows "2 * (a div (2 * b)) = a div b" (is "?P") |
|
602 |
and "a mod (2 * b) = a mod b" (is "?Q") |
|
603 |
proof - |
|
604 |
define w where "w = a div b mod 2" |
|
605 |
then have w_exhaust: "w = 0 \<or> w = 1" by auto |
|
606 |
have mod_w: "a mod (2 * b) = a mod b + b * w" |
|
607 |
by (simp add: w_def mod_mult2_eq ac_simps) |
|
608 |
moreover have "b \<le> a mod b + b" |
|
609 |
proof - |
|
610 |
from \<open>0 < b\<close> pos_mod_sign have "0 \<le> a mod b" by blast |
|
611 |
then have "0 + b \<le> a mod b + b" by (rule add_right_mono) |
|
612 |
then show ?thesis by simp |
|
613 |
qed |
|
614 |
moreover note assms w_exhaust |
|
615 |
ultimately have "w = 0" by auto |
|
616 |
with mod_w have mod: "a mod (2 * b) = a mod b" by simp |
|
617 |
have "2 * (a div (2 * b)) = a div b - w" |
|
618 |
by (simp add: w_def div_mult2_eq minus_mod_eq_mult_div ac_simps) |
|
619 |
with \<open>w = 0\<close> have div: "2 * (a div (2 * b)) = a div b" by simp |
|
620 |
then show ?P and ?Q |
|
621 |
by (simp_all add: div mod) |
|
622 |
qed |
|
623 |
||
624 |
lemma mod_double_modulus: |
|
625 |
assumes "m > 0" "x \<ge> 0" |
|
626 |
shows "x mod (2 * m) = x mod m \<or> x mod (2 * m) = x mod m + m" |
|
627 |
proof (cases "x mod (2 * m) < m") |
|
628 |
case True |
|
629 |
thus ?thesis using assms using divmod_digit_0(2)[of m x] by auto |
|
630 |
next |
|
631 |
case False |
|
632 |
hence *: "x mod (2 * m) - m = x mod m" |
|
633 |
using assms by (intro divmod_digit_1) auto |
|
634 |
hence "x mod (2 * m) = x mod m + m" |
|
635 |
by (subst * [symmetric], subst le_add_diff_inverse2) (use False in auto) |
|
636 |
thus ?thesis by simp |
|
637 |
qed |
|
638 |
||
639 |
end |
|
640 |
||
641 |
hide_fact (open) div_less mod_less mod_less_eq_dividend mod_mult2_eq div_mult2_eq |
|
642 |
||
643 |
instance nat :: unique_euclidean_semiring_numeral |
|
644 |
by standard |
|
645 |
(auto simp add: div_greater_zero_iff div_mult2_eq mod_mult2_eq) |
|
646 |
||
647 |
instance int :: unique_euclidean_semiring_numeral |
|
648 |
by standard (auto intro: zmod_le_nonneg_dividend simp add: |
|
649 |
pos_imp_zdiv_pos_iff zmod_zmult2_eq zdiv_zmult2_eq) |
|
650 |
||
68631 | 651 |
lemma div_geq: "m div n = Suc ((m - n) div n)" if "0 < n" and " \<not> m < n" for m n :: nat |
66808
1907167b6038
elementary definition of division on natural numbers
haftmann
parents:
66806
diff
changeset
|
652 |
by (rule le_div_geq) (use that in \<open>simp_all add: not_less\<close>) |
1907167b6038
elementary definition of division on natural numbers
haftmann
parents:
66806
diff
changeset
|
653 |
|
68631 | 654 |
lemma mod_geq: "m mod n = (m - n) mod n" if "\<not> m < n" for m n :: nat |
66808
1907167b6038
elementary definition of division on natural numbers
haftmann
parents:
66806
diff
changeset
|
655 |
by (rule le_mod_geq) (use that in \<open>simp add: not_less\<close>) |
1907167b6038
elementary definition of division on natural numbers
haftmann
parents:
66806
diff
changeset
|
656 |
|
68631 | 657 |
lemma mod_eq_0D: "\<exists>q. m = d * q" if "m mod d = 0" for m d :: nat |
658 |
using that by (auto simp add: mod_eq_0_iff_dvd) |
|
66816
212a3334e7da
more fundamental definition of div and mod on int
haftmann
parents:
66815
diff
changeset
|
659 |
|
69695 | 660 |
lemma pos_mod_conj: "0 < b \<Longrightarrow> 0 \<le> a mod b \<and> a mod b < b" for a b :: int |
661 |
by simp |
|
662 |
||
663 |
lemma neg_mod_conj: "b < 0 \<Longrightarrow> a mod b \<le> 0 \<and> b < a mod b" for a b :: int |
|
664 |
by simp |
|
665 |
||
666 |
lemma zmod_eq_0_iff: "m mod d = 0 \<longleftrightarrow> (\<exists>q. m = d * q)" for m d :: int |
|
667 |
by (auto simp add: mod_eq_0_iff_dvd) |
|
668 |
||
669 |
(* REVISIT: should this be generalized to all semiring_div types? *) |
|
670 |
lemma zmod_eq_0D [dest!]: "\<exists>q. m = d * q" if "m mod d = 0" for m d :: int |
|
671 |
using that by auto |
|
672 |
||
75937 | 673 |
lemma div_positive_int: |
674 |
"k div l > 0" if "k \<ge> l" and "l > 0" for k l :: int |
|
675 |
using that by (simp add: nonneg1_imp_zdiv_pos_iff) |
|
676 |
||
33361
1f18de40b43f
combined former theories Divides and IntDiv to one theory Divides
haftmann
parents:
33340
diff
changeset
|
677 |
end |