48 subsection {* Euclid's Algorithm and GCD *} |
48 subsection {* Euclid's Algorithm and GCD *} |
49 |
49 |
50 |
50 |
51 lemma zrelprime_zdvd_zmult_aux: |
51 lemma zrelprime_zdvd_zmult_aux: |
52 "zgcd n k = 1 ==> k dvd m * n ==> 0 \<le> m ==> k dvd m" |
52 "zgcd n k = 1 ==> k dvd m * n ==> 0 \<le> m ==> k dvd m" |
53 by (metis abs_of_nonneg zdvd_triv_right zgcd_greatest_iff zgcd_zmult_distrib2_abs zmult_1_right) |
53 by (metis abs_of_nonneg dvd_triv_right zgcd_greatest_iff zgcd_zmult_distrib2_abs zmult_1_right) |
54 |
54 |
55 lemma zrelprime_zdvd_zmult: "zgcd n k = 1 ==> k dvd m * n ==> k dvd m" |
55 lemma zrelprime_zdvd_zmult: "zgcd n k = 1 ==> k dvd m * n ==> k dvd m" |
56 apply (case_tac "0 \<le> m") |
56 apply (case_tac "0 \<le> m") |
57 apply (blast intro: zrelprime_zdvd_zmult_aux) |
57 apply (blast intro: zrelprime_zdvd_zmult_aux) |
58 apply (subgoal_tac "k dvd -m") |
58 apply (subgoal_tac "k dvd -m") |
71 done |
71 done |
72 |
72 |
73 lemma zprime_imp_zrelprime: |
73 lemma zprime_imp_zrelprime: |
74 "zprime p ==> \<not> p dvd n ==> zgcd n p = 1" |
74 "zprime p ==> \<not> p dvd n ==> zgcd n p = 1" |
75 apply (auto simp add: zprime_def) |
75 apply (auto simp add: zprime_def) |
76 apply (metis zgcd_commute zgcd_geq_zero zgcd_zdvd1 zgcd_zdvd2) |
76 apply (metis zgcd_geq_zero zgcd_zdvd1 zgcd_zdvd2) |
77 done |
77 done |
78 |
78 |
79 lemma zless_zprime_imp_zrelprime: |
79 lemma zless_zprime_imp_zrelprime: |
80 "zprime p ==> 0 < n ==> n < p ==> zgcd n p = 1" |
80 "zprime p ==> 0 < n ==> n < p ==> zgcd n p = 1" |
81 apply (erule zprime_imp_zrelprime) |
81 apply (erule zprime_imp_zrelprime) |
91 apply (simp add: mod_add_eq) |
91 apply (simp add: mod_add_eq) |
92 apply (rule zgcd_eq [symmetric]) |
92 apply (rule zgcd_eq [symmetric]) |
93 done |
93 done |
94 |
94 |
95 lemma zgcd_zdvd_zgcd_zmult: "zgcd m n dvd zgcd (k * m) n" |
95 lemma zgcd_zdvd_zgcd_zmult: "zgcd m n dvd zgcd (k * m) n" |
96 apply (simp add: zgcd_greatest_iff) |
96 by (simp add: zgcd_greatest_iff) |
97 apply (blast intro: zdvd_trans dvd_triv_right) |
|
98 done |
|
99 |
97 |
100 lemma zgcd_zmult_zdvd_zgcd: |
98 lemma zgcd_zmult_zdvd_zgcd: |
101 "zgcd k n = 1 ==> zgcd (k * m) n dvd zgcd m n" |
99 "zgcd k n = 1 ==> zgcd (k * m) n dvd zgcd m n" |
102 apply (simp add: zgcd_greatest_iff) |
100 apply (simp add: zgcd_greatest_iff) |
103 apply (rule_tac n = k in zrelprime_zdvd_zmult) |
101 apply (rule_tac n = k in zrelprime_zdvd_zmult) |
125 |
123 |
126 lemma zcong_refl [simp]: "[k = k] (mod m)" |
124 lemma zcong_refl [simp]: "[k = k] (mod m)" |
127 by (unfold zcong_def, auto) |
125 by (unfold zcong_def, auto) |
128 |
126 |
129 lemma zcong_sym: "[a = b] (mod m) = [b = a] (mod m)" |
127 lemma zcong_sym: "[a = b] (mod m) = [b = a] (mod m)" |
130 unfolding zcong_def minus_diff_eq [of a, symmetric] zdvd_zminus_iff .. |
128 unfolding zcong_def minus_diff_eq [of a, symmetric] dvd_minus_iff .. |
131 |
129 |
132 lemma zcong_zadd: |
130 lemma zcong_zadd: |
133 "[a = b] (mod m) ==> [c = d] (mod m) ==> [a + c = b + d] (mod m)" |
131 "[a = b] (mod m) ==> [c = d] (mod m) ==> [a + c = b + d] (mod m)" |
134 apply (unfold zcong_def) |
132 apply (unfold zcong_def) |
135 apply (rule_tac s = "(a - b) + (c - d)" in subst) |
133 apply (rule_tac s = "(a - b) + (c - d)" in subst) |
136 apply (rule_tac [2] zdvd_zadd, auto) |
134 apply (rule_tac [2] dvd_add, auto) |
137 done |
135 done |
138 |
136 |
139 lemma zcong_zdiff: |
137 lemma zcong_zdiff: |
140 "[a = b] (mod m) ==> [c = d] (mod m) ==> [a - c = b - d] (mod m)" |
138 "[a = b] (mod m) ==> [c = d] (mod m) ==> [a - c = b - d] (mod m)" |
141 apply (unfold zcong_def) |
139 apply (unfold zcong_def) |
142 apply (rule_tac s = "(a - b) - (c - d)" in subst) |
140 apply (rule_tac s = "(a - b) - (c - d)" in subst) |
143 apply (rule_tac [2] zdvd_zdiff, auto) |
141 apply (rule_tac [2] dvd_diff, auto) |
144 done |
142 done |
145 |
143 |
146 lemma zcong_trans: |
144 lemma zcong_trans: |
147 "[a = b] (mod m) ==> [b = c] (mod m) ==> [a = c] (mod m)" |
145 "[a = b] (mod m) ==> [b = c] (mod m) ==> [a = c] (mod m)" |
148 unfolding zcong_def by (auto elim!: dvdE simp add: algebra_simps) |
146 unfolding zcong_def by (auto elim!: dvdE simp add: algebra_simps) |
149 |
147 |
150 lemma zcong_zmult: |
148 lemma zcong_zmult: |
151 "[a = b] (mod m) ==> [c = d] (mod m) ==> [a * c = b * d] (mod m)" |
149 "[a = b] (mod m) ==> [c = d] (mod m) ==> [a * c = b * d] (mod m)" |
152 apply (rule_tac b = "b * c" in zcong_trans) |
150 apply (rule_tac b = "b * c" in zcong_trans) |
153 apply (unfold zcong_def) |
151 apply (unfold zcong_def) |
154 apply (metis zdiff_zmult_distrib2 zdvd_zmult zmult_commute) |
152 apply (metis zdiff_zmult_distrib2 dvd_mult zmult_commute) |
155 apply (metis zdiff_zmult_distrib2 zdvd_zmult) |
153 apply (metis zdiff_zmult_distrib2 dvd_mult) |
156 done |
154 done |
157 |
155 |
158 lemma zcong_scalar: "[a = b] (mod m) ==> [a * k = b * k] (mod m)" |
156 lemma zcong_scalar: "[a = b] (mod m) ==> [a * k = b * k] (mod m)" |
159 by (rule zcong_zmult, simp_all) |
157 by (rule zcong_zmult, simp_all) |
160 |
158 |
161 lemma zcong_scalar2: "[a = b] (mod m) ==> [k * a = k * b] (mod m)" |
159 lemma zcong_scalar2: "[a = b] (mod m) ==> [k * a = k * b] (mod m)" |
162 by (rule zcong_zmult, simp_all) |
160 by (rule zcong_zmult, simp_all) |
163 |
161 |
164 lemma zcong_zmult_self: "[a * m = b * m] (mod m)" |
162 lemma zcong_zmult_self: "[a * m = b * m] (mod m)" |
165 apply (unfold zcong_def) |
163 apply (unfold zcong_def) |
166 apply (rule zdvd_zdiff, simp_all) |
164 apply (rule dvd_diff, simp_all) |
167 done |
165 done |
168 |
166 |
169 lemma zcong_square: |
167 lemma zcong_square: |
170 "[| zprime p; 0 < a; [a * a = 1] (mod p)|] |
168 "[| zprime p; 0 < a; [a * a = 1] (mod p)|] |
171 ==> [a = 1] (mod p) \<or> [a = p - 1] (mod p)" |
169 ==> [a = 1] (mod p) \<or> [a = p - 1] (mod p)" |
189 apply (unfold zcong_def) |
187 apply (unfold zcong_def) |
190 apply (rule_tac [!] zrelprime_zdvd_zmult) |
188 apply (rule_tac [!] zrelprime_zdvd_zmult) |
191 apply (simp_all add: zdiff_zmult_distrib) |
189 apply (simp_all add: zdiff_zmult_distrib) |
192 apply (subgoal_tac "m dvd (-(a * k - b * k))") |
190 apply (subgoal_tac "m dvd (-(a * k - b * k))") |
193 apply simp |
191 apply simp |
194 apply (subst zdvd_zminus_iff, assumption) |
192 apply (subst dvd_minus_iff, assumption) |
195 done |
193 done |
196 |
194 |
197 lemma zcong_cancel2: |
195 lemma zcong_cancel2: |
198 "0 \<le> m ==> |
196 "0 \<le> m ==> |
199 zgcd k m = 1 ==> [k * a = k * b] (mod m) = [a = b] (mod m)" |
197 zgcd k m = 1 ==> [k * a = k * b] (mod m) = [a = b] (mod m)" |
204 ==> [a = b] (mod m * n)" |
202 ==> [a = b] (mod m * n)" |
205 apply (auto simp add: zcong_def dvd_def) |
203 apply (auto simp add: zcong_def dvd_def) |
206 apply (subgoal_tac "m dvd n * ka") |
204 apply (subgoal_tac "m dvd n * ka") |
207 apply (subgoal_tac "m dvd ka") |
205 apply (subgoal_tac "m dvd ka") |
208 apply (case_tac [2] "0 \<le> ka") |
206 apply (case_tac [2] "0 \<le> ka") |
209 apply (metis zdvd_mult_div_cancel zdvd_refl zdvd_zminus2_iff zdvd_zmultD2 zgcd_zminus zmult_commute zmult_zminus zrelprime_zdvd_zmult) |
207 apply (metis zdvd_mult_div_cancel dvd_refl dvd_mult_left zmult_commute zrelprime_zdvd_zmult) |
210 apply (metis IntDiv.zdvd_abs1 abs_of_nonneg zadd_0 zgcd_0_left zgcd_commute zgcd_zadd_zmult zgcd_zdvd_zgcd_zmult zgcd_zmult_distrib2_abs zmult_1_right zmult_commute) |
208 apply (metis abs_dvd_iff abs_of_nonneg zadd_0 zgcd_0_left zgcd_commute zgcd_zadd_zmult zgcd_zdvd_zgcd_zmult zgcd_zmult_distrib2_abs zmult_1_right zmult_commute) |
211 apply (metis abs_eq_0 int_0_neq_1 mult_le_0_iff zdvd_mono zdvd_mult_cancel zdvd_mult_cancel1 zdvd_refl zdvd_triv_left zdvd_zmult2 zero_le_mult_iff zgcd_greatest_iff zle_anti_sym zle_linear zle_refl zmult_commute zrelprime_zdvd_zmult) |
209 apply (metis mult_le_0_iff zdvd_mono zdvd_mult_cancel dvd_triv_left zero_le_mult_iff zle_anti_sym zle_linear zle_refl zmult_commute zrelprime_zdvd_zmult) |
212 apply (metis zdvd_triv_left) |
210 apply (metis dvd_triv_left) |
213 done |
211 done |
214 |
212 |
215 lemma zcong_zless_imp_eq: |
213 lemma zcong_zless_imp_eq: |
216 "0 \<le> a ==> |
214 "0 \<le> a ==> |
217 a < m ==> 0 \<le> b ==> b < m ==> [a = b] (mod m) ==> a = b" |
215 a < m ==> 0 \<le> b ==> b < m ==> [a = b] (mod m) ==> a = b" |
218 apply (unfold zcong_def dvd_def, auto) |
216 apply (unfold zcong_def dvd_def, auto) |
219 apply (drule_tac f = "\<lambda>z. z mod m" in arg_cong) |
217 apply (drule_tac f = "\<lambda>z. z mod m" in arg_cong) |
220 apply (metis diff_add_cancel mod_pos_pos_trivial zadd_0 zadd_commute zmod_eq_0_iff zmod_zadd_right_eq) |
218 apply (metis diff_add_cancel mod_pos_pos_trivial zadd_0 zadd_commute zmod_eq_0_iff mod_add_right_eq) |
221 done |
219 done |
222 |
220 |
223 lemma zcong_square_zless: |
221 lemma zcong_square_zless: |
224 "zprime p ==> 0 < a ==> a < p ==> |
222 "zprime p ==> 0 < a ==> a < p ==> |
225 [a * a = 1] (mod p) ==> a = 1 \<or> a = p - 1" |
223 [a * a = 1] (mod p) ==> a = 1 \<or> a = p - 1" |