From 23cbc1d8f1a50299ce32056633f263ef7e8c5838 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sat, 4 Apr 2026 00:31:36 +0100 Subject: [PATCH 01/43] save --- Mathlib.lean | 2 + Mathlib/NumberTheory/ModularForms/Basic.lean | 24 +++++ .../ModularForms/CongruenceSubgroups.lean | 4 + .../ModularForms/Discriminant.lean | 87 ++++++++++++++++++- .../ModularForms/EisensteinSeries/Basic.lean | 7 +- .../EisensteinSeries/QExpansion.lean | 7 +- .../NumberTheory/ModularForms/LevelOne.lean | 8 +- 7 files changed, 131 insertions(+), 8 deletions(-) diff --git a/Mathlib.lean b/Mathlib.lean index 293afedbdf27b2..c8637a2c3d8cc8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5578,6 +5578,7 @@ public import Mathlib.NumberTheory.ModularForms.Basic public import Mathlib.NumberTheory.ModularForms.BoundedAtCusp public import Mathlib.NumberTheory.ModularForms.Bounds public import Mathlib.NumberTheory.ModularForms.CongruenceSubgroups +public import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule public import Mathlib.NumberTheory.ModularForms.Cusps public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Delta @@ -5600,6 +5601,7 @@ public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold public import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable public import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.NormTrace public import Mathlib.NumberTheory.ModularForms.Petersson public import Mathlib.NumberTheory.ModularForms.QExpansion diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index daff18550bed69..3100c9f841d33d 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -370,6 +370,18 @@ lemma coe_intCast [Γ.HasDetPlusMinusOne] (z : ℤ) : lemma toSlashInvariantForm_intCast [Γ.HasDetPlusMinusOne] (z : ℤ) : (z : ModularForm Γ 0).toSlashInvariantForm = z := rfl +/-- Transport a modular form along an equality of subgroups. -/ +def ofSubgroupEq {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) : + ModularForm Γ' k where + toFun := f + slash_action_eq' A hA := f.slash_action_eq' A (h ▸ hA) + holo' := f.holo' + bdd_at_cusps' hc := f.bdd_at_cusps' (h ▸ hc) + +@[simp] +lemma ofSubgroupEq_apply {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) + (z : ℍ) : (f.ofSubgroupEq h) z = f z := rfl + end ModularForm namespace CuspForm @@ -504,6 +516,18 @@ instance (priority := 99) [FunLike F ℍ ℂ] [CuspFormClass F Γ k] : ModularFo holo := CuspFormClass.holo bdd_at_cusps f _ hc g hg := (CuspFormClass.zero_at_cusps f hc g hg).boundedAtFilter +/-- Transport a cusp form along an equality of subgroups. -/ +def ofSubgroupEq {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : CuspForm Γ k) : + CuspForm Γ' k where + toFun := f + slash_action_eq' A hA := f.slash_action_eq' A (h ▸ hA) + holo' := f.holo' + zero_at_cusps' hc := f.zero_at_cusps' (h ▸ hc) + +@[simp] +lemma ofSubgroupEq_apply {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : CuspForm Γ k) + (z : ℍ) : (f.ofSubgroupEq h) z = f z := rfl + end CuspForm namespace ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean b/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean index c2e8ed6841c1f1..bda2a576528cb1 100644 --- a/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean +++ b/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean @@ -69,6 +69,10 @@ theorem Gamma_one_top : Gamma 1 = ⊤ := by lemma mem_Gamma_one (γ : SL(2, ℤ)) : γ ∈ Γ(1) := by simp only [Gamma_one_top, Subgroup.mem_top] +/-- The GL-image of `Γ(1)` equals `𝒮ℒ` (the image of `SL(2, ℤ)` in `GL(2, ℝ)`). -/ +theorem Gamma_one_coe_eq_SL : (↑(Gamma 1) : Subgroup (GL (Fin 2) ℝ)) = 𝒮ℒ := by + change (Gamma 1).map (mapGL ℝ) = (mapGL ℝ).range; rw [Gamma_one_top, MonoidHom.range_eq_map] + theorem Gamma_zero_bot : Gamma 0 = ⊥ := rfl lemma ModularGroup_T_pow_mem_Gamma (N M : ℤ) (hNM : N ∣ M) : diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 6861c50bb5bb92..fbca87f567f656 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -11,6 +11,7 @@ public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Basic public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.E2.Transform public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.QExpansion /-! # The modular discriminant Δ @@ -35,7 +36,8 @@ be expressed as `q * ∏' (1 - q ^ (n + 1)) ^ 24` where `q = e ^ (2πiz)`. * [F. Diamond and J. Shurman, *A First Course in Modular Forms*][diamondshurman2005], section 1.2 -/ -open Function Complex Topology Filter SlashInvariantForm CongruenceSubgroup MatrixGroups +open Function Complex Topology Filter SlashInvariantForm SlashInvariantFormClass + CongruenceSubgroup MatrixGroups ModularFormClass open UpperHalfPlane hiding I @@ -192,6 +194,89 @@ def discriminantCuspForm : CuspForm 𝒮ℒ 12 where rw [slash_action_generators_SL2Z discriminant_S_invariant discriminant_T_invariant] exact discriminant_isZeroAtImInfty +/-- The infinite product `∏ (1 - q^(n+1))` is multipliable for `‖q‖ < 1`. -/ +private lemma multipliable_one_sub_pow {q : ℂ} (hq : ‖q‖ < 1) : + Multipliable fun i ↦ 1 - q ^ (i + 1) := by + rw [show (fun i ↦ 1 - q ^ (i + 1)) = (fun i ↦ 1 + (-q ^ (i + 1))) from by ext; ring] + apply multipliable_one_add_of_summable + simp only [norm_neg, norm_pow] + exact (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) + +/-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` +on `ball 0 (1/2)`. -/ +private lemma discriminant_cuspFunction_eqOn : + Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) := by + intro q hq + by_cases hq0 : q = 0 + · simp only [hq0, zero_mul] + exact Periodic.cuspFunction_zero_of_zero_at_inf one_pos + discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex + · have hqn : ‖q‖ < 1 := lt_trans (by simpa [dist_zero_right] using hq) (by norm_num) + have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 + rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, + comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] + -- eta_q n z = (qParam 1 z)^(n+1), and qParam(invQParam(q)) = q + have hqr := Periodic.qParam_right_inv one_ne_zero hq0 + have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by + simp [eta_q, hqr] + simp only [hqr, heta] + +/-- The partial products `∏_{i simp [differentiableOn_const] + | succ n ih => + simp_rw [Finset.prod_range_succ]; exact ih.mul (by fun_prop)) + Metric.isOpen_ball + have hmem := Metric.mem_ball_self (x := (0 : ℂ)) (by norm_num : (0 : ℝ) < 1 / 2) + -- (∏(1-q^(n+1)))^24 is differentiable as a power of a differentiable function + have h24 := (hdiff 0 hmem).pow (n := 24) + -- ∏(1-q^(n+1))^24 = (∏(1-q^(n+1)))^24 by tprod_pow, so congr gives differentiability + refine h24.congr (fun q hq ↦ ?_) (by simp) + exact (multipliable_one_sub_pow (lt_trans (by simpa [dist_zero_right] using hq) + (by norm_num : (1 : ℝ) / 2 < 1))).tprod_pow 24 + +/-- The first q-expansion coefficient of the modular discriminant is 1. -/ +lemma discriminant_qExpansion_coeff_one : + (qExpansion 1 (discriminantCuspForm : ℍ → ℂ)).coeff 1 = 1 := by + rw [qExpansion_coeff] + simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, + iteratedDeriv_zero] + have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) (1 / 2 : ℝ) := Metric.mem_ball_self (by norm_num) + change deriv (cuspFunction 1 Δ) 0 = 1 + rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem] + rw [derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem)] + have : derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 = + derivWithin id (Metric.ball 0 (1 / 2)) 0 * (∏' i, (1 - (0 : ℂ) ^ (i + 1)) ^ 24) + + id 0 * derivWithin (fun q ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 := + derivWithin_mul differentiableWithinAt_id' differentiableWithinAt_eta_prod_pow + rw [this, derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + simp + end end ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean index 386d86e4de8bbf..e6e4c33ee3bf95 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean @@ -26,7 +26,7 @@ noncomputable section namespace ModularForm -open EisensteinSeries CongruenceSubgroup Matrix.SpecialLinearGroup +open EisensteinSeries CongruenceSubgroup Matrix.SpecialLinearGroup MatrixGroups /-- This defines Eisenstein series as modular forms of weight `k`, level `Γ(N)` and congruence condition given by `a : Fin 2 → ZMod N`. -/ @@ -44,7 +44,8 @@ def eisensteinSeriesMF {k : ℤ} {N : ℕ} [NeZero N] (hk : 3 ≤ k) (a : Fin 2 /-- Normalised Eisenstein series of level 1 and weight `k`, here they have been scaled by `1/2` since we sum over coprime pairs. -/ -noncomputable def E {k : ℕ} (hk : 3 ≤ k) : ModularForm Γ(1) k := - (1 / 2 : ℂ) • eisensteinSeriesMF (mod_cast hk) 0 +noncomputable def E {k : ℕ} (hk : 3 ≤ k) : ModularForm 𝒮ℒ k := + ((1 / 2 : ℂ) • eisensteinSeriesMF (mod_cast hk) 0).ofSubgroupEq + CongruenceSubgroup.Gamma_one_coe_eq_SL end ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean index 96dab6415c09b5..158f8c89164524 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean @@ -43,7 +43,7 @@ public section open Set Metric TopologicalSpace Function Filter Complex ArithmeticFunction ModularForm EisensteinSeries -open scoped Topology Real Nat Complex Pointwise ArithmeticFunction.sigma +open scoped Topology Real Nat Complex Pointwise ArithmeticFunction.sigma MatrixGroups open _root_.UpperHalfPlane hiding I @@ -277,7 +277,8 @@ lemma EisensteinSeries.q_expansion_riemannZeta {k : ℕ} (hk : 3 ≤ k) (hk2 : E E hk z = 1 + (riemannZeta k)⁻¹ * (-2 * π * I) ^ k / (k - 1)! * ∑' n : ℕ+, σ (k - 1) n * cexp (2 * π * I * z) ^ (n : ℤ) := by have : eisensteinSeriesMF (Int.toNat_le.mp hk) 0 z = eisensteinSeriesSIF (N := 1) 0 k z := rfl - rw [E, ModularForm.IsGLPos.smul_apply, this, eisensteinSeriesSIF_apply 0 k z, eisensteinSeries] + rw [E, ModularForm.ofSubgroupEq_apply, ModularForm.IsGLPos.smul_apply, this, + eisensteinSeriesSIF_apply 0 k z, eisensteinSeries] have HE1 := tsum_eisSummand_eq_tsum_sigma_mul_cexp_pow hk hk2 z have HE2 := tsum_eisSummand_eq_riemannZeta_mul_eisensteinSeries hk z have z2 : riemannZeta k ≠ 0 := riemannZeta_ne_zero_of_one_lt_re <| by norm_cast; grind @@ -326,6 +327,8 @@ lemma EisensteinSeries.E_qExpansion_coeff {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k if m = 0 then 1 else -(2 * k / bernoulli k : ℂ) * (σ (k - 1) m) := by set β : ℂ := -(2 * k / bernoulli k : ℂ) set c : ℕ → ℂ := fun m ↦ if m = 0 then 1 else β * ↑(σ (k - 1) m) + haveI : ModularFormClass (ModularForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := + CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance suffices ∀ τ : ℍ, HasSum (fun m ↦ c m • 𝕢 (1 : ℝ) τ ^ m) (E hk τ) from (qExpansion_coeff_unique one_pos one_mem_strictPeriods_SL2Z this m).symm intro τ diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne.lean index f62bd3810ea1c2..30c515d4933a0b 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne.lean @@ -104,12 +104,16 @@ lemma levelOne_weight_zero_const [ModularFormClass F Γ(1) 0] (f : F) : end ModularFormClass -lemma ModularForm.levelOne_weight_zero_rank_one : Module.rank ℂ (ModularForm Γ(1) 0) = 1 := by +lemma ModularForm.levelOne_weight_zero_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 0) = 1 := by + haveI : ModularFormClass (ModularForm 𝒮ℒ 0) Γ(1) 0 := + Gamma_one_coe_eq_SL ▸ inferInstance refine rank_eq_one (const 1) (by simp [DFunLike.ne_iff]) fun g ↦ ?_ obtain ⟨c', hc'⟩ := levelOne_weight_zero_const g aesop lemma ModularForm.levelOne_neg_weight_rank_zero (hk : k < 0) : - Module.rank ℂ (ModularForm Γ(1) k) = 0 := by + Module.rank ℂ (ModularForm 𝒮ℒ k) = 0 := by + haveI : ModularFormClass (ModularForm 𝒮ℒ k) Γ(1) k := + Gamma_one_coe_eq_SL ▸ inferInstance refine rank_eq_zero_iff.mpr fun f ↦ ⟨_, one_ne_zero, ?_⟩ simpa [← coe_eq_zero_iff] using levelOne_neg_weight_eq_zero hk f From 1548cacc125e261f1d66152aae1d53ef3005ba13 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 08:22:54 +0100 Subject: [PATCH 02/43] feat(NumberTheory/ModularForms): add cusp form submodule and level one dimension formula Adds `CuspFormSubmodule.lean` providing the cusp form submodule of modular forms together with API, and `DimensionFormulas/LevelOne.lean` proving the classical dimension formula for spaces of level one modular forms. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/CuspFormSubmodule.lean | 143 ++++++ .../DimensionFormulas/LevelOne.lean | 463 ++++++++++++++++++ 2 files changed, 606 insertions(+) create mode 100644 Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean create mode 100644 Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean new file mode 100644 index 00000000000000..b75d24bcfa9c34 --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -0,0 +1,143 @@ +/- +Copyright (c) 2026 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +import Mathlib.NumberTheory.ModularForms.QExpansion +import Mathlib.NumberTheory.ModularForms.LevelOne +import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion + +/-! +# Cusp form submodule and IsCuspForm predicate + +This file defines the inclusion of cusp forms into modular forms as a linear map, the cusp form +submodule of modular forms, and the `IsCuspForm` predicate. It also provides a direct constructor +`ModularForm.toCuspForm` for building cusp forms from modular forms with vanishing constant +q-expansion coefficient (for `𝒮ℒ`). + +## Main definitions + +* `CuspForm.toModularFormₗ`: the inclusion `CuspForm Γ k →ₗ[ℂ] ModularForm Γ k`. +* `ModularForm.cuspFormSubmodule`: the submodule of `ModularForm Γ k` consisting of cusp forms. +* `ModularForm.IsCuspForm`: predicate that a modular form lies in the cusp form submodule. +* `ModularForm.toCuspForm`: builds a `CuspForm 𝒮ℒ k` from a `ModularForm` whose q-expansion + has vanishing constant term. + +## Main results + +* `CuspForm.toModularFormₗ_injective`: the inclusion is injective. +* `CuspForm.equivCuspFormSubmodule`: `CuspForm Γ k ≃ₗ[ℂ] cuspFormSubmodule Γ k`. +* `ModularForm.isCuspForm_iff_coeffZero_eq_zero`: for `𝒮ℒ`, `IsCuspForm` is equivalent to the + q-expansion having vanishing constant term. +-/ + +open UpperHalfPlane ModularForm Complex SlashInvariantForm SlashInvariantFormClass + ModularFormClass MatrixGroups OnePoint Filter Topology + +noncomputable section + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +namespace CuspForm + +/-- The inclusion of cusp forms into modular forms, as a ℂ-linear map. -/ +def toModularFormₗ [Γ.HasDetOne] : CuspForm Γ k →ₗ[ℂ] ModularForm Γ k where + toFun f := + { toSlashInvariantForm := f.toSlashInvariantForm + holo' := f.holo' + bdd_at_cusps' := fun hc g hg ↦ (f.zero_at_cusps' hc g hg).boundedAtFilter } + map_add' _ _ := by ext; rfl + map_smul' _ _ := by ext; rfl + +@[simp] +lemma toModularFormₗ_apply [Γ.HasDetOne] (f : CuspForm Γ k) (z : ℍ) : + (toModularFormₗ f) z = f z := rfl + +lemma toModularFormₗ_injective [Γ.HasDetOne] : + Function.Injective (toModularFormₗ : CuspForm Γ k → ModularForm Γ k) := + fun _ _ h ↦ DFunLike.ext _ _ fun z ↦ congr_fun (congr_arg DFunLike.coe h) z + +end CuspForm + +namespace ModularForm + +/-- The submodule of `ModularForm Γ k` consisting of cusp forms, defined as the range of +the inclusion `CuspForm.toModularFormₗ`. -/ +def cuspFormSubmodule [Γ.HasDetOne] : Submodule ℂ (ModularForm Γ k) := + LinearMap.range (CuspForm.toModularFormₗ) + +/-- A modular form is a cusp form if it lies in the cusp form submodule. -/ +def IsCuspForm [Γ.HasDetOne] (f : ModularForm Γ k) : Prop := + f ∈ cuspFormSubmodule (Γ := Γ) (k := k) + +/-- The cusp form submodule is linearly equivalent to the type of cusp forms. -/ +def CuspForm.equivCuspFormSubmodule [Γ.HasDetOne] : + CuspForm Γ k ≃ₗ[ℂ] cuspFormSubmodule (Γ := Γ) (k := k) := + LinearEquiv.ofInjective CuspForm.toModularFormₗ CuspForm.toModularFormₗ_injective + +/-- A modular form is a cusp form if and only if it vanishes at every cusp. This is the +general characterization valid for any subgroup. -/ +lemma isCuspForm_iff [Γ.HasDetOne] (f : ModularForm Γ k) : + IsCuspForm f ↔ ∀ {c : OnePoint ℝ}, IsCusp c Γ → c.IsZeroAt f k := by + constructor + · rintro ⟨g, hg⟩ c hc + have : (f : ℍ → ℂ) = (g : ℍ → ℂ) := congr_arg DFunLike.coe hg.symm + simpa [this] using g.zero_at_cusps' hc + · intro h + exact ⟨⟨f.toSlashInvariantForm, f.holo', h⟩, by ext; rfl⟩ + +section SL2Z + +open EisensteinSeries + +variable {k : ℤ} + +lemma one_mem_strictPeriods_SL : (1 : ℝ) ∈ (𝒮ℒ : Subgroup (GL (Fin 2) ℝ)).strictPeriods := + CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ one_mem_strictPeriods_SL2Z + +/-- If an `𝒮ℒ` modular form has `valueAtInfty f = 0`, then it is zero at infinity. -/ +lemma isZeroAtImInfty_of_valueAtInfty_eq_zero + (f : ModularForm 𝒮ℒ k) (h : valueAtInfty f = 0) : IsZeroAtImInfty f := by + change Filter.Tendsto f atImInfty (𝓝 0) + rw [show (0 : ℂ) = cuspFunction 1 f 0 from by + rw [cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL]; exact h.symm] + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt.tendsto.comp + (qParam_tendsto_atImInfty one_pos)).congr + (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) + +/-- An `𝒮ℒ` modular form with vanishing q-expansion constant term vanishes at every cusp. -/ +private lemma isZeroAt_of_coeffZero_eq_zero (f : ModularForm 𝒮ℒ k) + (h : (qExpansion 1 f).coeff 0 = 0) {c : OnePoint ℝ} (hc : IsCusp c 𝒮ℒ) : + c.IsZeroAt f k := by + rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc + rw [isZeroAt_iff_forall_SL2Z hc] + intro γ _ + rw [show (⇑f ∣[k] γ) = ⇑f from f.slash_action_eq' _ (MonoidHom.mem_range.mpr ⟨γ, rfl⟩)] + exact isZeroAtImInfty_of_valueAtInfty_eq_zero f <| by + rwa [← qExpansion_coeff_zero f one_pos one_mem_strictPeriods_SL] + +/-- Build a `CuspForm 𝒮ℒ k` from a `ModularForm 𝒮ℒ k` whose q-expansion has vanishing +constant term. The resulting cusp form has the same underlying function. -/ +def toCuspForm (f : ModularForm 𝒮ℒ k) (h : (qExpansion 1 f).coeff 0 = 0) : CuspForm 𝒮ℒ k where + toSlashInvariantForm := f.toSlashInvariantForm + holo' := f.holo' + zero_at_cusps' := isZeroAt_of_coeffZero_eq_zero f h + +@[simp] +lemma toCuspForm_apply (f : ModularForm 𝒮ℒ k) (h : (qExpansion 1 f).coeff 0 = 0) + (z : ℍ) : (toCuspForm f h) z = f z := rfl + +/-- For `𝒮ℒ` modular forms, `IsCuspForm` is equivalent to the q-expansion having vanishing +constant term. -/ +lemma isCuspForm_iff_coeffZero_eq_zero (f : ModularForm 𝒮ℒ k) : + IsCuspForm f ↔ (qExpansion 1 f).coeff 0 = 0 := by + constructor + · intro ⟨g, hg⟩ + rw [qExpansion_coeff_zero f one_pos one_mem_strictPeriods_SL] + exact congr_arg valueAtInfty (congr_arg DFunLike.coe hg.symm) ▸ + (CuspFormClass.zero_at_infty g).valueAtInfty_eq_zero + · exact fun h ↦ (isCuspForm_iff f).mpr (isZeroAt_of_coeffZero_eq_zero f h) + +end SL2Z + +end ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean new file mode 100644 index 00000000000000..aff3fb037ce6be --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -0,0 +1,463 @@ +/- +Copyright (c) 2026 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule +import Mathlib.NumberTheory.ModularForms.Discriminant +import Mathlib.Data.Rat.Star +import Mathlib.LinearAlgebra.Dimension.Localization + +/-! +# Dimension formula for level 1 modular forms + +This file proves the dimension formula for the space of modular forms for `𝒮ℒ` (= `SL(2, ℤ)`) +of even weight `k ≥ 3`. + +## Main results + +* `CuspForm.discriminantEquiv`: `CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - 12)`. +* `ModularForm.rank_eq_one_add_rank_cuspForm`: `rank M_k = 1 + rank S_k` for even `k ≥ 3`. +* `ModularForm.dimension_level_one`: the full dimension formula. +-/ + +open UpperHalfPlane ModularForm Complex SlashInvariantForm SlashInvariantFormClass + ModularFormClass CongruenceSubgroup MatrixGroups OnePoint Filter Topology EisensteinSeries + +noncomputable section + +/-! ### Delta isomorphism: `CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - 12)` -/ + +section DeltaIsomorphism + +variable {k : ℤ} + +local notation "Δ" => ModularForm.discriminant + +namespace CuspForm + +/-- Multiply a modular form of weight `k - 12` by the discriminant to get a cusp form of +weight `k`. Built directly as a CuspForm (no `IsCuspForm` intermediary). -/ +def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := + let Δ' := CuspForm.toModularFormₗ discriminantCuspForm + ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) (by + have : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := by + rw [qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL] + exact (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero + rw [show (ModularForm.mcast _ (f.mul Δ') : ℍ → ℂ) = (f : ℍ → ℂ) * Δ' from rfl, + qExpansion_mul_coeff_zero + (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt + (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt, + this, mul_zero]) + +@[simp] +lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : + (ofMulDiscriminant f) z = f z * Δ z := rfl + +private lemma divByDiscriminant_slash_eq (f : CuspForm 𝒮ℒ k) (γ : SL(2, ℤ)) : + (fun z ↦ f z / Δ z) ∣[k - 12] γ = fun z ↦ f z / Δ z := by + haveI : SlashInvariantFormClass (CuspForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := + CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance + haveI : SlashInvariantFormClass (CuspForm 𝒮ℒ 12) (CongruenceSubgroup.Gamma 1) 12 := + CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance + have hf := slash_action_eqn_SL'' f (mem_Gamma_one γ) + have hΔ := slash_action_eqn_SL'' discriminantCuspForm (mem_Gamma_one γ) + ext z + rw [SL_slash_apply, hf, show Δ (γ • z) = denom γ z ^ (12 : ℤ) * Δ z from by + exact_mod_cast hΔ z] + have hd : (denom γ z : ℂ) ≠ 0 := denom_ne_zero γ z + rw [div_mul_eq_mul_div, mul_right_comm, ← zpow_add₀ hd, + show k + -(k - 12) = (12 : ℤ) from by ring] + exact mul_div_mul_left (f z) (Δ z) (zpow_ne_zero _ hd) + +private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : + (f : ℍ → ℂ) =O[atImInfty] Δ := by + have hf_decay := CuspFormClass.exp_decay_atImInfty (h := 1) f one_pos one_mem_strictPeriods_SL + have hΔ_lower : ∀ᶠ τ : ℍ in atImInfty, + ‖(fun τ : ℍ ↦ Real.exp (-2 * Real.pi * τ.im / 1)) τ‖ ≤ 2 * ‖Δ τ‖ := by + have hprod := discriminant_bounded_factor.eventually + (Metric.ball_mem_nhds (1 : ℂ) (by norm_num : (0 : ℝ) < 1/2)) + filter_upwards [hprod] with τ hτ + simp only [div_one] + rw [discriminant_eq_q_prod, norm_mul, Real.norm_of_nonneg (Real.exp_pos _).le] + have hq_norm : ‖Function.Periodic.qParam 1 (τ : ℂ)‖ = + Real.exp (-2 * Real.pi * τ.im) := by + simp [Function.Periodic.qParam, Complex.norm_exp, Complex.mul_re, div_one] + rw [← hq_norm] + have hprod_bound : 1 / 2 ≤ ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24‖ := by + have hsub : ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24 - 1‖ < 1 / 2 := by + rwa [Complex.dist_eq] at hτ + have h1 := norm_sub_norm_le (1 : ℂ) (∏' (n : ℕ), (1 - eta_q n τ) ^ 24) + simp only [norm_one] at h1 + linarith [norm_sub_rev (1 : ℂ) (∏' (n : ℕ), (1 - eta_q n τ) ^ 24)] + linarith [norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)), + mul_le_mul_of_nonneg_left hprod_bound + (norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)))] + exact hf_decay.trans (Asymptotics.IsBigO.of_bound 2 hΔ_lower) + +/-- Divide a cusp form by the discriminant to get a modular form of weight `k - 12`. -/ +def divDiscriminant (f : CuspForm 𝒮ℒ k) : ModularForm 𝒮ℒ (k - 12) where + toFun z := f z / Δ z + slash_action_eq' A hA := by + obtain ⟨γ, rfl⟩ := hA + exact divByDiscriminant_slash_eq f γ + holo' := by + rw [UpperHalfPlane.mdifferentiable_iff] + apply DifferentiableOn.div + · exact UpperHalfPlane.mdifferentiable_iff.mp f.holo' + · exact UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo' + · intro z hz + simp only [ofComplex_apply_of_im_pos hz] + exact discriminant_ne_zero ⟨z, hz⟩ + bdd_at_cusps' {c} hc := by + rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc + rw [isBoundedAt_iff_forall_SL2Z hc] + intro γ _ + rw [divByDiscriminant_slash_eq f γ, IsBoundedAtImInfty, BoundedAtFilter] + exact (Asymptotics.div_isBoundedUnder_of_isBigO + (exp_decay_isBigO_discriminant f)).isBigO_one ℝ + +@[simp] +lemma divDiscriminant_apply (f : CuspForm 𝒮ℒ k) (z : ℍ) : + (divDiscriminant f) z = f z / Δ z := rfl + +/-- The linear equivalence between cusp forms of weight `k` and modular forms of weight `k - 12`, +given by division by the discriminant. -/ +def discriminantEquiv : CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - 12) where + toFun := divDiscriminant + map_add' a b := by ext z; simp [add_div] + map_smul' c a := by ext z; simp [mul_div_assoc] + invFun := ofMulDiscriminant + left_inv f := by + ext z + simp only [divDiscriminant_apply, ofMulDiscriminant_apply] + exact div_mul_cancel₀ (f z) (discriminant_ne_zero z) + right_inv f := by + ext z + simp only [ofMulDiscriminant_apply, divDiscriminant_apply] + exact mul_div_cancel_right₀ (f z) (discriminant_ne_zero z) + +end CuspForm + +end DeltaIsomorphism + +/-! ### Rank identities -/ + +section RankIdentity + +variable {k : ℤ} + +/-- Cusp forms of weight `k < 12` for `𝒮ℒ` are zero-dimensional. -/ +lemma cuspForm_rank_lt_twelve (hk : k < 12) : + Module.rank ℂ (CuspForm 𝒮ℒ k) = 0 := by + rw [LinearEquiv.rank_eq CuspForm.discriminantEquiv] + exact levelOne_neg_weight_rank_zero (by omega) + +/-- The space of weight 12 cusp forms for `𝒮ℒ` has rank 1. -/ +lemma cuspForm_rank_twelve : Module.rank ℂ (CuspForm 𝒮ℒ 12) = 1 := by + rw [LinearEquiv.rank_eq CuspForm.discriminantEquiv, + show (12 : ℤ) - 12 = 0 from by norm_num] + exact levelOne_weight_zero_rank_one + +/-- Every weight 12 cusp form for `𝒮ℒ` is a scalar multiple of the discriminant. -/ +lemma cuspForm_twelve_smul_discriminant (f : CuspForm 𝒮ℒ 12) : + ∃ c : ℂ, c • discriminantCuspForm = f := by + have hne : discriminantCuspForm ≠ 0 := fun h ↦ + discriminant_ne_zero UpperHalfPlane.I (congr_fun (congr_arg DFunLike.coe h) _) + exact (finrank_eq_one_iff_of_nonzero' discriminantCuspForm hne).mp + (Module.rank_eq_one_iff_finrank_eq_one.mp cuspForm_rank_twelve) f + +/-- For even `k ≥ 3`, the rank of `𝒮ℒ` modular forms is one more than the rank of +cusp forms. -/ +lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : + Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by + have h_add := Submodule.rank_quotient_add_rank + (cuspFormSubmodule (Γ := 𝒮ℒ) (k := (k : ℤ))) + rw [show Module.rank ℂ ↥(cuspFormSubmodule (Γ := 𝒮ℒ) (k := (k : ℤ))) = + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) from + (LinearEquiv.rank_eq CuspForm.equivCuspFormSubmodule).symm] at h_add + suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule) = 1 by + rw [← h_add, h1] + have hk' : 3 ≤ k := by exact_mod_cast hk + have hE_coeff_zero := E_qExpansion_coeff_zero hk' hk2 + apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule) (E hk')) + · intro h + rw [Submodule.Quotient.mk_eq_zero] at h + exact one_ne_zero <| + hE_coeff_zero.symm.trans <| + (isCuspForm_iff_coeffZero_eq_zero _).mp h + · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ + ⟨(qExpansion 1 f).coeff 0, ?_⟩ + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk' ∈ + cuspFormSubmodule := + (isCuspForm_iff_coeffZero_eq_zero _).mpr (by + set c := (qExpansion 1 ↑f).coeff 0 with hc + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (k : ℤ))).map_sub + f (c • E hk') + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub + rw [hsub] + have hcoe : ⇑(c • E hk') = c • (E hk' : ℍ → ℂ) := rfl + rw [hcoe, qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk')] + simp only [_root_.map_sub, _root_.map_smul, smul_eq_mul, hE_coeff_zero, mul_one, ← hc, + sub_self]) + have h0 : (cuspFormSubmodule.mkQ (f - (qExpansion 1 ↑f).coeff 0 • + E hk') : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule) = 0 := + (Submodule.Quotient.mk_eq_zero _).mpr h_mem + rw [map_sub, LinearMap.map_smul, Submodule.mkQ_apply, Submodule.mkQ_apply, + sub_eq_zero] at h0 + exact h0.symm + +end RankIdentity + +/-! ### Dimension formula -/ + +section DimensionFormula + +/-! ### Helpers for weight 2 proof -/ + +/-- In a rank-1 module over ℂ, any element is a scalar multiple of any nonzero element. -/ +private lemma exists_smul_eq_of_rank_one {M : Type*} [AddCommGroup M] [Module ℂ M] + (hrank : Module.rank ℂ M = 1) {e : M} (he : e ≠ 0) (f : M) : ∃ c : ℂ, c • e = f := by + obtain ⟨v, _, hv⟩ := rank_eq_one_iff.mp hrank + obtain ⟨a, rfl⟩ := hv e; obtain ⟨b, rfl⟩ := hv f + exact ⟨b * a⁻¹, by rw [smul_smul, mul_assoc, inv_mul_cancel₀ (fun h ↦ he (by simp [h])), + mul_one]⟩ + +/-- Weight 4 modular forms for `𝒮ℒ` are 1-dimensional. -/ +private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (4 : ℤ)) = 1 := + (rank_eq_one_add_rank_cuspForm (show (3 : ℤ) ≤ 4 by norm_num) ⟨2, rfl⟩).trans + ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (show (4 : ℤ) < 12 by norm_num))).trans + (by norm_cast)) + +/-- Weight 6 modular forms for `𝒮ℒ` are 1-dimensional. -/ +private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ℤ)) = 1 := + (rank_eq_one_add_rank_cuspForm (show (3 : ℤ) ≤ 6 by norm_num) ⟨3, rfl⟩).trans + ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (show (6 : ℤ) < 12 by norm_num))).trans + (by norm_cast)) + +private lemma E_qExpansion_coeff_one_four : + (qExpansion 1 (E (show 3 ≤ 4 by norm_num))).coeff 1 = 240 := by + rw [E_qExpansion_coeff (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩] + simp only [show (1 : ℕ) ≠ 0 from one_ne_zero, ↓reduceIte] + rw [show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by + rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num)]; exact bernoulli'_four] + simp [ArithmeticFunction.sigma_one]; norm_num + +private lemma E_qExpansion_coeff_one_six : + (qExpansion 1 (E (show 3 ≤ 6 by norm_num))).coeff 1 = -504 := by + rw [E_qExpansion_coeff (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩] + simp only [show (1 : ℕ) ≠ 0 from one_ne_zero, ↓reduceIte] + rw [show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by + rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num), bernoulli'_def] + norm_num [Finset.sum_range_succ, Finset.sum_range_zero, + show Nat.choose 6 2 = 15 from by decide, show Nat.choose 6 4 = 15 from by decide, + bernoulli'_eq_zero_of_odd (show Odd 5 from ⟨2, rfl⟩) (by norm_num)]] + simp [ArithmeticFunction.sigma_one]; norm_num + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ +theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : + 1728 * discriminant z = + E (show 3 ≤ 4 by norm_num) z ^ 3 - E (show 3 ≤ 6 by norm_num) z ^ 2 := by + set E4 := E (show 3 ≤ 4 by norm_num) + set E6 := E (show 3 ≤ 6 by norm_num) + set F : ModularForm 𝒮ℒ 12 := + ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) + (E4.mul (ModularForm.mcast (show 4 + 4 = 4 + 4 from rfl) (E4.mul E4))) - + ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E6.mul E6) + have hF : ∀ w, F w = E4 w ^ 3 - E6 w ^ 2 := fun w ↦ by + change E4 w * (E4 w * E4 w) - E6 w * E6 w = E4 w ^ 3 - E6 w ^ 2; ring + have h0_4 := E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ + have h0_6 := E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ + -- q-expansion of F splits as products minus products + -- F is a cusp form (coeff 0 = valueAtInfty F = 1³-1² = 0) + have hF_cusp : IsCuspForm F := (isCuspForm_iff_coeffZero_eq_zero F).mpr (by + rw [qExpansion_coeff_zero F one_pos one_mem_strictPeriods_SL] + -- valueAtInfty F = valueAtInfty (E₄*E₄*E₄ - E₆*E₆) = 1*1*1 - 1*1 = 0 + have hv4 : valueAtInfty (E4 : ℍ → ℂ) = 1 := by + rwa [← qExpansion_coeff_zero E4 one_pos one_mem_strictPeriods_SL] + have hv6 : valueAtInfty (E6 : ℍ → ℂ) = 1 := by + rwa [← qExpansion_coeff_zero E6 one_pos one_mem_strictPeriods_SL] + change limUnder atImInfty (fun w ↦ E4 w * (E4 w * E4 w) - E6 w * E6 w) = 0 + have htend : ∀ (k' : ℤ) (f : ModularForm 𝒮ℒ k') (c' : ℂ) (_ : valueAtInfty f = c'), + Filter.Tendsto f atImInfty (𝓝 c') := fun _ f c' hv ↦ by + rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL + ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr + (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) + have h4 := htend _ E4 _ hv4 + have h6 := htend _ E6 _ hv6 + convert ((h4.mul (h4.mul h4)).sub (h6.mul h6)).limUnder_eq using 1 + norm_num) + obtain ⟨g, hg⟩ := hF_cusp + obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g + -- c = 1728 by comparing q-expansion coeff 1 + have hc_eq : c = 1728 := by + -- coeff 1 of g = coeff 1 of F (since g = F as modular forms) + -- coeff 1 of g = c * coeff 1 of Δ = c * 1 = c (since c•Δ = g) + have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (F : ℍ → ℂ) := by + congr 1; exact congr_arg DFunLike.coe hg + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = + c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) + from congr_arg DFunLike.coe hc.symm] + exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm + -- coeff 1 of F = c (from hgF, hgΔ, and discriminant_qExpansion_coeff_one) + have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) + simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, + mul_one] at h + -- (qExpansion 1 F).coeff 1 = 3*240 - 2*(-504) = 1728 + -- Use ModularForm.qExpansion_mul which works on ModularForm, not raw functions + have hq44 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 E4 + have hq444 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 + (ModularForm.mcast rfl (E4.mul E4)) + have hq66 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E6 E6 + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub + (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) + (ModularForm.mcast (by norm_num) (E6.mul E6)) + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub + -- mcast doesn't change coercions, so qExpansion is unaffected + have hmcast : ∀ (a b : ℤ) (h : a = b) (f : ModularForm 𝒮ℒ a), + qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := + fun _ _ _ _ ↦ rfl + simp only [hmcast] at hsub + rw [hsub, hq444] at h; simp only [hmcast] at h; rw [hq44, hq66] at h + -- h now has: coeff 1 of (p4 * (p4 * p4) - p6 * p6) = c + -- Build the numeric value via calc, avoiding simp-at-h which consumes h + have h1_4 : (PowerSeries.coeff 1) (qExpansion 1 E4) = 240 := E_qExpansion_coeff_one_four + have h1_6 : (PowerSeries.coeff 1) (qExpansion 1 E6) = -504 := E_qExpansion_coeff_one_six + have hc0_4 : PowerSeries.constantCoeff (qExpansion 1 (E4 : ℍ → ℂ)) = 1 := by + rw [← PowerSeries.coeff_zero_eq_constantCoeff]; exact h0_4 + have hc0_6 : PowerSeries.constantCoeff (qExpansion 1 (E6 : ℍ → ℂ)) = 1 := by + rw [← PowerSeries.coeff_zero_eq_constantCoeff]; exact h0_6 + -- Use native_decide or norm_num on the coefficient computation + simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, + Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, + Finset.map_singleton, Function.Embedding.prodMap, Prod.map, + Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, + Function.Embedding.refl_apply, h1_4, h1_6] at h + exact h.symm.trans (by norm_num [show (PowerSeries.coeff 0) (qExpansion 1 (E4 : ℍ → ℂ)) = 1 + from h0_4, show (PowerSeries.coeff 0) (qExpansion 1 (E6 : ℍ → ℂ)) = 1 from h0_6]) + calc 1728 * discriminant z = c * discriminant z := by rw [hc_eq] + _ = (c • discriminantCuspForm) z := rfl + _ = g z := by rw [← hc] + _ = (CuspForm.toModularFormₗ g) z := rfl + _ = F z := by rw [hg] + _ = E4 z ^ 3 - E6 z ^ 2 := hF z + +private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) + (hf : ¬IsCuspForm f) : f = 0 := by + exfalso + have hc0 : (qExpansion 1 f).coeff 0 ≠ 0 := + fun h ↦ hf ((isCuspForm_iff_coeffZero_eq_zero f).mpr h) + obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one + (E_ne_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩) (f.mul f) + obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one + (E_ne_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩) ((f.mul f).mul f) + set p := qExpansion 1 f + set p4 := qExpansion 1 (E (show 3 ≤ 4 by norm_num)) + set p6 := qExpansion 1 (E (show 3 ≤ 6 by norm_num)) + have hqc4 : c4 • p4 = p * p := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 + (E (show 3 ≤ 4 by norm_num)) + rw [show (c4 • E (show 3 ≤ 4 by norm_num) : ℍ → ℂ) = + (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] + exact hsmul.symm + have hqc6 : c6 • p6 = p * p * p := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 + (E (show 3 ≤ 6 by norm_num)) + have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f + rw [show (c6 • E (show 3 ≤ 6 by norm_num) : ℍ → ℂ) = + ((f.mul f).mul f : ℍ → ℂ) from congrArg DFunLike.coe hc6] at hsmul + rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 + rw [← hmul1]; exact hsmul.symm + have hp4_0 : p4.coeff 0 = 1 := + E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ + have hp6_0 : p6.coeff 0 = 1 := + E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ + have hc4_eq : c4 = p.coeff 0 ^ 2 := by + have h := congr_arg (·.coeff 0) hqc4 + simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, + Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp4_0, mul_one] at h + rw [sq]; exact h + have hc6_eq : c6 = p.coeff 0 ^ 3 := by + have h := congr_arg (·.coeff 0) hqc6 + simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, + Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp6_0, mul_one] at h + rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h + have hp4_1 : p4.coeff 1 = 240 := E_qExpansion_coeff_one_four + have hp6_1 : p6.coeff 1 = -504 := E_qExpansion_coeff_one_six + have heq4 : c4 * 240 = 2 * p.coeff 0 * p.coeff 1 := by + have h := congr_arg (·.coeff 1) hqc4 + simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h + rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring] at h + exact h + have heq6 : c6 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by + have h := congr_arg (·.coeff 1) hqc6 + simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h + rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring] at h + exact h + rw [hc4_eq] at heq4; rw [hc6_eq] at heq6 + have h1728 : 1728 * p.coeff 0 ^ 3 = 0 := by + linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 + exact hc0 (by + by_contra h + exact absurd h1728 (mul_ne_zero (by norm_num : (1728 : ℂ) ≠ 0) (pow_ne_zero 3 h))) + +/-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ +theorem ModularForm.levelOne_weight_two_rank_zero : + Module.rank ℂ (ModularForm 𝒮ℒ (2 : ℤ)) = 0 := by + rw [rank_zero_iff_forall_zero] + intro f + by_cases hf : IsCuspForm f + · obtain ⟨g, hg⟩ := hf + rw [← hg] + simp [rank_zero_iff_forall_zero.mp + (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] + · exact weight_two_eq_zero_of_not_cuspForm f hf + +private lemma floor_lem1 (k a : ℚ) (ha : 0 < a) (hak : a ≤ k) : + 1 + Nat.floor ((k - a) / a) = Nat.floor (k / a) := by + rw [div_sub_same (Ne.symm (ne_of_lt ha))] + have := Nat.floor_sub_one (k / a) + push_cast at * + rw [this] + refine Nat.add_sub_cancel' ?_ + exact Nat.le_floor ((le_div_iff₀ ha).mpr (by simpa using hak)) + +/-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ +theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : + Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = + if 12 ∣ ((k : ℤ) - 2) then Nat.floor ((k : ℚ) / 12) + else Nat.floor ((k : ℚ) / 12) + 1 := by + induction k using Nat.strong_induction_on with | h k ihn => + rw [rank_eq_one_add_rank_cuspForm (by omega) hk2, + LinearEquiv.rank_eq CuspForm.discriminantEquiv] + by_cases HK : (3 : ℤ) ≤ ((k : ℤ) - 12) + · have iH := ihn (k - 12) (by omega) (by omega) + ((Nat.even_sub (by omega)).mpr (by simp only [hk2, true_iff]; decide)) + have hk12 : (((k - 12) : ℕ) : ℤ) = k - 12 := by + norm_cast; exact Eq.symm (Int.subNatNat_of_le (by omega)) + rw [hk12] at iH + rw [iH, show ((k - 12 : ℕ) : ℚ) = (k : ℚ) - 12 from by norm_cast] + have hfl := floor_lem1 k 12 (by norm_num) + by_cases h12 : 12 ∣ ((k) : ℤ) - 2 + · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12] + norm_cast at *; apply hfl; omega + · simp only [show ¬ 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12, + Nat.cast_add, Nat.cast_one] + norm_cast at *; rw [← add_assoc, hfl]; omega + · simp only [not_le] at HK + have hkop : k ∈ Finset.filter Even (Finset.Icc 3 14) := by + simp only [Finset.mem_filter, Finset.mem_Icc, hk2, and_true]; omega + rw [show Finset.filter Even (Finset.Icc 3 14) = ({4, 6, 8, 10, 12, 14} : Finset ℕ) + from by decide] at hkop + fin_cases hkop <;> simp only [Nat.cast_ofNat, Int.reduceSub, Int.reduceNeg] at * + all_goals first + | exact (congrArg (1 + ·) (levelOne_neg_weight_rank_zero (by omega))).trans (by norm_cast) + | exact (congrArg (1 + ·) levelOne_weight_zero_rank_one).trans (by norm_cast) + | exact (congrArg (1 + ·) levelOne_weight_two_rank_zero).trans (by norm_cast) + +end DimensionFormula From 40cd50a3921bf7e79a9b68b789fa9e055531fb04 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 10:03:27 +0100 Subject: [PATCH 03/43] chore(NumberTheory/ModularForms): address PR review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Targeted fixes from PR #37789 review: - `cuspFormSubmodule` and `equivCuspFormSubmodule`: make `Γ`/`k` explicit - `isCuspForm_iff`: shorter proof - `ofMulDiscriminant`: simplify cusp-form coeff zero argument - `divDiscriminant.holo'`: golf by inlining the differentiability subgoals - `rank_eq_one_add_rank_cuspForm`: take `hk : 3 ≤ k` over `ℕ` - `discriminant_eq_E4_cube_sub_E6_sq`: restate as `Δ = (E₄³ - E₆²)/1728`, drop inline proof comments, fold redundant `have`s - `exists_smul_eq_of_rank_one`: use `finrank_eq_one_iff_of_nonzero'` from mathlib - Move `one_mem_strictPeriods_SL` to `LevelOne.lean` so the haveI workaround in `EisensteinSeries.E_qExpansion_coeff` can be dropped Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/CuspFormSubmodule.lean | 22 ++-- .../DimensionFormulas/LevelOne.lean | 123 +++++++----------- .../EisensteinSeries/QExpansion.lean | 4 +- .../NumberTheory/ModularForms/LevelOne.lean | 3 + 4 files changed, 62 insertions(+), 90 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index b75d24bcfa9c34..42f695b0886447 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -63,28 +63,25 @@ namespace ModularForm /-- The submodule of `ModularForm Γ k` consisting of cusp forms, defined as the range of the inclusion `CuspForm.toModularFormₗ`. -/ -def cuspFormSubmodule [Γ.HasDetOne] : Submodule ℂ (ModularForm Γ k) := - LinearMap.range (CuspForm.toModularFormₗ) +def cuspFormSubmodule (Γ : Subgroup (GL (Fin 2) ℝ)) (k : ℤ) [Γ.HasDetOne] : + Submodule ℂ (ModularForm Γ k) := + LinearMap.range CuspForm.toModularFormₗ /-- A modular form is a cusp form if it lies in the cusp form submodule. -/ def IsCuspForm [Γ.HasDetOne] (f : ModularForm Γ k) : Prop := - f ∈ cuspFormSubmodule (Γ := Γ) (k := k) + f ∈ cuspFormSubmodule Γ k /-- The cusp form submodule is linearly equivalent to the type of cusp forms. -/ -def CuspForm.equivCuspFormSubmodule [Γ.HasDetOne] : - CuspForm Γ k ≃ₗ[ℂ] cuspFormSubmodule (Γ := Γ) (k := k) := +def CuspForm.equivCuspFormSubmodule (Γ : Subgroup (GL (Fin 2) ℝ)) (k : ℤ) [Γ.HasDetOne] : + CuspForm Γ k ≃ₗ[ℂ] cuspFormSubmodule Γ k := LinearEquiv.ofInjective CuspForm.toModularFormₗ CuspForm.toModularFormₗ_injective /-- A modular form is a cusp form if and only if it vanishes at every cusp. This is the general characterization valid for any subgroup. -/ lemma isCuspForm_iff [Γ.HasDetOne] (f : ModularForm Γ k) : IsCuspForm f ↔ ∀ {c : OnePoint ℝ}, IsCusp c Γ → c.IsZeroAt f k := by - constructor - · rintro ⟨g, hg⟩ c hc - have : (f : ℍ → ℂ) = (g : ℍ → ℂ) := congr_arg DFunLike.coe hg.symm - simpa [this] using g.zero_at_cusps' hc - · intro h - exact ⟨⟨f.toSlashInvariantForm, f.holo', h⟩, by ext; rfl⟩ + refine ⟨fun ⟨g, hg⟩ c hc ↦ hg ▸ g.zero_at_cusps' hc, fun h ↦ + ⟨⟨f.toSlashInvariantForm, f.holo', h⟩, rfl⟩⟩ section SL2Z @@ -92,9 +89,6 @@ open EisensteinSeries variable {k : ℤ} -lemma one_mem_strictPeriods_SL : (1 : ℝ) ∈ (𝒮ℒ : Subgroup (GL (Fin 2) ℝ)).strictPeriods := - CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ one_mem_strictPeriods_SL2Z - /-- If an `𝒮ℒ` modular form has `valueAtInfty f = 0`, then it is zero at infinity. -/ lemma isZeroAtImInfty_of_valueAtInfty_eq_zero (f : ModularForm 𝒮ℒ k) (h : valueAtInfty f = 0) : IsZeroAtImInfty f := by diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index aff3fb037ce6be..7ddac2e6cffd59 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -41,14 +41,14 @@ weight `k`. Built directly as a CuspForm (no `IsCuspForm` intermediary). -/ def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := let Δ' := CuspForm.toModularFormₗ discriminantCuspForm ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) (by - have : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := by - rw [qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL] - exact (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero + have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := + (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans + (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero rw [show (ModularForm.mcast _ (f.mul Δ') : ℍ → ℂ) = (f : ℍ → ℂ) * Δ' from rfl, qExpansion_mul_coeff_zero (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt, - this, mul_zero]) + hΔ', mul_zero]) @[simp] lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : @@ -103,12 +103,9 @@ def divDiscriminant (f : CuspForm 𝒮ℒ k) : ModularForm 𝒮ℒ (k - 12) wher exact divByDiscriminant_slash_eq f γ holo' := by rw [UpperHalfPlane.mdifferentiable_iff] - apply DifferentiableOn.div - · exact UpperHalfPlane.mdifferentiable_iff.mp f.holo' - · exact UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo' - · intro z hz - simp only [ofComplex_apply_of_im_pos hz] - exact discriminant_ne_zero ⟨z, hz⟩ + refine (UpperHalfPlane.mdifferentiable_iff.mp f.holo').div + (UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo') fun z hz ↦ ?_ + simpa [ofComplex_apply_of_im_pos hz] using discriminant_ne_zero ⟨z, hz⟩ bdd_at_cusps' {c} hc := by rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc rw [isBoundedAt_iff_forall_SL2Z hc] @@ -169,18 +166,16 @@ lemma cuspForm_twelve_smul_discriminant (f : CuspForm 𝒮ℒ 12) : /-- For even `k ≥ 3`, the rank of `𝒮ℒ` modular forms is one more than the rank of cusp forms. -/ -lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : +lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k) : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by - have h_add := Submodule.rank_quotient_add_rank - (cuspFormSubmodule (Γ := 𝒮ℒ) (k := (k : ℤ))) - rw [show Module.rank ℂ ↥(cuspFormSubmodule (Γ := 𝒮ℒ) (k := (k : ℤ))) = + have h_add := Submodule.rank_quotient_add_rank (cuspFormSubmodule 𝒮ℒ (k : ℤ)) + rw [show Module.rank ℂ ↥(cuspFormSubmodule 𝒮ℒ (k : ℤ)) = Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) from - (LinearEquiv.rank_eq CuspForm.equivCuspFormSubmodule).symm] at h_add - suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule) = 1 by + (LinearEquiv.rank_eq (CuspForm.equivCuspFormSubmodule 𝒮ℒ (k : ℤ))).symm] at h_add + suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 1 by rw [← h_add, h1] - have hk' : 3 ≤ k := by exact_mod_cast hk - have hE_coeff_zero := E_qExpansion_coeff_zero hk' hk2 - apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule) (E hk')) + have hE_coeff_zero := E_qExpansion_coeff_zero hk hk2 + apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule 𝒮ℒ (k : ℤ)) (E hk)) · intro h rw [Submodule.Quotient.mk_eq_zero] at h exact one_ne_zero <| @@ -188,20 +183,20 @@ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ (k : ℤ)) (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ - have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk' ∈ - cuspFormSubmodule := + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ + cuspFormSubmodule 𝒮ℒ (k : ℤ) := (isCuspForm_iff_coeffZero_eq_zero _).mpr (by set c := (qExpansion 1 ↑f).coeff 0 with hc have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (k : ℤ))).map_sub - f (c • E hk') + f (c • E hk) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub rw [hsub] - have hcoe : ⇑(c • E hk') = c • (E hk' : ℍ → ℂ) := rfl - rw [hcoe, qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk')] + have hcoe : ⇑(c • E hk) = c • (E hk : ℍ → ℂ) := rfl + rw [hcoe, qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk)] simp only [_root_.map_sub, _root_.map_smul, smul_eq_mul, hE_coeff_zero, mul_one, ← hc, sub_self]) - have h0 : (cuspFormSubmodule.mkQ (f - (qExpansion 1 ↑f).coeff 0 • - E hk') : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule) = 0 := + have h0 : ((cuspFormSubmodule 𝒮ℒ (k : ℤ)).mkQ (f - (qExpansion 1 ↑f).coeff 0 • + E hk) : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 0 := (Submodule.Quotient.mk_eq_zero _).mpr h_mem rw [map_sub, LinearMap.map_smul, Submodule.mkQ_apply, Submodule.mkQ_apply, sub_eq_zero] at h0 @@ -215,25 +210,22 @@ section DimensionFormula /-! ### Helpers for weight 2 proof -/ -/-- In a rank-1 module over ℂ, any element is a scalar multiple of any nonzero element. -/ +/-- In a rank-one ℂ-module, every element is a scalar multiple of any nonzero element. +This is a thin wrapper around `finrank_eq_one_iff_of_nonzero'` adapted to `Module.rank`. -/ private lemma exists_smul_eq_of_rank_one {M : Type*} [AddCommGroup M] [Module ℂ M] - (hrank : Module.rank ℂ M = 1) {e : M} (he : e ≠ 0) (f : M) : ∃ c : ℂ, c • e = f := by - obtain ⟨v, _, hv⟩ := rank_eq_one_iff.mp hrank - obtain ⟨a, rfl⟩ := hv e; obtain ⟨b, rfl⟩ := hv f - exact ⟨b * a⁻¹, by rw [smul_smul, mul_assoc, inv_mul_cancel₀ (fun h ↦ he (by simp [h])), - mul_one]⟩ + (hrank : Module.rank ℂ M = 1) {e : M} (he : e ≠ 0) (f : M) : ∃ c : ℂ, c • e = f := + (finrank_eq_one_iff_of_nonzero' e he).mp + (Module.rank_eq_one_iff_finrank_eq_one.mp hrank) f /-- Weight 4 modular forms for `𝒮ℒ` are 1-dimensional. -/ private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (4 : ℤ)) = 1 := - (rank_eq_one_add_rank_cuspForm (show (3 : ℤ) ≤ 4 by norm_num) ⟨2, rfl⟩).trans - ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (show (4 : ℤ) < 12 by norm_num))).trans - (by norm_cast)) + (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨2, rfl⟩).trans + ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) /-- Weight 6 modular forms for `𝒮ℒ` are 1-dimensional. -/ private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ℤ)) = 1 := - (rank_eq_one_add_rank_cuspForm (show (3 : ℤ) ≤ 6 by norm_num) ⟨3, rfl⟩).trans - ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (show (6 : ℤ) < 12 by norm_num))).trans - (by norm_cast)) + (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨3, rfl⟩).trans + ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) private lemma E_qExpansion_coeff_one_four : (qExpansion 1 (E (show 3 ≤ 4 by norm_num))).coeff 1 = 240 := by @@ -256,8 +248,8 @@ private lemma E_qExpansion_coeff_one_six : /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : - 1728 * discriminant z = - E (show 3 ≤ 4 by norm_num) z ^ 3 - E (show 3 ≤ 6 by norm_num) z ^ 2 := by + discriminant z = (1 / 1728) * + (E (show 3 ≤ 4 by norm_num) z ^ 3 - E (show 3 ≤ 6 by norm_num) z ^ 2) := by set E4 := E (show 3 ≤ 4 by norm_num) set E6 := E (show 3 ≤ 6 by norm_num) set F : ModularForm 𝒮ℒ 12 := @@ -268,11 +260,8 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : change E4 w * (E4 w * E4 w) - E6 w * E6 w = E4 w ^ 3 - E6 w ^ 2; ring have h0_4 := E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ have h0_6 := E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ - -- q-expansion of F splits as products minus products - -- F is a cusp form (coeff 0 = valueAtInfty F = 1³-1² = 0) have hF_cusp : IsCuspForm F := (isCuspForm_iff_coeffZero_eq_zero F).mpr (by rw [qExpansion_coeff_zero F one_pos one_mem_strictPeriods_SL] - -- valueAtInfty F = valueAtInfty (E₄*E₄*E₄ - E₆*E₆) = 1*1*1 - 1*1 = 0 have hv4 : valueAtInfty (E4 : ℍ → ℂ) = 1 := by rwa [← qExpansion_coeff_zero E4 one_pos one_mem_strictPeriods_SL] have hv6 : valueAtInfty (E6 : ℍ → ℂ) = 1 := by @@ -290,10 +279,7 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : norm_num) obtain ⟨g, hg⟩ := hF_cusp obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g - -- c = 1728 by comparing q-expansion coeff 1 have hc_eq : c = 1728 := by - -- coeff 1 of g = coeff 1 of F (since g = F as modular forms) - -- coeff 1 of g = c * coeff 1 of Δ = c * 1 = c (since c•Δ = g) have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (F : ℍ → ℂ) := by congr 1; exact congr_arg DFunLike.coe hg have hgΔ : qExpansion 1 (g : ℍ → ℂ) = @@ -301,35 +287,23 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) from congr_arg DFunLike.coe hc.symm] exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm - -- coeff 1 of F = c (from hgF, hgΔ, and discriminant_qExpansion_coeff_one) have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, mul_one] at h - -- (qExpansion 1 F).coeff 1 = 3*240 - 2*(-504) = 1728 - -- Use ModularForm.qExpansion_mul which works on ModularForm, not raw functions - have hq44 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 E4 - have hq444 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 - (ModularForm.mcast rfl (E4.mul E4)) - have hq66 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E6 E6 - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) - (ModularForm.mcast (by norm_num) (E6.mul E6)) - simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub - -- mcast doesn't change coercions, so qExpansion is unaffected have hmcast : ∀ (a b : ℤ) (h : a = b) (f : ModularForm 𝒮ℒ a), qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := fun _ _ _ _ ↦ rfl - simp only [hmcast] at hsub - rw [hsub, hq444] at h; simp only [hmcast] at h; rw [hq44, hq66] at h - -- h now has: coeff 1 of (p4 * (p4 * p4) - p6 * p6) = c - -- Build the numeric value via calc, avoiding simp-at-h which consumes h + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub + (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) + (ModularForm.mcast (by norm_num) (E6.mul E6)) + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 + (ModularForm.mcast rfl (E4.mul E4))] at h + simp only [hmcast] at h + rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 E4, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E6 E6] at h have h1_4 : (PowerSeries.coeff 1) (qExpansion 1 E4) = 240 := E_qExpansion_coeff_one_four have h1_6 : (PowerSeries.coeff 1) (qExpansion 1 E6) = -504 := E_qExpansion_coeff_one_six - have hc0_4 : PowerSeries.constantCoeff (qExpansion 1 (E4 : ℍ → ℂ)) = 1 := by - rw [← PowerSeries.coeff_zero_eq_constantCoeff]; exact h0_4 - have hc0_6 : PowerSeries.constantCoeff (qExpansion 1 (E6 : ℍ → ℂ)) = 1 := by - rw [← PowerSeries.coeff_zero_eq_constantCoeff]; exact h0_6 - -- Use native_decide or norm_num on the coefficient computation simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, Finset.map_singleton, Function.Embedding.prodMap, Prod.map, @@ -337,12 +311,15 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : Function.Embedding.refl_apply, h1_4, h1_6] at h exact h.symm.trans (by norm_num [show (PowerSeries.coeff 0) (qExpansion 1 (E4 : ℍ → ℂ)) = 1 from h0_4, show (PowerSeries.coeff 0) (qExpansion 1 (E6 : ℍ → ℂ)) = 1 from h0_6]) - calc 1728 * discriminant z = c * discriminant z := by rw [hc_eq] - _ = (c • discriminantCuspForm) z := rfl - _ = g z := by rw [← hc] - _ = (CuspForm.toModularFormₗ g) z := rfl - _ = F z := by rw [hg] - _ = E4 z ^ 3 - E6 z ^ 2 := hF z + have h1728 : (1728 : ℂ) * discriminant z = E4 z ^ 3 - E6 z ^ 2 := by + calc (1728 : ℂ) * discriminant z + = c * discriminant z := by rw [hc_eq] + _ = (c • discriminantCuspForm) z := rfl + _ = g z := by rw [← hc] + _ = (CuspForm.toModularFormₗ g) z := rfl + _ = F z := by rw [hg] + _ = E4 z ^ 3 - E6 z ^ 2 := hF z + linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) (hf : ¬IsCuspForm f) : f = 0 := by diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean index 158f8c89164524..8de94c3361db09 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean @@ -327,10 +327,8 @@ lemma EisensteinSeries.E_qExpansion_coeff {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k if m = 0 then 1 else -(2 * k / bernoulli k : ℂ) * (σ (k - 1) m) := by set β : ℂ := -(2 * k / bernoulli k : ℂ) set c : ℕ → ℂ := fun m ↦ if m = 0 then 1 else β * ↑(σ (k - 1) m) - haveI : ModularFormClass (ModularForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := - CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance suffices ∀ τ : ℍ, HasSum (fun m ↦ c m • 𝕢 (1 : ℝ) τ ^ m) (E hk τ) from - (qExpansion_coeff_unique one_pos one_mem_strictPeriods_SL2Z this m).symm + (qExpansion_coeff_unique one_pos one_mem_strictPeriods_SL this m).symm intro τ have hS : Summable fun n : ℕ ↦ (σ (k - 1) (n + 1) : ℂ) * cexp (2 * π * I * τ) ^ (n + 1) := (summable_nat_add_iff 1).mpr (summable_sigma_mul_cexp_pow (by omega) τ) diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne.lean index 30c515d4933a0b..15fb58c051e639 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne.lean @@ -69,6 +69,9 @@ variable [ModularFormClass F Γ(1) k] lemma one_mem_strictPeriods_SL2Z : (1 : ℝ) ∈ Γ(1).strictPeriods := by simp +lemma one_mem_strictPeriods_SL : (1 : ℝ) ∈ (𝒮ℒ : Subgroup (GL (Fin 2) ℝ)).strictPeriods := + Gamma_one_coe_eq_SL ▸ one_mem_strictPeriods_SL2Z + private theorem cuspFunction_eqOn_const_of_nonpos_wt (hk : k ≤ 0) (f : F) : Set.EqOn (cuspFunction 1 f) (const ℂ (cuspFunction 1 f 0)) (Metric.ball 0 1) := by refine eq_const_of_exists_le (fun q hq ↦ ?_) (exp_nonneg (-π)) ?_ (fun q hq ↦ ?_) From fda7c119519fa3cb4172fb7054126d5ced7eab9f Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 10:24:16 +0100 Subject: [PATCH 04/43] chore(NumberTheory/ModularForms): inline more haves in dimension formula proofs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `discriminant_eq_E4_cube_sub_E6_sq`: hoist `hmcast` (used 3x) above its use, drop redundant calc step `_ = (CuspForm.toModularFormₗ g) z := rfl` - `weight_two_eq_zero_of_not_cuspForm`: drop `hc0`, fold the c4/c6 substitutions directly into `heq4`/`heq6` rather than via separate `hc4_eq`/`hc6_eq` + `rw`, replace the by_contra finale with `pow_eq_zero_iff`/`mul_eq_zero` Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 7ddac2e6cffd59..578278f6f050de 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -280,6 +280,9 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : obtain ⟨g, hg⟩ := hF_cusp obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g have hc_eq : c = 1728 := by + have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), + qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := + fun _ _ ↦ rfl have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (F : ℍ → ℂ) := by congr 1; exact congr_arg DFunLike.coe hg have hgΔ : qExpansion 1 (g : ℍ → ℂ) = @@ -290,9 +293,6 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, mul_one] at h - have hmcast : ∀ (a b : ℤ) (h : a = b) (f : ModularForm 𝒮ℒ a), - qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := - fun _ _ _ _ ↦ rfl have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) (ModularForm.mcast (by norm_num) (E6.mul E6)) @@ -311,21 +311,18 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : Function.Embedding.refl_apply, h1_4, h1_6] at h exact h.symm.trans (by norm_num [show (PowerSeries.coeff 0) (qExpansion 1 (E4 : ℍ → ℂ)) = 1 from h0_4, show (PowerSeries.coeff 0) (qExpansion 1 (E6 : ℍ → ℂ)) = 1 from h0_6]) - have h1728 : (1728 : ℂ) * discriminant z = E4 z ^ 3 - E6 z ^ 2 := by + have h1728 : (1728 : ℂ) * discriminant z = E4 z ^ 3 - E6 z ^ 2 := calc (1728 : ℂ) * discriminant z = c * discriminant z := by rw [hc_eq] _ = (c • discriminantCuspForm) z := rfl _ = g z := by rw [← hc] - _ = (CuspForm.toModularFormₗ g) z := rfl - _ = F z := by rw [hg] + _ = F z := congr_fun (congr_arg DFunLike.coe hg) z _ = E4 z ^ 3 - E6 z ^ 2 := hF z linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) (hf : ¬IsCuspForm f) : f = 0 := by exfalso - have hc0 : (qExpansion 1 f).coeff 0 ≠ 0 := - fun h ↦ hf ((isCuspForm_iff_coeffZero_eq_zero f).mpr h) obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one (E_ne_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩) (f.mul f) obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one @@ -338,8 +335,7 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : (E (show 3 ≤ 4 by norm_num)) rw [show (c4 • E (show 3 ≤ 4 by norm_num) : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul - rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] - exact hsmul.symm + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm have hqc6 : c6 • p6 = p * p * p := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 (E (show 3 ≤ 6 by norm_num)) @@ -352,36 +348,35 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ have hp6_0 : p6.coeff 0 = 1 := E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ - have hc4_eq : c4 = p.coeff 0 ^ 2 := by + have h0_4 : c4 = p.coeff 0 ^ 2 := by have h := congr_arg (·.coeff 0) hqc4 simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp4_0, mul_one] at h rw [sq]; exact h - have hc6_eq : c6 = p.coeff 0 ^ 3 := by + have h0_6 : c6 = p.coeff 0 ^ 3 := by have h := congr_arg (·.coeff 0) hqc6 simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp6_0, mul_one] at h rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h have hp4_1 : p4.coeff 1 = 240 := E_qExpansion_coeff_one_four have hp6_1 : p6.coeff 1 = -504 := E_qExpansion_coeff_one_six - have heq4 : c4 * 240 = 2 * p.coeff 0 * p.coeff 1 := by + have heq4 : p.coeff 0 ^ 2 * 240 = 2 * p.coeff 0 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc4 simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring] at h + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_4] at h exact h - have heq6 : c6 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by + have heq6 : p.coeff 0 ^ 3 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc6 simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring] at h + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_6] at h exact h - rw [hc4_eq] at heq4; rw [hc6_eq] at heq6 - have h1728 : 1728 * p.coeff 0 ^ 3 = 0 := by + refine hf ((isCuspForm_iff_coeffZero_eq_zero f).mpr <| + pow_eq_zero_iff (n := 3) three_ne_zero |>.mp ?_) + have h0 : (1728 : ℂ) * p.coeff 0 ^ 3 = 0 := by linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 - exact hc0 (by - by_contra h - exact absurd h1728 (mul_ne_zero (by norm_num : (1728 : ℂ) ≠ 0) (pow_ne_zero 3 h))) + exact (mul_eq_zero.mp h0).resolve_left (by norm_num) /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : From 563616ad36a66fab91253078f0c0eeb41b7b78b7 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 10:31:48 +0100 Subject: [PATCH 05/43] =?UTF-8?q?feat(NumberTheory/ModularForms):=20add=20?= =?UTF-8?q?E=E2=82=84=20and=20E=E2=82=86=20abbreviations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add public `noncomputable abbrev`s `ModularForm.E₄ : ModularForm 𝒮ℒ 4` and `ModularForm.E₆ : ModularForm 𝒮ℒ 6` for the normalised level 1 Eisenstein series of weights 4 and 6. Use them throughout `DimensionFormulas/LevelOne.lean` to drop the awkward `E (show 3 ≤ 4 by norm_num)` and `set E4 := …` patterns. The `abbrev` (rather than `def` or notation) is required so all uses share a single underlying proof of `3 ≤ 4` / `3 ≤ 6`, which lets simp lemmas about their q-expansions match consistently. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 114 ++++++++---------- .../ModularForms/EisensteinSeries/Basic.lean | 6 + 2 files changed, 58 insertions(+), 62 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 578278f6f050de..51ba125cbfbe19 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -227,18 +227,18 @@ private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨3, rfl⟩).trans ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) -private lemma E_qExpansion_coeff_one_four : - (qExpansion 1 (E (show 3 ≤ 4 by norm_num))).coeff 1 = 240 := by - rw [E_qExpansion_coeff (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩] - simp only [show (1 : ℕ) ≠ 0 from one_ne_zero, ↓reduceIte] +private lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by + rw [show (E₄ : ModularForm 𝒮ℒ 4) = E (by norm_num : (3 : ℕ) ≤ 4) from rfl, + E_qExpansion_coeff _ ⟨2, rfl⟩] + simp only [one_ne_zero, ↓reduceIte] rw [show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num)]; exact bernoulli'_four] simp [ArithmeticFunction.sigma_one]; norm_num -private lemma E_qExpansion_coeff_one_six : - (qExpansion 1 (E (show 3 ≤ 6 by norm_num))).coeff 1 = -504 := by - rw [E_qExpansion_coeff (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩] - simp only [show (1 : ℕ) ≠ 0 from one_ne_zero, ↓reduceIte] +private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by + rw [show (E₆ : ModularForm 𝒮ℒ 6) = E (by norm_num : (3 : ℕ) ≤ 6) from rfl, + E_qExpansion_coeff _ ⟨3, rfl⟩] + simp only [one_ne_zero, ↓reduceIte] rw [show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num), bernoulli'_def] norm_num [Finset.sum_range_succ, Finset.sum_range_zero, @@ -248,33 +248,32 @@ private lemma E_qExpansion_coeff_one_six : /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : - discriminant z = (1 / 1728) * - (E (show 3 ≤ 4 by norm_num) z ^ 3 - E (show 3 ≤ 6 by norm_num) z ^ 2) := by - set E4 := E (show 3 ≤ 4 by norm_num) - set E6 := E (show 3 ≤ 6 by norm_num) + discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by set F : ModularForm 𝒮ℒ 12 := ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) - (E4.mul (ModularForm.mcast (show 4 + 4 = 4 + 4 from rfl) (E4.mul E4))) - - ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E6.mul E6) - have hF : ∀ w, F w = E4 w ^ 3 - E6 w ^ 2 := fun w ↦ by - change E4 w * (E4 w * E4 w) - E6 w * E6 w = E4 w ^ 3 - E6 w ^ 2; ring - have h0_4 := E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ - have h0_6 := E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ + (E₄.mul (ModularForm.mcast (show 4 + 4 = 4 + 4 from rfl) (E₄.mul E₄))) - + ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) + have hF : ∀ w, F w = E₄ w ^ 3 - E₆ w ^ 2 := fun w ↦ by + change E₄ w * (E₄ w * E₄ w) - E₆ w * E₆ w = E₄ w ^ 3 - E₆ w ^ 2; ring + have h0_4 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := + E_qExpansion_coeff_zero _ ⟨2, rfl⟩ + have h0_6 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := + E_qExpansion_coeff_zero _ ⟨3, rfl⟩ have hF_cusp : IsCuspForm F := (isCuspForm_iff_coeffZero_eq_zero F).mpr (by rw [qExpansion_coeff_zero F one_pos one_mem_strictPeriods_SL] - have hv4 : valueAtInfty (E4 : ℍ → ℂ) = 1 := by - rwa [← qExpansion_coeff_zero E4 one_pos one_mem_strictPeriods_SL] - have hv6 : valueAtInfty (E6 : ℍ → ℂ) = 1 := by - rwa [← qExpansion_coeff_zero E6 one_pos one_mem_strictPeriods_SL] - change limUnder atImInfty (fun w ↦ E4 w * (E4 w * E4 w) - E6 w * E6 w) = 0 - have htend : ∀ (k' : ℤ) (f : ModularForm 𝒮ℒ k') (c' : ℂ) (_ : valueAtInfty f = c'), - Filter.Tendsto f atImInfty (𝓝 c') := fun _ f c' hv ↦ by + have hv4 : valueAtInfty (E₄ : ℍ → ℂ) = 1 := by + rwa [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] + have hv6 : valueAtInfty (E₆ : ℍ → ℂ) = 1 := by + rwa [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] + change limUnder atImInfty (fun w ↦ E₄ w * (E₄ w * E₄ w) - E₆ w * E₆ w) = 0 + have htend : ∀ {k' : ℤ} (f : ModularForm 𝒮ℒ k') {c' : ℂ}, valueAtInfty (f : ℍ → ℂ) = c' → + Filter.Tendsto f atImInfty (𝓝 c') := fun {_} f {_} hv ↦ by rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) - have h4 := htend _ E4 _ hv4 - have h6 := htend _ E6 _ hv6 + have h4 := htend E₄ hv4 + have h6 := htend E₆ hv6 convert ((h4.mul (h4.mul h4)).sub (h6.mul h6)).limUnder_eq using 1 norm_num) obtain ⟨g, hg⟩ := hF_cusp @@ -294,60 +293,53 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, mul_one] at h have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) - (ModularForm.mcast (by norm_num) (E6.mul E6)) + (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 - (ModularForm.mcast rfl (E4.mul E4))] at h + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ + (ModularForm.mcast rfl (E₄.mul E₄))] at h simp only [hmcast] at h - rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 E4, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E6 E6] at h - have h1_4 : (PowerSeries.coeff 1) (qExpansion 1 E4) = 240 := E_qExpansion_coeff_one_four - have h1_6 : (PowerSeries.coeff 1) (qExpansion 1 E6) = -504 := E_qExpansion_coeff_one_six + rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] at h simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, Finset.map_singleton, Function.Embedding.prodMap, Prod.map, Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, - Function.Embedding.refl_apply, h1_4, h1_6] at h - exact h.symm.trans (by norm_num [show (PowerSeries.coeff 0) (qExpansion 1 (E4 : ℍ → ℂ)) = 1 - from h0_4, show (PowerSeries.coeff 0) (qExpansion 1 (E6 : ℍ → ℂ)) = 1 from h0_6]) - have h1728 : (1728 : ℂ) * discriminant z = E4 z ^ 3 - E6 z ^ 2 := + Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, + E₆_qExpansion_coeff_one] at h + exact h.symm.trans (by norm_num [h0_4, h0_6]) + have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := calc (1728 : ℂ) * discriminant z = c * discriminant z := by rw [hc_eq] _ = (c • discriminantCuspForm) z := rfl _ = g z := by rw [← hc] _ = F z := congr_fun (congr_arg DFunLike.coe hg) z - _ = E4 z ^ 3 - E6 z ^ 2 := hF z + _ = E₄ z ^ 3 - E₆ z ^ 2 := hF z linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) (hf : ¬IsCuspForm f) : f = 0 := by exfalso obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one - (E_ne_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩) (f.mul f) + (E_ne_zero _ ⟨2, rfl⟩ : (E₄ : ModularForm 𝒮ℒ 4) ≠ 0) (f.mul f) obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one - (E_ne_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩) ((f.mul f).mul f) + (E_ne_zero _ ⟨3, rfl⟩ : (E₆ : ModularForm 𝒮ℒ 6) ≠ 0) ((f.mul f).mul f) set p := qExpansion 1 f - set p4 := qExpansion 1 (E (show 3 ≤ 4 by norm_num)) - set p6 := qExpansion 1 (E (show 3 ≤ 6 by norm_num)) - have hqc4 : c4 • p4 = p * p := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 - (E (show 3 ≤ 4 by norm_num)) - rw [show (c4 • E (show 3 ≤ 4 by norm_num) : ℍ → ℂ) = - (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul + have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = p * p := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ + rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm - have hqc6 : c6 • p6 = p * p * p := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 - (E (show 3 ≤ 6 by norm_num)) + have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = p * p * p := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f - rw [show (c6 • E (show 3 ≤ 6 by norm_num) : ℍ → ℂ) = - ((f.mul f).mul f : ℍ → ℂ) from congrArg DFunLike.coe hc6] at hsmul + rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from + congrArg DFunLike.coe hc6] at hsmul rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 rw [← hmul1]; exact hsmul.symm - have hp4_0 : p4.coeff 0 = 1 := - E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ - have hp6_0 : p6.coeff 0 = 1 := - E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ + have hp4_0 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := + E_qExpansion_coeff_zero _ ⟨2, rfl⟩ + have hp6_0 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := + E_qExpansion_coeff_zero _ ⟨3, rfl⟩ have h0_4 : c4 = p.coeff 0 ^ 2 := by have h := congr_arg (·.coeff 0) hqc4 simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, @@ -358,17 +350,15 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp6_0, mul_one] at h rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h - have hp4_1 : p4.coeff 1 = 240 := E_qExpansion_coeff_one_four - have hp6_1 : p6.coeff 1 = -504 := E_qExpansion_coeff_one_six have heq4 : p.coeff 0 ^ 2 * 240 = 2 * p.coeff 0 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc4 - simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h + simp only [PowerSeries.coeff_smul, smul_eq_mul, E₄_qExpansion_coeff_one] at h rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_4] at h exact h have heq6 : p.coeff 0 ^ 3 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc6 - simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h + simp only [PowerSeries.coeff_smul, smul_eq_mul, E₆_qExpansion_coeff_one] at h rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_6] at h exact h diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean index e6e4c33ee3bf95..62b0a89b7fadf2 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean @@ -48,4 +48,10 @@ noncomputable def E {k : ℕ} (hk : 3 ≤ k) : ModularForm 𝒮ℒ k := ((1 / 2 : ℂ) • eisensteinSeriesMF (mod_cast hk) 0).ofSubgroupEq CongruenceSubgroup.Gamma_one_coe_eq_SL +/-- The normalised level 1 Eisenstein series of weight 4. -/ +noncomputable abbrev E₄ : ModularForm 𝒮ℒ 4 := E (by norm_num : (3 : ℕ) ≤ 4) + +/-- The normalised level 1 Eisenstein series of weight 6. -/ +noncomputable abbrev E₆ : ModularForm 𝒮ℒ 6 := E (by norm_num : (3 : ℕ) ≤ 6) + end ModularForm From ba215366fc3bb3271ef290a0e5cd7e54cd7e9829 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 10:38:59 +0100 Subject: [PATCH 06/43] golf --- Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index 42f695b0886447..a9b6378449a2f0 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -46,8 +46,8 @@ def toModularFormₗ [Γ.HasDetOne] : CuspForm Γ k →ₗ[ℂ] ModularForm Γ k { toSlashInvariantForm := f.toSlashInvariantForm holo' := f.holo' bdd_at_cusps' := fun hc g hg ↦ (f.zero_at_cusps' hc g hg).boundedAtFilter } - map_add' _ _ := by ext; rfl - map_smul' _ _ := by ext; rfl + map_add' _ _ := rfl + map_smul' _ _ := rfl @[simp] lemma toModularFormₗ_apply [Γ.HasDetOne] (f : CuspForm Γ k) (z : ℍ) : From 58ce4e1e1504910e36bd45bdf75b0abe9735779e Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 12:56:10 +0100 Subject: [PATCH 07/43] feat(Algebra/Order/Floor/Semifield): add `Nat.floor_div_eq_one_add_floor_sub_div` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the lemma `⌊k / a⌋₊ = 1 + ⌊(k - a) / a⌋₊` for `0 < a ≤ k` over a linear ordered field, generalising the local `floor_lem1` helper that was buried in `DimensionFormulas/LevelOne.lean`. Inline the helper at its single use site in `dimension_level_one`. Co-Authored-By: Claude Opus 4.6 (1M context) --- Mathlib/Algebra/Order/Floor/Semifield.lean | 5 +++++ .../DimensionFormulas/LevelOne.lean | 19 +++++++------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Mathlib/Algebra/Order/Floor/Semifield.lean b/Mathlib/Algebra/Order/Floor/Semifield.lean index 4690b6da5f5b2d..5a78c62a053682 100644 --- a/Mathlib/Algebra/Order/Floor/Semifield.lean +++ b/Mathlib/Algebra/Order/Floor/Semifield.lean @@ -53,6 +53,11 @@ end LinearOrderedSemifield section LinearOrderedField variable [Field K] [LinearOrder K] [IsStrictOrderedRing K] [FloorSemiring K] {a b : K} +theorem floor_div_eq_one_add_floor_sub_div (k a : K) (ha : 0 < a) (hak : a ≤ k) : + ⌊k / a⌋₊ = 1 + ⌊(k - a) / a⌋₊ := by + rw [sub_div, div_self ha.ne', Nat.floor_sub_one] + exact (Nat.add_sub_cancel' (Nat.le_floor (mod_cast (one_le_div₀ ha).mpr hak))).symm + lemma mul_lt_floor (hb₀ : 0 < b) (hb : b < 1) (hba : ⌈b / (1 - b)⌉₊ ≤ a) : b * a < ⌊a⌋₊ := by calc b * a < b * (⌊a⌋₊ + 1) := by gcongr; apply lt_floor_add_one diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 51ba125cbfbe19..f137c1580b49f3 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -3,6 +3,7 @@ Copyright (c) 2026 Chris Birkbeck. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ +import Mathlib.Algebra.Order.Floor.Semifield import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule import Mathlib.NumberTheory.ModularForms.Discriminant import Mathlib.Data.Rat.Star @@ -380,15 +381,6 @@ theorem ModularForm.levelOne_weight_two_rank_zero : (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] · exact weight_two_eq_zero_of_not_cuspForm f hf -private lemma floor_lem1 (k a : ℚ) (ha : 0 < a) (hak : a ≤ k) : - 1 + Nat.floor ((k - a) / a) = Nat.floor (k / a) := by - rw [div_sub_same (Ne.symm (ne_of_lt ha))] - have := Nat.floor_sub_one (k / a) - push_cast at * - rw [this] - refine Nat.add_sub_cancel' ?_ - exact Nat.le_floor ((le_div_iff₀ ha).mpr (by simpa using hak)) - /-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = @@ -404,13 +396,16 @@ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : norm_cast; exact Eq.symm (Int.subNatNat_of_le (by omega)) rw [hk12] at iH rw [iH, show ((k - 12 : ℕ) : ℚ) = (k : ℚ) - 12 from by norm_cast] - have hfl := floor_lem1 k 12 (by norm_num) + have hfl (hk' : (12 : ℚ) ≤ k) : + ⌊(k : ℚ) / 12⌋₊ = 1 + ⌊((k : ℚ) - 12) / 12⌋₊ := + Nat.floor_div_eq_one_add_floor_sub_div (k : ℚ) 12 (by norm_num) hk' by_cases h12 : 12 ∣ ((k) : ℤ) - 2 · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12] - norm_cast at *; apply hfl; omega + norm_cast at *; rw [hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [show ¬ 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12, Nat.cast_add, Nat.cast_one] - norm_cast at *; rw [← add_assoc, hfl]; omega + norm_cast at * + rw [← add_assoc, ← hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [not_le] at HK have hkop : k ∈ Finset.filter Even (Finset.Icc 3 14) := by simp only [Finset.mem_filter, Finset.mem_Icc, hk2, and_true]; omega From c9064312d2e432a6421e3ae841b4fed249148d36 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 13:22:51 +0100 Subject: [PATCH 08/43] refactor(NumberTheory/ModularForms): pull q-coordinate eta-product helpers up to DedekindEta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds three q-coordinate lemmas to `DedekindEta.lean`: - `multipliable_one_sub_pow {q : ℂ} (hq : ‖q‖ < 1)`: pointwise multipliability - `multipliableLocallyUniformlyOn_one_sub_pow`: local uniform convergence on the open unit disc - `differentiableOn_tprod_one_sub_pow_pow (k : ℕ)`: differentiability of the k-th power of the product on the open unit disc These cover the case `q = 0` (the cusp at infinity), which the existing eta-side lemmas (`multipliableLocallyUniformlyOn_eta` etc., stated on `ℍₒ`) cannot. In `Discriminant.lean`, deletes the three private helpers `multipliable_one_sub_pow`, `tendstoLocallyUniformlyOn_eta_prod`, `differentiableWithinAt_eta_prod_pow`, and rewrites `discriminant_cuspFunction_eqOn` and `discriminant_qExpansion_coeff_one` to work on the full open unit disc `Metric.ball 0 1` (instead of the arbitrary `Metric.ball 0 (1/2)`) and to call the new helpers from `DedekindEta.lean`. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/DedekindEta.lean | 54 +++++++++++++++ .../ModularForms/Discriminant.lean | 69 +++---------------- 2 files changed, 65 insertions(+), 58 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index b2905265b4ee9b..3ecd57ab784478 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -65,6 +65,60 @@ noncomputable def eta (z : ℂ) := 𝕢 24 z * ∏' n, (1 - eta_q n z) /-- Notation for the Dedekind eta function. -/ scoped[ModularForm] notation "η" => eta +/-! ### q-coordinate facts about `∏ (1 - q^(n+1))` + +The following lemmas describe the analytic behaviour of the infinite product +`∏' n, (1 - q^(n+1))` viewed as a function of `q` on the open unit disc, including the +behaviour at `q = 0` (the cusp at infinity). The eta-side lemmas below derive from these +by pulling back along `qParam 1 : ℍₒ → 𝔻 \ {0}`. +-/ + +/-- For `‖q‖ < 1`, the infinite product `∏ (1 - q^(n+1))` is multipliable. -/ +lemma multipliable_one_sub_pow {q : ℂ} (hq : ‖q‖ < 1) : + Multipliable fun n : ℕ ↦ 1 - q ^ (n + 1) := by + rw [show (fun n : ℕ ↦ 1 - q ^ (n + 1)) = (fun n ↦ 1 + (-q ^ (n + 1))) from by ext; ring] + apply multipliable_one_add_of_summable + simp only [norm_neg, norm_pow] + exact (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) + +/-- The infinite product `∏ (1 - q^(n+1))` converges locally uniformly on the open unit disc, +with limit `q ↦ ∏' n, (1 - q^(n+1))`. -/ +lemma multipliableLocallyUniformlyOn_one_sub_pow : + MultipliableLocallyUniformlyOn (fun n q ↦ 1 - q ^ (n + 1)) (Metric.ball (0 : ℂ) 1) := by + use fun q ↦ ∏' n, (1 - q ^ (n + 1)) + simp_rw [sub_eq_add_neg] + apply hasProdLocallyUniformlyOn_of_forall_compact Metric.isOpen_ball + intro K hK hcK + by_cases hN : K.Nonempty + · have hc : ContinuousOn (fun q : ℂ ↦ ‖q‖) K := by fun_prop + obtain ⟨q₀, hq₀, _, HB⟩ := hcK.exists_sSup_image_eq_and_ge hN hc + have hq₀_lt : ‖q₀‖ < 1 := by simpa [Metric.mem_ball, dist_zero_right] using hK hq₀ + have hsum : Summable fun n : ℕ ↦ ‖q₀‖ ^ (n + 1) := + (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq₀_lt) + refine hsum.hasProdUniformlyOn_nat_one_add hcK (.of_forall fun n x hx ↦ ?_) + (fun _ ↦ by fun_prop) + simpa [norm_pow] using pow_le_pow_left₀ (norm_nonneg _) (HB x hx) (n + 1) + · rw [hasProdUniformlyOn_iff_tendstoUniformlyOn] + simpa [not_nonempty_iff_eq_empty.mp hN] using tendstoUniformlyOn_empty + +/-- The infinite product `q ↦ ∏' n, (1 - q^(n+1))` is differentiable on the open unit disc. -/ +lemma differentiableOn_tprod_one_sub_pow : + DifferentiableOn ℂ (fun q ↦ ∏' n, (1 - q ^ (n + 1))) (Metric.ball (0 : ℂ) 1) := by + apply multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn.differentiableOn + ?_ Metric.isOpen_ball + filter_upwards with n + simpa [Finset.prod_fn] using DifferentiableOn.finset_prod (fun _ _ ↦ by fun_prop) + +/-- For any `k`, the function `q ↦ ∏' n, (1 - q^(n+1))^k` is differentiable on the +open unit disc. -/ +lemma differentiableOn_tprod_one_sub_pow_pow (k : ℕ) : + DifferentiableOn ℂ (fun q ↦ ∏' n, (1 - q ^ (n + 1)) ^ k) (Metric.ball (0 : ℂ) 1) := by + refine (differentiableOn_tprod_one_sub_pow.fun_pow k).congr fun q hq ↦ ?_ + have hq_lt : ‖q‖ < 1 := by simpa [Metric.mem_ball, dist_zero_right] using hq + exact (multipliable_one_sub_pow hq_lt).tprod_pow k + +/-! ### z-coordinate eta product facts (derived from q-coordinate versions) -/ + theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by simp [eta_q, eta_q_eq_pow, summable_nat_add_iff 1, norm_exp_two_pi_I_lt_one z] diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index fbca87f567f656..4fb13197343168 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -194,87 +194,40 @@ def discriminantCuspForm : CuspForm 𝒮ℒ 12 where rw [slash_action_generators_SL2Z discriminant_S_invariant discriminant_T_invariant] exact discriminant_isZeroAtImInfty -/-- The infinite product `∏ (1 - q^(n+1))` is multipliable for `‖q‖ < 1`. -/ -private lemma multipliable_one_sub_pow {q : ℂ} (hq : ‖q‖ < 1) : - Multipliable fun i ↦ 1 - q ^ (i + 1) := by - rw [show (fun i ↦ 1 - q ^ (i + 1)) = (fun i ↦ 1 + (-q ^ (i + 1))) from by ext; ring] - apply multipliable_one_add_of_summable - simp only [norm_neg, norm_pow] - exact (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) - /-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` -on `ball 0 (1/2)`. -/ +on the open unit disc. -/ private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) - (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) := by + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by intro q hq by_cases hq0 : q = 0 · simp only [hq0, zero_mul] exact Periodic.cuspFunction_zero_of_zero_at_inf one_pos discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex - · have hqn : ‖q‖ < 1 := lt_trans (by simpa [dist_zero_right] using hq) (by norm_num) + · have hqn : ‖q‖ < 1 := by simpa [dist_zero_right] using hq have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] - -- eta_q n z = (qParam 1 z)^(n+1), and qParam(invQParam(q)) = q have hqr := Periodic.qParam_right_inv one_ne_zero hq0 have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by simp [eta_q, hqr] simp only [hqr, heta] -/-- The partial products `∏_{i simp [differentiableOn_const] - | succ n ih => - simp_rw [Finset.prod_range_succ]; exact ih.mul (by fun_prop)) - Metric.isOpen_ball - have hmem := Metric.mem_ball_self (x := (0 : ℂ)) (by norm_num : (0 : ℝ) < 1 / 2) - -- (∏(1-q^(n+1)))^24 is differentiable as a power of a differentiable function - have h24 := (hdiff 0 hmem).pow (n := 24) - -- ∏(1-q^(n+1))^24 = (∏(1-q^(n+1)))^24 by tprod_pow, so congr gives differentiability - refine h24.congr (fun q hq ↦ ?_) (by simp) - exact (multipliable_one_sub_pow (lt_trans (by simpa [dist_zero_right] using hq) - (by norm_num : (1 : ℝ) / 2 < 1))).tprod_pow 24 - /-- The first q-expansion coefficient of the modular discriminant is 1. -/ lemma discriminant_qExpansion_coeff_one : (qExpansion 1 (discriminantCuspForm : ℍ → ℂ)).coeff 1 = 1 := by rw [qExpansion_coeff] simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, iteratedDeriv_zero] - have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) (1 / 2 : ℝ) := Metric.mem_ball_self (by norm_num) + have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos change deriv (cuspFunction 1 Δ) 0 = 1 - rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem] - rw [derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem)] - have : derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 = - derivWithin id (Metric.ball 0 (1 / 2)) 0 * (∏' i, (1 - (0 : ℂ) ^ (i + 1)) ^ 24) + - id 0 * derivWithin (fun q ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 := - derivWithin_mul differentiableWithinAt_id' differentiableWithinAt_eta_prod_pow - rw [this, derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem, + derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem), + show (fun q : ℂ ↦ q * ∏' n, (1 - q ^ (n + 1)) ^ 24) = + (fun q ↦ id q * ∏' n, (1 - q ^ (n + 1)) ^ 24) from rfl, + derivWithin_fun_mul differentiableWithinAt_id + (differentiableOn_tprod_one_sub_pow_pow 24 0 hmem), + derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] simp end From 4870bfc8b33fdf25a1bfecba326d9bd281bc51da Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 13:53:27 +0100 Subject: [PATCH 09/43] refactor(NumberTheory/ModularForms): derive z-coord eta lemmas from q-coord base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than having parallel q-coord and z-coord proofs of the same convergence facts about the eta product, derive the z-coord versions from the q-coord ones by composing with `Periodic.qParam 1 : ℍₒ → Metric.ball 0 1`. - `multipliableLocallyUniformlyOn_eta` is now derived from `multipliableLocallyUniformlyOn_one_sub_pow` via `TendstoLocallyUniformlyOn.comp`, shrinking the proof from ~14 lines to ~7. - `differentiableAt_eta_tprod` now derives from `differentiableOn_tprod_one_sub_pow` by chain rule (instead of going through the eta-side multipliable lemma). - `summable_eta_q` switched to `norm_qParam_lt_one` (which the q-coord material already uses) for consistency. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/DedekindEta.lean | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index 3ecd57ab784478..55411f1649cb51 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -120,24 +120,21 @@ lemma differentiableOn_tprod_one_sub_pow_pow (k : ℕ) : /-! ### z-coordinate eta product facts (derived from q-coordinate versions) -/ theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by - simp [eta_q, eta_q_eq_pow, summable_nat_add_iff 1, norm_exp_two_pi_I_lt_one z] + have hq : ‖(𝕢 (1 : ℝ) ↑z : ℂ)‖ < 1 := by exact_mod_cast norm_qParam_lt_one 1 z + simpa only [norm_neg, eta_q, norm_pow] using + (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) lemma multipliableLocallyUniformlyOn_eta : MultipliableLocallyUniformlyOn (fun n a ↦ 1 - eta_q n a) ℍₒ := by - use fun z ↦ ∏' n, (1 - eta_q n z) - simp_rw [sub_eq_add_neg] - apply hasProdLocallyUniformlyOn_of_forall_compact isOpen_upperHalfPlaneSet - intro K hK hcK - by_cases hN : K.Nonempty - · have hc : ContinuousOn (fun x ↦ ‖cexp (2 * π * I * x)‖) K := by fun_prop - obtain ⟨z, hz, hB, HB⟩ := hcK.exists_sSup_image_eq_and_ge hN hc - apply (summable_eta_q ⟨z, hK hz⟩).hasProdUniformlyOn_nat_one_add hcK - · filter_upwards with n x hx - simpa [eta_q, eta_q_eq_pow] using pow_le_pow_left₀ (by simp [norm_nonneg]) (HB x hx) _ - · simp_rw [eta_q, Periodic.qParam] - fun_prop - · rw [hasProdUniformlyOn_iff_tendstoUniformlyOn] - simpa [not_nonempty_iff_eq_empty.mp hN] using tendstoUniformlyOn_empty + refine ⟨fun z ↦ ∏' n, (1 - eta_q n z), ?_⟩ + rw [hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn] + have h := multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn + rw [hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn] at h + exact h.comp (Periodic.qParam 1) + (fun z hz ↦ by + simpa [Metric.mem_ball, dist_zero_right] using + (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) + (by fun_prop) lemma eta_tprod_ne_zero {z : ℂ} (hz : z ∈ ℍₒ) : ∏' n, (1 - eta_q n z) ≠ 0 := by refine tprod_one_add_ne_zero_of_summable (f := fun n ↦ -eta_q n z) ?_ ?_ @@ -179,10 +176,11 @@ lemma tsum_logDeriv_eta_q (z : ℂ) : ∑' n, logDeriv (fun x ↦ 1 - eta_q n x) lemma differentiableAt_eta_tprod {z : ℂ} (hz : z ∈ ℍₒ) : DifferentiableAt ℂ (fun x ↦ ∏' n, (1 - eta_q n x)) z := by - apply (multipliableLocallyUniformlyOn_eta.hasProdLocallyUniformlyOn.differentiableOn ?_ - isOpen_upperHalfPlaneSet z hz).differentiableAt (isOpen_upperHalfPlaneSet.mem_nhds hz) - filter_upwards with b - simpa [Finset.prod_fn] using DifferentiableOn.finset_prod (by fun_prop) + have hq : (𝕢 (1 : ℝ) z : ℂ) ∈ Metric.ball (0 : ℂ) 1 := by + simpa [Metric.mem_ball, dist_zero_right] using + (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1) + exact (((differentiableOn_tprod_one_sub_pow).differentiableAt + (Metric.isOpen_ball.mem_nhds hq)).comp z (by fun_prop : DifferentiableAt ℂ (𝕢 (1 : ℝ)) z)) theorem differentiableAt_eta_of_mem_upperHalfPlaneSet {z : ℂ} (hz : z ∈ ℍₒ) : DifferentiableAt ℂ eta z := From 53ec44010ea7c2c03c80ba923cd520e503ab0348 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 14:00:40 +0100 Subject: [PATCH 10/43] chore(NumberTheory/ModularForms): shorten `multipliableLocallyUniformlyOn_eta` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn` is `Iff.rfl`, so the two `rw` calls in the previous proof are unnecessary — a type ascription on the underlying `HasProdLocallyUniformlyOn` is enough to invoke `TendstoLocallyUniformlyOn.comp` via dot notation. Collapse the proof to a 6-line term-mode expression. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../NumberTheory/ModularForms/DedekindEta.lean | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index 55411f1649cb51..1b5e52c6561510 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -125,16 +125,12 @@ theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) lemma multipliableLocallyUniformlyOn_eta : - MultipliableLocallyUniformlyOn (fun n a ↦ 1 - eta_q n a) ℍₒ := by - refine ⟨fun z ↦ ∏' n, (1 - eta_q n z), ?_⟩ - rw [hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn] - have h := multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn - rw [hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn] at h - exact h.comp (Periodic.qParam 1) - (fun z hz ↦ by - simpa [Metric.mem_ball, dist_zero_right] using - (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) - (by fun_prop) + MultipliableLocallyUniformlyOn (fun n a ↦ 1 - eta_q n a) ℍₒ := + ⟨_, (multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn : + TendstoLocallyUniformlyOn _ _ _ _).comp (Periodic.qParam 1) + (fun z hz ↦ by simpa [Metric.mem_ball, dist_zero_right] using + (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) + (by fun_prop)⟩ lemma eta_tprod_ne_zero {z : ℂ} (hz : z ∈ ℍₒ) : ∏' n, (1 - eta_q n z) ≠ 0 := by refine tprod_one_add_ne_zero_of_summable (f := fun n ↦ -eta_q n z) ?_ ?_ From 1f1ec2dc04d69cce8c3bb9dfbba35589f7ebd7d5 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 14:10:52 +0100 Subject: [PATCH 11/43] refactor(NumberTheory/ModularForms): decompose dimension-formula proofs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extracts helper lemmas to shorten the two main proofs: - `tendsto_valueAtInfty`: a modular form whose `valueAtInfty` is `c` tends to `c` along `atImInfty`. Used in `E4_cube_sub_E6_sq_form_isCuspForm`. - `E4_cube_sub_E6_sq_form` (def): the explicit `ModularForm 𝒮ℒ 12` whose pointwise value is `E₄³ - E₆²`, with companion lemmas `_apply`, `_isCuspForm`, `_qExpansion_coeff_one`. The main theorem `discriminant_eq_E4_cube_sub_E6_sq` is now ~15 lines instead of ~70. - `coeffZero_eq_zero_of_pow_eq_smul`: the algebraic core of the weight-2 vanishing argument as a pure power-series fact (no modular forms). `weight_two_eq_zero_of_not_cuspForm` becomes a thin wrapper that transports the modular-form identities into the power-series form, shrinking from ~50 lines to ~25. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 183 ++++++++++-------- 1 file changed, 101 insertions(+), 82 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index f137c1580b49f3..8a517d753cce2b 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -247,100 +247,95 @@ private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := bernoulli'_eq_zero_of_odd (show Odd 5 from ⟨2, rfl⟩) (by norm_num)]] simp [ArithmeticFunction.sigma_one]; norm_num -/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ -theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : - discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by - set F : ModularForm 𝒮ℒ 12 := - ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) - (E₄.mul (ModularForm.mcast (show 4 + 4 = 4 + 4 from rfl) (E₄.mul E₄))) - +/-- A modular form whose `valueAtInfty` is `c` tends to `c` along `atImInfty`. -/ +private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : ℂ) + (hv : valueAtInfty (f : ℍ → ℂ) = c) : Filter.Tendsto f atImInfty (𝓝 c) := by + rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL + ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr + (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) + +/-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ +private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := + ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) + (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) - have hF : ∀ w, F w = E₄ w ^ 3 - E₆ w ^ 2 := fun w ↦ by - change E₄ w * (E₄ w * E₄ w) - E₆ w * E₆ w = E₄ w ^ 3 - E₆ w ^ 2; ring + +private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : + E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by + change E₄ z * (E₄ z * E₄ z) - E₆ z * E₆ z = _; ring + +private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by + refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ + rw [qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] + have h4 : Filter.Tendsto (E₄ : ℍ → ℂ) atImInfty (𝓝 1) := tendsto_valueAtInfty E₄ 1 (by + rw [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero _ ⟨2, rfl⟩) + have h6 : Filter.Tendsto (E₆ : ℍ → ℂ) atImInfty (𝓝 1) := tendsto_valueAtInfty E₆ 1 (by + rw [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero _ ⟨3, rfl⟩) + refine ((Filter.Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq + simpa using (h4.pow 3).sub (h6.pow 2) + +private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : + (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by + have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), + qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := + fun _ _ ↦ rfl have h0_4 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := E_qExpansion_coeff_zero _ ⟨2, rfl⟩ have h0_6 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := E_qExpansion_coeff_zero _ ⟨3, rfl⟩ - have hF_cusp : IsCuspForm F := (isCuspForm_iff_coeffZero_eq_zero F).mpr (by - rw [qExpansion_coeff_zero F one_pos one_mem_strictPeriods_SL] - have hv4 : valueAtInfty (E₄ : ℍ → ℂ) = 1 := by - rwa [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] - have hv6 : valueAtInfty (E₆ : ℍ → ℂ) = 1 := by - rwa [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] - change limUnder atImInfty (fun w ↦ E₄ w * (E₄ w * E₄ w) - E₆ w * E₆ w) = 0 - have htend : ∀ {k' : ℤ} (f : ModularForm 𝒮ℒ k') {c' : ℂ}, valueAtInfty (f : ℍ → ℂ) = c' → - Filter.Tendsto f atImInfty (𝓝 c') := fun {_} f {_} hv ↦ by - rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] - exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL - ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr - (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) - have h4 := htend E₄ hv4 - have h6 := htend E₆ hv6 - convert ((h4.mul (h4.mul h4)).sub (h6.mul h6)).limUnder_eq using 1 - norm_num) - obtain ⟨g, hg⟩ := hF_cusp + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub + (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)) + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub + rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = + (((ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - + ModularForm.mcast (by norm_num) (E₆.mul E₆) : ModularForm 𝒮ℒ 12)) : ℍ → ℂ) from rfl, + hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ + (ModularForm.mcast rfl (E₄.mul E₄)), hmcast, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, + Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, + Finset.map_singleton, Function.Embedding.prodMap, Prod.map, + Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, + Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one] + norm_num [h0_4, h0_6] + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ +theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : + discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by + obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g + have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) := by + congr 1; exact congr_arg DFunLike.coe hg + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) + from congr_arg DFunLike.coe hc.symm] + exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have hc_eq : c = 1728 := by - have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), - qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := - fun _ _ ↦ rfl - have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (F : ℍ → ℂ) := by - congr 1; exact congr_arg DFunLike.coe hg - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = - c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by - conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) - from congr_arg DFunLike.coe hc.symm] - exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, - mul_one] at h - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)) - simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ - (ModularForm.mcast rfl (E₄.mul E₄))] at h - simp only [hmcast] at h - rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] at h - simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, - Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, - Finset.map_singleton, Function.Embedding.prodMap, Prod.map, - Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, - Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, - E₆_qExpansion_coeff_one] at h - exact h.symm.trans (by norm_num [h0_4, h0_6]) + mul_one, E4_cube_sub_E6_sq_form_qExpansion_coeff_one] at h + exact h.symm have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := calc (1728 : ℂ) * discriminant z = c * discriminant z := by rw [hc_eq] _ = (c • discriminantCuspForm) z := rfl _ = g z := by rw [← hc] - _ = F z := congr_fun (congr_arg DFunLike.coe hg) z - _ = E₄ z ^ 3 - E₆ z ^ 2 := hF z + _ = E4_cube_sub_E6_sq_form z := congr_fun (congr_arg DFunLike.coe hg) z + _ = _ := E4_cube_sub_E6_sq_form_apply z linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 -private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) - (hf : ¬IsCuspForm f) : f = 0 := by - exfalso - obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one - (E_ne_zero _ ⟨2, rfl⟩ : (E₄ : ModularForm 𝒮ℒ 4) ≠ 0) (f.mul f) - obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one - (E_ne_zero _ ⟨3, rfl⟩ : (E₆ : ModularForm 𝒮ℒ 6) ≠ 0) ((f.mul f).mul f) - set p := qExpansion 1 f - have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = p * p := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ - rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul - rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm - have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = p * p * p := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ - have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f - rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from - congrArg DFunLike.coe hc6] at hsmul - rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 - rw [← hmul1]; exact hsmul.symm - have hp4_0 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := - E_qExpansion_coeff_zero _ ⟨2, rfl⟩ - have hp6_0 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := - E_qExpansion_coeff_zero _ ⟨3, rfl⟩ +/-- Algebraic core of the weight-2 vanishing argument: if a complex power series `p` +satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant +terms equal to `1` and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ +private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c6 : ℂ} + (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) + (hp4_1 : p4.coeff 1 = 240) (hp6_1 : p6.coeff 1 = -504) + (hqc4 : c4 • p4 = p * p) (hqc6 : c6 • p6 = p * p * p) : p.coeff 0 = 0 := by have h0_4 : c4 = p.coeff 0 ^ 2 := by have h := congr_arg (·.coeff 0) hqc4 simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, @@ -353,22 +348,46 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h have heq4 : p.coeff 0 ^ 2 * 240 = 2 * p.coeff 0 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc4 - simp only [PowerSeries.coeff_smul, smul_eq_mul, E₄_qExpansion_coeff_one] at h + simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_4] at h exact h have heq6 : p.coeff 0 ^ 3 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc6 - simp only [PowerSeries.coeff_smul, smul_eq_mul, E₆_qExpansion_coeff_one] at h + simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_6] at h exact h - refine hf ((isCuspForm_iff_coeffZero_eq_zero f).mpr <| - pow_eq_zero_iff (n := 3) three_ne_zero |>.mp ?_) + refine pow_eq_zero_iff (n := 3) three_ne_zero |>.mp ?_ have h0 : (1728 : ℂ) * p.coeff 0 ^ 3 = 0 := by linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 exact (mul_eq_zero.mp h0).resolve_left (by norm_num) +private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) + (hf : ¬IsCuspForm f) : f = 0 := by + exfalso + obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one + (E_ne_zero _ ⟨2, rfl⟩ : (E₄ : ModularForm 𝒮ℒ 4) ≠ 0) (f.mul f) + obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one + (E_ne_zero _ ⟨3, rfl⟩ : (E₆ : ModularForm 𝒮ℒ 6) ≠ 0) ((f.mul f).mul f) + have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = + qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ + rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm + have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = + qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ + have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f + rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from + congrArg DFunLike.coe hc6] at hsmul + rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 + rw [← hmul1]; exact hsmul.symm + exact hf <| (isCuspForm_iff_coeffZero_eq_zero f).mpr <| + coeffZero_eq_zero_of_pow_eq_smul (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) + (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one + hqc4 hqc6 + /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : Module.rank ℂ (ModularForm 𝒮ℒ (2 : ℤ)) = 0 := by From 9aee73773e5d6e237461aad506059c0360f8acc1 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 14:15:17 +0100 Subject: [PATCH 12/43] chore(NumberTheory/ModularForms): tighten dimension-formula proofs after decomposition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `discriminant_eq_E4_cube_sub_E6_sq`: move `hgΔ` back inside the local `hc_eq` block (it's only used there), inline `hgF`, and use `simpa` for the final step. - `E4_cube_sub_E6_sq_form_qExpansion_coeff_one`: minor simplification collapsing the chained `mcast`/`hmcast` rewrites. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 8a517d753cce2b..4e6c1ecc087c40 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -290,11 +290,10 @@ private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) (ModularForm.mcast (by norm_num) (E₆.mul E₆)) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = - (((ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) : ModularForm 𝒮ℒ 12)) : ℍ → ℂ) from rfl, - hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ - (ModularForm.mcast rfl (E₄.mul E₄)), hmcast, + rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = ((ModularForm.mcast (by norm_num) + (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - + ModularForm.mcast (by norm_num) (E₆.mul E₆) : ModularForm 𝒮ℒ 12) : ℍ → ℂ) from rfl, + hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ _, hmcast, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, @@ -309,17 +308,16 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g - have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) := by - congr 1; exact congr_arg DFunLike.coe hg - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by - conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) - from congr_arg DFunLike.coe hc.symm] - exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have hc_eq : c = 1728 := by - have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) - simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, - mul_one, E4_cube_sub_E6_sq_form_qExpansion_coeff_one] at h - exact h.symm + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) + from congr_arg DFunLike.coe hc.symm] + exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm + have h := congr_arg (·.coeff 1) <| + (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) + from congr_arg _ (congr_arg DFunLike.coe hg)).symm.trans hgΔ + simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, + E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := calc (1728 : ℂ) * discriminant z = c * discriminant z := by rw [hc_eq] From b8144c96040403f80814561bc005ac180eb6e4ff Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 14:18:38 +0100 Subject: [PATCH 13/43] =?UTF-8?q?chore(NumberTheory/ModularForms):=20wrap?= =?UTF-8?q?=20long=20lines=20to=20=E2=89=A4=20100=20chars?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wraps several lines in the dimension-formula proofs to fit within mathlib's 100-character line length limit. No semantic changes. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 4e6c1ecc087c40..cbbedae2751b12 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -168,12 +168,14 @@ lemma cuspForm_twelve_smul_discriminant (f : CuspForm 𝒮ℒ 12) : /-- For even `k ≥ 3`, the rank of `𝒮ℒ` modular forms is one more than the rank of cusp forms. -/ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k) : - Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by + Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = + 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by have h_add := Submodule.rank_quotient_add_rank (cuspFormSubmodule 𝒮ℒ (k : ℤ)) rw [show Module.rank ℂ ↥(cuspFormSubmodule 𝒮ℒ (k : ℤ)) = Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) from (LinearEquiv.rank_eq (CuspForm.equivCuspFormSubmodule 𝒮ℒ (k : ℤ))).symm] at h_add - suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 1 by + suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ + cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 1 by rw [← h_add, h1] have hE_coeff_zero := E_qExpansion_coeff_zero hk hk2 apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule 𝒮ℒ (k : ℤ)) (E hk)) @@ -268,12 +270,14 @@ private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ rw [qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] - have h4 : Filter.Tendsto (E₄ : ℍ → ℂ) atImInfty (𝓝 1) := tendsto_valueAtInfty E₄ 1 (by - rw [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] - exact E_qExpansion_coeff_zero _ ⟨2, rfl⟩) - have h6 : Filter.Tendsto (E₆ : ℍ → ℂ) atImInfty (𝓝 1) := tendsto_valueAtInfty E₆ 1 (by - rw [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] - exact E_qExpansion_coeff_zero _ ⟨3, rfl⟩) + have h4 : Filter.Tendsto (E₄ : ℍ → ℂ) atImInfty (𝓝 1) := + tendsto_valueAtInfty E₄ 1 <| by + rw [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero _ ⟨2, rfl⟩ + have h6 : Filter.Tendsto (E₆ : ℍ → ℂ) atImInfty (𝓝 1) := + tendsto_valueAtInfty E₆ 1 <| by + rw [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero _ ⟨3, rfl⟩ refine ((Filter.Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq simpa using (h4.pow 3).sub (h6.pow 2) @@ -292,7 +296,8 @@ private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = ((ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) : ModularForm 𝒮ℒ 12) : ℍ → ℂ) from rfl, + ModularForm.mcast (by norm_num) (E₆.mul E₆) : + ModularForm 𝒮ℒ 12) : ℍ → ℂ) from rfl, hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ _, hmcast, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] @@ -309,9 +314,11 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g have hc_eq : c = 1728 := by - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by - conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) - from congr_arg DFunLike.coe hc.symm] + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = + c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + conv_lhs => rw [show (g : ℍ → ℂ) = + ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) from + congr_arg DFunLike.coe hc.symm] exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have h := congr_arg (·.coeff 1) <| (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) @@ -327,9 +334,9 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : _ = _ := E4_cube_sub_E6_sq_form_apply z linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 -/-- Algebraic core of the weight-2 vanishing argument: if a complex power series `p` -satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant -terms equal to `1` and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ +/-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies +`c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` +and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c6 : ℂ} (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) (hp4_1 : p4.coeff 1 = 240) (hp6_1 : p6.coeff 1 = -504) @@ -371,10 +378,13 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ - rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul - rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm + rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from + congrArg DFunLike.coe hc4] at hsmul + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] + exact hsmul.symm have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = - qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by + qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) * + qExpansion 1 (f : ℍ → ℂ) := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from From 3ab18d1e84974910ed9bed4f10eec525be5b10aa Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 15:03:59 +0100 Subject: [PATCH 14/43] =?UTF-8?q?chore(NumberTheory/ModularForms):=20drop?= =?UTF-8?q?=20redundant=20show=20in=20E=E2=82=84/E=E2=82=86=20qExpansion?= =?UTF-8?q?=20lemmas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `E₄` and `E₆` are `noncomputable abbrev`s, so they reduce automatically and the explicit `show E₄ = E (...) from rfl` step in `E₄_qExpansion_coeff_one` and `E₆_qExpansion_coeff_one` was unnecessary. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/DimensionFormulas/LevelOne.lean | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index cbbedae2751b12..0c5c61cd10b273 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -231,16 +231,14 @@ private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) private lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by - rw [show (E₄ : ModularForm 𝒮ℒ 4) = E (by norm_num : (3 : ℕ) ≤ 4) from rfl, - E_qExpansion_coeff _ ⟨2, rfl⟩] + rw [E_qExpansion_coeff _ ⟨2, rfl⟩] simp only [one_ne_zero, ↓reduceIte] rw [show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num)]; exact bernoulli'_four] simp [ArithmeticFunction.sigma_one]; norm_num private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by - rw [show (E₆ : ModularForm 𝒮ℒ 6) = E (by norm_num : (3 : ℕ) ≤ 6) from rfl, - E_qExpansion_coeff _ ⟨3, rfl⟩] + rw [E_qExpansion_coeff _ ⟨3, rfl⟩] simp only [one_ne_zero, ↓reduceIte] rw [show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num), bernoulli'_def] From 1722006fd8c4487224519f0e8e2fc3bd7134d429 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 16:35:43 +0100 Subject: [PATCH 15/43] some golfs --- .../ModularForms/DedekindEta.lean | 4 +- .../DimensionFormulas/LevelOne.lean | 124 +++++++----------- .../ModularForms/Discriminant.lean | 11 +- 3 files changed, 53 insertions(+), 86 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index 1b5e52c6561510..c2abe6a5a5d7d0 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -117,8 +117,6 @@ lemma differentiableOn_tprod_one_sub_pow_pow (k : ℕ) : have hq_lt : ‖q‖ < 1 := by simpa [Metric.mem_ball, dist_zero_right] using hq exact (multipliable_one_sub_pow hq_lt).tprod_pow k -/-! ### z-coordinate eta product facts (derived from q-coordinate versions) -/ - theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by have hq : ‖(𝕢 (1 : ℝ) ↑z : ℂ)‖ < 1 := by exact_mod_cast norm_qParam_lt_one 1 z simpa only [norm_neg, eta_q, norm_pow] using @@ -130,7 +128,7 @@ lemma multipliableLocallyUniformlyOn_eta : TendstoLocallyUniformlyOn _ _ _ _).comp (Periodic.qParam 1) (fun z hz ↦ by simpa [Metric.mem_ball, dist_zero_right] using (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) - (by fun_prop)⟩ + (by fun_prop)⟩ lemma eta_tprod_ne_zero {z : ℂ} (hz : z ∈ ℍₒ) : ∏' n, (1 - eta_q n z) ≠ 0 := by refine tprod_one_add_ne_zero_of_summable (f := fun n ↦ -eta_q n z) ?_ ?_ diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 0c5c61cd10b273..0db6b772cb4a76 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -39,17 +39,16 @@ namespace CuspForm /-- Multiply a modular form of weight `k - 12` by the discriminant to get a cusp form of weight `k`. Built directly as a CuspForm (no `IsCuspForm` intermediary). -/ -def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := +def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := by let Δ' := CuspForm.toModularFormₗ discriminantCuspForm - ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) (by - have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := - (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans - (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero - rw [show (ModularForm.mcast _ (f.mul Δ') : ℍ → ℂ) = (f : ℍ → ℂ) * Δ' from rfl, - qExpansion_mul_coeff_zero - (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt - (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt, - hΔ', mul_zero]) + apply ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) + have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := + (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans + (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero + rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, + qExpansion_mul_coeff_zero + (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt + (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt,hΔ', mul_zero] @[simp] lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : @@ -57,9 +56,9 @@ lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : private lemma divByDiscriminant_slash_eq (f : CuspForm 𝒮ℒ k) (γ : SL(2, ℤ)) : (fun z ↦ f z / Δ z) ∣[k - 12] γ = fun z ↦ f z / Δ z := by - haveI : SlashInvariantFormClass (CuspForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := + have : SlashInvariantFormClass (CuspForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance - haveI : SlashInvariantFormClass (CuspForm 𝒮ℒ 12) (CongruenceSubgroup.Gamma 1) 12 := + have : SlashInvariantFormClass (CuspForm 𝒮ℒ 12) (CongruenceSubgroup.Gamma 1) 12 := CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance have hf := slash_action_eqn_SL'' f (mem_Gamma_one γ) have hΔ := slash_action_eqn_SL'' discriminantCuspForm (mem_Gamma_one γ) @@ -153,8 +152,7 @@ lemma cuspForm_rank_lt_twelve (hk : k < 12) : /-- The space of weight 12 cusp forms for `𝒮ℒ` has rank 1. -/ lemma cuspForm_rank_twelve : Module.rank ℂ (CuspForm 𝒮ℒ 12) = 1 := by - rw [LinearEquiv.rank_eq CuspForm.discriminantEquiv, - show (12 : ℤ) - 12 = 0 from by norm_num] + rw [LinearEquiv.rank_eq CuspForm.discriminantEquiv, show (12 : ℤ) - 12 = 0 from by norm_num] exact levelOne_weight_zero_rank_one /-- Every weight 12 cusp form for `𝒮ℒ` is a scalar multiple of the discriminant. -/ @@ -186,18 +184,14 @@ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ - have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ - cuspFormSubmodule 𝒮ℒ (k : ℤ) := - (isCuspForm_iff_coeffZero_eq_zero _).mpr (by - set c := (qExpansion 1 ↑f).coeff 0 with hc - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (k : ℤ))).map_sub - f (c • E hk) - simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub - rw [hsub] - have hcoe : ⇑(c • E hk) = c • (E hk : ℍ → ℂ) := rfl - rw [hcoe, qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk)] - simp only [_root_.map_sub, _root_.map_smul, smul_eq_mul, hE_coeff_zero, mul_one, ← hc, - sub_self]) + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ cuspFormSubmodule 𝒮ℒ (k : ℤ) := by + apply (isCuspForm_iff_coeffZero_eq_zero _).mpr + set c := (qExpansion 1 ↑f).coeff 0 with hc + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f (c • E hk) + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub + rw [hsub] + simp [qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk), + _root_.map_sub, _root_.map_smul, hE_coeff_zero, mul_one, ← hc] have h0 : ((cuspFormSubmodule 𝒮ℒ (k : ℤ)).mkQ (f - (qExpansion 1 ↑f).coeff 0 • E hk) : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 0 := (Submodule.Quotient.mk_eq_zero _).mpr h_mem @@ -211,15 +205,6 @@ end RankIdentity section DimensionFormula -/-! ### Helpers for weight 2 proof -/ - -/-- In a rank-one ℂ-module, every element is a scalar multiple of any nonzero element. -This is a thin wrapper around `finrank_eq_one_iff_of_nonzero'` adapted to `Module.rank`. -/ -private lemma exists_smul_eq_of_rank_one {M : Type*} [AddCommGroup M] [Module ℂ M] - (hrank : Module.rank ℂ M = 1) {e : M} (he : e ≠ 0) (f : M) : ∃ c : ℂ, c • e = f := - (finrank_eq_one_iff_of_nonzero' e he).mp - (Module.rank_eq_one_iff_finrank_eq_one.mp hrank) f - /-- Weight 4 modular forms for `𝒮ℒ` are 1-dimensional. -/ private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (4 : ℤ)) = 1 := (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨2, rfl⟩).trans @@ -249,10 +234,10 @@ private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := /-- A modular form whose `valueAtInfty` is `c` tends to `c` along `atImInfty`. -/ private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : ℂ) - (hv : valueAtInfty (f : ℍ → ℂ) = c) : Filter.Tendsto f atImInfty (𝓝 c) := by + (hv : valueAtInfty f = c) : Filter.Tendsto f atImInfty (𝓝 c) := by rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] - exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL - ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt.tendsto.comp + (qParam_tendsto_atImInfty one_pos)).congr (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ @@ -282,20 +267,13 @@ private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_f private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), - qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := - fun _ _ ↦ rfl - have h0_4 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := - E_qExpansion_coeff_zero _ ⟨2, rfl⟩ - have h0_6 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := - E_qExpansion_coeff_zero _ ⟨3, rfl⟩ + qExpansion 1 (mcast h f) = qExpansion 1 (f : ℍ → ℂ) := fun _ _ ↦ rfl have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)) + (mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) + (mcast (by norm_num) (E₆.mul E₆)) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = ((ModularForm.mcast (by norm_num) - (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) : - ModularForm 𝒮ℒ 12) : ℍ → ℂ) from rfl, + rw [show (E4_cube_sub_E6_sq_form) = ((mcast (by norm_num) + (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - mcast (by norm_num) (E₆.mul E₆))) from rfl, hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ _, hmcast, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] @@ -304,7 +282,7 @@ private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : Finset.map_singleton, Function.Embedding.prodMap, Prod.map, Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one] - norm_num [h0_4, h0_6] + norm_num [E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : @@ -312,14 +290,13 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g have hc_eq : c = 1728 := by - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = - c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm) := by conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) from congr_arg DFunLike.coe hc.symm] exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have h := congr_arg (·.coeff 1) <| - (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) + (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form) from congr_arg _ (congr_arg DFunLike.coe hg)).symm.trans hgΔ simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm @@ -330,7 +307,7 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : _ = g z := by rw [← hc] _ = E4_cube_sub_E6_sq_form z := congr_fun (congr_arg DFunLike.coe hg) z _ = _ := E4_cube_sub_E6_sq_form_apply z - linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 + linear_combination (1 / 1728 : ℂ) * h1728 /-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` @@ -366,33 +343,31 @@ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 exact (mul_eq_zero.mp h0).resolve_left (by norm_num) -private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) +private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) (hf : ¬IsCuspForm f) : f = 0 := by exfalso - obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one - (E_ne_zero _ ⟨2, rfl⟩ : (E₄ : ModularForm 𝒮ℒ 4) ≠ 0) (f.mul f) - obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one - (E_ne_zero _ ⟨3, rfl⟩ : (E₆ : ModularForm 𝒮ℒ 6) ≠ 0) ((f.mul f).mul f) + have h0 := Module.rank_eq_one_iff_finrank_eq_one.mp weight_four_rank_one + rw [(finrank_eq_one_iff_of_nonzero' E₄ (E_ne_zero _ ⟨2, rfl⟩ : E₄ ≠ 0))] at h0 + have h1 := Module.rank_eq_one_iff_finrank_eq_one.mp weight_six_rank_one + rw [(finrank_eq_one_iff_of_nonzero' E₆ (E_ne_zero _ ⟨3, rfl⟩ : E₆ ≠ 0))] at h1 + obtain ⟨c4, hc4⟩ := h0 (f.mul f) + obtain ⟨c6, hc6⟩ := h1 ((f.mul f).mul f) have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = - qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by + qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 f := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ - rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from + rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from congrArg DFunLike.coe hc4] at hsmul rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] exact hsmul.symm - have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = - qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) * - qExpansion 1 (f : ℍ → ℂ) := by + have hqc6 : c6 • qExpansion 1 E₆ = qExpansion 1 f * qExpansion 1 f * qExpansion 1 f := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f - rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from - congrArg DFunLike.coe hc6] at hsmul + rw [show (c6 • E₆ : ℍ → ℂ) = (f.mul f).mul f from congrArg DFunLike.coe hc6] at hsmul rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 - rw [← hmul1]; exact hsmul.symm + simp [← hmul1, hsmul.symm] exact hf <| (isCuspForm_iff_coeffZero_eq_zero f).mpr <| coeffZero_eq_zero_of_pow_eq_smul (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) - (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one - hqc4 hqc6 + (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one hqc4 hqc6 /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : @@ -402,8 +377,7 @@ theorem ModularForm.levelOne_weight_two_rank_zero : by_cases hf : IsCuspForm f · obtain ⟨g, hg⟩ := hf rw [← hg] - simp [rank_zero_iff_forall_zero.mp - (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] + simp [rank_zero_iff_forall_zero.mp (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] · exact weight_two_eq_zero_of_not_cuspForm f hf /-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ @@ -412,8 +386,7 @@ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : if 12 ∣ ((k : ℤ) - 2) then Nat.floor ((k : ℚ) / 12) else Nat.floor ((k : ℚ) / 12) + 1 := by induction k using Nat.strong_induction_on with | h k ihn => - rw [rank_eq_one_add_rank_cuspForm (by omega) hk2, - LinearEquiv.rank_eq CuspForm.discriminantEquiv] + rw [rank_eq_one_add_rank_cuspForm (by omega) hk2, LinearEquiv.rank_eq CuspForm.discriminantEquiv] by_cases HK : (3 : ℤ) ≤ ((k : ℤ) - 12) · have iH := ihn (k - 12) (by omega) (by omega) ((Nat.even_sub (by omega)).mpr (by simp only [hk2, true_iff]; decide)) @@ -426,7 +399,8 @@ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : Nat.floor_div_eq_one_add_floor_sub_div (k : ℚ) 12 (by norm_num) hk' by_cases h12 : 12 ∣ ((k) : ℤ) - 2 · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12] - norm_cast at *; rw [hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] + norm_cast at * + rw [hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [show ¬ 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12, Nat.cast_add, Nat.cast_one] norm_cast at * diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 4fb13197343168..a6a118d9fd92fd 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -197,8 +197,7 @@ def discriminantCuspForm : CuspForm 𝒮ℒ 12 where /-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` on the open unit disc. -/ private lemma discriminant_cuspFunction_eqOn : - Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) - (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by + Set.EqOn (cuspFunction 1 Δ) (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by intro q hq by_cases hq0 : q = 0 · simp only [hq0, zero_mul] @@ -208,14 +207,10 @@ private lemma discriminant_cuspFunction_eqOn : have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] - have hqr := Periodic.qParam_right_inv one_ne_zero hq0 - have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by - simp [eta_q, hqr] - simp only [hqr, heta] + simp [eta_q, Periodic.qParam_right_inv one_ne_zero hq0] /-- The first q-expansion coefficient of the modular discriminant is 1. -/ -lemma discriminant_qExpansion_coeff_one : - (qExpansion 1 (discriminantCuspForm : ℍ → ℂ)).coeff 1 = 1 := by +lemma discriminant_qExpansion_coeff_one : (qExpansion 1 discriminantCuspForm).coeff 1 = 1 := by rw [qExpansion_coeff] simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, iteratedDeriv_zero] From 8d4689c385bc5d5355fec6252ca8f523dc794495 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 16:51:52 +0100 Subject: [PATCH 16/43] more golfs --- .../DimensionFormulas/LevelOne.lean | 19 ++++++------------- .../ModularForms/Discriminant.lean | 3 +-- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 0db6b772cb4a76..1f6b388aaa7ca6 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -45,8 +45,7 @@ def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero - rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, - qExpansion_mul_coeff_zero + rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, qExpansion_mul_coeff_zero (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt,hΔ', mul_zero] @@ -70,8 +69,7 @@ private lemma divByDiscriminant_slash_eq (f : CuspForm 𝒮ℒ k) (γ : SL(2, show k + -(k - 12) = (12 : ℤ) from by ring] exact mul_div_mul_left (f z) (Δ z) (zpow_ne_zero _ hd) -private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : - (f : ℍ → ℂ) =O[atImInfty] Δ := by +private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : f =O[atImInfty] Δ := by have hf_decay := CuspFormClass.exp_decay_atImInfty (h := 1) f one_pos one_mem_strictPeriods_SL have hΔ_lower : ∀ᶠ τ : ℍ in atImInfty, ‖(fun τ : ℍ ↦ Real.exp (-2 * Real.pi * τ.im / 1)) τ‖ ≤ 2 * ‖Δ τ‖ := by @@ -216,16 +214,12 @@ private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) private lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by - rw [E_qExpansion_coeff _ ⟨2, rfl⟩] - simp only [one_ne_zero, ↓reduceIte] - rw [show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by + rw [E_qExpansion_coeff _ ⟨2, rfl⟩, show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num)]; exact bernoulli'_four] simp [ArithmeticFunction.sigma_one]; norm_num private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by - rw [E_qExpansion_coeff _ ⟨3, rfl⟩] - simp only [one_ne_zero, ↓reduceIte] - rw [show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by + rw [E_qExpansion_coeff _ ⟨3, rfl⟩, show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num), bernoulli'_def] norm_num [Finset.sum_range_succ, Finset.sum_range_zero, show Nat.choose 6 2 = 15 from by decide, show Nat.choose 6 4 = 15 from by decide, @@ -242,9 +236,8 @@ private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := - ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) - (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - - ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) + mcast (show 4 + (4 + 4) = 12 by norm_num) (E₄.mul (mcast rfl (E₄.mul E₄))) - + mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index a6a118d9fd92fd..4705397a850a06 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -216,14 +216,13 @@ lemma discriminant_qExpansion_coeff_one : (qExpansion 1 discriminantCuspForm).co iteratedDeriv_zero] have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos change deriv (cuspFunction 1 Δ) 0 = 1 - rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem, + simp [← derivWithin_of_isOpen Metric.isOpen_ball hmem, derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem), show (fun q : ℂ ↦ q * ∏' n, (1 - q ^ (n + 1)) ^ 24) = (fun q ↦ id q * ∏' n, (1 - q ^ (n + 1)) ^ 24) from rfl, derivWithin_fun_mul differentiableWithinAt_id (differentiableOn_tprod_one_sub_pow_pow 24 0 hmem), derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] - simp end From 97c057c64ba3231e956cc931aa971340d7604396 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 10 Apr 2026 17:37:14 +0100 Subject: [PATCH 17/43] cleanup --- .../ModularForms/CuspFormSubmodule.lean | 14 +- .../DimensionFormulas/LevelOne.lean | 178 ++++++++---------- .../ModularForms/Discriminant.lean | 2 +- 3 files changed, 85 insertions(+), 109 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index a9b6378449a2f0..f717c96303b259 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -3,9 +3,11 @@ Copyright (c) 2026 Chris Birkbeck. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ -import Mathlib.NumberTheory.ModularForms.QExpansion -import Mathlib.NumberTheory.ModularForms.LevelOne -import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion +module + +public import Mathlib.NumberTheory.ModularForms.QExpansion +public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion /-! # Cusp form submodule and IsCuspForm predicate @@ -31,11 +33,11 @@ q-expansion coefficient (for `𝒮ℒ`). q-expansion having vanishing constant term. -/ +@[expose] public noncomputable section + open UpperHalfPlane ModularForm Complex SlashInvariantForm SlashInvariantFormClass ModularFormClass MatrixGroups OnePoint Filter Topology -noncomputable section - variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} namespace CuspForm @@ -100,7 +102,7 @@ lemma isZeroAtImInfty_of_valueAtInfty_eq_zero (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) /-- An `𝒮ℒ` modular form with vanishing q-expansion constant term vanishes at every cusp. -/ -private lemma isZeroAt_of_coeffZero_eq_zero (f : ModularForm 𝒮ℒ k) +lemma isZeroAt_of_coeffZero_eq_zero (f : ModularForm 𝒮ℒ k) (h : (qExpansion 1 f).coeff 0 = 0) {c : OnePoint ℝ} (hc : IsCusp c 𝒮ℒ) : c.IsZeroAt f k := by rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 1f6b388aaa7ca6..30e85a8f7b3e8a 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -3,11 +3,13 @@ Copyright (c) 2026 Chris Birkbeck. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ -import Mathlib.Algebra.Order.Floor.Semifield -import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule -import Mathlib.NumberTheory.ModularForms.Discriminant -import Mathlib.Data.Rat.Star -import Mathlib.LinearAlgebra.Dimension.Localization +module + +public import Mathlib.Algebra.Order.Floor.Semifield +public import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule +public import Mathlib.NumberTheory.ModularForms.Discriminant +public import Mathlib.Data.Rat.Star +public import Mathlib.LinearAlgebra.Dimension.Localization /-! # Dimension formula for level 1 modular forms @@ -22,11 +24,11 @@ of even weight `k ≥ 3`. * `ModularForm.dimension_level_one`: the full dimension formula. -/ +@[expose] public noncomputable section + open UpperHalfPlane ModularForm Complex SlashInvariantForm SlashInvariantFormClass ModularFormClass CongruenceSubgroup MatrixGroups OnePoint Filter Topology EisensteinSeries -noncomputable section - /-! ### Delta isomorphism: `CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - 12)` -/ section DeltaIsomorphism @@ -45,9 +47,11 @@ def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero - rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, qExpansion_mul_coeff_zero + rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, + qExpansion_mul_coeff_zero (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt - (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt,hΔ', mul_zero] + (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt, + hΔ', mul_zero] @[simp] lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : @@ -182,10 +186,12 @@ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ - have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ cuspFormSubmodule 𝒮ℒ (k : ℤ) := by + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ + cuspFormSubmodule 𝒮ℒ (k : ℤ) := by apply (isCuspForm_iff_coeffZero_eq_zero _).mpr set c := (qExpansion 1 ↑f).coeff 0 with hc - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f (c • E hk) + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f + (c • E hk) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub rw [hsub] simp [qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk), @@ -228,139 +234,106 @@ private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := /-- A modular form whose `valueAtInfty` is `c` tends to `c` along `atImInfty`. -/ private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : ℂ) - (hv : valueAtInfty f = c) : Filter.Tendsto f atImInfty (𝓝 c) := by + (hv : valueAtInfty f = c) : Tendsto f atImInfty (𝓝 c) := by rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] - exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt.tendsto.comp - (qParam_tendsto_atImInfty one_pos)).congr - (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) + refine (((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt + |>.tendsto.comp (qParam_tendsto_atImInfty one_pos))).congr fun τ ↦ ?_ + exact eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := - mcast (show 4 + (4 + 4) = 12 by norm_num) (E₄.mul (mcast rfl (E₄.mul E₄))) - - mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) + mcast (by norm_num) ((E₄.mul E₄).mul E₄) - mcast (by norm_num) (E₆.mul E₆) private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by - change E₄ z * (E₄ z * E₄ z) - E₆ z * E₆ z = _; ring + change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _; ring private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ rw [qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] - have h4 : Filter.Tendsto (E₄ : ℍ → ℂ) atImInfty (𝓝 1) := - tendsto_valueAtInfty E₄ 1 <| by - rw [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] - exact E_qExpansion_coeff_zero _ ⟨2, rfl⟩ - have h6 : Filter.Tendsto (E₆ : ℍ → ℂ) atImInfty (𝓝 1) := - tendsto_valueAtInfty E₆ 1 <| by - rw [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] - exact E_qExpansion_coeff_zero _ ⟨3, rfl⟩ - refine ((Filter.Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq - simpa using (h4.pow 3).sub (h6.pow 2) + have hE : ∀ {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k), + Tendsto ((E hk : ModularForm 𝒮ℒ k) : ℍ → ℂ) atImInfty (𝓝 1) := fun hk hk2 ↦ + tendsto_valueAtInfty _ 1 <| by + rw [← qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero hk hk2 + refine ((Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq + simpa using ((hE _ ⟨2, rfl⟩).pow 3).sub ((hE _ ⟨3, rfl⟩).pow 2) private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by - have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), - qExpansion 1 (mcast h f) = qExpansion 1 (f : ℍ → ℂ) := fun _ _ ↦ rfl - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) - (mcast (by norm_num) (E₆.mul E₆)) - simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [show (E4_cube_sub_E6_sq_form) = ((mcast (by norm_num) - (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - mcast (by norm_num) (E₆.mul E₆))) from rfl, - hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ _, hmcast, + have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - + qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := + qExpansion_sub one_pos one_mem_strictPeriods_SL + (mcast (by norm_num) ((E₄.mul E₄).mul E₄)) (mcast (by norm_num) (E₆.mul E₆)) + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, - Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, - Finset.map_singleton, Function.Embedding.prodMap, Prod.map, - Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, - Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one] - norm_num [E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, + E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one, + E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + ring /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g + have hgE : (g : ℍ → ℂ) = E4_cube_sub_E6_sq_form := congrArg DFunLike.coe hg have hc_eq : c = 1728 := by - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm) := by - conv_lhs => rw [show (g : ℍ → ℂ) = - ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) from - congr_arg DFunLike.coe hc.symm] - exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm - have h := congr_arg (·.coeff 1) <| - (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form) - from congr_arg _ (congr_arg DFunLike.coe hg)).symm.trans hgΔ + have hcΔ : (c • discriminantCuspForm : ℍ → ℂ) = g := congrArg DFunLike.coe hc + have hgΔ := qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm + rw [hcΔ, hgE] at hgΔ + have h := congr_arg (·.coeff 1) hgΔ simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm - have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := - calc (1728 : ℂ) * discriminant z - = c * discriminant z := by rw [hc_eq] - _ = (c • discriminantCuspForm) z := rfl - _ = g z := by rw [← hc] - _ = E4_cube_sub_E6_sq_form z := congr_fun (congr_arg DFunLike.coe hg) z - _ = _ := E4_cube_sub_E6_sq_form_apply z + have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by + rw [← hc_eq, show c * discriminant z = (c • discriminantCuspForm) z from rfl, hc, + congr_fun hgE z, E4_cube_sub_E6_sq_form_apply] linear_combination (1 / 1728 : ℂ) * h1728 -/-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies -`c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` -and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ +/-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` +satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with +constant term `1` and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c6 : ℂ} (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) (hp4_1 : p4.coeff 1 = 240) (hp6_1 : p6.coeff 1 = -504) (hqc4 : c4 • p4 = p * p) (hqc6 : c6 • p6 = p * p * p) : p.coeff 0 = 0 := by - have h0_4 : c4 = p.coeff 0 ^ 2 := by - have h := congr_arg (·.coeff 0) hqc4 - simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, - Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp4_0, mul_one] at h - rw [sq]; exact h - have h0_6 : c6 = p.coeff 0 ^ 3 := by - have h := congr_arg (·.coeff 0) hqc6 - simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, - Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp6_0, mul_one] at h - rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h - have heq4 : p.coeff 0 ^ 2 * 240 = 2 * p.coeff 0 * p.coeff 1 := by - have h := congr_arg (·.coeff 1) hqc4 - simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h - rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_4] at h - exact h - have heq6 : p.coeff 0 ^ 3 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by - have h := congr_arg (·.coeff 1) hqc6 - simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h - rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_6] at h - exact h + have h40 := congr_arg (·.coeff 0) hqc4 + have h41 := congr_arg (·.coeff 1) hqc4 + have h60 := congr_arg (·.coeff 0) hqc6 + have h61 := congr_arg (·.coeff 1) hqc6 + simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, + Finset.Nat.antidiagonal_zero, Finset.Nat.antidiagonal_succ, Finset.sum_singleton, + Finset.sum_cons, Finset.map_singleton, Function.Embedding.prodMap, Prod.map, + Function.Embedding.coeFn_mk, Function.Embedding.refl_apply, hp4_0, hp4_1, hp6_0, hp6_1, + mul_one] at h40 h41 h60 h61 refine pow_eq_zero_iff (n := 3) three_ne_zero |>.mp ?_ have h0 : (1728 : ℂ) * p.coeff 0 ^ 3 = 0 := by - linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 + linear_combination 3 * p.coeff 0 * h41 - 2 * h61 - 720 * p.coeff 0 * h40 - 1008 * h60 exact (mul_eq_zero.mp h0).resolve_left (by norm_num) private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) (hf : ¬IsCuspForm f) : f = 0 := by exfalso - have h0 := Module.rank_eq_one_iff_finrank_eq_one.mp weight_four_rank_one - rw [(finrank_eq_one_iff_of_nonzero' E₄ (E_ne_zero _ ⟨2, rfl⟩ : E₄ ≠ 0))] at h0 - have h1 := Module.rank_eq_one_iff_finrank_eq_one.mp weight_six_rank_one - rw [(finrank_eq_one_iff_of_nonzero' E₆ (E_ne_zero _ ⟨3, rfl⟩ : E₆ ≠ 0))] at h1 - obtain ⟨c4, hc4⟩ := h0 (f.mul f) - obtain ⟨c6, hc6⟩ := h1 ((f.mul f).mul f) + obtain ⟨c4, hc4⟩ := (finrank_eq_one_iff_of_nonzero' E₄ (E_ne_zero _ ⟨2, rfl⟩)).mp + (Module.rank_eq_one_iff_finrank_eq_one.mp weight_four_rank_one) (f.mul f) + obtain ⟨c6, hc6⟩ := (finrank_eq_one_iff_of_nonzero' E₆ (E_ne_zero _ ⟨3, rfl⟩)).mp + (Module.rank_eq_one_iff_finrank_eq_one.mp weight_six_rank_one) ((f.mul f).mul f) have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 f := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ - rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from - congrArg DFunLike.coe hc4] at hsmul - rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] - exact hsmul.symm + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, + ← qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄, + show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from congrArg DFunLike.coe hc4] have hqc6 : c6 • qExpansion 1 E₆ = qExpansion 1 f * qExpansion 1 f * qExpansion 1 f := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ - have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f - rw [show (c6 • E₆ : ℍ → ℂ) = (f.mul f).mul f from congrArg DFunLike.coe hc6] at hsmul - rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 - simp [← hmul1, hsmul.symm] + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, + ← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f, + ← qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆, + show (c6 • E₆ : ℍ → ℂ) = (f.mul f).mul f from congrArg DFunLike.coe hc6] exact hf <| (isCuspForm_iff_coeffZero_eq_zero f).mpr <| coeffZero_eq_zero_of_pow_eq_smul (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) - (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one hqc4 hqc6 + (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one + hqc4 hqc6 /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : @@ -370,7 +343,8 @@ theorem ModularForm.levelOne_weight_two_rank_zero : by_cases hf : IsCuspForm f · obtain ⟨g, hg⟩ := hf rw [← hg] - simp [rank_zero_iff_forall_zero.mp (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] + simp [rank_zero_iff_forall_zero.mp + (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] · exact weight_two_eq_zero_of_not_cuspForm f hf /-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index ff85b397cc0b17..a570ab86c2b05e 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -177,7 +177,7 @@ lemma discriminant_isZeroAtImInfty : IsZeroAtImInfty Δ := by (discriminant_bounded_factor.congr fun z ↦ by congr 1) /-- The modular discriminant `Δ` as a cusp form of weight 12 and level 1. -/ -def discriminantCuspForm : CuspForm 𝒮ℒ 12 where +@[expose] def discriminantCuspForm : CuspForm 𝒮ℒ 12 where toFun := Δ slash_action_eq' A hA := by obtain ⟨A, rfl⟩ := hA From 8d9031061f15578f43bc70154db2d2b28e1cbe4a Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 13 Apr 2026 10:24:33 +0100 Subject: [PATCH 18/43] feat(NumberTheory/ModularForms): Coe from CuspForm to ModularForm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `CuspForm.toModularForm` and a `Coe (CuspForm Γ k) (ModularForm Γ k)` instance so cusp forms can be viewed as modular forms automatically. Refactors `CuspForm.toModularFormₗ` to delegate to this plain function and updates call sites. Co-Authored-By: Claude Opus 4.6 (1M context) --- Mathlib/NumberTheory/ModularForms/Basic.lean | 15 ++ .../ModularForms/CuspFormSubmodule.lean | 8 +- .../DimensionFormulas/LevelOne.lean | 191 ++++++++---------- 3 files changed, 104 insertions(+), 110 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index 3100c9f841d33d..9a356680b7c080 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -516,6 +516,21 @@ instance (priority := 99) [FunLike F ℍ ℂ] [CuspFormClass F Γ k] : ModularFo holo := CuspFormClass.holo bdd_at_cusps f _ hc g hg := (CuspFormClass.zero_at_cusps f hc g hg).boundedAtFilter +/-- The underlying modular form of a cusp form. -/ +def toModularForm (f : CuspForm Γ k) : ModularForm Γ k where + toSlashInvariantForm := f.toSlashInvariantForm + holo' := f.holo' + bdd_at_cusps' hc g hg := (f.zero_at_cusps' hc g hg).boundedAtFilter + +@[simp] +lemma toModularForm_apply (f : CuspForm Γ k) (z : ℍ) : (toModularForm f) z = f z := rfl + +/-- A cusp form can be viewed as a modular form. -/ +instance : Coe (CuspForm Γ k) (ModularForm Γ k) := ⟨toModularForm⟩ + +@[simp] +lemma coe_toModularForm (f : CuspForm Γ k) (z : ℍ) : ((f : ModularForm Γ k) : ℍ → ℂ) z = f z := rfl + /-- Transport a cusp form along an equality of subgroups. -/ def ofSubgroupEq {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : CuspForm Γ k) : CuspForm Γ' k where diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index f717c96303b259..5b7dbde9c17d3f 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -44,10 +44,7 @@ namespace CuspForm /-- The inclusion of cusp forms into modular forms, as a ℂ-linear map. -/ def toModularFormₗ [Γ.HasDetOne] : CuspForm Γ k →ₗ[ℂ] ModularForm Γ k where - toFun f := - { toSlashInvariantForm := f.toSlashInvariantForm - holo' := f.holo' - bdd_at_cusps' := fun hc g hg ↦ (f.zero_at_cusps' hc g hg).boundedAtFilter } + toFun := toModularForm map_add' _ _ := rfl map_smul' _ _ := rfl @@ -55,6 +52,9 @@ def toModularFormₗ [Γ.HasDetOne] : CuspForm Γ k →ₗ[ℂ] ModularForm Γ k lemma toModularFormₗ_apply [Γ.HasDetOne] (f : CuspForm Γ k) (z : ℍ) : (toModularFormₗ f) z = f z := rfl +lemma toModularFormₗ_eq_coe [Γ.HasDetOne] (f : CuspForm Γ k) : + toModularFormₗ f = (f : ModularForm Γ k) := rfl + lemma toModularFormₗ_injective [Γ.HasDetOne] : Function.Injective (toModularFormₗ : CuspForm Γ k → ModularForm Γ k) := fun _ _ h ↦ DFunLike.ext _ _ fun z ↦ congr_fun (congr_arg DFunLike.coe h) z diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 30e85a8f7b3e8a..fcfd2bb195e0b0 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -42,7 +42,7 @@ namespace CuspForm /-- Multiply a modular form of weight `k - 12` by the discriminant to get a cusp form of weight `k`. Built directly as a CuspForm (no `IsCuspForm` intermediary). -/ def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := by - let Δ' := CuspForm.toModularFormₗ discriminantCuspForm + let Δ' : ModularForm 𝒮ℒ 12 := discriminantCuspForm apply ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans @@ -65,15 +65,12 @@ private lemma divByDiscriminant_slash_eq (f : CuspForm 𝒮ℒ k) (γ : SL(2, CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance have hf := slash_action_eqn_SL'' f (mem_Gamma_one γ) have hΔ := slash_action_eqn_SL'' discriminantCuspForm (mem_Gamma_one γ) - ext z - rw [SL_slash_apply, hf, show Δ (γ • z) = denom γ z ^ (12 : ℤ) * Δ z from by - exact_mod_cast hΔ z] - have hd : (denom γ z : ℂ) ≠ 0 := denom_ne_zero γ z - rw [div_mul_eq_mul_div, mul_right_comm, ← zpow_add₀ hd, - show k + -(k - 12) = (12 : ℤ) from by ring] - exact mul_div_mul_left (f z) (Δ z) (zpow_ne_zero _ hd) - -private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : f =O[atImInfty] Δ := by + ext z; rw [SL_slash_apply, hf, show Δ (γ • z) = denom γ z ^ (12 : ℤ) * Δ z from by + exact_mod_cast hΔ z, div_mul_eq_mul_div, mul_right_comm, + ← zpow_add₀ (denom_ne_zero γ z), show k + -(k - 12) = (12 : ℤ) from by ring] + exact mul_div_mul_left (f z) (Δ z) (zpow_ne_zero _ (denom_ne_zero γ z)) + +lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : f =O[atImInfty] Δ := by have hf_decay := CuspFormClass.exp_decay_atImInfty (h := 1) f one_pos one_mem_strictPeriods_SL have hΔ_lower : ∀ᶠ τ : ℍ in atImInfty, ‖(fun τ : ℍ ↦ Real.exp (-2 * Real.pi * τ.im / 1)) τ‖ ≤ 2 * ‖Δ τ‖ := by @@ -82,37 +79,30 @@ private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : f =O[atIm filter_upwards [hprod] with τ hτ simp only [div_one] rw [discriminant_eq_q_prod, norm_mul, Real.norm_of_nonneg (Real.exp_pos _).le] - have hq_norm : ‖Function.Periodic.qParam 1 (τ : ℂ)‖ = - Real.exp (-2 * Real.pi * τ.im) := by + have hq_norm : ‖Function.Periodic.qParam 1 (τ : ℂ)‖ = Real.exp (-2 * Real.pi * τ.im) := by simp [Function.Periodic.qParam, Complex.norm_exp, Complex.mul_re, div_one] rw [← hq_norm] have hprod_bound : 1 / 2 ≤ ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24‖ := by - have hsub : ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24 - 1‖ < 1 / 2 := by - rwa [Complex.dist_eq] at hτ + have hsub : ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24 - 1‖ < 1 / 2 := by rwa [Complex.dist_eq] at hτ have h1 := norm_sub_norm_le (1 : ℂ) (∏' (n : ℕ), (1 - eta_q n τ) ^ 24) simp only [norm_one] at h1 linarith [norm_sub_rev (1 : ℂ) (∏' (n : ℕ), (1 - eta_q n τ) ^ 24)] - linarith [norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)), - mul_le_mul_of_nonneg_left hprod_bound - (norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)))] + linarith [norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)), mul_le_mul_of_nonneg_left + hprod_bound (norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)))] exact hf_decay.trans (Asymptotics.IsBigO.of_bound 2 hΔ_lower) /-- Divide a cusp form by the discriminant to get a modular form of weight `k - 12`. -/ def divDiscriminant (f : CuspForm 𝒮ℒ k) : ModularForm 𝒮ℒ (k - 12) where toFun z := f z / Δ z - slash_action_eq' A hA := by - obtain ⟨γ, rfl⟩ := hA - exact divByDiscriminant_slash_eq f γ + slash_action_eq' _ hA := by obtain ⟨γ, rfl⟩ := hA; exact divByDiscriminant_slash_eq f γ holo' := by rw [UpperHalfPlane.mdifferentiable_iff] - refine (UpperHalfPlane.mdifferentiable_iff.mp f.holo').div - (UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo') fun z hz ↦ ?_ - simpa [ofComplex_apply_of_im_pos hz] using discriminant_ne_zero ⟨z, hz⟩ + exact (UpperHalfPlane.mdifferentiable_iff.mp f.holo').div + (UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo') fun z hz ↦ by + simpa [ofComplex_apply_of_im_pos hz] using discriminant_ne_zero ⟨z, hz⟩ bdd_at_cusps' {c} hc := by - rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc - rw [isBoundedAt_iff_forall_SL2Z hc] - intro γ _ - rw [divByDiscriminant_slash_eq f γ, IsBoundedAtImInfty, BoundedAtFilter] + rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc; rw [isBoundedAt_iff_forall_SL2Z hc] + intro γ _; rw [divByDiscriminant_slash_eq f γ, IsBoundedAtImInfty, BoundedAtFilter] exact (Asymptotics.div_isBoundedUnder_of_isBigO (exp_decay_isBigO_discriminant f)).isBigO_one ℝ @@ -127,14 +117,8 @@ def discriminantEquiv : CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - map_add' a b := by ext z; simp [add_div] map_smul' c a := by ext z; simp [mul_div_assoc] invFun := ofMulDiscriminant - left_inv f := by - ext z - simp only [divDiscriminant_apply, ofMulDiscriminant_apply] - exact div_mul_cancel₀ (f z) (discriminant_ne_zero z) - right_inv f := by - ext z - simp only [ofMulDiscriminant_apply, divDiscriminant_apply] - exact mul_div_cancel_right₀ (f z) (discriminant_ne_zero z) + left_inv f := by ext z; simpa using div_mul_cancel₀ (f z) (discriminant_ne_zero z) + right_inv f := by ext z; simpa using mul_div_cancel_right₀ (f z) (discriminant_ne_zero z) end CuspForm @@ -159,49 +143,38 @@ lemma cuspForm_rank_twelve : Module.rank ℂ (CuspForm 𝒮ℒ 12) = 1 := by /-- Every weight 12 cusp form for `𝒮ℒ` is a scalar multiple of the discriminant. -/ lemma cuspForm_twelve_smul_discriminant (f : CuspForm 𝒮ℒ 12) : - ∃ c : ℂ, c • discriminantCuspForm = f := by - have hne : discriminantCuspForm ≠ 0 := fun h ↦ - discriminant_ne_zero UpperHalfPlane.I (congr_fun (congr_arg DFunLike.coe h) _) - exact (finrank_eq_one_iff_of_nonzero' discriminantCuspForm hne).mp + ∃ c : ℂ, c • discriminantCuspForm = f := + (finrank_eq_one_iff_of_nonzero' discriminantCuspForm (fun h ↦ + discriminant_ne_zero UpperHalfPlane.I (congr_fun (congr_arg DFunLike.coe h) _))).mp (Module.rank_eq_one_iff_finrank_eq_one.mp cuspForm_rank_twelve) f /-- For even `k ≥ 3`, the rank of `𝒮ℒ` modular forms is one more than the rank of cusp forms. -/ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k) : - Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = - 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by - have h_add := Submodule.rank_quotient_add_rank (cuspFormSubmodule 𝒮ℒ (k : ℤ)) - rw [show Module.rank ℂ ↥(cuspFormSubmodule 𝒮ℒ (k : ℤ)) = - Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) from - (LinearEquiv.rank_eq (CuspForm.equivCuspFormSubmodule 𝒮ℒ (k : ℤ))).symm] at h_add - suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ - cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 1 by + Module.rank ℂ (ModularForm 𝒮ℒ k) = 1 + Module.rank ℂ (CuspForm 𝒮ℒ k) := by + have h_add := Submodule.rank_quotient_add_rank (cuspFormSubmodule 𝒮ℒ k) + rw [show Module.rank ℂ ↥(cuspFormSubmodule 𝒮ℒ k) = Module.rank ℂ (CuspForm 𝒮ℒ k) from + (LinearEquiv.rank_eq (CuspForm.equivCuspFormSubmodule 𝒮ℒ k)).symm] at h_add + suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ k ⧸ cuspFormSubmodule 𝒮ℒ k) = 1 by rw [← h_add, h1] - have hE_coeff_zero := E_qExpansion_coeff_zero hk hk2 - apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule 𝒮ℒ (k : ℤ)) (E hk)) + have hE := E_qExpansion_coeff_zero hk hk2 + apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule 𝒮ℒ k) (E hk)) · intro h rw [Submodule.Quotient.mk_eq_zero] at h - exact one_ne_zero <| - hE_coeff_zero.symm.trans <| - (isCuspForm_iff_coeffZero_eq_zero _).mp h + exact one_ne_zero <| hE.symm.trans <| (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ - have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ - cuspFormSubmodule 𝒮ℒ (k : ℤ) := by + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ cuspFormSubmodule 𝒮ℒ k := by apply (isCuspForm_iff_coeffZero_eq_zero _).mpr set c := (qExpansion 1 ↑f).coeff 0 with hc - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f - (c • E hk) + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f (c • E hk) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub - rw [hsub] - simp [qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk), - _root_.map_sub, _root_.map_smul, hE_coeff_zero, mul_one, ← hc] - have h0 : ((cuspFormSubmodule 𝒮ℒ (k : ℤ)).mkQ (f - (qExpansion 1 ↑f).coeff 0 • - E hk) : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 0 := + rw [hsub]; simp [qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk), + _root_.map_sub, _root_.map_smul, hE, mul_one, ← hc] + have h0 : (cuspFormSubmodule 𝒮ℒ k).mkQ (f - (qExpansion 1 ↑f).coeff 0 • E hk) = 0 := (Submodule.Quotient.mk_eq_zero _).mpr h_mem - rw [map_sub, LinearMap.map_smul, Submodule.mkQ_apply, Submodule.mkQ_apply, - sub_eq_zero] at h0 - exact h0.symm + rwa [map_sub, LinearMap.map_smul, Submodule.mkQ_apply, Submodule.mkQ_apply, + sub_eq_zero, eq_comm] at h0 end RankIdentity @@ -210,12 +183,12 @@ end RankIdentity section DimensionFormula /-- Weight 4 modular forms for `𝒮ℒ` are 1-dimensional. -/ -private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (4 : ℤ)) = 1 := +private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 4) = 1 := (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨2, rfl⟩).trans ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) /-- Weight 6 modular forms for `𝒮ℒ` are 1-dimensional. -/ -private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ℤ)) = 1 := +private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 6) = 1 := (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨3, rfl⟩).trans ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) @@ -236,9 +209,9 @@ private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : ℂ) (hv : valueAtInfty f = c) : Tendsto f atImInfty (𝓝 c) := by rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] - refine (((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt - |>.tendsto.comp (qParam_tendsto_atImInfty one_pos))).congr fun τ ↦ ?_ - exact eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt + |>.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr + fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := @@ -256,22 +229,20 @@ private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_f tendsto_valueAtInfty _ 1 <| by rw [← qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] exact E_qExpansion_coeff_zero hk hk2 - refine ((Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq - simpa using ((hE _ ⟨2, rfl⟩).pow 3).sub ((hE _ ⟨3, rfl⟩).pow 2) + exact (Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) + (by simpa using ((hE _ ⟨2, rfl⟩).pow 3).sub ((hE _ ⟨3, rfl⟩).pow 2))).limUnder_eq private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = - qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := - qExpansion_sub one_pos one_mem_strictPeriods_SL - (mcast (by norm_num) ((E₄.mul E₄).mul E₄)) (mcast (by norm_num) (E₆.mul E₆)) + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := + qExpansion_sub one_pos one_mem_strictPeriods_SL (mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (mcast (by norm_num) (E₆.mul E₆)) rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, - E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one, - E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, + E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] ring /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ @@ -292,13 +263,30 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : congr_fun hgE z, E4_cube_sub_E6_sq_form_apply] linear_combination (1 / 1728 : ℂ) * h1728 +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring +`⨁ k, ModularForm 𝒮ℒ k`. -/ +theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq_in_graded_ring : + DirectSum.of (ModularForm 𝒮ℒ) 12 (discriminantCuspForm : ModularForm 𝒮ℒ 12) = + (1 / 1728 : ℂ) • (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by + have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = + DirectSum.of (ModularForm 𝒮ℒ) 12 (mcast (by norm_num) ((E₄.mul E₄).mul E₄)) := by + rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of]; rfl + have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = + DirectSum.of (ModularForm 𝒮ℒ) 12 (mcast (by norm_num) (E₆.mul E₆)) := by + rw [pow_two, DirectSum.of_mul_of]; rfl + rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] + congr 1; ext z + change discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) + rw [discriminant_eq_E4_cube_sub_E6_sq z]; ring + /-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c6 : ℂ} - (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) - (hp4_1 : p4.coeff 1 = 240) (hp6_1 : p6.coeff 1 = -504) - (hqc4 : c4 • p4 = p * p) (hqc6 : c6 • p6 = p * p * p) : p.coeff 0 = 0 := by + (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) (hp4_1 : p4.coeff 1 = 240) + (hp6_1 : p6.coeff 1 = -504) (hqc4 : c4 • p4 = p * p) + (hqc6 : c6 • p6 = p * p * p) : p.coeff 0 = 0 := by have h40 := congr_arg (·.coeff 0) hqc4 have h41 := congr_arg (·.coeff 1) hqc4 have h60 := congr_arg (·.coeff 0) hqc6 @@ -313,15 +301,14 @@ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c linear_combination 3 * p.coeff 0 * h41 - 2 * h61 - 720 * p.coeff 0 * h40 - 1008 * h60 exact (mul_eq_zero.mp h0).resolve_left (by norm_num) -private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) - (hf : ¬IsCuspForm f) : f = 0 := by +private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) (hf : ¬IsCuspForm f) : + f = 0 := by exfalso obtain ⟨c4, hc4⟩ := (finrank_eq_one_iff_of_nonzero' E₄ (E_ne_zero _ ⟨2, rfl⟩)).mp (Module.rank_eq_one_iff_finrank_eq_one.mp weight_four_rank_one) (f.mul f) obtain ⟨c6, hc6⟩ := (finrank_eq_one_iff_of_nonzero' E₆ (E_ne_zero _ ⟨3, rfl⟩)).mp (Module.rank_eq_one_iff_finrank_eq_one.mp weight_six_rank_one) ((f.mul f).mul f) - have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = - qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 f := by + have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 f := by rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, ← qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄, show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from congrArg DFunLike.coe hc4] @@ -337,46 +324,38 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : - Module.rank ℂ (ModularForm 𝒮ℒ (2 : ℤ)) = 0 := by - rw [rank_zero_iff_forall_zero] - intro f + Module.rank ℂ (ModularForm 𝒮ℒ 2) = 0 := by + rw [rank_zero_iff_forall_zero]; intro f by_cases hf : IsCuspForm f - · obtain ⟨g, hg⟩ := hf - rw [← hg] - simp [rank_zero_iff_forall_zero.mp - (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] + · obtain ⟨g, hg⟩ := hf; rw [← hg] + simp [rank_zero_iff_forall_zero.mp (cuspForm_rank_lt_twelve (by norm_num)) g] · exact weight_two_eq_zero_of_not_cuspForm f hf /-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : - Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = - if 12 ∣ ((k : ℤ) - 2) then Nat.floor ((k : ℚ) / 12) + Module.rank ℂ (ModularForm 𝒮ℒ k) = if 12 ∣ ((k : ℤ) - 2) then Nat.floor ((k : ℚ) / 12) else Nat.floor ((k : ℚ) / 12) + 1 := by induction k using Nat.strong_induction_on with | h k ihn => rw [rank_eq_one_add_rank_cuspForm (by omega) hk2, LinearEquiv.rank_eq CuspForm.discriminantEquiv] - by_cases HK : (3 : ℤ) ≤ ((k : ℤ) - 12) + by_cases HK : (3 : ℤ) ≤ (k : ℤ) - 12 · have iH := ihn (k - 12) (by omega) (by omega) ((Nat.even_sub (by omega)).mpr (by simp only [hk2, true_iff]; decide)) - have hk12 : (((k - 12) : ℕ) : ℤ) = k - 12 := by - norm_cast; exact Eq.symm (Int.subNatNat_of_le (by omega)) + have hk12 : (((k - 12) : ℕ) : ℤ) = k - 12 := by grind rw [hk12] at iH rw [iH, show ((k - 12 : ℕ) : ℚ) = (k : ℚ) - 12 from by norm_cast] - have hfl (hk' : (12 : ℚ) ≤ k) : - ⌊(k : ℚ) / 12⌋₊ = 1 + ⌊((k : ℚ) - 12) / 12⌋₊ := + have hfl (hk' : (12 : ℚ) ≤ k) : ⌊(k : ℚ) / 12⌋₊ = 1 + ⌊((k : ℚ) - 12) / 12⌋₊ := Nat.floor_div_eq_one_add_floor_sub_div (k : ℚ) 12 (by norm_num) hk' - by_cases h12 : 12 ∣ ((k) : ℤ) - 2 - · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12] - norm_cast at * + by_cases h12 : 12 ∣ (k : ℤ) - 2 + · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12]; norm_cast at * rw [hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [show ¬ 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12, - Nat.cast_add, Nat.cast_one] - norm_cast at * + Nat.cast_add, Nat.cast_one]; norm_cast at * rw [← add_assoc, ← hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [not_le] at HK have hkop : k ∈ Finset.filter Even (Finset.Icc 3 14) := by simp only [Finset.mem_filter, Finset.mem_Icc, hk2, and_true]; omega - rw [show Finset.filter Even (Finset.Icc 3 14) = ({4, 6, 8, 10, 12, 14} : Finset ℕ) - from by decide] at hkop + rw [show Finset.filter Even (Finset.Icc 3 14) = ({4, 6, 8, 10, 12, 14} : Finset ℕ) from by + decide] at hkop fin_cases hkop <;> simp only [Nat.cast_ofNat, Int.reduceSub, Int.reduceNeg] at * all_goals first | exact (congrArg (1 + ·) (levelOne_neg_weight_rank_zero (by omega))).trans (by norm_cast) From 43c4faed12cd741a4c5dbee9f2952271aa4f0e43 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 13 Apr 2026 10:58:47 +0100 Subject: [PATCH 19/43] chore: run mk_all to fix Mathlib.lean import order Co-Authored-By: Claude Opus 4.6 (1M context) --- Mathlib.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib.lean b/Mathlib.lean index 2c55ac3de481c2..99802f82937a45 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5589,6 +5589,7 @@ public import Mathlib.NumberTheory.ModularForms.Cusps public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Delta public import Mathlib.NumberTheory.ModularForms.Derivative +public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.Discriminant public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Defs @@ -5607,7 +5608,6 @@ public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold public import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable public import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable public import Mathlib.NumberTheory.ModularForms.LevelOne -public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.NormTrace public import Mathlib.NumberTheory.ModularForms.Petersson public import Mathlib.NumberTheory.ModularForms.QExpansion From f91e8daf2061d88d325ff4fe721f15baea3d921b Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 13 Apr 2026 11:26:41 +0100 Subject: [PATCH 20/43] feat(NumberTheory/ModularForms): CuspFormClass instance for cuspFormSubmodule Co-Authored-By: Claude Opus 4.6 (1M context) --- Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index 5b7dbde9c17d3f..86faed2b8a72fa 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -85,6 +85,15 @@ lemma isCuspForm_iff [Γ.HasDetOne] (f : ModularForm Γ k) : refine ⟨fun ⟨g, hg⟩ c hc ↦ hg ▸ g.zero_at_cusps' hc, fun h ↦ ⟨⟨f.toSlashInvariantForm, f.holo', h⟩, rfl⟩⟩ +instance [Γ.HasDetOne] : FunLike (cuspFormSubmodule Γ k) ℍ ℂ where + coe f := (f : ModularForm Γ k) + coe_injective' _ _ h := Subtype.ext (DFunLike.ext _ _ (congr_fun h)) + +instance [Γ.HasDetOne] : CuspFormClass (cuspFormSubmodule Γ k) Γ k where + slash_action_eq f := (f : ModularForm Γ k).slash_action_eq' + holo f := (f : ModularForm Γ k).holo' + zero_at_cusps f := (isCuspForm_iff f.1).mp f.2 + section SL2Z open EisensteinSeries From b5f280eba93b610f8e2cb370d44e4b1f1a0941af Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 11:30:10 +0100 Subject: [PATCH 21/43] =?UTF-8?q?feat(NumberTheory/ModularForms):=20restor?= =?UTF-8?q?e=20=CE=94=20=3D=20(E=E2=82=84=C2=B3=20-=20E=E2=82=86=C2=B2)=20?= =?UTF-8?q?/=201728?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restores ModularForm.discriminant_eq_E4_cube_sub_E6_sq, ported from earlier work (commit 8d9031061f1) and updated to current master's API: - discriminantCuspForm → CuspForm.discriminant - cuspForm_twelve_smul_discriminant → CuspForm.exists_smul_discriminant_of_weight_eq_twelve - qExpansion_sub/qExpansion_smul → ModularFormClass.qExpansion_sub/qExpansion_smul - The `IsCuspForm` proof uses an algebraic q-expansion split rather than the no-longer-available tendsto_valueAtInfty. Adds supporting lemmas in Discriminant.lean: - discriminant_cuspFunction_eqOn (private) - differentiableWithinAt_eta_prod_pow (private; shorter than original since differentiableOn_tprod_one_sub_pow_pow is now in mathlib) - discriminant_qExpansion_coeff_one Also drops merge-induced duplicates of master lemmas (summable_eta_q, multipliableLocallyUniformlyOn_eta, differentiableOn_tprod_one_sub_pow, differentiableOn_tprod_one_sub_pow_pow, one_mem_strictPeriods_SL) and removes two unused/duplicating helpers (floor_div_eq_one_add_floor_sub_div, which is too specific for a top-level file and unused, and ModularForm.ofSubgroupEq, which duplicates mcast). --- Mathlib/Algebra/Order/Floor/Semifield.lean | 5 -- Mathlib/NumberTheory/ModularForms/Basic.lean | 12 ---- .../ModularForms/DedekindEta.lean | 29 --------- .../DimensionFormulas/LevelOne.lean | 59 +++++++++++++++++++ .../ModularForms/Discriminant.lean | 44 ++++++++++++++ .../NumberTheory/ModularForms/LevelOne.lean | 3 - 6 files changed, 103 insertions(+), 49 deletions(-) diff --git a/Mathlib/Algebra/Order/Floor/Semifield.lean b/Mathlib/Algebra/Order/Floor/Semifield.lean index 43af3f6b88c848..e3bdf9a4329851 100644 --- a/Mathlib/Algebra/Order/Floor/Semifield.lean +++ b/Mathlib/Algebra/Order/Floor/Semifield.lean @@ -53,11 +53,6 @@ end LinearOrderedSemifield section LinearOrderedField variable [Field K] [LinearOrder K] [IsOrderedRing K] [FloorSemiring K] {a b : K} -theorem floor_div_eq_one_add_floor_sub_div (k a : K) (ha : 0 < a) (hak : a ≤ k) : - ⌊k / a⌋₊ = 1 + ⌊(k - a) / a⌋₊ := by - rw [sub_div, div_self ha.ne', Nat.floor_sub_one] - exact (Nat.add_sub_cancel' (Nat.le_floor (mod_cast (one_le_div₀ ha).mpr hak))).symm - lemma mul_lt_floor (hb₀ : 0 < b) (hb : b < 1) (hba : ⌈b / (1 - b)⌉₊ ≤ a) : b * a < ⌊a⌋₊ := by calc b * a < b * (⌊a⌋₊ + 1) := by gcongr; apply lt_floor_add_one diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index 9ef354b962b0d6..cfb4abba9ed314 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -395,18 +395,6 @@ lemma coe_intCast [Γ.HasDetPlusMinusOne] (z : ℤ) : lemma toSlashInvariantForm_intCast [Γ.HasDetPlusMinusOne] (z : ℤ) : (z : ModularForm Γ 0).toSlashInvariantForm = z := rfl -/-- Transport a modular form along an equality of subgroups. -/ -def ofSubgroupEq {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) : - ModularForm Γ' k where - toFun := f - slash_action_eq' A hA := f.slash_action_eq' A (h ▸ hA) - holo' := f.holo' - bdd_at_cusps' hc := f.bdd_at_cusps' (h ▸ hc) - -@[simp] -lemma ofSubgroupEq_apply {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) - (z : ℍ) : (f.ofSubgroupEq h) z = f z := rfl - end ModularForm namespace CuspForm diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index 0a0107a7debfb9..b8b69cf7e4c144 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -108,35 +108,6 @@ lemma multipliableLocallyUniformlyOn_eta : multipliableLocallyUniformlyOn_one_sub_pow.comp (𝕢 1) (fun z hz ↦ by simpa using norm_qParam_lt_one 1 ⟨z, hz⟩) (by fun_prop) -/-- The infinite product `q ↦ ∏' n, (1 - q^(n+1))` is differentiable on the open unit disc. -/ -lemma differentiableOn_tprod_one_sub_pow : - DifferentiableOn ℂ (fun q ↦ ∏' n, (1 - q ^ (n + 1))) (Metric.ball (0 : ℂ) 1) := by - apply multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn.differentiableOn - ?_ Metric.isOpen_ball - filter_upwards with n - simpa [Finset.prod_fn] using DifferentiableOn.finset_prod (fun _ _ ↦ by fun_prop) - -/-- For any `k`, the function `q ↦ ∏' n, (1 - q^(n+1))^k` is differentiable on the -open unit disc. -/ -lemma differentiableOn_tprod_one_sub_pow_pow (k : ℕ) : - DifferentiableOn ℂ (fun q ↦ ∏' n, (1 - q ^ (n + 1)) ^ k) (Metric.ball (0 : ℂ) 1) := by - refine (differentiableOn_tprod_one_sub_pow.fun_pow k).congr fun q hq ↦ ?_ - have hq_lt : ‖q‖ < 1 := by simpa [Metric.mem_ball, dist_zero_right] using hq - exact (multipliable_one_sub_pow hq_lt).tprod_pow k - -theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by - have hq : ‖(𝕢 (1 : ℝ) ↑z : ℂ)‖ < 1 := by exact_mod_cast norm_qParam_lt_one 1 z - simpa only [norm_neg, eta_q, norm_pow] using - (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) - -lemma multipliableLocallyUniformlyOn_eta : - MultipliableLocallyUniformlyOn (fun n a ↦ 1 - eta_q n a) ℍₒ := - ⟨_, (multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn : - TendstoLocallyUniformlyOn _ _ _ _).comp (Periodic.qParam 1) - (fun z hz ↦ by simpa [Metric.mem_ball, dist_zero_right] using - (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) - (by fun_prop)⟩ - lemma eta_tprod_ne_zero {z : ℂ} (hz : z ∈ ℍₒ) : ∏' n, (1 - eta_q n z) ≠ 0 := by refine tprod_one_add_ne_zero_of_summable (f := fun n ↦ -eta_q n z) ?_ ?_ · exact fun i ↦ by simpa using one_sub_eta_q_ne_zero i hz diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 0ddf7a000f7e55..83083c0afe4ccb 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -163,6 +163,65 @@ lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by norm_num [E_qExpansion_coeff _ ⟨3, rfl⟩, show bernoulli 6 = 1 / 42 by decide +kernel] +/-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ +private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := + ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - + ModularForm.mcast (by norm_num) (E₆.mul E₆) + +private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : + E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by + change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ + ring + +private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by + refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ + have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := + ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)) + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + have h4 := E_qExpansion_coeff_zero (show (3 : ℕ) ≤ 4 by norm_num) ⟨2, rfl⟩ + have h6 := E_qExpansion_coeff_zero (show (3 : ℕ) ≤ 6 by norm_num) ⟨3, rfl⟩ + rw [PowerSeries.coeff_zero_eq_constantCoeff] at h4 h6 ⊢ + simp [h4, h6] + +private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : + (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by + have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := + ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)) + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, + E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, + E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + ring + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ +theorem discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : + discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by + obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm + obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g + have hgE : (g : ℍ → ℂ) = E4_cube_sub_E6_sq_form := congrArg DFunLike.coe hg + have hc_eq : c = 1728 := by + have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc + have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c + CuspForm.discriminant + rw [hcΔ, hgE] at hgΔ + have h := congr_arg (·.coeff 1) hgΔ + simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, + E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm + have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by + rw [← hc_eq, show c * discriminant z = (c • CuspForm.discriminant) z from rfl, hc, + congr_fun hgE z, E4_cube_sub_E6_sq_form_apply] + linear_combination (1 / 1728 : ℂ) * h1728 + /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` and first-order coefficients `240` and `-504`, then `p = 0`. -/ diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 582d40a8fefd1d..d22a368066fde1 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -192,6 +192,50 @@ lemma exp_isBigO_discriminant : (fun τ ↦ Real.exp (-2 * π * τ.im)) =O[atImI grind [norm_one, norm_sub_rev] linarith [norm_nonneg (𝕢 1 τ), mul_le_mul_of_nonneg_left hprod_bound (norm_nonneg (𝕢 1 τ))] +/-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` +on `ball 0 (1/2)`. -/ +private lemma discriminant_cuspFunction_eqOn : + Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) := by + intro q hq + by_cases hq0 : q = 0 + · simp only [hq0, zero_mul] + exact Periodic.cuspFunction_zero_of_zero_at_inf one_pos + discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex + · have hqn : ‖q‖ < 1 := lt_trans (by simpa [dist_zero_right] using hq) (by norm_num) + have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 + rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, + comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] + have hqr := Periodic.qParam_right_inv one_ne_zero hq0 + have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by + simp [eta_q, hqr] + simp only [hqr, heta] + +/-- The product `∏' i, (1 - q^(i+1))^24` is differentiable within `ball 0 (1/2)` at 0. -/ +private lemma differentiableWithinAt_eta_prod_pow : + DifferentiableWithinAt ℂ (fun q : ℂ ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) + (Metric.ball 0 (1 / 2)) 0 := + (differentiableOn_tprod_one_sub_pow_pow 24 0 + (by simp [Metric.mem_ball] : (0 : ℂ) ∈ Metric.ball 0 1)).mono + (Metric.ball_subset_ball (by norm_num)) + +/-- The first q-expansion coefficient of the modular discriminant is 1. -/ +lemma discriminant_qExpansion_coeff_one : + (qExpansion 1 (Δ : ℍ → ℂ)).coeff 1 = 1 := by + rw [qExpansion_coeff] + simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, + iteratedDeriv_zero] + have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) (1 / 2 : ℝ) := Metric.mem_ball_self (by norm_num) + change deriv (cuspFunction 1 Δ) 0 = 1 + rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem] + rw [derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem)] + have : derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 = + derivWithin id (Metric.ball 0 (1 / 2)) 0 * (∏' i, (1 - (0 : ℂ) ^ (i + 1)) ^ 24) + + id 0 * derivWithin (fun q ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 := + derivWithin_mul differentiableWithinAt_id' differentiableWithinAt_eta_prod_pow + rw [this, derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + simp + end end ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne.lean index 90e84f176c71fc..18b54c2095a625 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne.lean @@ -72,9 +72,6 @@ namespace ModularFormClass variable [ModularFormClass F 𝒮ℒ k] -lemma one_mem_strictPeriods_SL : (1 : ℝ) ∈ (𝒮ℒ : Subgroup (GL (Fin 2) ℝ)).strictPeriods := - Gamma_one_coe_eq_SL ▸ one_mem_strictPeriods_SL2Z - private theorem cuspFunction_eqOn_const_of_nonpos_wt (hk : k ≤ 0) (f : F) : Set.EqOn (cuspFunction 1 f) (const ℂ (cuspFunction 1 f 0)) (Metric.ball 0 1) := by refine eq_const_of_exists_le (fun q hq ↦ ?_) (exp_nonneg (-π)) ?_ (fun q hq ↦ ?_) From 5ebde02548a1ed952501090401a0f46abd55e265 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 12:53:34 +0100 Subject: [PATCH 22/43] =?UTF-8?q?chore(NumberTheory/ModularForms):=20clean?= =?UTF-8?q?=20up=20=CE=94=20=3D=20(E=E2=82=84=C2=B3=20-=20E=E2=82=86=C2=B2?= =?UTF-8?q?)=20/=201728=20proof?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Applies findings from /simplify code review: - Extract the duplicated `qExpansion_sub` rewrite chain into a shared `E₄CubeSubE₆SqForm_qExpansion_eq` helper. Both `_isCuspForm` and `_qExpansion_coeff_one` now reduce to a one-line `rw` of this helper (~16 lines saved). - `linear_combination (1 / 1728 : ℂ) * h1728` → `linear_combination h1728 / 1728`. - Rename `E4_cube_sub_E6_sq_form` → `E₄CubeSubE₆SqForm` (camelCase + subscripts per mathlib def naming convention) and `discriminant_eq_E4_cube_sub_E6_sq` → `discriminant_eq_E₄_cube_sub_E₆_sq`. - Use `ball 0 1` instead of `ball 0 (1/2)` in `discriminant_cuspFunction_eqOn` and `discriminant_qExpansion_coeff_one` (the actual constraint is `‖q‖ < 1`), which lets `differentiableOn_tprod_one_sub_pow_pow` apply directly and removes the now-unnecessary `differentiableWithinAt_eta_prod_pow` helper. --- .../DimensionFormulas/LevelOne.lean | 65 +++++++++---------- .../ModularForms/Discriminant.lean | 48 +++++--------- 2 files changed, 45 insertions(+), 68 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 83083c0afe4ccb..f32cf75aa63e3d 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -164,63 +164,58 @@ lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by norm_num [E_qExpansion_coeff _ ⟨3, rfl⟩, show bernoulli 6 = 1 / 42 by decide +kernel] /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ -private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := +private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - ModularForm.mcast (by norm_num) (E₆.mul E₆) -private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : - E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by +private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : + E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ ring -private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by - refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ - have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = - qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := - ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)) - rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - have h4 := E_qExpansion_coeff_zero (show (3 : ℕ) ≤ 4 by norm_num) ⟨2, rfl⟩ - have h6 := E_qExpansion_coeff_zero (show (3 : ℕ) ≤ 6 by norm_num) ⟨3, rfl⟩ - rw [PowerSeries.coeff_zero_eq_constantCoeff] at h4 h6 ⊢ - simp [h4, h6] - -private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : - (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by - have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = - qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := - ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)) - rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, +private lemma E₄CubeSubE₆SqForm_qExpansion_eq : + qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ) = + qExpansion 1 (E₄ : ℍ → ℂ) * qExpansion 1 E₄ * qExpansion 1 E₄ - + qExpansion 1 (E₆ : ℍ → ℂ) * qExpansion 1 E₆ := by + rw [show qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ) = + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) from + ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)), + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, + +private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by + refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ + rw [E₄CubeSubE₆SqForm_qExpansion_eq] + simp [PowerSeries.coeff_mul, -PowerSeries.coeff_zero_eq_constantCoeff, + E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + +private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : + (qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ)).coeff 1 = 1728 := by + rw [E₄CubeSubE₆SqForm_qExpansion_eq] + norm_num [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] - ring /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ -theorem discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : +theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by - obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm + obtain ⟨g, hg⟩ := E₄CubeSubE₆SqForm_isCuspForm obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g - have hgE : (g : ℍ → ℂ) = E4_cube_sub_E6_sq_form := congrArg DFunLike.coe hg + have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg have hc_eq : c = 1728 := by have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c CuspForm.discriminant rw [hcΔ, hgE] at hgΔ - have h := congr_arg (·.coeff 1) hgΔ simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, - E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm + E₄CubeSubE₆SqForm_qExpansion_coeff_one] using (congr_arg (·.coeff 1) hgΔ).symm have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by rw [← hc_eq, show c * discriminant z = (c • CuspForm.discriminant) z from rfl, hc, - congr_fun hgE z, E4_cube_sub_E6_sq_form_apply] - linear_combination (1 / 1728 : ℂ) * h1728 + congr_fun hgE z, E₄CubeSubE₆SqForm_apply] + linear_combination h1728 / 1728 /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index d22a368066fde1..9798ae883c45f5 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -193,48 +193,30 @@ lemma exp_isBigO_discriminant : (fun τ ↦ Real.exp (-2 * π * τ.im)) =O[atImI linarith [norm_nonneg (𝕢 1 τ), mul_le_mul_of_nonneg_left hprod_bound (norm_nonneg (𝕢 1 τ))] /-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` -on `ball 0 (1/2)`. -/ +on the open unit disc. -/ private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) - (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) := by + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by intro q hq by_cases hq0 : q = 0 - · simp only [hq0, zero_mul] - exact Periodic.cuspFunction_zero_of_zero_at_inf one_pos + · simpa [hq0] using Periodic.cuspFunction_zero_of_zero_at_inf one_pos discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex - · have hqn : ‖q‖ < 1 := lt_trans (by simpa [dist_zero_right] using hq) (by norm_num) - have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 - rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, - comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] - have hqr := Periodic.qParam_right_inv one_ne_zero hq0 - have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by - simp [eta_q, hqr] - simp only [hqr, heta] - -/-- The product `∏' i, (1 - q^(i+1))^24` is differentiable within `ball 0 (1/2)` at 0. -/ -private lemma differentiableWithinAt_eta_prod_pow : - DifferentiableWithinAt ℂ (fun q : ℂ ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) - (Metric.ball 0 (1 / 2)) 0 := - (differentiableOn_tprod_one_sub_pow_pow 24 0 - (by simp [Metric.mem_ball] : (0 : ℂ) ∈ Metric.ball 0 1)).mono - (Metric.ball_subset_ball (by norm_num)) + · have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos + (by simpa [dist_zero_right] using hq) hq0 + simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, + comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩, + Periodic.qParam_right_inv one_ne_zero hq0, eta_q] /-- The first q-expansion coefficient of the modular discriminant is 1. -/ lemma discriminant_qExpansion_coeff_one : (qExpansion 1 (Δ : ℍ → ℂ)).coeff 1 = 1 := by - rw [qExpansion_coeff] - simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, - iteratedDeriv_zero] - have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) (1 / 2 : ℝ) := Metric.mem_ball_self (by norm_num) - change deriv (cuspFunction 1 Δ) 0 = 1 - rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem] - rw [derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem)] - have : derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 = - derivWithin id (Metric.ball 0 (1 / 2)) 0 * (∏' i, (1 - (0 : ℂ) ^ (i + 1)) ^ 24) + - id 0 * derivWithin (fun q ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 := - derivWithin_mul differentiableWithinAt_id' differentiableWithinAt_eta_prod_pow - rw [this, derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] - simp + have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos + simp [qExpansion_coeff, iteratedDeriv_succ, iteratedDeriv_zero, + ← derivWithin_of_isOpen Metric.isOpen_ball hmem, + derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem), + derivWithin_fun_mul (s := Metric.ball 0 1) differentiableWithinAt_id' + (differentiableOn_tprod_one_sub_pow_pow 24 _ hmem), + derivWithin_id' _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] end From 82028aa9cc1036b5c52b431e04d28bd58c51729b Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 13:02:40 +0100 Subject: [PATCH 23/43] =?UTF-8?q?chore(NumberTheory/ModularForms):=20drop?= =?UTF-8?q?=20redundant=20=E2=84=8D=20=E2=86=92=20=E2=84=82=20ascriptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drops `(... : ℍ → ℂ)` type ascriptions where the surrounding term already forces the coercion (`qExpansion 1 E₄`, `cuspFunction 1 Δ`, `qExpansion 1 E₄CubeSubE₆SqForm`, etc.). Also reflows the affected declarations to fit the 100-character line limit. --- .../ModularForms/DimensionFormulas/LevelOne.lean | 11 +++++------ Mathlib/NumberTheory/ModularForms/Discriminant.lean | 12 +++++------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index f32cf75aa63e3d..ad1db030e3eba2 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -174,11 +174,10 @@ private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : ring private lemma E₄CubeSubE₆SqForm_qExpansion_eq : - qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ) = - qExpansion 1 (E₄ : ℍ → ℂ) * qExpansion 1 E₄ * qExpansion 1 E₄ - - qExpansion 1 (E₆ : ℍ → ℂ) * qExpansion 1 E₆ := by - rw [show qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ) = - qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) from + qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - + qExpansion 1 E₆ * qExpansion 1 E₆ := by + rw [show qExpansion 1 E₄CubeSubE₆SqForm = + qExpansion 1 ((E₄.mul E₄).mul E₄) - qExpansion 1 (E₆.mul E₆) from ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) (ModularForm.mcast (by norm_num) (E₆.mul E₆)), @@ -193,7 +192,7 @@ private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqFor E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : - (qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ)).coeff 1 = 1728 := by + (qExpansion 1 E₄CubeSubE₆SqForm).coeff 1 = 1728 := by rw [E₄CubeSubE₆SqForm_qExpansion_eq] norm_num [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 9798ae883c45f5..08efb060e5203e 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -194,22 +194,20 @@ lemma exp_isBigO_discriminant : (fun τ ↦ Real.exp (-2 * π * τ.im)) =O[atImI /-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` on the open unit disc. -/ -private lemma discriminant_cuspFunction_eqOn : - Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) - (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by +private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 Δ) + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by intro q hq by_cases hq0 : q = 0 · simpa [hq0] using Periodic.cuspFunction_zero_of_zero_at_inf one_pos discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex · have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos (by simpa [dist_zero_right] using hq) hq0 - simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, - comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩, + simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, comp_apply, + ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩, Periodic.qParam_right_inv one_ne_zero hq0, eta_q] /-- The first q-expansion coefficient of the modular discriminant is 1. -/ -lemma discriminant_qExpansion_coeff_one : - (qExpansion 1 (Δ : ℍ → ℂ)).coeff 1 = 1 := by +lemma discriminant_qExpansion_coeff_one : (qExpansion 1 Δ).coeff 1 = 1 := by have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos simp [qExpansion_coeff, iteratedDeriv_succ, iteratedDeriv_zero, ← derivWithin_of_isOpen Metric.isOpen_ball hmem, From d2b5d0e8dfeb17ee675d8b4fdd4cf3e9b8c35b7b Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 15:46:36 +0100 Subject: [PATCH 24/43] =?UTF-8?q?feat(NumberTheory/ModularForms):=20graded?= =?UTF-8?q?-ring=20version=20of=20=CE=94=20=3D=20(E=E2=82=84=C2=B3=20-=20E?= =?UTF-8?q?=E2=82=86=C2=B2)=20/=201728?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`, the analogue of `discriminant_eq_E₄_cube_sub_E₆_sq` in the graded ring `⨁ k, ModularForm 𝒮ℒ k`: DirectSum.of (ModularForm 𝒮ℒ) 12 (CuspForm.discriminant : ModularForm 𝒮ℒ 12) = (1 / 1728 : ℂ) • (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) The proof reduces to the pointwise identity via `DirectSum.of_mul_of`, `congr 1`, and `ext`, then closes by `discriminant_eq_E₄_cube_sub_E₆_sq` and `ring`. --- .../DimensionFormulas/LevelOne.lean | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index ad1db030e3eba2..d65412a50ecf90 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -23,6 +23,8 @@ of even weight. * `ModularForm.rank_eq_one_add_rank_cuspForm`: `rank M_k = 1 + rank S_k` for even `k ≥ 3`. * `ModularForm.dimension_level_one`: the full dimension formula for all even `k : ℕ`. * `ModularForm.levelOne_odd_weight_rank_zero`: modular forms of odd weight are zero. +* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq`: the identity `Δ = (E₄³ - E₆²) / 1728`, + with a graded-ring version `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`. * A `FiniteDimensional ℂ (ModularForm 𝒮ℒ k)` instance for every `k : ℤ`. -/ @@ -216,6 +218,28 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : congr_fun hgE z, E₄CubeSubE₆SqForm_apply] linear_combination h1728 / 1728 +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring +`⨁ k, ModularForm 𝒮ℒ k`. -/ +theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : + DirectSum.of (ModularForm 𝒮ℒ) 12 (CuspForm.discriminant : ModularForm 𝒮ℒ 12) = + (1 / 1728 : ℂ) • (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by + have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = DirectSum.of (ModularForm 𝒮ℒ) 12 + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) := by + rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of] + rfl + have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = + DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by norm_num) (E₆.mul E₆)) := by + rw [pow_two, DirectSum.of_mul_of] + rfl + rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] + congr 1 + ext z + change ModularForm.discriminant z = + (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) + rw [discriminant_eq_E₄_cube_sub_E₆_sq z] + ring + /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` and first-order coefficients `240` and `-504`, then `p = 0`. -/ From 4b367badbfe4266a158531426cd15117b040dd3f Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 15:54:08 +0100 Subject: [PATCH 25/43] chore(NumberTheory/ModularForms): use decide for nat equalities in mcast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In `discriminant_eq_E₄_cube_sub_E₆_sq_graded`, replace `(by norm_num)` proofs of `4 + 4 + 4 = 12` and `6 + 6 = 12` with `(by decide)` (kernel reduction). --- .../ModularForms/DimensionFormulas/LevelOne.lean | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index d65412a50ecf90..ab4f264c03b330 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -221,24 +221,21 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : /-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring `⨁ k, ModularForm 𝒮ℒ k`. -/ theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : - DirectSum.of (ModularForm 𝒮ℒ) 12 (CuspForm.discriminant : ModularForm 𝒮ℒ 12) = - (1 / 1728 : ℂ) • (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - - DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by + DirectSum.of (ModularForm 𝒮ℒ) 12 CuspForm.discriminant = + (1 / 1728 : ℂ) • (.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - .of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = DirectSum.of (ModularForm 𝒮ℒ) 12 - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) := by + (ModularForm.mcast (by decide) ((E₄.mul E₄).mul E₄)) := by rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of] rfl have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = - DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by norm_num) (E₆.mul E₆)) := by + DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by decide) (E₆.mul E₆)) := by rw [pow_two, DirectSum.of_mul_of] rfl rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] congr 1 ext z - change ModularForm.discriminant z = - (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) - rw [discriminant_eq_E₄_cube_sub_E₆_sq z] - ring + change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) + grind [discriminant_eq_E₄_cube_sub_E₆_sq z] /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with From 8de2aff96a1c5443840512d551fc0d7a9cc82110 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 16:01:05 +0100 Subject: [PATCH 26/43] feat(NumberTheory/ModularForms): mcast_apply simp lemmas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `@[simp]` lemmas `ModularForm.mcast_apply` and `CuspForm.mcast_apply` saying `mcast h f hΓ z = f z` (true by `rfl`). These let `simp` automatically unfold `mcast` in pointwise reasoning, and are useful API for any future proofs that mix `ModularForm.mcast`/`CuspForm.mcast` with `simp`-based function-level rewriting. --- Mathlib/NumberTheory/ModularForms/Basic.lean | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index cfb4abba9ed314..6a3070e0e34275 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -549,6 +549,10 @@ def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : Cusp holo' := f.holo' zero_at_cusps' hc := h ▸ f.zero_at_cusps' (hΓ ▸ hc) +@[simp] +lemma mcast_apply {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : CuspForm Γ a) + (hΓ : Γ' = Γ := by rfl) (z : ℍ) : mcast h f hΓ z = f z := rfl + end CuspForm namespace ModularForm @@ -564,6 +568,10 @@ def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : Modu holo' := f.holo' bdd_at_cusps' hc := h ▸ f.bdd_at_cusps' (hΓ ▸ hc) +@[simp] +lemma mcast_apply {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : ModularForm Γ a) + (hΓ : Γ' = Γ := by rfl) (z : ℍ) : mcast h f hΓ z = f z := rfl + @[ext (iff := false)] theorem gradedMonoid_eq_of_cast {Γ : Subgroup (GL (Fin 2) ℝ)} {a b : GradedMonoid (ModularForm Γ)} (h : a.fst = b.fst) (h2 : mcast h a.snd = b.snd) : a = b := by From 0ce59fdc426ca49ac3781248fc681f910c0f531c Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 16:35:31 +0100 Subject: [PATCH 27/43] Revert "feat(NumberTheory/ModularForms): mcast_apply simp lemmas" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The simp lemmas were unused — `change` in `discriminant_eq_E₄_cube_sub_E₆_sq_graded` goes through defeq directly, and the `simp only`-based alternatives I tried didn't close the goal. Removing per "no unused API" guideline; can be re-added later when there's a proof that benefits. This reverts commit 8de2aff96a1. --- Mathlib/NumberTheory/ModularForms/Basic.lean | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index 6a3070e0e34275..cfb4abba9ed314 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -549,10 +549,6 @@ def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : Cusp holo' := f.holo' zero_at_cusps' hc := h ▸ f.zero_at_cusps' (hΓ ▸ hc) -@[simp] -lemma mcast_apply {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : CuspForm Γ a) - (hΓ : Γ' = Γ := by rfl) (z : ℍ) : mcast h f hΓ z = f z := rfl - end CuspForm namespace ModularForm @@ -568,10 +564,6 @@ def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : Modu holo' := f.holo' bdd_at_cusps' hc := h ▸ f.bdd_at_cusps' (hΓ ▸ hc) -@[simp] -lemma mcast_apply {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : ModularForm Γ a) - (hΓ : Γ' = Γ := by rfl) (z : ℍ) : mcast h f hΓ z = f z := rfl - @[ext (iff := false)] theorem gradedMonoid_eq_of_cast {Γ : Subgroup (GL (Fin 2) ℝ)} {a b : GradedMonoid (ModularForm Γ)} (h : a.fst = b.fst) (h2 : mcast h a.snd = b.snd) : a = b := by From 9f3dadc6b2e1f24100a399a7a5db99f045338376 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 16:46:48 +0100 Subject: [PATCH 28/43] refactor(NumberTheory/ModularForms): move discriminant identity to GradedRing.lean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Splits the `Δ = (E₄³ - E₆²) / 1728` results out of `DimensionFormulas/LevelOne.lean` into a new file `DimensionFormulas/GradedRing.lean`. This new file is intended to collect structural results about the graded ring `⨁ k, ModularForm 𝒮ℒ k` of level-1 modular forms (e.g. that `E₄, E₆` generate the full graded ring, to come). Moved declarations: - `E₄CubeSubE₆SqForm` (private) - `E₄CubeSubE₆SqForm_apply` (private) - `E₄CubeSubE₆SqForm_qExpansion_eq` (private) - `E₄CubeSubE₆SqForm_isCuspForm` (private) - `E₄CubeSubE₆SqForm_qExpansion_coeff_one` (private) - `discriminant_eq_E₄_cube_sub_E₆_sq` - `discriminant_eq_E₄_cube_sub_E₆_sq_graded` --- Mathlib.lean | 1 + .../DimensionFormulas/GradedRing.lean | 104 ++++++++++++++++++ .../DimensionFormulas/LevelOne.lean | 74 ------------- .../ModularForms/Discriminant.lean | 2 +- 4 files changed, 106 insertions(+), 75 deletions(-) create mode 100644 Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean diff --git a/Mathlib.lean b/Mathlib.lean index 06e253281cc1da..4735ad3e08a74e 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5655,6 +5655,7 @@ public import Mathlib.NumberTheory.ModularForms.Cusps public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Delta public import Mathlib.NumberTheory.ModularForms.Derivative +public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.GradedRing public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.Discriminant public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean new file mode 100644 index 00000000000000..f3c55e20f78f1b --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean @@ -0,0 +1,104 @@ +/- +Copyright (c) 2026 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +module + +public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne + +/-! +# The graded ring of level-1 modular forms + +This file collects structural results about the graded ring `⨁ k, ModularForm 𝒮ℒ k` of +level-1 modular forms, beyond those that fall out of the dimension formula directly. + +## Main results + +* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq`: the pointwise identity + `Δ = (E₄³ - E₆²) / 1728`. +* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`: the same identity in the graded + ring `⨁ k, ModularForm 𝒮ℒ k`. +-/ + +@[expose] public noncomputable section + +open UpperHalfPlane ModularForm ModularFormClass MatrixGroups EisensteinSeries + +namespace ModularForm + +/-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ +private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := + ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - + ModularForm.mcast (by norm_num) (E₆.mul E₆) + +private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : + E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by + change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ + ring + +private lemma E₄CubeSubE₆SqForm_qExpansion_eq : + qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - + qExpansion 1 E₆ * qExpansion 1 E₆ := by + rw [show qExpansion 1 E₄CubeSubE₆SqForm = + qExpansion 1 ((E₄.mul E₄).mul E₄) - qExpansion 1 (E₆.mul E₆) from + ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)), + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + +private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by + refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ + rw [E₄CubeSubE₆SqForm_qExpansion_eq] + simp [PowerSeries.coeff_mul, -PowerSeries.coeff_zero_eq_constantCoeff, + E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + +private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : + (qExpansion 1 E₄CubeSubE₆SqForm).coeff 1 = 1728 := by + rw [E₄CubeSubE₆SqForm_qExpansion_eq] + norm_num [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, + E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, + E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ +theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : + discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by + obtain ⟨g, hg⟩ := E₄CubeSubE₆SqForm_isCuspForm + obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g + have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg + have hc_eq : c = 1728 := by + have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc + have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c + CuspForm.discriminant + rw [hcΔ, hgE] at hgΔ + simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, + E₄CubeSubE₆SqForm_qExpansion_coeff_one] using (congr_arg (·.coeff 1) hgΔ).symm + have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by + rw [← hc_eq, show c * discriminant z = (c • CuspForm.discriminant) z from rfl, hc, + congr_fun hgE z, E₄CubeSubE₆SqForm_apply] + linear_combination h1728 / 1728 + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring +`⨁ k, ModularForm 𝒮ℒ k`. -/ +theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : + DirectSum.of (ModularForm 𝒮ℒ) 12 CuspForm.discriminant = + (1 / 1728 : ℂ) • (.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - .of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by + have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = DirectSum.of (ModularForm 𝒮ℒ) 12 + (ModularForm.mcast (by decide) ((E₄.mul E₄).mul E₄)) := by + rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of] + rfl + have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = + DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by decide) (E₆.mul E₆)) := by + rw [pow_two, DirectSum.of_mul_of] + rfl + rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] + congr 1 + ext z + change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) + grind [discriminant_eq_E₄_cube_sub_E₆_sq z] + +end ModularForm + +end diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index ab4f264c03b330..0ddf7a000f7e55 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -23,8 +23,6 @@ of even weight. * `ModularForm.rank_eq_one_add_rank_cuspForm`: `rank M_k = 1 + rank S_k` for even `k ≥ 3`. * `ModularForm.dimension_level_one`: the full dimension formula for all even `k : ℕ`. * `ModularForm.levelOne_odd_weight_rank_zero`: modular forms of odd weight are zero. -* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq`: the identity `Δ = (E₄³ - E₆²) / 1728`, - with a graded-ring version `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`. * A `FiniteDimensional ℂ (ModularForm 𝒮ℒ k)` instance for every `k : ℤ`. -/ @@ -165,78 +163,6 @@ lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by norm_num [E_qExpansion_coeff _ ⟨3, rfl⟩, show bernoulli 6 = 1 / 42 by decide +kernel] -/-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ -private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := - ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) - -private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : - E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by - change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ - ring - -private lemma E₄CubeSubE₆SqForm_qExpansion_eq : - qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - - qExpansion 1 E₆ * qExpansion 1 E₆ := by - rw [show qExpansion 1 E₄CubeSubE₆SqForm = - qExpansion 1 ((E₄.mul E₄).mul E₄) - qExpansion 1 (E₆.mul E₆) from - ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)), - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - -private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by - refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ - rw [E₄CubeSubE₆SqForm_qExpansion_eq] - simp [PowerSeries.coeff_mul, -PowerSeries.coeff_zero_eq_constantCoeff, - E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] - -private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : - (qExpansion 1 E₄CubeSubE₆SqForm).coeff 1 = 1728 := by - rw [E₄CubeSubE₆SqForm_qExpansion_eq] - norm_num [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, - E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, - E_qExpansion_coeff_zero _ ⟨3, rfl⟩] - -/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ -theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : - discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by - obtain ⟨g, hg⟩ := E₄CubeSubE₆SqForm_isCuspForm - obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g - have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg - have hc_eq : c = 1728 := by - have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc - have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c - CuspForm.discriminant - rw [hcΔ, hgE] at hgΔ - simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, - E₄CubeSubE₆SqForm_qExpansion_coeff_one] using (congr_arg (·.coeff 1) hgΔ).symm - have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by - rw [← hc_eq, show c * discriminant z = (c • CuspForm.discriminant) z from rfl, hc, - congr_fun hgE z, E₄CubeSubE₆SqForm_apply] - linear_combination h1728 / 1728 - -/-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring -`⨁ k, ModularForm 𝒮ℒ k`. -/ -theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : - DirectSum.of (ModularForm 𝒮ℒ) 12 CuspForm.discriminant = - (1 / 1728 : ℂ) • (.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - .of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by - have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = DirectSum.of (ModularForm 𝒮ℒ) 12 - (ModularForm.mcast (by decide) ((E₄.mul E₄).mul E₄)) := by - rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of] - rfl - have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = - DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by decide) (E₆.mul E₆)) := by - rw [pow_two, DirectSum.of_mul_of] - rfl - rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] - congr 1 - ext z - change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) - grind [discriminant_eq_E₄_cube_sub_E₆_sq z] - /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` and first-order coefficients `240` and `-504`, then `p = 0`. -/ diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 08efb060e5203e..627a7139ddaa04 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -202,7 +202,7 @@ private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 Δ) discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex · have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos (by simpa [dist_zero_right] using hq) hq0 - simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, comp_apply, + simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩, Periodic.qParam_right_inv one_ne_zero hq0, eta_q] From a4125e642e648e05bef5674067fc47cfea30f9b9 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 16:54:24 +0100 Subject: [PATCH 29/43] chore(NumberTheory/ModularForms): move GradedRing.lean to ModularForms/ root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move `DimensionFormulas/GradedRing.lean` → `GradedRing.lean`. The graded-ring results aren't specifically about dimension formulas, so they belong at the top of the `ModularForms/` directory. --- Mathlib.lean | 2 +- .../ModularForms/{DimensionFormulas => }/GradedRing.lean | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename Mathlib/NumberTheory/ModularForms/{DimensionFormulas => }/GradedRing.lean (100%) diff --git a/Mathlib.lean b/Mathlib.lean index 4735ad3e08a74e..094ddc76d96bb5 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5655,7 +5655,6 @@ public import Mathlib.NumberTheory.ModularForms.Cusps public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Delta public import Mathlib.NumberTheory.ModularForms.Derivative -public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.GradedRing public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.Discriminant public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic @@ -5669,6 +5668,7 @@ public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.MDifferentiable public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Summable public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.UniformConvergence +public import Mathlib.NumberTheory.ModularForms.GradedRing public import Mathlib.NumberTheory.ModularForms.Identities public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Bounds public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean similarity index 100% rename from Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean rename to Mathlib/NumberTheory/ModularForms/GradedRing.lean From e05f5e31d04f8b991998ddbe65c1a012ecd8f04e Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 10:39:54 +0100 Subject: [PATCH 30/43] review: address loefflerd's review comments on PR #38806 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Discriminant.lean: convert single `simp` for `discriminant_qExpansion_coeff_one` to a 3-step `calc` proof for robustness. - Basic.lean: add `ModularForm.pow` (with `coe_pow` simp lemma). - QExpansion.lean: add `ModularForm.qExpansion_pow`. - GradedRing.lean: use `pow` and `qExpansion_pow` in the `E₄³ - E₆²` def. - QExpansion.lean: move `cuspFunction_smul/neg/add/sub` and `qExpansion_smul/neg/add/sub` from `ModularFormClass` to `ModularForm` namespace, per the convention that lemmas about `Foo` go in the `Foo` namespace even when their input is class-generic. Co-Authored-By: Claude Opus 4.7 (1M context) --- Mathlib/NumberTheory/ModularForms/Basic.lean | 17 ++++++++++ .../DimensionFormulas/LevelOne.lean | 8 ++--- .../ModularForms/Discriminant.lean | 17 ++++++---- .../NumberTheory/ModularForms/GradedRing.lean | 24 +++++++------- .../NumberTheory/ModularForms/QExpansion.lean | 31 ++++++++++++------- 5 files changed, 63 insertions(+), 34 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index cfb4abba9ed314..e687391fa631f6 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -571,6 +571,23 @@ theorem gradedMonoid_eq_of_cast {Γ : Subgroup (GL (Fin 2) ℝ)} {a b : GradedMo cases h exact congr_arg _ h2 +/-- The `n`-th power of a modular form, as a modular form of weight `n * k`. -/ +def pow {Γ : Subgroup (GL (Fin 2) ℝ)} [Γ.HasDetPlusMinusOne] {k : ℤ} (f : ModularForm Γ k) : + ∀ (n : ℕ), ModularForm Γ ((n : ℤ) * k) + | 0 => mcast (by simp) (1 : ModularForm Γ 0) + | n + 1 => mcast (by push_cast; ring) ((f.pow n).mul f) + +@[simp] +lemma coe_pow {Γ : Subgroup (GL (Fin 2) ℝ)} [Γ.HasDetPlusMinusOne] {k : ℤ} + (f : ModularForm Γ k) (n : ℕ) : ⇑(f.pow n) = (⇑f) ^ n := by + induction n with + | zero => + change (1 : ℍ → ℂ) = _ + rw [pow_zero] + | succ n ih => + change ((f.pow n).mul f : ℍ → ℂ) = _ + rw [coe_mul, ih, pow_succ] + instance (Γ : Subgroup (GL (Fin 2) ℝ)) [Γ.HasDetPlusMinusOne] : GradedMonoid.GOne (ModularForm Γ) where one := 1 diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 0ddf7a000f7e55..dd37aa7f69b6b1 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -136,8 +136,8 @@ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : exact one_ne_zero <| hE.symm.trans <| (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.forall _).mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ rw [← Submodule.Quotient.mk_smul, Submodule.Quotient.eq, mem_cuspFormSubmodule_iff, - isCuspForm_iff_coeffZero_eq_zero, ModularForm.coe_sub, ModularFormClass.qExpansion_sub, - IsGLPos.coe_smul, ModularFormClass.qExpansion_smul, map_sub, + isCuspForm_iff_coeffZero_eq_zero, ModularForm.coe_sub, ModularForm.qExpansion_sub, + IsGLPos.coe_smul, ModularForm.qExpansion_smul, map_sub, PowerSeries.coeff_smul, E_qExpansion_coeff_zero hk hk2, smul_eq_mul, mul_one, sub_self] all_goals simp @@ -187,12 +187,12 @@ private lemma weight_two_qExpansion_eq_zero (f : ModularForm 𝒮ℒ 2) : qExpan (Module.rank_eq_one_iff_finrank_eq_one.mp levelOne_weight_six_rank_one) _ have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) ^ 2 := by rw [pow_two, ← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, - ← ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄, + ← ModularForm.qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄, show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from congrArg DFunLike.coe hc4] have hqc6 : c6 • qExpansion 1 E₆ = qExpansion 1 (f : ℍ → ℂ) ^ 3 := by rw [pow_succ, pow_two, ← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, ← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f, - ← ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆, + ← ModularForm.qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆, show (c6 • E₆ : ℍ → ℂ) = (f.mul f).mul f from congrArg DFunLike.coe hc6] exact eq_zero_of_pow_eq_smul (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one hqc4 hqc6 diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 627a7139ddaa04..5bec8502b02a13 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -209,12 +209,17 @@ private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 Δ) /-- The first q-expansion coefficient of the modular discriminant is 1. -/ lemma discriminant_qExpansion_coeff_one : (qExpansion 1 Δ).coeff 1 = 1 := by have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos - simp [qExpansion_coeff, iteratedDeriv_succ, iteratedDeriv_zero, - ← derivWithin_of_isOpen Metric.isOpen_ball hmem, - derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem), - derivWithin_fun_mul (s := Metric.ball 0 1) differentiableWithinAt_id' - (differentiableOn_tprod_one_sub_pow_pow 24 _ hmem), - derivWithin_id' _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + calc (qExpansion 1 Δ).coeff 1 + = derivWithin (cuspFunction 1 Δ) (Metric.ball 0 1) 0 := by + simp [qExpansion_coeff, iteratedDeriv_succ, iteratedDeriv_zero, + ← derivWithin_of_isOpen Metric.isOpen_ball hmem] + _ = derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) 0 := + derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem) + _ = 1 := by + rw [derivWithin_fun_mul (s := Metric.ball 0 1) differentiableWithinAt_id' + (differentiableOn_tprod_one_sub_pow_pow 24 _ hmem), + derivWithin_id' _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + simp end diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index f3c55e20f78f1b..8c4e365a615dee 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -29,25 +29,25 @@ namespace ModularForm /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := - ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) + ModularForm.mcast (by decide) (E₄.pow 3) - ModularForm.mcast (by decide) (E₆.pow 2) private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by - change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ - ring + change ⇑(E₄.pow 3) z - ⇑(E₆.pow 2) z = _ + rw [coe_pow, coe_pow] + rfl private lemma E₄CubeSubE₆SqForm_qExpansion_eq : qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - qExpansion 1 E₆ * qExpansion 1 E₆ := by rw [show qExpansion 1 E₄CubeSubE₆SqForm = - qExpansion 1 ((E₄.mul E₄).mul E₄) - qExpansion 1 (E₆.mul E₆) from - ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)), - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + qExpansion 1 (E₄.pow 3) - qExpansion 1 (E₆.pow 2) from + ModularForm.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by decide) (E₄.pow 3)) + (ModularForm.mcast (by decide) (E₆.pow 2)), + ModularForm.qExpansion_pow one_pos one_mem_strictPeriods_SL E₄ 3, + ModularForm.qExpansion_pow one_pos one_mem_strictPeriods_SL E₆ 2] + ring private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ @@ -70,7 +70,7 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg have hc_eq : c = 1728 := by have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc - have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c + have hgΔ := ModularForm.qExpansion_smul one_pos one_mem_strictPeriods_SL c CuspForm.discriminant rw [hcΔ, hgE] at hgΔ simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, diff --git a/Mathlib/NumberTheory/ModularForms/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/QExpansion.lean index 06ff2fd364d9a0..0dec76a41cf843 100644 --- a/Mathlib/NumberTheory/ModularForms/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/QExpansion.lean @@ -522,7 +522,7 @@ lemma qExpansion_one (h) : qExpansion h (1 : ℍ → ℂ) = 1 := by end UpperHalfPlane -namespace ModularFormClass +namespace ModularForm protected lemma cuspFunction_smul (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) (a : ℂ) (f : F) [ModularFormClass F Γ k] : cuspFunction h (a • f) = a • cuspFunction h f := @@ -544,6 +544,12 @@ protected lemma cuspFunction_sub {G : Type*} [FunLike G ℍ ℂ] (hh : 0 < h) cuspFunction_sub (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ).continuousAt (ModularFormClass.analyticAt_cuspFunction_zero g hh hΓ).continuousAt +protected lemma cuspFunction_mul [Γ.HasDetPlusMinusOne] (hh : 0 < h) + (hΓ : h ∈ Γ.strictPeriods) {a b : ℤ} (f : ModularForm Γ a) (g : ModularForm Γ b) : + cuspFunction h (f.mul g) = cuspFunction h f * cuspFunction h g := + cuspFunction_mul (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ).continuousAt + (ModularFormClass.analyticAt_cuspFunction_zero g hh hΓ).continuousAt + protected lemma qExpansion_smul (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) (a : ℂ) (f : F) [ModularFormClass F Γ k] : qExpansion h (a • f) = a • qExpansion h f := qExpansion_smul (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ) a @@ -564,16 +570,6 @@ protected lemma qExpansion_sub {G : Type*} [FunLike G ℍ ℂ] (hh : 0 < h) qExpansion_sub (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ) (ModularFormClass.analyticAt_cuspFunction_zero g hh hΓ) -end ModularFormClass - -namespace ModularForm - -protected lemma cuspFunction_mul [Γ.HasDetPlusMinusOne] (hh : 0 < h) - (hΓ : h ∈ Γ.strictPeriods) {a b : ℤ} (f : ModularForm Γ a) (g : ModularForm Γ b) : - cuspFunction h (f.mul g) = cuspFunction h f * cuspFunction h g := - cuspFunction_mul (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ).continuousAt - (ModularFormClass.analyticAt_cuspFunction_zero g hh hΓ).continuousAt - protected lemma qExpansion_mul [Γ.HasDetPlusMinusOne] (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) {a b : ℤ} (f : ModularForm Γ a) (g : ModularForm Γ b) : qExpansion h (f.mul g) = qExpansion h f * qExpansion h g := @@ -589,12 +585,23 @@ protected lemma qExpansion_one [Γ.HasDetPlusMinusOne] : qExpansion h (1 : ModularForm Γ 0) = 1 := by simp [qExpansion_one] +protected lemma qExpansion_pow [Γ.HasDetPlusMinusOne] (hh : 0 < h) + (hΓ : h ∈ Γ.strictPeriods) (f : ModularForm Γ k) (n : ℕ) : + qExpansion h (f.pow n) = (qExpansion h f) ^ n := by + induction n with + | zero => + change qExpansion h (1 : ModularForm Γ 0) = _ + rw [pow_zero, ModularForm.qExpansion_one] + | succ n ih => + change qExpansion h ((f.pow n).mul f) = _ + rw [ModularForm.qExpansion_mul hh hΓ, ih, pow_succ] + /-- The qExpansion map as an additive group hom. to power series over `ℂ`. -/ def qExpansionAddHom (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) (k : ℤ) : ModularForm Γ k →+ PowerSeries ℂ where toFun f := qExpansion h f map_zero' := qExpansion_zero h - map_add' f g := ModularFormClass.qExpansion_add hh hΓ f g + map_add' f g := ModularForm.qExpansion_add hh hΓ f g open scoped DirectSum in /-- The qExpansion map as a map from the graded ring of modular forms to power series over `ℂ`. -/ From a12e6ac15f6539803aa433a62b5a7b641f862e0f Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 08:30:00 +0100 Subject: [PATCH 31/43] rev updates --- Mathlib.lean | 3 ++ Mathlib/NumberTheory/ModularForms/Basic.lean | 16 ++++------- .../ModularForms/CuspFormSubmodule.lean | 2 +- .../ModularForms/Discriminant.lean | 8 ++---- .../EisensteinSeries/QExpansion.lean | 2 +- .../{LevelOne.lean => LevelOne/Basic.lean} | 0 .../DimensionFormula.lean} | 0 .../{ => LevelOne}/GradedRing.lean | 25 ++++++----------- .../NumberTheory/ModularForms/NormTrace.lean | 2 +- .../NumberTheory/ModularForms/QExpansion.lean | 28 +++++++++++++++++++ 10 files changed, 52 insertions(+), 34 deletions(-) rename Mathlib/NumberTheory/ModularForms/{LevelOne.lean => LevelOne/Basic.lean} (100%) rename Mathlib/NumberTheory/ModularForms/{DimensionFormulas/LevelOne.lean => LevelOne/DimensionFormula.lean} (100%) rename Mathlib/NumberTheory/ModularForms/{ => LevelOne}/GradedRing.lean (82%) diff --git a/Mathlib.lean b/Mathlib.lean index 094ddc76d96bb5..7bd94308067813 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5675,6 +5675,9 @@ public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold public import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable public import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.LevelOne.Basic +public import Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula +public import Mathlib.NumberTheory.ModularForms.LevelOne.GradedRing public import Mathlib.NumberTheory.ModularForms.NormTrace public import Mathlib.NumberTheory.ModularForms.Petersson public import Mathlib.NumberTheory.ModularForms.ProperlyDiscontinuous diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index e687391fa631f6..8fe5991ef0b962 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -557,6 +557,7 @@ section GradedRing /-- Cast for modular forms, which is useful for avoiding `Heq`s. Optionally transports along an equality of subgroups. -/ +@[simps -fullyApplied coe] def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : ModularForm Γ a) (hΓ : Γ' = Γ := by rfl) : ModularForm Γ' b where toFun := (f : ℍ → ℂ) @@ -572,21 +573,16 @@ theorem gradedMonoid_eq_of_cast {Γ : Subgroup (GL (Fin 2) ℝ)} {a b : GradedMo exact congr_arg _ h2 /-- The `n`-th power of a modular form, as a modular form of weight `n * k`. -/ -def pow {Γ : Subgroup (GL (Fin 2) ℝ)} [Γ.HasDetPlusMinusOne] {k : ℤ} (f : ModularForm Γ k) : - ∀ (n : ℕ), ModularForm Γ ((n : ℤ) * k) - | 0 => mcast (by simp) (1 : ModularForm Γ 0) - | n + 1 => mcast (by push_cast; ring) ((f.pow n).mul f) +def pow {Γ : Subgroup (GL (Fin 2) ℝ)} [Γ.HasDetPlusMinusOne] {k : ℤ} (f : ModularForm Γ k) + (n : ℕ) : ModularForm Γ (n * k) := + n.rec (mcast (by simp) (1 : ModularForm Γ 0)) (fun n g ↦ (g.mul f).mcast (by grind)) @[simp] lemma coe_pow {Γ : Subgroup (GL (Fin 2) ℝ)} [Γ.HasDetPlusMinusOne] {k : ℤ} (f : ModularForm Γ k) (n : ℕ) : ⇑(f.pow n) = (⇑f) ^ n := by induction n with - | zero => - change (1 : ℍ → ℂ) = _ - rw [pow_zero] - | succ n ih => - change ((f.pow n).mul f : ℍ → ℂ) = _ - rw [coe_mul, ih, pow_succ] + | zero => simp [pow] + | succ n ih => simp_all only [pow, coe_mcast, coe_mul, pow_succ] instance (Γ : Subgroup (GL (Fin 2) ℝ)) [Γ.HasDetPlusMinusOne] : GradedMonoid.GOne (ModularForm Γ) where diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index 5d38f28dbec919..dcd9a8cd6975d3 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -6,7 +6,7 @@ Authors: Chris Birkbeck module public import Mathlib.NumberTheory.ModularForms.QExpansion -public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.LevelOne.Basic public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion /-! diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 5bec8502b02a13..c283e2a4742ba4 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -10,7 +10,7 @@ public import Mathlib.Analysis.Normed.Ring.InfiniteProd public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Basic public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.E2.Transform -public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.LevelOne.Basic public import Mathlib.NumberTheory.ModularForms.QExpansion /-! @@ -211,15 +211,13 @@ lemma discriminant_qExpansion_coeff_one : (qExpansion 1 Δ).coeff 1 = 1 := by have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos calc (qExpansion 1 Δ).coeff 1 = derivWithin (cuspFunction 1 Δ) (Metric.ball 0 1) 0 := by - simp [qExpansion_coeff, iteratedDeriv_succ, iteratedDeriv_zero, - ← derivWithin_of_isOpen Metric.isOpen_ball hmem] + simp [qExpansion_coeff, ← derivWithin_of_isOpen Metric.isOpen_ball hmem] _ = derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) 0 := derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem) _ = 1 := by - rw [derivWithin_fun_mul (s := Metric.ball 0 1) differentiableWithinAt_id' + simp [derivWithin_fun_mul differentiableWithinAt_id' (differentiableOn_tprod_one_sub_pow_pow 24 _ hmem), derivWithin_id' _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] - simp end diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean index 4c02bb54420f53..300dfb9bd5b2e7 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean @@ -10,7 +10,7 @@ public import Mathlib.Analysis.SpecialFunctions.Trigonometric.Cotangent public import Mathlib.NumberTheory.LSeries.Dirichlet public import Mathlib.NumberTheory.LSeries.HurwitzZetaValues public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic -public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.LevelOne.Basic public import Mathlib.NumberTheory.TsumDivisorsAntidiagonal import Mathlib.Topology.EMetricSpace.Paracompact diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/Basic.lean similarity index 100% rename from Mathlib/NumberTheory/ModularForms/LevelOne.lean rename to Mathlib/NumberTheory/ModularForms/LevelOne/Basic.lean diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/DimensionFormula.lean similarity index 100% rename from Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean rename to Mathlib/NumberTheory/ModularForms/LevelOne/DimensionFormula.lean diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/GradedRing.lean similarity index 82% rename from Mathlib/NumberTheory/ModularForms/GradedRing.lean rename to Mathlib/NumberTheory/ModularForms/LevelOne/GradedRing.lean index 8c4e365a615dee..628e02aedd3126 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne/GradedRing.lean @@ -5,7 +5,7 @@ Authors: Chris Birkbeck -/ module -public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne +public import Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula /-! # The graded ring of level-1 modular forms @@ -21,7 +21,7 @@ level-1 modular forms, beyond those that fall out of the dimension formula direc ring `⨁ k, ModularForm 𝒮ℒ k`. -/ -@[expose] public noncomputable section +public noncomputable section open UpperHalfPlane ModularForm ModularFormClass MatrixGroups EisensteinSeries @@ -33,26 +33,19 @@ private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by - change ⇑(E₄.pow 3) z - ⇑(E₆.pow 2) z = _ - rw [coe_pow, coe_pow] - rfl + simp only [E₄CubeSubE₆SqForm, coe_mcast, coe_pow, sub_apply, Pi.pow_apply] private lemma E₄CubeSubE₆SqForm_qExpansion_eq : qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - qExpansion 1 E₆ * qExpansion 1 E₆ := by - rw [show qExpansion 1 E₄CubeSubE₆SqForm = - qExpansion 1 (E₄.pow 3) - qExpansion 1 (E₆.pow 2) from - ModularForm.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by decide) (E₄.pow 3)) - (ModularForm.mcast (by decide) (E₆.pow 2)), - ModularForm.qExpansion_pow one_pos one_mem_strictPeriods_SL E₄ 3, - ModularForm.qExpansion_pow one_pos one_mem_strictPeriods_SL E₆ 2] + simp only [E₄CubeSubE₆SqForm, coe_sub, coe_mcast, + ModularForm.qExpansion_sub one_pos one_mem_strictPeriods_SL, + ModularForm.qExpansion_pow one_pos one_mem_strictPeriods_SL] ring private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by - refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ - rw [E₄CubeSubE₆SqForm_qExpansion_eq] - simp [PowerSeries.coeff_mul, -PowerSeries.coeff_zero_eq_constantCoeff, + simp [isCuspForm_iff_coeffZero_eq_zero, E₄CubeSubE₆SqForm_qExpansion_eq, + PowerSeries.coeff_mul, -PowerSeries.coeff_zero_eq_constantCoeff, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : @@ -64,7 +57,7 @@ private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : - discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by + discriminant z = (E₄ z ^ 3 - E₆ z ^ 2) / 1728 := by obtain ⟨g, hg⟩ := E₄CubeSubE₆SqForm_isCuspForm obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg diff --git a/Mathlib/NumberTheory/ModularForms/NormTrace.lean b/Mathlib/NumberTheory/ModularForms/NormTrace.lean index 4b4b9fe043873c..f09510a9db3449 100644 --- a/Mathlib/NumberTheory/ModularForms/NormTrace.lean +++ b/Mathlib/NumberTheory/ModularForms/NormTrace.lean @@ -5,7 +5,7 @@ Authors: David Loeffler -/ module -public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.LevelOne.Basic /-! # Norm and trace maps diff --git a/Mathlib/NumberTheory/ModularForms/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/QExpansion.lean index 0dec76a41cf843..8e37b6c2d42aee 100644 --- a/Mathlib/NumberTheory/ModularForms/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/QExpansion.lean @@ -630,6 +630,34 @@ lemma qExpansion_of_pow [Γ.HasDetPlusMinusOne] (hh : 0 < h) end ModularForm +namespace ModularFormClass + +@[deprecated (since := "2026-05-05")] +protected alias cuspFunction_smul := ModularForm.cuspFunction_smul + +@[deprecated (since := "2026-05-05")] +protected alias cuspFunction_neg := ModularForm.cuspFunction_neg + +@[deprecated (since := "2026-05-05")] +protected alias cuspFunction_add := ModularForm.cuspFunction_add + +@[deprecated (since := "2026-05-05")] +protected alias cuspFunction_sub := ModularForm.cuspFunction_sub + +@[deprecated (since := "2026-05-05")] +protected alias qExpansion_smul := ModularForm.qExpansion_smul + +@[deprecated (since := "2026-05-05")] +protected alias qExpansion_neg := ModularForm.qExpansion_neg + +@[deprecated (since := "2026-05-05")] +protected alias qExpansion_add := ModularForm.qExpansion_add + +@[deprecated (since := "2026-05-05")] +protected alias qExpansion_sub := ModularForm.qExpansion_sub + +end ModularFormClass + end ring section uniqueness From c64e68598f5f6373ce20c1ee50427d09c064948f Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 08:39:14 +0100 Subject: [PATCH 32/43] fix --- Mathlib.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib.lean b/Mathlib.lean index 7bd94308067813..849907fae954c3 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5668,7 +5668,6 @@ public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.MDifferentiable public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Summable public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.UniformConvergence -public import Mathlib.NumberTheory.ModularForms.GradedRing public import Mathlib.NumberTheory.ModularForms.Identities public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Bounds public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold From 344eb2101db1d07a40d1ff914cdd83612bc9016d Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 08:46:12 +0100 Subject: [PATCH 33/43] fix: restore deprecation shims for files moved into LevelOne/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `LevelOne.lean` and `DimensionFormulas/LevelOne.lean` existed on master, so moving their content into `LevelOne/Basic.lean` and `LevelOne/DimensionFormula.lean` must leave deprecation shims at the old paths — otherwise `Mathlib.lean`'s existing imports of those paths point at missing files and CI fails with `bad import`. Each shim is a `module -- shake: keep-all` stub that `public import`s the new location plus `deprecated_module ... (since := "2026-05-05")`. Note: `GradedRing.lean` was added in this PR (no master version), so no shim is needed for it. --- .../ModularForms/DimensionFormulas/LevelOne.lean | 12 ++++++++++++ Mathlib/NumberTheory/ModularForms/LevelOne.lean | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean create mode 100644 Mathlib/NumberTheory/ModularForms/LevelOne.lean diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean new file mode 100644 index 00000000000000..f8c47807bd1cdf --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -0,0 +1,12 @@ +/- +Copyright (c) 2026 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +module -- shake: keep-all + +public import Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula +public import Mathlib.Tactic.Linter.DeprecatedModule + +deprecated_module "Use `Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula` instead." + (since := "2026-05-05") diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne.lean new file mode 100644 index 00000000000000..3e348cc516da4a --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/LevelOne.lean @@ -0,0 +1,12 @@ +/- +Copyright (c) 2024 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +module -- shake: keep-all + +public import Mathlib.NumberTheory.ModularForms.LevelOne.Basic +public import Mathlib.Tactic.Linter.DeprecatedModule + +deprecated_module "Use `Mathlib.NumberTheory.ModularForms.LevelOne.Basic` instead." + (since := "2026-05-05") From ce615cc0e5da65d10846699739b49d576e23761c Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 09:05:20 +0100 Subject: [PATCH 34/43] ci: trigger rebuild From 79af9eb99403c2215388cd5ec0038575d82c8d7b Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 10:19:07 +0100 Subject: [PATCH 35/43] fix: drop in-PR deprecation shims so git rename-detection preserves history Per loefflerd's followup on this PR: > If the old file doesn't vanish entirely, but gets reduced to a one-line > deprecation stub, then Git treats the newly-relocated file as if it were > freshly created. So `LevelOne.lean` and `DimensionFormulas/LevelOne.lean` are simply removed here (the move into `LevelOne/Basic.lean` and `LevelOne/DimensionFormula.lean` preserves git history). A separate follow-up PR will reintroduce deprecation shims at those old paths for downstream users. `Mathlib.lean` updated via `lake exe mk_all`. --- Mathlib.lean | 2 -- .../ModularForms/DimensionFormulas/LevelOne.lean | 12 ------------ Mathlib/NumberTheory/ModularForms/LevelOne.lean | 12 ------------ 3 files changed, 26 deletions(-) delete mode 100644 Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean delete mode 100644 Mathlib/NumberTheory/ModularForms/LevelOne.lean diff --git a/Mathlib.lean b/Mathlib.lean index f2fdcbc5d97c5a..30c41021072211 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5665,7 +5665,6 @@ public import Mathlib.NumberTheory.ModularForms.Cusps public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Delta public import Mathlib.NumberTheory.ModularForms.Derivative -public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.Discriminant public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Defs @@ -5683,7 +5682,6 @@ public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Bounds public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold public import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable public import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable -public import Mathlib.NumberTheory.ModularForms.LevelOne public import Mathlib.NumberTheory.ModularForms.LevelOne.Basic public import Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula public import Mathlib.NumberTheory.ModularForms.LevelOne.GradedRing diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean deleted file mode 100644 index f8c47807bd1cdf..00000000000000 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ /dev/null @@ -1,12 +0,0 @@ -/- -Copyright (c) 2026 Chris Birkbeck. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Birkbeck --/ -module -- shake: keep-all - -public import Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula -public import Mathlib.Tactic.Linter.DeprecatedModule - -deprecated_module "Use `Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula` instead." - (since := "2026-05-05") diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne.lean deleted file mode 100644 index 3e348cc516da4a..00000000000000 --- a/Mathlib/NumberTheory/ModularForms/LevelOne.lean +++ /dev/null @@ -1,12 +0,0 @@ -/- -Copyright (c) 2024 Chris Birkbeck. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Birkbeck --/ -module -- shake: keep-all - -public import Mathlib.NumberTheory.ModularForms.LevelOne.Basic -public import Mathlib.Tactic.Linter.DeprecatedModule - -deprecated_module "Use `Mathlib.NumberTheory.ModularForms.LevelOne.Basic` instead." - (since := "2026-05-05") From 94cdc0c783d5ac9aa9b54f70c0c3e0799ac698ce Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 11:13:08 +0100 Subject: [PATCH 36/43] feat(NumberTheory/ModularForms): Sturm bound for level-1 modular forms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A modular form `f` of weight `k` for `SL(2, ℤ)` whose first `⌊k/12⌋ + 1` q-expansion coefficients all vanish must be identically zero. The proof iterates `CuspForm.discriminantEquiv` (cusp forms ≃ modular forms of weight `k - 12` via division by `Δ`): a sufficiently-vanishing form is divisible by a power of `Δ`, eventually landing in negative weight where `ModularFormClass.levelOne_neg_weight_eq_zero` finishes. * `ModularForm.eq_zero_of_qExpansion_coeff_zero_lt` (private auxiliary form) * `ModularForm.sturm_bound_levelOne` (the main theorem) --- Mathlib.lean | 1 + .../ModularForms/LevelOne/SturmBound.lean | 128 ++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean diff --git a/Mathlib.lean b/Mathlib.lean index 30c41021072211..02eb53bf377624 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5685,6 +5685,7 @@ public import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable public import Mathlib.NumberTheory.ModularForms.LevelOne.Basic public import Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula public import Mathlib.NumberTheory.ModularForms.LevelOne.GradedRing +public import Mathlib.NumberTheory.ModularForms.LevelOne.SturmBound public import Mathlib.NumberTheory.ModularForms.NormTrace public import Mathlib.NumberTheory.ModularForms.Petersson public import Mathlib.NumberTheory.ModularForms.ProperlyDiscontinuous diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean new file mode 100644 index 00000000000000..78c6549ea770d9 --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2026 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +module + +public import Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula + +/-! +# The Sturm bound for level-1 modular forms + +This file proves the *Sturm bound* for level-1 modular forms: a modular form of weight `k` for +`SL(2, ℤ)` whose first `⌊k/12⌋ + 1` q-expansion coefficients all vanish must be identically zero. + +The proof iterates the isomorphism +`CuspForm.discriminantEquiv : CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - 12)` +(division by the modular discriminant `Δ`): a sufficiently-vanishing form is divisible by a power +of `Δ`, landing eventually in negative weight where everything is zero. + +## Main results + +* `ModularForm.eq_zero_of_qExpansion_coeff_zero_lt`: the auxiliary form of the Sturm bound, stated + in terms of an integer bound `n` with `k < 12 * n`. +* `ModularForm.sturm_bound_levelOne`: the Sturm bound stated in the standard form: if every + coefficient of `q^i` in `qExpansion 1 f` with `12 * i ≤ k` is zero, then `f = 0`. +-/ + +@[expose] public noncomputable section + +open UpperHalfPlane ModularForm CuspForm MatrixGroups + +namespace ModularForm + +private lemma analyticAt_cuspFunction_discriminant : + AnalyticAt ℂ (cuspFunction 1 ModularForm.discriminant) 0 := by + have h := ModularFormClass.analyticAt_cuspFunction_zero + (CuspForm.discriminant : CuspForm 𝒮ℒ 12) one_pos one_mem_strictPeriods_SL + rwa [CuspForm.coe_discriminant] at h + +private lemma qExpansion_eq_qExpansion_discriminant_mul {k : ℤ} (f : ModularForm 𝒮ℒ k) + (hcusp : (qExpansion 1 f).coeff 0 = 0) : + qExpansion 1 f = qExpansion 1 ModularForm.discriminant * + qExpansion 1 (CuspForm.discriminantEquiv (toCuspForm f hcusp)) := by + set g := CuspForm.discriminantEquiv (toCuspForm f hcusp) with hg_def + have hsymm : CuspForm.discriminantEquiv.symm g = toCuspForm f hcusp := by simp [hg_def] + have hfun_z : ∀ z, (f : ℍ → ℂ) z = ModularForm.discriminant z * g z := by + intro z + have hCD : CuspForm.ofMulDiscriminant g = toCuspForm f hcusp := hsymm + have h1 := CuspForm.ofMulDiscriminant_apply g z + rw [hCD, toCuspForm_apply] at h1 + exact h1 + have hfun : (f : ℍ → ℂ) = ModularForm.discriminant * (g : ℍ → ℂ) := by + funext z; rw [Pi.mul_apply]; exact hfun_z z + rw [hfun] + exact UpperHalfPlane.qExpansion_mul analyticAt_cuspFunction_discriminant + (ModularFormClass.analyticAt_cuspFunction_zero g one_pos one_mem_strictPeriods_SL) + +private lemma orderOf_qExpansion_discriminant : + (qExpansion 1 ModularForm.discriminant).order = 1 := by + refine PowerSeries.order_eq_nat.mpr ⟨?_, ?_⟩ + · rw [ModularForm.discriminant_qExpansion_coeff_one] + exact one_ne_zero + · intro i hi + interval_cases i + have hcusp : IsCuspForm ((CuspForm.discriminant : ModularForm 𝒮ℒ 12)) := + ⟨CuspForm.discriminant, rfl⟩ + have h0 := (isCuspForm_iff_coeffZero_eq_zero + ((CuspForm.discriminant : ModularForm 𝒮ℒ 12))).mp hcusp + rwa [show ((CuspForm.discriminant : ModularForm 𝒮ℒ 12) : ℍ → ℂ) = + ModularForm.discriminant from CuspForm.coe_discriminant] at h0 + +private lemma eq_zero_of_qExpansion_coeff_zero_lt : + ∀ (n : ℕ) {k : ℤ} (f : ModularForm 𝒮ℒ k), + k < 12 * n → (∀ i < n, (qExpansion 1 f).coeff i = 0) → f = 0 := by + intro n + induction n with + | zero => + intro k f hk _ + push_cast at hk + rw [← coe_eq_zero_iff] + exact ModularFormClass.levelOne_neg_weight_eq_zero (by omega) f + | succ n ih => + intro k f hk hcoeff + have h0 : (qExpansion 1 f).coeff 0 = 0 := hcoeff 0 (Nat.zero_lt_succ n) + set g := CuspForm.discriminantEquiv (toCuspForm f h0) with hg_def + have hqE : qExpansion 1 f = + qExpansion 1 ModularForm.discriminant * qExpansion 1 g := + qExpansion_eq_qExpansion_discriminant_mul f h0 + have hf_order : ↑(n + 1 : ℕ) ≤ (qExpansion 1 f).order := + PowerSeries.nat_le_order _ _ hcoeff + have hg_order : ↑(n : ℕ) ≤ (qExpansion 1 g).order := by + have hmul : (qExpansion 1 f).order = 1 + (qExpansion 1 g).order := by + rw [hqE, PowerSeries.order_mul, orderOf_qExpansion_discriminant] + rw [hmul] at hf_order + have h1 : (1 : ℕ∞) + ↑n ≤ 1 + (qExpansion 1 g).order := by + have heq : ((n + 1 : ℕ) : ℕ∞) = 1 + ↑n := by push_cast; ring + rw [← heq]; exact hf_order + exact (WithTop.add_le_add_iff_left (by simp : (1 : ℕ∞) ≠ ⊤)).mp h1 + have hgcoeff : ∀ i < n, (qExpansion 1 g).coeff i = 0 := fun i hi => + PowerSeries.coeff_of_lt_order _ (lt_of_lt_of_le (by exact_mod_cast hi) hg_order) + have hk' : k - 12 < 12 * (n : ℤ) := by push_cast at hk; linarith + have hg_zero : g = 0 := ih g hk' hgcoeff + have hf' : toCuspForm f h0 = 0 := by + apply CuspForm.discriminantEquiv.injective + simpa [← hg_def] using hg_zero + ext z + have hz := DFunLike.congr_fun hf' z + simpa [toCuspForm_apply] using hz + +/-- **Sturm bound for level-1 modular forms.** If a modular form `f` of weight `k` for `SL(2, ℤ)` +has zero coefficient on `q^i` in its q-expansion for every `i ≥ 0` with `12 * i ≤ k`, then +`f` is identically zero. -/ +theorem sturm_bound_levelOne {k : ℤ} (f : ModularForm 𝒮ℒ k) + (h : ∀ i : ℕ, 12 * (i : ℤ) ≤ k → (qExpansion 1 f).coeff i = 0) : f = 0 := by + by_cases hk_neg : k < 0 + · rw [← coe_eq_zero_iff] + exact ModularFormClass.levelOne_neg_weight_eq_zero hk_neg f + push Not at hk_neg + refine eq_zero_of_qExpansion_coeff_zero_lt (k.toNat / 12 + 1) f ?_ fun i hi => h i ?_ + · have hkn : (k : ℤ) = k.toNat := (Int.toNat_of_nonneg hk_neg).symm + omega + · have hkn : (k : ℤ) = k.toNat := (Int.toNat_of_nonneg hk_neg).symm + omega + +end ModularForm + +end From acf000cb6c116b63a8f40de9279becf6b51af54b Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 11:23:35 +0100 Subject: [PATCH 37/43] =?UTF-8?q?chore:=20cleanup=20Sturm=20bound=20?= =?UTF-8?q?=E2=80=94=20inline=20single-use=20haves,=20drop=20unused=20have?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup pass via /cleanup: * `analyticAt_cuspFunction_discriminant`: term-mode via `▸`. * `qExpansion_eq_qExpansion_discriminant_mul`: drop `hfun_z` intermediate, inline `h1`. * `eq_zero_of_qExpansion_coeff_zero_lt`: inline `hqE`/`hf_order`/`hgcoeff`/`hz`, collapse the ℕ∞ arithmetic, term-mode `hf'`. * `sturm_bound_levelOne`: drop two unused `hkn` haves — `omega` handles `Int.toNat` directly given the nonneg hypothesis. 128 → 113 lines. --- .../ModularForms/LevelOne/SturmBound.lean | 51 +++++++------------ 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean index 78c6549ea770d9..0a17b624a9e230 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean @@ -20,8 +20,6 @@ of `Δ`, landing eventually in negative weight where everything is zero. ## Main results -* `ModularForm.eq_zero_of_qExpansion_coeff_zero_lt`: the auxiliary form of the Sturm bound, stated - in terms of an integer bound `n` with `k < 12 * n`. * `ModularForm.sturm_bound_levelOne`: the Sturm bound stated in the standard form: if every coefficient of `q^i` in `qExpansion 1 f` with `12 * i ≤ k` is zero, then `f = 0`. -/ @@ -33,10 +31,9 @@ open UpperHalfPlane ModularForm CuspForm MatrixGroups namespace ModularForm private lemma analyticAt_cuspFunction_discriminant : - AnalyticAt ℂ (cuspFunction 1 ModularForm.discriminant) 0 := by - have h := ModularFormClass.analyticAt_cuspFunction_zero + AnalyticAt ℂ (cuspFunction 1 ModularForm.discriminant) 0 := + CuspForm.coe_discriminant ▸ ModularFormClass.analyticAt_cuspFunction_zero (CuspForm.discriminant : CuspForm 𝒮ℒ 12) one_pos one_mem_strictPeriods_SL - rwa [CuspForm.coe_discriminant] at h private lemma qExpansion_eq_qExpansion_discriminant_mul {k : ℤ} (f : ModularForm 𝒮ℒ k) (hcusp : (qExpansion 1 f).coeff 0 = 0) : @@ -44,14 +41,12 @@ private lemma qExpansion_eq_qExpansion_discriminant_mul {k : ℤ} (f : ModularFo qExpansion 1 (CuspForm.discriminantEquiv (toCuspForm f hcusp)) := by set g := CuspForm.discriminantEquiv (toCuspForm f hcusp) with hg_def have hsymm : CuspForm.discriminantEquiv.symm g = toCuspForm f hcusp := by simp [hg_def] - have hfun_z : ∀ z, (f : ℍ → ℂ) z = ModularForm.discriminant z * g z := by - intro z - have hCD : CuspForm.ofMulDiscriminant g = toCuspForm f hcusp := hsymm + have hfun : (f : ℍ → ℂ) = ModularForm.discriminant * (g : ℍ → ℂ) := by + funext z have h1 := CuspForm.ofMulDiscriminant_apply g z - rw [hCD, toCuspForm_apply] at h1 + rw [show CuspForm.ofMulDiscriminant g = toCuspForm f hcusp from hsymm, + toCuspForm_apply] at h1 exact h1 - have hfun : (f : ℍ → ℂ) = ModularForm.discriminant * (g : ℍ → ℂ) := by - funext z; rw [Pi.mul_apply]; exact hfun_z z rw [hfun] exact UpperHalfPlane.qExpansion_mul analyticAt_cuspFunction_discriminant (ModularFormClass.analyticAt_cuspFunction_zero g one_pos one_mem_strictPeriods_SL) @@ -84,29 +79,21 @@ private lemma eq_zero_of_qExpansion_coeff_zero_lt : intro k f hk hcoeff have h0 : (qExpansion 1 f).coeff 0 = 0 := hcoeff 0 (Nat.zero_lt_succ n) set g := CuspForm.discriminantEquiv (toCuspForm f h0) with hg_def - have hqE : qExpansion 1 f = - qExpansion 1 ModularForm.discriminant * qExpansion 1 g := - qExpansion_eq_qExpansion_discriminant_mul f h0 - have hf_order : ↑(n + 1 : ℕ) ≤ (qExpansion 1 f).order := - PowerSeries.nat_le_order _ _ hcoeff have hg_order : ↑(n : ℕ) ≤ (qExpansion 1 g).order := by have hmul : (qExpansion 1 f).order = 1 + (qExpansion 1 g).order := by - rw [hqE, PowerSeries.order_mul, orderOf_qExpansion_discriminant] - rw [hmul] at hf_order - have h1 : (1 : ℕ∞) + ↑n ≤ 1 + (qExpansion 1 g).order := by + rw [qExpansion_eq_qExpansion_discriminant_mul f h0, PowerSeries.order_mul, + orderOf_qExpansion_discriminant] + have hf_order : (1 : ℕ∞) + ↑n ≤ 1 + (qExpansion 1 g).order := by have heq : ((n + 1 : ℕ) : ℕ∞) = 1 + ↑n := by push_cast; ring - rw [← heq]; exact hf_order - exact (WithTop.add_le_add_iff_left (by simp : (1 : ℕ∞) ≠ ⊤)).mp h1 - have hgcoeff : ∀ i < n, (qExpansion 1 g).coeff i = 0 := fun i hi => + rw [← heq, ← hmul] + exact PowerSeries.nat_le_order _ _ hcoeff + exact (WithTop.add_le_add_iff_left (by simp : (1 : ℕ∞) ≠ ⊤)).mp hf_order + have hg_zero : g = 0 := ih g (by push_cast at hk; linarith) fun i hi => PowerSeries.coeff_of_lt_order _ (lt_of_lt_of_le (by exact_mod_cast hi) hg_order) - have hk' : k - 12 < 12 * (n : ℤ) := by push_cast at hk; linarith - have hg_zero : g = 0 := ih g hk' hgcoeff - have hf' : toCuspForm f h0 = 0 := by - apply CuspForm.discriminantEquiv.injective - simpa [← hg_def] using hg_zero + have hf' : toCuspForm f h0 = 0 := + CuspForm.discriminantEquiv.injective (by simpa [← hg_def] using hg_zero) ext z - have hz := DFunLike.congr_fun hf' z - simpa [toCuspForm_apply] using hz + simpa [toCuspForm_apply] using DFunLike.congr_fun hf' z /-- **Sturm bound for level-1 modular forms.** If a modular form `f` of weight `k` for `SL(2, ℤ)` has zero coefficient on `q^i` in its q-expansion for every `i ≥ 0` with `12 * i ≤ k`, then @@ -118,10 +105,8 @@ theorem sturm_bound_levelOne {k : ℤ} (f : ModularForm 𝒮ℒ k) exact ModularFormClass.levelOne_neg_weight_eq_zero hk_neg f push Not at hk_neg refine eq_zero_of_qExpansion_coeff_zero_lt (k.toNat / 12 + 1) f ?_ fun i hi => h i ?_ - · have hkn : (k : ℤ) = k.toNat := (Int.toNat_of_nonneg hk_neg).symm - omega - · have hkn : (k : ℤ) = k.toNat := (Int.toNat_of_nonneg hk_neg).symm - omega + · omega + · omega end ModularForm From a15bb98f9d5abe8843d7270b87072a954ab4c791 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 11:28:17 +0100 Subject: [PATCH 38/43] =?UTF-8?q?chore:=20simplify=20Sturm=20bound=20?= =?UTF-8?q?=E2=80=94=20extract=20`eq=5Fzero=5Fof=5Fneg=5Fweight`,=20drop?= =?UTF-8?q?=20`interval=5Fcases`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /simplify pass: * Extract `eq_zero_of_neg_weight` private helper to dedupe the `coe_eq_zero_iff` + `levelOne_neg_weight_eq_zero` pattern (used 2×). * `WithTop.add_le_add_iff_left` → `ENat.add_le_add_iff_left` (more idiomatic for the ℕ∞ type). * `interval_cases i` (with `i < 1`) → `obtain rfl : i = 0 := by omega` (lighter machinery for a single value). * Inline single-use `hcusp` in `orderOf_qExpansion_discriminant`. --- .../ModularForms/LevelOne/SturmBound.lean | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean index 0a17b624a9e230..c6e245b794acf8 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean @@ -35,6 +35,9 @@ private lemma analyticAt_cuspFunction_discriminant : CuspForm.coe_discriminant ▸ ModularFormClass.analyticAt_cuspFunction_zero (CuspForm.discriminant : CuspForm 𝒮ℒ 12) one_pos one_mem_strictPeriods_SL +private lemma eq_zero_of_neg_weight {k : ℤ} (hk : k < 0) (f : ModularForm 𝒮ℒ k) : f = 0 := + coe_eq_zero_iff f |>.mp <| ModularFormClass.levelOne_neg_weight_eq_zero hk f + private lemma qExpansion_eq_qExpansion_discriminant_mul {k : ℤ} (f : ModularForm 𝒮ℒ k) (hcusp : (qExpansion 1 f).coeff 0 = 0) : qExpansion 1 f = qExpansion 1 ModularForm.discriminant * @@ -57,11 +60,9 @@ private lemma orderOf_qExpansion_discriminant : · rw [ModularForm.discriminant_qExpansion_coeff_one] exact one_ne_zero · intro i hi - interval_cases i - have hcusp : IsCuspForm ((CuspForm.discriminant : ModularForm 𝒮ℒ 12)) := - ⟨CuspForm.discriminant, rfl⟩ + obtain rfl : i = 0 := by omega have h0 := (isCuspForm_iff_coeffZero_eq_zero - ((CuspForm.discriminant : ModularForm 𝒮ℒ 12))).mp hcusp + ((CuspForm.discriminant : ModularForm 𝒮ℒ 12))).mp ⟨CuspForm.discriminant, rfl⟩ rwa [show ((CuspForm.discriminant : ModularForm 𝒮ℒ 12) : ℍ → ℂ) = ModularForm.discriminant from CuspForm.coe_discriminant] at h0 @@ -73,8 +74,7 @@ private lemma eq_zero_of_qExpansion_coeff_zero_lt : | zero => intro k f hk _ push_cast at hk - rw [← coe_eq_zero_iff] - exact ModularFormClass.levelOne_neg_weight_eq_zero (by omega) f + exact eq_zero_of_neg_weight (by omega) f | succ n ih => intro k f hk hcoeff have h0 : (qExpansion 1 f).coeff 0 = 0 := hcoeff 0 (Nat.zero_lt_succ n) @@ -87,7 +87,7 @@ private lemma eq_zero_of_qExpansion_coeff_zero_lt : have heq : ((n + 1 : ℕ) : ℕ∞) = 1 + ↑n := by push_cast; ring rw [← heq, ← hmul] exact PowerSeries.nat_le_order _ _ hcoeff - exact (WithTop.add_le_add_iff_left (by simp : (1 : ℕ∞) ≠ ⊤)).mp hf_order + exact (ENat.add_le_add_iff_left (by simp : (1 : ℕ∞) ≠ ⊤)).mp hf_order have hg_zero : g = 0 := ih g (by push_cast at hk; linarith) fun i hi => PowerSeries.coeff_of_lt_order _ (lt_of_lt_of_le (by exact_mod_cast hi) hg_order) have hf' : toCuspForm f h0 = 0 := @@ -101,8 +101,7 @@ has zero coefficient on `q^i` in its q-expansion for every `i ≥ 0` with `12 * theorem sturm_bound_levelOne {k : ℤ} (f : ModularForm 𝒮ℒ k) (h : ∀ i : ℕ, 12 * (i : ℤ) ≤ k → (qExpansion 1 f).coeff i = 0) : f = 0 := by by_cases hk_neg : k < 0 - · rw [← coe_eq_zero_iff] - exact ModularFormClass.levelOne_neg_weight_eq_zero hk_neg f + · exact eq_zero_of_neg_weight hk_neg f push Not at hk_neg refine eq_zero_of_qExpansion_coeff_zero_lt (k.toNat / 12 + 1) f ?_ fun i hi => h i ?_ · omega From b98bf904d53cc51fd79cd969d08c7f615a8b8d2f Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 11:33:20 +0100 Subject: [PATCH 39/43] =?UTF-8?q?chore:=20drop=20redundant=20wrappers=20?= =?UTF-8?q?=E2=80=94=20use=20existing=20mathlib=20API=20directly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both `analyticAt_cuspFunction_discriminant` and `eq_zero_of_neg_weight` were thin wrappers around existing mathlib API: * `analyticAt_cuspFunction_discriminant` was a one-use specialization of `ModularFormClass.analyticAt_cuspFunction_zero` for `Δ`. Inlined. * `eq_zero_of_neg_weight` (`f = 0` for negative weight) follows from `ModularForm.levelOne_neg_weight_rank_zero` plus `rank_zero_iff_forall_zero`. --- .../ModularForms/LevelOne/SturmBound.lean | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean index c6e245b794acf8..5a38b105c2d3c3 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean @@ -30,14 +30,6 @@ open UpperHalfPlane ModularForm CuspForm MatrixGroups namespace ModularForm -private lemma analyticAt_cuspFunction_discriminant : - AnalyticAt ℂ (cuspFunction 1 ModularForm.discriminant) 0 := - CuspForm.coe_discriminant ▸ ModularFormClass.analyticAt_cuspFunction_zero - (CuspForm.discriminant : CuspForm 𝒮ℒ 12) one_pos one_mem_strictPeriods_SL - -private lemma eq_zero_of_neg_weight {k : ℤ} (hk : k < 0) (f : ModularForm 𝒮ℒ k) : f = 0 := - coe_eq_zero_iff f |>.mp <| ModularFormClass.levelOne_neg_weight_eq_zero hk f - private lemma qExpansion_eq_qExpansion_discriminant_mul {k : ℤ} (f : ModularForm 𝒮ℒ k) (hcusp : (qExpansion 1 f).coeff 0 = 0) : qExpansion 1 f = qExpansion 1 ModularForm.discriminant * @@ -51,7 +43,9 @@ private lemma qExpansion_eq_qExpansion_discriminant_mul {k : ℤ} (f : ModularFo toCuspForm_apply] at h1 exact h1 rw [hfun] - exact UpperHalfPlane.qExpansion_mul analyticAt_cuspFunction_discriminant + exact UpperHalfPlane.qExpansion_mul + (CuspForm.coe_discriminant ▸ ModularFormClass.analyticAt_cuspFunction_zero + (CuspForm.discriminant : CuspForm 𝒮ℒ 12) one_pos one_mem_strictPeriods_SL) (ModularFormClass.analyticAt_cuspFunction_zero g one_pos one_mem_strictPeriods_SL) private lemma orderOf_qExpansion_discriminant : @@ -74,7 +68,8 @@ private lemma eq_zero_of_qExpansion_coeff_zero_lt : | zero => intro k f hk _ push_cast at hk - exact eq_zero_of_neg_weight (by omega) f + exact rank_zero_iff_forall_zero.mp + (ModularForm.levelOne_neg_weight_rank_zero (by omega)) f | succ n ih => intro k f hk hcoeff have h0 : (qExpansion 1 f).coeff 0 = 0 := hcoeff 0 (Nat.zero_lt_succ n) @@ -101,7 +96,7 @@ has zero coefficient on `q^i` in its q-expansion for every `i ≥ 0` with `12 * theorem sturm_bound_levelOne {k : ℤ} (f : ModularForm 𝒮ℒ k) (h : ∀ i : ℕ, 12 * (i : ℤ) ≤ k → (qExpansion 1 f).coeff i = 0) : f = 0 := by by_cases hk_neg : k < 0 - · exact eq_zero_of_neg_weight hk_neg f + · exact rank_zero_iff_forall_zero.mp (ModularForm.levelOne_neg_weight_rank_zero hk_neg) f push Not at hk_neg refine eq_zero_of_qExpansion_coeff_zero_lt (k.toNat / 12 + 1) f ?_ fun i hi => h i ?_ · omega From 5ff012d3f5b169f7379209d2e2724ea8247093dc Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 12:43:34 +0100 Subject: [PATCH 40/43] chore: deeper /cleanup pass on Sturm bound proofs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per-declaration deep golf: * `qExpansion_eq_qExpansion_discriminant_mul`: drop `set g`/`have hsymm` scaffolding; use `funext fun z ↦ simp [CuspForm.discriminantEquiv, mul_div_cancel₀ _ (discriminant_ne_zero z)]` directly. (17 → 11 lines) * `orderOf_qExpansion_discriminant`: collapse first bullet via `▸`, replace `rwa [show … from coe_discriminant]` with `simpa using h0` (since `coe_discriminant` is `@[simp]`). (11 → 8 lines) * `eq_zero_of_qExpansion_coeff_zero_lt`: restructure the ℕ∞-arithmetic block — invert the chain so `ENat.add_le_add_iff_left` runs once at the start, then a single `rw` sequence reaches `nat_le_order`. (29 → 26 lines) 107 → 95 lines. --- .../ModularForms/LevelOne/SturmBound.lean | 42 +++++++------------ 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean index 5a38b105c2d3c3..c79b7f53e230dd 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean @@ -34,31 +34,22 @@ private lemma qExpansion_eq_qExpansion_discriminant_mul {k : ℤ} (f : ModularFo (hcusp : (qExpansion 1 f).coeff 0 = 0) : qExpansion 1 f = qExpansion 1 ModularForm.discriminant * qExpansion 1 (CuspForm.discriminantEquiv (toCuspForm f hcusp)) := by - set g := CuspForm.discriminantEquiv (toCuspForm f hcusp) with hg_def - have hsymm : CuspForm.discriminantEquiv.symm g = toCuspForm f hcusp := by simp [hg_def] - have hfun : (f : ℍ → ℂ) = ModularForm.discriminant * (g : ℍ → ℂ) := by - funext z - have h1 := CuspForm.ofMulDiscriminant_apply g z - rw [show CuspForm.ofMulDiscriminant g = toCuspForm f hcusp from hsymm, - toCuspForm_apply] at h1 - exact h1 - rw [hfun] + rw [show (f : ℍ → ℂ) = ModularForm.discriminant * + (CuspForm.discriminantEquiv (toCuspForm f hcusp) : ℍ → ℂ) from funext fun z ↦ by + simp [CuspForm.discriminantEquiv, mul_div_cancel₀ _ (discriminant_ne_zero z)]] exact UpperHalfPlane.qExpansion_mul (CuspForm.coe_discriminant ▸ ModularFormClass.analyticAt_cuspFunction_zero (CuspForm.discriminant : CuspForm 𝒮ℒ 12) one_pos one_mem_strictPeriods_SL) - (ModularFormClass.analyticAt_cuspFunction_zero g one_pos one_mem_strictPeriods_SL) + (ModularFormClass.analyticAt_cuspFunction_zero _ one_pos one_mem_strictPeriods_SL) private lemma orderOf_qExpansion_discriminant : (qExpansion 1 ModularForm.discriminant).order = 1 := by - refine PowerSeries.order_eq_nat.mpr ⟨?_, ?_⟩ - · rw [ModularForm.discriminant_qExpansion_coeff_one] - exact one_ne_zero - · intro i hi - obtain rfl : i = 0 := by omega - have h0 := (isCuspForm_iff_coeffZero_eq_zero - ((CuspForm.discriminant : ModularForm 𝒮ℒ 12))).mp ⟨CuspForm.discriminant, rfl⟩ - rwa [show ((CuspForm.discriminant : ModularForm 𝒮ℒ 12) : ℍ → ℂ) = - ModularForm.discriminant from CuspForm.coe_discriminant] at h0 + refine PowerSeries.order_eq_nat.mpr + ⟨ModularForm.discriminant_qExpansion_coeff_one ▸ one_ne_zero, fun i hi => ?_⟩ + obtain rfl : i = 0 := by omega + have h0 := (isCuspForm_iff_coeffZero_eq_zero + ((CuspForm.discriminant : ModularForm 𝒮ℒ 12))).mp ⟨CuspForm.discriminant, rfl⟩ + simpa using h0 private lemma eq_zero_of_qExpansion_coeff_zero_lt : ∀ (n : ℕ) {k : ℤ} (f : ModularForm 𝒮ℒ k), @@ -75,14 +66,11 @@ private lemma eq_zero_of_qExpansion_coeff_zero_lt : have h0 : (qExpansion 1 f).coeff 0 = 0 := hcoeff 0 (Nat.zero_lt_succ n) set g := CuspForm.discriminantEquiv (toCuspForm f h0) with hg_def have hg_order : ↑(n : ℕ) ≤ (qExpansion 1 g).order := by - have hmul : (qExpansion 1 f).order = 1 + (qExpansion 1 g).order := by - rw [qExpansion_eq_qExpansion_discriminant_mul f h0, PowerSeries.order_mul, - orderOf_qExpansion_discriminant] - have hf_order : (1 : ℕ∞) + ↑n ≤ 1 + (qExpansion 1 g).order := by - have heq : ((n + 1 : ℕ) : ℕ∞) = 1 + ↑n := by push_cast; ring - rw [← heq, ← hmul] - exact PowerSeries.nat_le_order _ _ hcoeff - exact (ENat.add_le_add_iff_left (by simp : (1 : ℕ∞) ≠ ⊤)).mp hf_order + refine (ENat.add_le_add_iff_left ENat.one_ne_top (k := 1)).mp ?_ + rw [show (1 : ℕ∞) + ↑n = ((n + 1 : ℕ) : ℕ∞) by push_cast; ring, + ← orderOf_qExpansion_discriminant, ← PowerSeries.order_mul, + ← qExpansion_eq_qExpansion_discriminant_mul f h0] + exact PowerSeries.nat_le_order _ _ hcoeff have hg_zero : g = 0 := ih g (by push_cast at hk; linarith) fun i hi => PowerSeries.coeff_of_lt_order _ (lt_of_lt_of_le (by exact_mod_cast hi) hg_order) have hf' : toCuspForm f h0 = 0 := From c1065e0a8d8249cedb23ddac71b166d92e9ce937 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 13:15:49 +0100 Subject: [PATCH 41/43] chore: hoist `k` to a section variable, take `n` as a direct argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two minor cleanups suggested in review: * `variable {k : ℤ}` after `namespace ModularForm`, removing the per-lemma `{k : ℤ}` binders. * `eq_zero_of_qExpansion_coeff_zero_lt` now takes `n` as a parameter and uses `induction n generalizing k f` instead of stating `∀ n, ...` and manually `intro`-ing each case. --- .../ModularForms/LevelOne/SturmBound.lean | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean index c79b7f53e230dd..541dc2b7cabb31 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean @@ -30,11 +30,13 @@ open UpperHalfPlane ModularForm CuspForm MatrixGroups namespace ModularForm -private lemma qExpansion_eq_qExpansion_discriminant_mul {k : ℤ} (f : ModularForm 𝒮ℒ k) +variable {k : ℤ} + +private lemma qExpansion_eq_qExpansion_discriminant_mul (f : ModularForm 𝒮ℒ k) (hcusp : (qExpansion 1 f).coeff 0 = 0) : - qExpansion 1 f = qExpansion 1 ModularForm.discriminant * - qExpansion 1 (CuspForm.discriminantEquiv (toCuspForm f hcusp)) := by - rw [show (f : ℍ → ℂ) = ModularForm.discriminant * + qExpansion 1 f = qExpansion 1 discriminant * + qExpansion 1 (discriminantEquiv (toCuspForm f hcusp)) := by + rw [show (f : ℍ → ℂ) = discriminant * (CuspForm.discriminantEquiv (toCuspForm f hcusp) : ℍ → ℂ) from funext fun z ↦ by simp [CuspForm.discriminantEquiv, mul_div_cancel₀ _ (discriminant_ne_zero z)]] exact UpperHalfPlane.qExpansion_mul @@ -51,18 +53,14 @@ private lemma orderOf_qExpansion_discriminant : ((CuspForm.discriminant : ModularForm 𝒮ℒ 12))).mp ⟨CuspForm.discriminant, rfl⟩ simpa using h0 -private lemma eq_zero_of_qExpansion_coeff_zero_lt : - ∀ (n : ℕ) {k : ℤ} (f : ModularForm 𝒮ℒ k), - k < 12 * n → (∀ i < n, (qExpansion 1 f).coeff i = 0) → f = 0 := by - intro n - induction n with +private lemma eq_zero_of_qExpansion_coeff_zero_lt (n : ℕ) (f : ModularForm 𝒮ℒ k) + (hk : k < 12 * n) (hcoeff : ∀ i < n, (qExpansion 1 f).coeff i = 0) : f = 0 := by + induction n generalizing k f with | zero => - intro k f hk _ push_cast at hk exact rank_zero_iff_forall_zero.mp (ModularForm.levelOne_neg_weight_rank_zero (by omega)) f | succ n ih => - intro k f hk hcoeff have h0 : (qExpansion 1 f).coeff 0 = 0 := hcoeff 0 (Nat.zero_lt_succ n) set g := CuspForm.discriminantEquiv (toCuspForm f h0) with hg_def have hg_order : ↑(n : ℕ) ≤ (qExpansion 1 g).order := by @@ -81,7 +79,7 @@ private lemma eq_zero_of_qExpansion_coeff_zero_lt : /-- **Sturm bound for level-1 modular forms.** If a modular form `f` of weight `k` for `SL(2, ℤ)` has zero coefficient on `q^i` in its q-expansion for every `i ≥ 0` with `12 * i ≤ k`, then `f` is identically zero. -/ -theorem sturm_bound_levelOne {k : ℤ} (f : ModularForm 𝒮ℒ k) +theorem sturm_bound_levelOne (f : ModularForm 𝒮ℒ k) (h : ∀ i : ℕ, 12 * (i : ℤ) ≤ k → (qExpansion 1 f).coeff i = 0) : f = 0 := by by_cases hk_neg : k < 0 · exact rank_zero_iff_forall_zero.mp (ModularForm.levelOne_neg_weight_rank_zero hk_neg) f From c0df70562e5ff7fcb6f01482ac1b1ed2db0f642a Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 13:22:18 +0100 Subject: [PATCH 42/43] chore: hoist `f` to a section variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `variable (f : ModularForm 𝒮ℒ k)` after the namespace; per-lemma `f` binders dropped from `qExpansion_eq_qExpansion_discriminant_mul`, `eq_zero_of_qExpansion_coeff_zero_lt`, and `sturm_bound_levelOne`. The `f`-first argument order at the `eq_zero_of_qExpansion_coeff_zero_lt` call site is updated accordingly. --- .../NumberTheory/ModularForms/LevelOne/SturmBound.lean | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean index 541dc2b7cabb31..3ce24f5560c121 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean @@ -30,9 +30,9 @@ open UpperHalfPlane ModularForm CuspForm MatrixGroups namespace ModularForm -variable {k : ℤ} +variable {k : ℤ} (f : ModularForm 𝒮ℒ k) -private lemma qExpansion_eq_qExpansion_discriminant_mul (f : ModularForm 𝒮ℒ k) +private lemma qExpansion_eq_qExpansion_discriminant_mul (hcusp : (qExpansion 1 f).coeff 0 = 0) : qExpansion 1 f = qExpansion 1 discriminant * qExpansion 1 (discriminantEquiv (toCuspForm f hcusp)) := by @@ -53,7 +53,7 @@ private lemma orderOf_qExpansion_discriminant : ((CuspForm.discriminant : ModularForm 𝒮ℒ 12))).mp ⟨CuspForm.discriminant, rfl⟩ simpa using h0 -private lemma eq_zero_of_qExpansion_coeff_zero_lt (n : ℕ) (f : ModularForm 𝒮ℒ k) +private lemma eq_zero_of_qExpansion_coeff_zero_lt (n : ℕ) (hk : k < 12 * n) (hcoeff : ∀ i < n, (qExpansion 1 f).coeff i = 0) : f = 0 := by induction n generalizing k f with | zero => @@ -79,12 +79,12 @@ private lemma eq_zero_of_qExpansion_coeff_zero_lt (n : ℕ) (f : ModularForm /-- **Sturm bound for level-1 modular forms.** If a modular form `f` of weight `k` for `SL(2, ℤ)` has zero coefficient on `q^i` in its q-expansion for every `i ≥ 0` with `12 * i ≤ k`, then `f` is identically zero. -/ -theorem sturm_bound_levelOne (f : ModularForm 𝒮ℒ k) +theorem sturm_bound_levelOne (h : ∀ i : ℕ, 12 * (i : ℤ) ≤ k → (qExpansion 1 f).coeff i = 0) : f = 0 := by by_cases hk_neg : k < 0 · exact rank_zero_iff_forall_zero.mp (ModularForm.levelOne_neg_weight_rank_zero hk_neg) f push Not at hk_neg - refine eq_zero_of_qExpansion_coeff_zero_lt (k.toNat / 12 + 1) f ?_ fun i hi => h i ?_ + refine eq_zero_of_qExpansion_coeff_zero_lt f (k.toNat / 12 + 1) ?_ fun i hi => h i ?_ · omega · omega From 7ca8e7e67cd20ccaa9e38bb29ff7ec0f6d2d6071 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 6 May 2026 13:23:02 +0100 Subject: [PATCH 43/43] =?UTF-8?q?chore:=20extract=20`f=20=3D=20=CE=94=20*?= =?UTF-8?q?=20g`=20step=20to=20a=20separate=20`have=20hfun`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids a `simp` nested inside a `rw [show ... from ...]`. The statement of `hfun` is also self-documenting now. --- .../NumberTheory/ModularForms/LevelOne/SturmBound.lean | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean index 3ce24f5560c121..a88a8675edf8e8 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne/SturmBound.lean @@ -36,9 +36,11 @@ private lemma qExpansion_eq_qExpansion_discriminant_mul (hcusp : (qExpansion 1 f).coeff 0 = 0) : qExpansion 1 f = qExpansion 1 discriminant * qExpansion 1 (discriminantEquiv (toCuspForm f hcusp)) := by - rw [show (f : ℍ → ℂ) = discriminant * - (CuspForm.discriminantEquiv (toCuspForm f hcusp) : ℍ → ℂ) from funext fun z ↦ by - simp [CuspForm.discriminantEquiv, mul_div_cancel₀ _ (discriminant_ne_zero z)]] + have hfun : (f : ℍ → ℂ) = discriminant * + (CuspForm.discriminantEquiv (toCuspForm f hcusp) : ℍ → ℂ) := by + funext z + simp [CuspForm.discriminantEquiv, mul_div_cancel₀ _ (discriminant_ne_zero z)] + rw [hfun] exact UpperHalfPlane.qExpansion_mul (CuspForm.coe_discriminant ▸ ModularFormClass.analyticAt_cuspFunction_zero (CuspForm.discriminant : CuspForm 𝒮ℒ 12) one_pos one_mem_strictPeriods_SL)