185 by (auto simp: B_def p_prime p_a_relprime A_ncong_p dest: cong_prime_prod_zero_int) |
185 by (auto simp: B_def p_prime p_a_relprime A_ncong_p dest: cong_prime_prod_zero_int) |
186 |
186 |
187 lemma B_greater_zero: "x \<in> B \<Longrightarrow> 0 < x" |
187 lemma B_greater_zero: "x \<in> B \<Longrightarrow> 0 < x" |
188 using a_nonzero by (auto simp add: B_def A_greater_zero) |
188 using a_nonzero by (auto simp add: B_def A_greater_zero) |
189 |
189 |
|
190 lemma B_mod_greater_zero: |
|
191 "0 < x mod int p" if "x \<in> B" |
|
192 proof - |
|
193 from that have "x mod int p \<noteq> 0" |
|
194 using B_ncong_p cong_def cong_mult_self_left by blast |
|
195 moreover from that have "0 < x" |
|
196 by (rule B_greater_zero) |
|
197 then have "0 \<le> x mod int p" |
|
198 by (auto simp add: mod_int_pos_iff intro: neq_le_trans) |
|
199 ultimately show ?thesis |
|
200 by simp |
|
201 qed |
|
202 |
190 lemma C_greater_zero: "y \<in> C \<Longrightarrow> 0 < y" |
203 lemma C_greater_zero: "y \<in> C \<Longrightarrow> 0 < y" |
191 proof (auto simp add: C_def) |
204 by (auto simp add: C_def B_mod_greater_zero) |
192 fix x :: int |
|
193 assume x: "x \<in> B" |
|
194 moreover from x have "x mod int p \<noteq> 0" |
|
195 using B_ncong_p cong_int_def by simp |
|
196 moreover have "int y = 0 \<or> 0 < int y" for y |
|
197 by linarith |
|
198 ultimately show "0 < x mod int p" |
|
199 using B_greater_zero [of x] |
|
200 by (auto simp add: mod_int_pos_iff intro: neq_le_trans) |
|
201 qed |
|
202 |
205 |
203 lemma F_subset: "F \<subseteq> {x. 0 < x \<and> x \<le> ((int p - 1) div 2)}" |
206 lemma F_subset: "F \<subseteq> {x. 0 < x \<and> x \<le> ((int p - 1) div 2)}" |
204 apply (auto simp add: F_def E_def C_def) |
207 apply (auto simp add: F_def E_def C_def) |
205 apply (metis p_ge_2 Divides.pos_mod_bound nat_int zless_nat_conj) |
208 apply (metis p_ge_2 Divides.pos_mod_bound nat_int zless_nat_conj) |
206 apply (auto intro: p_odd_int) |
209 apply (auto intro: p_odd_int) |
259 lemma C_B_zcong_prod: "[prod id C = prod id B] (mod p)" |
262 lemma C_B_zcong_prod: "[prod id C = prod id B] (mod p)" |
260 apply (auto simp add: C_def) |
263 apply (auto simp add: C_def) |
261 apply (insert finite_B SR_B_inj) |
264 apply (insert finite_B SR_B_inj) |
262 apply (drule prod.reindex [of "\<lambda>x. x mod int p" B id]) |
265 apply (drule prod.reindex [of "\<lambda>x. x mod int p" B id]) |
263 apply auto |
266 apply auto |
264 apply (rule cong_prod_int) |
267 apply (rule cong_prod) |
265 apply (auto simp add: cong_int_def) |
268 apply (auto simp add: cong_def) |
266 done |
269 done |
267 |
270 |
268 lemma F_Un_D_subset: "(F \<union> D) \<subseteq> A" |
271 lemma F_Un_D_subset: "(F \<union> D) \<subseteq> A" |
269 by (intro Un_least subset_trans [OF F_subset] subset_trans [OF D_subset]) (auto simp: A_def) |
272 by (intro Un_least subset_trans [OF F_subset] subset_trans [OF D_subset]) (auto simp: A_def) |
270 |
273 |
271 lemma F_D_disj: "(F \<inter> D) = {}" |
274 lemma F_D_disj: "(F \<inter> D) = {}" |
272 proof (auto simp add: F_eq D_eq) |
275 proof (auto simp add: F_eq D_eq) |
273 fix y z :: int |
276 fix y z :: int |
274 assume "p - (y * a) mod p = (z * a) mod p" |
277 assume "p - (y * a) mod p = (z * a) mod p" |
275 then have "[(y * a) mod p + (z * a) mod p = 0] (mod p)" |
278 then have "[(y * a) mod p + (z * a) mod p = 0] (mod p)" |
276 by (metis add.commute diff_eq_eq dvd_refl cong_int_def dvd_eq_mod_eq_0 mod_0) |
279 by (metis add.commute diff_eq_eq dvd_refl cong_def dvd_eq_mod_eq_0 mod_0) |
277 moreover have "[y * a = (y * a) mod p] (mod p)" |
280 moreover have "[y * a = (y * a) mod p] (mod p)" |
278 by (metis cong_int_def mod_mod_trivial) |
281 by (metis cong_def mod_mod_trivial) |
279 ultimately have "[a * (y + z) = 0] (mod p)" |
282 ultimately have "[a * (y + z) = 0] (mod p)" |
280 by (metis cong_int_def mod_add_left_eq mod_add_right_eq mult.commute ring_class.ring_distribs(1)) |
283 by (metis cong_def mod_add_left_eq mod_add_right_eq mult.commute ring_class.ring_distribs(1)) |
281 with p_prime a_nonzero p_a_relprime have a: "[y + z = 0] (mod p)" |
284 with p_prime a_nonzero p_a_relprime have a: "[y + z = 0] (mod p)" |
282 by (auto dest!: cong_prime_prod_zero_int) |
285 by (auto dest!: cong_prime_prod_zero_int) |
283 assume b: "y \<in> A" and c: "z \<in> A" |
286 assume b: "y \<in> A" and c: "z \<in> A" |
284 then have "0 < y + z" |
287 then have "0 < y + z" |
285 by (auto simp: A_def) |
288 by (auto simp: A_def) |
312 apply (insert finite_E inj_on_pminusx_E) |
315 apply (insert finite_E inj_on_pminusx_E) |
313 apply (drule prod.reindex) |
316 apply (drule prod.reindex) |
314 apply auto |
317 apply auto |
315 done |
318 done |
316 then have "\<forall>x \<in> E. [(p-x) mod p = - x](mod p)" |
319 then have "\<forall>x \<in> E. [(p-x) mod p = - x](mod p)" |
317 by (metis cong_int_def minus_mod_self1 mod_mod_trivial) |
320 by (metis cong_def minus_mod_self1 mod_mod_trivial) |
318 then have "[prod ((\<lambda>x. x mod p) o (op - p)) E = prod (uminus) E](mod p)" |
321 then have "[prod ((\<lambda>x. x mod p) o (op - p)) E = prod (uminus) E](mod p)" |
319 using finite_E p_ge_2 cong_prod_int [of E "(\<lambda>x. x mod p) o (op - p)" uminus p] |
322 using finite_E p_ge_2 cong_prod [of E "(\<lambda>x. x mod p) o (op - p)" uminus p] |
320 by auto |
323 by auto |
321 then have two: "[prod id F = prod (uminus) E](mod p)" |
324 then have two: "[prod id F = prod (uminus) E](mod p)" |
322 by (metis FE cong_cong_mod_int cong_refl_int cong_prod_int minus_mod_self1) |
325 by (metis FE cong_cong_mod_int cong_refl cong_prod minus_mod_self1) |
323 have "prod uminus E = (-1) ^ card E * prod id E" |
326 have "prod uminus E = (-1) ^ card E * prod id E" |
324 using finite_E by (induct set: finite) auto |
327 using finite_E by (induct set: finite) auto |
325 with two show ?thesis |
328 with two show ?thesis |
326 by simp |
329 by simp |
327 qed |
330 qed |
328 |
331 |
329 |
332 |
330 subsection \<open>Gauss' Lemma\<close> |
333 subsection \<open>Gauss' Lemma\<close> |
331 |
334 |
332 lemma aux: "prod id A * (- 1) ^ card E * a ^ card A * (- 1) ^ card E = prod id A * a ^ card A" |
335 lemma aux: "prod id A * (- 1) ^ card E * a ^ card A * (- 1) ^ card E = prod id A * a ^ card A" |
333 by (metis (no_types) minus_minus mult.commute mult.left_commute power_minus power_one) |
336 by auto |
334 |
337 |
335 theorem pre_gauss_lemma: "[a ^ nat((int p - 1) div 2) = (-1) ^ (card E)] (mod p)" |
338 theorem pre_gauss_lemma: "[a ^ nat((int p - 1) div 2) = (-1) ^ (card E)] (mod p)" |
336 proof - |
339 proof - |
337 have "[prod id A = prod id F * prod id D](mod p)" |
340 have "[prod id A = prod id F * prod id D](mod p)" |
338 by (auto simp: prod_D_F_eq_prod_A mult.commute cong del: prod.strong_cong) |
341 by (auto simp: prod_D_F_eq_prod_A mult.commute cong del: prod.strong_cong) |
339 then have "[prod id A = ((-1)^(card E) * prod id E) * prod id D] (mod p)" |
342 then have "[prod id A = ((-1)^(card E) * prod id E) * prod id D] (mod p)" |
340 by (rule cong_trans_int) (metis cong_scalar_int prod_F_zcong) |
343 by (rule cong_trans) (metis cong_scalar_right prod_F_zcong) |
341 then have "[prod id A = ((-1)^(card E) * prod id C)] (mod p)" |
344 then have "[prod id A = ((-1)^(card E) * prod id C)] (mod p)" |
342 by (metis C_prod_eq_D_times_E mult.commute mult.left_commute) |
345 using finite_D finite_E by (auto simp add: ac_simps C_prod_eq_D_times_E C_eq D_E_disj prod.union_disjoint) |
343 then have "[prod id A = ((-1)^(card E) * prod id B)] (mod p)" |
346 then have "[prod id A = ((-1)^(card E) * prod id B)] (mod p)" |
344 by (rule cong_trans_int) (metis C_B_zcong_prod cong_scalar2_int) |
347 by (rule cong_trans) (metis C_B_zcong_prod cong_scalar_left) |
345 then have "[prod id A = ((-1)^(card E) * prod id ((\<lambda>x. x * a) ` A))] (mod p)" |
348 then have "[prod id A = ((-1)^(card E) * prod id ((\<lambda>x. x * a) ` A))] (mod p)" |
346 by (simp add: B_def) |
349 by (simp add: B_def) |
347 then have "[prod id A = ((-1)^(card E) * prod (\<lambda>x. x * a) A)] (mod p)" |
350 then have "[prod id A = ((-1)^(card E) * prod (\<lambda>x. x * a) A)] (mod p)" |
348 by (simp add: inj_on_xa_A prod.reindex) |
351 by (simp add: inj_on_xa_A prod.reindex) |
349 moreover have "prod (\<lambda>x. x * a) A = prod (\<lambda>x. a) A * prod id A" |
352 moreover have "prod (\<lambda>x. x * a) A = prod (\<lambda>x. a) A * prod id A" |
350 using finite_A by (induct set: finite) auto |
353 using finite_A by (induct set: finite) auto |
351 ultimately have "[prod id A = ((-1)^(card E) * (prod (\<lambda>x. a) A * prod id A))] (mod p)" |
354 ultimately have "[prod id A = ((-1)^(card E) * (prod (\<lambda>x. a) A * prod id A))] (mod p)" |
352 by simp |
355 by simp |
353 then have "[prod id A = ((-1)^(card E) * a^(card A) * prod id A)](mod p)" |
356 then have "[prod id A = ((-1)^(card E) * a^(card A) * prod id A)](mod p)" |
354 by (rule cong_trans_int) |
357 by (rule cong_trans) |
355 (simp add: cong_scalar2_int cong_scalar_int finite_A prod_constant mult.assoc) |
358 (simp add: cong_scalar_left cong_scalar_right finite_A prod_constant ac_simps) |
356 then have a: "[prod id A * (-1)^(card E) = |
359 then have a: "[prod id A * (-1)^(card E) = |
357 ((-1)^(card E) * a^(card A) * prod id A * (-1)^(card E))](mod p)" |
360 ((-1)^(card E) * a^(card A) * prod id A * (-1)^(card E))](mod p)" |
358 by (rule cong_scalar_int) |
361 by (rule cong_scalar_right) |
359 then have "[prod id A * (-1)^(card E) = prod id A * |
362 then have "[prod id A * (-1)^(card E) = prod id A * |
360 (-1)^(card E) * a^(card A) * (-1)^(card E)](mod p)" |
363 (-1)^(card E) * a^(card A) * (-1)^(card E)](mod p)" |
361 by (rule cong_trans_int) (simp add: a mult.commute mult.left_commute) |
364 by (rule cong_trans) (simp add: a ac_simps) |
362 then have "[prod id A * (-1)^(card E) = prod id A * a^(card A)](mod p)" |
365 then have "[prod id A * (-1)^(card E) = prod id A * a^(card A)](mod p)" |
363 by (rule cong_trans_int) (simp add: aux cong del: prod.strong_cong) |
366 by (rule cong_trans) (simp add: aux cong del: prod.strong_cong) |
364 with A_prod_relprime have "[(- 1) ^ card E = a ^ card A](mod p)" |
367 with A_prod_relprime have "[(- 1) ^ card E = a ^ card A](mod p)" |
365 by (metis cong_mult_lcancel_int) |
368 by (metis cong_mult_lcancel_int) |
366 then show ?thesis |
369 then show ?thesis |
367 by (simp add: A_card_eq cong_sym_int) |
370 by (simp add: A_card_eq cong_sym) |
368 qed |
371 qed |
369 |
372 |
370 theorem gauss_lemma: "Legendre a p = (-1) ^ (card E)" |
373 theorem gauss_lemma: "Legendre a p = (-1) ^ (card E)" |
371 proof - |
374 proof - |
372 from euler_criterion p_prime p_ge_2 have "[Legendre a p = a^(nat (((p) - 1) div 2))] (mod p)" |
375 from euler_criterion p_prime p_ge_2 have "[Legendre a p = a^(nat (((p) - 1) div 2))] (mod p)" |
374 moreover have "int ((p - 1) div 2) = (int p - 1) div 2" |
377 moreover have "int ((p - 1) div 2) = (int p - 1) div 2" |
375 using p_eq2 by linarith |
378 using p_eq2 by linarith |
376 then have "[a ^ nat (int ((p - 1) div 2)) = a ^ nat ((int p - 1) div 2)] (mod int p)" |
379 then have "[a ^ nat (int ((p - 1) div 2)) = a ^ nat ((int p - 1) div 2)] (mod int p)" |
377 by force |
380 by force |
378 ultimately have "[Legendre a p = (-1) ^ (card E)] (mod p)" |
381 ultimately have "[Legendre a p = (-1) ^ (card E)] (mod p)" |
379 using pre_gauss_lemma cong_trans_int by blast |
382 using pre_gauss_lemma cong_trans by blast |
380 moreover from p_a_relprime have "Legendre a p = 1 \<or> Legendre a p = -1" |
383 moreover from p_a_relprime have "Legendre a p = 1 \<or> Legendre a p = -1" |
381 by (auto simp add: Legendre_def) |
384 by (auto simp add: Legendre_def) |
382 moreover have "(-1::int) ^ (card E) = 1 \<or> (-1::int) ^ (card E) = -1" |
385 moreover have "(-1::int) ^ (card E) = 1 \<or> (-1::int) ^ (card E) = -1" |
383 using neg_one_even_power neg_one_odd_power by blast |
386 using neg_one_even_power neg_one_odd_power by blast |
384 moreover have "[1 \<noteq> - 1] (mod int p)" |
387 moreover have "[1 \<noteq> - 1] (mod int p)" |
385 using cong_altdef_int nonzero_mod_p[of 2] p_odd_int by fastforce |
388 using cong_altdef_int nonzero_mod_p[of 2] p_odd_int by fastforce |
386 ultimately show ?thesis |
389 ultimately show ?thesis |
387 by (auto simp add: cong_sym_int) |
390 by (auto simp add: cong_sym) |
388 qed |
391 qed |
389 |
392 |
390 end |
393 end |
391 |
394 |
392 end |
395 end |