@@ -3,8 +3,9 @@ Copyright (c) 2024 Chris Birkbeck. All rights reserved.
33Released under Apache 2.0 license as described in the file LICENSE.
44Authors: Chris Birkbeck, David Loeffler
55-/
6+ import Mathlib.Algebra.EuclideanDomain.Int
67import Mathlib.NumberTheory.ModularForms.SlashInvariantForms
7- import Mathlib.NumberTheory.ModularForms.CongruenceSubgroups
8+ import Mathlib.RingTheory.EuclideanDomain
89
910/-!
1011# Eisenstein Series
@@ -25,52 +26,139 @@ import Mathlib.NumberTheory.ModularForms.CongruenceSubgroups
2526
2627noncomputable section
2728
28- open ModularForm UpperHalfPlane Complex Matrix CongruenceSubgroup
29+ open ModularForm UpperHalfPlane Complex Matrix CongruenceSubgroup Set
2930
3031open scoped MatrixGroups
3132
3233namespace EisensteinSeries
3334
34- variable (N : ℕ) (a : Fin 2 → ZMod N)
35+ variable (N r : ℕ) (a : Fin 2 → ZMod N)
3536
3637section gammaSet_def
3738
38- /-- The set of pairs of coprime integers congruent to `a` mod `N`. -/
39- def gammaSet := {v : Fin 2 → ℤ | (↑) ∘ v = a ∧ IsCoprime (v 0 ) (v 1 )}
39+ /-- The set of pairs of integers congruent to `a` mod `N` and with `gcd` equal to `r `. -/
40+ def gammaSet := {v : Fin 2 → ℤ | (↑) ∘ v = a ∧ (v 0 ).gcd (v 1 ) = r }
4041
4142open scoped Function in -- required for scoped `on` notation
42- lemma pairwise_disjoint_gammaSet : Pairwise (Disjoint on gammaSet N) := by
43+ lemma pairwise_disjoint_gammaSet : Pairwise (Disjoint on gammaSet N r ) := by
4344 refine fun u v huv ↦ ?_
4445 contrapose! huv
4546 obtain ⟨f, hf⟩ := Set.not_disjoint_iff.mp huv
4647 exact hf.1 .1 .symm.trans hf.2 .1
4748
4849/-- For level `N = 1`, the gamma sets are all equal. -/
49- lemma gammaSet_one_eq (a a' : Fin 2 → ZMod 1 ) : gammaSet 1 a = gammaSet 1 a' :=
50+ lemma gammaSet_one_const (a a' : Fin 2 → ZMod 1 ) : gammaSet 1 r a = gammaSet 1 r a' :=
5051 congr_arg _ (Subsingleton.elim _ _)
5152
53+ /-- For level `N = 1`, the gamma sets simplify to only a `gcd` condition. -/
54+ lemma gammaSet_one_eq (a : Fin 2 → ZMod 1 ) :
55+ gammaSet 1 r a = {v : Fin 2 → ℤ | (v 0 ).gcd (v 1 ) = r} := by
56+ simp [gammaSet, Subsingleton.eq_zero]
57+
58+ lemma gammaSet_one_mem_iff (v : Fin 2 → ℤ) : v ∈ gammaSet 1 r 0 ↔ (v 0 ).gcd (v 1 ) = r := by
59+ simp [gammaSet, Subsingleton.eq_zero]
60+
5261/-- For level `N = 1`, the gamma sets are all equivalent; this is the equivalence. -/
53- def gammaSet_one_equiv (a a' : Fin 2 → ZMod 1 ) : gammaSet 1 a ≃ gammaSet 1 a' :=
54- Equiv.setCongr (gammaSet_one_eq a a')
62+ def gammaSet_one_equiv (a a' : Fin 2 → ZMod 1 ) : gammaSet 1 r a ≃ gammaSet 1 r a' :=
63+ Equiv.setCongr (gammaSet_one_const r a a')
64+
65+ /-- The map from `Fin 2 → ℤ` sending `![a,b]` to `a.gcd b`. -/
66+ abbrev finGcdMap (v : Fin 2 → ℤ) : ℕ := (v 0 ).gcd (v 1 )
67+
68+ lemma finGcdMap_div {r : ℕ} [NeZero r] (v : Fin 2 → ℤ) (hv : finGcdMap v = r) :
69+ IsCoprime ((v / r) 0 ) ((v / r) 1 ) := by
70+ rw [← hv]
71+ apply isCoprime_div_gcd_div_gcd_of_gcd_ne_zero
72+ have := NeZero.ne r
73+ aesop
74+
75+ lemma finGcdMap_smul {r : ℕ} (a : ℤ) {v : Fin 2 → ℤ} (hv : finGcdMap v = r) :
76+ finGcdMap (a • v) = a.natAbs * r := by
77+ simp [finGcdMap, Int.gcd_mul_left, hv]
78+
79+ /-- An abbreviation of the map which divides a integer vector by an integer. -/
80+ abbrev divIntMap (r : ℤ) {m : ℕ} (v : Fin m → ℤ) : Fin m → ℤ := v / r
81+
82+ lemma mem_gammaSet_one (v : Fin 2 → ℤ) : v ∈ gammaSet 1 1 0 ↔ IsCoprime (v 0 ) (v 1 ) := by
83+ rw [gammaSet_one_mem_iff, Int.isCoprime_iff_gcd_eq_one]
84+
85+ lemma gammaSet_div_gcd {r : ℕ} {v : Fin 2 → ℤ} (hv : v ∈ (gammaSet 1 r 0 )) (i : Fin 2 ) :
86+ (r : ℤ) ∣ v i := by
87+ fin_cases i <;> simp [← hv.2 , Int.gcd_dvd_left, Int.gcd_dvd_right]
88+
89+ lemma gammaSet_div_gcd_to_gammaSet10_bijection (r : ℕ) [NeZero r] :
90+ Set.BijOn (divIntMap r) (gammaSet 1 r 0 ) (gammaSet 1 1 0 ) := by
91+ refine ⟨?_, ?_, ?_⟩
92+ · intro x hx
93+ simp only [divIntMap, mem_gammaSet_one] at *
94+ exact finGcdMap_div _ hx.2
95+ · intro x hx v hv hv2
96+ ext i
97+ exact (Int.ediv_left_inj (gammaSet_div_gcd hx i) (gammaSet_div_gcd hv i)).mp
98+ (congr_fun hv2 i)
99+ · intro x hx
100+ use r • x
101+ simp only [nsmul_eq_mul, divIntMap, Int.cast_natCast]
102+ constructor
103+ · rw [mem_gammaSet_one, Int.isCoprime_iff_gcd_eq_one] at hx
104+ exact ⟨Subsingleton.eq_zero _, by simp [Int.gcd_mul_left, hx]⟩
105+ · ext i
106+ simp_all [NeZero.ne r]
107+
108+ lemma gammaSet_eq_gcd_mul_divIntMap {r : ℕ} {v : Fin 2 → ℤ} (hv : v ∈ gammaSet 1 r 0 ) :
109+ v = r • (divIntMap r v) := by
110+ by_cases hr : r = 0
111+ · have hv := hv.2
112+ simp only [hr, Fin.isValue, Int.gcd_eq_zero_iff, CharP.cast_eq_zero, zero_smul] at *
113+ ext i
114+ fin_cases i <;> simp [hv]
115+ · ext i
116+ simp_all [Pi.smul_apply, divIntMap, ← Int.mul_ediv_assoc _ (gammaSet_div_gcd hv i)]
117+
118+ /-- The equivalence between `gammaSet 1 r 0` and `gammaSet 1 1 0` for non-zero `r`. -/
119+ def gammaSetDivGcdEquiv (r : ℕ) [NeZero r] : gammaSet 1 r 0 ≃ gammaSet 1 1 0 :=
120+ Set.BijOn.equiv _ (gammaSet_div_gcd_to_gammaSet10_bijection r)
121+
122+ /-- The equivalence between `(Fin 2 → ℤ)` and `Σ n : ℕ, gammaSet 1 n 0)` . -/
123+ def gammaSetDivGcdSigmaEquiv : (Fin 2 → ℤ) ≃ (Σ r : ℕ, gammaSet 1 r 0 ) := by
124+ apply (Equiv.sigmaFiberEquiv finGcdMap).symm.trans
125+ refine Equiv.sigmaCongrRight fun b => ?_
126+ apply Equiv.setCongr
127+ rw [gammaSet_one_eq]
128+ rfl
129+
130+ @[simp]
131+ lemma gammaSetDivGcdSigmaEquiv_symm_eq (v : Σ r : ℕ, gammaSet 1 r 0 ) :
132+ (gammaSetDivGcdSigmaEquiv.symm v) = v.2 := rfl
55133
56134end gammaSet_def
57135
58- variable {N a}
136+ variable {N a r} [NeZero r]
59137
60138section gamma_action
61139
140+ /-- Right-multiplying a vector by a matrix in `SL(2, ℤ)` doesn't change its gcd. -/
141+ lemma vecMulSL_gcd {v : Fin 2 → ℤ} (hab : finGcdMap v = r) (A : SL(2 , ℤ)) :
142+ finGcdMap (v ᵥ* A.1 ) = r := by
143+ have hvr : v = r • (v / r) := by
144+ ext i
145+ refine Eq.symm (Int.mul_ediv_cancel' ?_)
146+ fin_cases i <;> simp [← hab, Int.gcd_dvd_left, Int.gcd_dvd_right]
147+ rw [hvr, smul_vecMul]
148+ simpa using finGcdMap_smul r (Int.isCoprime_iff_gcd_eq_one.mp ((finGcdMap_div v hab).vecMulSL A))
149+
62150/-- Right-multiplying by `γ ∈ SL(2, ℤ)` sends `gammaSet N a` to `gammaSet N (a ᵥ* γ)`. -/
63- lemma vecMul_SL2_mem_gammaSet {v : Fin 2 → ℤ} (hv : v ∈ gammaSet N a) (γ : SL( 2 , ℤ)) :
64- v ᵥ* γ ∈ gammaSet N (a ᵥ* γ) := by
65- refine ⟨?_, hv.2 .vecMulSL γ⟩
151+ lemma vecMul_SL2_mem_gammaSet {v : Fin 2 → ℤ} (hv : v ∈ gammaSet N r a)
152+ (γ : SL( 2 , ℤ)) : v ᵥ* γ ∈ gammaSet N r (a ᵥ* γ) := by
153+ refine ⟨?_, vecMulSL_gcd hv.2 γ⟩
66154 have := RingHom.map_vecMul (m := Fin 2 ) (n := Fin 2 ) (Int.castRingHom (ZMod N)) γ v
67155 simp only [eq_intCast, Int.coe_castRingHom] at this
68156 simp_rw [Function.comp_def, this, hv.1 ]
69157 simp
70158
71159variable (a) in
72160/-- The bijection between `GammaSets` given by multiplying by an element of `SL(2, ℤ)`. -/
73- def gammaSetEquiv (γ : SL(2 , ℤ)) : gammaSet N a ≃ gammaSet N (a ᵥ* γ) where
161+ def gammaSetEquiv (γ : SL(2 , ℤ)) : gammaSet N r a ≃ gammaSet N r (a ᵥ* γ) where
74162 toFun v := ⟨v.1 ᵥ* γ, vecMul_SL2_mem_gammaSet v.2 γ⟩
75163 invFun v := ⟨v.1 ᵥ* ↑(γ⁻¹), by
76164 have := vecMul_SL2_mem_gammaSet v.2 γ⁻¹
@@ -106,7 +194,7 @@ end eisSummand
106194variable (a)
107195
108196/-- An Eisenstein series of weight `k` and level `Γ(N)`, with congruence condition `a`. -/
109- def _root_.eisensteinSeries (k : ℤ) (z : ℍ) : ℂ := ∑' x : gammaSet N a, eisSummand k x z
197+ def _root_.eisensteinSeries (k : ℤ) (z : ℍ) : ℂ := ∑' x : gammaSet N 1 a, eisSummand k x z
110198
111199lemma eisensteinSeries_slash_apply (k : ℤ) (γ : SL(2 , ℤ)) :
112200 eisensteinSeries a k ∣[k] γ = eisensteinSeries (a ᵥ* γ) k := by
0 commit comments