1 (* Title: HOL/Old_Number_Theory/IntPrimes.thy |
1 (* Title: HOL/Old_Number_Theory/IntPrimes.thy |
2 Author: Thomas M. Rasmussen |
2 Author: Thomas M. Rasmussen |
3 Copyright 2000 University of Cambridge |
3 Copyright 2000 University of Cambridge |
4 *) |
4 *) |
5 |
5 |
6 section {* Divisibility and prime numbers (on integers) *} |
6 section \<open>Divisibility and prime numbers (on integers)\<close> |
7 |
7 |
8 theory IntPrimes |
8 theory IntPrimes |
9 imports Primes |
9 imports Primes |
10 begin |
10 begin |
11 |
11 |
12 text {* |
12 text \<open> |
13 The @{text dvd} relation, GCD, Euclid's extended algorithm, primes, |
13 The @{text dvd} relation, GCD, Euclid's extended algorithm, primes, |
14 congruences (all on the Integers). Comparable to theory @{text |
14 congruences (all on the Integers). Comparable to theory @{text |
15 Primes}, but @{text dvd} is included here as it is not present in |
15 Primes}, but @{text dvd} is included here as it is not present in |
16 main HOL. Also includes extended GCD and congruences not present in |
16 main HOL. Also includes extended GCD and congruences not present in |
17 @{text Primes}. |
17 @{text Primes}. |
18 *} |
18 \<close> |
19 |
19 |
20 |
20 |
21 subsection {* Definitions *} |
21 subsection \<open>Definitions\<close> |
22 |
22 |
23 fun xzgcda :: "int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int => (int * int * int)" |
23 fun xzgcda :: "int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int => (int * int * int)" |
24 where |
24 where |
25 "xzgcda m n r' r s' s t' t = |
25 "xzgcda m n r' r s' s t' t = |
26 (if r \<le> 0 then (r', s', t') |
26 (if r \<le> 0 then (r', s', t') |
36 |
36 |
37 definition zcong :: "int => int => int => bool" ("(1[_ = _] '(mod _'))") |
37 definition zcong :: "int => int => int => bool" ("(1[_ = _] '(mod _'))") |
38 where "[a = b] (mod m) = (m dvd (a - b))" |
38 where "[a = b] (mod m) = (m dvd (a - b))" |
39 |
39 |
40 |
40 |
41 subsection {* Euclid's Algorithm and GCD *} |
41 subsection \<open>Euclid's Algorithm and GCD\<close> |
42 |
42 |
43 |
43 |
44 lemma zrelprime_zdvd_zmult_aux: |
44 lemma zrelprime_zdvd_zmult_aux: |
45 "zgcd n k = 1 ==> k dvd m * n ==> 0 \<le> m ==> k dvd m" |
45 "zgcd n k = 1 ==> k dvd m * n ==> 0 \<le> m ==> k dvd m" |
46 by (metis abs_of_nonneg dvd_triv_right zgcd_greatest_iff zgcd_zmult_distrib2_abs mult_1_right) |
46 by (metis abs_of_nonneg dvd_triv_right zgcd_greatest_iff zgcd_zmult_distrib2_abs mult_1_right) |
53 done |
53 done |
54 |
54 |
55 lemma zgcd_geq_zero: "0 <= zgcd x y" |
55 lemma zgcd_geq_zero: "0 <= zgcd x y" |
56 by (auto simp add: zgcd_def) |
56 by (auto simp add: zgcd_def) |
57 |
57 |
58 text{*This is merely a sanity check on zprime, since the previous version |
58 text\<open>This is merely a sanity check on zprime, since the previous version |
59 denoted the empty set.*} |
59 denoted the empty set.\<close> |
60 lemma "zprime 2" |
60 lemma "zprime 2" |
61 apply (auto simp add: zprime_def) |
61 apply (auto simp add: zprime_def) |
62 apply (frule zdvd_imp_le, simp) |
62 apply (frule zdvd_imp_le, simp) |
63 apply (auto simp add: order_le_less dvd_def) |
63 apply (auto simp add: order_le_less dvd_def) |
64 done |
64 done |
107 lemma zdvd_iff_zgcd: "0 < m ==> m dvd n \<longleftrightarrow> zgcd n m = m" |
107 lemma zdvd_iff_zgcd: "0 < m ==> m dvd n \<longleftrightarrow> zgcd n m = m" |
108 by (metis abs_of_pos dvd_mult_div_cancel zgcd_0 zgcd_commute zgcd_geq_zero zgcd_zdvd2 zgcd_zmult_eq_self) |
108 by (metis abs_of_pos dvd_mult_div_cancel zgcd_0 zgcd_commute zgcd_geq_zero zgcd_zdvd2 zgcd_zmult_eq_self) |
109 |
109 |
110 |
110 |
111 |
111 |
112 subsection {* Congruences *} |
112 subsection \<open>Congruences\<close> |
113 |
113 |
114 lemma zcong_1 [simp]: "[a = b] (mod 1)" |
114 lemma zcong_1 [simp]: "[a = b] (mod 1)" |
115 by (unfold zcong_def, auto) |
115 by (unfold zcong_def, auto) |
116 |
116 |
117 lemma zcong_refl [simp]: "[k = k] (mod m)" |
117 lemma zcong_refl [simp]: "[k = k] (mod m)" |
279 lemma "[a = b] (mod m) = (a mod m = b mod m)" |
279 lemma "[a = b] (mod m) = (a mod m = b mod m)" |
280 apply (cases "m = 0", simp) |
280 apply (cases "m = 0", simp) |
281 apply (simp add: linorder_neq_iff) |
281 apply (simp add: linorder_neq_iff) |
282 apply (erule disjE) |
282 apply (erule disjE) |
283 prefer 2 apply (simp add: zcong_zmod_eq) |
283 prefer 2 apply (simp add: zcong_zmod_eq) |
284 txt{*Remainding case: @{term "m<0"}*} |
284 txt\<open>Remainding case: @{term "m<0"}\<close> |
285 apply (rule_tac t = m in minus_minus [THEN subst]) |
285 apply (rule_tac t = m in minus_minus [THEN subst]) |
286 apply (subst zcong_zminus) |
286 apply (subst zcong_zminus) |
287 apply (subst zcong_zmod_eq, arith) |
287 apply (subst zcong_zmod_eq, arith) |
288 apply (frule neg_mod_bound [of _ a], frule neg_mod_bound [of _ b]) |
288 apply (frule neg_mod_bound [of _ a], frule neg_mod_bound [of _ b]) |
289 apply (simp add: zmod_zminus2_eq_if del: neg_mod_bound) |
289 apply (simp add: zmod_zminus2_eq_if del: neg_mod_bound) |
290 done |
290 done |
291 |
291 |
292 subsection {* Modulo *} |
292 subsection \<open>Modulo\<close> |
293 |
293 |
294 lemma zmod_zdvd_zmod: |
294 lemma zmod_zdvd_zmod: |
295 "0 < (m::int) ==> m dvd b ==> (a mod b mod m) = (a mod m)" |
295 "0 < (m::int) ==> m dvd b ==> (a mod b mod m) = (a mod m)" |
296 by (rule mod_mod_cancel) |
296 by (rule mod_mod_cancel) |
297 |
297 |
298 |
298 |
299 subsection {* Extended GCD *} |
299 subsection \<open>Extended GCD\<close> |
300 |
300 |
301 declare xzgcda.simps [simp del] |
301 declare xzgcda.simps [simp del] |
302 |
302 |
303 lemma xzgcd_correct_aux1: |
303 lemma xzgcd_correct_aux1: |
304 "zgcd r' r = k --> 0 < r --> |
304 "zgcd r' r = k --> 0 < r --> |
334 apply (rule_tac [2] xzgcd_correct_aux2 [THEN mp, THEN mp]) |
334 apply (rule_tac [2] xzgcd_correct_aux2 [THEN mp, THEN mp]) |
335 apply (rule xzgcd_correct_aux1 [THEN mp, THEN mp], auto) |
335 apply (rule xzgcd_correct_aux1 [THEN mp, THEN mp], auto) |
336 done |
336 done |
337 |
337 |
338 |
338 |
339 text {* \medskip @{term xzgcd} linear *} |
339 text \<open>\medskip @{term xzgcd} linear\<close> |
340 |
340 |
341 lemma xzgcda_linear_aux1: |
341 lemma xzgcda_linear_aux1: |
342 "(a - r * b) * m + (c - r * d) * (n::int) = |
342 "(a - r * b) * m + (c - r * d) * (n::int) = |
343 (a * m + c * n) - r * (b * m + d * n)" |
343 (a * m + c * n) - r * (b * m + d * n)" |
344 by (simp add: left_diff_distrib distrib_left mult.assoc) |
344 by (simp add: left_diff_distrib distrib_left mult.assoc) |
397 lemma zcong_lineq_unique: |
397 lemma zcong_lineq_unique: |
398 "0 < n ==> |
398 "0 < n ==> |
399 zgcd a n = 1 ==> \<exists>!x. 0 \<le> x \<and> x < n \<and> [a * x = b] (mod n)" |
399 zgcd a n = 1 ==> \<exists>!x. 0 \<le> x \<and> x < n \<and> [a * x = b] (mod n)" |
400 apply auto |
400 apply auto |
401 apply (rule_tac [2] zcong_zless_imp_eq) |
401 apply (rule_tac [2] zcong_zless_imp_eq) |
402 apply (tactic {* stac @{context} (@{thm zcong_cancel2} RS sym) 6 *}) |
402 apply (tactic \<open>stac @{context} (@{thm zcong_cancel2} RS sym) 6\<close>) |
403 apply (rule_tac [8] zcong_trans) |
403 apply (rule_tac [8] zcong_trans) |
404 apply (simp_all (no_asm_simp)) |
404 apply (simp_all (no_asm_simp)) |
405 prefer 2 |
405 prefer 2 |
406 apply (simp add: zcong_sym) |
406 apply (simp add: zcong_sym) |
407 apply (cut_tac a = a and n = n in zcong_lineq_ex, auto) |
407 apply (cut_tac a = a and n = n in zcong_lineq_ex, auto) |