author | paulson |
Thu, 29 Jul 1999 12:44:57 +0200 | |
changeset 7127 | 48e235179ffb |
parent 7086 | f9aa63a5a8b6 |
child 7499 | 23e090051cb8 |
permissions | -rw-r--r-- |
6917 | 1 |
(* Title: HOL/IntDiv.ML |
2 |
ID: $Id$ |
|
3 |
Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
|
4 |
Copyright 1999 University of Cambridge |
|
5 |
||
6 |
The division operators div, mod and the divides relation "dvd" |
|
6992 | 7 |
|
8 |
Here is the division algorithm in ML: |
|
9 |
||
10 |
fun posDivAlg (a,b) = |
|
11 |
if a<b then (0,a) |
|
12 |
else let val (q,r) = posDivAlg(a, 2*b) |
|
13 |
in if 0<=r-b then (2*q+1, r-b) else (2*q, r) |
|
14 |
end; |
|
15 |
||
16 |
fun negDivAlg (a,b) = |
|
17 |
if 0<=a+b then (~1,a+b) |
|
18 |
else let val (q,r) = negDivAlg(a, 2*b) |
|
19 |
in if 0<=r-b then (2*q+1, r-b) else (2*q, r) |
|
20 |
end; |
|
21 |
||
22 |
fun negateSnd (q,r:int) = (q,~r); |
|
23 |
||
24 |
fun divAlg (a,b) = if 0<=a then |
|
25 |
if b>0 then posDivAlg (a,b) |
|
26 |
else if a=0 then (0,0) |
|
27 |
else negateSnd (negDivAlg (~a,~b)) |
|
28 |
else |
|
29 |
if 0<b then negDivAlg (a,b) |
|
30 |
else negateSnd (posDivAlg (~a,~b)); |
|
6917 | 31 |
*) |
32 |
||
33 |
Addsimps [zless_nat_conj]; |
|
34 |
||
35 |
(*** Uniqueness and monotonicity of quotients and remainders ***) |
|
36 |
||
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
37 |
Goal "[| b*q' + r' <= b*q + r; #0 <= r'; #0 < b; r < b |] \ |
6917 | 38 |
\ ==> q' <= (q::int)"; |
39 |
by (subgoal_tac "r' + b * (q'-q) <= r" 1); |
|
40 |
by (simp_tac (simpset() addsimps zcompare_rls@[zdiff_zmult_distrib2]) 2); |
|
41 |
by (subgoal_tac "#0 < b * (#1 + q - q')" 1); |
|
42 |
by (etac order_le_less_trans 2); |
|
43 |
by (full_simp_tac (simpset() addsimps zcompare_rls@[zdiff_zmult_distrib2, |
|
44 |
zadd_zmult_distrib2]) 2); |
|
45 |
by (subgoal_tac "b * q' < b * (#1 + q)" 1); |
|
46 |
by (full_simp_tac (simpset() addsimps zcompare_rls@[zdiff_zmult_distrib2, |
|
47 |
zadd_zmult_distrib2]) 2); |
|
48 |
by (Asm_full_simp_tac 1); |
|
49 |
qed "unique_quotient_lemma"; |
|
50 |
||
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
51 |
Goal "[| b*q' + r' <= b*q + r; r <= #0; b < #0; b < r' |] \ |
6917 | 52 |
\ ==> q <= (q'::int)"; |
53 |
by (res_inst_tac [("b", "-b"), ("r", "-r'"), ("r'", "-r")] |
|
54 |
unique_quotient_lemma 1); |
|
55 |
by (auto_tac (claset(), |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
56 |
simpset() addsimps zcompare_rls@ |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
57 |
[zmult_zminus, zmult_zminus_right])); |
6917 | 58 |
qed "unique_quotient_lemma_neg"; |
59 |
||
60 |
||
61 |
Goal "[| quorem ((a,b), (q,r)); quorem ((a,b), (q',r')); b ~= #0 |] \ |
|
62 |
\ ==> q = q'"; |
|
63 |
by (asm_full_simp_tac |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
64 |
(simpset() addsimps split_ifs@ |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
65 |
[quorem_def, linorder_neq_iff]) 1); |
6917 | 66 |
by Safe_tac; |
67 |
by (ALLGOALS Asm_full_simp_tac); |
|
68 |
by (REPEAT |
|
69 |
(blast_tac (claset() addIs [order_antisym] |
|
70 |
addDs [order_eq_refl RS unique_quotient_lemma, |
|
71 |
order_eq_refl RS unique_quotient_lemma_neg, |
|
72 |
sym]) 1)); |
|
73 |
qed "unique_quotient"; |
|
74 |
||
75 |
||
76 |
Goal "[| quorem ((a,b), (q,r)); quorem ((a,b), (q',r')); b ~= #0 |] \ |
|
77 |
\ ==> r = r'"; |
|
78 |
by (subgoal_tac "q = q'" 1); |
|
79 |
by (blast_tac (claset() addIs [unique_quotient]) 2); |
|
80 |
by (asm_full_simp_tac (simpset() addsimps [quorem_def]) 1); |
|
81 |
qed "unique_remainder"; |
|
82 |
||
83 |
||
84 |
(*** Correctness of posDivAlg, the division algorithm for a>=0 and b>0 ***) |
|
85 |
||
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
86 |
(*Unfold all "let"s involving constants*) |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
87 |
Addsimps [read_instantiate_sg (sign_of IntDiv.thy) |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
88 |
[("s", "number_of ?v")] Let_def]; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
89 |
|
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
90 |
|
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
91 |
Goal "adjust a b (q,r) = (let diff = r-b in \ |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
92 |
\ if #0 <= diff then (#2*q + #1, diff) \ |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
93 |
\ else (#2*q, r))"; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
94 |
by (simp_tac (simpset() addsimps [Let_def,adjust_def]) 1); |
6917 | 95 |
qed "adjust_eq"; |
96 |
Addsimps [adjust_eq]; |
|
97 |
||
98 |
(*Proving posDivAlg's termination condition*) |
|
99 |
val [tc] = posDivAlg.tcs; |
|
100 |
goalw_cterm [] (cterm_of (sign_of thy) (HOLogic.mk_Trueprop tc)); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
101 |
by (auto_tac (claset(), simpset() addsimps [zmult_2])); |
6917 | 102 |
val lemma = result(); |
103 |
||
104 |
(* removing the termination condition from the generated theorems *) |
|
105 |
||
106 |
bind_thm ("posDivAlg_raw_eqn", lemma RS hd posDivAlg.rules); |
|
107 |
||
108 |
(**use with simproc to avoid re-proving the premise*) |
|
109 |
Goal "#0 < b ==> \ |
|
110 |
\ posDivAlg (a,b) = \ |
|
111 |
\ (if a<b then (#0,a) else adjust a b (posDivAlg(a, #2*b)))"; |
|
112 |
by (rtac (posDivAlg_raw_eqn RS trans) 1); |
|
113 |
by (Asm_simp_tac 1); |
|
114 |
qed "posDivAlg_eqn"; |
|
115 |
||
116 |
val posDivAlg_induct = lemma RS posDivAlg.induct; |
|
117 |
||
118 |
||
119 |
(*Correctness of posDivAlg: it computes quotients correctly*) |
|
120 |
Goal "#0 <= a --> #0 < b --> quorem ((a, b), posDivAlg (a, b))"; |
|
121 |
by (res_inst_tac [("u", "a"), ("v", "b")] posDivAlg_induct 1); |
|
122 |
by Auto_tac; |
|
123 |
by (ALLGOALS |
|
124 |
(asm_full_simp_tac (simpset() addsimps [quorem_def, |
|
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
125 |
pos_imp_zmult_pos_iff]))); |
6917 | 126 |
(*base case: a<b*) |
127 |
by (asm_full_simp_tac (simpset() addsimps [posDivAlg_eqn]) 1); |
|
128 |
(*main argument*) |
|
129 |
by (stac posDivAlg_eqn 1); |
|
130 |
by (ALLGOALS Asm_simp_tac); |
|
131 |
by (etac splitE 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
132 |
by (auto_tac (claset(), |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
133 |
simpset() addsimps zmult_ac@[zadd_zmult_distrib2, Let_def])); |
6917 | 134 |
(*the "just double" case*) |
135 |
by (asm_full_simp_tac (simpset() addsimps zcompare_rls@[zmult_2_right]) 1); |
|
136 |
qed_spec_mp "posDivAlg_correct"; |
|
137 |
||
138 |
||
139 |
(*** Correctness of negDivAlg, the division algorithm for a<0 and b>0 ***) |
|
140 |
||
141 |
(*Proving negDivAlg's termination condition*) |
|
142 |
val [tc] = negDivAlg.tcs; |
|
143 |
goalw_cterm [] (cterm_of (sign_of thy) (HOLogic.mk_Trueprop tc)); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
144 |
by (auto_tac (claset(), simpset() addsimps [zmult_2])); |
6917 | 145 |
val lemma = result(); |
146 |
||
147 |
(* removing the termination condition from the generated theorems *) |
|
148 |
||
149 |
bind_thm ("negDivAlg_raw_eqn", lemma RS hd negDivAlg.rules); |
|
150 |
||
151 |
(**use with simproc to avoid re-proving the premise*) |
|
152 |
Goal "#0 < b ==> \ |
|
153 |
\ negDivAlg (a,b) = \ |
|
154 |
\ (if #0<=a+b then (#-1,a+b) else adjust a b (negDivAlg(a, #2*b)))"; |
|
155 |
by (rtac (negDivAlg_raw_eqn RS trans) 1); |
|
156 |
by (Asm_simp_tac 1); |
|
157 |
qed "negDivAlg_eqn"; |
|
158 |
||
159 |
val negDivAlg_induct = lemma RS negDivAlg.induct; |
|
160 |
||
161 |
||
162 |
(*Correctness of negDivAlg: it computes quotients correctly |
|
163 |
It doesn't work if a=0 because the 0/b=0 rather than -1*) |
|
164 |
Goal "a < #0 --> #0 < b --> quorem ((a, b), negDivAlg (a, b))"; |
|
165 |
by (res_inst_tac [("u", "a"), ("v", "b")] negDivAlg_induct 1); |
|
166 |
by Auto_tac; |
|
167 |
by (ALLGOALS |
|
168 |
(asm_full_simp_tac (simpset() addsimps [quorem_def, |
|
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
169 |
pos_imp_zmult_pos_iff]))); |
6917 | 170 |
(*base case: 0<=a+b*) |
171 |
by (asm_full_simp_tac (simpset() addsimps [negDivAlg_eqn]) 1); |
|
172 |
(*main argument*) |
|
173 |
by (stac negDivAlg_eqn 1); |
|
174 |
by (ALLGOALS Asm_simp_tac); |
|
175 |
by (etac splitE 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
176 |
by (auto_tac (claset(), |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
177 |
simpset() addsimps zmult_ac@[zadd_zmult_distrib2, Let_def])); |
6917 | 178 |
(*the "just double" case*) |
179 |
by (asm_full_simp_tac (simpset() addsimps zcompare_rls@[zmult_2_right]) 1); |
|
180 |
qed_spec_mp "negDivAlg_correct"; |
|
181 |
||
182 |
||
183 |
(*** Existence shown by proving the division algorithm to be correct ***) |
|
184 |
||
185 |
(*the case a=0*) |
|
186 |
Goal "b ~= #0 ==> quorem ((#0,b), (#0,#0))"; |
|
187 |
by (auto_tac (claset(), |
|
188 |
simpset() addsimps [quorem_def, linorder_neq_iff])); |
|
189 |
qed "quorem_0"; |
|
190 |
||
191 |
Goal "posDivAlg (#0, b) = (#0, #0)"; |
|
192 |
by (stac posDivAlg_raw_eqn 1); |
|
193 |
by Auto_tac; |
|
194 |
qed "posDivAlg_0"; |
|
195 |
Addsimps [posDivAlg_0]; |
|
196 |
||
197 |
Goal "negDivAlg (#-1, b) = (#-1, b-#1)"; |
|
198 |
by (stac negDivAlg_raw_eqn 1); |
|
199 |
by Auto_tac; |
|
200 |
qed "negDivAlg_minus1"; |
|
201 |
Addsimps [negDivAlg_minus1]; |
|
202 |
||
203 |
Goalw [negateSnd_def] "negateSnd(q,r) = (q,-r)"; |
|
204 |
by Auto_tac; |
|
205 |
qed "negateSnd_eq"; |
|
206 |
Addsimps [negateSnd_eq]; |
|
207 |
||
208 |
Goal "quorem ((-a,-b), qr) ==> quorem ((a,b), negateSnd qr)"; |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
209 |
by (auto_tac (claset(), |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
210 |
simpset() addsimps split_ifs@[zmult_zminus, quorem_def])); |
6917 | 211 |
qed "quorem_neg"; |
212 |
||
213 |
Goal "b ~= #0 ==> quorem ((a,b), divAlg(a,b))"; |
|
214 |
by (auto_tac (claset(), |
|
215 |
simpset() addsimps [quorem_0, divAlg_def])); |
|
216 |
by (REPEAT_FIRST (resolve_tac [quorem_neg, posDivAlg_correct, |
|
217 |
negDivAlg_correct])); |
|
218 |
by (auto_tac (claset(), |
|
219 |
simpset() addsimps [quorem_def, linorder_neq_iff])); |
|
220 |
qed "divAlg_correct"; |
|
221 |
||
6992 | 222 |
(** Aribtrary definitions for division by zero. Useful to simplify |
223 |
certain equations **) |
|
224 |
||
225 |
Goal "a div (#0::int) = #0"; |
|
226 |
by (simp_tac (simpset() addsimps [div_def, divAlg_def, posDivAlg_raw_eqn]) 1); |
|
7035 | 227 |
qed "DIVISION_BY_ZERO_ZDIV"; (*NOT for adding to default simpset*) |
6992 | 228 |
|
229 |
Goal "a mod (#0::int) = a"; |
|
230 |
by (simp_tac (simpset() addsimps [mod_def, divAlg_def, posDivAlg_raw_eqn]) 1); |
|
7035 | 231 |
qed "DIVISION_BY_ZERO_ZMOD"; (*NOT for adding to default simpset*) |
6992 | 232 |
|
7035 | 233 |
fun zdiv_undefined_case_tac s i = |
6992 | 234 |
case_tac s i THEN |
7035 | 235 |
asm_simp_tac (simpset() addsimps [DIVISION_BY_ZERO_ZDIV, |
236 |
DIVISION_BY_ZERO_ZMOD]) i; |
|
6992 | 237 |
|
238 |
(** Basic laws about division and remainder **) |
|
239 |
||
240 |
Goal "(a::int) = b * (a div b) + (a mod b)"; |
|
7035 | 241 |
by (zdiv_undefined_case_tac "b = #0" 1); |
6917 | 242 |
by (cut_inst_tac [("a","a"),("b","b")] divAlg_correct 1); |
243 |
by (auto_tac (claset(), |
|
244 |
simpset() addsimps [quorem_def, div_def, mod_def])); |
|
245 |
qed "zmod_zdiv_equality"; |
|
246 |
||
247 |
Goal "(#0::int) < b ==> #0 <= a mod b & a mod b < b"; |
|
248 |
by (cut_inst_tac [("a","a"),("b","b")] divAlg_correct 1); |
|
249 |
by (auto_tac (claset(), |
|
250 |
simpset() addsimps [quorem_def, mod_def])); |
|
251 |
bind_thm ("pos_mod_sign", result() RS conjunct1); |
|
252 |
bind_thm ("pos_mod_bound", result() RS conjunct2); |
|
253 |
||
254 |
Goal "b < (#0::int) ==> a mod b <= #0 & b < a mod b"; |
|
255 |
by (cut_inst_tac [("a","a"),("b","b")] divAlg_correct 1); |
|
256 |
by (auto_tac (claset(), |
|
257 |
simpset() addsimps [quorem_def, div_def, mod_def])); |
|
258 |
bind_thm ("neg_mod_sign", result() RS conjunct1); |
|
259 |
bind_thm ("neg_mod_bound", result() RS conjunct2); |
|
260 |
||
261 |
||
6992 | 262 |
(** proving general properties of div and mod **) |
263 |
||
264 |
Goal "b ~= #0 ==> quorem ((a, b), (a div b, a mod b))"; |
|
265 |
by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1); |
|
266 |
by (auto_tac |
|
267 |
(claset(), |
|
268 |
simpset() addsimps [quorem_def, linorder_neq_iff, |
|
269 |
pos_mod_sign,pos_mod_bound, |
|
270 |
neg_mod_sign, neg_mod_bound])); |
|
271 |
qed "quorem_div_mod"; |
|
272 |
||
273 |
Goal "[| quorem((a,b),(q,r)); b ~= #0 |] ==> a div b = q"; |
|
274 |
by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS unique_quotient]) 1); |
|
275 |
qed "quorem_div"; |
|
276 |
||
277 |
Goal "[| quorem((a,b),(q,r)); b ~= #0 |] ==> a mod b = r"; |
|
278 |
by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS unique_remainder]) 1); |
|
279 |
qed "quorem_mod"; |
|
280 |
||
281 |
Goal "[| (#0::int) <= a; a < b |] ==> a div b = #0"; |
|
282 |
by (rtac quorem_div 1); |
|
283 |
by (auto_tac (claset(), simpset() addsimps [quorem_def])); |
|
6999 | 284 |
qed "div_pos_pos_trivial"; |
6992 | 285 |
|
286 |
Goal "[| a <= (#0::int); b < a |] ==> a div b = #0"; |
|
287 |
by (rtac quorem_div 1); |
|
288 |
by (auto_tac (claset(), simpset() addsimps [quorem_def])); |
|
6999 | 289 |
qed "div_neg_neg_trivial"; |
290 |
||
291 |
Goal "[| (#0::int) < a; a+b <= #0 |] ==> a div b = #-1"; |
|
292 |
by (rtac quorem_div 1); |
|
293 |
by (auto_tac (claset(), simpset() addsimps [quorem_def])); |
|
294 |
qed "div_pos_neg_trivial"; |
|
295 |
||
296 |
(*There is no div_neg_pos_trivial because #0 div b = #0 would supersede it*) |
|
6992 | 297 |
|
298 |
Goal "[| (#0::int) <= a; a < b |] ==> a mod b = a"; |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
299 |
by (res_inst_tac [("q","#0")] quorem_mod 1); |
6992 | 300 |
by (auto_tac (claset(), simpset() addsimps [quorem_def])); |
6999 | 301 |
qed "mod_pos_pos_trivial"; |
6992 | 302 |
|
303 |
Goal "[| a <= (#0::int); b < a |] ==> a mod b = a"; |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
304 |
by (res_inst_tac [("q","#0")] quorem_mod 1); |
6992 | 305 |
by (auto_tac (claset(), simpset() addsimps [quorem_def])); |
6999 | 306 |
qed "mod_neg_neg_trivial"; |
307 |
||
308 |
Goal "[| (#0::int) < a; a+b <= #0 |] ==> a mod b = a+b"; |
|
309 |
by (res_inst_tac [("q","#-1")] quorem_mod 1); |
|
310 |
by (auto_tac (claset(), simpset() addsimps [quorem_def])); |
|
311 |
qed "mod_pos_neg_trivial"; |
|
312 |
||
313 |
(*There is no mod_neg_pos_trivial...*) |
|
6992 | 314 |
|
315 |
||
316 |
(*Simpler laws such as -a div b = -(a div b) FAIL*) |
|
317 |
Goal "(-a) div (-b) = a div (b::int)"; |
|
7035 | 318 |
by (zdiv_undefined_case_tac "b = #0" 1); |
6992 | 319 |
by (stac ((simplify(simpset()) (quorem_div_mod RS quorem_neg)) |
320 |
RS quorem_div) 1); |
|
321 |
by Auto_tac; |
|
322 |
qed "zdiv_zminus_zminus"; |
|
323 |
Addsimps [zdiv_zminus_zminus]; |
|
324 |
||
325 |
(*Simpler laws such as -a mod b = -(a mod b) FAIL*) |
|
326 |
Goal "(-a) mod (-b) = - (a mod (b::int))"; |
|
7035 | 327 |
by (zdiv_undefined_case_tac "b = #0" 1); |
6992 | 328 |
by (stac ((simplify(simpset()) (quorem_div_mod RS quorem_neg)) |
329 |
RS quorem_mod) 1); |
|
330 |
by Auto_tac; |
|
331 |
qed "zmod_zminus_zminus"; |
|
332 |
Addsimps [zmod_zminus_zminus]; |
|
333 |
||
334 |
||
335 |
(*** division of a number by itself ***) |
|
336 |
||
337 |
Goal "[| (#0::int) < a; a = r + a*q; r < a |] ==> #1 <= q"; |
|
338 |
by (subgoal_tac "#0 < a*q" 1); |
|
339 |
by (arith_tac 2); |
|
340 |
by (asm_full_simp_tac (simpset() addsimps [pos_imp_zmult_pos_iff]) 1); |
|
341 |
val lemma1 = result(); |
|
342 |
||
343 |
Goal "[| (#0::int) < a; a = r + a*q; #0 <= r |] ==> q <= #1"; |
|
344 |
by (subgoal_tac "#0 <= a*(#1-q)" 1); |
|
345 |
by (asm_simp_tac (simpset() addsimps [zdiff_zmult_distrib2]) 2); |
|
346 |
by (asm_full_simp_tac (simpset() addsimps [pos_imp_zmult_nonneg_iff]) 1); |
|
347 |
by (full_simp_tac (simpset() addsimps zcompare_rls) 1); |
|
348 |
val lemma2 = result(); |
|
349 |
||
350 |
Goal "[| quorem((a,a),(q,r)); a ~= (#0::int) |] ==> q = #1"; |
|
351 |
by (asm_full_simp_tac |
|
352 |
(simpset() addsimps split_ifs@[quorem_def, linorder_neq_iff]) 1); |
|
353 |
by (rtac order_antisym 1); |
|
354 |
by Safe_tac; |
|
355 |
by Auto_tac; |
|
356 |
by (res_inst_tac [("a", "-a"),("r", "-r")] lemma1 3); |
|
357 |
by (res_inst_tac [("a", "-a"),("r", "-r")] lemma2 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
358 |
by (REPEAT (force_tac (claset() addIs [lemma1,lemma2], |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
359 |
simpset() addsimps [zadd_commute, zmult_zminus]) 1)); |
6992 | 360 |
qed "self_quotient"; |
361 |
||
362 |
Goal "[| quorem((a,a),(q,r)); a ~= (#0::int) |] ==> r = #0"; |
|
363 |
by (forward_tac [self_quotient] 1); |
|
364 |
by (assume_tac 1); |
|
365 |
by (asm_full_simp_tac (simpset() addsimps [quorem_def]) 1); |
|
366 |
qed "self_remainder"; |
|
367 |
||
368 |
Goal "a ~= #0 ==> a div a = (#1::int)"; |
|
369 |
by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS self_quotient]) 1); |
|
370 |
qed "zdiv_self"; |
|
371 |
Addsimps [zdiv_self]; |
|
372 |
||
373 |
(*Here we have 0 mod 0 = 0, also assumed by Knuth (who puts m mod 0 = 0) *) |
|
374 |
Goal "a mod a = (#0::int)"; |
|
7035 | 375 |
by (zdiv_undefined_case_tac "a = #0" 1); |
6992 | 376 |
by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS self_remainder]) 1); |
377 |
qed "zmod_self"; |
|
378 |
Addsimps [zmod_self]; |
|
379 |
||
380 |
||
6917 | 381 |
(*** Computation of division and remainder ***) |
382 |
||
383 |
Goal "(#0::int) div b = #0"; |
|
384 |
by (simp_tac (simpset() addsimps [div_def, divAlg_def]) 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
385 |
qed "zdiv_zero"; |
6917 | 386 |
|
7035 | 387 |
Goal "(#0::int) < b ==> #-1 div b = #-1"; |
388 |
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1); |
|
389 |
qed "div_eq_minus1"; |
|
390 |
||
6917 | 391 |
Goal "(#0::int) mod b = #0"; |
392 |
by (simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
393 |
qed "zmod_zero"; |
6917 | 394 |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
395 |
Addsimps [zdiv_zero, zmod_zero]; |
6917 | 396 |
|
7035 | 397 |
Goal "(#0::int) < b ==> #-1 div b = #-1"; |
398 |
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
399 |
qed "zdiv_minus1"; |
7035 | 400 |
|
401 |
Goal "(#0::int) < b ==> #-1 mod b = b-#1"; |
|
402 |
by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
403 |
qed "zmod_minus1"; |
7035 | 404 |
|
6917 | 405 |
(** a positive, b positive **) |
406 |
||
6992 | 407 |
Goal "[| #0 < a; #0 <= b |] ==> a div b = fst (posDivAlg(a,b))"; |
6917 | 408 |
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1); |
409 |
qed "div_pos_pos"; |
|
410 |
||
6992 | 411 |
Goal "[| #0 < a; #0 <= b |] ==> a mod b = snd (posDivAlg(a,b))"; |
6917 | 412 |
by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1); |
413 |
qed "mod_pos_pos"; |
|
414 |
||
415 |
(** a negative, b positive **) |
|
416 |
||
417 |
Goal "[| a < #0; #0 < b |] ==> a div b = fst (negDivAlg(a,b))"; |
|
418 |
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1); |
|
419 |
qed "div_neg_pos"; |
|
420 |
||
421 |
Goal "[| a < #0; #0 < b |] ==> a mod b = snd (negDivAlg(a,b))"; |
|
422 |
by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1); |
|
423 |
qed "mod_neg_pos"; |
|
424 |
||
425 |
(** a positive, b negative **) |
|
426 |
||
427 |
Goal "[| #0 < a; b < #0 |] ==> a div b = fst (negateSnd(negDivAlg(-a,-b)))"; |
|
428 |
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1); |
|
429 |
qed "div_pos_neg"; |
|
430 |
||
431 |
Goal "[| #0 < a; b < #0 |] ==> a mod b = snd (negateSnd(negDivAlg(-a,-b)))"; |
|
432 |
by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1); |
|
433 |
qed "mod_pos_neg"; |
|
434 |
||
435 |
(** a negative, b negative **) |
|
436 |
||
6992 | 437 |
Goal "[| a < #0; b <= #0 |] ==> a div b = fst (negateSnd(posDivAlg(-a,-b)))"; |
6917 | 438 |
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1); |
439 |
qed "div_neg_neg"; |
|
440 |
||
6992 | 441 |
Goal "[| a < #0; b <= #0 |] ==> a mod b = snd (negateSnd(posDivAlg(-a,-b)))"; |
6917 | 442 |
by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1); |
443 |
qed "mod_neg_neg"; |
|
444 |
||
445 |
Addsimps (map (read_instantiate_sg (sign_of IntDiv.thy) |
|
446 |
[("a", "number_of ?v"), ("b", "number_of ?w")]) |
|
447 |
[div_pos_pos, div_neg_pos, div_pos_neg, div_neg_neg, |
|
448 |
mod_pos_pos, mod_neg_pos, mod_pos_neg, mod_neg_neg, |
|
449 |
posDivAlg_eqn, negDivAlg_eqn]); |
|
6992 | 450 |
|
6917 | 451 |
|
452 |
(** Special-case simplification **) |
|
453 |
||
454 |
Goal "a mod (#1::int) = #0"; |
|
455 |
by (cut_inst_tac [("a","a"),("b","#1")] pos_mod_sign 1); |
|
456 |
by (cut_inst_tac [("a","a"),("b","#1")] pos_mod_bound 2); |
|
457 |
by Auto_tac; |
|
458 |
qed "zmod_1"; |
|
459 |
Addsimps [zmod_1]; |
|
460 |
||
461 |
Goal "a div (#1::int) = a"; |
|
462 |
by (cut_inst_tac [("a","a"),("b","#1")] zmod_zdiv_equality 1); |
|
463 |
by Auto_tac; |
|
464 |
qed "zdiv_1"; |
|
465 |
Addsimps [zdiv_1]; |
|
466 |
||
467 |
Goal "a mod (#-1::int) = #0"; |
|
468 |
by (cut_inst_tac [("a","a"),("b","#-1")] neg_mod_sign 1); |
|
469 |
by (cut_inst_tac [("a","a"),("b","#-1")] neg_mod_bound 2); |
|
470 |
by Auto_tac; |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
471 |
qed "zmod_minus1_right"; |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
472 |
Addsimps [zmod_minus1_right]; |
6917 | 473 |
|
474 |
Goal "a div (#-1::int) = -a"; |
|
475 |
by (cut_inst_tac [("a","a"),("b","#-1")] zmod_zdiv_equality 1); |
|
476 |
by Auto_tac; |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
477 |
qed "zdiv_minus1_right"; |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
478 |
Addsimps [zdiv_minus1_right]; |
6917 | 479 |
|
480 |
||
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
481 |
(*** Monotonicity in the first argument (divisor) ***) |
6917 | 482 |
|
483 |
Goal "[| a <= a'; #0 < (b::int) |] ==> a div b <= a' div b"; |
|
484 |
by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1); |
|
6992 | 485 |
by (cut_inst_tac [("a","a'"),("b","b")] zmod_zdiv_equality 1); |
6917 | 486 |
by (rtac unique_quotient_lemma 1); |
487 |
by (etac subst 1); |
|
488 |
by (etac subst 1); |
|
489 |
by (ALLGOALS (asm_simp_tac (simpset() addsimps [pos_mod_sign,pos_mod_bound]))); |
|
490 |
qed "zdiv_mono1"; |
|
491 |
||
492 |
Goal "[| a <= a'; (b::int) < #0 |] ==> a' div b <= a div b"; |
|
493 |
by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1); |
|
6992 | 494 |
by (cut_inst_tac [("a","a'"),("b","b")] zmod_zdiv_equality 1); |
6917 | 495 |
by (rtac unique_quotient_lemma_neg 1); |
496 |
by (etac subst 1); |
|
497 |
by (etac subst 1); |
|
498 |
by (ALLGOALS (asm_simp_tac (simpset() addsimps [neg_mod_sign,neg_mod_bound]))); |
|
499 |
qed "zdiv_mono1_neg"; |
|
500 |
||
501 |
||
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
502 |
(*** Monotonicity in the second argument (dividend) ***) |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
503 |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
504 |
Goal "[| b*q + r = b'*q' + r'; #0 <= b'*q' + r'; \ |
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
505 |
\ r' < b'; #0 <= r; #0 < b'; b' <= b |] \ |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
506 |
\ ==> q <= (q'::int)"; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
507 |
by (subgoal_tac "#0 <= q'" 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
508 |
by (subgoal_tac "#0 < b'*(q' + #1)" 2); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
509 |
by (asm_simp_tac (simpset() addsimps [zadd_zmult_distrib2]) 3); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
510 |
by (asm_full_simp_tac (simpset() addsimps [pos_imp_zmult_pos_iff]) 2); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
511 |
by (subgoal_tac "b*q < b*(q' + #1)" 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
512 |
by (Asm_full_simp_tac 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
513 |
by (subgoal_tac "b*q = r' - r + b'*q'" 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
514 |
by (simp_tac (simpset() addsimps zcompare_rls) 2); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
515 |
by (asm_simp_tac (simpset() addsimps [zadd_zmult_distrib2]) 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
516 |
by (stac zadd_commute 1 THEN rtac zadd_zless_mono 1 THEN arith_tac 1); |
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
517 |
by (rtac zmult_zle_mono1 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
518 |
by Auto_tac; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
519 |
qed "zdiv_mono2_lemma"; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
520 |
|
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
521 |
Goal "[| (#0::int) <= a; #0 < b'; b' <= b |] \ |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
522 |
\ ==> a div b <= a div b'"; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
523 |
by (subgoal_tac "b ~= #0" 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
524 |
by (arith_tac 2); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
525 |
by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1); |
6992 | 526 |
by (cut_inst_tac [("a","a"),("b","b'")] zmod_zdiv_equality 1); |
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
527 |
by (rtac zdiv_mono2_lemma 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
528 |
by (etac subst 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
529 |
by (etac subst 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
530 |
by (ALLGOALS (asm_simp_tac (simpset() addsimps [pos_mod_sign,pos_mod_bound]))); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
531 |
qed "zdiv_mono2"; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
532 |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
533 |
Goal "[| b*q + r = b'*q' + r'; b'*q' + r' < #0; \ |
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
534 |
\ r < b; #0 <= r'; #0 < b'; b' <= b |] \ |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
535 |
\ ==> q' <= (q::int)"; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
536 |
by (subgoal_tac "q' < #0" 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
537 |
by (subgoal_tac "b'*q' < #0" 2); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
538 |
by (arith_tac 3); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
539 |
by (asm_full_simp_tac (simpset() addsimps [pos_imp_zmult_neg_iff]) 2); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
540 |
by (subgoal_tac "b*q' < b*(q + #1)" 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
541 |
by (Asm_full_simp_tac 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
542 |
by (asm_simp_tac (simpset() addsimps [zadd_zmult_distrib2]) 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
543 |
by (subgoal_tac "b*q' <= b'*q'" 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
544 |
by (asm_simp_tac (simpset() addsimps [zmult_zle_mono1_neg]) 2); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
545 |
by (subgoal_tac "b'*q' < b + b*q" 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
546 |
by (Asm_simp_tac 2); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
547 |
by (arith_tac 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
548 |
qed "zdiv_mono2_neg_lemma"; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
549 |
|
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
550 |
Goal "[| a < (#0::int); #0 < b'; b' <= b |] \ |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
551 |
\ ==> a div b' <= a div b"; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
552 |
by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1); |
6992 | 553 |
by (cut_inst_tac [("a","a"),("b","b'")] zmod_zdiv_equality 1); |
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
554 |
by (rtac zdiv_mono2_neg_lemma 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
555 |
by (etac subst 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
556 |
by (etac subst 1); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
557 |
by (ALLGOALS (asm_simp_tac (simpset() addsimps [pos_mod_sign,pos_mod_bound]))); |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
558 |
qed "zdiv_mono2_neg"; |
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
559 |
|
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
560 |
|
6992 | 561 |
(*** More algebraic laws for div and mod ***) |
6943
2cde117d2738
faster division algorithm; monotonicity of div in 2nd arg
paulson
parents:
6917
diff
changeset
|
562 |
|
6992 | 563 |
(** proving (a*b) div c = a * (b div c) + a * (b mod c) **) |
564 |
||
565 |
Goal "[| quorem((b,c),(q,r)); c ~= #0 |] \ |
|
566 |
\ ==> quorem ((a*b, c), (a*q + a*r div c, a*r mod c))"; |
|
567 |
by (auto_tac |
|
568 |
(claset(), |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
569 |
simpset() addsimps split_ifs@zmult_ac@ |
6992 | 570 |
[quorem_def, linorder_neq_iff, |
571 |
zadd_zmult_distrib2, |
|
572 |
pos_mod_sign,pos_mod_bound, |
|
573 |
neg_mod_sign, neg_mod_bound])); |
|
574 |
by (rtac (zmod_zdiv_equality RS trans) 2); |
|
575 |
by (rtac (zmod_zdiv_equality RS trans) 1); |
|
576 |
by Auto_tac; |
|
577 |
val lemma = result(); |
|
578 |
||
579 |
Goal "(a*b) div c = a*(b div c) + a*(b mod c) div (c::int)"; |
|
7035 | 580 |
by (zdiv_undefined_case_tac "c = #0" 1); |
6992 | 581 |
by (blast_tac (claset() addIs [quorem_div_mod RS lemma RS quorem_div]) 1); |
582 |
qed "zdiv_zmult1_eq"; |
|
583 |
||
584 |
Goal "(a*b) mod c = a*(b mod c) mod (c::int)"; |
|
7035 | 585 |
by (zdiv_undefined_case_tac "c = #0" 1); |
6992 | 586 |
by (blast_tac (claset() addIs [quorem_div_mod RS lemma RS quorem_mod]) 1); |
587 |
qed "zmod_zmult1_eq"; |
|
588 |
||
589 |
Goal "b ~= (#0::int) ==> (a*b) div b = a"; |
|
590 |
by (asm_simp_tac (simpset() addsimps [zdiv_zmult1_eq]) 1); |
|
591 |
qed "zdiv_zmult_self1"; |
|
592 |
||
593 |
Goal "b ~= (#0::int) ==> (b*a) div b = a"; |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
594 |
by (stac zmult_commute 1 THEN etac zdiv_zmult_self1 1); |
6992 | 595 |
qed "zdiv_zmult_self2"; |
596 |
||
597 |
Addsimps [zdiv_zmult_self1, zdiv_zmult_self2]; |
|
598 |
||
599 |
Goal "(a*b) mod b = (#0::int)"; |
|
600 |
by (simp_tac (simpset() addsimps [zmod_zmult1_eq]) 1); |
|
601 |
qed "zmod_zmult_self1"; |
|
602 |
||
603 |
Goal "(b*a) mod b = (#0::int)"; |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
604 |
by (simp_tac (simpset() addsimps [zmult_commute, zmod_zmult1_eq]) 1); |
6992 | 605 |
qed "zmod_zmult_self2"; |
606 |
||
607 |
Addsimps [zmod_zmult_self1, zmod_zmult_self2]; |
|
608 |
||
609 |
||
610 |
(** proving (a+b) div c = a div c + b div c + ((a mod c + b mod c) div c) **) |
|
6917 | 611 |
|
6992 | 612 |
Goal "[| quorem((a,c),(aq,ar)); quorem((b,c),(bq,br)); c ~= #0 |] \ |
613 |
\ ==> quorem ((a+b, c), (aq + bq + (ar+br) div c, (ar+br) mod c))"; |
|
614 |
by (auto_tac |
|
615 |
(claset(), |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
616 |
simpset() addsimps split_ifs@zmult_ac@ |
6992 | 617 |
[quorem_def, linorder_neq_iff, |
618 |
zadd_zmult_distrib2, |
|
619 |
pos_mod_sign,pos_mod_bound, |
|
620 |
neg_mod_sign, neg_mod_bound])); |
|
621 |
by (rtac (zmod_zdiv_equality RS trans) 2); |
|
622 |
by (rtac (zmod_zdiv_equality RS trans) 1); |
|
623 |
by Auto_tac; |
|
624 |
val lemma = result(); |
|
625 |
||
6999 | 626 |
(*NOT suitable for rewriting: the RHS has an instance of the LHS*) |
6992 | 627 |
Goal "(a+b) div (c::int) = a div c + b div c + ((a mod c + b mod c) div c)"; |
7035 | 628 |
by (zdiv_undefined_case_tac "c = #0" 1); |
6992 | 629 |
by (blast_tac (claset() addIs [[quorem_div_mod,quorem_div_mod] |
630 |
MRS lemma RS quorem_div]) 1); |
|
631 |
qed "zdiv_zadd1_eq"; |
|
632 |
||
633 |
Goal "(a+b) mod (c::int) = (a mod c + b mod c) mod c"; |
|
7035 | 634 |
by (zdiv_undefined_case_tac "c = #0" 1); |
6992 | 635 |
by (blast_tac (claset() addIs [[quorem_div_mod,quorem_div_mod] |
636 |
MRS lemma RS quorem_mod]) 1); |
|
637 |
qed "zmod_zadd1_eq"; |
|
638 |
||
639 |
||
640 |
Goal "(a mod b) div b = (#0::int)"; |
|
7035 | 641 |
by (zdiv_undefined_case_tac "b = #0" 1); |
6992 | 642 |
by (auto_tac (claset(), |
6999 | 643 |
simpset() addsimps [linorder_neq_iff, |
644 |
pos_mod_sign, pos_mod_bound, div_pos_pos_trivial, |
|
645 |
neg_mod_sign, neg_mod_bound, div_neg_neg_trivial])); |
|
6992 | 646 |
qed "mod_div_trivial"; |
647 |
Addsimps [mod_div_trivial]; |
|
648 |
||
649 |
Goal "(a mod b) mod b = a mod (b::int)"; |
|
7035 | 650 |
by (zdiv_undefined_case_tac "b = #0" 1); |
6992 | 651 |
by (auto_tac (claset(), |
6999 | 652 |
simpset() addsimps [linorder_neq_iff, |
653 |
pos_mod_sign, pos_mod_bound, mod_pos_pos_trivial, |
|
654 |
neg_mod_sign, neg_mod_bound, mod_neg_neg_trivial])); |
|
6992 | 655 |
qed "mod_mod_trivial"; |
656 |
Addsimps [mod_mod_trivial]; |
|
657 |
||
658 |
||
659 |
Goal "a ~= (#0::int) ==> (a+b) div a = b div a + #1"; |
|
660 |
by (asm_simp_tac (simpset() addsimps [zdiv_zadd1_eq]) 1); |
|
661 |
qed "zdiv_zadd_self1"; |
|
662 |
||
663 |
Goal "a ~= (#0::int) ==> (b+a) div a = b div a + #1"; |
|
664 |
by (asm_simp_tac (simpset() addsimps [zdiv_zadd1_eq]) 1); |
|
665 |
qed "zdiv_zadd_self2"; |
|
666 |
Addsimps [zdiv_zadd_self1, zdiv_zadd_self2]; |
|
667 |
||
668 |
Goal "(a+b) mod a = b mod (a::int)"; |
|
7035 | 669 |
by (zdiv_undefined_case_tac "a = #0" 1); |
6992 | 670 |
by (asm_simp_tac (simpset() addsimps [zmod_zadd1_eq]) 1); |
671 |
qed "zmod_zadd_self1"; |
|
672 |
||
673 |
Goal "(b+a) mod a = b mod (a::int)"; |
|
7035 | 674 |
by (zdiv_undefined_case_tac "a = #0" 1); |
6992 | 675 |
by (asm_simp_tac (simpset() addsimps [zmod_zadd1_eq]) 1); |
676 |
qed "zmod_zadd_self2"; |
|
677 |
Addsimps [zmod_zadd_self1, zmod_zadd_self2]; |
|
678 |
||
679 |
||
680 |
(*** proving a div (b*c) = (a div b) div c ***) |
|
681 |
||
682 |
(*The condition c>0 seems necessary. Consider that 7 div ~6 = ~2 but |
|
683 |
7 div 2 div ~3 = 3 div ~3 = ~1. The subcase (a div b) mod c = 0 seems |
|
684 |
to cause particular problems.*) |
|
685 |
||
686 |
(** first, four lemmas to bound the remainder for the cases b<0 and b>0 **) |
|
6917 | 687 |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
688 |
Goal "[| (#0::int) < c; b < r; r <= #0 |] ==> b*c < b*(q mod c) + r"; |
6992 | 689 |
by (subgoal_tac "b * (c - q mod c) < r * #1" 1); |
690 |
by (asm_full_simp_tac (simpset() addsimps [zdiff_zmult_distrib2]) 1); |
|
691 |
by (rtac order_le_less_trans 1); |
|
692 |
by (etac zmult_zless_mono1 2); |
|
693 |
by (rtac zmult_zle_mono2_neg 1); |
|
694 |
by (auto_tac |
|
695 |
(claset(), |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
696 |
simpset() addsimps zcompare_rls@ |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
697 |
[zadd_commute, add1_zle_eq, pos_mod_bound])); |
6992 | 698 |
val lemma1 = result(); |
699 |
||
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
700 |
Goal "[| (#0::int) < c; b < r; r <= #0 |] ==> b * (q mod c) + r <= #0"; |
6992 | 701 |
by (subgoal_tac "b * (q mod c) <= #0" 1); |
702 |
by (arith_tac 1); |
|
703 |
by (asm_simp_tac (simpset() addsimps [neg_imp_zmult_nonpos_iff, |
|
704 |
pos_mod_sign]) 1); |
|
705 |
val lemma2 = result(); |
|
706 |
||
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
707 |
Goal "[| (#0::int) < c; #0 <= r; r < b |] ==> #0 <= b * (q mod c) + r"; |
6992 | 708 |
by (subgoal_tac "#0 <= b * (q mod c)" 1); |
709 |
by (arith_tac 1); |
|
710 |
by (asm_simp_tac |
|
711 |
(simpset() addsimps [pos_imp_zmult_nonneg_iff, pos_mod_sign]) 1); |
|
712 |
val lemma3 = result(); |
|
713 |
||
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
714 |
Goal "[| (#0::int) < c; #0 <= r; r < b |] ==> b * (q mod c) + r < b * c"; |
6992 | 715 |
by (subgoal_tac "r * #1 < b * (c - q mod c)" 1); |
716 |
by (asm_full_simp_tac (simpset() addsimps [zdiff_zmult_distrib2]) 1); |
|
717 |
by (rtac order_less_le_trans 1); |
|
718 |
by (etac zmult_zless_mono1 1); |
|
719 |
by (rtac zmult_zle_mono2 2); |
|
720 |
by (auto_tac |
|
721 |
(claset(), |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
722 |
simpset() addsimps zcompare_rls@ |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
723 |
[zadd_commute, add1_zle_eq, pos_mod_bound])); |
6992 | 724 |
val lemma4 = result(); |
725 |
||
726 |
Goal "[| quorem ((a,b), (q,r)); b ~= #0; #0 < c |] \ |
|
727 |
\ ==> quorem ((a, b*c), (q div c, b*(q mod c) + r))"; |
|
728 |
by (auto_tac (*SLOW*) |
|
729 |
(claset(), |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
730 |
simpset() addsimps split_ifs@zmult_ac@ |
6992 | 731 |
[quorem_def, linorder_neq_iff, |
732 |
pos_imp_zmult_pos_iff, |
|
733 |
neg_imp_zmult_pos_iff, |
|
734 |
zadd_zmult_distrib2 RS sym, |
|
735 |
lemma1, lemma2, lemma3, lemma4])); |
|
736 |
by (rtac (zmod_zdiv_equality RS trans) 2); |
|
737 |
by (rtac (zmod_zdiv_equality RS trans) 1); |
|
738 |
by Auto_tac; |
|
739 |
val lemma = result(); |
|
740 |
||
741 |
Goal "(#0::int) < c ==> a div (b*c) = (a div b) div c"; |
|
7035 | 742 |
by (zdiv_undefined_case_tac "b = #0" 1); |
6992 | 743 |
by (force_tac (claset(), |
744 |
simpset() addsimps [quorem_div_mod RS lemma RS quorem_div, |
|
745 |
zmult_eq_0_iff]) 1); |
|
746 |
qed "zdiv_zmult2_eq"; |
|
6917 | 747 |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
748 |
Goal "(#0::int) < c ==> a mod (b*c) = b*(a div b mod c) + a mod b"; |
7035 | 749 |
by (zdiv_undefined_case_tac "b = #0" 1); |
6992 | 750 |
by (force_tac (claset(), |
751 |
simpset() addsimps [quorem_div_mod RS lemma RS quorem_mod, |
|
752 |
zmult_eq_0_iff]) 1); |
|
753 |
qed "zmod_zmult2_eq"; |
|
754 |
||
755 |
||
756 |
(*** Cancellation of common factors in "div" ***) |
|
757 |
||
758 |
Goal "[| (#0::int) < b; c ~= #0 |] ==> (c*a) div (c*b) = a div b"; |
|
759 |
by (stac zdiv_zmult2_eq 1); |
|
760 |
by Auto_tac; |
|
761 |
val lemma1 = result(); |
|
762 |
||
763 |
Goal "[| b < (#0::int); c ~= #0 |] ==> (c*a) div (c*b) = a div b"; |
|
7127
48e235179ffb
added parentheses to cope with a possible reduction of the precedence of unary
paulson
parents:
7086
diff
changeset
|
764 |
by (subgoal_tac "(c * (-a)) div (c * (-b)) = (-a) div (-b)" 1); |
6992 | 765 |
by (rtac lemma1 2); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
766 |
by (auto_tac (claset(), simpset() addsimps [zmult_zminus_right])); |
6992 | 767 |
val lemma2 = result(); |
768 |
||
769 |
Goal "c ~= (#0::int) ==> (c*a) div (c*b) = a div b"; |
|
7035 | 770 |
by (zdiv_undefined_case_tac "b = #0" 1); |
6992 | 771 |
by (auto_tac |
772 |
(claset(), |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
773 |
simpset() addsimps [read_instantiate [("x", "b")] linorder_neq_iff, |
6992 | 774 |
lemma1, lemma2])); |
775 |
qed "zdiv_zmult_zmult1"; |
|
6917 | 776 |
|
6992 | 777 |
Goal "c ~= (#0::int) ==> (a*c) div (b*c) = a div b"; |
778 |
by (dtac zdiv_zmult_zmult1 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
779 |
by (auto_tac (claset(), simpset() addsimps [zmult_commute])); |
6992 | 780 |
qed "zdiv_zmult_zmult2"; |
781 |
||
782 |
||
783 |
||
784 |
(*** Distribution of factors over "mod" ***) |
|
785 |
||
786 |
Goal "[| (#0::int) < b; c ~= #0 |] ==> (c*a) mod (c*b) = c * (a mod b)"; |
|
787 |
by (stac zmod_zmult2_eq 1); |
|
788 |
by Auto_tac; |
|
789 |
val lemma1 = result(); |
|
790 |
||
791 |
Goal "[| b < (#0::int); c ~= #0 |] ==> (c*a) mod (c*b) = c * (a mod b)"; |
|
7127
48e235179ffb
added parentheses to cope with a possible reduction of the precedence of unary
paulson
parents:
7086
diff
changeset
|
792 |
by (subgoal_tac "(c * (-a)) mod (c * (-b)) = c * ((-a) mod (-b))" 1); |
6992 | 793 |
by (rtac lemma1 2); |
794 |
by (auto_tac (claset(), |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
795 |
simpset() addsimps [zmult_zminus_right, zmod_zminus_zminus])); |
6992 | 796 |
val lemma2 = result(); |
797 |
||
6999 | 798 |
Goal "(c*a) mod (c*b) = (c::int) * (a mod b)"; |
7035 | 799 |
by (zdiv_undefined_case_tac "b = #0" 1); |
800 |
by (zdiv_undefined_case_tac "c = #0" 1); |
|
6992 | 801 |
by (auto_tac |
802 |
(claset(), |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
803 |
simpset() addsimps [read_instantiate [("x", "b")] linorder_neq_iff, |
6992 | 804 |
lemma1, lemma2])); |
805 |
qed "zmod_zmult_zmult1"; |
|
806 |
||
6999 | 807 |
Goal "(a*c) mod (b*c) = (a mod b) * (c::int)"; |
808 |
by (cut_inst_tac [("c","c")] zmod_zmult_zmult1 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
809 |
by (auto_tac (claset(), simpset() addsimps [zmult_commute])); |
6992 | 810 |
qed "zmod_zmult_zmult2"; |
811 |
||
812 |
||
6999 | 813 |
(*** Speeding up the division algorithm with shifting ***) |
6992 | 814 |
|
7035 | 815 |
(** computing "div" by shifting **) |
6999 | 816 |
|
817 |
Goal "(#0::int) <= a ==> (#1 + #2*b) div (#2*a) = b div a"; |
|
7035 | 818 |
by (zdiv_undefined_case_tac "a = #0" 1); |
6999 | 819 |
by (subgoal_tac "#1 <= a" 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
820 |
by (arith_tac 2); |
6999 | 821 |
by (subgoal_tac "#1 < a * #2" 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
822 |
by (dres_inst_tac [("i","#1"), ("k", "#2")] zmult_zle_mono1 2); |
6999 | 823 |
by (subgoal_tac "#2*(#1 + b mod a) <= #2*a" 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
824 |
by (rtac zmult_zle_mono2 2); |
6999 | 825 |
by (auto_tac (claset(), |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
826 |
simpset() addsimps [zadd_commute, zmult_commute, |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
827 |
add1_zle_eq, pos_mod_bound])); |
6999 | 828 |
by (stac zdiv_zadd1_eq 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
829 |
by (asm_simp_tac (simpset() addsimps [zdiv_zmult_zmult2, zmod_zmult_zmult2, |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
830 |
div_pos_pos_trivial]) 1); |
6999 | 831 |
by (stac div_pos_pos_trivial 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
832 |
by (asm_simp_tac (simpset() addsimps zadd_ac@ |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
833 |
[zmult_2_right, mod_pos_pos_trivial, |
6999 | 834 |
pos_mod_sign RS zadd_zle_mono1 RSN (2,order_trans)]) 1); |
835 |
by (auto_tac (claset(), |
|
836 |
simpset() addsimps [mod_pos_pos_trivial])); |
|
837 |
qed "pos_zdiv_times_2"; |
|
838 |
||
839 |
||
840 |
Goal "a <= (#0::int) ==> (#1 + #2*b) div (#2*a) = (b+#1) div a"; |
|
7127
48e235179ffb
added parentheses to cope with a possible reduction of the precedence of unary
paulson
parents:
7086
diff
changeset
|
841 |
by (subgoal_tac "(#1 + #2*(-b-#1)) div (#2 * (-a)) = (-b-#1) div (-a)" 1); |
7035 | 842 |
by (rtac pos_zdiv_times_2 2); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
843 |
by (auto_tac (claset(), |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
844 |
simpset() addsimps [zmult_zminus_right])); |
7127
48e235179ffb
added parentheses to cope with a possible reduction of the precedence of unary
paulson
parents:
7086
diff
changeset
|
845 |
by (subgoal_tac "(#-1 - (#2 * b)) = - (#1 + (#2 * b))" 1); |
6999 | 846 |
by (Simp_tac 2); |
847 |
by (asm_full_simp_tac (HOL_ss |
|
848 |
addsimps [zdiv_zminus_zminus, zdiff_def, |
|
849 |
zminus_zadd_distrib RS sym]) 1); |
|
850 |
qed "neg_zdiv_times_2"; |
|
851 |
||
852 |
||
853 |
(*Not clear why this must be proved separately; probably number_of causes |
|
854 |
simplification problems*) |
|
855 |
Goal "~ #0 <= x ==> x <= (#0::int)"; |
|
7035 | 856 |
by Auto_tac; |
6999 | 857 |
val lemma = result(); |
858 |
||
859 |
Goal "number_of (v BIT b) div number_of (w BIT False) = \ |
|
860 |
\ (if ~b | (#0::int) <= number_of w \ |
|
861 |
\ then number_of v div (number_of w) \ |
|
862 |
\ else (number_of v + (#1::int)) div (number_of w))"; |
|
863 |
by (simp_tac (simpset_of Int.thy |
|
864 |
addsimps [zadd_assoc, number_of_BIT]) 1); |
|
7035 | 865 |
by (asm_simp_tac (simpset() |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
866 |
delsimps bin_arith_extra_simps@bin_rel_simps |
7035 | 867 |
addsimps [zmult_2 RS sym, zdiv_zmult_zmult1, |
868 |
pos_zdiv_times_2, lemma, neg_zdiv_times_2]) 1); |
|
6999 | 869 |
qed "zdiv_number_of_BIT"; |
870 |
||
871 |
Addsimps [zdiv_number_of_BIT]; |
|
872 |
||
873 |
||
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
874 |
(** computing "mod" by shifting (proofs resemble those for "div") **) |
7035 | 875 |
|
876 |
Goal "(#0::int) <= a ==> (#1 + #2*b) mod (#2*a) = #1 + #2 * (b mod a)"; |
|
877 |
by (zdiv_undefined_case_tac "a = #0" 1); |
|
878 |
by (subgoal_tac "#1 <= a" 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
879 |
by (arith_tac 2); |
7035 | 880 |
by (subgoal_tac "#1 < a * #2" 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
881 |
by (dres_inst_tac [("i","#1"), ("k", "#2")] zmult_zle_mono1 2); |
7035 | 882 |
by (subgoal_tac "#2*(#1 + b mod a) <= #2*a" 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
883 |
by (rtac zmult_zle_mono2 2); |
7035 | 884 |
by (auto_tac (claset(), |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
885 |
simpset() addsimps [zadd_commute, zmult_commute, |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
886 |
add1_zle_eq, pos_mod_bound])); |
7035 | 887 |
by (stac zmod_zadd1_eq 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
888 |
by (asm_simp_tac (simpset() addsimps [zmod_zmult_zmult2, |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
889 |
mod_pos_pos_trivial]) 1); |
7035 | 890 |
by (rtac mod_pos_pos_trivial 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
891 |
by (asm_simp_tac (simpset() addsimps zadd_ac@ |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
892 |
[zmult_2_right, mod_pos_pos_trivial, |
7035 | 893 |
pos_mod_sign RS zadd_zle_mono1 RSN (2,order_trans)]) 1); |
894 |
by (auto_tac (claset(), |
|
895 |
simpset() addsimps [mod_pos_pos_trivial])); |
|
896 |
qed "pos_zmod_times_2"; |
|
897 |
||
898 |
||
899 |
Goal "a <= (#0::int) ==> (#1 + #2*b) mod (#2*a) = #2 * ((b+#1) mod a) - #1"; |
|
900 |
by (subgoal_tac |
|
7127
48e235179ffb
added parentheses to cope with a possible reduction of the precedence of unary
paulson
parents:
7086
diff
changeset
|
901 |
"(#1 + #2*(-b-#1)) mod (#2*(-a)) = #1 + #2*((-b-#1) mod (-a))" 1); |
7035 | 902 |
by (rtac pos_zmod_times_2 2); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
903 |
by (auto_tac (claset(), |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
904 |
simpset() addsimps [zmult_zminus_right])); |
7127
48e235179ffb
added parentheses to cope with a possible reduction of the precedence of unary
paulson
parents:
7086
diff
changeset
|
905 |
by (subgoal_tac "(#-1 - (#2 * b)) = - (#1 + (#2 * b))" 1); |
7035 | 906 |
by (Simp_tac 2); |
907 |
by (asm_full_simp_tac (HOL_ss |
|
908 |
addsimps [zmod_zminus_zminus, zdiff_def, |
|
909 |
zminus_zadd_distrib RS sym]) 1); |
|
7086 | 910 |
by (dtac (zminus_equation RS iffD1 RS sym) 1); |
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
911 |
by (auto_tac (claset(), |
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
912 |
simpset() addsimps [zmult_zminus_right])); |
7035 | 913 |
qed "neg_zmod_times_2"; |
914 |
||
915 |
Goal "number_of (v BIT b) mod number_of (w BIT False) = \ |
|
916 |
\ (if b then \ |
|
917 |
\ if (#0::int) <= number_of w \ |
|
918 |
\ then #2 * (number_of v mod number_of w) + #1 \ |
|
919 |
\ else #2 * ((number_of v + (#1::int)) mod number_of w) - #1 \ |
|
920 |
\ else #2 * (number_of v mod number_of w))"; |
|
921 |
by (simp_tac (simpset_of Int.thy |
|
922 |
addsimps [zadd_assoc, number_of_BIT]) 1); |
|
923 |
by (asm_simp_tac (simpset() |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
924 |
delsimps bin_arith_extra_simps@bin_rel_simps |
7035 | 925 |
addsimps [zmult_2 RS sym, zmod_zmult_zmult1, |
926 |
pos_zmod_times_2, lemma, neg_zmod_times_2]) 1); |
|
927 |
qed "zmod_number_of_BIT"; |
|
928 |
||
929 |
Addsimps [zmod_number_of_BIT]; |
|
930 |
||
931 |
||
932 |
(** Quotients of signs **) |
|
933 |
||
934 |
Goal "[| a < (#0::int); #0 < b |] ==> a div b < #0"; |
|
935 |
by (subgoal_tac "a div b <= #-1" 1); |
|
936 |
by (Force_tac 1); |
|
937 |
by (rtac order_trans 1); |
|
938 |
by (res_inst_tac [("a'","#-1")] zdiv_mono1 1); |
|
7074
e0730ffaafcc
zadd_ac and zmult_ac are no longer included by default
paulson
parents:
7035
diff
changeset
|
939 |
by (auto_tac (claset(), simpset() addsimps [zdiv_minus1])); |
7127
48e235179ffb
added parentheses to cope with a possible reduction of the precedence of unary
paulson
parents:
7086
diff
changeset
|
940 |
qed "div_neg_pos_less0"; |
7035 | 941 |
|
942 |
Goal "[| (#0::int) <= a; b < #0 |] ==> a div b <= #0"; |
|
943 |
by (dtac zdiv_mono1_neg 1); |
|
944 |
by Auto_tac; |
|
7127
48e235179ffb
added parentheses to cope with a possible reduction of the precedence of unary
paulson
parents:
7086
diff
changeset
|
945 |
qed "div_nonneg_neg_le0"; |
7035 | 946 |
|
947 |
Goal "(#0::int) < b ==> (#0 <= a div b) = (#0 <= a)"; |
|
948 |
by Auto_tac; |
|
949 |
by (dtac zdiv_mono1 2); |
|
950 |
by (auto_tac (claset(), simpset() addsimps [linorder_neq_iff])); |
|
951 |
by (full_simp_tac (simpset() addsimps [linorder_not_less RS sym]) 1); |
|
7127
48e235179ffb
added parentheses to cope with a possible reduction of the precedence of unary
paulson
parents:
7086
diff
changeset
|
952 |
by (blast_tac (claset() addIs [div_neg_pos_less0]) 1); |
7035 | 953 |
qed "pos_imp_zdiv_nonneg_iff"; |
954 |
||
955 |
Goal "b < (#0::int) ==> (#0 <= a div b) = (a <= (#0::int))"; |
|
956 |
by (stac (zdiv_zminus_zminus RS sym) 1); |
|
957 |
by (stac pos_imp_zdiv_nonneg_iff 1); |
|
958 |
by Auto_tac; |
|
959 |
qed "neg_imp_zdiv_nonneg_iff"; |
|
960 |
||
961 |
(*But not (a div b <= 0 iff a<=0); consider a=1, b=2 when a div b = 0.*) |
|
962 |
Goal "(#0::int) < b ==> (a div b < #0) = (a < #0)"; |
|
963 |
by (asm_simp_tac (simpset() addsimps [linorder_not_le RS sym, |
|
964 |
pos_imp_zdiv_nonneg_iff]) 1); |
|
965 |
qed "pos_imp_zdiv_neg_iff"; |
|
966 |
||
967 |
(*Again the law fails for <=: consider a = -1, b = -2 when a div b = 0*) |
|
968 |
Goal "b < (#0::int) ==> (a div b < #0) = (#0 < a)"; |
|
969 |
by (asm_simp_tac (simpset() addsimps [linorder_not_le RS sym, |
|
970 |
neg_imp_zdiv_nonneg_iff]) 1); |
|
971 |
qed "neg_imp_zdiv_neg_iff"; |