Skip to content

Commit 6985e17

Browse files
committed
feat: port NumberTheory.Cyclotomic.Discriminant (#5413)
1 parent 489a049 commit 6985e17

File tree

2 files changed

+217
-0
lines changed

2 files changed

+217
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,6 +2289,7 @@ import Mathlib.NumberTheory.ClassNumber.AdmissibleAbs
22892289
import Mathlib.NumberTheory.ClassNumber.AdmissibleAbsoluteValue
22902290
import Mathlib.NumberTheory.ClassNumber.AdmissibleCardPowDegree
22912291
import Mathlib.NumberTheory.Cyclotomic.Basic
2292+
import Mathlib.NumberTheory.Cyclotomic.Discriminant
22922293
import Mathlib.NumberTheory.Cyclotomic.PrimitiveRoots
22932294
import Mathlib.NumberTheory.Dioph
22942295
import Mathlib.NumberTheory.DiophantineApproximation
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/-
2+
Copyright (c) 2022 Riccardo Brasca. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Riccardo Brasca
5+
6+
! This file was ported from Lean 3 source module number_theory.cyclotomic.discriminant
7+
! leanprover-community/mathlib commit 3e068ece210655b7b9a9477c3aff38a492400aa1
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.NumberTheory.Cyclotomic.PrimitiveRoots
12+
import Mathlib.RingTheory.Discriminant
13+
14+
/-!
15+
# Discriminant of cyclotomic fields
16+
We compute the discriminant of a `p ^ n`-th cyclotomic extension.
17+
18+
## Main results
19+
* `IsCyclotomicExtension.discr_odd_prime` : if `p` is an odd prime such that
20+
`IsCyclotomicExtension {p} K L` and `Irreducible (cyclotomic p K)`, then
21+
`discr K (hζ.powerBasis K).basis = (-1) ^ ((p - 1) / 2) * p ^ (p - 2)` for any
22+
`hζ : IsPrimitiveRoot ζ p`.
23+
24+
-/
25+
26+
27+
universe u v
28+
29+
local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue #2220
30+
31+
open Algebra Polynomial Nat IsPrimitiveRoot PowerBasis
32+
33+
open scoped Polynomial Cyclotomic
34+
35+
namespace IsPrimitiveRoot
36+
37+
variable {n : ℕ+} {K : Type u} [Field K] [CharZero K] {ζ : K}
38+
39+
variable [ce : IsCyclotomicExtension {n} ℚ K]
40+
41+
/-- The discriminant of the power basis given by a primitive root of unity `ζ` is the same as the
42+
discriminant of the power basis given by `ζ - 1`. -/
43+
theorem discr_zeta_eq_discr_zeta_sub_one (hζ : IsPrimitiveRoot ζ n) :
44+
discr ℚ (hζ.powerBasis ℚ).basis = discr ℚ (hζ.subOnePowerBasis ℚ).basis := by
45+
haveI : NumberField K := @NumberField.mk _ _ _ (IsCyclotomicExtension.finiteDimensional {n} ℚ K)
46+
have H₁ : (aeval (hζ.powerBasis ℚ).gen) (X - 1 : ℤ[X]) = (hζ.subOnePowerBasis ℚ).gen := by simp
47+
have H₂ : (aeval (hζ.subOnePowerBasis ℚ).gen) (X + 1 : ℤ[X]) = (hζ.powerBasis ℚ).gen := by simp
48+
refine' discr_eq_discr_of_toMatrix_coeff_isIntegral _ (fun i j => toMatrix_isIntegral H₁ _ _ _ _)
49+
fun i j => toMatrix_isIntegral H₂ _ _ _ _
50+
· exact hζ.isIntegral n.pos
51+
· refine' minpoly.isIntegrallyClosed_eq_field_fractions' (K := ℚ) (hζ.isIntegral n.pos)
52+
· exact isIntegral_sub (hζ.isIntegral n.pos) isIntegral_one
53+
· refine' minpoly.isIntegrallyClosed_eq_field_fractions' (K := ℚ) _
54+
exact isIntegral_sub (hζ.isIntegral n.pos) isIntegral_one
55+
#align is_primitive_root.discr_zeta_eq_discr_zeta_sub_one IsPrimitiveRoot.discr_zeta_eq_discr_zeta_sub_one
56+
57+
end IsPrimitiveRoot
58+
59+
namespace IsCyclotomicExtension
60+
61+
variable {p : ℕ+} {k : ℕ} {K : Type u} {L : Type v} {ζ : L} [Field K] [Field L]
62+
63+
variable [Algebra K L]
64+
65+
/-- If `p` is a prime and `IsCyclotomicExtension {p ^ (k + 1)} K L`, then the discriminant of
66+
`hζ.powerBasis K` is `(-1) ^ ((p ^ (k + 1).totient) / 2) * p ^ (p ^ k * ((p - 1) * (k + 1) - 1))`
67+
if `Irreducible (cyclotomic (p ^ (k + 1)) K))`, and `p ^ (k + 1) ≠ 2`. -/
68+
theorem discr_prime_pow_ne_two [IsCyclotomicExtension {p ^ (k + 1)} K L] [hp : Fact (p : ℕ).Prime]
69+
(hζ : IsPrimitiveRoot ζ ↑(p ^ (k + 1))) (hirr : Irreducible (cyclotomic (↑(p ^ (k + 1)) : ℕ) K))
70+
(hk : p ^ (k + 1) ≠ 2) : discr K (hζ.powerBasis K).basis =
71+
(-1) ^ ((p ^ (k + 1) : ℕ).totient / 2) * p ^ ((p : ℕ) ^ k * ((p - 1) * (k + 1) - 1)) := by
72+
haveI hne := IsCyclotomicExtension.ne_zero' (p ^ (k + 1)) K L
73+
-- Porting note: these two instances are not automatically synthesised and must be constructed
74+
haveI mf : Module.Finite K L := finiteDimensional {p ^ (k + 1)} K L
75+
haveI se : IsSeparable K L := (isGalois (p ^ (k + 1)) K L).to_isSeparable
76+
rw [discr_powerBasis_eq_norm, finrank L hirr, hζ.powerBasis_gen _, ←
77+
hζ.minpoly_eq_cyclotomic_of_irreducible hirr, PNat.pow_coe,
78+
totient_prime_pow hp.out (succ_pos k), succ_sub_one]
79+
have coe_two : ((2 : ℕ+) : ℕ) = 2 := rfl
80+
have hp2 : p = 2 → k ≠ 0 := by
81+
rintro rfl rfl
82+
exact absurd rfl hk
83+
congr 1
84+
· rcases eq_or_ne p 2 with (rfl | hp2)
85+
· rcases Nat.exists_eq_succ_of_ne_zero (hp2 rfl) with ⟨k, rfl⟩
86+
rw [coe_two, succ_sub_succ_eq_sub, tsub_zero, mul_one]; simp only [_root_.pow_succ]
87+
rw [mul_assoc, Nat.mul_div_cancel_left _ zero_lt_two, Nat.mul_div_cancel_left _ zero_lt_two]
88+
cases k
89+
· simp
90+
· norm_num; simp_rw [_root_.pow_succ, (even_two.mul_right _).neg_one_pow,
91+
((even_two.mul_right _).mul_right _).neg_one_pow]
92+
· replace hp2 : (p : ℕ) ≠ 2
93+
· rwa [Ne.def, ← coe_two, PNat.coe_inj]
94+
have hpo : Odd (p : ℕ) := hp.out.odd_of_ne_two hp2
95+
obtain ⟨a, ha⟩ := (hp.out.even_sub_one hp2).two_dvd
96+
rw [ha, mul_left_comm, mul_assoc, Nat.mul_div_cancel_left _ two_pos,
97+
Nat.mul_div_cancel_left _ two_pos, mul_right_comm, pow_mul, (hpo.pow.mul _).neg_one_pow,
98+
pow_mul, hpo.pow.neg_one_pow]; · norm_cast
99+
refine' Nat.Even.sub_odd _ (even_two_mul _) odd_one
100+
rw [mul_left_comm, ← ha]
101+
exact one_le_mul (one_le_pow _ _ hp.1.pos) (succ_le_iff.2 <| tsub_pos_of_lt hp.1.one_lt)
102+
· have H := congr_arg (@derivative K _) (cyclotomic_prime_pow_mul_X_pow_sub_one K p k)
103+
rw [derivative_mul, derivative_sub, derivative_one, sub_zero, derivative_X_pow, C_eq_nat_cast,
104+
derivative_sub, derivative_one, sub_zero, derivative_X_pow, C_eq_nat_cast, ← PNat.pow_coe,
105+
hζ.minpoly_eq_cyclotomic_of_irreducible hirr] at H
106+
replace H := congr_arg (fun P => aeval ζ P) H
107+
simp only [aeval_add, aeval_mul, minpoly.aeval, MulZeroClass.zero_mul, add_zero, aeval_nat_cast,
108+
_root_.map_sub, aeval_one, aeval_X_pow] at H
109+
replace H := congr_arg (Algebra.norm K) H
110+
have hnorm : (norm K) (ζ ^ (p : ℕ) ^ k - 1) = (p : K) ^ (p : ℕ) ^ k := by
111+
by_cases hp : p = 2
112+
· exact_mod_cast hζ.pow_sub_one_norm_prime_pow_of_ne_zero hirr le_rfl (hp2 hp)
113+
· exact_mod_cast hζ.pow_sub_one_norm_prime_ne_two hirr le_rfl hp
114+
rw [MonoidHom.map_mul, hnorm, MonoidHom.map_mul, ← map_natCast (algebraMap K L),
115+
Algebra.norm_algebraMap, finrank L hirr] at H
116+
conv_rhs at H => -- Porting note: need to drill down to successfully rewrite the totient
117+
enter [1, 2]
118+
rw [PNat.pow_coe, ← succ_eq_add_one, totient_prime_pow hp.out (succ_pos k), Nat.sub_one,
119+
Nat.pred_succ]
120+
rw [← hζ.minpoly_eq_cyclotomic_of_irreducible hirr, map_pow, hζ.norm_eq_one hk hirr, one_pow,
121+
mul_one, PNat.pow_coe, cast_pow, ← pow_mul, ← mul_assoc, mul_comm (k + 1), mul_assoc] at H
122+
have := mul_pos (succ_pos k) (tsub_pos_of_lt hp.out.one_lt)
123+
rw [← succ_pred_eq_of_pos this, mul_succ, pow_add _ _ ((p : ℕ) ^ k)] at H
124+
replace H := (mul_left_inj' fun h => ?_).1 H
125+
· simp only [H, mul_comm _ (k + 1)]; norm_cast
126+
· -- Porting note: was `replace h := pow_eq_zero h; rw [coe_coe] at h; simpa using hne.1`
127+
have := hne.1
128+
rw [PNat.pow_coe, Nat.cast_pow, Ne.def, pow_eq_zero_iff (by linarith)] at this
129+
exact absurd (pow_eq_zero h) this
130+
#align is_cyclotomic_extension.discr_prime_pow_ne_two IsCyclotomicExtension.discr_prime_pow_ne_two
131+
132+
/-- If `p` is a prime and `IsCyclotomicExtension {p ^ (k + 1)} K L`, then the discriminant of
133+
`hζ.powerBasis K` is `(-1) ^ (p ^ k * (p - 1) / 2) * p ^ (p ^ k * ((p - 1) * (k + 1) - 1))`
134+
if `Irreducible (cyclotomic (p ^ (k + 1)) K))`, and `p ^ (k + 1) ≠ 2`. -/
135+
theorem discr_prime_pow_ne_two' [IsCyclotomicExtension {p ^ (k + 1)} K L] [hp : Fact (p : ℕ).Prime]
136+
(hζ : IsPrimitiveRoot ζ ↑(p ^ (k + 1))) (hirr : Irreducible (cyclotomic (↑(p ^ (k + 1)) : ℕ) K))
137+
(hk : p ^ (k + 1) ≠ 2) : discr K (hζ.powerBasis K).basis =
138+
(-1) ^ ((p : ℕ) ^ k * (p - 1) / 2) * p ^ ((p : ℕ) ^ k * ((p - 1) * (k + 1) - 1)) :=
139+
by simpa [totient_prime_pow hp.out (succ_pos k)] using discr_prime_pow_ne_two hζ hirr hk
140+
#align is_cyclotomic_extension.discr_prime_pow_ne_two' IsCyclotomicExtension.discr_prime_pow_ne_two'
141+
142+
/-- If `p` is a prime and `IsCyclotomicExtension {p ^ k} K L`, then the discriminant of
143+
`hζ.powerBasis K` is `(-1) ^ ((p ^ k).totient / 2) * p ^ (p ^ (k - 1) * ((p - 1) * k - 1))`
144+
if `Irreducible (cyclotomic (p ^ k) K))`. Beware that in the cases `p ^ k = 1` and `p ^ k = 2`
145+
the formula uses `1 / 2 = 0` and `0 - 1 = 0`. It is useful only to have a uniform result.
146+
See also `IsCyclotomicExtension.discr_prime_pow_eq_unit_mul_pow`. -/
147+
theorem discr_prime_pow [hcycl : IsCyclotomicExtension {p ^ k} K L] [hp : Fact (p : ℕ).Prime]
148+
(hζ : IsPrimitiveRoot ζ ↑(p ^ k)) (hirr : Irreducible (cyclotomic (↑(p ^ k) : ℕ) K)) :
149+
discr K (hζ.powerBasis K).basis =
150+
(-1) ^ ((p ^ k : ℕ).totient / 2) * p ^ ((p : ℕ) ^ (k - 1) * ((p - 1) * k - 1)) := by
151+
cases' k with k k
152+
· simp only [coe_basis, _root_.pow_zero, powerBasis_gen, totient_one, mul_zero, mul_one,
153+
show 1 / 2 = 0 by rfl, discr, traceMatrix]
154+
have hζone : ζ = 1 := by simpa using hζ
155+
rw [hζ.powerBasis_dim _, hζone, ← (algebraMap K L).map_one,
156+
minpoly.eq_X_sub_C_of_algebraMap_inj _ (algebraMap K L).injective, natDegree_X_sub_C]
157+
simp only [traceMatrix, map_one, one_pow, Matrix.det_unique, traceForm_apply, mul_one]
158+
rw [← (algebraMap K L).map_one, trace_algebraMap, finrank _ hirr]
159+
simp; norm_num
160+
· by_cases hk : p ^ (k + 1) = 2
161+
· have coe_two : 2 = ((2 : ℕ+) : ℕ) := rfl
162+
have hp : p = 2 := by
163+
rw [← PNat.coe_inj, PNat.pow_coe, ← pow_one 2] at hk
164+
replace hk :=
165+
eq_of_prime_pow_eq (prime_iff.1 hp.out) (prime_iff.1 Nat.prime_two) (succ_pos _) hk
166+
rwa [coe_two, PNat.coe_inj] at hk
167+
rw [hp, ← PNat.coe_inj, PNat.pow_coe] at hk
168+
nth_rw 2 [← pow_one 2] at hk
169+
replace hk := Nat.pow_right_injective rfl.le hk
170+
rw [add_left_eq_self] at hk
171+
rw [hp, hk] at hζ; norm_num at hζ; rw [← coe_two] at hζ
172+
rw [coe_basis, powerBasis_gen]; simp only [hp, hk]; norm_num
173+
rw [← coe_two, totient_two, show 1 / 2 = 0 by rfl, _root_.pow_zero]
174+
-- Porting note: the goal at this point is `(discr K fun i ↦ ζ ^ ↑i) = 1`.
175+
-- This `simp_rw` is needed so the next `rw` can rewrite the type of `i` from
176+
-- `Fin (natDegree (minpoly K ζ))` to `Fin 1`
177+
simp_rw [hζ.eq_neg_one_of_two_right, show (-1 : L) = algebraMap K L (-1) by simp]
178+
rw [hζ.eq_neg_one_of_two_right, show (-1 : L) = algebraMap K L (-1) by simp,
179+
minpoly.eq_X_sub_C_of_algebraMap_inj _ (algebraMap K L).injective, natDegree_X_sub_C]
180+
simp only [discr, traceMatrix_apply, Matrix.det_unique, Fin.default_eq_zero, Fin.val_zero,
181+
_root_.pow_zero, traceForm_apply, mul_one]
182+
rw [← (algebraMap K L).map_one, trace_algebraMap, finrank _ hirr, hp, hk]; norm_num
183+
simp [← coe_two]
184+
· exact discr_prime_pow_ne_two hζ hirr hk
185+
#align is_cyclotomic_extension.discr_prime_pow IsCyclotomicExtension.discr_prime_pow
186+
187+
/-- If `p` is a prime and `IsCyclotomicExtension {p ^ k} K L`, then there are `u : ℤˣ` and
188+
`n : ℕ` such that the discriminant of `hζ.powerBasis K` is `u * p ^ n`. Often this is enough and
189+
less cumbersome to use than `IsCyclotomicExtension.discr_prime_pow`. -/
190+
theorem discr_prime_pow_eq_unit_mul_pow [IsCyclotomicExtension {p ^ k} K L]
191+
[hp : Fact (p : ℕ).Prime] (hζ : IsPrimitiveRoot ζ ↑(p ^ k))
192+
(hirr : Irreducible (cyclotomic (↑(p ^ k) : ℕ) K)) :
193+
∃ (u : ℤˣ) (n : ℕ), discr K (hζ.powerBasis K).basis = u * p ^ n := by
194+
rw [discr_prime_pow hζ hirr]
195+
by_cases heven : Even ((p ^ k : ℕ).totient / 2)
196+
· refine' ⟨1, (p : ℕ) ^ (k - 1) * ((p - 1) * k - 1), by rw [heven.neg_one_pow]; norm_num⟩
197+
· exact ⟨-1, (p : ℕ) ^ (k - 1) * ((p - 1) * k - 1), by
198+
rw [(odd_iff_not_even.2 heven).neg_one_pow]; norm_num⟩
199+
#align is_cyclotomic_extension.discr_prime_pow_eq_unit_mul_pow IsCyclotomicExtension.discr_prime_pow_eq_unit_mul_pow
200+
201+
/-- If `p` is an odd prime and `IsCyclotomicExtension {p} K L`, then
202+
`discr K (hζ.powerBasis K).basis = (-1) ^ ((p - 1) / 2) * p ^ (p - 2)` if
203+
`Irreducible (cyclotomic p K)`. -/
204+
theorem discr_odd_prime [IsCyclotomicExtension {p} K L] [hp : Fact (p : ℕ).Prime]
205+
(hζ : IsPrimitiveRoot ζ p) (hirr : Irreducible (cyclotomic p K)) (hodd : p ≠ 2) :
206+
discr K (hζ.powerBasis K).basis = (-1) ^ (((p : ℕ) - 1) / 2) * p ^ ((p : ℕ) - 2) := by
207+
have : IsCyclotomicExtension {p ^ (0 + 1)} K L := by
208+
rw [zero_add, pow_one]
209+
infer_instance
210+
have hζ' : IsPrimitiveRoot ζ ↑(p ^ (0 + 1)) := by simpa using hζ
211+
convert discr_prime_pow_ne_two hζ' (by simpa [hirr]) (by simp [hodd]) using 2
212+
· rw [zero_add, pow_one, totient_prime hp.out]
213+
· rw [_root_.pow_zero, one_mul, zero_add, mul_one, Nat.sub_sub]
214+
#align is_cyclotomic_extension.discr_odd_prime IsCyclotomicExtension.discr_odd_prime
215+
216+
end IsCyclotomicExtension

0 commit comments

Comments
 (0)