Skip to content

Commit 6210e2d

Browse files
feat: port NumberTheory.LegendreSymbol.ZModChar (#4205)
Co-authored-by: Parcly Taxel <reddeloostw@gmail.com> Co-authored-by: Jeremy Tan Jie Rui <reddeloostw@gmail.com>
1 parent 76a0306 commit 6210e2d

File tree

2 files changed

+231
-0
lines changed

2 files changed

+231
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,6 +1751,7 @@ import Mathlib.NumberTheory.Divisors
17511751
import Mathlib.NumberTheory.Fermat4
17521752
import Mathlib.NumberTheory.FrobeniusNumber
17531753
import Mathlib.NumberTheory.LegendreSymbol.MulCharacter
1754+
import Mathlib.NumberTheory.LegendreSymbol.ZModChar
17541755
import Mathlib.NumberTheory.LucasLehmer
17551756
import Mathlib.NumberTheory.LucasPrimality
17561757
import Mathlib.NumberTheory.Multiplicity
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
/-
2+
Copyright (c) 2022 Michael Stoll. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Michael Stoll
5+
6+
! This file was ported from Lean 3 source module number_theory.legendre_symbol.zmod_char
7+
! leanprover-community/mathlib commit 70fd9563a21e7b963887c9360bd29b2393e6225a
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Data.Int.Range
12+
import Mathlib.Data.ZMod.Basic
13+
import Mathlib.NumberTheory.LegendreSymbol.MulCharacter
14+
15+
/-!
16+
# Quadratic characters on ℤ/nℤ
17+
18+
This file defines some quadratic characters on the rings ℤ/4ℤ and ℤ/8ℤ.
19+
20+
We set them up to be of type `MulChar (ZMod n) ℤ`, where `n` is `4` or `8`.
21+
22+
## Tags
23+
24+
quadratic character, zmod
25+
-/
26+
27+
28+
/-!
29+
### Quadratic characters mod 4 and 8
30+
31+
We define the primitive quadratic characters `χ₄`on `ZMod 4`
32+
and `χ₈`, `χ₈'` on `ZMod 8`.
33+
-/
34+
35+
36+
namespace ZMod
37+
38+
section QuadCharModP
39+
40+
/-- Define the nontrivial quadratic character on `ZMod 4`, `χ₄`.
41+
It corresponds to the extension `ℚ(√-1)/ℚ`. -/
42+
@[simps]
43+
def χ₄ : MulChar (ZMod 4) ℤ where
44+
toFun := (![0, 1, 0, -1] : ZMod 4 → ℤ)
45+
map_one' := rfl
46+
map_mul' := by decide
47+
map_nonunit' := by decide
48+
#align zmod.χ₄ ZMod.χ₄
49+
50+
/-- `χ₄` takes values in `{0, 1, -1}` -/
51+
theorem isQuadratic_χ₄ : χ₄.IsQuadratic := by
52+
intro a
53+
-- Porting note: was `decide!`
54+
fin_cases a
55+
all_goals decide
56+
#align zmod.is_quadratic_χ₄ ZMod.isQuadratic_χ₄
57+
58+
/-- The value of `χ₄ n`, for `n : ℕ`, depends only on `n % 4`. -/
59+
theorem χ₄_nat_mod_four (n : ℕ) : χ₄ n = χ₄ (n % 4 : ℕ) := by rw [← ZMod.nat_cast_mod n 4]
60+
#align zmod.χ₄_nat_mod_four ZMod.χ₄_nat_mod_four
61+
62+
/-- The value of `χ₄ n`, for `n : ℤ`, depends only on `n % 4`. -/
63+
theorem χ₄_int_mod_four (n : ℤ) : χ₄ n = χ₄ (n % 4 : ℤ) := by
64+
rw [← ZMod.int_cast_mod n 4]
65+
norm_cast
66+
#align zmod.χ₄_int_mod_four ZMod.χ₄_int_mod_four
67+
68+
/-- An explicit description of `χ₄` on integers / naturals -/
69+
theorem χ₄_int_eq_if_mod_four (n : ℤ) :
70+
χ₄ n = if n % 2 = 0 then 0 else if n % 4 = 1 then 1 else -1 := by
71+
have help : ∀ m : ℤ, 0 ≤ m → m < 4 → χ₄ m = if m % 2 = 0 then 0 else if m = 1 then 1 else -1 := by
72+
decide
73+
rw [← Int.emod_emod_of_dvd n (by norm_num : (2 : ℤ) ∣ 4), ← ZMod.int_cast_mod n 4]
74+
exact help (n % 4) (Int.emod_nonneg n (by norm_num)) (Int.emod_lt n (by norm_num))
75+
#align zmod.χ₄_int_eq_if_mod_four ZMod.χ₄_int_eq_if_mod_four
76+
77+
theorem χ₄_nat_eq_if_mod_four (n : ℕ) :
78+
χ₄ n = if n % 2 = 0 then 0 else if n % 4 = 1 then 1 else -1 := by
79+
exact_mod_cast χ₄_int_eq_if_mod_four n
80+
#align zmod.χ₄_nat_eq_if_mod_four ZMod.χ₄_nat_eq_if_mod_four
81+
82+
/-- Alternative description of `χ₄ n` for odd `n : ℕ` in terms of powers of `-1` -/
83+
theorem χ₄_eq_neg_one_pow {n : ℕ} (hn : n % 2 = 1) : χ₄ n = (-1) ^ (n / 2) := by
84+
rw [χ₄_nat_eq_if_mod_four]
85+
simp only [hn, Nat.one_ne_zero, if_false]
86+
--porting note: `nth_rw` didn't work here anymore. artifical workaround
87+
nth_rw 3 [← Nat.div_add_mod n 4]
88+
nth_rw 3 [(by norm_num : 4 = 2 * 2)]
89+
rw [mul_assoc, add_comm, Nat.add_mul_div_left _ _ (by norm_num : 0 < 2), pow_add, pow_mul,
90+
neg_one_sq, one_pow, mul_one]
91+
have help : ∀ m : ℕ, m < 4 → m % 2 = 1 → ite (m = 1) (1 : ℤ) (-1) = (-1) ^ (m / 2) := by decide
92+
exact
93+
help (n % 4) (Nat.mod_lt n (by norm_num))
94+
((Nat.mod_mod_of_dvd n (by norm_num : 24)).trans hn)
95+
#align zmod.χ₄_eq_neg_one_pow ZMod.χ₄_eq_neg_one_pow
96+
97+
/-- If `n % 4 = 1`, then `χ₄ n = 1`. -/
98+
theorem χ₄_nat_one_mod_four {n : ℕ} (hn : n % 4 = 1) : χ₄ n = 1 := by
99+
rw [χ₄_nat_mod_four, hn]
100+
rfl
101+
#align zmod.χ₄_nat_one_mod_four ZMod.χ₄_nat_one_mod_four
102+
103+
/-- If `n % 4 = 3`, then `χ₄ n = -1`. -/
104+
theorem χ₄_nat_three_mod_four {n : ℕ} (hn : n % 4 = 3) : χ₄ n = -1 := by
105+
rw [χ₄_nat_mod_four, hn]
106+
rfl
107+
#align zmod.χ₄_nat_three_mod_four ZMod.χ₄_nat_three_mod_four
108+
109+
/-- If `n % 4 = 1`, then `χ₄ n = 1`. -/
110+
theorem χ₄_int_one_mod_four {n : ℤ} (hn : n % 4 = 1) : χ₄ n = 1 := by
111+
rw [χ₄_int_mod_four, hn]
112+
rfl
113+
#align zmod.χ₄_int_one_mod_four ZMod.χ₄_int_one_mod_four
114+
115+
/-- If `n % 4 = 3`, then `χ₄ n = -1`. -/
116+
theorem χ₄_int_three_mod_four {n : ℤ} (hn : n % 4 = 3) : χ₄ n = -1 := by
117+
rw [χ₄_int_mod_four, hn]
118+
rfl
119+
#align zmod.χ₄_int_three_mod_four ZMod.χ₄_int_three_mod_four
120+
121+
/-- If `n % 4 = 1`, then `(-1)^(n/2) = 1`. -/
122+
theorem neg_one_pow_div_two_of_one_mod_four {n : ℕ} (hn : n % 4 = 1) : (-1 : ℤ) ^ (n / 2) = 1 := by
123+
rw [← χ₄_eq_neg_one_pow (Nat.odd_of_mod_four_eq_one hn), ← nat_cast_mod, hn]
124+
rfl
125+
#align zmod.neg_one_pow_div_two_of_one_mod_four ZMod.neg_one_pow_div_two_of_one_mod_four
126+
127+
/-- If `n % 4 = 3`, then `(-1)^(n/2) = -1`. -/
128+
theorem neg_one_pow_div_two_of_three_mod_four {n : ℕ} (hn : n % 4 = 3) :
129+
(-1 : ℤ) ^ (n / 2) = -1 := by
130+
rw [← χ₄_eq_neg_one_pow (Nat.odd_of_mod_four_eq_three hn), ← nat_cast_mod, hn]
131+
rfl
132+
#align zmod.neg_one_pow_div_two_of_three_mod_four ZMod.neg_one_pow_div_two_of_three_mod_four
133+
134+
lemma test : IsUnit (7 : ZMod 8) := by
135+
have : (7 : ZMod 8) * 7 = 1 := by decide
136+
exact isUnit_of_mul_eq_one (7 : ZMod 8) 7 this
137+
138+
set_option maxHeartbeats 250000 in -- Porting note: otherwise `map_nonunit'` times out
139+
/-- Define the first primitive quadratic character on `ZMod 8`, `χ₈`.
140+
It corresponds to the extension `ℚ(√2)/ℚ`. -/
141+
@[simps]
142+
def χ₈ : MulChar (ZMod 8) ℤ where
143+
toFun := (![0, 1, 0, -1, 0, -1, 0, 1] : ZMod 8 → ℤ)
144+
map_one' := rfl
145+
map_mul' := by decide
146+
map_nonunit' := by decide
147+
#align zmod.χ₈ ZMod.χ₈
148+
149+
/-- `χ₈` takes values in `{0, 1, -1}` -/
150+
theorem isQuadratic_χ₈ : χ₈.IsQuadratic := by
151+
intro a
152+
--porting note: was `decide!`
153+
fin_cases a
154+
all_goals decide
155+
#align zmod.is_quadratic_χ₈ ZMod.isQuadratic_χ₈
156+
157+
/-- The value of `χ₈ n`, for `n : ℕ`, depends only on `n % 8`. -/
158+
theorem χ₈_nat_mod_eight (n : ℕ) : χ₈ n = χ₈ (n % 8 : ℕ) := by rw [← ZMod.nat_cast_mod n 8]
159+
#align zmod.χ₈_nat_mod_eight ZMod.χ₈_nat_mod_eight
160+
161+
/-- The value of `χ₈ n`, for `n : ℤ`, depends only on `n % 8`. -/
162+
theorem χ₈_int_mod_eight (n : ℤ) : χ₈ n = χ₈ (n % 8 : ℤ) := by
163+
rw [← ZMod.int_cast_mod n 8]
164+
norm_cast
165+
#align zmod.χ₈_int_mod_eight ZMod.χ₈_int_mod_eight
166+
167+
/-- An explicit description of `χ₈` on integers / naturals -/
168+
theorem χ₈_int_eq_if_mod_eight (n : ℤ) :
169+
χ₈ n = if n % 2 = 0 then 0 else if n % 8 = 1 ∨ n % 8 = 7 then 1 else -1 := by
170+
have help :
171+
∀ m : ℤ, 0 ≤ m → m < 8 → χ₈ m = if m % 2 = 0 then 0 else if m = 1 ∨ m = 7 then 1 else -1 := by
172+
decide
173+
rw [← Int.emod_emod_of_dvd n (by norm_num : (2 : ℤ) ∣ 8), ← ZMod.int_cast_mod n 8]
174+
exact help (n % 8) (Int.emod_nonneg n (by norm_num)) (Int.emod_lt n (by norm_num))
175+
#align zmod.χ₈_int_eq_if_mod_eight ZMod.χ₈_int_eq_if_mod_eight
176+
177+
theorem χ₈_nat_eq_if_mod_eight (n : ℕ) :
178+
χ₈ n = if n % 2 = 0 then 0 else if n % 8 = 1 ∨ n % 8 = 7 then 1 else -1 := by
179+
exact_mod_cast χ₈_int_eq_if_mod_eight n
180+
#align zmod.χ₈_nat_eq_if_mod_eight ZMod.χ₈_nat_eq_if_mod_eight
181+
182+
set_option maxHeartbeats 250000 in -- Porting note: otherwise `map_nonunit'` times out
183+
/-- Define the second primitive quadratic character on `ZMod 8`, `χ₈'`.
184+
It corresponds to the extension `ℚ(√-2)/ℚ`. -/
185+
@[simps]
186+
def χ₈' : MulChar (ZMod 8) ℤ where
187+
toFun := (![0, 1, 0, 1, 0, -1, 0, -1] : ZMod 8 → ℤ)
188+
map_one' := rfl
189+
map_mul' := by decide
190+
map_nonunit' := by decide
191+
#align zmod.χ₈' ZMod.χ₈'
192+
193+
/-- `χ₈'` takes values in `{0, 1, -1}` -/
194+
theorem isQuadratic_χ₈' : χ₈'.IsQuadratic := by
195+
intro a
196+
--porting note: was `decide!`
197+
fin_cases a
198+
all_goals decide
199+
#align zmod.is_quadratic_χ₈' ZMod.isQuadratic_χ₈'
200+
201+
/-- An explicit description of `χ₈'` on integers / naturals -/
202+
theorem χ₈'_int_eq_if_mod_eight (n : ℤ) :
203+
χ₈' n = if n % 2 = 0 then 0 else if n % 8 = 1 ∨ n % 8 = 3 then 1 else -1 := by
204+
have help :
205+
∀ m : ℤ, 0 ≤ m → m < 8 → χ₈' m = if m % 2 = 0 then 0 else if m = 1 ∨ m = 3 then 1 else -1 := by
206+
decide
207+
rw [← Int.emod_emod_of_dvd n (by norm_num : (2 : ℤ) ∣ 8), ← ZMod.int_cast_mod n 8]
208+
exact help (n % 8) (Int.emod_nonneg n (by norm_num)) (Int.emod_lt n (by norm_num))
209+
#align zmod.χ₈'_int_eq_if_mod_eight ZMod.χ₈'_int_eq_if_mod_eight
210+
211+
theorem χ₈'_nat_eq_if_mod_eight (n : ℕ) :
212+
χ₈' n = if n % 2 = 0 then 0 else if n % 8 = 1 ∨ n % 8 = 3 then 1 else -1 := by
213+
exact_mod_cast χ₈'_int_eq_if_mod_eight n
214+
#align zmod.χ₈'_nat_eq_if_mod_eight ZMod.χ₈'_nat_eq_if_mod_eight
215+
216+
/-- The relation between `χ₄`, `χ₈` and `χ₈'` -/
217+
theorem χ₈'_eq_χ₄_mul_χ₈ (a : ZMod 8) : χ₈' a = χ₄ a * χ₈ a := by
218+
--porting note: was `decide!`
219+
fin_cases a
220+
all_goals decide
221+
#align zmod.χ₈'_eq_χ₄_mul_χ₈ ZMod.χ₈'_eq_χ₄_mul_χ₈
222+
223+
theorem χ₈'_int_eq_χ₄_mul_χ₈ (a : ℤ) : χ₈' a = χ₄ a * χ₈ a := by
224+
rw [← @cast_int_cast 8 (ZMod 4) _ 4 _ (by norm_num) a]
225+
exact χ₈'_eq_χ₄_mul_χ₈ a
226+
#align zmod.χ₈'_int_eq_χ₄_mul_χ₈ ZMod.χ₈'_int_eq_χ₄_mul_χ₈
227+
228+
end QuadCharModP
229+
230+
end ZMod

0 commit comments

Comments
 (0)