1 (* Title: HOL/IntDiv.ML
3 Author: Lawrence C Paulson, Cambridge University Computer Laboratory
4 Copyright 1999 University of Cambridge
6 The division operators div, mod and the divides relation "dvd"
8 Here is the division algorithm in ML:
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)
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)
22 fun negateSnd (q,r:int) = (q,~r);
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))
29 if 0<b then negDivAlg (a,b)
30 else negateSnd (posDivAlg (~a,~b));
33 Addsimps [zless_nat_conj];
35 (*** Uniqueness and monotonicity of quotients and remainders ***)
37 Goal "[| b*q' + r' <= b*q + r; 0 <= r'; 0 < b; r < b |] \
38 \ ==> q' <= (q::int)";
39 by (subgoal_tac "r' + b * (q'-q) <= r" 1);
40 by (simp_tac (simpset() addsimps [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 [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 [zdiff_zmult_distrib2,
47 zadd_zmult_distrib2]) 2);
48 by (asm_full_simp_tac (simpset() addsimps [zmult_zless_cancel1]) 1);
49 qed "unique_quotient_lemma";
51 Goal "[| b*q' + r' <= b*q + r; r <= 0; b < 0; b < r' |] \
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(),
56 simpset() addsimps [zmult_zminus, zmult_zminus_right]));
57 qed "unique_quotient_lemma_neg";
60 Goal "[| quorem ((a,b), (q,r)); quorem ((a,b), (q',r')); b ~= 0 |] \
63 (simpset() addsimps split_ifs@
64 [quorem_def, linorder_neq_iff]) 1);
66 by (ALLGOALS Asm_full_simp_tac);
68 (blast_tac (claset() addIs [order_antisym]
69 addDs [order_eq_refl RS unique_quotient_lemma,
70 order_eq_refl RS unique_quotient_lemma_neg,
72 qed "unique_quotient";
75 Goal "[| quorem ((a,b), (q,r)); quorem ((a,b), (q',r')); b ~= 0 |] \
77 by (subgoal_tac "q = q'" 1);
78 by (blast_tac (claset() addIs [unique_quotient]) 2);
79 by (asm_full_simp_tac (simpset() addsimps [quorem_def]) 1);
80 qed "unique_remainder";
83 (*** Correctness of posDivAlg, the division algorithm for a>=0 and b>0 ***)
86 Goal "adjust b (q,r) = (let diff = r-b in \
87 \ if 0 <= diff then (2*q + 1, diff) \
89 by (simp_tac (simpset() addsimps [Let_def,adjust_def]) 1);
93 (*Proving posDivAlg's termination condition*)
94 val [tc] = posDivAlg.tcs;
95 goalw_cterm [] (cterm_of (sign_of (the_context ())) (HOLogic.mk_Trueprop tc));
99 (* removing the termination condition from the generated theorems *)
101 bind_thm ("posDivAlg_raw_eqn", lemma RS hd posDivAlg.simps);
103 (**use with simproc to avoid re-proving the premise*)
105 \ posDivAlg (a,b) = \
106 \ (if a<b then (0,a) else adjust b (posDivAlg(a, 2*b)))";
107 by (rtac (posDivAlg_raw_eqn RS trans) 1);
111 bind_thm ("posDivAlg_induct", lemma RS posDivAlg.induct);
114 (*Correctness of posDivAlg: it computes quotients correctly*)
115 Goal "0 <= a --> 0 < b --> quorem ((a, b), posDivAlg (a, b))";
116 by (induct_thm_tac posDivAlg_induct "a b" 1);
118 by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [quorem_def])));
120 by (asm_full_simp_tac (simpset() addsimps [posDivAlg_eqn]) 1);
122 by (stac posDivAlg_eqn 1);
123 by (ALLGOALS Asm_simp_tac);
125 by (auto_tac (claset(), simpset() addsimps [zadd_zmult_distrib2, Let_def]));
126 qed_spec_mp "posDivAlg_correct";
129 (*** Correctness of negDivAlg, the division algorithm for a<0 and b>0 ***)
131 (*Proving negDivAlg's termination condition*)
132 val [tc] = negDivAlg.tcs;
133 goalw_cterm [] (cterm_of (sign_of (the_context ())) (HOLogic.mk_Trueprop tc));
135 val lemma = result();
137 (* removing the termination condition from the generated theorems *)
139 bind_thm ("negDivAlg_raw_eqn", lemma RS hd negDivAlg.simps);
141 (**use with simproc to avoid re-proving the premise*)
143 \ negDivAlg (a,b) = \
144 \ (if 0<=a+b then (-1,a+b) else adjust b (negDivAlg(a, 2*b)))";
145 by (rtac (negDivAlg_raw_eqn RS trans) 1);
149 bind_thm ("negDivAlg_induct", lemma RS negDivAlg.induct);
152 (*Correctness of negDivAlg: it computes quotients correctly
153 It doesn't work if a=0 because the 0/b=0 rather than -1*)
154 Goal "a < 0 --> 0 < b --> quorem ((a, b), negDivAlg (a, b))";
155 by (induct_thm_tac negDivAlg_induct "a b" 1);
157 by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [quorem_def])));
158 (*base case: 0<=a+b*)
159 by (asm_full_simp_tac (simpset() addsimps [negDivAlg_eqn]) 1);
161 by (stac negDivAlg_eqn 1);
162 by (ALLGOALS Asm_simp_tac);
164 by (auto_tac (claset(), simpset() addsimps [zadd_zmult_distrib2, Let_def]));
165 qed_spec_mp "negDivAlg_correct";
168 (*** Existence shown by proving the division algorithm to be correct ***)
171 Goal "b ~= 0 ==> quorem ((0,b), (0,0))";
172 by (auto_tac (claset(),
173 simpset() addsimps [quorem_def, linorder_neq_iff]));
176 Goal "posDivAlg (0, b) = (0, 0)";
177 by (stac posDivAlg_raw_eqn 1);
180 Addsimps [posDivAlg_0];
182 Goal "negDivAlg (-1, b) = (-1, b - 1)";
183 by (stac negDivAlg_raw_eqn 1);
185 qed "negDivAlg_minus1";
186 Addsimps [negDivAlg_minus1];
188 Goalw [negateSnd_def] "negateSnd(q,r) = (q,-r)";
191 Addsimps [negateSnd_eq];
193 Goal "quorem ((-a,-b), qr) ==> quorem ((a,b), negateSnd qr)";
194 by (auto_tac (claset(), simpset() addsimps split_ifs@[quorem_def]));
197 Goal "b ~= 0 ==> quorem ((a,b), divAlg(a,b))";
198 by (auto_tac (claset(),
199 simpset() addsimps [quorem_0, divAlg_def]));
200 by (REPEAT_FIRST (resolve_tac [quorem_neg, posDivAlg_correct,
201 negDivAlg_correct]));
202 by (auto_tac (claset(),
203 simpset() addsimps [quorem_def, linorder_neq_iff]));
204 qed "divAlg_correct";
206 (** Arbitrary definitions for division by zero. Useful to simplify
207 certain equations **)
209 Goal "a div (0::int) = 0";
210 by (simp_tac (simpset() addsimps [div_def, divAlg_def, posDivAlg_raw_eqn]) 1);
211 qed "DIVISION_BY_ZERO_ZDIV"; (*NOT for adding to default simpset*)
213 Goal "a mod (0::int) = a";
214 by (simp_tac (simpset() addsimps [mod_def, divAlg_def, posDivAlg_raw_eqn]) 1);
215 qed "DIVISION_BY_ZERO_ZMOD"; (*NOT for adding to default simpset*)
217 fun zdiv_undefined_case_tac s i =
219 asm_simp_tac (simpset() addsimps [DIVISION_BY_ZERO_ZDIV,
220 DIVISION_BY_ZERO_ZMOD]) i;
222 (** Basic laws about division and remainder **)
224 Goal "(a::int) = b * (a div b) + (a mod b)";
225 by (zdiv_undefined_case_tac "b = 0" 1);
226 by (cut_inst_tac [("a","a"),("b","b")] divAlg_correct 1);
227 by (auto_tac (claset(),
228 simpset() addsimps [quorem_def, div_def, mod_def]));
229 qed "zmod_zdiv_equality";
231 Goal "(0::int) < b ==> 0 <= a mod b & a mod b < b";
232 by (cut_inst_tac [("a","a"),("b","b")] divAlg_correct 1);
233 by (auto_tac (claset(),
234 simpset() addsimps [quorem_def, mod_def]));
235 bind_thm ("pos_mod_sign", result() RS conjunct1);
236 bind_thm ("pos_mod_bound", result() RS conjunct2);
238 Goal "b < (0::int) ==> a mod b <= 0 & b < a mod b";
239 by (cut_inst_tac [("a","a"),("b","b")] divAlg_correct 1);
240 by (auto_tac (claset(),
241 simpset() addsimps [quorem_def, div_def, mod_def]));
242 bind_thm ("neg_mod_sign", result() RS conjunct1);
243 bind_thm ("neg_mod_bound", result() RS conjunct2);
246 (** proving general properties of div and mod **)
248 Goal "b ~= 0 ==> quorem ((a, b), (a div b, a mod b))";
249 by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1);
252 simpset() addsimps [quorem_def, linorder_neq_iff,
253 pos_mod_sign,pos_mod_bound,
254 neg_mod_sign, neg_mod_bound]));
255 qed "quorem_div_mod";
257 Goal "[| quorem((a,b),(q,r)); b ~= 0 |] ==> a div b = q";
258 by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS unique_quotient]) 1);
261 Goal "[| quorem((a,b),(q,r)); b ~= 0 |] ==> a mod b = r";
262 by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS unique_remainder]) 1);
265 Goal "[| (0::int) <= a; a < b |] ==> a div b = 0";
266 by (rtac quorem_div 1);
267 by (auto_tac (claset(), simpset() addsimps [quorem_def]));
268 qed "div_pos_pos_trivial";
270 Goal "[| a <= (0::int); b < a |] ==> a div b = 0";
271 by (rtac quorem_div 1);
272 by (auto_tac (claset(), simpset() addsimps [quorem_def]));
273 qed "div_neg_neg_trivial";
275 Goal "[| (0::int) < a; a+b <= 0 |] ==> a div b = -1";
276 by (rtac quorem_div 1);
277 by (auto_tac (claset(), simpset() addsimps [quorem_def]));
278 qed "div_pos_neg_trivial";
280 (*There is no div_neg_pos_trivial because 0 div b = 0 would supersede it*)
282 Goal "[| (0::int) <= a; a < b |] ==> a mod b = a";
283 by (res_inst_tac [("q","0")] quorem_mod 1);
284 by (auto_tac (claset(), simpset() addsimps [quorem_def]));
285 qed "mod_pos_pos_trivial";
287 Goal "[| a <= (0::int); b < a |] ==> a mod b = a";
288 by (res_inst_tac [("q","0")] quorem_mod 1);
289 by (auto_tac (claset(), simpset() addsimps [quorem_def]));
290 qed "mod_neg_neg_trivial";
292 Goal "[| (0::int) < a; a+b <= 0 |] ==> a mod b = a+b";
293 by (res_inst_tac [("q","-1")] quorem_mod 1);
294 by (auto_tac (claset(), simpset() addsimps [quorem_def]));
295 qed "mod_pos_neg_trivial";
297 (*There is no mod_neg_pos_trivial...*)
300 (*Simpler laws such as -a div b = -(a div b) FAIL, but see just below*)
301 Goal "(-a) div (-b) = a div (b::int)";
302 by (zdiv_undefined_case_tac "b = 0" 1);
303 by (stac ((simplify(simpset()) (quorem_div_mod RS quorem_neg))
306 qed "zdiv_zminus_zminus";
307 Addsimps [zdiv_zminus_zminus];
309 (*Simpler laws such as -a mod b = -(a mod b) FAIL, but see just below*)
310 Goal "(-a) mod (-b) = - (a mod (b::int))";
311 by (zdiv_undefined_case_tac "b = 0" 1);
312 by (stac ((simplify(simpset()) (quorem_div_mod RS quorem_neg))
315 qed "zmod_zminus_zminus";
316 Addsimps [zmod_zminus_zminus];
319 (*** div, mod and unary minus ***)
321 Goal "quorem((a,b),(q,r)) \
322 \ ==> quorem ((-a,b), (if r=0 then -q else -q - 1), \
323 \ (if r=0 then 0 else b-r))";
326 simpset() addsimps split_ifs@
327 [quorem_def, linorder_neq_iff,
328 zdiff_zmult_distrib2]));
329 val lemma = result();
331 Goal "b ~= (0::int) \
333 \ (if a mod b = 0 then - (a div b) else - (a div b) - 1)";
334 by (blast_tac (claset() addIs [quorem_div_mod RS lemma RS quorem_div]) 1);
335 qed "zdiv_zminus1_eq_if";
337 Goal "(-a::int) mod b = (if a mod b = 0 then 0 else b - (a mod b))";
338 by (zdiv_undefined_case_tac "b = 0" 1);
339 by (blast_tac (claset() addIs [quorem_div_mod RS lemma RS quorem_mod]) 1);
340 qed "zmod_zminus1_eq_if";
342 Goal "a div (-b) = (-a::int) div b";
343 by (cut_inst_tac [("a","-a")] zdiv_zminus_zminus 1);
347 Goal "a mod (-b) = - ((-a::int) mod b)";
348 by (cut_inst_tac [("a","-a"),("b","b")] zmod_zminus_zminus 1);
352 Goal "b ~= (0::int) \
354 \ (if a mod b = 0 then - (a div b) else - (a div b) - 1)";
355 by (asm_simp_tac (simpset() addsimps [zdiv_zminus1_eq_if, zdiv_zminus2]) 1);
356 qed "zdiv_zminus2_eq_if";
358 Goal "a mod (-b::int) = (if a mod b = 0 then 0 else (a mod b) - b)";
359 by (asm_simp_tac (simpset() addsimps [zmod_zminus1_eq_if, zmod_zminus2]) 1);
360 qed "zmod_zminus2_eq_if";
363 (*** division of a number by itself ***)
365 Goal "[| (0::int) < a; a = r + a*q; r < a |] ==> 1 <= q";
366 by (subgoal_tac "0 < a*q" 1);
368 by (asm_full_simp_tac (simpset() addsimps [int_0_less_mult_iff]) 1);
369 val lemma1 = result();
371 Goal "[| (0::int) < a; a = r + a*q; 0 <= r |] ==> q <= 1";
372 by (subgoal_tac "0 <= a*(1-q)" 1);
373 by (asm_simp_tac (simpset() addsimps [zdiff_zmult_distrib2]) 2);
374 by (asm_full_simp_tac (simpset() addsimps [int_0_le_mult_iff]) 1);
375 val lemma2 = result();
377 Goal "[| quorem((a,a),(q,r)); a ~= (0::int) |] ==> q = 1";
378 by (asm_full_simp_tac
379 (simpset() addsimps split_ifs@[quorem_def, linorder_neq_iff]) 1);
380 by (rtac order_antisym 1);
383 by (res_inst_tac [("a", "-a"),("r", "-r")] lemma1 3);
384 by (res_inst_tac [("a", "-a"),("r", "-r")] lemma2 1);
385 by (REPEAT (force_tac (claset() addIs [lemma1,lemma2],
386 simpset() addsimps [zadd_commute, zmult_zminus]) 1));
389 Goal "[| quorem((a,a),(q,r)); a ~= (0::int) |] ==> r = 0";
390 by (ftac self_quotient 1);
392 by (asm_full_simp_tac (simpset() addsimps [quorem_def]) 1);
393 qed "self_remainder";
395 Goal "a ~= 0 ==> a div a = (1::int)";
396 by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS self_quotient]) 1);
398 Addsimps [zdiv_self];
400 (*Here we have 0 mod 0 = 0, also assumed by Knuth (who puts m mod 0 = 0) *)
401 Goal "a mod a = (0::int)";
402 by (zdiv_undefined_case_tac "a = 0" 1);
403 by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS self_remainder]) 1);
405 Addsimps [zmod_self];
408 (*** Computation of division and remainder ***)
410 Goal "(0::int) div b = 0";
411 by (simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
414 Goal "(0::int) < b ==> -1 div b = -1";
415 by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
418 Goal "(0::int) mod b = 0";
419 by (simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
422 Addsimps [zdiv_zero, zmod_zero];
424 Goal "(0::int) < b ==> -1 div b = -1";
425 by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
428 Goal "(0::int) < b ==> -1 mod b = b - 1";
429 by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
432 (** a positive, b positive **)
434 Goal "[| 0 < a; 0 <= b |] ==> a div b = fst (posDivAlg(a,b))";
435 by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
438 Goal "[| 0 < a; 0 <= b |] ==> a mod b = snd (posDivAlg(a,b))";
439 by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
442 (** a negative, b positive **)
444 Goal "[| a < 0; 0 < b |] ==> a div b = fst (negDivAlg(a,b))";
445 by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
448 Goal "[| a < 0; 0 < b |] ==> a mod b = snd (negDivAlg(a,b))";
449 by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
452 (** a positive, b negative **)
454 Goal "[| 0 < a; b < 0 |] ==> a div b = fst (negateSnd(negDivAlg(-a,-b)))";
455 by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
458 Goal "[| 0 < a; b < 0 |] ==> a mod b = snd (negateSnd(negDivAlg(-a,-b)))";
459 by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
462 (** a negative, b negative **)
464 Goal "[| a < 0; b <= 0 |] ==> a div b = fst (negateSnd(posDivAlg(-a,-b)))";
465 by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
468 Goal "[| a < 0; b <= 0 |] ==> a mod b = snd (negateSnd(posDivAlg(-a,-b)))";
469 by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
472 Addsimps (map (read_instantiate_sg (sign_of (the_context ()))
473 [("a", "number_of ?v"), ("b", "number_of ?w")])
474 [div_pos_pos, div_neg_pos, div_pos_neg, div_neg_neg,
475 mod_pos_pos, mod_neg_pos, mod_pos_neg, mod_neg_neg,
476 posDivAlg_eqn, negDivAlg_eqn]);
479 (** Special-case simplification **)
481 Goal "a mod (1::int) = 0";
482 by (cut_inst_tac [("a","a"),("b","1")] pos_mod_sign 1);
483 by (cut_inst_tac [("a","a"),("b","1")] pos_mod_bound 2);
488 Goal "a div (1::int) = a";
489 by (cut_inst_tac [("a","a"),("b","1")] zmod_zdiv_equality 1);
494 Goal "a mod (-1::int) = 0";
495 by (cut_inst_tac [("a","a"),("b","-1")] neg_mod_sign 1);
496 by (cut_inst_tac [("a","a"),("b","-1")] neg_mod_bound 2);
498 qed "zmod_minus1_right";
499 Addsimps [zmod_minus1_right];
501 Goal "a div (-1::int) = -a";
502 by (cut_inst_tac [("a","a"),("b","-1")] zmod_zdiv_equality 1);
504 qed "zdiv_minus1_right";
505 Addsimps [zdiv_minus1_right];
507 (** The last remaining cases: 1 div z and 1 mod z **)
509 Addsimps (map (fn th => int_0_less_1 RS inst "b" "number_of ?w" th)
510 [div_pos_pos, div_pos_neg, mod_pos_pos, mod_pos_neg]);
512 Addsimps (map (read_instantiate_sg (sign_of (the_context ()))
513 [("a", "1"), ("b", "number_of ?w")])
514 [posDivAlg_eqn, negDivAlg_eqn]);
517 (*** Monotonicity in the first argument (divisor) ***)
519 Goal "[| a <= a'; 0 < (b::int) |] ==> a div b <= a' div b";
520 by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1);
521 by (cut_inst_tac [("a","a'"),("b","b")] zmod_zdiv_equality 1);
522 by (rtac unique_quotient_lemma 1);
525 by (ALLGOALS (asm_simp_tac (simpset() addsimps [pos_mod_sign,pos_mod_bound])));
528 Goal "[| a <= a'; (b::int) < 0 |] ==> a' div b <= a div b";
529 by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1);
530 by (cut_inst_tac [("a","a'"),("b","b")] zmod_zdiv_equality 1);
531 by (rtac unique_quotient_lemma_neg 1);
534 by (ALLGOALS (asm_simp_tac (simpset() addsimps [neg_mod_sign,neg_mod_bound])));
535 qed "zdiv_mono1_neg";
538 (*** Monotonicity in the second argument (dividend) ***)
540 Goal "[| b*q + r = b'*q' + r'; 0 <= b'*q' + r'; \
541 \ r' < b'; 0 <= r; 0 < b'; b' <= b |] \
542 \ ==> q <= (q'::int)";
543 by (subgoal_tac "0 <= q'" 1);
544 by (subgoal_tac "0 < b'*(q' + 1)" 2);
545 by (asm_simp_tac (simpset() addsimps [zadd_zmult_distrib2]) 3);
546 by (asm_full_simp_tac (simpset() addsimps [int_0_less_mult_iff]) 2);
547 by (subgoal_tac "b*q < b*(q' + 1)" 1);
548 by (asm_full_simp_tac (simpset() addsimps [zmult_zless_cancel1]) 1);
549 by (subgoal_tac "b*q = r' - r + b'*q'" 1);
551 by (asm_simp_tac (simpset() addsimps [zadd_zmult_distrib2]) 1);
552 by (stac zadd_commute 1 THEN rtac zadd_zless_mono 1 THEN arith_tac 1);
553 by (rtac zmult_zle_mono1 1);
555 qed "zdiv_mono2_lemma";
557 Goal "[| (0::int) <= a; 0 < b'; b' <= b |] \
558 \ ==> a div b <= a div b'";
559 by (subgoal_tac "b ~= 0" 1);
561 by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1);
562 by (cut_inst_tac [("a","a"),("b","b'")] zmod_zdiv_equality 1);
563 by (rtac zdiv_mono2_lemma 1);
566 by (ALLGOALS (asm_simp_tac (simpset() addsimps [pos_mod_sign,pos_mod_bound])));
569 Goal "[| b*q + r = b'*q' + r'; b'*q' + r' < 0; \
570 \ r < b; 0 <= r'; 0 < b'; b' <= b |] \
571 \ ==> q' <= (q::int)";
572 by (subgoal_tac "q' < 0" 1);
573 by (subgoal_tac "b'*q' < 0" 2);
575 by (asm_full_simp_tac (simpset() addsimps [zmult_less_0_iff]) 2);
576 by (subgoal_tac "b*q' < b*(q + 1)" 1);
577 by (asm_full_simp_tac (simpset() addsimps [zmult_zless_cancel1]) 1);
578 by (asm_simp_tac (simpset() addsimps [zadd_zmult_distrib2]) 1);
579 by (subgoal_tac "b*q' <= b'*q'" 1);
580 by (asm_simp_tac (simpset() addsimps [zmult_zle_mono1_neg]) 2);
581 by (subgoal_tac "b'*q' < b + b*q" 1);
584 qed "zdiv_mono2_neg_lemma";
586 Goal "[| a < (0::int); 0 < b'; b' <= b |] \
587 \ ==> a div b' <= a div b";
588 by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1);
589 by (cut_inst_tac [("a","a"),("b","b'")] zmod_zdiv_equality 1);
590 by (rtac zdiv_mono2_neg_lemma 1);
593 by (ALLGOALS (asm_simp_tac (simpset() addsimps [pos_mod_sign,pos_mod_bound])));
594 qed "zdiv_mono2_neg";
597 (*** More algebraic laws for div and mod ***)
599 (** proving (a*b) div c = a * (b div c) + a * (b mod c) **)
601 Goal "[| quorem((b,c),(q,r)); c ~= 0 |] \
602 \ ==> quorem ((a*b, c), (a*q + a*r div c, a*r mod c))";
605 simpset() addsimps split_ifs@
606 [quorem_def, linorder_neq_iff,
608 pos_mod_sign,pos_mod_bound,
609 neg_mod_sign, neg_mod_bound]));
610 by (ALLGOALS(rtac zmod_zdiv_equality));
611 val lemma = result();
613 Goal "(a*b) div c = a*(b div c) + a*(b mod c) div (c::int)";
614 by (zdiv_undefined_case_tac "c = 0" 1);
615 by (blast_tac (claset() addIs [quorem_div_mod RS lemma RS quorem_div]) 1);
616 qed "zdiv_zmult1_eq";
618 Goal "(a*b) mod c = a*(b mod c) mod (c::int)";
619 by (zdiv_undefined_case_tac "c = 0" 1);
620 by (blast_tac (claset() addIs [quorem_div_mod RS lemma RS quorem_mod]) 1);
621 qed "zmod_zmult1_eq";
623 Goal "(a*b) mod (c::int) = ((a mod c) * b) mod c";
625 by (res_inst_tac [("s","b*a mod c")] trans 1);
626 by (rtac zmod_zmult1_eq 2);
627 by (ALLGOALS (simp_tac (simpset() addsimps [zmult_commute])));
628 qed "zmod_zmult1_eq'";
630 Goal "(a*b) mod (c::int) = ((a mod c) * (b mod c)) mod c";
631 by (rtac (zmod_zmult1_eq' RS trans) 1);
632 by (rtac zmod_zmult1_eq 1);
633 qed "zmod_zmult_distrib";
635 Goal "b ~= (0::int) ==> (a*b) div b = a";
636 by (asm_simp_tac (simpset() addsimps [zdiv_zmult1_eq]) 1);
637 qed "zdiv_zmult_self1";
639 Goal "b ~= (0::int) ==> (b*a) div b = a";
640 by (stac zmult_commute 1 THEN etac zdiv_zmult_self1 1);
641 qed "zdiv_zmult_self2";
643 Addsimps [zdiv_zmult_self1, zdiv_zmult_self2];
645 Goal "(a*b) mod b = (0::int)";
646 by (simp_tac (simpset() addsimps [zmod_zmult1_eq]) 1);
647 qed "zmod_zmult_self1";
649 Goal "(b*a) mod b = (0::int)";
650 by (simp_tac (simpset() addsimps [zmult_commute, zmod_zmult1_eq]) 1);
651 qed "zmod_zmult_self2";
653 Addsimps [zmod_zmult_self1, zmod_zmult_self2];
655 Goal "(m mod d = 0) = (EX q::int. m = d*q)";
656 by (cut_inst_tac [("a","m"),("b","d")] zmod_zdiv_equality 1);
659 AddSDs [zmod_eq_0_iff RS iffD1];
662 (** proving (a+b) div c = a div c + b div c + ((a mod c + b mod c) div c) **)
664 Goal "[| quorem((a,c),(aq,ar)); quorem((b,c),(bq,br)); c ~= 0 |] \
665 \ ==> quorem ((a+b, c), (aq + bq + (ar+br) div c, (ar+br) mod c))";
668 simpset() addsimps split_ifs@
669 [quorem_def, linorder_neq_iff,
671 pos_mod_sign,pos_mod_bound,
672 neg_mod_sign, neg_mod_bound]));
673 by (ALLGOALS(rtac zmod_zdiv_equality));
674 val lemma = result();
676 (*NOT suitable for rewriting: the RHS has an instance of the LHS*)
677 Goal "(a+b) div (c::int) = a div c + b div c + ((a mod c + b mod c) div c)";
678 by (zdiv_undefined_case_tac "c = 0" 1);
679 by (blast_tac (claset() addIs [[quorem_div_mod,quorem_div_mod]
680 MRS lemma RS quorem_div]) 1);
683 Goal "(a+b) mod (c::int) = (a mod c + b mod c) mod c";
684 by (zdiv_undefined_case_tac "c = 0" 1);
685 by (blast_tac (claset() addIs [[quorem_div_mod,quorem_div_mod]
686 MRS lemma RS quorem_mod]) 1);
689 Goal "(a mod b) div b = (0::int)";
690 by (zdiv_undefined_case_tac "b = 0" 1);
691 by (auto_tac (claset(),
692 simpset() addsimps [linorder_neq_iff,
693 pos_mod_sign, pos_mod_bound, div_pos_pos_trivial,
694 neg_mod_sign, neg_mod_bound, div_neg_neg_trivial]));
695 qed "mod_div_trivial";
696 Addsimps [mod_div_trivial];
698 Goal "(a mod b) mod b = a mod (b::int)";
699 by (zdiv_undefined_case_tac "b = 0" 1);
700 by (auto_tac (claset(),
701 simpset() addsimps [linorder_neq_iff,
702 pos_mod_sign, pos_mod_bound, mod_pos_pos_trivial,
703 neg_mod_sign, neg_mod_bound, mod_neg_neg_trivial]));
704 qed "mod_mod_trivial";
705 Addsimps [mod_mod_trivial];
707 Goal "(a+b) mod (c::int) = ((a mod c) + b) mod c";
708 by (rtac (trans RS sym) 1);
709 by (rtac zmod_zadd1_eq 1);
711 by (rtac (zmod_zadd1_eq RS sym) 1);
712 qed "zmod_zadd_left_eq";
714 Goal "(a+b) mod (c::int) = (a + (b mod c)) mod c";
715 by (rtac (trans RS sym) 1);
716 by (rtac zmod_zadd1_eq 1);
718 by (rtac (zmod_zadd1_eq RS sym) 1);
719 qed "zmod_zadd_right_eq";
722 Goal "a ~= (0::int) ==> (a+b) div a = b div a + 1";
723 by (asm_simp_tac (simpset() addsimps [zdiv_zadd1_eq]) 1);
724 qed "zdiv_zadd_self1";
726 Goal "a ~= (0::int) ==> (b+a) div a = b div a + 1";
727 by (asm_simp_tac (simpset() addsimps [zdiv_zadd1_eq]) 1);
728 qed "zdiv_zadd_self2";
729 Addsimps [zdiv_zadd_self1, zdiv_zadd_self2];
731 Goal "(a+b) mod a = b mod (a::int)";
732 by (zdiv_undefined_case_tac "a = 0" 1);
733 by (asm_simp_tac (simpset() addsimps [zmod_zadd1_eq]) 1);
734 qed "zmod_zadd_self1";
736 Goal "(b+a) mod a = b mod (a::int)";
737 by (zdiv_undefined_case_tac "a = 0" 1);
738 by (asm_simp_tac (simpset() addsimps [zmod_zadd1_eq]) 1);
739 qed "zmod_zadd_self2";
740 Addsimps [zmod_zadd_self1, zmod_zadd_self2];
743 (*** proving a div (b*c) = (a div b) div c ***)
745 (*The condition c>0 seems necessary. Consider that 7 div ~6 = ~2 but
746 7 div 2 div ~3 = 3 div ~3 = ~1. The subcase (a div b) mod c = 0 seems
747 to cause particular problems.*)
749 (** first, four lemmas to bound the remainder for the cases b<0 and b>0 **)
751 Goal "[| (0::int) < c; b < r; r <= 0 |] ==> b*c < b*(q mod c) + r";
752 by (subgoal_tac "b * (c - q mod c) < r * 1" 1);
753 by (asm_full_simp_tac (simpset() addsimps [zdiff_zmult_distrib2]) 1);
754 by (rtac order_le_less_trans 1);
755 by (etac zmult_zless_mono1 2);
756 by (rtac zmult_zle_mono2_neg 1);
759 simpset() addsimps zcompare_rls@
760 [inst "z" "1" zadd_commute, add1_zle_eq,
762 val lemma1 = result();
764 Goal "[| (0::int) < c; b < r; r <= 0 |] ==> b * (q mod c) + r <= 0";
765 by (subgoal_tac "b * (q mod c) <= 0" 1);
767 by (asm_simp_tac (simpset() addsimps [zmult_le_0_iff, pos_mod_sign]) 1);
768 val lemma2 = result();
770 Goal "[| (0::int) < c; 0 <= r; r < b |] ==> 0 <= b * (q mod c) + r";
771 by (subgoal_tac "0 <= b * (q mod c)" 1);
773 by (asm_simp_tac (simpset() addsimps [int_0_le_mult_iff, pos_mod_sign]) 1);
774 val lemma3 = result();
776 Goal "[| (0::int) < c; 0 <= r; r < b |] ==> b * (q mod c) + r < b * c";
777 by (subgoal_tac "r * 1 < b * (c - q mod c)" 1);
778 by (asm_full_simp_tac (simpset() addsimps [zdiff_zmult_distrib2]) 1);
779 by (rtac order_less_le_trans 1);
780 by (etac zmult_zless_mono1 1);
781 by (rtac zmult_zle_mono2 2);
784 simpset() addsimps zcompare_rls@
785 [inst "z" "1" zadd_commute, add1_zle_eq,
787 val lemma4 = result();
789 Goal "[| quorem ((a,b), (q,r)); b ~= 0; 0 < c |] \
790 \ ==> quorem ((a, b*c), (q div c, b*(q mod c) + r))";
793 simpset() addsimps zmult_ac@
794 [zmod_zdiv_equality, quorem_def, linorder_neq_iff,
796 zadd_zmult_distrib2 RS sym,
797 lemma1, lemma2, lemma3, lemma4]));
798 val lemma = result();
800 Goal "(0::int) < c ==> a div (b*c) = (a div b) div c";
801 by (zdiv_undefined_case_tac "b = 0" 1);
802 by (force_tac (claset(),
803 simpset() addsimps [quorem_div_mod RS lemma RS quorem_div,
805 qed "zdiv_zmult2_eq";
807 Goal "(0::int) < c ==> a mod (b*c) = b*(a div b mod c) + a mod b";
808 by (zdiv_undefined_case_tac "b = 0" 1);
809 by (force_tac (claset(),
810 simpset() addsimps [quorem_div_mod RS lemma RS quorem_mod,
812 qed "zmod_zmult2_eq";
815 (*** Cancellation of common factors in "div" ***)
817 Goal "[| (0::int) < b; c ~= 0 |] ==> (c*a) div (c*b) = a div b";
818 by (stac zdiv_zmult2_eq 1);
820 val lemma1 = result();
822 Goal "[| b < (0::int); c ~= 0 |] ==> (c*a) div (c*b) = a div b";
823 by (subgoal_tac "(c * (-a)) div (c * (-b)) = (-a) div (-b)" 1);
826 val lemma2 = result();
828 Goal "c ~= (0::int) ==> (c*a) div (c*b) = a div b";
829 by (zdiv_undefined_case_tac "b = 0" 1);
832 simpset() addsimps [read_instantiate [("x", "b")] linorder_neq_iff,
834 qed "zdiv_zmult_zmult1";
836 Goal "c ~= (0::int) ==> (a*c) div (b*c) = a div b";
837 by (dtac zdiv_zmult_zmult1 1);
838 by (auto_tac (claset(), simpset() addsimps [zmult_commute]));
839 qed "zdiv_zmult_zmult2";
843 (*** Distribution of factors over "mod" ***)
845 Goal "[| (0::int) < b; c ~= 0 |] ==> (c*a) mod (c*b) = c * (a mod b)";
846 by (stac zmod_zmult2_eq 1);
848 val lemma1 = result();
850 Goal "[| b < (0::int); c ~= 0 |] ==> (c*a) mod (c*b) = c * (a mod b)";
851 by (subgoal_tac "(c * (-a)) mod (c * (-b)) = c * ((-a) mod (-b))" 1);
854 val lemma2 = result();
856 Goal "(c*a) mod (c*b) = (c::int) * (a mod b)";
857 by (zdiv_undefined_case_tac "b = 0" 1);
858 by (zdiv_undefined_case_tac "c = 0" 1);
861 simpset() addsimps [read_instantiate [("x", "b")] linorder_neq_iff,
863 qed "zmod_zmult_zmult1";
865 Goal "(a*c) mod (b*c) = (a mod b) * (c::int)";
866 by (cut_inst_tac [("c","c")] zmod_zmult_zmult1 1);
867 by (auto_tac (claset(), simpset() addsimps [zmult_commute]));
868 qed "zmod_zmult_zmult2";
871 (*** Speeding up the division algorithm with shifting ***)
873 (** computing "div" by shifting **)
875 Goal "(0::int) <= a ==> (1 + 2*b) div (2*a) = b div a";
876 by (zdiv_undefined_case_tac "a = 0" 1);
877 by (subgoal_tac "1 <= a" 1);
879 by (subgoal_tac "1 < a * 2" 1);
881 by (subgoal_tac "2*(1 + b mod a) <= 2*a" 1);
882 by (rtac zmult_zle_mono2 2);
883 by (auto_tac (claset(),
884 simpset() addsimps [inst "z" "1" zadd_commute, zmult_commute,
885 add1_zle_eq, pos_mod_bound]));
886 by (stac zdiv_zadd1_eq 1);
887 by (asm_simp_tac (simpset() addsimps [zdiv_zmult_zmult2, zmod_zmult_zmult2,
888 div_pos_pos_trivial]) 1);
889 by (stac div_pos_pos_trivial 1);
890 by (asm_simp_tac (simpset()
891 addsimps [mod_pos_pos_trivial,
892 pos_mod_sign RS zadd_zle_mono1 RSN (2,order_trans)]) 1);
893 by (auto_tac (claset(),
894 simpset() addsimps [mod_pos_pos_trivial]));
895 by (subgoal_tac "0 <= b mod a" 1);
896 by (asm_simp_tac (simpset() addsimps [pos_mod_sign]) 2);
898 qed "pos_zdiv_mult_2";
901 Goal "a <= (0::int) ==> (1 + 2*b) div (2*a) = (b+1) div a";
902 by (subgoal_tac "(1 + 2*(-b - 1)) div (2 * (-a)) = (-b - 1) div (-a)" 1);
903 by (rtac pos_zdiv_mult_2 2);
904 by (auto_tac (claset(),
905 simpset() addsimps [zmult_zminus_right]));
906 by (subgoal_tac "(-1 - (2 * b)) = - (1 + (2 * b))" 1);
908 by (asm_full_simp_tac (HOL_ss
909 addsimps [zdiv_zminus_zminus, zdiff_def,
910 zminus_zadd_distrib RS sym]) 1);
911 qed "neg_zdiv_mult_2";
914 (*Not clear why this must be proved separately; probably number_of causes
915 simplification problems*)
916 Goal "~ 0 <= x ==> x <= (0::int)";
918 val lemma = result();
920 Goal "number_of (v BIT b) div number_of (w BIT False) = \
921 \ (if ~b | (0::int) <= number_of w \
922 \ then number_of v div (number_of w) \
923 \ else (number_of v + (1::int)) div (number_of w))";
924 by (simp_tac (simpset_of Int.thy addsimps [zadd_assoc, number_of_BIT]) 1);
925 by (subgoal_tac "2 ~= (0::int)" 1);
926 by (Simp_tac 2); (*we do this because the next step can't simplify numerals*)
927 by (asm_simp_tac (simpset()
928 delsimps bin_arith_extra_simps
929 addsimps [zdiv_zmult_zmult1, pos_zdiv_mult_2, lemma,
930 neg_zdiv_mult_2]) 1);
931 qed "zdiv_number_of_BIT";
932 Addsimps [zdiv_number_of_BIT];
935 (** computing "mod" by shifting (proofs resemble those for "div") **)
937 Goal "(0::int) <= a ==> (1 + 2*b) mod (2*a) = 1 + 2 * (b mod a)";
938 by (zdiv_undefined_case_tac "a = 0" 1);
939 by (subgoal_tac "1 <= a" 1);
941 by (subgoal_tac "1 < a * 2" 1);
943 by (subgoal_tac "2*(1 + b mod a) <= 2*a" 1);
944 by (rtac zmult_zle_mono2 2);
945 by (auto_tac (claset(),
946 simpset() addsimps [inst "z" "1" zadd_commute, zmult_commute,
947 add1_zle_eq, pos_mod_bound]));
948 by (stac zmod_zadd1_eq 1);
949 by (asm_simp_tac (simpset() addsimps [zmod_zmult_zmult2,
950 mod_pos_pos_trivial]) 1);
951 by (rtac mod_pos_pos_trivial 1);
952 by (asm_simp_tac (simpset()
953 addsimps [mod_pos_pos_trivial,
954 pos_mod_sign RS zadd_zle_mono1 RSN (2,order_trans)]) 1);
955 by (auto_tac (claset(),
956 simpset() addsimps [mod_pos_pos_trivial]));
957 by (subgoal_tac "0 <= b mod a" 1);
958 by (asm_simp_tac (simpset() addsimps [pos_mod_sign]) 2);
960 qed "pos_zmod_mult_2";
963 Goal "a <= (0::int) ==> (1 + 2*b) mod (2*a) = 2 * ((b+1) mod a) - 1";
965 "(1 + 2*(-b - 1)) mod (2*(-a)) = 1 + 2*((-b - 1) mod (-a))" 1);
966 by (rtac pos_zmod_mult_2 2);
967 by (auto_tac (claset(), simpset() addsimps [zmult_zminus_right]));
968 by (subgoal_tac "(-1 - (2 * b)) = - (1 + (2 * b))" 1);
970 by (asm_full_simp_tac (HOL_ss
971 addsimps [zmod_zminus_zminus, zdiff_def,
972 zminus_zadd_distrib RS sym]) 1);
973 by (dtac (zminus_equation RS iffD1 RS sym) 1);
975 qed "neg_zmod_mult_2";
977 Goal "number_of (v BIT b) mod number_of (w BIT False) = \
979 \ if (0::int) <= number_of w \
980 \ then 2 * (number_of v mod number_of w) + 1 \
981 \ else 2 * ((number_of v + (1::int)) mod number_of w) - 1 \
982 \ else 2 * (number_of v mod number_of w))";
983 by (simp_tac (simpset_of Int.thy addsimps [zadd_assoc, number_of_BIT]) 1);
984 by (asm_simp_tac (simpset()
985 delsimps bin_arith_extra_simps@bin_rel_simps
986 addsimps [zmod_zmult_zmult1,
987 pos_zmod_mult_2, lemma, neg_zmod_mult_2]) 1);
989 qed "zmod_number_of_BIT";
991 Addsimps [zmod_number_of_BIT];
994 (** Quotients of signs **)
996 Goal "[| a < (0::int); 0 < b |] ==> a div b < 0";
997 by (subgoal_tac "a div b <= -1" 1);
999 by (rtac order_trans 1);
1000 by (res_inst_tac [("a'","-1")] zdiv_mono1 1);
1001 by (auto_tac (claset(), simpset() addsimps [zdiv_minus1]));
1002 qed "div_neg_pos_less0";
1004 Goal "[| (0::int) <= a; b < 0 |] ==> a div b <= 0";
1005 by (dtac zdiv_mono1_neg 1);
1007 qed "div_nonneg_neg_le0";
1009 Goal "(0::int) < b ==> (0 <= a div b) = (0 <= a)";
1011 by (dtac zdiv_mono1 2);
1012 by (auto_tac (claset(), simpset() addsimps [linorder_neq_iff]));
1013 by (full_simp_tac (simpset() addsimps [linorder_not_less RS sym]) 1);
1014 by (blast_tac (claset() addIs [div_neg_pos_less0]) 1);
1015 qed "pos_imp_zdiv_nonneg_iff";
1017 Goal "b < (0::int) ==> (0 <= a div b) = (a <= (0::int))";
1018 by (stac (zdiv_zminus_zminus RS sym) 1);
1019 by (stac pos_imp_zdiv_nonneg_iff 1);
1021 qed "neg_imp_zdiv_nonneg_iff";
1023 (*But not (a div b <= 0 iff a<=0); consider a=1, b=2 when a div b = 0.*)
1024 Goal "(0::int) < b ==> (a div b < 0) = (a < 0)";
1025 by (asm_simp_tac (simpset() addsimps [linorder_not_le RS sym,
1026 pos_imp_zdiv_nonneg_iff]) 1);
1027 qed "pos_imp_zdiv_neg_iff";
1029 (*Again the law fails for <=: consider a = -1, b = -2 when a div b = 0*)
1030 Goal "b < (0::int) ==> (a div b < 0) = (0 < a)";
1031 by (asm_simp_tac (simpset() addsimps [linorder_not_le RS sym,
1032 neg_imp_zdiv_nonneg_iff]) 1);
1033 qed "neg_imp_zdiv_neg_iff";