5 *) |
5 *) |
6 |
6 |
7 header {* The division operators div, mod and the divides relation "dvd" *} |
7 header {* The division operators div, mod and the divides relation "dvd" *} |
8 |
8 |
9 theory Divides |
9 theory Divides |
10 imports Datatype |
10 imports Datatype Power |
11 begin |
11 begin |
12 |
12 |
13 (*We use the same class for div and mod; |
13 (*We use the same class for div and mod; |
14 moreover, dvd is defined whenever multiplication is*) |
14 moreover, dvd is defined whenever multiplication is*) |
15 axclass |
15 class div = |
16 div < type |
16 fixes div :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" |
17 |
17 fixes mod :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" |
18 instance nat :: div .. |
18 begin |
|
19 |
|
20 notation |
|
21 div (infixl "\<^loc>div" 70) |
|
22 |
|
23 notation |
|
24 mod (infixl "\<^loc>mod" 70) |
|
25 |
|
26 end |
|
27 |
|
28 notation |
|
29 div (infixl "div" 70) |
|
30 |
|
31 notation |
|
32 mod (infixl "mod" 70) |
|
33 |
|
34 instance nat :: "Divides.div" |
|
35 mod_def: "m mod n == wfrec (trancl pred_nat) |
|
36 (%f j. if j<n | n=0 then j else f (j-n)) m" |
|
37 div_def: "m div n == wfrec (trancl pred_nat) |
|
38 (%f j. if j<n | n=0 then 0 else Suc (f (j-n))) m" .. |
|
39 |
|
40 definition |
|
41 (*The definition of dvd is polymorphic!*) |
|
42 dvd :: "'a::times \<Rightarrow> 'a \<Rightarrow> bool" (infixl "dvd" 50) where |
|
43 dvd_def: "m dvd n \<longleftrightarrow> (\<exists>k. n = m*k)" |
19 |
44 |
20 consts |
45 consts |
21 div :: "'a::div \<Rightarrow> 'a \<Rightarrow> 'a" (infixl 70) |
46 quorem :: "(nat*nat) * (nat*nat) => bool" |
22 mod :: "'a::div \<Rightarrow> 'a \<Rightarrow> 'a" (infixl 70) |
|
23 dvd :: "'a::times \<Rightarrow> 'a \<Rightarrow> bool" (infixl 50) |
|
24 |
|
25 |
47 |
26 defs |
48 defs |
27 |
49 (*This definition helps prove the harder properties of div and mod. |
28 mod_def: "m mod n == wfrec (trancl pred_nat) |
50 It is copied from IntDiv.thy; should it be overloaded?*) |
29 (%f j. if j<n | n=0 then j else f (j-n)) m" |
51 quorem_def: "quorem \<equiv> (%((a,b), (q,r)). |
30 |
52 a = b*q + r & |
31 div_def: "m div n == wfrec (trancl pred_nat) |
53 (if 0<b then 0\<le>r & r<b else b<r & r \<le>0))" |
32 (%f j. if j<n | n=0 then 0 else Suc (f (j-n))) m" |
|
33 |
|
34 (*The definition of dvd is polymorphic!*) |
|
35 dvd_def: "m dvd n == \<exists>k. n = m*k" |
|
36 |
|
37 (*This definition helps prove the harder properties of div and mod. |
|
38 It is copied from IntDiv.thy; should it be overloaded?*) |
|
39 constdefs |
|
40 quorem :: "(nat*nat) * (nat*nat) => bool" |
|
41 "quorem == %((a,b), (q,r)). |
|
42 a = b*q + r & |
|
43 (if 0<b then 0\<le>r & r<b else b<r & r \<le>0)" |
|
44 |
54 |
45 |
55 |
46 |
56 |
47 subsection{*Initial Lemmas*} |
57 subsection{*Initial Lemmas*} |
48 |
58 |
185 |
195 |
186 |
196 |
187 structure CancelDivModData = |
197 structure CancelDivModData = |
188 struct |
198 struct |
189 |
199 |
190 val div_name = "Divides.op div"; |
200 val div_name = "Divides.div"; |
191 val mod_name = "Divides.op mod"; |
201 val mod_name = "Divides.mod"; |
192 val mk_binop = HOLogic.mk_binop; |
202 val mk_binop = HOLogic.mk_binop; |
193 val mk_sum = NatArithUtils.mk_sum; |
203 val mk_sum = NatArithUtils.mk_sum; |
194 val dest_sum = NatArithUtils.dest_sum; |
204 val dest_sum = NatArithUtils.dest_sum; |
195 |
205 |
196 (*logic*) |
206 (*logic*) |
264 prefer 2 apply (blast intro: unique_quotient) |
274 prefer 2 apply (blast intro: unique_quotient) |
265 apply (simp add: quorem_def) |
275 apply (simp add: quorem_def) |
266 done |
276 done |
267 |
277 |
268 lemma quorem_div_mod: "0 < b ==> quorem ((a, b), (a div b, a mod b))" |
278 lemma quorem_div_mod: "0 < b ==> quorem ((a, b), (a div b, a mod b))" |
269 by (auto simp add: quorem_def) |
279 unfolding quorem_def by simp |
270 |
280 |
271 lemma quorem_div: "[| quorem((a,b),(q,r)); 0 < b |] ==> a div b = q" |
281 lemma quorem_div: "[| quorem((a,b),(q,r)); 0 < b |] ==> a div b = q" |
272 by (simp add: quorem_div_mod [THEN unique_quotient]) |
282 by (simp add: quorem_div_mod [THEN unique_quotient]) |
273 |
283 |
274 lemma quorem_mod: "[| quorem((a,b),(q,r)); 0 < b |] ==> a mod b = r" |
284 lemma quorem_mod: "[| quorem((a,b),(q,r)); 0 < b |] ==> a mod b = r" |
647 |
657 |
648 lemma dvd_mult_div_cancel: "n dvd m ==> n * (m div n) = (m::nat)" |
658 lemma dvd_mult_div_cancel: "n dvd m ==> n * (m div n) = (m::nat)" |
649 apply (subgoal_tac "m mod n = 0") |
659 apply (subgoal_tac "m mod n = 0") |
650 apply (simp add: mult_div_cancel) |
660 apply (simp add: mult_div_cancel) |
651 apply (simp only: dvd_eq_mod_eq_0) |
661 apply (simp only: dvd_eq_mod_eq_0) |
|
662 done |
|
663 |
|
664 lemma le_imp_power_dvd: "!!i::nat. m \<le> n ==> i^m dvd i^n" |
|
665 apply (unfold dvd_def) |
|
666 apply (erule linorder_not_less [THEN iffD2, THEN add_diff_inverse, THEN subst]) |
|
667 apply (simp add: power_add) |
|
668 done |
|
669 |
|
670 lemma nat_zero_less_power_iff [simp]: "(0 < x^n) = (x \<noteq> (0::nat) | n=0)" |
|
671 by (induct "n", auto) |
|
672 |
|
673 lemma power_le_dvd [rule_format]: "k^j dvd n --> i\<le>j --> k^i dvd (n::nat)" |
|
674 apply (induct "j") |
|
675 apply (simp_all add: le_Suc_eq) |
|
676 apply (blast dest!: dvd_mult_right) |
|
677 done |
|
678 |
|
679 lemma power_dvd_imp_le: "[|i^m dvd i^n; (1::nat) < i|] ==> m \<le> n" |
|
680 apply (rule power_le_imp_le_exp, assumption) |
|
681 apply (erule dvd_imp_le, simp) |
652 done |
682 done |
653 |
683 |
654 lemma mod_eq_0_iff: "(m mod d = 0) = (\<exists>q::nat. m = d*q)" |
684 lemma mod_eq_0_iff: "(m mod d = 0) = (\<exists>q::nat. m = d*q)" |
655 by (auto simp add: dvd_eq_mod_eq_0 [symmetric] dvd_def) |
685 by (auto simp add: dvd_eq_mod_eq_0 [symmetric] dvd_def) |
656 |
686 |