35 qed; |
35 qed; |
36 |
36 |
37 lemma aux4: " -(m * n) = (-m) * (n::int)"; |
37 lemma aux4: " -(m * n) = (-m) * (n::int)"; |
38 by auto |
38 by auto |
39 |
39 |
40 lemma zprime_zdvd_zmult_better: "[| p \<in> zprime; p dvd (m * n) |] ==> |
40 lemma zprime_zdvd_zmult_better: "[| zprime p; p dvd (m * n) |] ==> |
41 (p dvd m) | (p dvd n)"; |
41 (p dvd m) | (p dvd n)"; |
42 apply (case_tac "0 \<le> m") |
42 apply (case_tac "0 \<le> m") |
43 apply (simp add: zprime_zdvd_zmult) |
43 apply (simp add: zprime_zdvd_zmult) |
44 by (insert zprime_zdvd_zmult [of "-m" p n], auto) |
44 by (insert zprime_zdvd_zmult [of "-m" p n], auto) |
45 |
45 |
46 lemma zpower_zdvd_prop2 [rule_format]: "p \<in> zprime --> p dvd ((y::int) ^ n) |
46 lemma zpower_zdvd_prop2 [rule_format]: "zprime p --> p dvd ((y::int) ^ n) |
47 --> 0 < n --> p dvd y"; |
47 --> 0 < n --> p dvd y"; |
48 apply (induct_tac n, auto) |
48 apply (induct_tac n, auto) |
49 apply (frule zprime_zdvd_zmult_better, auto) |
49 apply (frule zprime_zdvd_zmult_better, auto) |
50 done |
50 done |
51 |
51 |
158 qed; |
158 qed; |
159 |
159 |
160 lemma zcong_zero_equiv_div: "[a = 0] (mod m) = (m dvd a)"; |
160 lemma zcong_zero_equiv_div: "[a = 0] (mod m) = (m dvd a)"; |
161 by (auto simp add: zcong_def) |
161 by (auto simp add: zcong_def) |
162 |
162 |
163 lemma zcong_zprime_prod_zero: "[| p \<in> zprime; 0 < a |] ==> |
163 lemma zcong_zprime_prod_zero: "[| zprime p; 0 < a |] ==> |
164 [a * b = 0] (mod p) ==> [a = 0] (mod p) | [b = 0] (mod p)"; |
164 [a * b = 0] (mod p) ==> [a = 0] (mod p) | [b = 0] (mod p)"; |
165 by (auto simp add: zcong_zero_equiv_div zprime_zdvd_zmult) |
165 by (auto simp add: zcong_zero_equiv_div zprime_zdvd_zmult) |
166 |
166 |
167 lemma zcong_zprime_prod_zero_contra: "[| p \<in> zprime; 0 < a |] ==> |
167 lemma zcong_zprime_prod_zero_contra: "[| zprime p; 0 < a |] ==> |
168 ~[a = 0](mod p) & ~[b = 0](mod p) ==> ~[a * b = 0] (mod p)"; |
168 ~[a = 0](mod p) & ~[b = 0](mod p) ==> ~[a * b = 0] (mod p)"; |
169 apply auto |
169 apply auto |
170 apply (frule_tac a = a and b = b and p = p in zcong_zprime_prod_zero) |
170 apply (frule_tac a = a and b = b and p = p in zcong_zprime_prod_zero) |
171 by auto |
171 by auto |
172 |
172 |
189 |
189 |
190 lemma MultInv_prop1: "[| 2 < p; [x = y] (mod p) |] ==> |
190 lemma MultInv_prop1: "[| 2 < p; [x = y] (mod p) |] ==> |
191 [(MultInv p x) = (MultInv p y)] (mod p)"; |
191 [(MultInv p x) = (MultInv p y)] (mod p)"; |
192 by (auto simp add: MultInv_def zcong_zpower) |
192 by (auto simp add: MultInv_def zcong_zpower) |
193 |
193 |
194 lemma MultInv_prop2: "[| 2 < p; p \<in> zprime; ~([x = 0](mod p)) |] ==> |
194 lemma MultInv_prop2: "[| 2 < p; zprime p; ~([x = 0](mod p)) |] ==> |
195 [(x * (MultInv p x)) = 1] (mod p)"; |
195 [(x * (MultInv p x)) = 1] (mod p)"; |
196 proof (simp add: MultInv_def zcong_eq_zdvd_prop); |
196 proof (simp add: MultInv_def zcong_eq_zdvd_prop); |
197 assume "2 < p" and "p \<in> zprime" and "~ p dvd x"; |
197 assume "2 < p" and "zprime p" and "~ p dvd x"; |
198 have "x * x ^ nat (p - 2) = x ^ (nat (p - 2) + 1)"; |
198 have "x * x ^ nat (p - 2) = x ^ (nat (p - 2) + 1)"; |
199 by auto |
199 by auto |
200 also from prems have "nat (p - 2) + 1 = nat (p - 2 + 1)"; |
200 also from prems have "nat (p - 2) + 1 = nat (p - 2 + 1)"; |
201 by (simp only: nat_add_distrib, auto) |
201 by (simp only: nat_add_distrib, auto) |
202 also have "p - 2 + 1 = p - 1" by arith |
202 also have "p - 2 + 1 = p - 1" by arith |
205 also from prems have "[x ^ nat (p - 1) = 1] (mod p)"; |
205 also from prems have "[x ^ nat (p - 1) = 1] (mod p)"; |
206 by (auto simp add: Little_Fermat) |
206 by (auto simp add: Little_Fermat) |
207 finally (zcong_trans) show "[x * x ^ nat (p - 2) = 1] (mod p)";.; |
207 finally (zcong_trans) show "[x * x ^ nat (p - 2) = 1] (mod p)";.; |
208 qed; |
208 qed; |
209 |
209 |
210 lemma MultInv_prop2a: "[| 2 < p; p \<in> zprime; ~([x = 0](mod p)) |] ==> |
210 lemma MultInv_prop2a: "[| 2 < p; zprime p; ~([x = 0](mod p)) |] ==> |
211 [(MultInv p x) * x = 1] (mod p)"; |
211 [(MultInv p x) * x = 1] (mod p)"; |
212 by (auto simp add: MultInv_prop2 zmult_ac) |
212 by (auto simp add: MultInv_prop2 zmult_ac) |
213 |
213 |
214 lemma aux_1: "2 < p ==> ((nat p) - 2) = (nat (p - 2))"; |
214 lemma aux_1: "2 < p ==> ((nat p) - 2) = (nat (p - 2))"; |
215 by (simp add: nat_diff_distrib) |
215 by (simp add: nat_diff_distrib) |
216 |
216 |
217 lemma aux_2: "2 < p ==> 0 < nat (p - 2)"; |
217 lemma aux_2: "2 < p ==> 0 < nat (p - 2)"; |
218 by auto |
218 by auto |
219 |
219 |
220 lemma MultInv_prop3: "[| 2 < p; p \<in> zprime; ~([x = 0](mod p)) |] ==> |
220 lemma MultInv_prop3: "[| 2 < p; zprime p; ~([x = 0](mod p)) |] ==> |
221 ~([MultInv p x = 0](mod p))"; |
221 ~([MultInv p x = 0](mod p))"; |
222 apply (auto simp add: MultInv_def zcong_eq_zdvd_prop aux_1) |
222 apply (auto simp add: MultInv_def zcong_eq_zdvd_prop aux_1) |
223 apply (drule aux_2) |
223 apply (drule aux_2) |
224 apply (drule zpower_zdvd_prop2, auto) |
224 apply (drule zpower_zdvd_prop2, auto) |
225 done |
225 done |
226 |
226 |
227 lemma aux__1: "[| 2 < p; p \<in> zprime; ~([x = 0](mod p))|] ==> |
227 lemma aux__1: "[| 2 < p; zprime p; ~([x = 0](mod p))|] ==> |
228 [(MultInv p (MultInv p x)) = (x * (MultInv p x) * |
228 [(MultInv p (MultInv p x)) = (x * (MultInv p x) * |
229 (MultInv p (MultInv p x)))] (mod p)"; |
229 (MultInv p (MultInv p x)))] (mod p)"; |
230 apply (drule MultInv_prop2, auto) |
230 apply (drule MultInv_prop2, auto) |
231 apply (drule_tac k = "MultInv p (MultInv p x)" in zcong_scalar, auto); |
231 apply (drule_tac k = "MultInv p (MultInv p x)" in zcong_scalar, auto); |
232 apply (auto simp add: zcong_sym) |
232 apply (auto simp add: zcong_sym) |
233 done |
233 done |
234 |
234 |
235 lemma aux__2: "[| 2 < p; p \<in> zprime; ~([x = 0](mod p))|] ==> |
235 lemma aux__2: "[| 2 < p; zprime p; ~([x = 0](mod p))|] ==> |
236 [(x * (MultInv p x) * (MultInv p (MultInv p x))) = x] (mod p)"; |
236 [(x * (MultInv p x) * (MultInv p (MultInv p x))) = x] (mod p)"; |
237 apply (frule MultInv_prop3, auto) |
237 apply (frule MultInv_prop3, auto) |
238 apply (insert MultInv_prop2 [of p "MultInv p x"], auto) |
238 apply (insert MultInv_prop2 [of p "MultInv p x"], auto) |
239 apply (drule MultInv_prop2, auto) |
239 apply (drule MultInv_prop2, auto) |
240 apply (drule_tac k = x in zcong_scalar2, auto) |
240 apply (drule_tac k = x in zcong_scalar2, auto) |
241 apply (auto simp add: zmult_ac) |
241 apply (auto simp add: zmult_ac) |
242 done |
242 done |
243 |
243 |
244 lemma MultInv_prop4: "[| 2 < p; p \<in> zprime; ~([x = 0](mod p)) |] ==> |
244 lemma MultInv_prop4: "[| 2 < p; zprime p; ~([x = 0](mod p)) |] ==> |
245 [(MultInv p (MultInv p x)) = x] (mod p)"; |
245 [(MultInv p (MultInv p x)) = x] (mod p)"; |
246 apply (frule aux__1, auto) |
246 apply (frule aux__1, auto) |
247 apply (drule aux__2, auto) |
247 apply (drule aux__2, auto) |
248 apply (drule zcong_trans, auto) |
248 apply (drule zcong_trans, auto) |
249 done |
249 done |
250 |
250 |
251 lemma MultInv_prop5: "[| 2 < p; p \<in> zprime; ~([x = 0](mod p)); |
251 lemma MultInv_prop5: "[| 2 < p; zprime p; ~([x = 0](mod p)); |
252 ~([y = 0](mod p)); [(MultInv p x) = (MultInv p y)] (mod p) |] ==> |
252 ~([y = 0](mod p)); [(MultInv p x) = (MultInv p y)] (mod p) |] ==> |
253 [x = y] (mod p)"; |
253 [x = y] (mod p)"; |
254 apply (drule_tac a = "MultInv p x" and b = "MultInv p y" and |
254 apply (drule_tac a = "MultInv p x" and b = "MultInv p y" and |
255 m = p and k = x in zcong_scalar) |
255 m = p and k = x in zcong_scalar) |
256 apply (insert MultInv_prop2 [of p x], simp) |
256 apply (insert MultInv_prop2 [of p x], simp) |
269 |
269 |
270 lemma aux___1: "[j = a * MultInv p k] (mod p) ==> |
270 lemma aux___1: "[j = a * MultInv p k] (mod p) ==> |
271 [j * k = a * MultInv p k * k] (mod p)"; |
271 [j * k = a * MultInv p k * k] (mod p)"; |
272 by (auto simp add: zcong_scalar) |
272 by (auto simp add: zcong_scalar) |
273 |
273 |
274 lemma aux___2: "[|2 < p; p \<in> zprime; ~([k = 0](mod p)); |
274 lemma aux___2: "[|2 < p; zprime p; ~([k = 0](mod p)); |
275 [j * k = a * MultInv p k * k] (mod p) |] ==> [j * k = a] (mod p)"; |
275 [j * k = a * MultInv p k * k] (mod p) |] ==> [j * k = a] (mod p)"; |
276 apply (insert MultInv_prop2a [of p k] zcong_zmult_prop2 |
276 apply (insert MultInv_prop2a [of p k] zcong_zmult_prop2 |
277 [of "MultInv p k * k" 1 p "j * k" a]) |
277 [of "MultInv p k * k" 1 p "j * k" a]) |
278 apply (auto simp add: zmult_ac) |
278 apply (auto simp add: zmult_ac) |
279 done |
279 done |
280 |
280 |
281 lemma aux___3: "[j * k = a] (mod p) ==> [(MultInv p j) * j * k = |
281 lemma aux___3: "[j * k = a] (mod p) ==> [(MultInv p j) * j * k = |
282 (MultInv p j) * a] (mod p)"; |
282 (MultInv p j) * a] (mod p)"; |
283 by (auto simp add: zmult_assoc zcong_scalar2) |
283 by (auto simp add: zmult_assoc zcong_scalar2) |
284 |
284 |
285 lemma aux___4: "[|2 < p; p \<in> zprime; ~([j = 0](mod p)); |
285 lemma aux___4: "[|2 < p; zprime p; ~([j = 0](mod p)); |
286 [(MultInv p j) * j * k = (MultInv p j) * a] (mod p) |] |
286 [(MultInv p j) * j * k = (MultInv p j) * a] (mod p) |] |
287 ==> [k = a * (MultInv p j)] (mod p)"; |
287 ==> [k = a * (MultInv p j)] (mod p)"; |
288 apply (insert MultInv_prop2a [of p j] zcong_zmult_prop1 |
288 apply (insert MultInv_prop2a [of p j] zcong_zmult_prop1 |
289 [of "MultInv p j * j" 1 p "MultInv p j * a" k]) |
289 [of "MultInv p j * j" 1 p "MultInv p j * a" k]) |
290 apply (auto simp add: zmult_ac zcong_sym) |
290 apply (auto simp add: zmult_ac zcong_sym) |
291 done |
291 done |
292 |
292 |
293 lemma MultInv_zcong_prop2: "[| 2 < p; p \<in> zprime; ~([k = 0](mod p)); |
293 lemma MultInv_zcong_prop2: "[| 2 < p; zprime p; ~([k = 0](mod p)); |
294 ~([j = 0](mod p)); [j = a * MultInv p k] (mod p) |] ==> |
294 ~([j = 0](mod p)); [j = a * MultInv p k] (mod p) |] ==> |
295 [k = a * MultInv p j] (mod p)"; |
295 [k = a * MultInv p j] (mod p)"; |
296 apply (drule aux___1) |
296 apply (drule aux___1) |
297 apply (frule aux___2, auto) |
297 apply (frule aux___2, auto) |
298 by (drule aux___3, drule aux___4, auto) |
298 by (drule aux___3, drule aux___4, auto) |
299 |
299 |
300 lemma MultInv_zcong_prop3: "[| 2 < p; p \<in> zprime; ~([a = 0](mod p)); |
300 lemma MultInv_zcong_prop3: "[| 2 < p; zprime p; ~([a = 0](mod p)); |
301 ~([k = 0](mod p)); ~([j = 0](mod p)); |
301 ~([k = 0](mod p)); ~([j = 0](mod p)); |
302 [a * MultInv p j = a * MultInv p k] (mod p) |] ==> |
302 [a * MultInv p j = a * MultInv p k] (mod p) |] ==> |
303 [j = k] (mod p)"; |
303 [j = k] (mod p)"; |
304 apply (auto simp add: zcong_eq_zdvd_prop [of a p]) |
304 apply (auto simp add: zcong_eq_zdvd_prop [of a p]) |
305 apply (frule zprime_imp_zrelprime, auto) |
305 apply (frule zprime_imp_zrelprime, auto) |