wenzelm@38159: (* Title: HOL/Old_Number_Theory/Quadratic_Reciprocity.thy wenzelm@38159: Authors: Jeremy Avigad, David Gray, and Adam Kramer paulson@13871: *) paulson@13871: paulson@13871: header {* The law of Quadratic reciprocity *} paulson@13871: nipkow@15392: theory Quadratic_Reciprocity nipkow@15392: imports Gauss nipkow@15392: begin paulson@13871: wenzelm@19670: text {* wenzelm@19670: Lemmas leading up to the proof of theorem 3.3 in Niven and wenzelm@19670: Zuckerman's presentation. wenzelm@19670: *} paulson@13871: wenzelm@21233: context GAUSS wenzelm@21233: begin wenzelm@21233: wenzelm@21233: lemma QRLemma1: "a * setsum id A = nipkow@15392: p * setsum (%x. ((x * a) div p)) A + setsum id D + setsum id E" nipkow@15392: proof - wenzelm@18369: from finite_A have "a * setsum id A = setsum (%x. a * x) A" paulson@13871: by (auto simp add: setsum_const_mult id_def) wenzelm@18369: also have "setsum (%x. a * x) = setsum (%x. x * a)" haftmann@57512: by (auto simp add: mult.commute) nipkow@15392: also have "setsum (%x. x * a) A = setsum id B" haftmann@57418: by (simp add: B_def setsum.reindex [OF inj_on_xa_A]) nipkow@15392: also have "... = setsum (%x. p * (x div p) + StandardRes p x) B" nipkow@16733: by (auto simp add: StandardRes_def zmod_zdiv_equality) nipkow@15392: also have "... = setsum (%x. p * (x div p)) B + setsum (StandardRes p) B" haftmann@57418: by (rule setsum.distrib) nipkow@15392: also have "setsum (StandardRes p) B = setsum id C" haftmann@57418: by (auto simp add: C_def setsum.reindex [OF SR_B_inj]) nipkow@15392: also from C_eq have "... = setsum id (D \ E)" paulson@13871: by auto nipkow@15392: also from finite_D finite_E have "... = setsum id D + setsum id E" haftmann@57418: by (rule setsum.union_disjoint) (auto simp add: D_def E_def) wenzelm@18369: also have "setsum (%x. p * (x div p)) B = nipkow@15392: setsum ((%x. p * (x div p)) o (%x. (x * a))) A" haftmann@57418: by (auto simp add: B_def setsum.reindex inj_on_xa_A) nipkow@15392: also have "... = setsum (%x. p * ((x * a) div p)) A" paulson@13871: by (auto simp add: o_def) wenzelm@18369: also from finite_A have "setsum (%x. p * ((x * a) div p)) A = nipkow@15392: p * setsum (%x. ((x * a) div p)) A" paulson@13871: by (auto simp add: setsum_const_mult) paulson@13871: finally show ?thesis by arith nipkow@15392: qed paulson@13871: wenzelm@21233: lemma QRLemma2: "setsum id A = p * int (card E) - setsum id E + wenzelm@18369: setsum id D" nipkow@15392: proof - nipkow@15392: from F_Un_D_eq_A have "setsum id A = setsum id (D \ F)" paulson@13871: by (simp add: Un_commute) wenzelm@18369: also from F_D_disj finite_D finite_F wenzelm@18369: have "... = setsum id D + setsum id F" haftmann@57418: by (auto simp add: Int_commute intro: setsum.union_disjoint) nipkow@15392: also from F_def have "F = (%x. (p - x)) ` E" paulson@13871: by auto paulson@13871: also from finite_E inj_on_pminusx_E have "setsum id ((%x. (p - x)) ` E) = nipkow@15392: setsum (%x. (p - x)) E" haftmann@57418: by (auto simp add: setsum.reindex) nipkow@15392: also from finite_E have "setsum (op - p) E = setsum (%x. p) E - setsum id E" nipkow@15392: by (auto simp add: setsum_subtractf id_def) nipkow@15392: also from finite_E have "setsum (%x. p) E = p * int(card E)" paulson@13871: by (intro setsum_const) nipkow@15392: finally show ?thesis paulson@13871: by arith nipkow@15392: qed paulson@13871: wenzelm@21233: lemma QRLemma3: "(a - 1) * setsum id A = nipkow@15392: p * (setsum (%x. ((x * a) div p)) A - int(card E)) + 2 * setsum id E" nipkow@15392: proof - nipkow@15392: have "(a - 1) * setsum id A = a * setsum id A - setsum id A" huffman@44766: by (auto simp add: left_diff_distrib) nipkow@15392: also note QRLemma1 wenzelm@18369: also from QRLemma2 have "p * (\x \ A. x * a div p) + setsum id D + wenzelm@18369: setsum id E - setsum id A = wenzelm@18369: p * (\x \ A. x * a div p) + setsum id D + nipkow@15392: setsum id E - (p * int (card E) - setsum id E + setsum id D)" paulson@13871: by auto wenzelm@18369: also have "... = p * (\x \ A. x * a div p) - wenzelm@18369: p * int (card E) + 2 * setsum id E" paulson@13871: by arith nipkow@15392: finally show ?thesis huffman@44766: by (auto simp only: right_diff_distrib) nipkow@15392: qed paulson@13871: wenzelm@21233: lemma QRLemma4: "a \ zOdd ==> nipkow@15392: (setsum (%x. ((x * a) div p)) A \ zEven) = (int(card E): zEven)" nipkow@15392: proof - nipkow@15392: assume a_odd: "a \ zOdd" paulson@13871: from QRLemma3 have a: "p * (setsum (%x. ((x * a) div p)) A - int(card E)) = wenzelm@18369: (a - 1) * setsum id A - 2 * setsum id E" paulson@13871: by arith paulson@13871: from a_odd have "a - 1 \ zEven" paulson@13871: by (rule odd_minus_one_even) nipkow@15392: hence "(a - 1) * setsum id A \ zEven" paulson@13871: by (rule even_times_either) nipkow@15392: moreover have "2 * setsum id E \ zEven" paulson@13871: by (auto simp add: zEven_def) paulson@13871: ultimately have "(a - 1) * setsum id A - 2 * setsum id E \ zEven" paulson@13871: by (rule even_minus_even) nipkow@15392: with a have "p * (setsum (%x. ((x * a) div p)) A - int(card E)): zEven" paulson@13871: by simp nipkow@15392: hence "p \ zEven | (setsum (%x. ((x * a) div p)) A - int(card E)): zEven" paulson@14434: by (rule EvenOdd.even_product) nipkow@15392: with p_odd have "(setsum (%x. ((x * a) div p)) A - int(card E)): zEven" paulson@13871: by (auto simp add: odd_iff_not_even) nipkow@15392: thus ?thesis wenzelm@18369: by (auto simp only: even_diff [symmetric]) nipkow@15392: qed paulson@13871: wenzelm@21233: lemma QRLemma5: "a \ zOdd ==> nipkow@15392: (-1::int)^(card E) = (-1::int)^(nat(setsum (%x. ((x * a) div p)) A))" nipkow@15392: proof - nipkow@15392: assume "a \ zOdd" wenzelm@45630: from QRLemma4 [OF this] have wenzelm@45630: "(int(card E): zEven) = (setsum (%x. ((x * a) div p)) A \ zEven)" .. nipkow@15392: moreover have "0 \ int(card E)" paulson@13871: by auto nipkow@15392: moreover have "0 \ setsum (%x. ((x * a) div p)) A" nipkow@15392: proof (intro setsum_nonneg) nipkow@15537: show "\x \ A. 0 \ x * a div p" nipkow@15392: proof nipkow@15392: fix x nipkow@15392: assume "x \ A" nipkow@15392: then have "0 \ x" paulson@13871: by (auto simp add: A_def) nipkow@15392: with a_nonzero have "0 \ x * a" paulson@14353: by (auto simp add: zero_le_mult_iff) wenzelm@18369: with p_g_2 show "0 \ x * a div p" paulson@13871: by (auto simp add: pos_imp_zdiv_nonneg_iff) nipkow@15392: qed nipkow@15392: qed paulson@13871: ultimately have "(-1::int)^nat((int (card E))) = nipkow@15392: (-1)^nat(((\x \ A. x * a div p)))" paulson@13871: by (intro neg_one_power_parity, auto) nipkow@15392: also have "nat (int(card E)) = card E" paulson@13871: by auto nipkow@15392: finally show ?thesis . nipkow@15392: qed paulson@13871: wenzelm@21233: end wenzelm@21233: nipkow@16663: lemma MainQRLemma: "[| a \ zOdd; 0 < a; ~([a = 0] (mod p)); zprime p; 2 < p; wenzelm@18369: A = {x. 0 < x & x \ (p - 1) div 2} |] ==> nipkow@15392: (Legendre a p) = (-1::int)^(nat(setsum (%x. ((x * a) div p)) A))" paulson@13871: apply (subst GAUSS.gauss_lemma) paulson@13871: apply (auto simp add: GAUSS_def) paulson@13871: apply (subst GAUSS.QRLemma5) wenzelm@18369: apply (auto simp add: GAUSS_def) wenzelm@21233: apply (simp add: GAUSS.A_def [OF GAUSS.intro] GAUSS_def) wenzelm@18369: done paulson@13871: wenzelm@19670: wenzelm@19670: subsection {* Stuff about S, S1 and S2 *} paulson@13871: paulson@13871: locale QRTEMP = paulson@13871: fixes p :: "int" paulson@13871: fixes q :: "int" paulson@13871: nipkow@16663: assumes p_prime: "zprime p" paulson@13871: assumes p_g_2: "2 < p" nipkow@16663: assumes q_prime: "zprime q" paulson@13871: assumes q_g_2: "2 < q" paulson@13871: assumes p_neq_q: "p \ q" wenzelm@21233: begin paulson@13871: wenzelm@38159: definition P_set :: "int set" wenzelm@38159: where "P_set = {x. 0 < x & x \ ((p - 1) div 2) }" wenzelm@21233: wenzelm@38159: definition Q_set :: "int set" wenzelm@38159: where "Q_set = {x. 0 < x & x \ ((q - 1) div 2) }" wenzelm@21233: wenzelm@38159: definition S :: "(int * int) set" wenzelm@38159: where "S = P_set <*> Q_set" wenzelm@21233: wenzelm@38159: definition S1 :: "(int * int) set" wenzelm@38159: where "S1 = { (x, y). (x, y):S & ((p * y) < (q * x)) }" paulson@13871: wenzelm@38159: definition S2 :: "(int * int) set" wenzelm@38159: where "S2 = { (x, y). (x, y):S & ((q * x) < (p * y)) }" wenzelm@21233: wenzelm@38159: definition f1 :: "int => (int * int) set" wenzelm@38159: where "f1 j = { (j1, y). (j1, y):S & j1 = j & (y \ (q * j) div p) }" wenzelm@21233: wenzelm@38159: definition f2 :: "int => (int * int) set" wenzelm@38159: where "f2 j = { (x, j1). (x, j1):S & j1 = j & (x \ (p * j) div q) }" wenzelm@21233: wenzelm@21233: lemma p_fact: "0 < (p - 1) div 2" nipkow@15392: proof - wenzelm@21233: from p_g_2 have "2 \ p - 1" by arith paulson@13871: then have "2 div 2 \ (p - 1) div 2" by (rule zdiv_mono1, auto) paulson@13871: then show ?thesis by auto nipkow@15392: qed paulson@13871: wenzelm@21233: lemma q_fact: "0 < (q - 1) div 2" nipkow@15392: proof - wenzelm@21233: from q_g_2 have "2 \ q - 1" by arith paulson@13871: then have "2 div 2 \ (q - 1) div 2" by (rule zdiv_mono1, auto) paulson@13871: then show ?thesis by auto nipkow@15392: qed paulson@13871: wenzelm@41541: lemma pb_neq_qa: wenzelm@41541: assumes "1 \ b" and "b \ (q - 1) div 2" wenzelm@41541: shows "p * b \ q * a" nipkow@15392: proof wenzelm@41541: assume "p * b = q * a" paulson@13871: then have "q dvd (p * b)" by (auto simp add: dvd_def) nipkow@15392: with q_prime p_g_2 have "q dvd p | q dvd b" paulson@13871: by (auto simp add: zprime_zdvd_zmult) nipkow@15392: moreover have "~ (q dvd p)" nipkow@15392: proof nipkow@15392: assume "q dvd p" paulson@13871: with p_prime have "q = 1 | q = p" paulson@13871: apply (auto simp add: zprime_def QRTEMP_def) paulson@13871: apply (drule_tac x = q and R = False in allE) wenzelm@18369: apply (simp add: QRTEMP_def) paulson@13871: apply (subgoal_tac "0 \ q", simp add: QRTEMP_def) wenzelm@41541: apply (insert assms) wenzelm@18369: apply (auto simp add: QRTEMP_def) wenzelm@18369: done paulson@13871: with q_g_2 p_neq_q show False by auto nipkow@15392: qed paulson@13871: ultimately have "q dvd b" by auto nipkow@15392: then have "q \ b" nipkow@15392: proof - nipkow@15392: assume "q dvd b" wenzelm@41541: moreover from assms have "0 < b" by auto wenzelm@18369: ultimately show ?thesis using zdvd_bounds [of q b] by auto nipkow@15392: qed wenzelm@41541: with assms have "q \ (q - 1) div 2" by auto paulson@13871: then have "2 * q \ 2 * ((q - 1) div 2)" by arith nipkow@15392: then have "2 * q \ q - 1" nipkow@15392: proof - wenzelm@41541: assume a: "2 * q \ 2 * ((q - 1) div 2)" wenzelm@41541: with assms have "q \ zOdd" by (auto simp add: QRTEMP_def zprime_zOdd_eq_grt_2) paulson@13871: with odd_minus_one_even have "(q - 1):zEven" by auto paulson@13871: with even_div_2_prop2 have "(q - 1) = 2 * ((q - 1) div 2)" by auto wenzelm@41541: with a show ?thesis by auto nipkow@15392: qed paulson@13871: then have p1: "q \ -1" by arith paulson@13871: with q_g_2 show False by auto nipkow@15392: qed paulson@13871: wenzelm@21233: lemma P_set_finite: "finite (P_set)" wenzelm@18369: using p_fact by (auto simp add: P_set_def bdd_int_set_l_le_finite) paulson@13871: wenzelm@21233: lemma Q_set_finite: "finite (Q_set)" wenzelm@18369: using q_fact by (auto simp add: Q_set_def bdd_int_set_l_le_finite) paulson@13871: wenzelm@21233: lemma S_finite: "finite S" nipkow@15402: by (auto simp add: S_def P_set_finite Q_set_finite finite_cartesian_product) paulson@13871: wenzelm@21233: lemma S1_finite: "finite S1" nipkow@15392: proof - paulson@13871: have "finite S" by (auto simp add: S_finite) paulson@13871: moreover have "S1 \ S" by (auto simp add: S1_def S_def) paulson@13871: ultimately show ?thesis by (auto simp add: finite_subset) nipkow@15392: qed paulson@13871: wenzelm@21233: lemma S2_finite: "finite S2" nipkow@15392: proof - paulson@13871: have "finite S" by (auto simp add: S_finite) paulson@13871: moreover have "S2 \ S" by (auto simp add: S2_def S_def) paulson@13871: ultimately show ?thesis by (auto simp add: finite_subset) nipkow@15392: qed paulson@13871: wenzelm@21233: lemma P_set_card: "(p - 1) div 2 = int (card (P_set))" wenzelm@18369: using p_fact by (auto simp add: P_set_def card_bdd_int_set_l_le) paulson@13871: wenzelm@21233: lemma Q_set_card: "(q - 1) div 2 = int (card (Q_set))" wenzelm@18369: using q_fact by (auto simp add: Q_set_def card_bdd_int_set_l_le) paulson@13871: wenzelm@21233: lemma S_card: "((p - 1) div 2) * ((q - 1) div 2) = int (card(S))" wenzelm@18369: using P_set_card Q_set_card P_set_finite Q_set_finite wenzelm@41541: by (auto simp add: S_def zmult_int) paulson@13871: wenzelm@21233: lemma S1_Int_S2_prop: "S1 \ S2 = {}" paulson@13871: by (auto simp add: S1_def S2_def) paulson@13871: wenzelm@21233: lemma S1_Union_S2_prop: "S = S1 \ S2" paulson@13871: apply (auto simp add: S_def P_set_def Q_set_def S1_def S2_def) wenzelm@18369: proof - wenzelm@18369: fix a and b wenzelm@18369: assume "~ q * a < p * b" and b1: "0 < b" and b2: "b \ (q - 1) div 2" huffman@44766: with less_linear have "(p * b < q * a) | (p * b = q * a)" by auto wenzelm@18369: moreover from pb_neq_qa b1 b2 have "(p * b \ q * a)" by auto wenzelm@18369: ultimately show "p * b < q * a" by auto wenzelm@18369: qed paulson@13871: wenzelm@21233: lemma card_sum_S1_S2: "((p - 1) div 2) * ((q - 1) div 2) = nipkow@15392: int(card(S1)) + int(card(S2))" wenzelm@18369: proof - nipkow@15392: have "((p - 1) div 2) * ((q - 1) div 2) = int (card(S))" paulson@13871: by (auto simp add: S_card) nipkow@15392: also have "... = int( card(S1) + card(S2))" paulson@13871: apply (insert S1_finite S2_finite S1_Int_S2_prop S1_Union_S2_prop) paulson@13871: apply (drule card_Un_disjoint, auto) wenzelm@18369: done paulson@13871: also have "... = int(card(S1)) + int(card(S2))" by auto nipkow@15392: finally show ?thesis . nipkow@15392: qed paulson@13871: wenzelm@41541: lemma aux1a: wenzelm@41541: assumes "0 < a" and "a \ (p - 1) div 2" wenzelm@41541: and "0 < b" and "b \ (q - 1) div 2" wenzelm@41541: shows "(p * b < q * a) = (b \ q * a div p)" nipkow@15392: proof - nipkow@15392: have "p * b < q * a ==> b \ q * a div p" nipkow@15392: proof - nipkow@15392: assume "p * b < q * a" paulson@13871: then have "p * b \ q * a" by auto nipkow@15392: then have "(p * b) div p \ (q * a) div p" wenzelm@18369: by (rule zdiv_mono1) (insert p_g_2, auto) nipkow@15392: then show "b \ (q * a) div p" paulson@13871: apply (subgoal_tac "p \ 0") nipkow@30034: apply (frule div_mult_self1_is_id, force) wenzelm@18369: apply (insert p_g_2, auto) wenzelm@18369: done nipkow@15392: qed nipkow@15392: moreover have "b \ q * a div p ==> p * b < q * a" nipkow@15392: proof - nipkow@15392: assume "b \ q * a div p" nipkow@15392: then have "p * b \ p * ((q * a) div p)" wenzelm@18369: using p_g_2 by (auto simp add: mult_le_cancel_left) nipkow@15392: also have "... \ q * a" wenzelm@18369: by (rule zdiv_leq_prop) (insert p_g_2, auto) nipkow@15392: finally have "p * b \ q * a" . nipkow@15392: then have "p * b < q * a | p * b = q * a" paulson@13871: by (simp only: order_le_imp_less_or_eq) nipkow@15392: moreover have "p * b \ q * a" wenzelm@41541: by (rule pb_neq_qa) (insert assms, auto) paulson@13871: ultimately show ?thesis by auto nipkow@15392: qed nipkow@15392: ultimately show ?thesis .. nipkow@15392: qed paulson@13871: wenzelm@41541: lemma aux1b: wenzelm@41541: assumes "0 < a" and "a \ (p - 1) div 2" wenzelm@41541: and "0 < b" and "b \ (q - 1) div 2" wenzelm@41541: shows "(q * a < p * b) = (a \ p * b div q)" nipkow@15392: proof - nipkow@15392: have "q * a < p * b ==> a \ p * b div q" nipkow@15392: proof - nipkow@15392: assume "q * a < p * b" paulson@13871: then have "q * a \ p * b" by auto nipkow@15392: then have "(q * a) div q \ (p * b) div q" wenzelm@18369: by (rule zdiv_mono1) (insert q_g_2, auto) nipkow@15392: then show "a \ (p * b) div q" paulson@13871: apply (subgoal_tac "q \ 0") nipkow@30034: apply (frule div_mult_self1_is_id, force) wenzelm@18369: apply (insert q_g_2, auto) wenzelm@18369: done nipkow@15392: qed nipkow@15392: moreover have "a \ p * b div q ==> q * a < p * b" nipkow@15392: proof - nipkow@15392: assume "a \ p * b div q" nipkow@15392: then have "q * a \ q * ((p * b) div q)" wenzelm@18369: using q_g_2 by (auto simp add: mult_le_cancel_left) nipkow@15392: also have "... \ p * b" wenzelm@18369: by (rule zdiv_leq_prop) (insert q_g_2, auto) nipkow@15392: finally have "q * a \ p * b" . nipkow@15392: then have "q * a < p * b | q * a = p * b" paulson@13871: by (simp only: order_le_imp_less_or_eq) nipkow@15392: moreover have "p * b \ q * a" wenzelm@41541: by (rule pb_neq_qa) (insert assms, auto) paulson@13871: ultimately show ?thesis by auto nipkow@15392: qed nipkow@15392: ultimately show ?thesis .. nipkow@15392: qed paulson@13871: wenzelm@41541: lemma (in -) aux2: wenzelm@41541: assumes "zprime p" and "zprime q" and "2 < p" and "2 < q" wenzelm@41541: shows "(q * ((p - 1) div 2)) div p \ (q - 1) div 2" nipkow@15392: proof- paulson@13871: (* Set up what's even and odd *) wenzelm@41541: from assms have "p \ zOdd & q \ zOdd" paulson@13871: by (auto simp add: zprime_zOdd_eq_grt_2) nipkow@15392: then have even1: "(p - 1):zEven & (q - 1):zEven" paulson@13871: by (auto simp add: odd_minus_one_even) nipkow@15392: then have even2: "(2 * p):zEven & ((q - 1) * p):zEven" paulson@13871: by (auto simp add: zEven_def) nipkow@15392: then have even3: "(((q - 1) * p) + (2 * p)):zEven" paulson@14434: by (auto simp: EvenOdd.even_plus_even) paulson@13871: (* using these prove it *) wenzelm@41541: from assms have "q * (p - 1) < ((q - 1) * p) + (2 * p)" paulson@13871: by (auto simp add: int_distrib) nipkow@15392: then have "((p - 1) * q) div 2 < (((q - 1) * p) + (2 * p)) div 2" nipkow@15392: apply (rule_tac x = "((p - 1) * q)" in even_div_2_l) huffman@44766: by (auto simp add: even3, auto simp add: mult_ac) nipkow@15392: also have "((p - 1) * q) div 2 = q * ((p - 1) div 2)" paulson@13871: by (auto simp add: even1 even_prod_div_2) nipkow@15392: also have "(((q - 1) * p) + (2 * p)) div 2 = (((q - 1) div 2) * p) + p" paulson@13871: by (auto simp add: even1 even2 even_prod_div_2 even_sum_div_2) wenzelm@18369: finally show ?thesis wenzelm@18369: apply (rule_tac x = " q * ((p - 1) div 2)" and nipkow@15392: y = "(q - 1) div 2" in div_prop2) wenzelm@41541: using assms by auto nipkow@15392: qed paulson@13871: wenzelm@21233: lemma aux3a: "\j \ P_set. int (card (f1 j)) = (q * j) div p" nipkow@15392: proof nipkow@15392: fix j nipkow@15392: assume j_fact: "j \ P_set" nipkow@15392: have "int (card (f1 j)) = int (card {y. y \ Q_set & y \ (q * j) div p})" nipkow@15392: proof - nipkow@15392: have "finite (f1 j)" nipkow@15392: proof - paulson@13871: have "(f1 j) \ S" by (auto simp add: f1_def) paulson@13871: with S_finite show ?thesis by (auto simp add: finite_subset) nipkow@15392: qed nipkow@15392: moreover have "inj_on (%(x,y). y) (f1 j)" paulson@13871: by (auto simp add: f1_def inj_on_def) nipkow@15392: ultimately have "card ((%(x,y). y) ` (f1 j)) = card (f1 j)" paulson@13871: by (auto simp add: f1_def card_image) nipkow@15392: moreover have "((%(x,y). y) ` (f1 j)) = {y. y \ Q_set & y \ (q * j) div p}" wenzelm@41541: using j_fact by (auto simp add: f1_def S_def Q_set_def P_set_def image_def) paulson@13871: ultimately show ?thesis by (auto simp add: f1_def) nipkow@15392: qed nipkow@15392: also have "... = int (card {y. 0 < y & y \ (q * j) div p})" nipkow@15392: proof - wenzelm@18369: have "{y. y \ Q_set & y \ (q * j) div p} = nipkow@15392: {y. 0 < y & y \ (q * j) div p}" paulson@13871: apply (auto simp add: Q_set_def) wenzelm@18369: proof - wenzelm@18369: fix x wenzelm@41541: assume x: "0 < x" "x \ q * j div p" wenzelm@18369: with j_fact P_set_def have "j \ (p - 1) div 2" by auto wenzelm@18369: with q_g_2 have "q * j \ q * ((p - 1) div 2)" wenzelm@18369: by (auto simp add: mult_le_cancel_left) wenzelm@18369: with p_g_2 have "q * j div p \ q * ((p - 1) div 2) div p" wenzelm@18369: by (auto simp add: zdiv_mono1) wenzelm@41541: also from QRTEMP_axioms j_fact P_set_def have "... \ (q - 1) div 2" wenzelm@18369: apply simp wenzelm@18369: apply (insert aux2) wenzelm@18369: apply (simp add: QRTEMP_def) wenzelm@18369: done wenzelm@41541: finally show "x \ (q - 1) div 2" using x by auto wenzelm@18369: qed paulson@13871: then show ?thesis by auto nipkow@15392: qed nipkow@15392: also have "... = (q * j) div p" nipkow@15392: proof - paulson@13871: from j_fact P_set_def have "0 \ j" by auto paulson@14387: with q_g_2 have "q * 0 \ q * j" by (auto simp only: mult_left_mono) paulson@13871: then have "0 \ q * j" by auto nipkow@15392: then have "0 div p \ (q * j) div p" paulson@13871: apply (rule_tac a = 0 in zdiv_mono1) wenzelm@18369: apply (insert p_g_2, auto) wenzelm@18369: done paulson@13871: also have "0 div p = 0" by auto paulson@13871: finally show ?thesis by (auto simp add: card_bdd_int_set_l_le) nipkow@15392: qed nipkow@15392: finally show "int (card (f1 j)) = q * j div p" . nipkow@15392: qed paulson@13871: wenzelm@21233: lemma aux3b: "\j \ Q_set. int (card (f2 j)) = (p * j) div q" nipkow@15392: proof nipkow@15392: fix j nipkow@15392: assume j_fact: "j \ Q_set" nipkow@15392: have "int (card (f2 j)) = int (card {y. y \ P_set & y \ (p * j) div q})" nipkow@15392: proof - nipkow@15392: have "finite (f2 j)" nipkow@15392: proof - paulson@13871: have "(f2 j) \ S" by (auto simp add: f2_def) paulson@13871: with S_finite show ?thesis by (auto simp add: finite_subset) nipkow@15392: qed nipkow@15392: moreover have "inj_on (%(x,y). x) (f2 j)" paulson@13871: by (auto simp add: f2_def inj_on_def) nipkow@15392: ultimately have "card ((%(x,y). x) ` (f2 j)) = card (f2 j)" paulson@13871: by (auto simp add: f2_def card_image) nipkow@15392: moreover have "((%(x,y). x) ` (f2 j)) = {y. y \ P_set & y \ (p * j) div q}" wenzelm@41541: using j_fact by (auto simp add: f2_def S_def Q_set_def P_set_def image_def) paulson@13871: ultimately show ?thesis by (auto simp add: f2_def) nipkow@15392: qed nipkow@15392: also have "... = int (card {y. 0 < y & y \ (p * j) div q})" nipkow@15392: proof - wenzelm@18369: have "{y. y \ P_set & y \ (p * j) div q} = nipkow@15392: {y. 0 < y & y \ (p * j) div q}" paulson@13871: apply (auto simp add: P_set_def) wenzelm@18369: proof - wenzelm@18369: fix x wenzelm@41541: assume x: "0 < x" "x \ p * j div q" wenzelm@18369: with j_fact Q_set_def have "j \ (q - 1) div 2" by auto wenzelm@18369: with p_g_2 have "p * j \ p * ((q - 1) div 2)" wenzelm@18369: by (auto simp add: mult_le_cancel_left) wenzelm@18369: with q_g_2 have "p * j div q \ p * ((q - 1) div 2) div q" wenzelm@18369: by (auto simp add: zdiv_mono1) wenzelm@41541: also from QRTEMP_axioms j_fact have "... \ (p - 1) div 2" wenzelm@18369: by (auto simp add: aux2 QRTEMP_def) wenzelm@41541: finally show "x \ (p - 1) div 2" using x by auto nipkow@15392: qed paulson@13871: then show ?thesis by auto nipkow@15392: qed nipkow@15392: also have "... = (p * j) div q" nipkow@15392: proof - paulson@13871: from j_fact Q_set_def have "0 \ j" by auto paulson@14387: with p_g_2 have "p * 0 \ p * j" by (auto simp only: mult_left_mono) paulson@13871: then have "0 \ p * j" by auto nipkow@15392: then have "0 div q \ (p * j) div q" paulson@13871: apply (rule_tac a = 0 in zdiv_mono1) wenzelm@18369: apply (insert q_g_2, auto) wenzelm@18369: done paulson@13871: also have "0 div q = 0" by auto paulson@13871: finally show ?thesis by (auto simp add: card_bdd_int_set_l_le) nipkow@15392: qed nipkow@15392: finally show "int (card (f2 j)) = p * j div q" . nipkow@15392: qed paulson@13871: wenzelm@21233: lemma S1_card: "int (card(S1)) = setsum (%j. (q * j) div p) P_set" nipkow@15392: proof - nipkow@15392: have "\x \ P_set. finite (f1 x)" nipkow@15392: proof nipkow@15392: fix x paulson@13871: have "f1 x \ S" by (auto simp add: f1_def) paulson@13871: with S_finite show "finite (f1 x)" by (auto simp add: finite_subset) nipkow@15392: qed nipkow@15392: moreover have "(\x \ P_set. \y \ P_set. x \ y --> (f1 x) \ (f1 y) = {})" paulson@13871: by (auto simp add: f1_def) nipkow@15392: moreover note P_set_finite wenzelm@18369: ultimately have "int(card (UNION P_set f1)) = nipkow@15392: setsum (%x. int(card (f1 x))) P_set" nipkow@15402: by(simp add:card_UN_disjoint int_setsum o_def) nipkow@15392: moreover have "S1 = UNION P_set f1" paulson@13871: by (auto simp add: f1_def S_def S1_def S2_def P_set_def Q_set_def aux1a) wenzelm@18369: ultimately have "int(card (S1)) = setsum (%j. int(card (f1 j))) P_set" paulson@13871: by auto nipkow@15392: also have "... = setsum (%j. q * j div p) P_set" haftmann@57418: using aux3a by(fastforce intro: setsum.cong) nipkow@15392: finally show ?thesis . nipkow@15392: qed paulson@13871: wenzelm@21233: lemma S2_card: "int (card(S2)) = setsum (%j. (p * j) div q) Q_set" nipkow@15392: proof - nipkow@15392: have "\x \ Q_set. finite (f2 x)" nipkow@15392: proof nipkow@15392: fix x paulson@13871: have "f2 x \ S" by (auto simp add: f2_def) paulson@13871: with S_finite show "finite (f2 x)" by (auto simp add: finite_subset) nipkow@15392: qed wenzelm@18369: moreover have "(\x \ Q_set. \y \ Q_set. x \ y --> nipkow@15392: (f2 x) \ (f2 y) = {})" paulson@13871: by (auto simp add: f2_def) nipkow@15392: moreover note Q_set_finite wenzelm@18369: ultimately have "int(card (UNION Q_set f2)) = nipkow@15392: setsum (%x. int(card (f2 x))) Q_set" nipkow@15402: by(simp add:card_UN_disjoint int_setsum o_def) nipkow@15392: moreover have "S2 = UNION Q_set f2" paulson@13871: by (auto simp add: f2_def S_def S1_def S2_def P_set_def Q_set_def aux1b) wenzelm@18369: ultimately have "int(card (S2)) = setsum (%j. int(card (f2 j))) Q_set" paulson@13871: by auto nipkow@15392: also have "... = setsum (%j. p * j div q) Q_set" haftmann@57418: using aux3b by(fastforce intro: setsum.cong) nipkow@15392: finally show ?thesis . nipkow@15392: qed paulson@13871: wenzelm@21233: lemma S1_carda: "int (card(S1)) = nipkow@15392: setsum (%j. (j * q) div p) P_set" huffman@44766: by (auto simp add: S1_card mult_ac) paulson@13871: wenzelm@21233: lemma S2_carda: "int (card(S2)) = nipkow@15392: setsum (%j. (j * p) div q) Q_set" huffman@44766: by (auto simp add: S2_card mult_ac) paulson@13871: wenzelm@21233: lemma pq_sum_prop: "(setsum (%j. (j * p) div q) Q_set) + nipkow@15392: (setsum (%j. (j * q) div p) P_set) = ((p - 1) div 2) * ((q - 1) div 2)" nipkow@15392: proof - wenzelm@18369: have "(setsum (%j. (j * p) div q) Q_set) + nipkow@15392: (setsum (%j. (j * q) div p) P_set) = int (card S2) + int (card S1)" paulson@13871: by (auto simp add: S1_carda S2_carda) nipkow@15392: also have "... = int (card S1) + int (card S2)" paulson@13871: by auto nipkow@15392: also have "... = ((p - 1) div 2) * ((q - 1) div 2)" paulson@13871: by (auto simp add: card_sum_S1_S2) nipkow@15392: finally show ?thesis . nipkow@15392: qed paulson@13871: wenzelm@21233: wenzelm@21288: lemma (in -) pq_prime_neq: "[| zprime p; zprime q; p \ q |] ==> (~[p = 0] (mod q))" paulson@13871: apply (auto simp add: zcong_eq_zdvd_prop zprime_def) paulson@13871: apply (drule_tac x = q in allE) paulson@13871: apply (drule_tac x = p in allE) wenzelm@18369: apply auto wenzelm@18369: done paulson@13871: wenzelm@21233: wenzelm@21233: lemma QR_short: "(Legendre p q) * (Legendre q p) = nipkow@15392: (-1::int)^nat(((p - 1) div 2)*((q - 1) div 2))" nipkow@15392: proof - wenzelm@41541: from QRTEMP_axioms have "~([p = 0] (mod q))" paulson@13871: by (auto simp add: pq_prime_neq QRTEMP_def) wenzelm@41541: with QRTEMP_axioms Q_set_def have a1: "(Legendre p q) = (-1::int) ^ nipkow@15392: nat(setsum (%x. ((x * p) div q)) Q_set)" paulson@13871: apply (rule_tac p = q in MainQRLemma) wenzelm@18369: apply (auto simp add: zprime_zOdd_eq_grt_2 QRTEMP_def) wenzelm@18369: done wenzelm@41541: from QRTEMP_axioms have "~([q = 0] (mod p))" paulson@13871: apply (rule_tac p = q and q = p in pq_prime_neq) nipkow@15392: apply (simp add: QRTEMP_def)+ nipkow@16733: done wenzelm@41541: with QRTEMP_axioms P_set_def have a2: "(Legendre q p) = nipkow@15392: (-1::int) ^ nat(setsum (%x. ((x * q) div p)) P_set)" paulson@13871: apply (rule_tac p = p in MainQRLemma) wenzelm@18369: apply (auto simp add: zprime_zOdd_eq_grt_2 QRTEMP_def) wenzelm@18369: done wenzelm@18369: from a1 a2 have "(Legendre p q) * (Legendre q p) = paulson@13871: (-1::int) ^ nat(setsum (%x. ((x * p) div q)) Q_set) * nipkow@15392: (-1::int) ^ nat(setsum (%x. ((x * q) div p)) P_set)" paulson@13871: by auto wenzelm@18369: also have "... = (-1::int) ^ (nat(setsum (%x. ((x * p) div q)) Q_set) + nipkow@15392: nat(setsum (%x. ((x * q) div p)) P_set))" huffman@44766: by (auto simp add: power_add) wenzelm@18369: also have "nat(setsum (%x. ((x * p) div q)) Q_set) + paulson@13871: nat(setsum (%x. ((x * q) div p)) P_set) = wenzelm@18369: nat((setsum (%x. ((x * p) div q)) Q_set) + nipkow@15392: (setsum (%x. ((x * q) div p)) P_set))" wenzelm@20898: apply (rule_tac z = "setsum (%x. ((x * p) div q)) Q_set" in wenzelm@18369: nat_add_distrib [symmetric]) wenzelm@18369: apply (auto simp add: S1_carda [symmetric] S2_carda [symmetric]) wenzelm@18369: done nipkow@15392: also have "... = nat(((p - 1) div 2) * ((q - 1) div 2))" paulson@13871: by (auto simp add: pq_sum_prop) nipkow@15392: finally show ?thesis . nipkow@15392: qed paulson@13871: wenzelm@21233: end wenzelm@21233: paulson@13871: theorem Quadratic_Reciprocity: wenzelm@18369: "[| p \ zOdd; zprime p; q \ zOdd; zprime q; wenzelm@18369: p \ q |] wenzelm@18369: ==> (Legendre p q) * (Legendre q p) = nipkow@15392: (-1::int)^nat(((p - 1) div 2)*((q - 1) div 2))" wenzelm@18369: by (auto simp add: QRTEMP.QR_short zprime_zOdd_eq_grt_2 [symmetric] paulson@13871: QRTEMP_def) paulson@13871: paulson@13871: end