Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit abb635f

Browse files
feat(number_theory/legendre_symbol/quadratic_reciprocity): switch to Gauss sum proof, clean-up (#16171)
This PR is (for now) the final step in the quest to change the proof of Quadratic Reciprocity from using the Gauss and Eisenstein lemmas to using the results for quadratic characters of general finite fields obtained from properties of the quadratic Gauss sum. In addition, there is some clean-up of the file and some further results (e.g., on the quadratic character of `-2` and some versions of the law of quadratic reciprocity that are probably easier to use), and the documentation has been extended. The Gauss and Eisenstein lemmas have been moved to `number_theory/legendre_symbol/gauss_eisenstein_lemmas` (where the auxiliary results needed for them have already been residing). I have opened a [topic](https://leanprover.zulipchat.com/#narrow/stream/144837-PR-reviews/topic/.2316171.20renovate.20quadratic.20reciprocity/near/294460241) on this under "PR reviews".
1 parent fa6e024 commit abb635f

File tree

6 files changed

+274
-246
lines changed

6 files changed

+274
-246
lines changed

archive/imo/imo2008_q3.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ lemma p_lemma (p : ℕ) (hpp : nat.prime p) (hp_mod_4_eq_1 : p ≡ 1 [MOD 4]) (h
3333
begin
3434
haveI := fact.mk hpp,
3535
have hp_mod_4_ne_3 : p % 43, { linarith [(show p % 4 = 1, by exact hp_mod_4_eq_1)] },
36-
obtain ⟨y, hy⟩ := (zmod.exists_sq_eq_neg_one_iff p).mpr hp_mod_4_ne_3,
36+
obtain ⟨y, hy⟩ := zmod.exists_sq_eq_neg_one_iff.mpr hp_mod_4_ne_3,
3737

3838
let m := zmod.val_min_abs y,
3939
let n := int.nat_abs m,

src/number_theory/legendre_symbol/gauss_eisenstein_lemmas.lean

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ Copyright (c) 2018 Chris Hughes. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Chris Hughes
55
-/
6-
import field_theory.finite.basic
7-
import data.zmod.basic
6+
import number_theory.legendre_symbol.quadratic_reciprocity
87

98
/-!
109
# Lemmas of Gauss and Eisenstein
@@ -153,6 +152,22 @@ lemma gauss_lemma_aux (p : ℕ) [hp : fact p.prime] [fact (p % 2 = 1)]
153152
exact nat.div_lt_self hp.1.pos dec_trivial)).1 $
154153
by simpa using gauss_lemma_aux₁ p hap
155154

155+
/-- Gauss' lemma. The legendre symbol can be computed by considering the number of naturals less
156+
than `p/2` such that `(a * x) % p > p / 2` -/
157+
lemma gauss_lemma {p : ℕ} [fact p.prime] {a : ℤ} (hp : p ≠ 2) (ha0 : (a : zmod p) ≠ 0) :
158+
legendre_sym p a = (-1) ^ ((Ico 1 (p / 2).succ).filter
159+
(λ x : ℕ, p / 2 < (a * x : zmod p).val)).card :=
160+
begin
161+
haveI hp' : fact (p % 2 = 1) := ⟨nat.prime.mod_two_eq_one_iff_ne_two.mpr hp⟩,
162+
have : (legendre_sym p a : zmod p) = (((-1)^((Ico 1 (p / 2).succ).filter
163+
(λ x : ℕ, p / 2 < (a * x : zmod p).val)).card : ℤ) : zmod p) :=
164+
by { rw [legendre_sym_eq_pow, legendre_symbol.gauss_lemma_aux p ha0]; simp },
165+
cases legendre_sym_eq_one_or_neg_one p ha0;
166+
cases neg_one_pow_eq_or ℤ ((Ico 1 (p / 2).succ).filter
167+
(λ x : ℕ, p / 2 < (a * x : zmod p).val)).card;
168+
simp [*, ne_neg_self p one_ne_zero, (ne_neg_self p one_ne_zero).symm] at *
169+
end
170+
156171
private lemma eisenstein_lemma_aux₁ (p : ℕ) [fact p.prime] [hp2 : fact (p % 2 = 1)]
157172
{a : ℕ} (hap : (a : zmod p) ≠ 0) :
158173
((∑ x in Ico 1 (p / 2).succ, a * x : ℕ) : zmod 2) =
@@ -276,6 +291,17 @@ begin
276291
simp only [card_Ico, tsub_zero, succ_sub_succ_eq_sub]
277292
end
278293

294+
lemma eisenstein_lemma {p : ℕ} [fact p.prime] (hp : p ≠ 2) {a : ℕ} (ha1 : a % 2 = 1)
295+
(ha0 : (a : zmod p) ≠ 0) :
296+
legendre_sym p a = (-1)^∑ x in Ico 1 (p / 2).succ, (x * a) / p :=
297+
begin
298+
haveI hp' : fact (p % 2 = 1) := ⟨nat.prime.mod_two_eq_one_iff_ne_two.mpr hp⟩,
299+
have ha0' : ((a : ℤ) : zmod p) ≠ 0 := by { norm_cast, exact ha0 },
300+
rw [neg_one_pow_eq_pow_mod_two, gauss_lemma hp ha0', neg_one_pow_eq_pow_mod_two,
301+
(by norm_cast : ((a : ℤ) : zmod p) = (a : zmod p)),
302+
show _ = _, from legendre_symbol.eisenstein_lemma_aux p ha1 ha0]
303+
end
304+
279305
end legendre_symbol
280306

281307
end gauss_eisenstein

src/number_theory/legendre_symbol/quadratic_char.lean

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ It takes the value zero at zero; for non-zero argument `a : α`, it is `1`
3131
if `a` is a square, otherwise it is `-1`.
3232
3333
This only deserves the name "character" when it is multiplicative,
34-
e.g., when `α` is a finite field. See `quadratic_char_mul`.
34+
e.g., when `α` is a finite field. See `quadratic_char_fun_mul`.
3535
3636
We will later define `quadratic_char` to be a multiplicative character
3737
of type `mul_char F ℤ`, when the domain is a finite field `F`.
@@ -57,7 +57,7 @@ open mul_char
5757
variables {F : Type*} [field F] [fintype F] [decidable_eq F]
5858

5959
/-- Some basic API lemmas -/
60-
lemma quadratic_char_eq_zero_iff' {a : F} : quadratic_char_fun F a = 0 ↔ a = 0 :=
60+
lemma quadratic_char_fun_eq_zero_iff {a : F} : quadratic_char_fun F a = 0 ↔ a = 0 :=
6161
begin
6262
simp only [quadratic_char_fun],
6363
by_cases ha : a = 0,
@@ -67,15 +67,15 @@ begin
6767
end
6868

6969
@[simp]
70-
lemma quadratic_char_zero : quadratic_char_fun F 0 = 0 :=
70+
lemma quadratic_char_fun_zero : quadratic_char_fun F 0 = 0 :=
7171
by simp only [quadratic_char_fun, eq_self_iff_true, if_true, id.def]
7272

7373
@[simp]
74-
lemma quadratic_char_one : quadratic_char_fun F 1 = 1 :=
74+
lemma quadratic_char_fun_one : quadratic_char_fun F 1 = 1 :=
7575
by simp only [quadratic_char_fun, one_ne_zero, is_square_one, if_true, if_false, id.def]
7676

7777
/-- If `ring_char F = 2`, then `quadratic_char_fun F` takes the value `1` on nonzero elements. -/
78-
lemma quadratic_char_eq_one_of_char_two' (hF : ring_char F = 2) {a : F} (ha : a ≠ 0) :
78+
lemma quadratic_char_fun_eq_one_of_char_two (hF : ring_char F = 2) {a : F} (ha : a ≠ 0) :
7979
quadratic_char_fun F a = 1 :=
8080
begin
8181
simp only [quadratic_char_fun, ha, if_false, ite_eq_left_iff],
@@ -84,34 +84,34 @@ end
8484

8585
/-- If `ring_char F` is odd, then `quadratic_char_fun F a` can be computed in
8686
terms of `a ^ (fintype.card F / 2)`. -/
87-
lemma quadratic_char_eq_pow_of_char_ne_two' (hF : ring_char F ≠ 2) {a : F} (ha : a ≠ 0) :
87+
lemma quadratic_char_fun_eq_pow_of_char_ne_two (hF : ring_char F ≠ 2) {a : F} (ha : a ≠ 0) :
8888
quadratic_char_fun F a = if a ^ (fintype.card F / 2) = 1 then 1 else -1 :=
8989
begin
9090
simp only [quadratic_char_fun, ha, if_false],
9191
simp_rw finite_field.is_square_iff hF ha,
9292
end
9393

9494
/-- The quadratic character is multiplicative. -/
95-
lemma quadratic_char_mul (a b : F) :
95+
lemma quadratic_char_fun_mul (a b : F) :
9696
quadratic_char_fun F (a * b) = quadratic_char_fun F a * quadratic_char_fun F b :=
9797
begin
9898
by_cases ha : a = 0,
99-
{ rw [ha, zero_mul, quadratic_char_zero, zero_mul], },
99+
{ rw [ha, zero_mul, quadratic_char_fun_zero, zero_mul], },
100100
-- now `a ≠ 0`
101101
by_cases hb : b = 0,
102-
{ rw [hb, mul_zero, quadratic_char_zero, mul_zero], },
102+
{ rw [hb, mul_zero, quadratic_char_fun_zero, mul_zero], },
103103
-- now `a ≠ 0` and `b ≠ 0`
104104
have hab := mul_ne_zero ha hb,
105105
by_cases hF : ring_char F = 2,
106106
{ -- case `ring_char F = 2`
107-
rw [quadratic_char_eq_one_of_char_two' hF ha,
108-
quadratic_char_eq_one_of_char_two' hF hb,
109-
quadratic_char_eq_one_of_char_two' hF hab,
107+
rw [quadratic_char_fun_eq_one_of_char_two hF ha,
108+
quadratic_char_fun_eq_one_of_char_two hF hb,
109+
quadratic_char_fun_eq_one_of_char_two hF hab,
110110
mul_one], },
111111
{ -- case of odd characteristic
112-
rw [quadratic_char_eq_pow_of_char_ne_two' hF ha,
113-
quadratic_char_eq_pow_of_char_ne_two' hF hb,
114-
quadratic_char_eq_pow_of_char_ne_two' hF hab,
112+
rw [quadratic_char_fun_eq_pow_of_char_ne_two hF ha,
113+
quadratic_char_fun_eq_pow_of_char_ne_two hF hb,
114+
quadratic_char_fun_eq_pow_of_char_ne_two hF hab,
115115
mul_pow],
116116
cases finite_field.pow_dichotomy hF hb with hb' hb',
117117
{ simp only [hb', mul_one, eq_self_iff_true, if_true], },
@@ -126,15 +126,19 @@ variables (F)
126126
/-- The quadratic character as a multiplicative character. -/
127127
@[simps] def quadratic_char : mul_char F ℤ :=
128128
{ to_fun := quadratic_char_fun F,
129-
map_one' := quadratic_char_one,
130-
map_mul' := quadratic_char_mul,
131-
map_nonunit' := λ a ha, by { rw of_not_not (mt ne.is_unit ha), exact quadratic_char_zero, } }
129+
map_one' := quadratic_char_fun_one,
130+
map_mul' := quadratic_char_fun_mul,
131+
map_nonunit' := λ a ha, by { rw of_not_not (mt ne.is_unit ha), exact quadratic_char_fun_zero, } }
132132

133133
variables {F}
134134

135135
/-- The value of the quadratic character on `a` is zero iff `a = 0`. -/
136136
lemma quadratic_char_eq_zero_iff {a : F} : quadratic_char F a = 0 ↔ a = 0 :=
137-
quadratic_char_eq_zero_iff'
137+
quadratic_char_fun_eq_zero_iff
138+
139+
@[simp]
140+
lemma quadratic_char_zero : quadratic_char F 0 = 0 :=
141+
by simp only [quadratic_char_apply, quadratic_char_fun_zero]
138142

139143
/-- For nonzero `a : F`, `quadratic_char F a = 1 ↔ is_square a`. -/
140144
lemma quadratic_char_one_iff_is_square {a : F} (ha : a ≠ 0) :
@@ -181,15 +185,15 @@ lemma quadratic_char_exists_neg_one (hF : ring_char F ≠ 2) : ∃ a, quadratic_
181185
/-- If `ring_char F = 2`, then `quadratic_char F` takes the value `1` on nonzero elements. -/
182186
lemma quadratic_char_eq_one_of_char_two (hF : ring_char F = 2) {a : F} (ha : a ≠ 0) :
183187
quadratic_char F a = 1 :=
184-
quadratic_char_eq_one_of_char_two' hF ha
188+
quadratic_char_fun_eq_one_of_char_two hF ha
185189

186190
/-- If `ring_char F` is odd, then `quadratic_char F a` can be computed in
187191
terms of `a ^ (fintype.card F / 2)`. -/
188192
lemma quadratic_char_eq_pow_of_char_ne_two (hF : ring_char F ≠ 2) {a : F} (ha : a ≠ 0) :
189193
quadratic_char F a = if a ^ (fintype.card F / 2) = 1 then 1 else -1 :=
190-
quadratic_char_eq_pow_of_char_ne_two' hF ha
194+
quadratic_char_fun_eq_pow_of_char_ne_two hF ha
191195

192-
lemma quadratic_char_eq_pow_of_char_ne_two'' (hF : ring_char F ≠ 2) (a : F) :
196+
lemma quadratic_char_eq_pow_of_char_ne_two' (hF : ring_char F ≠ 2) (a : F) :
193197
(quadratic_char F a : F) = a ^ (fintype.card F / 2) :=
194198
begin
195199
by_cases ha : a = 0,
@@ -318,7 +322,7 @@ end
318322
lemma quadratic_char_two [decidable_eq F] (hF : ring_char F ≠ 2) :
319323
quadratic_char F 2 = χ₈ (fintype.card F) :=
320324
is_quadratic.eq_of_eq_coe (quadratic_char_is_quadratic F) is_quadratic_χ₈ hF
321-
((quadratic_char_eq_pow_of_char_ne_two'' hF 2).trans (finite_field.two_pow_card hF))
325+
((quadratic_char_eq_pow_of_char_ne_two' hF 2).trans (finite_field.two_pow_card hF))
322326

323327
/-- `2` is a square in `F` iff `#F` is not congruent to `3` or `5` mod `8`. -/
324328
lemma finite_field.is_square_two_iff :
@@ -394,7 +398,7 @@ begin
394398
exact ring.neg_one_ne_one_of_char_ne_two hF', },
395399
have hχ₂ : χ.is_quadratic := is_quadratic.comp (quadratic_char_is_quadratic F) _,
396400
have h := char.card_pow_card hχ₁ hχ₂ h hF',
397-
rw [← quadratic_char_eq_pow_of_char_ne_two'' hF'] at h,
401+
rw [← quadratic_char_eq_pow_of_char_ne_two' hF'] at h,
398402
exact (is_quadratic.eq_of_eq_coe (quadratic_char_is_quadratic F')
399403
(quadratic_char_is_quadratic F) hF' h).symm,
400404
end

0 commit comments

Comments
 (0)