Skip to content

Commit 4599860

Browse files
committed
feat(NumberTheory/LSeries): polish some results on ZMod L-series (#16913)
Strengthen functional equation for L-series of a function mod N so it holds at s = 1 as well (in cases where s = 1 is not a pole). Also some minor stylistic cleanup / golfing.
1 parent 211cd6b commit 4599860

File tree

1 file changed

+45
-23
lines changed

1 file changed

+45
-23
lines changed

Mathlib/NumberTheory/LSeries/ZMod.lean

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ Authors: David Loeffler
66

77
import Mathlib.Analysis.Fourier.ZMod
88
import Mathlib.Analysis.NormedSpace.Connected
9-
import Mathlib.LinearAlgebra.Dimension.DivisionRing
109
import Mathlib.NumberTheory.LSeries.RiemannZeta
11-
import Mathlib.Topology.Algebra.Module.Cardinality
1210

1311
/-!
1412
# L-series of functions on `ZMod N`
@@ -34,7 +32,7 @@ for general functions; for the specific case of Dirichlet characters see
3432
`LFunction (𝓕 Φ) s`, where `𝓕` is the Fourier transform.
3533
-/
3634

37-
open HurwitzZeta Complex ZMod Finset Classical Topology Filter
35+
open HurwitzZeta Complex ZMod Finset Classical Topology Filter Set
3836

3937
open scoped Real
4038

@@ -70,7 +68,7 @@ lemma LFunction_eq_LSeries (Φ : ZMod N → ℂ) {s : ℂ} (hs : 1 < re s) :
7068
LFunction Φ s = LSeries (Φ ·) s := by
7169
rw [LFunction, LSeries, mul_sum, Nat.sumByResidueClasses (LSeriesSummable_of_one_lt_re Φ hs) N]
7270
congr 1 with j
73-
have : (j.val / N : ℝ) ∈ Set.Icc 0 1 := Set.mem_Icc.mpr ⟨by positivity,
71+
have : (j.val / N : ℝ) ∈ Set.Icc 0 1 := mem_Icc.mpr ⟨by positivity,
7472
(div_le_one (Nat.cast_pos.mpr <| NeZero.pos _)).mpr <| Nat.cast_le.mpr (val_lt j).le⟩
7573
rw [toAddCircle_apply, ← (hasSum_hurwitzZeta_of_one_lt_re this hs).tsum_eq, ← mul_assoc,
7674
← tsum_mul_left]
@@ -119,6 +117,24 @@ lemma LFunction_residue_one (Φ : ZMod N → ℂ) :
119117
exact ((continuous_neg.const_cpow (Or.inl <| NeZero.ne _)).tendsto _).mono_left
120118
nhdsWithin_le_nhds
121119

120+
local notation "𝕖" => stdAddChar
121+
122+
/--
123+
The `LFunction` of the function `x ↦ e (j * x)`, where `e : ZMod N → ℂ` is the standard additive
124+
character, agrees with `expZeta (j / N)` on `1 < re s`. Private since it is a stepping-stone to
125+
the more general result `LFunction_stdAddChar_eq_expZeta` below.
126+
-/
127+
private lemma LFunction_stdAddChar_eq_expZeta_of_one_lt_re (j : ZMod N) {s : ℂ} (hs : 1 < s.re) :
128+
LFunction (fun k ↦ 𝕖 (j * k)) s = expZeta (ZMod.toAddCircle j) s := by
129+
rw [toAddCircle_apply, ← (hasSum_expZeta_of_one_lt_re (j.val / N) hs).tsum_eq,
130+
LFunction_eq_LSeries _ hs, LSeries]
131+
congr 1 with n
132+
rw [LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs), ofReal_div, ofReal_natCast,
133+
ofReal_natCast, mul_assoc, div_mul_eq_mul_div, stdAddChar_apply]
134+
have := ZMod.toCircle_intCast (N := N) (j.val * n)
135+
conv_rhs at this => rw [Int.cast_mul, Int.cast_natCast, Int.cast_natCast, mul_div_assoc]
136+
rw [← this, Int.cast_mul, Int.cast_natCast, Int.cast_natCast, natCast_zmod_val]
137+
122138
/--
123139
The `LFunction` of the function `x ↦ e (j * x)`, where `e : ZMod N → ℂ` is the standard additive
124140
character, is `expZeta (j / N)`.
@@ -127,16 +143,16 @@ Note this is not at all obvious from the definitions, and we prove it by analyti
127143
from the convergence range.
128144
-/
129145
lemma LFunction_stdAddChar_eq_expZeta (j : ZMod N) (s : ℂ) (hjs : j ≠ 0 ∨ s ≠ 1) :
130-
LFunction (fun k ↦ stdAddChar (j * k)) s = expZeta (ZMod.toAddCircle j) s := by
131-
let U := if j = 0 then {z : ℂ | z ≠ 1} else Set.univ -- region of analyticity of both functions
146+
LFunction (fun k ↦ 𝕖 (j * k)) s = expZeta (ZMod.toAddCircle j) s := by
147+
let U := if j = 0 then {z : ℂ | z ≠ 1} else univ -- region of analyticity of both functions
132148
let V := {z : ℂ | 1 < re z} -- convergence region
133149
have hUo : IsOpen U := by
134150
by_cases h : j = 0
135151
· simpa only [h, ↓reduceIte, U] using isOpen_compl_singleton
136152
· simp only [h, ↓reduceIte, isOpen_univ, U]
137153
let f := LFunction (fun k ↦ stdAddChar (j * k))
138154
let g := expZeta (toAddCircle j)
139-
have hU {u} : u ∈ U ↔ u ≠ 1 ∨ j ≠ 0 := by simp only [Set.mem_ite_univ_right, U]; tauto
155+
have hU {u} : u ∈ U ↔ u ≠ 1 ∨ j ≠ 0 := by simp only [mem_ite_univ_right, U]; tauto
140156
-- hypotheses for uniqueness of analytic continuation
141157
have hf : AnalyticOn ℂ f U := by
142158
refine DifferentiableOn.analyticOn (fun u hu ↦ ?_) hUo
@@ -158,41 +174,47 @@ lemma LFunction_stdAddChar_eq_expZeta (j : ZMod N) (s : ℂ) (hjs : j ≠ 0 ∨
158174
-- apply uniqueness result
159175
refine hf.eqOn_of_preconnected_of_eventuallyEq hg hUc hUmem ?_ hUmem'
160176
-- now remains to prove equality on `1 < re s`
161-
filter_upwards [hV] with z hz
162-
dsimp only [f, g]
163-
rw [toAddCircle_apply, ← (hasSum_expZeta_of_one_lt_re (j.val / N) hz).tsum_eq,
164-
LFunction_eq_LSeries _ hz, LSeries]
165-
congr 1 with n
166-
rw [LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hz), ofReal_div, ofReal_natCast,
167-
ofReal_natCast, mul_assoc, div_mul_eq_mul_div, stdAddChar_apply]
168-
have := ZMod.toCircle_intCast (N := N) (j.val * n)
169-
conv_rhs at this => rw [Int.cast_mul, Int.cast_natCast, Int.cast_natCast, mul_div_assoc]
170-
rw [← this, Int.cast_mul, Int.cast_natCast, Int.cast_natCast, natCast_zmod_val]
177+
filter_upwards [hV] with z using LFunction_stdAddChar_eq_expZeta_of_one_lt_re _
171178

172179
/-- Explicit formula for the L-function of `𝓕 Φ`, where `𝓕` is the discrete Fourier transform. -/
173-
lemma LFunction_dft (Φ : ZMod N → ℂ) {s : ℂ} (hs : s ≠ 1) :
180+
lemma LFunction_dft (Φ : ZMod N → ℂ) {s : ℂ} (hs : Φ 0 = 0s ≠ 1) :
174181
LFunction (𝓕 Φ) s = ∑ j : ZMod N, Φ j * expZeta (toAddCircle (-j)) s := by
175-
simp only [← LFunction_stdAddChar_eq_expZeta _ _ (Or.inr hs), LFunction, mul_sum]
176-
rw [sum_comm, dft_def]
182+
have (j : ZMod N) : Φ j * LFunction (fun k ↦ 𝕖 (-j * k)) s =
183+
Φ j * expZeta (toAddCircle (-j)) s := by
184+
by_cases h : -j ≠ 0 ∨ s ≠ 1
185+
· rw [LFunction_stdAddChar_eq_expZeta _ _ h]
186+
· simp only [neg_ne_zero, not_or, not_not] at h
187+
rw [h.1, show Φ 0 = 0 by tauto, zero_mul, zero_mul]
188+
simp only [LFunction, ← this, mul_sum]
189+
rw [dft_def, sum_comm]
177190
simp only [sum_mul, mul_sum, Circle.smul_def, smul_eq_mul, stdAddChar_apply, ← mul_assoc]
178191
congr 1 with j
179192
congr 1 with k
180193
rw [mul_assoc (Φ _), mul_comm (Φ _), neg_mul]
181194

182195
/-- Functional equation for `ZMod` L-functions, in terms of discrete Fourier transform. -/
183-
theorem LFunction_one_sub (Φ : ZMod N → ℂ) {s : ℂ} (hs : ∀ (n : ℕ), s ≠ -↑n) (hs' : s ≠ 1) :
196+
theorem LFunction_one_sub (Φ : ZMod N → ℂ) {s : ℂ}
197+
(hs : ∀ (n : ℕ), s ≠ -n) (hs' : Φ 0 = 0 ∨ s ≠ 1) :
184198
LFunction Φ (1 - s) = N ^ (s - 1) * (2 * π) ^ (-s) * Gamma s *
185199
(cexp (π * I * s / 2) * LFunction (𝓕 Φ) s
186200
+ cexp (-π * I * s / 2) * LFunction (𝓕 fun x ↦ Φ (-x)) s) := by
187201
rw [LFunction]
188-
simp only [hurwitzZeta_one_sub _ hs (Or.inr hs'), mul_assoc _ _ (Gamma s)]
202+
have (j : ZMod N) : Φ j * hurwitzZeta (toAddCircle j) (1 - s) = Φ j *
203+
((2 * π) ^ (-s) * Gamma s * (cexp (-π * I * s / 2) *
204+
expZeta (toAddCircle j) s + cexp (π * I * s / 2) * expZeta (-toAddCircle j) s)) := by
205+
rcases eq_or_ne j 0 with rfl | hj
206+
· rcases hs' with hΦ | hs'
207+
· simp only [hΦ, zero_mul]
208+
· rw [hurwitzZeta_one_sub _ hs (Or.inr hs')]
209+
· rw [hurwitzZeta_one_sub _ hs (Or.inl <| toAddCircle_eq_zero.not.mpr hj)]
210+
simp only [this, mul_assoc _ _ (Gamma s)]
189211
-- get rid of Gamma terms and power of N
190212
generalize (2 * π) ^ (-s) * Gamma s = C
191213
simp_rw [← mul_assoc, mul_comm _ C, mul_assoc, ← mul_sum, ← mul_assoc, mul_comm _ C, mul_assoc,
192214
neg_sub]
193215
congr 2
194216
-- now gather sum terms
195-
rw [LFunction_dft _ hs', LFunction_dft _ hs']
217+
rw [LFunction_dft _ hs', LFunction_dft _ (hs'.imp_left <| by simp only [neg_zero, imp_self])]
196218
conv_rhs => enter [2, 2]; rw [← (Equiv.neg _).sum_comp _ _ (by simp), Equiv.neg_apply]
197219
simp_rw [neg_neg, mul_sum, ← sum_add_distrib, ← mul_assoc, mul_comm _ (Φ _), mul_assoc,
198220
← mul_add, map_neg, add_comm]

0 commit comments

Comments
 (0)