1 (* ========================================================================= *)
2 (* Quadratic reciprocity. *)
3 (* ========================================================================= *)
5 needs "Library/prime.ml";;
6 needs "Library/pocklington.ml";;
10 (* ------------------------------------------------------------------------- *)
12 (* ------------------------------------------------------------------------- *)
14 let IN_NUMSEG_1 = prove
15 (`!p i. i IN 1..p - 1 <=> 0 < i /\ i < p`,
16 REWRITE_TAC[IN_NUMSEG] THEN ARITH_TAC);;
19 (`!n. EVEN n <=> n = 2 * (n DIV 2)`,
20 GEN_TAC THEN REWRITE_TAC[EVEN_MOD] THEN
21 MP_TAC(SPEC `n:num` (MATCH_MP DIVISION (ARITH_RULE `~(2 = 0)`))) THEN
24 let CONG_MINUS1_SQUARE = prove
25 (`2 <= p ==> ((p - 1) * (p - 1) == 1) (mod p)`,
26 SIMP_TAC[LE_EXISTS; LEFT_IMP_EXISTS_THM] THEN REPEAT STRIP_TAC THEN
27 REWRITE_TAC[cong; nat_mod; ARITH_RULE `(2 + x) - 1 = x + 1`] THEN
28 MAP_EVERY EXISTS_TAC [`0`; `d:num`] THEN ARITH_TAC);;
30 let CONG_EXP_MINUS1 = prove
31 (`!p n. 2 <= p ==> ((p - 1) EXP n == if EVEN n then 1 else p - 1) (mod p)`,
32 REWRITE_TAC[RIGHT_FORALL_IMP_THM] THEN GEN_TAC THEN DISCH_TAC THEN
33 INDUCT_TAC THEN REWRITE_TAC[EXP; ARITH; CONG_REFL] THEN
34 MATCH_MP_TAC CONG_TRANS THEN
35 EXISTS_TAC `(p - 1) * (if EVEN n then 1 else p - 1)` THEN
36 ASM_SIMP_TAC[CONG_MULT; CONG_REFL; EVEN] THEN
37 ASM_CASES_TAC `EVEN n` THEN
38 ASM_SIMP_TAC[MULT_CLAUSES; CONG_REFL; CONG_MINUS1_SQUARE]);;
40 let NOT_CONG_MINUS1 = prove
41 (`!p. 3 <= p ==> ~(p - 1 == 1) (mod p)`,
42 REPEAT STRIP_TAC THEN SUBGOAL_THEN `(2 == 0) (mod p)` MP_TAC THENL
43 [MATCH_MP_TAC CONG_ADD_LCANCEL THEN EXISTS_TAC `p - 1` THEN
44 ONCE_REWRITE_TAC[CONG_SYM] THEN
45 ASM_SIMP_TAC[ADD_CLAUSES; ARITH_RULE `3 <= p ==> (p - 1) + 2 = p + 1`] THEN
46 MATCH_MP_TAC CONG_TRANS THEN EXISTS_TAC `0 + 1` THEN CONJ_TAC THENL
47 [ASM_MESON_TAC[ADD_CLAUSES]; ALL_TAC] THEN
48 MATCH_MP_TAC CONG_ADD THEN
49 MESON_TAC[CONG_0; CONG_SYM; DIVIDES_REFL; CONG_REFL];
50 REWRITE_TAC[CONG_0] THEN DISCH_THEN(MP_TAC o MATCH_MP DIVIDES_LE) THEN
53 let CONG_COND_LEMMA = prove
55 ((if x then 1 else p - 1) == (if y then 1 else p - 1)) (mod p)
57 REPEAT GEN_TAC THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
58 ASM_MESON_TAC[CONG_SYM; NOT_CONG_MINUS1]);;
60 let FINITE_SUBCROSS = prove
61 (`!s:A->bool t:B->bool.
62 FINITE s /\ FINITE t ==> FINITE {x,y | x IN s /\ y IN t /\ P x y}`,
63 REPEAT STRIP_TAC THEN MATCH_MP_TAC FINITE_SUBSET THEN
64 EXISTS_TAC `(s:A->bool) CROSS (t:B->bool)` THEN
65 ASM_SIMP_TAC[FINITE_CROSS; SUBSET; IN_CROSS; FORALL_PAIR_THM;
68 let CARD_SUBCROSS_DETERMINATE = prove
69 (`FINITE s /\ FINITE t /\ (!x. x IN s /\ p(x) ==> f(x) IN t)
70 ==> CARD {(x:A),(y:B) | x IN s /\ y IN t /\ y = f x /\ p x} =
71 CARD {x | x IN s /\ p(x)}`,
72 REPEAT STRIP_TAC THEN CONV_TAC SYM_CONV THEN
73 MATCH_MP_TAC CARD_IMAGE_INJ_EQ THEN EXISTS_TAC `\(x:A,y:B). x` THEN
74 ASM_SIMP_TAC[FINITE_SUBCROSS; FORALL_PAIR_THM; EXISTS_UNIQUE_THM] THEN
75 REWRITE_TAC[EXISTS_PAIR_THM; IN_ELIM_PAIR_THM] THEN
76 SIMP_TAC[IN_ELIM_THM; PAIR_EQ] THEN ASM_MESON_TAC[]);;
78 let CARD_SUBCROSS_SWAP = prove
79 (`CARD {y,x | y IN 1..m /\ x IN 1..n /\ P x y} =
80 CARD {x,y | x IN 1..n /\ y IN 1..m /\ P x y}`,
81 REPEAT STRIP_TAC THEN MATCH_MP_TAC CARD_IMAGE_INJ_EQ THEN
82 EXISTS_TAC `\(x:num,y:num). (y,x)` THEN
83 ASM_SIMP_TAC[FINITE_SUBCROSS; FINITE_NUMSEG] THEN
84 REWRITE_TAC[EXISTS_UNIQUE_THM; FORALL_PAIR_THM; EXISTS_PAIR_THM] THEN
85 SIMP_TAC[IN_ELIM_PAIR_THM; PAIR_EQ] THEN MESON_TAC[]);;
87 (* ------------------------------------------------------------------------- *)
88 (* What it means to be a quadratic residue. I keep in the "mod p" as what *)
89 (* I think is a more intuitive notation. *)
91 (* We might explicitly assume that the two numbers are coprime, ruling out *)
92 (* the degenerate case of 0 as a quadratic residue. But this seems simpler. *)
93 (* ------------------------------------------------------------------------- *)
95 parse_as_infix("is_quadratic_residue",(12,"right"));;
97 let is_quadratic_residue = new_definition
98 `y is_quadratic_residue rel <=> ?x. (x EXP 2 == y) (rel)`;;
100 (* ------------------------------------------------------------------------- *)
101 (* Alternative formulation for special cases. *)
102 (* ------------------------------------------------------------------------- *)
104 let IS_QUADRATIC_RESIDUE = prove
105 (`!a p. ~(p = 0) /\ ~(p divides a)
106 ==> (a is_quadratic_residue (mod p) <=>
107 ?x. 0 < x /\ x < p /\ (x EXP 2 == a) (mod p))`,
108 REPEAT GEN_TAC THEN REWRITE_TAC[is_quadratic_residue; EXP_2] THEN
109 DISCH_TAC THEN EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
110 DISCH_THEN(X_CHOOSE_TAC `x:num`) THEN EXISTS_TAC `x MOD p` THEN
111 ASM_SIMP_TAC[DIVISION] THEN CONJ_TAC THENL
112 [ASM_MESON_TAC[LT_NZ; GSYM DIVIDES_MOD; CONG_DIVIDES; DIVIDES_LMUL];
113 UNDISCH_TAC `(x * x == a) (mod p)` THEN
114 ASM_SIMP_TAC[CONG; MOD_MULT_MOD2]]);;
116 let IS_QUADRATIC_RESIDUE_COMMON = prove
117 (`!a p. prime p /\ coprime(a,p)
118 ==> (a is_quadratic_residue (mod p) <=>
119 ?x. 0 < x /\ x < p /\ (x EXP 2 == a) (mod p))`,
120 REPEAT STRIP_TAC THEN MATCH_MP_TAC IS_QUADRATIC_RESIDUE THEN
121 ASM_MESON_TAC[COPRIME_PRIME; DIVIDES_REFL; PRIME_0]);;
123 (* ------------------------------------------------------------------------- *)
124 (* Some lemmas about dual pairs; these would be more natural over Z. *)
125 (* ------------------------------------------------------------------------- *)
127 let QUADRATIC_RESIDUE_PAIR_ADD = prove
129 ==> (((x + y) EXP 2 == x EXP 2) (mod p) <=>
130 p divides y \/ p divides (2 * x + y))`,
131 REWRITE_TAC[NUM_RING `(x + y) EXP 2 = y * (y + 2 * x) + x EXP 2`] THEN
132 SIMP_TAC[CONG_ADD_RCANCEL_EQ_0; CONG_0; PRIME_DIVPROD_EQ; ADD_SYM]);;
134 let QUADRATIC_RESIDUE_PAIR = prove
136 ==> ((x EXP 2 == y EXP 2) (mod p) <=>
137 p divides (x + y) \/ p divides (dist(x,y)))`,
138 GEN_TAC THEN MATCH_MP_TAC WLOG_LE THEN CONJ_TAC THENL
139 [MESON_TAC[DIST_SYM; CONG_SYM; ADD_SYM]; ALL_TAC] THEN
140 REWRITE_TAC[LE_EXISTS] THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
141 ONCE_REWRITE_TAC[CONG_SYM] THEN ASM_SIMP_TAC[QUADRATIC_RESIDUE_PAIR_ADD] THEN
142 REWRITE_TAC[DIST_RADD_0; ARITH_RULE `x + x + d = 2 * x + d`; DISJ_ACI]);;
144 let IS_QUADRATIC_RESIDUE_PAIR = prove
145 (`!a p. prime p /\ coprime(a,p)
146 ==> (a is_quadratic_residue (mod p) <=>
147 ?x y. 0 < x /\ x < p /\ 0 < y /\ y < p /\ x + y = p /\
148 (x EXP 2 == a) (mod p) /\ (y EXP 2 == a) (mod p) /\
149 !z. 0 < z /\ z < p /\ (z EXP 2 == a) (mod p)
150 ==> z = x \/ z = y)`,
151 SIMP_TAC[IS_QUADRATIC_RESIDUE_COMMON] THEN REPEAT STRIP_TAC THEN
152 EQ_TAC THENL [ALL_TAC; MESON_TAC[]] THEN
153 DISCH_THEN(X_CHOOSE_THEN `x:num` STRIP_ASSUME_TAC) THEN
154 MAP_EVERY EXISTS_TAC [`x:num`; `p - x:num`] THEN
155 ASM_SIMP_TAC[ARITH_RULE
156 `0 < x /\ x < p ==> 0 < p - x /\ p - x < p /\ x + (p - x) = p`] THEN
157 REPEAT STRIP_TAC THEN
158 FIRST_X_ASSUM(MP_TAC o MATCH_MP QUADRATIC_RESIDUE_PAIR) THENL
159 [DISCH_THEN(MP_TAC o SPECL [`x:num`; `p - x:num`]) THEN
160 ASM_SIMP_TAC[ARITH_RULE `x < p ==> x + (p - x) = p`; DIVIDES_REFL] THEN
161 ASM_MESON_TAC[CONG_TRANS; CONG_SYM];
162 DISCH_THEN(MP_TAC o SPECL [`x:num`; `z:num`]) THEN
163 SUBGOAL_THEN `(x EXP 2 == z EXP 2) (mod p)` (fun th -> SIMP_TAC[th]) THENL
164 [ASM_MESON_TAC[CONG_TRANS; CONG_SYM]; ALL_TAC] THEN
165 DISCH_THEN(DISJ_CASES_THEN (MP_TAC o MATCH_MP DIVIDES_CASES)) THEN
166 REWRITE_TAC[ADD_EQ_0; DIST_EQ_0] THEN REWRITE_TAC[dist] THEN
169 let QUADRATIC_RESIDUE_PAIR_PRODUCT = prove
170 (`!p x. 0 < x /\ x < p /\ (x EXP 2 == a) (mod p)
171 ==> (x * (p - x) == (p - 1) * a) (mod p)`,
172 REPEAT STRIP_TAC THEN
173 FIRST_ASSUM(ASSUME_TAC o MP (ARITH_RULE `x < p ==> 1 <= p`)) THEN
174 SUBGOAL_THEN `(x * (p - x) + x EXP 2 == a * (p - 1) + a * 1) (mod p)`
176 [ASM_SIMP_TAC[LEFT_SUB_DISTRIB; EXP_2; SUB_ADD;
177 LE_MULT_LCANCEL; LT_IMP_LE] THEN
178 REWRITE_TAC[cong; nat_mod] THEN ASM_MESON_TAC[ADD_SYM; MULT_SYM];
179 REWRITE_TAC[MULT_CLAUSES] THEN
180 ASM_MESON_TAC[CONG_ADD; CONG_TRANS; CONG_SYM; CONG_REFL; MULT_SYM;
181 CONG_ADD_RCANCEL]]);;
183 (* ------------------------------------------------------------------------- *)
184 (* Define the Legendre symbol. *)
185 (* ------------------------------------------------------------------------- *)
187 let legendre = new_definition
188 `(legendre:num#num->int)(a,p) =
189 if ~(coprime(a,p)) then &0
190 else if a is_quadratic_residue (mod p) then &1
193 (* ------------------------------------------------------------------------- *)
194 (* Definition of iterated product. *)
195 (* ------------------------------------------------------------------------- *)
197 let nproduct = new_definition `nproduct = iterate ( * )`;;
199 let NPRODUCT_CLAUSES = prove
200 (`(!f. nproduct {} f = 1) /\
202 ==> (nproduct (x INSERT s) f =
203 if x IN s then nproduct s f else f(x) * nproduct s f))`,
204 REWRITE_TAC[nproduct; GSYM NEUTRAL_MUL] THEN
205 ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
206 MATCH_MP_TAC ITERATE_CLAUSES THEN REWRITE_TAC[MONOIDAL_MUL]);;
208 let NPRODUCT_DELETE = prove
209 (`!s. FINITE s /\ a IN s
210 ==> f(a) * nproduct(s DELETE a) f = nproduct s f`,
211 SIMP_TAC[nproduct; ITERATE_DELETE; MONOIDAL_MUL]);;
213 let CONG_NPRODUCT = prove
214 (`!f g s. FINITE s /\ (!x. x IN s ==> (f x == g x) (mod n))
215 ==> (nproduct s f == nproduct s g) (mod n)`,
216 REWRITE_TAC[nproduct] THEN
217 MATCH_MP_TAC(MATCH_MP ITERATE_RELATED MONOIDAL_MUL) THEN
218 SIMP_TAC[CONG_REFL; CONG_MULT]);;
220 let NPRODUCT_MULT = prove
222 ==> nproduct s (\x. f x * g x) = nproduct s f * nproduct s g`,
223 GEN_TAC THEN GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
224 SIMP_TAC[NPRODUCT_CLAUSES; MULT_AC; MULT_CLAUSES]);;
226 let NPRODUCT_INJECTION = prove
227 (`!f p s. FINITE s /\
228 (!x. x IN s ==> p x IN s) /\
229 (!x y. x IN s /\ y IN s /\ p x = p y ==> x = y)
230 ==> nproduct s (f o p) = nproduct s f`,
231 REWRITE_TAC[nproduct] THEN MATCH_MP_TAC ITERATE_INJECTION THEN
232 REWRITE_TAC[MONOIDAL_MUL]);;
234 let NPRODUCT_CONST = prove
235 (`!c s. FINITE s ==> nproduct s (\x. c) = c EXP (CARD s)`,
236 GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
237 SIMP_TAC[NPRODUCT_CLAUSES; CARD_CLAUSES; EXP]);;
239 let NPRODUCT_DELTA_CONST = prove
241 ==> nproduct s (\x. if p(x) then c else 1) =
242 c EXP (CARD {x | x IN s /\ p(x)})`,
244 (`{x | x IN a INSERT s /\ p(x)} =
245 if p(a) then a INSERT {x | x IN s /\ p(x)}
246 else {x | x IN s /\ p(x)}`,
247 COND_CASES_TAC THEN ASM_REWRITE_TAC[EXTENSION; IN_INSERT; IN_ELIM_THM] THEN
250 (`FINITE s ==> FINITE {x | x IN s /\ p(x)}`,
251 MATCH_MP_TAC(ONCE_REWRITE_RULE[TAUT `a /\ b ==> c <=> b ==> a ==> c`]
253 SIMP_TAC[SUBSET; IN_ELIM_THM]) in
254 GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
255 SIMP_TAC[NPRODUCT_CLAUSES; CARD_CLAUSES; EXP; NOT_IN_EMPTY;
256 SET_RULE `{x | F} = {}`; lemma1] THEN
257 REPEAT STRIP_TAC THEN COND_CASES_TAC THEN
258 ASM_SIMP_TAC[CARD_CLAUSES; IN_ELIM_THM; lemma2; EXP; MULT_CLAUSES]);;
260 let COPRIME_NPRODUCT = prove
261 (`!f p s. FINITE s /\ (!x. x IN s ==> coprime(p,f x))
262 ==> coprime(p,nproduct s f)`,
263 GEN_TAC THEN GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
264 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
265 SIMP_TAC[NPRODUCT_CLAUSES; COPRIME_1; IN_INSERT; COPRIME_MUL]);;
267 (* ------------------------------------------------------------------------- *)
268 (* Factorial in terms of products. *)
269 (* ------------------------------------------------------------------------- *)
271 let FACT_NPRODUCT = prove
272 (`!n. FACT(n) = nproduct(1..n) (\i. i)`,
274 REWRITE_TAC[FACT; NUMSEG_CLAUSES; ARITH; NPRODUCT_CLAUSES] THEN
275 ASM_SIMP_TAC[ARITH_RULE `1 <= SUC n`; NPRODUCT_CLAUSES; FINITE_NUMSEG] THEN
276 REWRITE_TAC[IN_NUMSEG] THEN ARITH_TAC);;
278 (* ------------------------------------------------------------------------- *)
279 (* General "pairing up" theorem for products. *)
280 (* ------------------------------------------------------------------------- *)
282 let NPRODUCT_PAIRUP_INDUCT = prove
283 (`!f r n s k. s HAS_SIZE (2 * n) /\
284 (!x:A. x IN s ==> ?!y. y IN s /\ ~(y = x) /\
285 (f(x) * f(y) == k) (mod r))
286 ==> (nproduct s f == k EXP n) (mod r)`,
287 GEN_TAC THEN GEN_TAC THEN
288 MATCH_MP_TAC num_WF THEN X_GEN_TAC `n:num` THEN DISCH_TAC THEN
289 X_GEN_TAC `s:A->bool` THEN GEN_TAC THEN ASM_CASES_TAC `n = 0` THENL
290 [ASM_SIMP_TAC[MULT_CLAUSES; HAS_SIZE_0; NPRODUCT_CLAUSES; EXP; CONG_REFL];
292 ASM_CASES_TAC `s:A->bool = {}` THENL
293 [ASM_MESON_TAC[HAS_SIZE_0; ARITH_RULE `2 * n = 0 <=> n = 0`; HAS_SIZE];
295 STRIP_TAC THEN FIRST_X_ASSUM(X_CHOOSE_TAC `a:A` o
296 GEN_REWRITE_RULE I [GSYM MEMBER_NOT_EMPTY]) THEN
297 FIRST_X_ASSUM(MP_TAC o SPEC `n - 1`) THEN
298 ASM_SIMP_TAC[ARITH_RULE `~(n = 0) ==> n - 1 < n`] THEN
299 FIRST_ASSUM(MP_TAC o SPEC `a:A`) THEN REWRITE_TAC[ASSUME `(a:A) IN s`] THEN
300 REWRITE_TAC[EXISTS_UNIQUE] THEN
301 DISCH_THEN(X_CHOOSE_THEN `b:A` STRIP_ASSUME_TAC) THEN
302 DISCH_THEN(MP_TAC o SPECL [`(s DELETE a) DELETE (b:A)`; `k:num`]) THEN
303 SUBGOAL_THEN `s = (a:A) INSERT (b INSERT (s DELETE a DELETE b))`
304 (ASSUME_TAC o SYM) THENL [ASM SET_TAC[]; ALL_TAC] THEN ANTS_TAC THENL
306 [UNDISCH_TAC `(s:A->bool) HAS_SIZE 2 * n` THEN
307 FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o LAND_CONV)
309 SIMP_TAC[HAS_SIZE; FINITE_INSERT; CARD_CLAUSES; FINITE_DELETE;
310 IMP_CONJ; IN_DELETE; IN_INSERT] THEN
311 ASM_REWRITE_TAC[] THEN ARITH_TAC;
313 X_GEN_TAC `x:A` THEN ASM_REWRITE_TAC[IN_DELETE] THEN STRIP_TAC THEN
314 FIRST_ASSUM(MP_TAC o C MATCH_MP (ASSUME `(x:A) IN s`)) THEN
315 REWRITE_TAC[EXISTS_UNIQUE] THEN MATCH_MP_TAC MONO_EXISTS THEN
316 X_GEN_TAC `y:A` THEN STRIP_TAC THEN CONJ_TAC THENL
317 [ALL_TAC; ASM_MESON_TAC[]] THEN
318 ASM_REWRITE_TAC[] THEN CONJ_TAC THEN DISCH_THEN SUBST_ALL_TAC THENL
319 [ASM_MESON_TAC[MULT_SYM]; ALL_TAC] THEN
320 FIRST_X_ASSUM(MP_TAC o C MATCH_MP (ASSUME `(b:A) IN s`)) THEN
321 REWRITE_TAC[EXISTS_UNIQUE_THM] THEN
322 DISCH_THEN(MP_TAC o SPECL [`a:A`; `x:A`] o CONJUNCT2) THEN
323 ASM_MESON_TAC[MULT_SYM];
325 DISCH_TAC THEN EXPAND_TAC "s" THEN
326 FIRST_X_ASSUM(MP_TAC o CONJUNCT1 o REWRITE_RULE[HAS_SIZE]) THEN
327 SIMP_TAC[NPRODUCT_CLAUSES; FINITE_INSERT; FINITE_DELETE] THEN
328 REWRITE_TAC[IN_INSERT; IN_DELETE; MULT_CLAUSES] THEN
329 FIRST_ASSUM(SUBST1_TAC o MATCH_MP
330 (ARITH_RULE `~(n = 0) ==> n = SUC(n - 1)`)) THEN
331 ASM_REWRITE_TAC[MULT_ASSOC; EXP] THEN DISCH_TAC THEN
332 MATCH_MP_TAC CONG_MULT THEN ASM_REWRITE_TAC[]);;
334 (* ------------------------------------------------------------------------- *)
336 (* ------------------------------------------------------------------------- *)
338 let QUADRATIC_NONRESIDUE_FACT = prove
339 (`!a p. prime p /\ ODD(p) /\
340 coprime(a,p) /\ ~(a is_quadratic_residue (mod p))
341 ==> (a EXP ((p - 1) DIV 2) == FACT(p - 1)) (mod p)`,
342 REPEAT STRIP_TAC THEN REWRITE_TAC[FACT_NPRODUCT] THEN
343 ONCE_REWRITE_TAC[CONG_SYM] THEN MATCH_MP_TAC NPRODUCT_PAIRUP_INDUCT THEN
345 [FIRST_X_ASSUM(CHOOSE_THEN SUBST1_TAC o
346 GEN_REWRITE_RULE I [ODD_EXISTS]) THEN
347 SIMP_TAC[SUC_SUB1; DIV_MULT; ARITH] THEN
348 REWRITE_TAC[HAS_SIZE; FINITE_NUMSEG; CARD_NUMSEG; ADD_SUB];
350 ASM_CASES_TAC `p = 0` THENL [ASM_MESON_TAC[PRIME_0]; ALL_TAC] THEN
351 ASM_SIMP_TAC[IN_NUMSEG; ARITH_RULE `1 <= x <=> 0 < x`;
352 ARITH_RULE `~(p = 0) ==> (x <= p - 1 <=> x < p)`] THEN
353 REPEAT STRIP_TAC THEN
354 MP_TAC(SPECL [`a:num`; `p:num`; `x:num`] CONG_SOLVE_UNIQUE_NONTRIVIAL) THEN
355 ONCE_REWRITE_TAC[COPRIME_SYM] THEN ASM_REWRITE_TAC[] THEN
356 MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN
357 REWRITE_TAC[FUN_EQ_THM] THEN ASM_MESON_TAC[is_quadratic_residue; EXP_2]);;
359 let QUADRATIC_RESIDUE_FACT = prove
360 (`!a p. prime p /\ ODD(p) /\
361 coprime(a,p) /\ a is_quadratic_residue (mod p)
362 ==> (a EXP ((p - 1) DIV 2) == FACT(p - 2)) (mod p)`,
363 REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[CONG_SYM] THEN
364 SUBGOAL_THEN `3 <= p /\ ~(p = 0)` STRIP_ASSUME_TAC THENL
365 [FIRST_ASSUM(MP_TAC o MATCH_MP PRIME_GE_2) THEN UNDISCH_TAC `ODD(p)` THEN
366 ASM_CASES_TAC `p = 2` THEN ASM_REWRITE_TAC[ARITH] THEN
367 UNDISCH_TAC `~(p = 2)` THEN ARITH_TAC;
369 UNDISCH_TAC `a is_quadratic_residue (mod p)` THEN
370 ASM_SIMP_TAC[EXP_2; IS_QUADRATIC_RESIDUE_PAIR; LEFT_IMP_EXISTS_THM] THEN
371 MAP_EVERY X_GEN_TAC [`x:num`; `y:num`] THEN STRIP_TAC THEN
372 SUBGOAL_THEN `~(x:num = y)` ASSUME_TAC THENL
373 [ASM_MESON_TAC[ODD_ADD]; ALL_TAC] THEN
374 MP_TAC(ISPECL [`\i:num. i`; `p:num`; `(p - 3) DIV 2`;
375 `(1..p-1) DELETE x DELETE y`; `a:num`] NPRODUCT_PAIRUP_INDUCT) THEN
377 [ASM_SIMP_TAC[HAS_SIZE; FINITE_DELETE; FINITE_NUMSEG; IN_NUMSEG_1;
378 CARD_DELETE; IN_DELETE; CARD_NUMSEG_1] THEN
379 SIMP_TAC[ARITH_RULE `p - 1 - 1 - 1 = p - 3`] THEN
380 ASM_SIMP_TAC[GSYM EVEN_DIV; EVEN_SUB; ARITH; NOT_EVEN] THEN
381 X_GEN_TAC `u:num` THEN REPEAT STRIP_TAC THEN
382 MP_TAC(SPECL [`a:num`; `p:num`; `u:num`] CONG_SOLVE_UNIQUE_NONTRIVIAL) THEN
383 ONCE_REWRITE_TAC[COPRIME_SYM] THEN ASM_REWRITE_TAC[] THEN
384 MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ABS_TAC THEN EQ_TAC THEN
385 STRIP_TAC THEN ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THEN
386 DISCH_THEN SUBST_ALL_TAC THEN
387 RULE_ASSUM_TAC(ONCE_REWRITE_RULE[MULT_SYM]) THEN
388 ASM_MESON_TAC[CONG_SOLVE_UNIQUE; PRIME_0; PRIME_COPRIME_LT];
390 MP_TAC(SPECL [`p:num`; `x:num`] QUADRATIC_RESIDUE_PAIR_PRODUCT) THEN
391 ASM_SIMP_TAC[EXP_2; IMP_IMP; ARITH_RULE `x + y = p ==> p - x = y`] THEN
392 DISCH_THEN(MP_TAC o MATCH_MP CONG_MULT) THEN
393 ASM_SIMP_TAC[NPRODUCT_DELETE; GSYM MULT_ASSOC; IN_DELETE;
394 FINITE_DELETE; IN_NUMSEG_1; FINITE_NUMSEG] THEN
395 ASM_SIMP_TAC[GSYM(CONJUNCT2 EXP); GSYM FACT_NPRODUCT; ARITH_RULE
396 `3 <= p ==> SUC((p - 3) DIV 2) = (p - 1) DIV 2`] THEN
397 ASM_SIMP_TAC[FACT; ARITH_RULE `3 <= p ==> p - 1 = SUC(p - 2)`] THEN
398 ASM_SIMP_TAC[ARITH_RULE `3 <= p ==> SUC(p - 2) = p - 1`] THEN
399 ASM_MESON_TAC[COPRIME_MINUS1; CONG_MULT_LCANCEL; CONG_SYM]);;
401 (* ------------------------------------------------------------------------- *)
402 (* We immediately get one part of Wilson's theorem. *)
403 (* ------------------------------------------------------------------------- *)
405 let WILSON_LEMMA = prove
406 (`!p. prime(p) ==> (FACT(p - 2) == 1) (mod p)`,
407 REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[CONG_SYM] THEN
408 FIRST_ASSUM(DISJ_CASES_THEN2 SUBST_ALL_TAC ASSUME_TAC o MATCH_MP PRIME_ODD)
409 THENL [CONV_TAC NUM_REDUCE_CONV THEN CONV_TAC CONG_CONV; ALL_TAC] THEN
410 MP_TAC(SPECL [`1`; `p:num`] QUADRATIC_RESIDUE_FACT) THEN
411 ASM_MESON_TAC[is_quadratic_residue; COPRIME_SYM; COPRIME_1; CONG_REFL;
412 EXP_ONE; CONG_SYM]);;
414 let WILSON_IMP = prove
415 (`!p. prime(p) ==> (FACT(p - 1) == p - 1) (mod p)`,
416 SIMP_TAC[FACT; PRIME_GE_2; ARITH_RULE `2 <= p ==> p - 1 = SUC(p - 2)`] THEN
417 MESON_TAC[CONG_MULT; MULT_CLAUSES; WILSON_LEMMA; CONG_REFL]);;
420 (`!p. ~(p = 1) ==> (prime p <=> (FACT(p - 1) == p - 1) (mod p))`,
421 X_GEN_TAC `n:num` THEN DISCH_TAC THEN EQ_TAC THEN SIMP_TAC[WILSON_IMP] THEN
422 FIRST_X_ASSUM(MP_TAC o MATCH_MP PRIME_FACTOR) THEN
423 DISCH_THEN(X_CHOOSE_THEN `p:num` STRIP_ASSUME_TAC) THEN
424 FIRST_ASSUM(MP_TAC o MATCH_MP DIVIDES_LE) THEN
425 ASM_CASES_TAC `n = 0` THEN ASM_REWRITE_TAC[] THENL
426 [ASM_REWRITE_TAC[CONG_MOD_0] THEN CONV_TAC NUM_REDUCE_CONV; ALL_TAC] THEN
427 REWRITE_TAC[LE_LT] THEN ASM_CASES_TAC `n:num = p` THEN ASM_REWRITE_TAC[] THEN
428 DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE `x < y ==> x <= y - 1`)) THEN
429 ASM_SIMP_TAC[GSYM DIVIDES_FACT_PRIME] THEN
430 DISCH_THEN(fun th -> DISCH_TAC THEN MP_TAC th) THEN
431 SUBGOAL_THEN `p divides FACT(n - 1) <=> p divides (n - 1)` SUBST1_TAC THENL
432 [MATCH_MP_TAC CONG_DIVIDES THEN
433 MATCH_MP_TAC CONG_MOD_MULT THEN EXISTS_TAC `n:num` THEN
436 DISCH_TAC THEN SUBGOAL_THEN `p divides 1` MP_TAC THENL
437 [MATCH_MP_TAC DIVIDES_ADD_REVR THEN EXISTS_TAC `n - 1` THEN
438 ASM_SIMP_TAC[ARITH_RULE `~(n = 0) ==> n - 1 + 1 = n`];
439 REWRITE_TAC[DIVIDES_ONE] THEN ASM_MESON_TAC[PRIME_1]]);;
441 (* ------------------------------------------------------------------------- *)
442 (* Using Wilson's theorem we can get the Euler criterion. *)
443 (* ------------------------------------------------------------------------- *)
445 let EULER_CRITERION = prove
446 (`!a p. prime p /\ coprime(a,p)
447 ==> (a EXP ((p - 1) DIV 2) ==
448 (if a is_quadratic_residue (mod p) then 1 else p - 1)) (mod p)`,
449 REPEAT STRIP_TAC THEN FIRST_ASSUM(DISJ_CASES_THEN2 SUBST_ALL_TAC ASSUME_TAC o
450 MATCH_MP PRIME_ODD) THEN CONV_TAC NUM_REDUCE_CONV THEN
451 REWRITE_TAC[COND_ID; EXP; CONG_REFL] THEN
452 ASM_MESON_TAC[WILSON_LEMMA; WILSON_IMP; CONG_TRANS; CONG_SYM;
453 QUADRATIC_RESIDUE_FACT; QUADRATIC_NONRESIDUE_FACT]);;
455 (* ------------------------------------------------------------------------- *)
457 (* ------------------------------------------------------------------------- *)
459 let GAUSS_LEMMA_1 = prove
460 (`prime p /\ coprime(a,p) /\ 2 * r + 1 = p
461 ==> nproduct(1..r) (\x. let b = (a * x) MOD p in
462 if b <= r then b else p - b) =
463 nproduct(1..r) (\x. x)`,
464 REPEAT STRIP_TAC THEN FIRST_ASSUM(ASSUME_TAC o MATCH_MP PRIME_IMP_NZ) THEN
465 GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [SYM(CONJUNCT1(SPEC_ALL I_O_ID))] THEN
466 REWRITE_TAC[I_DEF] THEN MATCH_MP_TAC NPRODUCT_INJECTION THEN
467 REWRITE_TAC[FINITE_NUMSEG] THEN
468 ABBREV_TAC `f = \x. let b = (a * x) MOD p in
469 if b <= r then b else p - b` THEN
470 MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
471 [GEN_TAC THEN EXPAND_TAC "f" THEN REWRITE_TAC[IN_NUMSEG] THEN
472 LET_TAC THEN REWRITE_TAC[LET_DEF; LET_END_DEF] THEN REPEAT STRIP_TAC THENL
473 [ALL_TAC; EXPAND_TAC "p" THEN ARITH_TAC] THEN
474 REWRITE_TAC[ARITH_RULE `1 <= x <=> ~(x = 0)`] THEN COND_CASES_TAC THENL
475 [ALL_TAC; ASM_MESON_TAC[DIVISION; NOT_LE; SUB_EQ_0; PRIME_0]] THEN
476 EXPAND_TAC "b" THEN ASM_SIMP_TAC[GSYM DIVIDES_MOD; PRIME_IMP_NZ] THEN
477 ASM_SIMP_TAC[PRIME_DIVPROD_EQ] THEN STRIP_TAC THENL
478 [ASM_MESON_TAC[coprime; DIVIDES_REFL; PRIME_1];
479 ASM_MESON_TAC[DIVIDES_LE; ARITH_RULE `~(1 <= 0)`;
480 ARITH_RULE `~(2 * r + 1 <= i /\ i <= r)`]];
481 REWRITE_TAC[LET_DEF; LET_END_DEF] THEN DISCH_TAC] THEN
482 MAP_EVERY X_GEN_TAC [`i:num`; `j:num`] THEN REWRITE_TAC[IN_NUMSEG] THEN
483 REPEAT STRIP_TAC THEN MATCH_MP_TAC CONG_IMP_EQ THEN EXISTS_TAC `p:num` THEN
484 REPEAT(CONJ_TAC THENL
485 [ASM_MESON_TAC[ARITH_RULE `i <= r ==> i < 2 * r + 1`] ; ALL_TAC]) THEN
486 MATCH_MP_TAC CONG_MULT_LCANCEL THEN EXISTS_TAC `a:num` THEN
487 FIRST_X_ASSUM(MP_TAC o MATCH_MP (ARITH_RULE
488 `(if a then x else p - x) = (if b then y else p - y) ==> x < p /\ y < p
489 ==> x = y \/ x + y = p`)) THEN ASM_SIMP_TAC[DIVISION] THEN
490 DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL [ASM_MESON_TAC[CONG]; ALL_TAC] THEN
491 DISCH_THEN(MP_TAC o C AP_THM `p:num` o AP_TERM `(MOD)`) THEN
492 ASM_SIMP_TAC[MOD_ADD_MOD] THEN ASM_SIMP_TAC[GSYM CONG] THEN
493 DISCH_THEN(MP_TAC o MATCH_MP CONG_DIVIDES) THEN
494 ASM_SIMP_TAC[GSYM LEFT_ADD_DISTRIB; PRIME_DIVPROD_EQ; DIVIDES_REFL] THEN
496 [ASM_MESON_TAC[coprime; DIVIDES_REFL; PRIME_1]; ALL_TAC] THEN
497 FIRST_ASSUM(MP_TAC o MATCH_MP DIVIDES_LE) THEN
498 ASM_SIMP_TAC[ARITH_RULE `1 <= i ==> ~(i + j = 0)`] THEN
499 MAP_EVERY UNDISCH_TAC [`i <= r`; `j <= r`; `2 * r + 1 = p`] THEN ARITH_TAC);;
501 let GAUSS_LEMMA_2 = prove
502 (`prime p /\ coprime(a,p) /\ 2 * r + 1 = p
503 ==> (nproduct(1..r) (\x. let b = (a * x) MOD p in
504 if b <= r then b else p - b) ==
505 (p - 1) EXP (CARD {x | x IN 1..r /\ r < (a * x) MOD p}) *
506 a EXP r * nproduct(1..r) (\x. x)) (mod p)`,
507 REPEAT STRIP_TAC THEN
508 ABBREV_TAC `s = {x | x IN 1..r /\ (a * x) MOD p <= r}` THEN
509 MATCH_MP_TAC CONG_TRANS THEN
511 `nproduct(1..r) (\x. (if x IN s then 1 else p - 1) * (a * x) MOD p)` THEN
513 [MATCH_MP_TAC CONG_NPRODUCT THEN REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG] THEN
514 X_GEN_TAC `i:num` THEN STRIP_TAC THEN LET_TAC THEN
515 EXPAND_TAC "s" THEN REWRITE_TAC[IN_ELIM_THM] THEN
516 ASM_REWRITE_TAC[IN_NUMSEG] THEN
517 COND_CASES_TAC THEN ASM_REWRITE_TAC[MULT_CLAUSES; CONG_REFL] THEN
518 REWRITE_TAC[RIGHT_SUB_DISTRIB] THEN MATCH_MP_TAC CONG_SUB THEN
519 ASM_REWRITE_TAC[LE_MULT_RCANCEL; MULT_CLAUSES; CONG_REFL] THEN
520 REWRITE_TAC[ARITH_RULE `b <= p /\ (1 <= p \/ b = 0) <=> b <= p`] THEN
521 FIRST_ASSUM(MP_TAC o MATCH_MP PRIME_GE_2) THEN
522 DISCH_THEN(MP_TAC o SPEC `a * i:num` o MATCH_MP DIVISION o
523 MATCH_MP (ARITH_RULE `2 <= p ==> ~(p = 0)`)) THEN
524 ASM_SIMP_TAC[LT_IMP_LE; cong; nat_mod] THEN DISCH_THEN(K ALL_TAC) THEN
525 MAP_EVERY EXISTS_TAC [`b:num`; `1`] THEN ARITH_TAC;
527 ASM_SIMP_TAC[NPRODUCT_MULT; FINITE_NUMSEG] THEN
528 MATCH_MP_TAC CONG_MULT THEN CONJ_TAC THENL
529 [ONCE_REWRITE_TAC[TAUT `(if p then x else y) = (if ~p then y else x)`] THEN
530 SIMP_TAC[NPRODUCT_DELTA_CONST; FINITE_NUMSEG] THEN
531 MATCH_MP_TAC EQ_IMP_CONG THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
532 EXPAND_TAC "s" THEN REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
535 MATCH_MP_TAC CONG_TRANS THEN EXISTS_TAC `nproduct(1..r) (\x. a * x)` THEN
537 [ASM_SIMP_TAC[CONG_MOD; PRIME_IMP_NZ; CONG_NPRODUCT; FINITE_NUMSEG];
538 SIMP_TAC[NPRODUCT_MULT; FINITE_NUMSEG; NPRODUCT_CONST; CARD_NUMSEG_1] THEN
539 REWRITE_TAC[CONG_REFL]]);;
541 let GAUSS_LEMMA_3 = prove
542 (`prime p /\ coprime(a,p) /\ 2 * r + 1 = p
543 ==> ((p - 1) EXP CARD {x | x IN 1..r /\ r < (a * x) MOD p} *
544 (if a is_quadratic_residue mod p then 1 else p - 1) == 1) (mod p)`,
545 REPEAT STRIP_TAC THEN MATCH_MP_TAC CONG_TRANS THEN EXISTS_TAC
546 `(p - 1) EXP CARD {x | x IN 1..r /\ r < (a * x) MOD p} * a EXP r` THEN
547 ONCE_REWRITE_TAC[CONG_SYM] THEN CONJ_TAC THENL
548 [MATCH_MP_TAC CONG_MULT THEN REWRITE_TAC[CONG_REFL] THEN
549 SUBGOAL_THEN `r = (p - 1) DIV 2`
550 (fun th -> ASM_SIMP_TAC[th; EULER_CRITERION]) THEN
551 EXPAND_TAC "p" THEN ARITH_TAC;
553 MATCH_MP_TAC CONG_MULT_RCANCEL THEN
554 EXISTS_TAC `nproduct (1..r) (\x. x)` THEN
555 ASM_SIMP_TAC[MULT_CLAUSES; GSYM MULT_ASSOC;
556 SIMP_RULE[GAUSS_LEMMA_1] GAUSS_LEMMA_2] THEN
557 ONCE_REWRITE_TAC[COPRIME_SYM] THEN MATCH_MP_TAC COPRIME_NPRODUCT THEN
558 REWRITE_TAC[IN_NUMSEG; FINITE_NUMSEG] THEN REPEAT STRIP_TAC THEN
559 ONCE_REWRITE_TAC[COPRIME_SYM] THEN MATCH_MP_TAC PRIME_COPRIME_LT THEN
560 ASM_REWRITE_TAC[] THEN ASM_ARITH_TAC);;
562 let GAUSS_LEMMA_4 = prove
563 (`prime p /\ coprime(a,p) /\ 2 * r + 1 = p
564 ==> ((if EVEN(CARD{x | x IN 1..r /\ r < (a * x) MOD p}) then 1 else p - 1) *
565 (if a is_quadratic_residue mod p then 1 else p - 1) == 1) (mod p)`,
566 REPEAT STRIP_TAC THEN MATCH_MP_TAC CONG_TRANS THEN
567 EXISTS_TAC `(p - 1) EXP CARD {x | x IN 1..r /\ r < (a * x) MOD p} *
568 (if a is_quadratic_residue mod p then 1 else p - 1)` THEN
569 ASM_SIMP_TAC[GAUSS_LEMMA_3] THEN ONCE_REWRITE_TAC[CONG_SYM] THEN
570 ASM_SIMP_TAC[CONG_EXP_MINUS1; CONG_MULT; CONG_REFL; PRIME_GE_2]);;
572 let GAUSS_LEMMA = prove
573 (`!a p r. prime p /\ coprime(a,p) /\ 2 * r + 1 = p
574 ==> (a is_quadratic_residue (mod p) <=>
575 EVEN(CARD {x | x IN 1..r /\ r < (a * x) MOD p}))`,
576 REPEAT GEN_TAC THEN DISCH_TAC THEN
577 MATCH_MP_TAC CONG_COND_LEMMA THEN EXISTS_TAC `p:num` THEN CONJ_TAC THENL
578 [FIRST_X_ASSUM(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
579 EXPAND_TAC "p" THEN ASM_CASES_TAC `r = 0` THENL
580 [REWRITE_TAC[ASSUME `r = 0`; ARITH; PRIME_1];
581 UNDISCH_TAC `~(r = 0)` THEN ARITH_TAC];
582 FIRST_ASSUM(MP_TAC o MATCH_MP GAUSS_LEMMA_4) THEN
583 REPEAT(COND_CASES_TAC THEN ASM_SIMP_TAC[CONG_REFL]) THEN
584 REWRITE_TAC[MULT_CLAUSES] THEN MESON_TAC[CONG_SYM]]);;
586 (* ------------------------------------------------------------------------- *)
587 (* A more symmetrical version. *)
588 (* ------------------------------------------------------------------------- *)
590 let GAUSS_LEMMA_SYM = prove
591 (`!p q r s. prime p /\ prime q /\ coprime(p,q) /\
592 2 * r + 1 = p /\ 2 * s + 1 = q
593 ==> (q is_quadratic_residue (mod p) <=>
594 EVEN(CARD {x,y | x IN 1..r /\ y IN 1..s /\
595 q * x < p * y /\ p * y <= q * x + r}))`,
596 ONCE_REWRITE_TAC[COPRIME_SYM] THEN REPEAT STRIP_TAC THEN
597 MP_TAC(SPECL [`q:num`; `p:num`; `r:num`] GAUSS_LEMMA) THEN
598 ASM_SIMP_TAC[] THEN DISCH_THEN(K ALL_TAC) THEN AP_TERM_TAC THEN
599 MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC
600 `CARD {x,y | x IN 1..r /\ y IN 1..s /\
601 y = (q * x) DIV p + 1 /\ r < (q * x) MOD p}` THEN
603 [CONV_TAC SYM_CONV THEN MATCH_MP_TAC CARD_SUBCROSS_DETERMINATE THEN
604 REWRITE_TAC[FINITE_NUMSEG; IN_NUMSEG; ARITH_RULE `1 <= x + 1`] THEN
605 X_GEN_TAC `x:num` THEN STRIP_TAC THEN
606 SUBGOAL_THEN `p * (q * x) DIV p + r < q * r` MP_TAC THENL
607 [MATCH_MP_TAC LTE_TRANS THEN EXISTS_TAC `q * x` THEN
608 ASM_REWRITE_TAC[LE_MULT_LCANCEL] THEN
609 GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [MULT_SYM] THEN
610 ASM_MESON_TAC[PRIME_IMP_NZ; LT_ADD_LCANCEL; DIVISION];
611 MAP_EVERY EXPAND_TAC ["p"; "q"] THEN DISCH_THEN(MP_TAC o MATCH_MP
612 (ARITH_RULE `(2 * r + 1) * d + r < (2 * s + 1) * r
613 ==> (2 * r) * d < (2 * r) * s`)) THEN
614 SIMP_TAC[LT_MULT_LCANCEL; ARITH_RULE `x < y ==> x + 1 <= y`]];
616 REWRITE_TAC[EXTENSION; IN_ELIM_PAIR_THM; FORALL_PAIR_THM] THEN
617 MAP_EVERY X_GEN_TAC [`x:num`; `y:num`] THEN
618 AP_TERM_TAC THEN AP_TERM_TAC THEN EQ_TAC THEN DISCH_TAC THENL
619 [MP_TAC(MATCH_MP PRIME_IMP_NZ (ASSUME `prime p`)) THEN
620 DISCH_THEN(MP_TAC o SPEC `q * x` o MATCH_MP DIVISION) THEN
621 FIRST_ASSUM(CONJUNCTS_THEN2 SUBST1_TAC MP_TAC) THEN
622 UNDISCH_TAC `2 * r + 1 = p` THEN ARITH_TAC;
623 MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN CONJ_TAC THENL
625 DISCH_THEN SUBST_ALL_TAC THEN
626 MATCH_MP_TAC(ARITH_RULE
627 `!p d. 2 * r + 1 = p /\ p * (d + 1) <= (d * p + m) + r ==> r < m`) THEN
628 MAP_EVERY EXISTS_TAC [`p:num`; `(q * x) DIV p`] THEN
629 ASM_MESON_TAC[DIVISION; PRIME_IMP_NZ]] THEN
630 MATCH_MP_TAC(ARITH_RULE `~(x <= y) /\ ~(y + 2 <= x) ==> x = y + 1`) THEN
631 REPEAT STRIP_TAC THENL
632 [SUBGOAL_THEN `y * p <= ((q * x) DIV p) * p` MP_TAC THENL
633 [ASM_SIMP_TAC[LE_MULT_RCANCEL; PRIME_IMP_NZ]; ALL_TAC];
634 SUBGOAL_THEN `((q * x) DIV p + 2) * p <= y * p` MP_TAC THENL
635 [ASM_SIMP_TAC[LE_MULT_RCANCEL; PRIME_IMP_NZ]; ALL_TAC]] THEN
636 MP_TAC(MATCH_MP PRIME_IMP_NZ (ASSUME `prime p`)) THEN
637 DISCH_THEN(MP_TAC o SPEC `q * x` o MATCH_MP DIVISION) THEN
640 let GAUSS_LEMMA_SYM' = prove
641 (`!p q r s. prime p /\ prime q /\ coprime(p,q) /\
642 2 * r + 1 = p /\ 2 * s + 1 = q
643 ==> (p is_quadratic_residue (mod q) <=>
644 EVEN(CARD {x,y | x IN 1..r /\ y IN 1..s /\
645 p * y < q * x /\ q * x <= p * y + s}))`,
646 REPEAT STRIP_TAC THEN
647 MP_TAC(SPECL [`q:num`; `p:num`; `s:num`; `r:num`] GAUSS_LEMMA_SYM) THEN
648 ONCE_REWRITE_TAC[COPRIME_SYM] THEN ASM_REWRITE_TAC[] THEN
649 DISCH_THEN SUBST1_TAC THEN AP_TERM_TAC THEN
650 GEN_REWRITE_TAC LAND_CONV [CARD_SUBCROSS_SWAP] THEN
651 AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; FORALL_PAIR_THM] THEN
652 REWRITE_TAC[IN_ELIM_PAIR_THM; CONJ_ACI]);;
654 (* ------------------------------------------------------------------------- *)
655 (* The main result. *)
656 (* ------------------------------------------------------------------------- *)
658 let RECIPROCITY_SET_LEMMA = prove
660 a UNION b UNION c UNION d = (1..r) CROSS (1..s) /\
661 PAIRWISE DISJOINT [a;b;c;d] /\ CARD b = CARD c
662 ==> ((EVEN(CARD a) <=> EVEN(CARD d)) <=> ~(ODD r /\ ODD s))`,
663 REPEAT STRIP_TAC THEN
664 SUBGOAL_THEN `CARD(a:num#num->bool) + CARD(b:num#num->bool) +
665 CARD(c:num#num->bool) + CARD(d:num#num->bool) = r * s`
666 (fun th -> MP_TAC(AP_TERM `EVEN` th) THEN
667 ASM_REWRITE_TAC[EVEN_ADD; GSYM NOT_EVEN; EVEN_MULT] THEN
670 `FINITE(a:num#num->bool) /\ FINITE(b:num#num->bool) /\
671 FINITE(c:num#num->bool) /\ FINITE(d:num#num->bool)`
672 STRIP_ASSUME_TAC THENL
673 [REPEAT STRIP_TAC THEN MATCH_MP_TAC FINITE_SUBSET THEN
674 EXISTS_TAC `(1..r) CROSS (1..s)` THEN
675 SIMP_TAC[FINITE_CROSS; FINITE_NUMSEG] THEN
676 FIRST_X_ASSUM(SUBST_ALL_TAC o SYM) THEN ASM SET_TAC[];
678 FIRST_X_ASSUM(MP_TAC o AP_TERM `CARD:(num#num->bool)->num`) THEN
679 SIMP_TAC[CARD_CROSS; CARD_NUMSEG_1; FINITE_NUMSEG] THEN
680 DISCH_THEN(SUBST1_TAC o SYM) THEN
681 FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [PAIRWISE]) THEN
682 REWRITE_TAC[PAIRWISE; DISJOINT; ALL] THEN
683 ASM_SIMP_TAC[CARD_UNION; FINITE_UNION; SET_RULE
684 `a INTER (b UNION c) = {} <=> a INTER b = {} /\ a INTER c = {}`]);;
686 let RECIPROCITY_SIMPLE = prove
693 ==> ((q is_quadratic_residue (mod p) <=>
694 p is_quadratic_residue (mod q)) <=>
696 REPEAT STRIP_TAC THEN
697 MP_TAC(SPECL [`p:num`; `q:num`; `r:num`; `s:num`] GAUSS_LEMMA_SYM) THEN
698 MP_TAC(SPECL [`p:num`; `q:num`; `r:num`; `s:num`] GAUSS_LEMMA_SYM') THEN
699 ASM_REWRITE_TAC[] THEN
700 ONCE_REWRITE_TAC[COPRIME_SYM] THEN ASM_REWRITE_TAC[] THEN
701 REPEAT(DISCH_THEN SUBST1_TAC) THEN MATCH_MP_TAC RECIPROCITY_SET_LEMMA THEN
702 EXISTS_TAC `{x,y | x IN 1..r /\ y IN 1..s /\ q * x + r < p * y}` THEN
703 EXISTS_TAC `{x,y | x IN 1..r /\ y IN 1..s /\ p * y + s < q * x}` THEN
705 REWRITE_TAC[PAIRWISE; DISJOINT; EXTENSION; NOT_IN_EMPTY; FORALL_PAIR_THM;
706 ALL; IN_UNION; IN_CROSS; IN_ELIM_PAIR_THM; IN_INTER]
708 [MAP_EVERY X_GEN_TAC [`x:num`; `y:num`] THEN
709 MAP_EVERY ASM_CASES_TAC [`x IN 1..r`; `y IN 1..s`] THEN ASM_SIMP_TAC[] THEN
710 SUBGOAL_THEN `~(q * x = p * y)` (fun th -> MP_TAC th THEN ARITH_TAC) THEN
711 DISCH_THEN(MP_TAC o AP_TERM `(divides) p`) THEN
712 ASM_SIMP_TAC[PRIME_DIVPROD_EQ; DIVIDES_REFL] THEN STRIP_TAC THENL
713 [ASM_MESON_TAC[DIVIDES_REFL; PRIME_1; coprime]; ALL_TAC] THEN
714 FIRST_X_ASSUM(MP_TAC o MATCH_MP DIVIDES_LE) THEN
715 UNDISCH_TAC `x IN 1..r` THEN REWRITE_TAC[IN_NUMSEG] THEN
716 EXPAND_TAC "p" THEN ARITH_TAC;
718 MATCH_MP_TAC BIJECTIONS_CARD_EQ THEN
719 REPEAT(EXISTS_TAC `\(x,y). (r + 1) - x,(s + 1) - y`) THEN
720 SIMP_TAC[FINITE_SUBCROSS; FINITE_NUMSEG] THEN
721 REWRITE_TAC[FORALL_PAIR_THM; IN_ELIM_PAIR_THM; IN_NUMSEG; PAIR_EQ] THEN
722 CONJ_TAC THEN MAP_EVERY X_GEN_TAC [`x:num`; `y:num`] THEN
723 SIMP_TAC[ARITH_RULE `x <= y ==> (y + 1) - ((y + 1) - x) = x`] THEN
725 `1 <= x /\ x <= y ==> 1 <= (y + 1) - x /\ (y + 1) - x <= y`] THEN
726 REWRITE_TAC[LEFT_SUB_DISTRIB] THEN REPEAT STRIP_TAC THEN
727 MATCH_MP_TAC(ARITH_RULE
728 `x <= y /\ v + y + z < x + u ==> (y - x) + z < u - v`) THEN
729 ASM_SIMP_TAC[LE_MULT_LCANCEL; ARITH_RULE `x <= r ==> x <= r + 1`] THEN
730 REWRITE_TAC[ARITH_RULE `a + x < y + a <=> x < y`] THEN
731 REPEAT(FIRST_X_ASSUM(SUBST_ALL_TAC o SYM)) THEN
734 (* ------------------------------------------------------------------------- *)
735 (* In terms of the Legendre symbol. *)
736 (* ------------------------------------------------------------------------- *)
738 let RECIPROCITY_LEGENDRE = prove
739 (`!p q. prime p /\ prime q /\ ODD p /\ ODD q /\ ~(p = q)
740 ==> legendre(p,q) * legendre(q,p) =
741 --(&1) pow ((p - 1) DIV 2 * (q - 1) DIV 2)`,
742 REPEAT STRIP_TAC THEN MAP_EVERY UNDISCH_TAC [`ODD q`; `ODD p`] THEN
743 REWRITE_TAC[ODD_EXISTS; LEFT_IMP_EXISTS_THM; RIGHT_IMP_FORALL_THM] THEN
744 MAP_EVERY X_GEN_TAC [`r:num`; `s:num`] THEN REWRITE_TAC[ADD1] THEN
745 REPEAT(DISCH_THEN (fun th -> SUBST1_TAC th THEN ASSUME_TAC(SYM th))) THEN
746 REWRITE_TAC[ARITH_RULE `((2 * s + 1) - 1) DIV 2 = s`] THEN
747 MP_TAC(SPECL [`p:num`; `q:num`; `r:num`; `s:num`] RECIPROCITY_SIMPLE) THEN
748 ASM_SIMP_TAC[DISTINCT_PRIME_COPRIME; INT_POW_NEG; EVEN_MULT; legendre] THEN
749 REWRITE_TAC[DE_MORGAN_THM; NOT_ODD; INT_POW_ONE] THEN
750 MAP_EVERY ASM_CASES_TAC [`EVEN r`; `EVEN s`] THEN ASM_REWRITE_TAC[] THEN
751 SIMP_TAC[TAUT `~(a <=> b) <=> (a <=> ~b)`] THEN DISCH_THEN(K ALL_TAC) THEN
752 ASM_CASES_TAC `p is_quadratic_residue (mod q)` THEN
753 ASM_REWRITE_TAC[INT_MUL_LNEG; INT_MUL_RNEG; INT_NEG_NEG; INT_MUL_LID]);;