passagemath-schemes 10.8.1a4__cp314-cp314t-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
- passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
- passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
- passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
- passagemath_schemes/__init__.py +3 -0
- passagemath_schemes-10.8.1a4.dist-info/METADATA +203 -0
- passagemath_schemes-10.8.1a4.dist-info/METADATA.bak +204 -0
- passagemath_schemes-10.8.1a4.dist-info/RECORD +312 -0
- passagemath_schemes-10.8.1a4.dist-info/WHEEL +6 -0
- passagemath_schemes-10.8.1a4.dist-info/top_level.txt +3 -0
- sage/all__sagemath_schemes.py +23 -0
- sage/databases/all__sagemath_schemes.py +7 -0
- sage/databases/cremona.py +1723 -0
- sage/dynamics/all__sagemath_schemes.py +2 -0
- sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
- sage/dynamics/arithmetic_dynamics/all.py +14 -0
- sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
- sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
- sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
- sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
- sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
- sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
- sage/dynamics/arithmetic_dynamics/projective_ds.py +9556 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
- sage/dynamics/arithmetic_dynamics/wehlerK3.py +2578 -0
- sage/lfunctions/all.py +18 -0
- sage/lfunctions/dokchitser.py +727 -0
- sage/lfunctions/pari.py +971 -0
- sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
- sage/lfunctions/zero_sums.pyx +1847 -0
- sage/modular/abvar/abvar.py +5132 -0
- sage/modular/abvar/abvar_ambient_jacobian.py +414 -0
- sage/modular/abvar/abvar_newform.py +246 -0
- sage/modular/abvar/all.py +8 -0
- sage/modular/abvar/constructor.py +187 -0
- sage/modular/abvar/cuspidal_subgroup.py +371 -0
- sage/modular/abvar/finite_subgroup.py +896 -0
- sage/modular/abvar/homology.py +721 -0
- sage/modular/abvar/homspace.py +989 -0
- sage/modular/abvar/lseries.py +415 -0
- sage/modular/abvar/morphism.py +935 -0
- sage/modular/abvar/torsion_point.py +274 -0
- sage/modular/abvar/torsion_subgroup.py +741 -0
- sage/modular/all.py +43 -0
- sage/modular/arithgroup/all.py +20 -0
- sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
- sage/modular/arithgroup/arithgroup_element.pyx +474 -0
- sage/modular/arithgroup/arithgroup_generic.py +1406 -0
- sage/modular/arithgroup/arithgroup_perm.py +2692 -0
- sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
- sage/modular/arithgroup/congroup.pyx +334 -0
- sage/modular/arithgroup/congroup_gamma.py +361 -0
- sage/modular/arithgroup/congroup_gamma0.py +692 -0
- sage/modular/arithgroup/congroup_gamma1.py +659 -0
- sage/modular/arithgroup/congroup_gammaH.py +1491 -0
- sage/modular/arithgroup/congroup_generic.py +630 -0
- sage/modular/arithgroup/congroup_sl2z.py +266 -0
- sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
- sage/modular/arithgroup/farey_symbol.pyx +1067 -0
- sage/modular/arithgroup/tests.py +425 -0
- sage/modular/btquotients/all.py +4 -0
- sage/modular/btquotients/btquotient.py +3736 -0
- sage/modular/btquotients/pautomorphicform.py +2564 -0
- sage/modular/buzzard.py +100 -0
- sage/modular/congroup.py +29 -0
- sage/modular/congroup_element.py +13 -0
- sage/modular/cusps.py +1107 -0
- sage/modular/cusps_nf.py +1270 -0
- sage/modular/dims.py +571 -0
- sage/modular/dirichlet.py +3310 -0
- sage/modular/drinfeld_modform/all.py +2 -0
- sage/modular/drinfeld_modform/element.py +446 -0
- sage/modular/drinfeld_modform/ring.py +773 -0
- sage/modular/drinfeld_modform/tutorial.py +236 -0
- sage/modular/etaproducts.py +1076 -0
- sage/modular/hecke/algebra.py +725 -0
- sage/modular/hecke/all.py +19 -0
- sage/modular/hecke/ambient_module.py +994 -0
- sage/modular/hecke/degenmap.py +119 -0
- sage/modular/hecke/element.py +302 -0
- sage/modular/hecke/hecke_operator.py +736 -0
- sage/modular/hecke/homspace.py +185 -0
- sage/modular/hecke/module.py +1744 -0
- sage/modular/hecke/morphism.py +139 -0
- sage/modular/hecke/submodule.py +970 -0
- sage/modular/hypergeometric_misc.cpython-314t-darwin.so +0 -0
- sage/modular/hypergeometric_misc.pxd +4 -0
- sage/modular/hypergeometric_misc.pyx +166 -0
- sage/modular/hypergeometric_motive.py +2020 -0
- sage/modular/local_comp/all.py +2 -0
- sage/modular/local_comp/liftings.py +292 -0
- sage/modular/local_comp/local_comp.py +1070 -0
- sage/modular/local_comp/smoothchar.py +1825 -0
- sage/modular/local_comp/type_space.py +748 -0
- sage/modular/modform/all.py +30 -0
- sage/modular/modform/ambient.py +817 -0
- sage/modular/modform/ambient_R.py +177 -0
- sage/modular/modform/ambient_eps.py +306 -0
- sage/modular/modform/ambient_g0.py +120 -0
- sage/modular/modform/ambient_g1.py +199 -0
- sage/modular/modform/constructor.py +545 -0
- sage/modular/modform/cuspidal_submodule.py +708 -0
- sage/modular/modform/defaults.py +14 -0
- sage/modular/modform/eis_series.py +487 -0
- sage/modular/modform/eisenstein_submodule.py +663 -0
- sage/modular/modform/element.py +4105 -0
- sage/modular/modform/half_integral.py +154 -0
- sage/modular/modform/hecke_operator_on_qexp.py +247 -0
- sage/modular/modform/j_invariant.py +47 -0
- sage/modular/modform/l_series_gross_zagier.py +127 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314t-darwin.so +0 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
- sage/modular/modform/notes.py +45 -0
- sage/modular/modform/numerical.py +514 -0
- sage/modular/modform/periods.py +14 -0
- sage/modular/modform/ring.py +1257 -0
- sage/modular/modform/space.py +1859 -0
- sage/modular/modform/submodule.py +118 -0
- sage/modular/modform/tests.py +64 -0
- sage/modular/modform/theta.py +110 -0
- sage/modular/modform/vm_basis.py +380 -0
- sage/modular/modform/weight1.py +221 -0
- sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
- sage/modular/modform_hecketriangle/abstract_space.py +2527 -0
- sage/modular/modform_hecketriangle/all.py +30 -0
- sage/modular/modform_hecketriangle/analytic_type.py +590 -0
- sage/modular/modform_hecketriangle/constructor.py +416 -0
- sage/modular/modform_hecketriangle/element.py +351 -0
- sage/modular/modform_hecketriangle/functors.py +752 -0
- sage/modular/modform_hecketriangle/graded_ring.py +541 -0
- sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
- sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3349 -0
- sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1426 -0
- sage/modular/modform_hecketriangle/readme.py +1214 -0
- sage/modular/modform_hecketriangle/series_constructor.py +580 -0
- sage/modular/modform_hecketriangle/space.py +1037 -0
- sage/modular/modform_hecketriangle/subspace.py +423 -0
- sage/modular/modsym/all.py +17 -0
- sage/modular/modsym/ambient.py +3844 -0
- sage/modular/modsym/boundary.py +1420 -0
- sage/modular/modsym/element.py +336 -0
- sage/modular/modsym/g1list.py +178 -0
- sage/modular/modsym/ghlist.py +182 -0
- sage/modular/modsym/hecke_operator.py +73 -0
- sage/modular/modsym/manin_symbol.cpython-314t-darwin.so +0 -0
- sage/modular/modsym/manin_symbol.pxd +5 -0
- sage/modular/modsym/manin_symbol.pyx +497 -0
- sage/modular/modsym/manin_symbol_list.py +1291 -0
- sage/modular/modsym/modsym.py +400 -0
- sage/modular/modsym/modular_symbols.py +384 -0
- sage/modular/modsym/p1list_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-314t-darwin.so +0 -0
- sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
- sage/modular/modsym/space.py +2468 -0
- sage/modular/modsym/subspace.py +455 -0
- sage/modular/modsym/tests.py +376 -0
- sage/modular/multiple_zeta.py +2635 -0
- sage/modular/multiple_zeta_F_algebra.py +789 -0
- sage/modular/overconvergent/all.py +6 -0
- sage/modular/overconvergent/genus0.py +1879 -0
- sage/modular/overconvergent/hecke_series.py +1187 -0
- sage/modular/overconvergent/weightspace.py +776 -0
- sage/modular/pollack_stevens/all.py +4 -0
- sage/modular/pollack_stevens/distributions.py +874 -0
- sage/modular/pollack_stevens/fund_domain.py +1572 -0
- sage/modular/pollack_stevens/manin_map.py +856 -0
- sage/modular/pollack_stevens/modsym.py +1590 -0
- sage/modular/pollack_stevens/padic_lseries.py +417 -0
- sage/modular/pollack_stevens/sigma0.py +534 -0
- sage/modular/pollack_stevens/space.py +1078 -0
- sage/modular/quasimodform/all.py +3 -0
- sage/modular/quasimodform/element.py +846 -0
- sage/modular/quasimodform/ring.py +826 -0
- sage/modular/quatalg/all.py +3 -0
- sage/modular/quatalg/brandt.py +1642 -0
- sage/modular/ssmod/all.py +8 -0
- sage/modular/ssmod/ssmod.py +827 -0
- sage/rings/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/binary_form_reduce.py +585 -0
- sage/schemes/all.py +41 -0
- sage/schemes/berkovich/all.py +6 -0
- sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
- sage/schemes/berkovich/berkovich_space.py +700 -0
- sage/schemes/curves/affine_curve.py +2924 -0
- sage/schemes/curves/all.py +33 -0
- sage/schemes/curves/closed_point.py +434 -0
- sage/schemes/curves/constructor.py +397 -0
- sage/schemes/curves/curve.py +542 -0
- sage/schemes/curves/plane_curve_arrangement.py +1283 -0
- sage/schemes/curves/point.py +463 -0
- sage/schemes/curves/projective_curve.py +3203 -0
- sage/schemes/curves/weighted_projective_curve.py +106 -0
- sage/schemes/curves/zariski_vankampen.py +1931 -0
- sage/schemes/cyclic_covers/all.py +2 -0
- sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
- sage/schemes/cyclic_covers/constructor.py +137 -0
- sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
- sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
- sage/schemes/elliptic_curves/BSD.py +991 -0
- sage/schemes/elliptic_curves/Qcurves.py +592 -0
- sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
- sage/schemes/elliptic_curves/all.py +49 -0
- sage/schemes/elliptic_curves/cardinality.py +609 -0
- sage/schemes/elliptic_curves/cm.py +1103 -0
- sage/schemes/elliptic_curves/constructor.py +1530 -0
- sage/schemes/elliptic_curves/ec_database.py +175 -0
- sage/schemes/elliptic_curves/ell_curve_isogeny.py +3971 -0
- sage/schemes/elliptic_curves/ell_egros.py +457 -0
- sage/schemes/elliptic_curves/ell_field.py +2837 -0
- sage/schemes/elliptic_curves/ell_finite_field.py +3249 -0
- sage/schemes/elliptic_curves/ell_generic.py +3760 -0
- sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
- sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
- sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
- sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
- sage/schemes/elliptic_curves/ell_point.py +4944 -0
- sage/schemes/elliptic_curves/ell_rational_field.py +7184 -0
- sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
- sage/schemes/elliptic_curves/ell_torsion.py +436 -0
- sage/schemes/elliptic_curves/ell_wp.py +352 -0
- sage/schemes/elliptic_curves/formal_group.py +760 -0
- sage/schemes/elliptic_curves/gal_reps.py +1459 -0
- sage/schemes/elliptic_curves/gal_reps_number_field.py +1663 -0
- sage/schemes/elliptic_curves/gp_simon.py +152 -0
- sage/schemes/elliptic_curves/heegner.py +7328 -0
- sage/schemes/elliptic_curves/height.py +2108 -0
- sage/schemes/elliptic_curves/hom.py +1788 -0
- sage/schemes/elliptic_curves/hom_composite.py +1084 -0
- sage/schemes/elliptic_curves/hom_fractional.py +544 -0
- sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
- sage/schemes/elliptic_curves/hom_scalar.py +531 -0
- sage/schemes/elliptic_curves/hom_sum.py +681 -0
- sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
- sage/schemes/elliptic_curves/homset.py +271 -0
- sage/schemes/elliptic_curves/isogeny_class.py +1523 -0
- sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
- sage/schemes/elliptic_curves/jacobian.py +247 -0
- sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
- sage/schemes/elliptic_curves/kraus.py +1014 -0
- sage/schemes/elliptic_curves/lseries_ell.py +915 -0
- sage/schemes/elliptic_curves/mod5family.py +105 -0
- sage/schemes/elliptic_curves/mod_poly.py +197 -0
- sage/schemes/elliptic_curves/mod_sym_num.cpython-314t-darwin.so +0 -0
- sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
- sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
- sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
- sage/schemes/elliptic_curves/padics.py +1816 -0
- sage/schemes/elliptic_curves/period_lattice.py +2234 -0
- sage/schemes/elliptic_curves/period_lattice_region.cpython-314t-darwin.so +0 -0
- sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
- sage/schemes/elliptic_curves/saturation.py +716 -0
- sage/schemes/elliptic_curves/sha_tate.py +1158 -0
- sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
- sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
- sage/schemes/hyperelliptic_curves/all.py +6 -0
- sage/schemes/hyperelliptic_curves/constructor.py +369 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1948 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +936 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
- sage/schemes/hyperelliptic_curves/invariants.py +410 -0
- sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +312 -0
- sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
- sage/schemes/hyperelliptic_curves/jacobian_generic.py +437 -0
- sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
- sage/schemes/hyperelliptic_curves/jacobian_morphism.py +878 -0
- sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
- sage/schemes/hyperelliptic_curves/mestre.py +302 -0
- sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3863 -0
- sage/schemes/jacobians/abstract_jacobian.py +277 -0
- sage/schemes/jacobians/all.py +2 -0
- sage/schemes/overview.py +161 -0
- sage/schemes/plane_conics/all.py +22 -0
- sage/schemes/plane_conics/con_field.py +1296 -0
- sage/schemes/plane_conics/con_finite_field.py +158 -0
- sage/schemes/plane_conics/con_number_field.py +456 -0
- sage/schemes/plane_conics/con_rational_field.py +406 -0
- sage/schemes/plane_conics/con_rational_function_field.py +581 -0
- sage/schemes/plane_conics/constructor.py +249 -0
- sage/schemes/plane_quartics/all.py +2 -0
- sage/schemes/plane_quartics/quartic_constructor.py +71 -0
- sage/schemes/plane_quartics/quartic_generic.py +53 -0
- sage/schemes/riemann_surfaces/all.py +1 -0
- sage/schemes/riemann_surfaces/riemann_surface.py +4177 -0
- sage_wheels/share/cremona/cremona_mini.db +0 -0
- sage_wheels/share/ellcurves/rank0 +30427 -0
- sage_wheels/share/ellcurves/rank1 +31871 -0
- sage_wheels/share/ellcurves/rank10 +6 -0
- sage_wheels/share/ellcurves/rank11 +6 -0
- sage_wheels/share/ellcurves/rank12 +1 -0
- sage_wheels/share/ellcurves/rank14 +1 -0
- sage_wheels/share/ellcurves/rank15 +1 -0
- sage_wheels/share/ellcurves/rank17 +1 -0
- sage_wheels/share/ellcurves/rank19 +1 -0
- sage_wheels/share/ellcurves/rank2 +2388 -0
- sage_wheels/share/ellcurves/rank20 +1 -0
- sage_wheels/share/ellcurves/rank21 +1 -0
- sage_wheels/share/ellcurves/rank22 +1 -0
- sage_wheels/share/ellcurves/rank23 +1 -0
- sage_wheels/share/ellcurves/rank24 +1 -0
- sage_wheels/share/ellcurves/rank28 +1 -0
- sage_wheels/share/ellcurves/rank3 +836 -0
- sage_wheels/share/ellcurves/rank4 +10 -0
- sage_wheels/share/ellcurves/rank5 +5 -0
- sage_wheels/share/ellcurves/rank6 +5 -0
- sage_wheels/share/ellcurves/rank7 +5 -0
- sage_wheels/share/ellcurves/rank8 +6 -0
- sage_wheels/share/ellcurves/rank9 +7 -0
|
@@ -0,0 +1,4105 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# sage.doctest: needs sage.libs.flint sage.libs.pari
|
|
3
|
+
"""
|
|
4
|
+
Elements of modular forms spaces
|
|
5
|
+
|
|
6
|
+
Class hierarchy:
|
|
7
|
+
|
|
8
|
+
- :class:`ModularForm_abstract`
|
|
9
|
+
|
|
10
|
+
- :class:`Newform`
|
|
11
|
+
|
|
12
|
+
- :class:`ModularFormElement_elliptic_curve`
|
|
13
|
+
|
|
14
|
+
- :class:`ModularFormElement`
|
|
15
|
+
|
|
16
|
+
- :class:`EisensteinSeries`
|
|
17
|
+
|
|
18
|
+
- :class:`GradedModularFormElement`
|
|
19
|
+
|
|
20
|
+
AUTHORS:
|
|
21
|
+
|
|
22
|
+
- William Stein (2004-2008): first version
|
|
23
|
+
- David Ayotte (2021-06): GradedModularFormElement class
|
|
24
|
+
"""
|
|
25
|
+
# ****************************************************************************
|
|
26
|
+
# Copyright (C) 2004-2008 William Stein <wstein@gmail.com>
|
|
27
|
+
# 2021 David Ayotte
|
|
28
|
+
#
|
|
29
|
+
# This program is free software: you can redistribute it and/or modify
|
|
30
|
+
# it under the terms of the GNU General Public License as published by
|
|
31
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
32
|
+
# (at your option) any later version.
|
|
33
|
+
# https://www.gnu.org/licenses/
|
|
34
|
+
# ****************************************************************************
|
|
35
|
+
|
|
36
|
+
from sage.arith.functions import lcm
|
|
37
|
+
from sage.arith.misc import divisors, moebius, sigma, factor, crt
|
|
38
|
+
from sage.arith.srange import xsrange
|
|
39
|
+
from sage.matrix.constructor import Matrix
|
|
40
|
+
from sage.matrix.constructor import matrix
|
|
41
|
+
from sage.misc.cachefunc import cached_method
|
|
42
|
+
from sage.misc.lazy_import import lazy_import
|
|
43
|
+
from sage.misc.misc_c import prod
|
|
44
|
+
from sage.misc.verbose import verbose
|
|
45
|
+
from sage.modular.dirichlet import DirichletGroup
|
|
46
|
+
from sage.modular.modsym.modsym import ModularSymbols
|
|
47
|
+
from sage.modular.modsym.p1list import lift_to_sl2z
|
|
48
|
+
from sage.modular.modsym.space import ModularSymbolsSpace
|
|
49
|
+
from sage.modules.free_module_element import vector
|
|
50
|
+
from sage.rings.complex_mpfr import ComplexField
|
|
51
|
+
from sage.rings.fast_arith import prime_range
|
|
52
|
+
from sage.rings.integer import Integer
|
|
53
|
+
from sage.rings.integer_ring import ZZ
|
|
54
|
+
from sage.rings.morphism import RingHomomorphism
|
|
55
|
+
from sage.rings.power_series_ring import PowerSeriesRing
|
|
56
|
+
from sage.rings.rational_field import QQ
|
|
57
|
+
from sage.rings.real_mpfr import RealField
|
|
58
|
+
from sage.structure.element import coercion_model, ModuleElement, Element
|
|
59
|
+
from sage.structure.richcmp import richcmp, op_NE, op_EQ
|
|
60
|
+
|
|
61
|
+
import sage.modular.hecke.element as element
|
|
62
|
+
from . import defaults
|
|
63
|
+
|
|
64
|
+
lazy_import('sage.combinat.integer_vector_weighted', 'WeightedIntegerVectors')
|
|
65
|
+
lazy_import('sage.rings.number_field.number_field_morphisms', 'NumberFieldEmbedding')
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def is_ModularFormElement(x):
|
|
69
|
+
"""
|
|
70
|
+
Return ``True`` if x is a modular form.
|
|
71
|
+
|
|
72
|
+
EXAMPLES::
|
|
73
|
+
|
|
74
|
+
sage: from sage.modular.modform.element import is_ModularFormElement
|
|
75
|
+
sage: is_ModularFormElement(5)
|
|
76
|
+
doctest:warning...
|
|
77
|
+
DeprecationWarning: The function is_ModularFormElement is deprecated;
|
|
78
|
+
use 'isinstance(..., ModularFormElement)' instead.
|
|
79
|
+
See https://github.com/sagemath/sage/issues/38184 for details.
|
|
80
|
+
False
|
|
81
|
+
sage: is_ModularFormElement(ModularForms(11).0)
|
|
82
|
+
True
|
|
83
|
+
"""
|
|
84
|
+
from sage.misc.superseded import deprecation
|
|
85
|
+
deprecation(38184,
|
|
86
|
+
"The function is_ModularFormElement is deprecated; "
|
|
87
|
+
"use 'isinstance(..., ModularFormElement)' instead.")
|
|
88
|
+
return isinstance(x, ModularFormElement)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def delta_lseries(prec=53, max_imaginary_part=0):
|
|
92
|
+
r"""
|
|
93
|
+
Return the `L`-series of the modular form `\Delta`.
|
|
94
|
+
|
|
95
|
+
This returns an interface to Pari's
|
|
96
|
+
own general implementation of `L`-functions.
|
|
97
|
+
|
|
98
|
+
INPUT:
|
|
99
|
+
|
|
100
|
+
- ``prec`` -- integer (default: 53) bits precision
|
|
101
|
+
|
|
102
|
+
- ``max_imaginary_part`` -- real number (default: 0)
|
|
103
|
+
|
|
104
|
+
OUTPUT:
|
|
105
|
+
|
|
106
|
+
The `L`-series of `\Delta`.
|
|
107
|
+
|
|
108
|
+
EXAMPLES::
|
|
109
|
+
|
|
110
|
+
sage: L = delta_lseries()
|
|
111
|
+
sage: L(1)
|
|
112
|
+
0.0374412812685155
|
|
113
|
+
"""
|
|
114
|
+
from sage.lfunctions.pari import LFunction, lfun_delta
|
|
115
|
+
return LFunction(lfun_delta(), prec=prec,
|
|
116
|
+
max_im=max_imaginary_part)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class ModularForm_abstract(ModuleElement):
|
|
120
|
+
"""
|
|
121
|
+
Constructor for generic class of a modular form. This
|
|
122
|
+
should never be called directly; instead one should
|
|
123
|
+
instantiate one of the derived classes of this
|
|
124
|
+
class.
|
|
125
|
+
"""
|
|
126
|
+
def group(self):
|
|
127
|
+
"""
|
|
128
|
+
Return the group for which ``self`` is a modular form.
|
|
129
|
+
|
|
130
|
+
EXAMPLES::
|
|
131
|
+
|
|
132
|
+
sage: ModularForms(Gamma1(11), 2).gen(0).group()
|
|
133
|
+
Congruence Subgroup Gamma1(11)
|
|
134
|
+
"""
|
|
135
|
+
return self.parent().group()
|
|
136
|
+
|
|
137
|
+
def weight(self):
|
|
138
|
+
"""
|
|
139
|
+
Return the weight of ``self``.
|
|
140
|
+
|
|
141
|
+
EXAMPLES::
|
|
142
|
+
|
|
143
|
+
sage: (ModularForms(Gamma1(9),2).6).weight()
|
|
144
|
+
2
|
|
145
|
+
"""
|
|
146
|
+
return self.parent().weight()
|
|
147
|
+
|
|
148
|
+
def level(self):
|
|
149
|
+
"""
|
|
150
|
+
Return the level of ``self``.
|
|
151
|
+
|
|
152
|
+
EXAMPLES::
|
|
153
|
+
|
|
154
|
+
sage: ModularForms(25,4).0.level()
|
|
155
|
+
25
|
|
156
|
+
"""
|
|
157
|
+
return self.parent().level()
|
|
158
|
+
|
|
159
|
+
def is_homogeneous(self) -> bool:
|
|
160
|
+
"""
|
|
161
|
+
Return ``True``.
|
|
162
|
+
|
|
163
|
+
For compatibility with elements of a graded modular forms ring.
|
|
164
|
+
|
|
165
|
+
An alias of this method is ``is_modular_form``.
|
|
166
|
+
|
|
167
|
+
.. SEEALSO::
|
|
168
|
+
|
|
169
|
+
:meth:`sage.modular.modform.element.GradedModularFormElement.is_homogeneous`
|
|
170
|
+
|
|
171
|
+
EXAMPLES::
|
|
172
|
+
|
|
173
|
+
sage: ModularForms(1,12).0.is_homogeneous()
|
|
174
|
+
True
|
|
175
|
+
"""
|
|
176
|
+
return True
|
|
177
|
+
|
|
178
|
+
is_modular_form = is_homogeneous # alias
|
|
179
|
+
|
|
180
|
+
def _repr_(self) -> str:
|
|
181
|
+
"""
|
|
182
|
+
Return the string representation of ``self``.
|
|
183
|
+
|
|
184
|
+
EXAMPLES::
|
|
185
|
+
|
|
186
|
+
sage: ModularForms(25,4).0._repr_()
|
|
187
|
+
'q + O(q^6)'
|
|
188
|
+
|
|
189
|
+
sage: ModularForms(25,4).3._repr_()
|
|
190
|
+
'q^4 + O(q^6)'
|
|
191
|
+
"""
|
|
192
|
+
return str(self.q_expansion())
|
|
193
|
+
|
|
194
|
+
def _pari_init_(self):
|
|
195
|
+
"""
|
|
196
|
+
Conversion to Pari.
|
|
197
|
+
|
|
198
|
+
TESTS::
|
|
199
|
+
|
|
200
|
+
sage: M = EisensteinForms(96, 2)
|
|
201
|
+
sage: M.6
|
|
202
|
+
O(q^6)
|
|
203
|
+
sage: M.7
|
|
204
|
+
O(q^6)
|
|
205
|
+
sage: pari(M.6) == pari(M.7)
|
|
206
|
+
False
|
|
207
|
+
sage: pari(M.6).mfcoefs(10)
|
|
208
|
+
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
|
|
209
|
+
|
|
210
|
+
sage: M = ModularForms(DirichletGroup(17).0^2, 2)
|
|
211
|
+
sage: pari(M.0).mfcoefs(5)
|
|
212
|
+
[0, 1, Mod(-t^3 + t^2 - 1, t^4 + 1), Mod(t^3 - t^2 - t - 1, t^4 + 1), Mod(2*t^3 - t^2 + 2*t, t^4 + 1), Mod(-t^3 - t^2, t^4 + 1)]
|
|
213
|
+
sage: M.0.qexp(5)
|
|
214
|
+
q + (-zeta8^3 + zeta8^2 - 1)*q^2 + (zeta8^3 - zeta8^2 - zeta8 - 1)*q^3 + (2*zeta8^3 - zeta8^2 + 2*zeta8)*q^4 + O(q^5)
|
|
215
|
+
"""
|
|
216
|
+
from sage.libs.pari import pari
|
|
217
|
+
from sage.rings.number_field.number_field_element import NumberFieldElement
|
|
218
|
+
M = pari(self.parent())
|
|
219
|
+
f = self.qexp(self.parent().sturm_bound())
|
|
220
|
+
coefficients = [
|
|
221
|
+
x.__pari__('t') if isinstance(x, NumberFieldElement) else x
|
|
222
|
+
for x in f]
|
|
223
|
+
# we cannot compute pari(f) directly because we need to set the variable name as t
|
|
224
|
+
return M.mflinear(M.mftobasis(coefficients + [0] * (f.prec() - len(coefficients))))
|
|
225
|
+
|
|
226
|
+
def __call__(self, x, prec=None):
|
|
227
|
+
"""
|
|
228
|
+
Evaluate the `q`-expansion of this modular form at x.
|
|
229
|
+
|
|
230
|
+
EXAMPLES::
|
|
231
|
+
|
|
232
|
+
sage: f = ModularForms(DirichletGroup(17).0^2,2).2
|
|
233
|
+
|
|
234
|
+
sage: q = f.q_expansion().parent().gen()
|
|
235
|
+
sage: f(q^2 + O(q^7))
|
|
236
|
+
q^2 + (-zeta8^2 + 2)*q^4 + (zeta8 + 3)*q^6 + O(q^7)
|
|
237
|
+
|
|
238
|
+
sage: f(0)
|
|
239
|
+
0
|
|
240
|
+
|
|
241
|
+
Evaluate numerically::
|
|
242
|
+
|
|
243
|
+
sage: f = ModularForms(1, 12).0
|
|
244
|
+
sage: f(0.3) # rel tol 1e-12
|
|
245
|
+
2.34524576548591e-6
|
|
246
|
+
sage: f = EisensteinForms(1, 4).0
|
|
247
|
+
sage: f(0.9) # rel tol 1e-12
|
|
248
|
+
1.26475942209241e7
|
|
249
|
+
|
|
250
|
+
TESTS::
|
|
251
|
+
|
|
252
|
+
sage: f = ModularForms(96, 2).0
|
|
253
|
+
sage: f(0.3) # rel tol 1e-12
|
|
254
|
+
0.299999997396191
|
|
255
|
+
sage: f(0.0+0.0*I)
|
|
256
|
+
0
|
|
257
|
+
|
|
258
|
+
For simplicity, ``float`` or ``complex`` input are converted to ``CC``, except for
|
|
259
|
+
input ``0`` where exact result is returned::
|
|
260
|
+
|
|
261
|
+
sage: result = f(0.3r); result # rel tol 1e-12
|
|
262
|
+
0.299999997396191
|
|
263
|
+
sage: result.parent()
|
|
264
|
+
Complex Field with 53 bits of precision
|
|
265
|
+
sage: result = f(0.3r + 0.3jr); result # rel tol 1e-12
|
|
266
|
+
0.299999359878484 + 0.299999359878484*I
|
|
267
|
+
sage: result.parent()
|
|
268
|
+
Complex Field with 53 bits of precision
|
|
269
|
+
|
|
270
|
+
Symbolic numerical values use precision of ``CC`` by default::
|
|
271
|
+
|
|
272
|
+
sage: f(sqrt(1/2)) # rel tol 1e-12
|
|
273
|
+
0.700041406692037
|
|
274
|
+
sage: f(sqrt(1/2)*QQbar.zeta(8)) # rel tol 1e-12
|
|
275
|
+
0.496956554651376 + 0.496956554651376*I
|
|
276
|
+
|
|
277
|
+
Higher precision::
|
|
278
|
+
|
|
279
|
+
sage: f(ComplexField(128)(0.3)) # rel tol 1e-36
|
|
280
|
+
0.29999999739619131029285166058750164058
|
|
281
|
+
sage: f(ComplexField(128)(1+2*I)/3) # rel tol 1e-36
|
|
282
|
+
0.32165384572356882556790532669389900691 + 0.67061244638367586302820790711257777390*I
|
|
283
|
+
|
|
284
|
+
Confirm numerical evaluation matches the q-expansion::
|
|
285
|
+
|
|
286
|
+
sage: f = EisensteinForms(1, 4).0
|
|
287
|
+
sage: f(0.3) # rel tol 1e-12
|
|
288
|
+
741.741819297986
|
|
289
|
+
sage: f.qexp(50).polynomial()(0.3) # rel tol 1e-12
|
|
290
|
+
741.741819297986
|
|
291
|
+
|
|
292
|
+
With a nontrivial character::
|
|
293
|
+
|
|
294
|
+
sage: M = ModularForms(DirichletGroup(17).0^2, 2)
|
|
295
|
+
sage: M.0(0.5) # rel tol 1e-12
|
|
296
|
+
0.166916655031616 + 0.0111529051752428*I
|
|
297
|
+
sage: M.0.qexp(60).polynomial()(0.5) # rel tol 1e-12
|
|
298
|
+
0.166916655031616 + 0.0111529051752428*I
|
|
299
|
+
|
|
300
|
+
Higher precision::
|
|
301
|
+
|
|
302
|
+
sage: f(ComplexField(128)(1+2*I)/3) # rel tol 1e-36
|
|
303
|
+
429.19994832206294278688085399056359632 - 786.15736284188243351153830824852974995*I
|
|
304
|
+
sage: f.qexp(400).polynomial()(ComplexField(128)(1+2*I)/3) # rel tol 1e-36
|
|
305
|
+
429.19994832206294278688085399056359631 - 786.15736284188243351153830824852974999*I
|
|
306
|
+
|
|
307
|
+
Check ``SR`` does not make the result lose precision::
|
|
308
|
+
|
|
309
|
+
sage: f(ComplexField(128)(1+2*I)/3 + x - x) # rel tol 1e-36
|
|
310
|
+
429.19994832206294278688085399056359632 - 786.15736284188243351153830824852974995*I
|
|
311
|
+
"""
|
|
312
|
+
from sage.misc.functional import log
|
|
313
|
+
from sage.structure.element import parent
|
|
314
|
+
from sage.rings.complex_mpfr import ComplexNumber
|
|
315
|
+
from sage.rings.cc import CC
|
|
316
|
+
from sage.rings.real_mpfr import RealNumber
|
|
317
|
+
from sage.symbolic.constants import pi
|
|
318
|
+
from sage.rings.imaginary_unit import I # import from here instead of sage.symbolic.constants to avoid cast to SR
|
|
319
|
+
from sage.symbolic.expression import Expression
|
|
320
|
+
if isinstance(x, Expression):
|
|
321
|
+
try:
|
|
322
|
+
x = x.pyobject()
|
|
323
|
+
except TypeError:
|
|
324
|
+
pass
|
|
325
|
+
if x in CC:
|
|
326
|
+
if x == 0:
|
|
327
|
+
return self.qexp(1)[0]
|
|
328
|
+
if not isinstance(x, (RealNumber, ComplexNumber)):
|
|
329
|
+
x = CC(x) # might lose precision if this is done unconditionally (TODO what about interval and ball types?)
|
|
330
|
+
if isinstance(x, (RealNumber, ComplexNumber)):
|
|
331
|
+
return self.eval_at_tau(log(x) / (2 * parent(x)(pi) * I)) # cast to parent(x) to force numerical evaluation of pi
|
|
332
|
+
return self.q_expansion(prec)(x)
|
|
333
|
+
|
|
334
|
+
def eval_at_tau(self, tau):
|
|
335
|
+
r"""
|
|
336
|
+
Evaluate this modular form at the half-period ratio `\tau`.
|
|
337
|
+
This is related to `q` by `q = e^{2\pi i \tau}`.
|
|
338
|
+
|
|
339
|
+
EXAMPLES::
|
|
340
|
+
|
|
341
|
+
sage: f = ModularForms(1, 12).0
|
|
342
|
+
sage: f.eval_at_tau(0.3 * I) # rel tol 1e-12
|
|
343
|
+
0.00150904633897550
|
|
344
|
+
|
|
345
|
+
TESTS:
|
|
346
|
+
|
|
347
|
+
Symbolic numerical values use precision of ``CC`` by default::
|
|
348
|
+
|
|
349
|
+
sage: f.eval_at_tau(sqrt(1/5)*I) # rel tol 1e-12
|
|
350
|
+
0.0123633234207127
|
|
351
|
+
sage: f.eval_at_tau(sqrt(1/2)*QQbar.zeta(8)) # rel tol 1e-12
|
|
352
|
+
-0.114263670441098
|
|
353
|
+
|
|
354
|
+
For simplicity, ``complex`` input are converted to ``CC``::
|
|
355
|
+
|
|
356
|
+
sage: result = f.eval_at_tau(0.3jr); result # rel tol 1e-12
|
|
357
|
+
0.00150904633897550
|
|
358
|
+
sage: result.parent()
|
|
359
|
+
Complex Field with 53 bits of precision
|
|
360
|
+
|
|
361
|
+
Check ``SR`` does not make the result lose precision::
|
|
362
|
+
|
|
363
|
+
sage: f = EisensteinForms(1, 4).0
|
|
364
|
+
sage: f.eval_at_tau(ComplexField(128)(1+2*I)/3 + x - x) # rel tol 1e-36
|
|
365
|
+
-1.0451570582202060056197878314286036966 + 2.7225112098519803098203933583286590274*I
|
|
366
|
+
"""
|
|
367
|
+
from sage.libs.pari import pari
|
|
368
|
+
from sage.rings.cc import CC
|
|
369
|
+
from sage.rings.complex_mpfr import ComplexNumber, ComplexField
|
|
370
|
+
from sage.rings.real_mpfr import RealNumber
|
|
371
|
+
from sage.symbolic.expression import Expression
|
|
372
|
+
if isinstance(tau, Expression):
|
|
373
|
+
try:
|
|
374
|
+
tau = tau.pyobject()
|
|
375
|
+
except TypeError:
|
|
376
|
+
pass
|
|
377
|
+
if not isinstance(tau, (RealNumber, ComplexNumber)):
|
|
378
|
+
tau = CC(tau)
|
|
379
|
+
precision = tau.prec()
|
|
380
|
+
return ComplexField(precision)(pari.mfeval(self.parent(), self, tau, precision=precision))
|
|
381
|
+
|
|
382
|
+
@cached_method
|
|
383
|
+
def valuation(self):
|
|
384
|
+
"""
|
|
385
|
+
Return the valuation of ``self`` (i.e. as an element of the power
|
|
386
|
+
series ring in q).
|
|
387
|
+
|
|
388
|
+
EXAMPLES::
|
|
389
|
+
|
|
390
|
+
sage: ModularForms(11,2).0.valuation()
|
|
391
|
+
1
|
|
392
|
+
sage: ModularForms(11,2).1.valuation()
|
|
393
|
+
0
|
|
394
|
+
sage: ModularForms(25,6).1.valuation()
|
|
395
|
+
2
|
|
396
|
+
sage: ModularForms(25,6).6.valuation()
|
|
397
|
+
7
|
|
398
|
+
"""
|
|
399
|
+
v = self.qexp().valuation()
|
|
400
|
+
if v != self.qexp().prec():
|
|
401
|
+
return v
|
|
402
|
+
return self.qexp(self.parent().sturm_bound()).valuation()
|
|
403
|
+
|
|
404
|
+
def qexp(self, prec=None):
|
|
405
|
+
"""
|
|
406
|
+
Same as ``self.q_expansion(prec)``.
|
|
407
|
+
|
|
408
|
+
.. SEEALSO:: :meth:`q_expansion`
|
|
409
|
+
|
|
410
|
+
EXAMPLES::
|
|
411
|
+
|
|
412
|
+
sage: CuspForms(1,12).0.qexp()
|
|
413
|
+
q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6)
|
|
414
|
+
"""
|
|
415
|
+
return self.q_expansion(prec)
|
|
416
|
+
|
|
417
|
+
def __eq__(self, other):
|
|
418
|
+
"""
|
|
419
|
+
Compare ``self`` to ``other``.
|
|
420
|
+
|
|
421
|
+
EXAMPLES::
|
|
422
|
+
|
|
423
|
+
sage: f = ModularForms(6,4).0
|
|
424
|
+
sage: g = ModularForms(23,2).0
|
|
425
|
+
sage: f == g # indirect doctest
|
|
426
|
+
False
|
|
427
|
+
sage: f == f
|
|
428
|
+
True
|
|
429
|
+
sage: f == loads(dumps(f))
|
|
430
|
+
True
|
|
431
|
+
"""
|
|
432
|
+
if not isinstance(other, ModularFormElement) or \
|
|
433
|
+
self.ambient_module() != other.ambient_module():
|
|
434
|
+
return False
|
|
435
|
+
else:
|
|
436
|
+
return self.element() == other.element()
|
|
437
|
+
|
|
438
|
+
def __ne__(self, other):
|
|
439
|
+
"""
|
|
440
|
+
Return ``True`` if ``self != other``.
|
|
441
|
+
|
|
442
|
+
EXAMPLES::
|
|
443
|
+
|
|
444
|
+
sage: f = Newforms(Gamma1(30), 2, names='a')[1]
|
|
445
|
+
sage: g = ModularForms(23, 2).0
|
|
446
|
+
sage: f != g
|
|
447
|
+
True
|
|
448
|
+
sage: f != f
|
|
449
|
+
False
|
|
450
|
+
|
|
451
|
+
TESTS:
|
|
452
|
+
|
|
453
|
+
The following used to fail (see :issue:`18068`)::
|
|
454
|
+
|
|
455
|
+
sage: f != loads(dumps(f))
|
|
456
|
+
False
|
|
457
|
+
"""
|
|
458
|
+
return not (self == other)
|
|
459
|
+
|
|
460
|
+
def _compute(self, X):
|
|
461
|
+
"""
|
|
462
|
+
Compute the coefficients of `q^n` of the power series of self,
|
|
463
|
+
for `n` in the list `X`. The results are not cached. (Use
|
|
464
|
+
coefficients for cached results).
|
|
465
|
+
|
|
466
|
+
EXAMPLES::
|
|
467
|
+
|
|
468
|
+
sage: f = ModularForms(18,2).1
|
|
469
|
+
sage: f.q_expansion(20)
|
|
470
|
+
q + 8*q^7 + 4*q^10 + 14*q^13 - 4*q^16 + 20*q^19 + O(q^20)
|
|
471
|
+
sage: f._compute([10,17])
|
|
472
|
+
[4, 0]
|
|
473
|
+
sage: f._compute([])
|
|
474
|
+
[]
|
|
475
|
+
"""
|
|
476
|
+
if not isinstance(X, list) or not X:
|
|
477
|
+
return []
|
|
478
|
+
bound = max(X)
|
|
479
|
+
q_exp = self.q_expansion(bound + 1)
|
|
480
|
+
return [q_exp[i] for i in X]
|
|
481
|
+
|
|
482
|
+
def coefficients(self, X):
|
|
483
|
+
r"""
|
|
484
|
+
Return the coefficients `a_n` of the `q`-expansion of this modular form.
|
|
485
|
+
|
|
486
|
+
This function caches the results of the compute function.
|
|
487
|
+
|
|
488
|
+
INPUT:
|
|
489
|
+
|
|
490
|
+
- ``X`` -- an iterator or an integer. If ``X`` is an iterator, a list
|
|
491
|
+
containing all `a_{X_i}` is returned. If ``X`` is an integer, it must
|
|
492
|
+
be positive, in which case the coefficients `a_1` to `a_X` are
|
|
493
|
+
returned in a list.
|
|
494
|
+
|
|
495
|
+
TESTS::
|
|
496
|
+
|
|
497
|
+
sage: e = DirichletGroup(11).gen()
|
|
498
|
+
sage: f = EisensteinForms(e, 3).eisenstein_series()[0]
|
|
499
|
+
sage: f.coefficients([0,1])
|
|
500
|
+
[15/11*zeta10^3 - 9/11*zeta10^2 - 26/11*zeta10 - 10/11,
|
|
501
|
+
1]
|
|
502
|
+
sage: f.coefficients([0,1,2,3])
|
|
503
|
+
[15/11*zeta10^3 - 9/11*zeta10^2 - 26/11*zeta10 - 10/11,
|
|
504
|
+
1,
|
|
505
|
+
4*zeta10 + 1,
|
|
506
|
+
-9*zeta10^3 + 1]
|
|
507
|
+
sage: f.coefficients([2,3])
|
|
508
|
+
[4*zeta10 + 1,
|
|
509
|
+
-9*zeta10^3 + 1]
|
|
510
|
+
|
|
511
|
+
Running this twice once revealed a bug, so we test it::
|
|
512
|
+
|
|
513
|
+
sage: f.coefficients([0,1,2,3])
|
|
514
|
+
[15/11*zeta10^3 - 9/11*zeta10^2 - 26/11*zeta10 - 10/11,
|
|
515
|
+
1,
|
|
516
|
+
4*zeta10 + 1,
|
|
517
|
+
-9*zeta10^3 + 1]
|
|
518
|
+
"""
|
|
519
|
+
try:
|
|
520
|
+
self.__coefficients
|
|
521
|
+
except AttributeError:
|
|
522
|
+
self.__coefficients = {}
|
|
523
|
+
if isinstance(X, (int, Integer)):
|
|
524
|
+
X = list(range(1, ZZ(X) + 1))
|
|
525
|
+
Y = [n for n in X if n not in self.__coefficients]
|
|
526
|
+
v = self._compute(Y)
|
|
527
|
+
for i in range(len(v)):
|
|
528
|
+
self.__coefficients[Y[i]] = v[i]
|
|
529
|
+
return [self.__coefficients[x] for x in X]
|
|
530
|
+
|
|
531
|
+
def __getitem__(self, n):
|
|
532
|
+
"""
|
|
533
|
+
Return the `q^n` coefficient of the `q`-expansion of ``self`` or
|
|
534
|
+
returns a list containing the `q^i` coefficients of self
|
|
535
|
+
where `i` is in slice `n`.
|
|
536
|
+
|
|
537
|
+
EXAMPLES::
|
|
538
|
+
|
|
539
|
+
sage: f = ModularForms(DirichletGroup(17).0^2,2).2
|
|
540
|
+
sage: f.__getitem__(10)
|
|
541
|
+
zeta8^3 - 5*zeta8^2 - 2*zeta8 + 10
|
|
542
|
+
sage: f[30]
|
|
543
|
+
-2*zeta8^3 - 17*zeta8^2 + 4*zeta8 + 29
|
|
544
|
+
sage: f[10:15]
|
|
545
|
+
[zeta8^3 - 5*zeta8^2 - 2*zeta8 + 10,
|
|
546
|
+
-zeta8^3 + 11,
|
|
547
|
+
-2*zeta8^3 - 6*zeta8^2 + 3*zeta8 + 9,
|
|
548
|
+
12,
|
|
549
|
+
2*zeta8^3 - 7*zeta8^2 + zeta8 + 14]
|
|
550
|
+
"""
|
|
551
|
+
if isinstance(n, slice):
|
|
552
|
+
if n.stop is None:
|
|
553
|
+
return self.q_expansion().list()[n]
|
|
554
|
+
else:
|
|
555
|
+
return self.q_expansion(n.stop + 1).list()[n]
|
|
556
|
+
else:
|
|
557
|
+
return self.q_expansion(n + 1)[int(n)]
|
|
558
|
+
|
|
559
|
+
def coefficient(self, n):
|
|
560
|
+
r"""
|
|
561
|
+
Return the `n`-th coefficient of the `q`-expansion of ``self``.
|
|
562
|
+
|
|
563
|
+
INPUT:
|
|
564
|
+
|
|
565
|
+
- ``n`` -- nonnegative integer
|
|
566
|
+
|
|
567
|
+
EXAMPLES::
|
|
568
|
+
|
|
569
|
+
sage: f = ModularForms(1, 12).0; f
|
|
570
|
+
q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6)
|
|
571
|
+
sage: f.coefficient(0)
|
|
572
|
+
0
|
|
573
|
+
sage: f.coefficient(1)
|
|
574
|
+
1
|
|
575
|
+
sage: f.coefficient(2)
|
|
576
|
+
-24
|
|
577
|
+
sage: f.coefficient(3)
|
|
578
|
+
252
|
|
579
|
+
sage: f.coefficient(4)
|
|
580
|
+
-1472
|
|
581
|
+
"""
|
|
582
|
+
n = ZZ(n)
|
|
583
|
+
return self.q_expansion(n + 1)[n]
|
|
584
|
+
|
|
585
|
+
def padded_list(self, n):
|
|
586
|
+
"""
|
|
587
|
+
Return a list of length n whose entries are the first n
|
|
588
|
+
coefficients of the `q`-expansion of ``self``.
|
|
589
|
+
|
|
590
|
+
EXAMPLES::
|
|
591
|
+
|
|
592
|
+
sage: CuspForms(1,12).0.padded_list(20)
|
|
593
|
+
[0, 1, -24, 252, -1472, 4830, -6048, -16744, 84480, -113643,
|
|
594
|
+
-115920, 534612, -370944, -577738, 401856, 1217160, 987136,
|
|
595
|
+
-6905934, 2727432, 10661420]
|
|
596
|
+
"""
|
|
597
|
+
return self.q_expansion(n).padded_list(n)
|
|
598
|
+
|
|
599
|
+
def _latex_(self):
|
|
600
|
+
"""
|
|
601
|
+
Return the LaTeX expression of ``self``.
|
|
602
|
+
|
|
603
|
+
EXAMPLES::
|
|
604
|
+
|
|
605
|
+
sage: ModularForms(25,4).0._latex_()
|
|
606
|
+
'q + O(q^{6})'
|
|
607
|
+
|
|
608
|
+
sage: ModularForms(25,4).4._latex_()
|
|
609
|
+
'q^{5} + O(q^{6})'
|
|
610
|
+
"""
|
|
611
|
+
return self.q_expansion()._latex_()
|
|
612
|
+
|
|
613
|
+
def character(self, compute=True):
|
|
614
|
+
"""
|
|
615
|
+
Return the character of ``self``. If ``compute=False``, then this will
|
|
616
|
+
return None unless the form was explicitly created as an element of a
|
|
617
|
+
space of forms with character, skipping the (potentially expensive)
|
|
618
|
+
computation of the matrices of the diamond operators.
|
|
619
|
+
|
|
620
|
+
EXAMPLES::
|
|
621
|
+
|
|
622
|
+
sage: ModularForms(DirichletGroup(17).0^2,2).2.character()
|
|
623
|
+
Dirichlet character modulo 17 of conductor 17 mapping 3 |--> zeta8
|
|
624
|
+
|
|
625
|
+
sage: CuspForms(Gamma1(7), 3).gen(0).character()
|
|
626
|
+
Dirichlet character modulo 7 of conductor 7 mapping 3 |--> -1
|
|
627
|
+
sage: CuspForms(Gamma1(7), 3).gen(0).character(compute = False) is None
|
|
628
|
+
True
|
|
629
|
+
sage: M = CuspForms(Gamma1(7), 5).gen(0).character()
|
|
630
|
+
Traceback (most recent call last):
|
|
631
|
+
...
|
|
632
|
+
ValueError: Form is not an eigenvector for <3>
|
|
633
|
+
"""
|
|
634
|
+
chi = self.parent().character()
|
|
635
|
+
if (chi is not None) or (not compute):
|
|
636
|
+
return chi
|
|
637
|
+
else: # do the expensive computation
|
|
638
|
+
G = DirichletGroup(self.parent().level(), base_ring=self.parent().base_ring())
|
|
639
|
+
gens = G.unit_gens()
|
|
640
|
+
i = self.valuation()
|
|
641
|
+
vals = []
|
|
642
|
+
for g in gens:
|
|
643
|
+
df = self.parent().diamond_bracket_operator(g)(self)
|
|
644
|
+
if df != (df[i] / self[i]) * self:
|
|
645
|
+
raise ValueError("Form is not an eigenvector for <%s>" % g)
|
|
646
|
+
vals.append(df[i] / self[i])
|
|
647
|
+
return G(vals)
|
|
648
|
+
|
|
649
|
+
def __bool__(self):
|
|
650
|
+
"""
|
|
651
|
+
Return ``True`` if ``self`` is nonzero, and ``False`` if not.
|
|
652
|
+
|
|
653
|
+
EXAMPLES::
|
|
654
|
+
|
|
655
|
+
sage: bool(ModularForms(25,6).6)
|
|
656
|
+
True
|
|
657
|
+
"""
|
|
658
|
+
return not self.element().is_zero()
|
|
659
|
+
|
|
660
|
+
def prec(self):
|
|
661
|
+
"""
|
|
662
|
+
Return the precision to which self.q_expansion() is
|
|
663
|
+
currently known. Note that this may be 0.
|
|
664
|
+
|
|
665
|
+
EXAMPLES::
|
|
666
|
+
|
|
667
|
+
sage: M = ModularForms(2,14)
|
|
668
|
+
sage: f = M.0
|
|
669
|
+
sage: f.prec()
|
|
670
|
+
0
|
|
671
|
+
|
|
672
|
+
sage: M.prec(20)
|
|
673
|
+
20
|
|
674
|
+
sage: f.prec()
|
|
675
|
+
0
|
|
676
|
+
sage: x = f.q_expansion() ; f.prec()
|
|
677
|
+
20
|
|
678
|
+
"""
|
|
679
|
+
try:
|
|
680
|
+
return self.__q_expansion[0]
|
|
681
|
+
except AttributeError:
|
|
682
|
+
return 0
|
|
683
|
+
|
|
684
|
+
def q_expansion(self, prec=None):
|
|
685
|
+
r"""
|
|
686
|
+
The `q`-expansion of the modular form to precision `O(q^\text{prec})`.
|
|
687
|
+
This function takes one argument, which is the integer prec.
|
|
688
|
+
|
|
689
|
+
EXAMPLES:
|
|
690
|
+
|
|
691
|
+
We compute the cusp form `\Delta`::
|
|
692
|
+
|
|
693
|
+
sage: delta = CuspForms(1,12).0
|
|
694
|
+
sage: delta.q_expansion()
|
|
695
|
+
q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6)
|
|
696
|
+
|
|
697
|
+
We compute the `q`-expansion of one of the cusp forms of level 23::
|
|
698
|
+
|
|
699
|
+
sage: f = CuspForms(23,2).0
|
|
700
|
+
sage: f.q_expansion()
|
|
701
|
+
q - q^3 - q^4 + O(q^6)
|
|
702
|
+
sage: f.q_expansion(10)
|
|
703
|
+
q - q^3 - q^4 - 2*q^6 + 2*q^7 - q^8 + 2*q^9 + O(q^10)
|
|
704
|
+
sage: f.q_expansion(2)
|
|
705
|
+
q + O(q^2)
|
|
706
|
+
sage: f.q_expansion(1)
|
|
707
|
+
O(q^1)
|
|
708
|
+
sage: f.q_expansion(0)
|
|
709
|
+
O(q^0)
|
|
710
|
+
sage: f.q_expansion(-1)
|
|
711
|
+
Traceback (most recent call last):
|
|
712
|
+
...
|
|
713
|
+
ValueError: prec (= -1) must be nonnegative
|
|
714
|
+
"""
|
|
715
|
+
if prec is None:
|
|
716
|
+
prec = self.parent().prec()
|
|
717
|
+
prec = Integer(prec)
|
|
718
|
+
try:
|
|
719
|
+
current_prec, f = self.__q_expansion
|
|
720
|
+
except AttributeError:
|
|
721
|
+
current_prec = 0
|
|
722
|
+
f = self.parent()._q_expansion_ring()(0, 0)
|
|
723
|
+
|
|
724
|
+
if current_prec == prec:
|
|
725
|
+
return f
|
|
726
|
+
elif current_prec > prec:
|
|
727
|
+
return f.add_bigoh(prec)
|
|
728
|
+
else:
|
|
729
|
+
f = self._compute_q_expansion(prec)
|
|
730
|
+
self.__q_expansion = (prec, f)
|
|
731
|
+
return f
|
|
732
|
+
|
|
733
|
+
def serre_derivative(self):
|
|
734
|
+
"""
|
|
735
|
+
Return the Serre derivative of the given modular form.
|
|
736
|
+
|
|
737
|
+
If ``self`` is of weight `k`, then the returned modular form will be of
|
|
738
|
+
weight `k+2`.
|
|
739
|
+
|
|
740
|
+
EXAMPLES::
|
|
741
|
+
|
|
742
|
+
sage: E4 = ModularForms(1, 4).0
|
|
743
|
+
sage: E6 = ModularForms(1, 6).0
|
|
744
|
+
sage: DE4 = E4.serre_derivative(); DE4
|
|
745
|
+
-1/3 + 168*q + 5544*q^2 + 40992*q^3 + 177576*q^4 + 525168*q^5 + O(q^6)
|
|
746
|
+
sage: DE6 = E6.serre_derivative(); DE6
|
|
747
|
+
-1/2 - 240*q - 30960*q^2 - 525120*q^3 - 3963120*q^4 - 18750240*q^5 + O(q^6)
|
|
748
|
+
sage: Del = ModularForms(1, 12).0 # Modular discriminant
|
|
749
|
+
sage: Del.serre_derivative()
|
|
750
|
+
0
|
|
751
|
+
sage: f = ModularForms(DirichletGroup(5).0, 1).0
|
|
752
|
+
sage: Df = f.serre_derivative(); Df
|
|
753
|
+
-1/12 + (-11/12*zeta4 + 19/4)*q + (11/6*zeta4 + 59/3)*q^2 + (-41/3*zeta4 + 239/6)*q^3 + (31/4*zeta4 + 839/12)*q^4 + (-251/12*zeta4 + 459/4)*q^5 + O(q^6)
|
|
754
|
+
|
|
755
|
+
The Serre derivative raises the weight of a modular form by `2`::
|
|
756
|
+
|
|
757
|
+
sage: DE4.weight()
|
|
758
|
+
6
|
|
759
|
+
sage: DE6.weight()
|
|
760
|
+
8
|
|
761
|
+
sage: Df.weight()
|
|
762
|
+
3
|
|
763
|
+
|
|
764
|
+
The Ramanujan identities are verified (see :wikipedia:`Eisenstein_series#Ramanujan_identities`)::
|
|
765
|
+
|
|
766
|
+
sage: DE4 == (-1/3) * E6
|
|
767
|
+
True
|
|
768
|
+
sage: DE6 == (-1/2) * E4 * E4
|
|
769
|
+
True
|
|
770
|
+
"""
|
|
771
|
+
from .eis_series import eisenstein_series_qexp
|
|
772
|
+
from .constructor import ModularForms
|
|
773
|
+
|
|
774
|
+
# check if the parent space has a character or not
|
|
775
|
+
if self.parent().has_character():
|
|
776
|
+
group = self.parent().character()
|
|
777
|
+
else:
|
|
778
|
+
group = self.parent().group()
|
|
779
|
+
|
|
780
|
+
# raise the weight by 2
|
|
781
|
+
parent_space = ModularForms(group, self.weight() + 2, self.base_ring())
|
|
782
|
+
|
|
783
|
+
# compute the precision for q-expansions
|
|
784
|
+
bound = parent_space._q_expansion_module().degree() + 1
|
|
785
|
+
E2 = eisenstein_series_qexp(2, prec=bound, K=self.base_ring(), normalization='integral')
|
|
786
|
+
self_qexp = self.q_expansion(prec=bound)
|
|
787
|
+
|
|
788
|
+
# compute the derivative via q-expansions
|
|
789
|
+
R = self.base_ring()
|
|
790
|
+
q = self_qexp.parent().gen()
|
|
791
|
+
mult = R(self.weight()) * R(12).inverse_of_unit()
|
|
792
|
+
der = q * self_qexp.derivative() + (mult) * E2 * self_qexp
|
|
793
|
+
|
|
794
|
+
return parent_space(der)
|
|
795
|
+
|
|
796
|
+
def atkin_lehner_eigenvalue(self, d=None, embedding=None):
|
|
797
|
+
"""
|
|
798
|
+
Return the eigenvalue of the Atkin-Lehner operator `W_d`
|
|
799
|
+
acting on ``self``.
|
|
800
|
+
|
|
801
|
+
INPUT:
|
|
802
|
+
|
|
803
|
+
- ``d`` -- positive integer exactly dividing the level `N`
|
|
804
|
+
of ``self``, i.e. `d` divides `N` and is coprime to `N/d`
|
|
805
|
+
(default: `d = N`)
|
|
806
|
+
|
|
807
|
+
- ``embedding`` -- (optional) embedding of the base ring of
|
|
808
|
+
``self`` into another ring
|
|
809
|
+
|
|
810
|
+
OUTPUT:
|
|
811
|
+
|
|
812
|
+
The Atkin-Lehner eigenvalue of `W_d` on ``self``. This is
|
|
813
|
+
returned as an element of the codomain of ``embedding`` if
|
|
814
|
+
specified, and in (a suitable extension of) the base field of
|
|
815
|
+
``self`` otherwise.
|
|
816
|
+
|
|
817
|
+
If ``self`` is not an eigenform for `W_d`, a :exc:`ValueError` is
|
|
818
|
+
raised.
|
|
819
|
+
|
|
820
|
+
.. SEEALSO::
|
|
821
|
+
|
|
822
|
+
:meth:`sage.modular.hecke.module.HeckeModule_free_module.atkin_lehner_operator`
|
|
823
|
+
(especially for the conventions used to define the operator `W_d`).
|
|
824
|
+
|
|
825
|
+
EXAMPLES::
|
|
826
|
+
|
|
827
|
+
sage: CuspForms(1, 12).0.atkin_lehner_eigenvalue()
|
|
828
|
+
1
|
|
829
|
+
sage: CuspForms(2, 8).0.atkin_lehner_eigenvalue()
|
|
830
|
+
Traceback (most recent call last):
|
|
831
|
+
...
|
|
832
|
+
NotImplementedError: don't know how to compute Atkin-Lehner matrix acting on this space (try using a newform constructor instead)
|
|
833
|
+
"""
|
|
834
|
+
raise NotImplementedError("don't know how to compute Atkin-Lehner matrix acting on this space (try using a newform constructor instead)")
|
|
835
|
+
|
|
836
|
+
# The methods period() and lseries() below currently live
|
|
837
|
+
# in ModularForm_abstract so they are inherited by Newform (which
|
|
838
|
+
# does *not* derive from ModularFormElement).
|
|
839
|
+
|
|
840
|
+
def period(self, M, prec=53):
|
|
841
|
+
r"""
|
|
842
|
+
Return the period of ``self`` with respect to `M`.
|
|
843
|
+
|
|
844
|
+
INPUT:
|
|
845
|
+
|
|
846
|
+
- ``self`` -- a cusp form `f` of weight 2 for `Gamma_0(N)`
|
|
847
|
+
|
|
848
|
+
- ``M`` -- an element of `\Gamma_0(N)`
|
|
849
|
+
|
|
850
|
+
- ``prec`` -- (default: 53) the working precision in bits. If
|
|
851
|
+
`f` is a normalised eigenform, then the output is correct to
|
|
852
|
+
approximately this number of bits.
|
|
853
|
+
|
|
854
|
+
OUTPUT:
|
|
855
|
+
|
|
856
|
+
A numerical approximation of the period `P_f(M)`. This period
|
|
857
|
+
is defined by the following integral over the complex upper
|
|
858
|
+
half-plane, for any `\alpha` in `\Bold{P}^1(\QQ)`:
|
|
859
|
+
|
|
860
|
+
.. MATH::
|
|
861
|
+
|
|
862
|
+
P_f(M) = 2 \pi i \int_\alpha^{M(\alpha)} f(z) dz.
|
|
863
|
+
|
|
864
|
+
This is independent of the choice of `\alpha`.
|
|
865
|
+
|
|
866
|
+
EXAMPLES::
|
|
867
|
+
|
|
868
|
+
sage: C = Newforms(11, 2)[0]
|
|
869
|
+
sage: m = C.group()(matrix([[-4, -3], [11, 8]]))
|
|
870
|
+
sage: C.period(m)
|
|
871
|
+
-0.634604652139776 - 1.45881661693850*I
|
|
872
|
+
|
|
873
|
+
sage: f = Newforms(15, 2)[0]
|
|
874
|
+
sage: g = Gamma0(15)(matrix([[-4, -3], [15, 11]]))
|
|
875
|
+
sage: f.period(g) # abs tol 1e-15
|
|
876
|
+
2.17298044293747e-16 - 1.59624222213178*I
|
|
877
|
+
|
|
878
|
+
If `E` is an elliptic curve over `\QQ` and `f` is the newform
|
|
879
|
+
associated to `E`, then the periods of `f` are in the period
|
|
880
|
+
lattice of `E` up to an integer multiple::
|
|
881
|
+
|
|
882
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
883
|
+
sage: E = EllipticCurve('11a3')
|
|
884
|
+
sage: f = E.newform()
|
|
885
|
+
sage: g = Gamma0(11)([3, 1, 11, 4])
|
|
886
|
+
sage: f.period(g)
|
|
887
|
+
0.634604652139777 + 1.45881661693850*I
|
|
888
|
+
sage: omega1, omega2 = E.period_lattice().basis()
|
|
889
|
+
sage: -2/5*omega1 + omega2
|
|
890
|
+
0.634604652139777 + 1.45881661693850*I
|
|
891
|
+
|
|
892
|
+
The integer multiple is 5 in this case, which is explained by
|
|
893
|
+
the fact that there is a 5-isogeny between the elliptic curves
|
|
894
|
+
`J_0(5)` and `E`.
|
|
895
|
+
|
|
896
|
+
The elliptic curve `E` has a pair of modular symbols attached
|
|
897
|
+
to it, which can be computed using the method
|
|
898
|
+
:meth:`sage.schemes.elliptic_curves.ell_rational_field.EllipticCurve_rational_field.modular_symbol`.
|
|
899
|
+
These can be used to express the periods of `f` as exact
|
|
900
|
+
linear combinations of the real and the imaginary period of `E`::
|
|
901
|
+
|
|
902
|
+
sage: # needs database_cremona_mini_ellcurve eclib
|
|
903
|
+
sage: s = E.modular_symbol(sign=+1)
|
|
904
|
+
sage: t = E.modular_symbol(sign=-1, implementation='sage')
|
|
905
|
+
sage: s(3/11), t(3/11)
|
|
906
|
+
(1/10, 1/2)
|
|
907
|
+
sage: s(3/11)*omega1 + t(3/11)*2*omega2.imag()*I
|
|
908
|
+
0.634604652139777 + 1.45881661693850*I
|
|
909
|
+
|
|
910
|
+
ALGORITHM:
|
|
911
|
+
|
|
912
|
+
We use the series expression from [Cre1997]_, Chapter II,
|
|
913
|
+
Proposition 2.10.3. The algorithm sums the first `T` terms of
|
|
914
|
+
this series, where `T` is chosen in such a way that the result
|
|
915
|
+
would approximate `P_f(M)` with an absolute error of at most
|
|
916
|
+
`2^{-\text{prec}}` if all computations were done exactly.
|
|
917
|
+
|
|
918
|
+
Since the actual precision is finite, the output is currently
|
|
919
|
+
*not* guaranteed to be correct to ``prec`` bits of precision.
|
|
920
|
+
|
|
921
|
+
TESTS::
|
|
922
|
+
|
|
923
|
+
sage: C = Newforms(11, 2)[0]
|
|
924
|
+
sage: g = Gamma0(15)(matrix([[-4, -3], [15, 11]]))
|
|
925
|
+
sage: C.period(g)
|
|
926
|
+
Traceback (most recent call last):
|
|
927
|
+
...
|
|
928
|
+
TypeError: matrix [-4 -3]
|
|
929
|
+
[15 11]
|
|
930
|
+
is not an element of Congruence Subgroup Gamma0(11)
|
|
931
|
+
|
|
932
|
+
sage: f = Newforms(Gamma0(15), 4)[0]
|
|
933
|
+
sage: f.period(g)
|
|
934
|
+
Traceback (most recent call last):
|
|
935
|
+
...
|
|
936
|
+
ValueError: period pairing only defined for cusp forms of weight 2
|
|
937
|
+
|
|
938
|
+
sage: S = Newforms(Gamma1(17), 2, names='a')
|
|
939
|
+
sage: f = S[1]
|
|
940
|
+
sage: g = Gamma1(17)([18, 1, 17, 1])
|
|
941
|
+
sage: f.period(g)
|
|
942
|
+
Traceback (most recent call last):
|
|
943
|
+
...
|
|
944
|
+
NotImplementedError: period pairing only implemented for cusp forms of trivial character
|
|
945
|
+
|
|
946
|
+
sage: E = ModularForms(Gamma0(4), 2).eisenstein_series()[0]
|
|
947
|
+
sage: gamma = Gamma0(4)([1, 0, 4, 1])
|
|
948
|
+
sage: E.period(gamma)
|
|
949
|
+
Traceback (most recent call last):
|
|
950
|
+
...
|
|
951
|
+
NotImplementedError: don't know how to compute Atkin-Lehner matrix acting on this space (try using a newform constructor instead)
|
|
952
|
+
|
|
953
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
954
|
+
sage: E = EllipticCurve('19a1')
|
|
955
|
+
sage: M = Gamma0(19)([10, 1, 19, 2])
|
|
956
|
+
sage: E.newform().period(M) # abs tol 1e-14
|
|
957
|
+
-1.35975973348831 + 1.09365931898146e-16*I
|
|
958
|
+
"""
|
|
959
|
+
R = RealField(prec)
|
|
960
|
+
|
|
961
|
+
N = self.level()
|
|
962
|
+
if not self.character().is_trivial():
|
|
963
|
+
raise NotImplementedError('period pairing only implemented for cusp forms of trivial character')
|
|
964
|
+
if self.weight() != 2:
|
|
965
|
+
raise ValueError('period pairing only defined for cusp forms of weight 2')
|
|
966
|
+
if not isinstance(self, (Newform, ModularFormElement_elliptic_curve)):
|
|
967
|
+
print('Warning: not a newform, precision not guaranteed')
|
|
968
|
+
|
|
969
|
+
M = self.group()(M)
|
|
970
|
+
# coefficients of the matrix M
|
|
971
|
+
b, c, d = (M.b(), M.c() / N, M.d())
|
|
972
|
+
if d == 0:
|
|
973
|
+
return R.zero()
|
|
974
|
+
if d < 0:
|
|
975
|
+
b, c, d = (-b, -c, -d)
|
|
976
|
+
|
|
977
|
+
twopi = 2 * R.pi()
|
|
978
|
+
I = R.complex_field().gen()
|
|
979
|
+
rootN = R(N).sqrt()
|
|
980
|
+
|
|
981
|
+
eps = self.atkin_lehner_eigenvalue()
|
|
982
|
+
mu_N = (-twopi / rootN).exp()
|
|
983
|
+
mu_dN = (-twopi / d / rootN).exp()
|
|
984
|
+
mu_d = (twopi * I / d).exp()
|
|
985
|
+
|
|
986
|
+
# We bound the tail of the series by means of the triangle
|
|
987
|
+
# inequality and the following bounds (tau(n) = #divisors(n)):
|
|
988
|
+
# mu_N <= mu_dN
|
|
989
|
+
# |a_n(f)| <= tau(n)*sqrt(n) (holds if f is a newform)
|
|
990
|
+
# tau(n) <= sqrt(3)*sqrt(n) for all n >= 1
|
|
991
|
+
# This gives a correct but somewhat coarse lower bound on the
|
|
992
|
+
# number of terms needed. We ignore rounding errors.
|
|
993
|
+
numterms = (((1 - mu_dN) * R(2)**(-prec)
|
|
994
|
+
/ ((abs(eps - 1) + 2) * R(3).sqrt())).log()
|
|
995
|
+
/ mu_dN.log()).ceil()
|
|
996
|
+
coeff = self.coefficients(numterms)
|
|
997
|
+
|
|
998
|
+
return sum((coeff[n - 1] / n)
|
|
999
|
+
* ((eps - 1) * mu_N ** n
|
|
1000
|
+
+ mu_dN ** n * (mu_d ** (n * b) - eps * mu_d ** (n * c)))
|
|
1001
|
+
for n in range(1, numterms + 1))
|
|
1002
|
+
|
|
1003
|
+
def lseries(self, embedding=0, prec=53, max_imaginary_part=0,
|
|
1004
|
+
max_asymp_coeffs=40):
|
|
1005
|
+
r"""
|
|
1006
|
+
Return the `L`-series of the weight k cusp form
|
|
1007
|
+
`f` on `\Gamma_0(N)`.
|
|
1008
|
+
|
|
1009
|
+
This actually returns an interface to Tim Dokchitser's program for
|
|
1010
|
+
computing with the `L`-series of the cusp form.
|
|
1011
|
+
|
|
1012
|
+
INPUT:
|
|
1013
|
+
|
|
1014
|
+
- ``embedding`` -- either an embedding of the coefficient field of self
|
|
1015
|
+
into `\CC`, or an integer `i` between 0 and D-1 where D is the degree
|
|
1016
|
+
of the coefficient field (meaning to pick the `i`-th embedding).
|
|
1017
|
+
(default: 0)
|
|
1018
|
+
|
|
1019
|
+
- ``prec`` -- integer (default: 53); bits precision
|
|
1020
|
+
|
|
1021
|
+
- ``max_imaginary_part`` -- real number (default: 0)
|
|
1022
|
+
|
|
1023
|
+
- ``max_asymp_coeffs`` -- integer (default: 40)
|
|
1024
|
+
|
|
1025
|
+
For more information on the significance of the last three arguments,
|
|
1026
|
+
see :mod:`~sage.lfunctions.dokchitser`.
|
|
1027
|
+
|
|
1028
|
+
.. NOTE::
|
|
1029
|
+
|
|
1030
|
+
If an explicit embedding is given, but this embedding is specified
|
|
1031
|
+
to smaller precision than ``prec``, it will be automatically
|
|
1032
|
+
refined to precision ``prec``.
|
|
1033
|
+
|
|
1034
|
+
OUTPUT:
|
|
1035
|
+
|
|
1036
|
+
The `L`-series of the cusp form, as a
|
|
1037
|
+
:class:`sage.lfunctions.dokchitser.Dokchitser` object.
|
|
1038
|
+
|
|
1039
|
+
EXAMPLES::
|
|
1040
|
+
|
|
1041
|
+
sage: f = CuspForms(2,8).newforms()[0]
|
|
1042
|
+
sage: L = f.lseries()
|
|
1043
|
+
sage: L
|
|
1044
|
+
L-series associated to the cusp form q - 8*q^2 + 12*q^3 + 64*q^4 - 210*q^5 + O(q^6)
|
|
1045
|
+
sage: L(1)
|
|
1046
|
+
0.0884317737041015
|
|
1047
|
+
sage: L(0.5)
|
|
1048
|
+
0.0296568512531983
|
|
1049
|
+
|
|
1050
|
+
As a consistency check, we verify that the functional equation holds::
|
|
1051
|
+
|
|
1052
|
+
sage: abs(L.check_functional_equation()) < 1.0e-20
|
|
1053
|
+
True
|
|
1054
|
+
|
|
1055
|
+
For non-rational newforms we can specify an embedding of the coefficient field::
|
|
1056
|
+
|
|
1057
|
+
sage: f = Newforms(43, names='a')[1]
|
|
1058
|
+
sage: K = f.hecke_eigenvalue_field()
|
|
1059
|
+
sage: phi1, phi2 = K.embeddings(CC)
|
|
1060
|
+
sage: L = f.lseries(embedding=phi1)
|
|
1061
|
+
sage: L
|
|
1062
|
+
L-series associated to the cusp form q + a1*q^2 - a1*q^3 + (-a1 + 2)*q^5 + O(q^6), a1=-1.41421356237310
|
|
1063
|
+
sage: L(1)
|
|
1064
|
+
0.620539857407845
|
|
1065
|
+
sage: L = f.lseries(embedding=1)
|
|
1066
|
+
sage: L(1)
|
|
1067
|
+
0.921328017272472
|
|
1068
|
+
|
|
1069
|
+
An example with a non-real coefficient field (`\QQ(\zeta_3)`
|
|
1070
|
+
in this case)::
|
|
1071
|
+
|
|
1072
|
+
sage: f = Newforms(Gamma1(13), 2, names='a')[0]
|
|
1073
|
+
sage: f.lseries(embedding=0)(1)
|
|
1074
|
+
0.298115272465799 - 0.0402203326076734*I
|
|
1075
|
+
sage: f.lseries(embedding=1)(1)
|
|
1076
|
+
0.298115272465799 + 0.0402203326076732*I
|
|
1077
|
+
|
|
1078
|
+
We compute with the `L`-series of the Eisenstein series `E_4`::
|
|
1079
|
+
|
|
1080
|
+
sage: f = ModularForms(1,4).0
|
|
1081
|
+
sage: L = f.lseries()
|
|
1082
|
+
sage: L(1)
|
|
1083
|
+
-0.0304484570583933
|
|
1084
|
+
sage: L = eisenstein_series_lseries(4)
|
|
1085
|
+
sage: L(1)
|
|
1086
|
+
-0.0304484570583933
|
|
1087
|
+
|
|
1088
|
+
Consistency check with delta_lseries (which computes coefficients in pari)::
|
|
1089
|
+
|
|
1090
|
+
sage: delta = CuspForms(1,12).0
|
|
1091
|
+
sage: L = delta.lseries()
|
|
1092
|
+
sage: L(1)
|
|
1093
|
+
0.0374412812685155
|
|
1094
|
+
sage: L = delta_lseries()
|
|
1095
|
+
sage: L(1)
|
|
1096
|
+
0.0374412812685155
|
|
1097
|
+
|
|
1098
|
+
We check that :issue:`5262` is fixed::
|
|
1099
|
+
|
|
1100
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
1101
|
+
sage: E = EllipticCurve('37b2')
|
|
1102
|
+
sage: h = Newforms(37)[1]
|
|
1103
|
+
sage: Lh = h.lseries()
|
|
1104
|
+
sage: LE = E.lseries()
|
|
1105
|
+
sage: Lh(1), LE(1)
|
|
1106
|
+
(0.725681061936153, 0.725681061936153)
|
|
1107
|
+
sage: CuspForms(1, 30).0.lseries().eps
|
|
1108
|
+
-1.00000000000000
|
|
1109
|
+
|
|
1110
|
+
We check that :issue:`25369` is fixed::
|
|
1111
|
+
|
|
1112
|
+
sage: f5 = Newforms(Gamma1(4), 5, names='a')[0]; f5
|
|
1113
|
+
q - 4*q^2 + 16*q^4 - 14*q^5 + O(q^6)
|
|
1114
|
+
sage: L5 = f5.lseries()
|
|
1115
|
+
sage: abs(L5.check_functional_equation()) < 1e-15
|
|
1116
|
+
True
|
|
1117
|
+
sage: abs(L5(4) - (gamma(1/4)^8/(3840*pi^2)).n()) < 1e-15
|
|
1118
|
+
True
|
|
1119
|
+
|
|
1120
|
+
We can change the precision (in bits)::
|
|
1121
|
+
|
|
1122
|
+
sage: f = Newforms(389, names='a')[0]
|
|
1123
|
+
sage: L = f.lseries(prec=30)
|
|
1124
|
+
sage: abs(L(1)) < 2^-30
|
|
1125
|
+
True
|
|
1126
|
+
sage: L = f.lseries(prec=53)
|
|
1127
|
+
sage: abs(L(1)) < 2^-53
|
|
1128
|
+
True
|
|
1129
|
+
sage: L = f.lseries(prec=100)
|
|
1130
|
+
sage: abs(L(1)) < 2^-100
|
|
1131
|
+
True
|
|
1132
|
+
|
|
1133
|
+
sage: f = Newforms(27, names='a')[0]
|
|
1134
|
+
sage: L = f.lseries()
|
|
1135
|
+
sage: L(1)
|
|
1136
|
+
0.588879583428483
|
|
1137
|
+
"""
|
|
1138
|
+
from sage.lfunctions.dokchitser import Dokchitser
|
|
1139
|
+
|
|
1140
|
+
# compute the requested embedding
|
|
1141
|
+
C = ComplexField(prec)
|
|
1142
|
+
K = self.base_ring()
|
|
1143
|
+
if isinstance(embedding, RingHomomorphism):
|
|
1144
|
+
# Target of embedding might have precision less than desired, so
|
|
1145
|
+
# need to refine
|
|
1146
|
+
emb = NumberFieldEmbedding(K, C, embedding(K.gen()))
|
|
1147
|
+
else:
|
|
1148
|
+
emb = self.base_ring().embeddings(C)[embedding]
|
|
1149
|
+
|
|
1150
|
+
# key = (prec, max_imaginary_part, max_asymp_coeffs)
|
|
1151
|
+
l = self.weight()
|
|
1152
|
+
N = self.level()
|
|
1153
|
+
|
|
1154
|
+
# get global root number
|
|
1155
|
+
w = self.atkin_lehner_eigenvalue(N, embedding=emb)
|
|
1156
|
+
e = ~C.gen()**l * w
|
|
1157
|
+
|
|
1158
|
+
if self.is_cuspidal():
|
|
1159
|
+
poles = [] # cuspidal
|
|
1160
|
+
else:
|
|
1161
|
+
poles = [l] # non-cuspidal
|
|
1162
|
+
|
|
1163
|
+
L = Dokchitser(conductor=N, gammaV=[0, 1], weight=l, eps=e, poles=poles,
|
|
1164
|
+
prec=prec)
|
|
1165
|
+
# Find out how many coefficients of the Dirichlet series are needed
|
|
1166
|
+
# in order to compute to the required precision
|
|
1167
|
+
n_coeffs = L.cost()
|
|
1168
|
+
coeffs = self.q_expansion(n_coeffs + 1).padded_list()[1:]
|
|
1169
|
+
|
|
1170
|
+
# renormalize so that coefficient of q is 1
|
|
1171
|
+
b = coeffs[0]
|
|
1172
|
+
if b != 1:
|
|
1173
|
+
invb = 1 / b
|
|
1174
|
+
coeffs = (invb * c for c in coeffs)
|
|
1175
|
+
|
|
1176
|
+
v = [emb(c) for c in coeffs]
|
|
1177
|
+
w = [c.conjugate() for c in v]
|
|
1178
|
+
L.init_coeffs(v=v, w=w,
|
|
1179
|
+
max_imaginary_part=max_imaginary_part,
|
|
1180
|
+
max_asymp_coeffs=max_asymp_coeffs)
|
|
1181
|
+
L.check_functional_equation()
|
|
1182
|
+
if K == QQ:
|
|
1183
|
+
L.rename('L-series associated to the cusp form %s' % self)
|
|
1184
|
+
else:
|
|
1185
|
+
L.rename('L-series associated to the cusp form %s, %s=%s'
|
|
1186
|
+
% (self, K.variable_name(), emb(K.gen())))
|
|
1187
|
+
return L
|
|
1188
|
+
|
|
1189
|
+
def symsquare_lseries(self, chi=None, embedding=0, prec=53):
|
|
1190
|
+
r"""
|
|
1191
|
+
Compute the symmetric square `L`-series of this modular form, twisted by
|
|
1192
|
+
the character `\chi`.
|
|
1193
|
+
|
|
1194
|
+
INPUT:
|
|
1195
|
+
|
|
1196
|
+
- ``chi`` -- Dirichlet character to twist by, or ``None`` (default:
|
|
1197
|
+
``None``), interpreted as the trivial character)
|
|
1198
|
+
- ``embedding`` -- embedding of the coefficient field into `\RR` or
|
|
1199
|
+
`\CC`, or an integer `i` (in which case take the `i`-th embedding)
|
|
1200
|
+
- ``prec`` -- the desired precision in bits (default: 53)
|
|
1201
|
+
|
|
1202
|
+
OUTPUT: the symmetric square `L`-series of the cusp form, as a
|
|
1203
|
+
:class:`sage.lfunctions.dokchitser.Dokchitser` object.
|
|
1204
|
+
|
|
1205
|
+
EXAMPLES::
|
|
1206
|
+
|
|
1207
|
+
sage: CuspForms(1, 12).0.symsquare_lseries()(22)
|
|
1208
|
+
0.999645711124771
|
|
1209
|
+
|
|
1210
|
+
An example twisted by a nontrivial character::
|
|
1211
|
+
|
|
1212
|
+
sage: psi = DirichletGroup(7).0^2
|
|
1213
|
+
sage: L = CuspForms(1, 16).0.symsquare_lseries(psi)
|
|
1214
|
+
sage: L(22)
|
|
1215
|
+
0.998407750967420 - 0.00295712911510708*I
|
|
1216
|
+
|
|
1217
|
+
An example with coefficients not in `\QQ`::
|
|
1218
|
+
|
|
1219
|
+
sage: F = Newforms(1, 24, names='a')[0]
|
|
1220
|
+
sage: K = F.hecke_eigenvalue_field()
|
|
1221
|
+
sage: phi = K.embeddings(RR)[0]
|
|
1222
|
+
sage: L = F.symsquare_lseries(embedding=phi)
|
|
1223
|
+
sage: L(5)
|
|
1224
|
+
verbose -1 (...: dokchitser.py, __call__) Warning: Loss of 8 decimal digits due to cancellation
|
|
1225
|
+
-3.57698266793901e19
|
|
1226
|
+
|
|
1227
|
+
TESTS::
|
|
1228
|
+
|
|
1229
|
+
sage: CuspForms(1,16).0.symsquare_lseries(prec=200).check_functional_equation().abs() < 1.0e-80
|
|
1230
|
+
True
|
|
1231
|
+
sage: CuspForms(1, 12).0.symsquare_lseries(prec=1000)(22) # long time (20s)
|
|
1232
|
+
0.999645711124771397835729622033153189549796658647254961493709341358991830134499267117001769570658192128781135161587571716303826382489492569725002840546129937149159065273765309218543427544527498868033604310899372849565046516553245752253255585377793879866297612679545029546953895098375829822346290125161
|
|
1233
|
+
|
|
1234
|
+
Check that :issue:`23247` is fixed::
|
|
1235
|
+
|
|
1236
|
+
sage: F = Newforms(1,12)[0]
|
|
1237
|
+
sage: chi = DirichletGroup(7).0
|
|
1238
|
+
sage: abs(F.symsquare_lseries(chi).check_functional_equation()) < 1e-5 # long time
|
|
1239
|
+
True
|
|
1240
|
+
|
|
1241
|
+
AUTHORS:
|
|
1242
|
+
|
|
1243
|
+
- Martin Raum (2011) -- original code posted to sage-nt
|
|
1244
|
+
- David Loeffler (2015) -- added support for twists, integrated into
|
|
1245
|
+
Sage library
|
|
1246
|
+
"""
|
|
1247
|
+
from sage.lfunctions.dokchitser import Dokchitser
|
|
1248
|
+
weight = self.weight()
|
|
1249
|
+
C = ComplexField(prec)
|
|
1250
|
+
if self.level() != 1:
|
|
1251
|
+
raise NotImplementedError("Symmetric square L-functions only implemented for level 1")
|
|
1252
|
+
|
|
1253
|
+
# compute the requested embedding
|
|
1254
|
+
if isinstance(embedding, RingHomomorphism):
|
|
1255
|
+
# Target of embedding might have precision less than desired, so
|
|
1256
|
+
# need to refine
|
|
1257
|
+
K = self.base_ring()
|
|
1258
|
+
emb = NumberFieldEmbedding(K, ComplexField(prec), embedding(K.gen()))
|
|
1259
|
+
else:
|
|
1260
|
+
emb = self.base_ring().embeddings(ComplexField(prec))[embedding]
|
|
1261
|
+
|
|
1262
|
+
if chi is None:
|
|
1263
|
+
eps = 1
|
|
1264
|
+
N = 1
|
|
1265
|
+
else:
|
|
1266
|
+
assert chi.is_primitive()
|
|
1267
|
+
chi = chi.change_ring(C)
|
|
1268
|
+
eps = chi.gauss_sum()**3 / chi.base_ring()(chi.conductor())**QQ((3, 2))
|
|
1269
|
+
N = chi.conductor()**3
|
|
1270
|
+
|
|
1271
|
+
if (chi is None) or chi.is_even():
|
|
1272
|
+
L = Dokchitser(N, [0, 1, -weight + 2], 2 * weight - 1,
|
|
1273
|
+
eps, prec=prec)
|
|
1274
|
+
else:
|
|
1275
|
+
L = Dokchitser(N, [0, 1, -weight + 1], 2 * weight - 1,
|
|
1276
|
+
eps * C((0, 1)), prec=prec)
|
|
1277
|
+
lcoeffs_prec = L.cost()
|
|
1278
|
+
|
|
1279
|
+
t = verbose("Computing %s coefficients of F" % lcoeffs_prec, level=1)
|
|
1280
|
+
F_series = [u**2 for u in self.qexp(lcoeffs_prec + 1).list()[1:]]
|
|
1281
|
+
verbose("done", t, level=1)
|
|
1282
|
+
|
|
1283
|
+
# utility function for Dirichlet convolution of series
|
|
1284
|
+
def dirichlet_convolution(A, B):
|
|
1285
|
+
return [sum(A[d - 1] * B[n // d - 1] for d in divisors(n))
|
|
1286
|
+
for n in range(1, 1 + min(len(A), len(B)))]
|
|
1287
|
+
|
|
1288
|
+
# The Dirichlet series for \zeta(2 s - 2 k + 2)
|
|
1289
|
+
riemann_series = [n**(weight - 1) if n.is_square() else 0
|
|
1290
|
+
for n in xsrange(1, lcoeffs_prec + 1)]
|
|
1291
|
+
# The Dirichlet series for 1 / \zeta(s - k + 1)
|
|
1292
|
+
mu_series = [moebius(n) * n**(weight - 1) for n in xsrange(1, lcoeffs_prec + 1)]
|
|
1293
|
+
conv_series = dirichlet_convolution(mu_series, riemann_series)
|
|
1294
|
+
|
|
1295
|
+
dirichlet_series = dirichlet_convolution(conv_series, F_series)
|
|
1296
|
+
|
|
1297
|
+
# If the base ring is QQ we pass the coefficients to GP/PARI as exact
|
|
1298
|
+
# rationals. Otherwise, need to use the embedding.
|
|
1299
|
+
if self.base_ring() != QQ:
|
|
1300
|
+
dirichlet_series = [emb(cf) for cf in dirichlet_series]
|
|
1301
|
+
|
|
1302
|
+
if chi is not None:
|
|
1303
|
+
pari_precode_chi = str(chi.values()) + "[n%" + str(chi.conductor()) + "+1]; "
|
|
1304
|
+
else:
|
|
1305
|
+
pari_precode_chi = "1"
|
|
1306
|
+
|
|
1307
|
+
pari_precode = "hhh(n) = " + str(dirichlet_series) + "[n] * " + pari_precode_chi
|
|
1308
|
+
|
|
1309
|
+
L.init_coeffs("hhh(k)", w="conj(hhh(k))",
|
|
1310
|
+
pari_precode=pari_precode)
|
|
1311
|
+
|
|
1312
|
+
return L
|
|
1313
|
+
|
|
1314
|
+
def petersson_norm(self, embedding=0, prec=53):
|
|
1315
|
+
r"""
|
|
1316
|
+
Compute the Petersson scalar product of f with itself:
|
|
1317
|
+
|
|
1318
|
+
.. MATH::
|
|
1319
|
+
|
|
1320
|
+
\langle f, f \rangle = \int_{\Gamma_0(N) \backslash \mathbb{H}} |f(x + iy)|^2 y^k\, \mathrm{d}x\, \mathrm{d}y.
|
|
1321
|
+
|
|
1322
|
+
Only implemented for N = 1 at present. It is assumed that `f` has real
|
|
1323
|
+
coefficients. The norm is computed as a special value of the symmetric
|
|
1324
|
+
square `L`-function, using the identity
|
|
1325
|
+
|
|
1326
|
+
.. MATH::
|
|
1327
|
+
|
|
1328
|
+
\langle f, f \rangle = \frac{(k-1)! L(\mathrm{Sym}^2 f, k)}{2^{2k-1} \pi^{k+1}}
|
|
1329
|
+
|
|
1330
|
+
INPUT:
|
|
1331
|
+
|
|
1332
|
+
- ``embedding`` -- embedding of the coefficient field into `\RR` or
|
|
1333
|
+
`\CC`, or an integer `i` (interpreted as the `i`-th embedding)
|
|
1334
|
+
(default: 0)
|
|
1335
|
+
- ``prec`` -- integer (default: 53); precision in bits
|
|
1336
|
+
|
|
1337
|
+
EXAMPLES::
|
|
1338
|
+
|
|
1339
|
+
sage: CuspForms(1, 16).0.petersson_norm()
|
|
1340
|
+
verbose -1 (...: dokchitser.py, __call__) Warning: Loss of 2 decimal digits due to cancellation
|
|
1341
|
+
2.16906134759063e-6
|
|
1342
|
+
|
|
1343
|
+
The Petersson norm depends on a choice of embedding::
|
|
1344
|
+
|
|
1345
|
+
sage: set_verbose(-2, "dokchitser.py") # disable precision-loss warnings
|
|
1346
|
+
sage: F = Newforms(1, 24, names='a')[0]
|
|
1347
|
+
sage: F.petersson_norm(embedding=0)
|
|
1348
|
+
0.000107836545077234
|
|
1349
|
+
sage: F.petersson_norm(embedding=1)
|
|
1350
|
+
0.000128992800758160
|
|
1351
|
+
|
|
1352
|
+
TESTS:
|
|
1353
|
+
|
|
1354
|
+
Verify that the Petersson norm is a quadratic form::
|
|
1355
|
+
|
|
1356
|
+
sage: F, G = CuspForms(1, 24).basis()
|
|
1357
|
+
sage: X = lambda u: u.petersson_norm(prec=100)
|
|
1358
|
+
sage: (X(F + G) + X(F - G) - 2*X(F) - 2*X(G)).abs() < 1e-25
|
|
1359
|
+
True
|
|
1360
|
+
"""
|
|
1361
|
+
pi = RealField(prec).pi()
|
|
1362
|
+
L = self.symsquare_lseries(prec=prec, embedding=embedding)
|
|
1363
|
+
k = self.weight()
|
|
1364
|
+
return (ZZ(k - 1).factorial() / 2**(2 * k - 1) / pi**(k + 1)) * L(k).real_part()
|
|
1365
|
+
|
|
1366
|
+
def _q_expansion_bound(self, eps):
|
|
1367
|
+
r"""
|
|
1368
|
+
This function takes as input a modular form, ``self`` and a
|
|
1369
|
+
Dirichlet character ``eps`` and returns an integer bound such
|
|
1370
|
+
that if ``self`` and its twist by ``eps`` have the same
|
|
1371
|
+
`q`-expansion up to this bound, then they are equal.
|
|
1372
|
+
|
|
1373
|
+
The bound is taken from [Mu1997]_. See also [Shi1971]_, Proposition
|
|
1374
|
+
3.64.
|
|
1375
|
+
|
|
1376
|
+
INPUT:
|
|
1377
|
+
|
|
1378
|
+
- ``eps`` -- a Dirichlet character
|
|
1379
|
+
|
|
1380
|
+
OUTPUT: a positive integer
|
|
1381
|
+
|
|
1382
|
+
EXAMPLES:
|
|
1383
|
+
|
|
1384
|
+
Here is an example that can easily be checked by hand. ::
|
|
1385
|
+
|
|
1386
|
+
sage: M = ModularForms(Gamma0(11), 2)
|
|
1387
|
+
sage: C = M.cuspidal_submodule()
|
|
1388
|
+
sage: f = C.gens()[0]
|
|
1389
|
+
sage: F = CyclotomicField(5)
|
|
1390
|
+
sage: D = DirichletGroup(11, F)
|
|
1391
|
+
sage: eps = D.gens()[0]
|
|
1392
|
+
sage: f._q_expansion_bound(eps)
|
|
1393
|
+
22
|
|
1394
|
+
|
|
1395
|
+
The level of ``self`` does not have to be related to the conductor
|
|
1396
|
+
of eps. ::
|
|
1397
|
+
|
|
1398
|
+
sage: M = ModularForms(Gamma0(1), 12)
|
|
1399
|
+
sage: C = M.cuspidal_submodule()
|
|
1400
|
+
sage: Delta = C.gens()[0]
|
|
1401
|
+
sage: F = CyclotomicField(12)
|
|
1402
|
+
sage: D = DirichletGroup(13, F)
|
|
1403
|
+
sage: eps = D.gens()[0]
|
|
1404
|
+
sage: Delta._q_expansion_bound(eps)
|
|
1405
|
+
182
|
|
1406
|
+
"""
|
|
1407
|
+
chi = self.character()
|
|
1408
|
+
M = lcm([self.level(), eps.conductor()**2,
|
|
1409
|
+
chi.conductor() * eps.conductor()])
|
|
1410
|
+
y = QQ(self.weight()) / QQ(12) * M
|
|
1411
|
+
for p in M.prime_divisors():
|
|
1412
|
+
y *= (1 + 1 / QQ(p))
|
|
1413
|
+
return y.ceil()
|
|
1414
|
+
|
|
1415
|
+
@cached_method
|
|
1416
|
+
def has_cm(self) -> bool:
|
|
1417
|
+
r"""
|
|
1418
|
+
Return whether the modular form ``self`` has complex multiplication.
|
|
1419
|
+
|
|
1420
|
+
OUTPUT: boolean
|
|
1421
|
+
|
|
1422
|
+
.. SEEALSO::
|
|
1423
|
+
|
|
1424
|
+
- :meth:`cm_discriminant` (to return the CM field)
|
|
1425
|
+
- :meth:`sage.schemes.elliptic_curves.ell_rational_field.has_cm`
|
|
1426
|
+
|
|
1427
|
+
EXAMPLES::
|
|
1428
|
+
|
|
1429
|
+
sage: G = DirichletGroup(21); eps = G.0 * G.1
|
|
1430
|
+
sage: Newforms(eps, 2)[0].has_cm()
|
|
1431
|
+
True
|
|
1432
|
+
|
|
1433
|
+
This example illustrates what happens when
|
|
1434
|
+
candidate_characters(self) is the empty list. ::
|
|
1435
|
+
|
|
1436
|
+
sage: M = ModularForms(Gamma0(1), 12)
|
|
1437
|
+
sage: C = M.cuspidal_submodule()
|
|
1438
|
+
sage: Delta = C.gens()[0]
|
|
1439
|
+
sage: Delta.has_cm()
|
|
1440
|
+
False
|
|
1441
|
+
|
|
1442
|
+
We now compare the function has_cm between elliptic curves and
|
|
1443
|
+
their associated modular forms. ::
|
|
1444
|
+
|
|
1445
|
+
sage: E = EllipticCurve([-1, 0])
|
|
1446
|
+
sage: f = E.modular_form()
|
|
1447
|
+
sage: f.has_cm()
|
|
1448
|
+
True
|
|
1449
|
+
sage: E.has_cm() == f.has_cm()
|
|
1450
|
+
True
|
|
1451
|
+
|
|
1452
|
+
Here is a non-cm example coming from elliptic curves. ::
|
|
1453
|
+
|
|
1454
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
1455
|
+
sage: E = EllipticCurve('11a')
|
|
1456
|
+
sage: f = E.modular_form()
|
|
1457
|
+
sage: f.has_cm()
|
|
1458
|
+
False
|
|
1459
|
+
sage: E.has_cm() == f.has_cm()
|
|
1460
|
+
True
|
|
1461
|
+
"""
|
|
1462
|
+
N = self.level()
|
|
1463
|
+
M = self.character().conductor()
|
|
1464
|
+
|
|
1465
|
+
for p in N.prime_factors():
|
|
1466
|
+
if M % p and N.valuation(p) == 1:
|
|
1467
|
+
verbose("Form is Steinberg at %s, cannot be CM" % p, level=1)
|
|
1468
|
+
return False
|
|
1469
|
+
cand_chars = [(x, self._q_expansion_bound(x)) for x in DirichletGroup(N, QQ) if x.is_odd()]
|
|
1470
|
+
|
|
1471
|
+
verbose("Conductors of candidate characters: %s" % (", ".join(str(x[0].conductor()) for x in cand_chars)), level=1)
|
|
1472
|
+
verbose("Qexp bounds: %s" % (", ".join(str(x[1]) for x in cand_chars)), level=1)
|
|
1473
|
+
# If there are no candidate characters, then self cannot have CM.
|
|
1474
|
+
if not cand_chars:
|
|
1475
|
+
return False
|
|
1476
|
+
|
|
1477
|
+
# Test each prime and discard characters for which eps(p) != 1 when f[p] != 0.
|
|
1478
|
+
p = ZZ(2)
|
|
1479
|
+
while p <= min(B for (eps, B) in cand_chars):
|
|
1480
|
+
verbose("Checking p = %s (%s candidate characters left))" % (p, len(cand_chars)), level=1)
|
|
1481
|
+
# We only have to test the CM condition at primes that do not
|
|
1482
|
+
# divide the level of self.
|
|
1483
|
+
if not self.level() % p:
|
|
1484
|
+
p = p.next_prime()
|
|
1485
|
+
continue
|
|
1486
|
+
|
|
1487
|
+
# Evaluating characters is cheap, while computing f[p] is
|
|
1488
|
+
# expensive, so if eps(p) = 1 for all p, then we don't bother to
|
|
1489
|
+
# compute f[p].
|
|
1490
|
+
cand_chars = [(eps, B) for (eps, B) in cand_chars if (eps(p) == 1 or self[p] == 0)]
|
|
1491
|
+
|
|
1492
|
+
if len(cand_chars) == 0:
|
|
1493
|
+
# f doesn't have CM
|
|
1494
|
+
return False
|
|
1495
|
+
|
|
1496
|
+
# go on to next prime
|
|
1497
|
+
p = p.next_prime()
|
|
1498
|
+
|
|
1499
|
+
B0 = min(B for (eps, B) in cand_chars)
|
|
1500
|
+
C = [eps for (eps, B) in cand_chars if B == B0]
|
|
1501
|
+
if len(C) > 1:
|
|
1502
|
+
# can't happen (except in weight 1, which isn't implemented yet
|
|
1503
|
+
# anyway)
|
|
1504
|
+
raise ArithmeticError("Got multiple characters in has_cm")
|
|
1505
|
+
self.__cm_char = C[0].primitive_character()
|
|
1506
|
+
return True
|
|
1507
|
+
|
|
1508
|
+
def cm_discriminant(self):
|
|
1509
|
+
r"""
|
|
1510
|
+
Return the discriminant of the CM field associated to this form. An
|
|
1511
|
+
error will be raised if the form isn't of CM type.
|
|
1512
|
+
|
|
1513
|
+
EXAMPLES::
|
|
1514
|
+
|
|
1515
|
+
sage: Newforms(49, 2)[0].cm_discriminant()
|
|
1516
|
+
-7
|
|
1517
|
+
sage: CuspForms(1, 12).gen(0).cm_discriminant()
|
|
1518
|
+
Traceback (most recent call last):
|
|
1519
|
+
...
|
|
1520
|
+
ValueError: Not a CM form
|
|
1521
|
+
"""
|
|
1522
|
+
if not self.has_cm():
|
|
1523
|
+
raise ValueError("Not a CM form")
|
|
1524
|
+
return -self.__cm_char.conductor()
|
|
1525
|
+
|
|
1526
|
+
|
|
1527
|
+
class Newform(ModularForm_abstract):
|
|
1528
|
+
# The reasons why Newform does not inherit from ModularFormElement
|
|
1529
|
+
# should really be documented somewhere.
|
|
1530
|
+
|
|
1531
|
+
def __init__(self, parent, component, names, check=True):
|
|
1532
|
+
r"""
|
|
1533
|
+
Initialize a Newform object.
|
|
1534
|
+
|
|
1535
|
+
INPUT:
|
|
1536
|
+
|
|
1537
|
+
- ``parent`` -- an ambient cuspidal space of modular forms for
|
|
1538
|
+
which ``self`` is a newform
|
|
1539
|
+
|
|
1540
|
+
- ``component`` -- a simple component of a cuspidal modular
|
|
1541
|
+
symbols space of any sign corresponding to this newform
|
|
1542
|
+
|
|
1543
|
+
- ``check`` -- if check is ``True``, check that parent and
|
|
1544
|
+
component have the same weight, level, and character, that
|
|
1545
|
+
component has sign 1 and is simple, and that the types are
|
|
1546
|
+
correct on all inputs.
|
|
1547
|
+
|
|
1548
|
+
EXAMPLES::
|
|
1549
|
+
|
|
1550
|
+
sage: sage.modular.modform.element.Newform(CuspForms(11,2), ModularSymbols(11,2,sign=1).cuspidal_subspace(), 'a')
|
|
1551
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6)
|
|
1552
|
+
|
|
1553
|
+
sage: f = Newforms(DirichletGroup(5).0, 7,names='a')[0]; f[2].trace(f.base_ring().base_field())
|
|
1554
|
+
-5*zeta4 - 5
|
|
1555
|
+
"""
|
|
1556
|
+
from .space import ModularFormsSpace
|
|
1557
|
+
if check:
|
|
1558
|
+
if not isinstance(parent, ModularFormsSpace):
|
|
1559
|
+
raise TypeError("parent must be a space of modular forms")
|
|
1560
|
+
if not isinstance(component, ModularSymbolsSpace):
|
|
1561
|
+
raise TypeError("component must be a space of modular symbols")
|
|
1562
|
+
if parent.group() != component.group():
|
|
1563
|
+
raise ValueError("parent and component must be defined by the same congruence subgroup")
|
|
1564
|
+
if parent.weight() != component.weight():
|
|
1565
|
+
raise ValueError("parent and component must have the same weight")
|
|
1566
|
+
if not component.is_cuspidal():
|
|
1567
|
+
raise ValueError("component must be cuspidal")
|
|
1568
|
+
if not component.is_simple():
|
|
1569
|
+
raise ValueError("component must be simple")
|
|
1570
|
+
extension_field = component.eigenvalue(1, name=names).parent()
|
|
1571
|
+
if extension_field != parent.base_ring(): # .degree() != 1 and rings.is_NumberField(extension_field):
|
|
1572
|
+
assert extension_field.base_field() == parent.base_ring()
|
|
1573
|
+
extension_field = parent.base_ring().extension(extension_field.relative_polynomial(), names=names)
|
|
1574
|
+
self.__name = names
|
|
1575
|
+
ModuleElement.__init__(self, parent.base_extend(extension_field))
|
|
1576
|
+
self.__modsym_space = component
|
|
1577
|
+
self.__hecke_eigenvalue_field = extension_field
|
|
1578
|
+
|
|
1579
|
+
def _name(self):
|
|
1580
|
+
r"""
|
|
1581
|
+
Return the name of the generator of the Hecke eigenvalue field
|
|
1582
|
+
of ``self``. Note that a name exists even when this field is `\QQ`.
|
|
1583
|
+
|
|
1584
|
+
EXAMPLES::
|
|
1585
|
+
|
|
1586
|
+
sage: [ f._name() for f in Newforms(38,4,names='a') ]
|
|
1587
|
+
['a0', 'a1', 'a2']
|
|
1588
|
+
"""
|
|
1589
|
+
return self.__name
|
|
1590
|
+
|
|
1591
|
+
def _compute_q_expansion(self, prec):
|
|
1592
|
+
"""
|
|
1593
|
+
Return the `q`-expansion of ``self`` to precision ``prec``.
|
|
1594
|
+
|
|
1595
|
+
EXAMPLES::
|
|
1596
|
+
|
|
1597
|
+
sage: forms = Newforms(31, 6, names='a')
|
|
1598
|
+
sage: forms[0]._compute_q_expansion(10)
|
|
1599
|
+
q + a0*q^2 + (5/704*a0^4 + 43/704*a0^3 - 61/88*a0^2 - 197/44*a0 + 717/88)*q^3 + (a0^2 - 32)*q^4 + (-31/352*a0^4 - 249/352*a0^3 + 111/22*a0^2 + 218/11*a0 - 2879/44)*q^5 + (-1/352*a0^4 - 79/352*a0^3 - 67/44*a0^2 + 13/22*a0 - 425/44)*q^6 + (17/88*a0^4 + 133/88*a0^3 - 405/44*a0^2 - 1005/22*a0 - 35/11)*q^7 + (a0^3 - 64*a0)*q^8 + (39/352*a0^4 + 441/352*a0^3 - 93/44*a0^2 - 441/22*a0 - 5293/44)*q^9 + O(q^10)
|
|
1600
|
+
sage: forms[0]._compute_q_expansion(15)
|
|
1601
|
+
q + a0*q^2 + (5/704*a0^4 + 43/704*a0^3 - 61/88*a0^2 - 197/44*a0 + 717/88)*q^3 + (a0^2 - 32)*q^4 + (-31/352*a0^4 - 249/352*a0^3 + 111/22*a0^2 + 218/11*a0 - 2879/44)*q^5 + (-1/352*a0^4 - 79/352*a0^3 - 67/44*a0^2 + 13/22*a0 - 425/44)*q^6 + (17/88*a0^4 + 133/88*a0^3 - 405/44*a0^2 - 1005/22*a0 - 35/11)*q^7 + (a0^3 - 64*a0)*q^8 + (39/352*a0^4 + 441/352*a0^3 - 93/44*a0^2 - 441/22*a0 - 5293/44)*q^9 + (15/176*a0^4 - 135/176*a0^3 - 185/11*a0^2 + 311/11*a0 + 2635/22)*q^10 + (-291/704*a0^4 - 3629/704*a0^3 + 1139/88*a0^2 + 10295/44*a0 - 21067/88)*q^11 + (-75/176*a0^4 - 645/176*a0^3 + 475/22*a0^2 + 1503/11*a0 - 5651/22)*q^12 + (207/704*a0^4 + 2977/704*a0^3 + 581/88*a0^2 - 3307/44*a0 - 35753/88)*q^13 + (-5/22*a0^4 + 39/11*a0^3 + 763/22*a0^2 - 2296/11*a0 - 2890/11)*q^14 + O(q^15)
|
|
1602
|
+
"""
|
|
1603
|
+
return self.modular_symbols(1).q_eigenform(prec, names=self._name())
|
|
1604
|
+
|
|
1605
|
+
def __eq__(self, other):
|
|
1606
|
+
"""
|
|
1607
|
+
Return ``True`` if ``self`` equals ``other``, and ``False`` otherwise.
|
|
1608
|
+
|
|
1609
|
+
EXAMPLES::
|
|
1610
|
+
|
|
1611
|
+
sage: f1, f2 = Newforms(17,4,names='a')
|
|
1612
|
+
sage: f1.__eq__(f1)
|
|
1613
|
+
True
|
|
1614
|
+
sage: f1.__eq__(f2)
|
|
1615
|
+
False
|
|
1616
|
+
|
|
1617
|
+
We test comparison of equal newforms with different parents
|
|
1618
|
+
(see :issue:`18478`)::
|
|
1619
|
+
|
|
1620
|
+
sage: f = Newforms(Gamma1(11), 2)[0]; f
|
|
1621
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6)
|
|
1622
|
+
sage: g = Newforms(Gamma0(11), 2)[0]; g
|
|
1623
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6)
|
|
1624
|
+
sage: f == g
|
|
1625
|
+
True
|
|
1626
|
+
|
|
1627
|
+
sage: f = Newforms(DirichletGroup(4)[1], 5)[0]; f
|
|
1628
|
+
q - 4*q^2 + 16*q^4 - 14*q^5 + O(q^6)
|
|
1629
|
+
sage: g = Newforms(Gamma1(4), 5)[0]; g
|
|
1630
|
+
q - 4*q^2 + 16*q^4 - 14*q^5 + O(q^6)
|
|
1631
|
+
sage: f == g
|
|
1632
|
+
True
|
|
1633
|
+
"""
|
|
1634
|
+
if (not isinstance(other, ModularForm_abstract) or self.weight() != other.weight()):
|
|
1635
|
+
return False
|
|
1636
|
+
if isinstance(other, Newform):
|
|
1637
|
+
if (self.level() != other.level() or self.character() != other.character()):
|
|
1638
|
+
return False
|
|
1639
|
+
# The two parents may have different Sturm bounds in case
|
|
1640
|
+
# one of them is a space of cusp forms with character
|
|
1641
|
+
# (possibly trivial, i.e. for the group Gamma0(n)) and the
|
|
1642
|
+
# other is a space of cusp forms for Gamma1(n). It is
|
|
1643
|
+
# safe to take the smaller bound because we have checked
|
|
1644
|
+
# that the characters agree.
|
|
1645
|
+
bound = min(self.parent().sturm_bound(),
|
|
1646
|
+
other.parent().sturm_bound())
|
|
1647
|
+
return self.q_expansion(bound) == other.q_expansion(bound)
|
|
1648
|
+
# other is a ModularFormElement
|
|
1649
|
+
return self.element() == other
|
|
1650
|
+
|
|
1651
|
+
@cached_method
|
|
1652
|
+
def abelian_variety(self):
|
|
1653
|
+
"""
|
|
1654
|
+
Return the abelian variety associated to ``self``.
|
|
1655
|
+
|
|
1656
|
+
EXAMPLES::
|
|
1657
|
+
|
|
1658
|
+
sage: Newforms(14,2)[0]
|
|
1659
|
+
q - q^2 - 2*q^3 + q^4 + O(q^6)
|
|
1660
|
+
sage: Newforms(14,2)[0].abelian_variety()
|
|
1661
|
+
Newform abelian subvariety 14a of dimension 1 of J0(14)
|
|
1662
|
+
sage: Newforms(1, 12)[0].abelian_variety()
|
|
1663
|
+
Traceback (most recent call last):
|
|
1664
|
+
...
|
|
1665
|
+
TypeError: f must have weight 2
|
|
1666
|
+
"""
|
|
1667
|
+
from sage.modular.abvar.abvar_newform import ModularAbelianVariety_newform
|
|
1668
|
+
return ModularAbelianVariety_newform(self)
|
|
1669
|
+
|
|
1670
|
+
def hecke_eigenvalue_field(self):
|
|
1671
|
+
r"""
|
|
1672
|
+
Return the field generated over the rationals by the
|
|
1673
|
+
coefficients of this newform.
|
|
1674
|
+
|
|
1675
|
+
EXAMPLES::
|
|
1676
|
+
|
|
1677
|
+
sage: ls = Newforms(35, 2, names='a') ; ls
|
|
1678
|
+
[q + q^3 - 2*q^4 - q^5 + O(q^6),
|
|
1679
|
+
q + a1*q^2 + (-a1 - 1)*q^3 + (-a1 + 2)*q^4 + q^5 + O(q^6)]
|
|
1680
|
+
sage: ls[0].hecke_eigenvalue_field()
|
|
1681
|
+
Rational Field
|
|
1682
|
+
sage: ls[1].hecke_eigenvalue_field()
|
|
1683
|
+
Number Field in a1 with defining polynomial x^2 + x - 4
|
|
1684
|
+
"""
|
|
1685
|
+
return self.__hecke_eigenvalue_field
|
|
1686
|
+
|
|
1687
|
+
def coefficient(self, n):
|
|
1688
|
+
"""
|
|
1689
|
+
Return the coefficient of `q^n` in the power series of ``self``.
|
|
1690
|
+
|
|
1691
|
+
INPUT:
|
|
1692
|
+
|
|
1693
|
+
- ``n`` -- positive integer
|
|
1694
|
+
|
|
1695
|
+
OUTPUT: the coefficient of `q^n` in the power series of ``self``
|
|
1696
|
+
|
|
1697
|
+
EXAMPLES::
|
|
1698
|
+
|
|
1699
|
+
sage: f = Newforms(11)[0]; f
|
|
1700
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6)
|
|
1701
|
+
sage: f.coefficient(100)
|
|
1702
|
+
-8
|
|
1703
|
+
|
|
1704
|
+
sage: g = Newforms(23, names='a')[0]; g
|
|
1705
|
+
q + a0*q^2 + (-2*a0 - 1)*q^3 + (-a0 - 1)*q^4 + 2*a0*q^5 + O(q^6)
|
|
1706
|
+
sage: g.coefficient(3)
|
|
1707
|
+
-2*a0 - 1
|
|
1708
|
+
"""
|
|
1709
|
+
return self.modular_symbols(1).eigenvalue(n, self._name())
|
|
1710
|
+
|
|
1711
|
+
def _compute(self, X):
|
|
1712
|
+
"""
|
|
1713
|
+
Compute the coefficients of `q^n` of the power series of self,
|
|
1714
|
+
for `n` in the list `X`. The results are not cached. (Use
|
|
1715
|
+
coefficients for cached results).
|
|
1716
|
+
|
|
1717
|
+
EXAMPLES::
|
|
1718
|
+
|
|
1719
|
+
sage: f = Newforms(39,4,names='a')[1] ; f
|
|
1720
|
+
q + a1*q^2 - 3*q^3 + (2*a1 + 5)*q^4 + (-2*a1 + 14)*q^5 + O(q^6)
|
|
1721
|
+
sage: f._compute([2,3,7])
|
|
1722
|
+
[a1, -3, -2*a1 + 2]
|
|
1723
|
+
sage: f._compute([])
|
|
1724
|
+
[]
|
|
1725
|
+
|
|
1726
|
+
Check that :issue:`20793` is fixed::
|
|
1727
|
+
|
|
1728
|
+
sage: f = Newforms(83, 2, names='a')[1]; f
|
|
1729
|
+
q + a1*q^2 + (1/2*a1^4 - 1/2*a1^3 - 7/2*a1^2 + 3/2*a1 + 4)*q^3 + (a1^2 - 2)*q^4 + (-1/2*a1^5 - 1/2*a1^4 + 9/2*a1^3 + 7/2*a1^2 - 8*a1 - 2)*q^5 + O(q^6)
|
|
1730
|
+
sage: K = f.hecke_eigenvalue_field(); K
|
|
1731
|
+
Number Field in a1 with defining polynomial x^6 - x^5 - 9*x^4 + 7*x^3 + 20*x^2 - 12*x - 8
|
|
1732
|
+
sage: l = f.coefficients(20); l[-1]
|
|
1733
|
+
-a1^4 + 5*a1^2 - 4
|
|
1734
|
+
sage: l[-1].parent() is K
|
|
1735
|
+
True
|
|
1736
|
+
"""
|
|
1737
|
+
M = self.modular_symbols(1)
|
|
1738
|
+
return [M.eigenvalue(x, name=self._name()) for x in X]
|
|
1739
|
+
|
|
1740
|
+
def element(self):
|
|
1741
|
+
"""
|
|
1742
|
+
Find an element of the ambient space of modular forms which
|
|
1743
|
+
represents this newform.
|
|
1744
|
+
|
|
1745
|
+
.. NOTE::
|
|
1746
|
+
|
|
1747
|
+
This can be quite expensive. Also, the polynomial defining
|
|
1748
|
+
the field of Hecke eigenvalues should be considered random,
|
|
1749
|
+
since it is generated by a random sum of Hecke
|
|
1750
|
+
operators. (The field itself is not random, of course.)
|
|
1751
|
+
|
|
1752
|
+
EXAMPLES::
|
|
1753
|
+
|
|
1754
|
+
sage: ls = Newforms(38,4,names='a')
|
|
1755
|
+
sage: ls[0]
|
|
1756
|
+
q - 2*q^2 - 2*q^3 + 4*q^4 - 9*q^5 + O(q^6)
|
|
1757
|
+
sage: ls # random
|
|
1758
|
+
[q - 2*q^2 - 2*q^3 + 4*q^4 - 9*q^5 + O(q^6),
|
|
1759
|
+
q - 2*q^2 + (-a1 - 2)*q^3 + 4*q^4 + (2*a1 + 10)*q^5 + O(q^6),
|
|
1760
|
+
q + 2*q^2 + (1/2*a2 - 1)*q^3 + 4*q^4 + (-3/2*a2 + 12)*q^5 + O(q^6)]
|
|
1761
|
+
sage: type(ls[0])
|
|
1762
|
+
<class 'sage.modular.modform.element.Newform'>
|
|
1763
|
+
sage: ls[2][3].minpoly()
|
|
1764
|
+
x^2 - 9*x + 2
|
|
1765
|
+
sage: ls2 = [ x.element() for x in ls ]
|
|
1766
|
+
sage: ls2 # random
|
|
1767
|
+
[q - 2*q^2 - 2*q^3 + 4*q^4 - 9*q^5 + O(q^6),
|
|
1768
|
+
q - 2*q^2 + (-a1 - 2)*q^3 + 4*q^4 + (2*a1 + 10)*q^5 + O(q^6),
|
|
1769
|
+
q + 2*q^2 + (1/2*a2 - 1)*q^3 + 4*q^4 + (-3/2*a2 + 12)*q^5 + O(q^6)]
|
|
1770
|
+
sage: type(ls2[0])
|
|
1771
|
+
<class 'sage.modular.modform.cuspidal_submodule.CuspidalSubmodule_g0_Q_with_category.element_class'>
|
|
1772
|
+
sage: ls2[2][3].minpoly()
|
|
1773
|
+
x^2 - 9*x + 2
|
|
1774
|
+
"""
|
|
1775
|
+
S = self.parent()
|
|
1776
|
+
return S(self.q_expansion(S.sturm_bound()))
|
|
1777
|
+
|
|
1778
|
+
def is_cuspidal(self) -> bool:
|
|
1779
|
+
"""
|
|
1780
|
+
Return ``True``.
|
|
1781
|
+
|
|
1782
|
+
For compatibility with elements of modular forms spaces.
|
|
1783
|
+
|
|
1784
|
+
EXAMPLES::
|
|
1785
|
+
|
|
1786
|
+
sage: Newforms(11, 2)[0].is_cuspidal()
|
|
1787
|
+
True
|
|
1788
|
+
"""
|
|
1789
|
+
return True
|
|
1790
|
+
|
|
1791
|
+
def modular_symbols(self, sign=0):
|
|
1792
|
+
"""
|
|
1793
|
+
Return the subspace with the specified sign of the space of
|
|
1794
|
+
modular symbols corresponding to this newform.
|
|
1795
|
+
|
|
1796
|
+
EXAMPLES::
|
|
1797
|
+
|
|
1798
|
+
sage: f = Newforms(18,4)[0]
|
|
1799
|
+
sage: f.modular_symbols()
|
|
1800
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 18 for Gamma_0(18) of weight 4 with sign 0 over Rational Field
|
|
1801
|
+
sage: f.modular_symbols(1)
|
|
1802
|
+
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 11 for Gamma_0(18) of weight 4 with sign 1 over Rational Field
|
|
1803
|
+
"""
|
|
1804
|
+
return self.__modsym_space.modular_symbols_of_sign(sign)
|
|
1805
|
+
|
|
1806
|
+
@cached_method
|
|
1807
|
+
def modsym_eigenspace(self, sign=0):
|
|
1808
|
+
"""
|
|
1809
|
+
Return a submodule of dimension 1 or 2 of the ambient space of
|
|
1810
|
+
the sign 0 modular symbols space associated to ``self``,
|
|
1811
|
+
base-extended to the Hecke eigenvalue field, which is an
|
|
1812
|
+
eigenspace for the Hecke operators with the same eigenvalues
|
|
1813
|
+
as this newform, *and* is an eigenspace for the star
|
|
1814
|
+
involution of the appropriate sign if the sign is not 0.
|
|
1815
|
+
|
|
1816
|
+
EXAMPLES::
|
|
1817
|
+
|
|
1818
|
+
sage: N = Newform("37a")
|
|
1819
|
+
sage: N.modular_symbols(0)
|
|
1820
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field
|
|
1821
|
+
sage: M = N.modular_symbols(0)
|
|
1822
|
+
sage: V = N.modsym_eigenspace(1); V
|
|
1823
|
+
Vector space of degree 5 and dimension 1 over Rational Field
|
|
1824
|
+
Basis matrix:
|
|
1825
|
+
[ 0 1 -1 1 0]
|
|
1826
|
+
sage: V.0 in M.free_module()
|
|
1827
|
+
True
|
|
1828
|
+
sage: V = N.modsym_eigenspace(-1); V
|
|
1829
|
+
Vector space of degree 5 and dimension 1 over Rational Field
|
|
1830
|
+
Basis matrix:
|
|
1831
|
+
[ 0 0 0 1 -1/2]
|
|
1832
|
+
sage: V.0 in M.free_module()
|
|
1833
|
+
True
|
|
1834
|
+
"""
|
|
1835
|
+
M = self.modular_symbols(sign=0)
|
|
1836
|
+
if sign != 0:
|
|
1837
|
+
Ms = M.sign_submodule(sign)
|
|
1838
|
+
r = 1
|
|
1839
|
+
else:
|
|
1840
|
+
Ms = M
|
|
1841
|
+
r = 2
|
|
1842
|
+
# silly thing: can't do Ms.eigenvector(), even when Ms is simple,
|
|
1843
|
+
# because it can't be relied on to choose the coefficient fields
|
|
1844
|
+
# consistently
|
|
1845
|
+
A = M.ambient()
|
|
1846
|
+
X = Ms.free_module().base_extend(self.hecke_eigenvalue_field())
|
|
1847
|
+
p = ZZ(2)
|
|
1848
|
+
while X.rank() > r:
|
|
1849
|
+
assert p <= M.sturm_bound()
|
|
1850
|
+
X = (A.hecke_matrix(p).base_extend(self.hecke_eigenvalue_field()) - self[p]).kernel_on(X)
|
|
1851
|
+
p = p.next_prime()
|
|
1852
|
+
|
|
1853
|
+
# should really return a modular symbol submodule object, but these are
|
|
1854
|
+
# not implemented over non-minimal base rings
|
|
1855
|
+
return X
|
|
1856
|
+
|
|
1857
|
+
def _defining_modular_symbols(self):
|
|
1858
|
+
"""
|
|
1859
|
+
Return the modular symbols space corresponding to ``self``.
|
|
1860
|
+
|
|
1861
|
+
EXAMPLES::
|
|
1862
|
+
|
|
1863
|
+
sage: Newforms(43,2,names='a')
|
|
1864
|
+
[q - 2*q^2 - 2*q^3 + 2*q^4 - 4*q^5 + O(q^6),
|
|
1865
|
+
q + a1*q^2 - a1*q^3 + (-a1 + 2)*q^5 + O(q^6)]
|
|
1866
|
+
sage: [ x._defining_modular_symbols() for x in Newforms(43,2,names='a') ]
|
|
1867
|
+
[Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 4 for Gamma_0(43) of weight 2 with sign 1 over Rational Field,
|
|
1868
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 for Gamma_0(43) of weight 2 with sign 1 over Rational Field]
|
|
1869
|
+
sage: ModularSymbols(43,2,sign=1).cuspidal_subspace().new_subspace().decomposition()
|
|
1870
|
+
[Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 4 for Gamma_0(43) of weight 2 with sign 1 over Rational Field,
|
|
1871
|
+
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 for Gamma_0(43) of weight 2 with sign 1 over Rational Field]
|
|
1872
|
+
"""
|
|
1873
|
+
return self.__modsym_space
|
|
1874
|
+
|
|
1875
|
+
def number(self):
|
|
1876
|
+
"""
|
|
1877
|
+
Return the index of this space in the list of simple, new,
|
|
1878
|
+
cuspidal subspaces of the full space of modular symbols for
|
|
1879
|
+
this weight and level.
|
|
1880
|
+
|
|
1881
|
+
EXAMPLES::
|
|
1882
|
+
|
|
1883
|
+
sage: Newforms(43, 2, names='a')[1].number()
|
|
1884
|
+
1
|
|
1885
|
+
"""
|
|
1886
|
+
return self._defining_modular_symbols().ambient().cuspidal_subspace().new_subspace().decomposition().index(self._defining_modular_symbols())
|
|
1887
|
+
|
|
1888
|
+
def __bool__(self):
|
|
1889
|
+
"""
|
|
1890
|
+
Return ``True``, as newforms are never zero.
|
|
1891
|
+
|
|
1892
|
+
EXAMPLES::
|
|
1893
|
+
|
|
1894
|
+
sage: bool(Newforms(14,2)[0])
|
|
1895
|
+
True
|
|
1896
|
+
"""
|
|
1897
|
+
return True
|
|
1898
|
+
|
|
1899
|
+
def character(self):
|
|
1900
|
+
r"""
|
|
1901
|
+
The nebentypus character of this newform (as a Dirichlet character with
|
|
1902
|
+
values in the field of Hecke eigenvalues of the form).
|
|
1903
|
+
|
|
1904
|
+
EXAMPLES::
|
|
1905
|
+
|
|
1906
|
+
sage: Newforms(Gamma1(7), 4,names='a')[1].character()
|
|
1907
|
+
Dirichlet character modulo 7 of conductor 7 mapping 3 |--> 1/2*a1
|
|
1908
|
+
sage: chi = DirichletGroup(3).0; Newforms(chi, 7)[0].character() == chi
|
|
1909
|
+
True
|
|
1910
|
+
"""
|
|
1911
|
+
return self._defining_modular_symbols().q_eigenform_character(self._name())
|
|
1912
|
+
|
|
1913
|
+
###########################
|
|
1914
|
+
# Atkin--Lehner operators #
|
|
1915
|
+
###########################
|
|
1916
|
+
|
|
1917
|
+
def _atkin_lehner_eigenvalue_from_qexp(self, Q):
|
|
1918
|
+
"""
|
|
1919
|
+
Return the arithmetically-normalized `W_Q`-pseudoeigenvalue of
|
|
1920
|
+
``self``, using a formula based on `q`-expansions (Theorem 2.1 of
|
|
1921
|
+
[AL1978]_).
|
|
1922
|
+
|
|
1923
|
+
INPUT:
|
|
1924
|
+
|
|
1925
|
+
- ``self`` -- a newform `f`
|
|
1926
|
+
|
|
1927
|
+
- ``Q`` -- integer exactly dividing the level of ``self``
|
|
1928
|
+
|
|
1929
|
+
.. NOTE::
|
|
1930
|
+
|
|
1931
|
+
This method assumes that the `Q`-th coefficient in the
|
|
1932
|
+
`q`-expansion of ``self`` is nonzero.
|
|
1933
|
+
|
|
1934
|
+
TESTS::
|
|
1935
|
+
|
|
1936
|
+
sage: f = Newforms(Gamma0(18), 4)[0]; f
|
|
1937
|
+
q + 2*q^2 + 4*q^4 - 6*q^5 + O(q^6)
|
|
1938
|
+
sage: f._atkin_lehner_eigenvalue_from_qexp(2)
|
|
1939
|
+
-2
|
|
1940
|
+
sage: f._atkin_lehner_eigenvalue_from_qexp(9)
|
|
1941
|
+
Traceback (most recent call last):
|
|
1942
|
+
...
|
|
1943
|
+
ValueError: a_Q must be nonzero
|
|
1944
|
+
|
|
1945
|
+
An example with odd weight::
|
|
1946
|
+
|
|
1947
|
+
sage: f = Newforms(Gamma1(15), 3, names='a')[2]; f
|
|
1948
|
+
q + a2*q^2 + (-a2 - 2)*q^3 - q^4 - a2*q^5 + O(q^6)
|
|
1949
|
+
sage: f._atkin_lehner_eigenvalue_from_qexp(5)
|
|
1950
|
+
a2
|
|
1951
|
+
"""
|
|
1952
|
+
if Q == 1:
|
|
1953
|
+
return ZZ.one()
|
|
1954
|
+
a_Q = self[Q]
|
|
1955
|
+
if not a_Q:
|
|
1956
|
+
raise ValueError("a_Q must be nonzero")
|
|
1957
|
+
|
|
1958
|
+
l = ZZ.one()
|
|
1959
|
+
M = self.character().conductor()
|
|
1960
|
+
for p, e in Q.factor():
|
|
1961
|
+
if p.divides(M): # principal series at p
|
|
1962
|
+
l *= (p**(self.weight() - 2) / self[p])**e
|
|
1963
|
+
else: # special at p
|
|
1964
|
+
l *= -self[p]
|
|
1965
|
+
return l
|
|
1966
|
+
|
|
1967
|
+
def _atkin_lehner_eigenvalue_from_modsym(self, Q):
|
|
1968
|
+
"""
|
|
1969
|
+
Return the arithmetically-normalized `W_Q`-pseudoeigenvalue of
|
|
1970
|
+
``self``, using the action of `W_Q` on modular symbols.
|
|
1971
|
+
|
|
1972
|
+
INPUT:
|
|
1973
|
+
|
|
1974
|
+
- ``self`` -- a newform `f`
|
|
1975
|
+
|
|
1976
|
+
- ``Q`` -- positive integer exactly dividing the level of ``self``
|
|
1977
|
+
|
|
1978
|
+
.. NOTE::
|
|
1979
|
+
|
|
1980
|
+
This algorithm is only valid if, for every prime `p` dividing `Q`,
|
|
1981
|
+
the `p`-part of the level of `f` is strictly larger than the
|
|
1982
|
+
`p`-part of the conductor of its character.
|
|
1983
|
+
|
|
1984
|
+
EXAMPLES::
|
|
1985
|
+
|
|
1986
|
+
sage: F = Newforms(Gamma1(15), 3, names='a')[2]
|
|
1987
|
+
sage: F._atkin_lehner_eigenvalue_from_modsym(5)
|
|
1988
|
+
a2
|
|
1989
|
+
sage: _ == F._atkin_lehner_eigenvalue_from_qexp(5)
|
|
1990
|
+
True
|
|
1991
|
+
"""
|
|
1992
|
+
if Q == 1:
|
|
1993
|
+
return ZZ.one()
|
|
1994
|
+
|
|
1995
|
+
S = self._defining_modular_symbols()
|
|
1996
|
+
A = S.ambient()
|
|
1997
|
+
N = self.level()
|
|
1998
|
+
M = self.character().conductor()
|
|
1999
|
+
Q0 = M // M.prime_to_m_part(Q)
|
|
2000
|
+
|
|
2001
|
+
W = self.group().atkin_lehner_matrix(Q)
|
|
2002
|
+
if Q0 == 1:
|
|
2003
|
+
L = [W]
|
|
2004
|
+
else:
|
|
2005
|
+
L = []
|
|
2006
|
+
for a in xsrange(Q0):
|
|
2007
|
+
if a.gcd(Q0) > 1:
|
|
2008
|
+
continue
|
|
2009
|
+
aa = crt(a, 1, Q, N.prime_to_m_part(Q))
|
|
2010
|
+
diam = matrix(ZZ, 2, lift_to_sl2z(0, aa, N))
|
|
2011
|
+
L.append((W * diam * matrix(QQ, 2, [1, a / Q0, 0, 1])).change_ring(ZZ))
|
|
2012
|
+
|
|
2013
|
+
W = A._matrix_of_operator_on_modular_symbols(A, [x.list() for x in L])
|
|
2014
|
+
e = S.dual_eigenvector(names=self._name())
|
|
2015
|
+
i = e.nonzero_positions()[0]
|
|
2016
|
+
w = (W * e)[i] / e[i]
|
|
2017
|
+
if W * e != w * e:
|
|
2018
|
+
raise ArithmeticError("Bug in Atkin--Lehner computation: eigenspace not invariant")
|
|
2019
|
+
sign = prod([eps(-1) for eps in self.character().decomposition() if eps.conductor().divides(Q)])
|
|
2020
|
+
return w / Q0 / sign * self.character()(crt(1, Q // Q0, Q, N // Q))
|
|
2021
|
+
|
|
2022
|
+
def atkin_lehner_action(self, d=None, normalization='analytic', embedding=None):
|
|
2023
|
+
r"""
|
|
2024
|
+
Return the result of the Atkin-Lehner operator `W_d` on this form `f`,
|
|
2025
|
+
in the form of a constant `\lambda_d(f)` and a normalized newform `f'`
|
|
2026
|
+
such that
|
|
2027
|
+
|
|
2028
|
+
.. math::
|
|
2029
|
+
|
|
2030
|
+
f \mid W_d = \lambda_d(f) f'.
|
|
2031
|
+
|
|
2032
|
+
See :meth:`atkin_lehner_eigenvalue` for further details.
|
|
2033
|
+
|
|
2034
|
+
EXAMPLES::
|
|
2035
|
+
|
|
2036
|
+
sage: f = Newforms(DirichletGroup(30).1^2, 2, names='a')[0]
|
|
2037
|
+
sage: emb = f.base_ring().complex_embeddings()[0]
|
|
2038
|
+
sage: for d in divisors(30):
|
|
2039
|
+
....: print(f.atkin_lehner_action(d, embedding=emb))
|
|
2040
|
+
(1.00000000000000, q + a0*q^2 - a0*q^3 - q^4 + (a0 - 2)*q^5 + O(q^6))
|
|
2041
|
+
(-1.00000000000000*I, q + a0*q^2 - a0*q^3 - q^4 + (a0 - 2)*q^5 + O(q^6))
|
|
2042
|
+
(1.00000000000000*I, q + a0*q^2 - a0*q^3 - q^4 + (a0 - 2)*q^5 + O(q^6))
|
|
2043
|
+
(-0.894427190999916 + 0.447213595499958*I, q - a0*q^2 + a0*q^3 - q^4 + (-a0 - 2)*q^5 + O(q^6))
|
|
2044
|
+
(1.00000000000000, q + a0*q^2 - a0*q^3 - q^4 + (a0 - 2)*q^5 + O(q^6))
|
|
2045
|
+
(-0.447213595499958 - 0.894427190999916*I, q - a0*q^2 + a0*q^3 - q^4 + (-a0 - 2)*q^5 + O(q^6))
|
|
2046
|
+
(0.447213595499958 + 0.894427190999916*I, q - a0*q^2 + a0*q^3 - q^4 + (-a0 - 2)*q^5 + O(q^6))
|
|
2047
|
+
(-0.894427190999916 + 0.447213595499958*I, q - a0*q^2 + a0*q^3 - q^4 + (-a0 - 2)*q^5 + O(q^6))
|
|
2048
|
+
|
|
2049
|
+
The above computation can also be done exactly::
|
|
2050
|
+
|
|
2051
|
+
sage: K.<z> = CyclotomicField(20)
|
|
2052
|
+
sage: f = Newforms(DirichletGroup(30).1^2, 2, names='a')[0]
|
|
2053
|
+
sage: emb = f.base_ring().embeddings(CyclotomicField(20, 'z'))[0]
|
|
2054
|
+
sage: for d in divisors(30):
|
|
2055
|
+
....: print(f.atkin_lehner_action(d, embedding=emb))
|
|
2056
|
+
(1, q + a0*q^2 - a0*q^3 - q^4 + (a0 - 2)*q^5 + O(q^6))
|
|
2057
|
+
(z^5, q + a0*q^2 - a0*q^3 - q^4 + (a0 - 2)*q^5 + O(q^6))
|
|
2058
|
+
(-z^5, q + a0*q^2 - a0*q^3 - q^4 + (a0 - 2)*q^5 + O(q^6))
|
|
2059
|
+
(-2/5*z^7 + 4/5*z^6 + 1/5*z^5 - 4/5*z^4 - 2/5*z^3 - 2/5, q - a0*q^2 + a0*q^3 - q^4 + (-a0 - 2)*q^5 + O(q^6))
|
|
2060
|
+
(1, q + a0*q^2 - a0*q^3 - q^4 + (a0 - 2)*q^5 + O(q^6))
|
|
2061
|
+
(4/5*z^7 + 2/5*z^6 - 2/5*z^5 - 2/5*z^4 + 4/5*z^3 - 1/5, q - a0*q^2 + a0*q^3 - q^4 + (-a0 - 2)*q^5 + O(q^6))
|
|
2062
|
+
(-4/5*z^7 - 2/5*z^6 + 2/5*z^5 + 2/5*z^4 - 4/5*z^3 + 1/5, q - a0*q^2 + a0*q^3 - q^4 + (-a0 - 2)*q^5 + O(q^6))
|
|
2063
|
+
(-2/5*z^7 + 4/5*z^6 + 1/5*z^5 - 4/5*z^4 - 2/5*z^3 - 2/5, q - a0*q^2 + a0*q^3 - q^4 + (-a0 - 2)*q^5 + O(q^6))
|
|
2064
|
+
|
|
2065
|
+
We can compute the eigenvalue of `W_{p^e}` in certain cases
|
|
2066
|
+
where the `p`-th coefficient of `f` is zero::
|
|
2067
|
+
|
|
2068
|
+
sage: f = Newforms(169, names='a')[0]; f
|
|
2069
|
+
q + a0*q^2 + 2*q^3 + q^4 - a0*q^5 + O(q^6)
|
|
2070
|
+
sage: f[13]
|
|
2071
|
+
0
|
|
2072
|
+
sage: f.atkin_lehner_eigenvalue(169)
|
|
2073
|
+
-1
|
|
2074
|
+
|
|
2075
|
+
An example showing the non-multiplicativity of the pseudo-eigenvalues::
|
|
2076
|
+
|
|
2077
|
+
sage: chi = DirichletGroup(18).0^4
|
|
2078
|
+
sage: f = Newforms(chi, 2)[0]
|
|
2079
|
+
sage: w2, _ = f.atkin_lehner_action(2); w2
|
|
2080
|
+
zeta6
|
|
2081
|
+
sage: w9, _ = f.atkin_lehner_action(9); w9
|
|
2082
|
+
-zeta18^4
|
|
2083
|
+
sage: w18,_ = f.atkin_lehner_action(18); w18
|
|
2084
|
+
-zeta18
|
|
2085
|
+
sage: w18 == w2 * w9 * chi( crt(2, 9, 9, 2) )
|
|
2086
|
+
True
|
|
2087
|
+
|
|
2088
|
+
TESTS::
|
|
2089
|
+
|
|
2090
|
+
sage: K.<a> = QuadraticField(1129)
|
|
2091
|
+
sage: f = Newforms(Gamma0(20), 8, base_ring=K)[2]; f
|
|
2092
|
+
q + (2*a - 10)*q^3 + 125*q^5 + O(q^6)
|
|
2093
|
+
sage: f.atkin_lehner_action(2)
|
|
2094
|
+
(-1, q + (2*a - 10)*q^3 + 125*q^5 + O(q^6))
|
|
2095
|
+
|
|
2096
|
+
sage: f = Newforms(Gamma1(11), 2)[0]
|
|
2097
|
+
sage: f.atkin_lehner_action(2)
|
|
2098
|
+
Traceback (most recent call last):
|
|
2099
|
+
...
|
|
2100
|
+
ValueError: d (= 2) does not divide the level (= 11)
|
|
2101
|
+
"""
|
|
2102
|
+
# normalise d
|
|
2103
|
+
N = self.level()
|
|
2104
|
+
if d is None:
|
|
2105
|
+
d = N
|
|
2106
|
+
else:
|
|
2107
|
+
d = ZZ(d)
|
|
2108
|
+
if not d.divides(N):
|
|
2109
|
+
raise ValueError('d (= {}) does not divide the level (= {})'.format(d, N))
|
|
2110
|
+
d = N // N.prime_to_m_part(d)
|
|
2111
|
+
|
|
2112
|
+
if d == 1:
|
|
2113
|
+
w = self.base_ring().one()
|
|
2114
|
+
if embedding is not None:
|
|
2115
|
+
w = embedding(w)
|
|
2116
|
+
return w, self
|
|
2117
|
+
|
|
2118
|
+
eps_d = prod([eps.extend(d) for eps in self.character().decomposition() if eps.modulus().divides(d)])
|
|
2119
|
+
if eps_d.is_trivial():
|
|
2120
|
+
g = self
|
|
2121
|
+
else:
|
|
2122
|
+
g = self.twist(~eps_d, level=N)
|
|
2123
|
+
l = self.atkin_lehner_eigenvalue(d, normalization, embedding)
|
|
2124
|
+
return l, g
|
|
2125
|
+
|
|
2126
|
+
def atkin_lehner_eigenvalue(self, d=None, normalization='analytic', embedding=None):
|
|
2127
|
+
r"""
|
|
2128
|
+
Return the pseudo-eigenvalue of the Atkin-Lehner operator `W_d`
|
|
2129
|
+
acting on this form `f`.
|
|
2130
|
+
|
|
2131
|
+
INPUT:
|
|
2132
|
+
|
|
2133
|
+
- ``d`` -- positive integer exactly dividing the level `N` of `f`,
|
|
2134
|
+
i.e., `d` divides `N` and is coprime to `N/d`; the default is `d = N`
|
|
2135
|
+
|
|
2136
|
+
If `d` does not divide `N` exactly, then it will be replaced with a
|
|
2137
|
+
multiple `D` of `d` such that `D` exactly divides `N` and `D` has the
|
|
2138
|
+
same prime factors as `d`. An error will be raised if `d` does not
|
|
2139
|
+
divide `N`.
|
|
2140
|
+
|
|
2141
|
+
- ``normalization`` -- either ``'analytic'`` (the default) or
|
|
2142
|
+
``'arithmetic'``; see below
|
|
2143
|
+
|
|
2144
|
+
- ``embedding`` -- (optional) embedding of the coefficient field of `f`
|
|
2145
|
+
into another ring; ignored if ``'normalization='arithmetic'``
|
|
2146
|
+
|
|
2147
|
+
OUTPUT:
|
|
2148
|
+
|
|
2149
|
+
The Atkin-Lehner pseudo-eigenvalue of `W_d` on `f`, as an element of
|
|
2150
|
+
the coefficient field of `f`, or the codomain of ``embedding`` if
|
|
2151
|
+
specified.
|
|
2152
|
+
|
|
2153
|
+
As defined in [AL1978]_, the pseudo-eigenvalue is the constant
|
|
2154
|
+
`\lambda_d(f)` such that
|
|
2155
|
+
|
|
2156
|
+
..math::
|
|
2157
|
+
|
|
2158
|
+
f \mid W_d = \lambda_d(f) f'
|
|
2159
|
+
|
|
2160
|
+
where `f'` is some normalised newform (not necessarily equal to `f`).
|
|
2161
|
+
|
|
2162
|
+
If ``normalisation='analytic'`` (the default), this routine will
|
|
2163
|
+
compute `\lambda_d`, using the conventions of [AL1978]_ for the weight
|
|
2164
|
+
`k` action, which imply that `\lambda_d` has complex absolute value 1.
|
|
2165
|
+
However, with these conventions `\lambda_d` is not in the Hecke
|
|
2166
|
+
eigenvalue field of `f` in general, so it is often necessary to specify
|
|
2167
|
+
an embedding of the eigenvalue field into a larger ring (which needs to
|
|
2168
|
+
contain roots of unity of sufficiently large order, and a square root
|
|
2169
|
+
of `d` if `k` is odd).
|
|
2170
|
+
|
|
2171
|
+
If ``normalisation='arithmetic'`` we compute instead the quotient
|
|
2172
|
+
|
|
2173
|
+
..math::
|
|
2174
|
+
|
|
2175
|
+
d^{k/2-1} \lambda_d(f) \varepsilon_{N/d}(d / d_0) / G(\varepsilon_d),
|
|
2176
|
+
|
|
2177
|
+
where `G(\varepsilon_d)` is the Gauss sum of the `d`-primary part of
|
|
2178
|
+
the nebentype of `f` (more precisely, of its associated primitive
|
|
2179
|
+
character), and `d_0` its conductor. This ratio is always in the Hecke
|
|
2180
|
+
eigenvalue field of `f` (and can be computed using only arithmetic in
|
|
2181
|
+
this field), so specifying an embedding is not needed, although we
|
|
2182
|
+
still allow it for consistency.
|
|
2183
|
+
|
|
2184
|
+
(Note that if `k = 2` and `\varepsilon` is trivial, both
|
|
2185
|
+
normalisations coincide.)
|
|
2186
|
+
|
|
2187
|
+
.. SEEALSO::
|
|
2188
|
+
|
|
2189
|
+
- :meth:`sage.modular.hecke.module.atkin_lehner_operator`
|
|
2190
|
+
(especially for the conventions used to define the operator
|
|
2191
|
+
`W_d`)
|
|
2192
|
+
|
|
2193
|
+
- :meth:`atkin_lehner_action`, which returns both the
|
|
2194
|
+
pseudo-eigenvalue and the newform `f'`.
|
|
2195
|
+
|
|
2196
|
+
EXAMPLES::
|
|
2197
|
+
|
|
2198
|
+
sage: [x.atkin_lehner_eigenvalue() for x in ModularForms(53).newforms('a')]
|
|
2199
|
+
[1, -1]
|
|
2200
|
+
|
|
2201
|
+
sage: f = Newforms(Gamma1(15), 3, names='a')[2]; f
|
|
2202
|
+
q + a2*q^2 + (-a2 - 2)*q^3 - q^4 - a2*q^5 + O(q^6)
|
|
2203
|
+
sage: f.atkin_lehner_eigenvalue(5)
|
|
2204
|
+
Traceback (most recent call last):
|
|
2205
|
+
...
|
|
2206
|
+
ValueError: Unable to compute square root. Try specifying an embedding into a larger ring
|
|
2207
|
+
sage: L = f.hecke_eigenvalue_field(); x = polygen(QQ); M.<sqrt5> = L.extension(x^2 - 5)
|
|
2208
|
+
sage: f.atkin_lehner_eigenvalue(5, embedding=M.coerce_map_from(L))
|
|
2209
|
+
1/5*a2*sqrt5
|
|
2210
|
+
sage: f.atkin_lehner_eigenvalue(5, normalization='arithmetic')
|
|
2211
|
+
a2
|
|
2212
|
+
|
|
2213
|
+
sage: Newforms(DirichletGroup(5).0^2, 6, names='a')[0].atkin_lehner_eigenvalue()
|
|
2214
|
+
Traceback (most recent call last):
|
|
2215
|
+
...
|
|
2216
|
+
ValueError: Unable to compute Gauss sum. Try specifying an embedding into a larger ring
|
|
2217
|
+
|
|
2218
|
+
TESTS:
|
|
2219
|
+
|
|
2220
|
+
Check that the bug reported at :issue:`18061` is fixed::
|
|
2221
|
+
|
|
2222
|
+
sage: K.<i> = CyclotomicField(4)
|
|
2223
|
+
sage: f = Newforms(DirichletGroup(30, QQ).1, 2, K)[0]
|
|
2224
|
+
sage: f.atkin_lehner_eigenvalue(embedding=K.embeddings(QQbar)[1])
|
|
2225
|
+
-0.8944271909999159? - 0.4472135954999580?*I
|
|
2226
|
+
|
|
2227
|
+
Check that :issue:`24086` is fixed::
|
|
2228
|
+
|
|
2229
|
+
sage: f = Newforms(24, 4)[0]
|
|
2230
|
+
sage: f.atkin_lehner_eigenvalue(8)
|
|
2231
|
+
-1
|
|
2232
|
+
sage: f.atkin_lehner_eigenvalue(3)
|
|
2233
|
+
-1
|
|
2234
|
+
|
|
2235
|
+
A case where the eigenvalue isn't in the coefficient field of `f`::
|
|
2236
|
+
|
|
2237
|
+
sage: chi = DirichletGroup(7, QQ).0
|
|
2238
|
+
sage: f = Newforms(chi, 3)[0]
|
|
2239
|
+
sage: f.atkin_lehner_eigenvalue()
|
|
2240
|
+
Traceback (most recent call last):
|
|
2241
|
+
...
|
|
2242
|
+
ValueError: Unable to compute square root. Try specifying an embedding into a larger ring
|
|
2243
|
+
sage: emb = f.hecke_eigenvalue_field().embeddings(QQbar)[0]
|
|
2244
|
+
sage: f.atkin_lehner_eigenvalue(embedding=emb)
|
|
2245
|
+
0.?e-18 - 1.000000000000000?*I
|
|
2246
|
+
|
|
2247
|
+
A case where the embeddings really matter::
|
|
2248
|
+
|
|
2249
|
+
sage: chi2 = chi.extend(63)
|
|
2250
|
+
sage: g = Newforms(chi2, 3, names='a')[2]
|
|
2251
|
+
sage: g.atkin_lehner_eigenvalue(7)
|
|
2252
|
+
Traceback (most recent call last):
|
|
2253
|
+
...
|
|
2254
|
+
ValueError: Unable to compute Gauss sum. Try specifying an embedding into a larger ring
|
|
2255
|
+
sage: g.atkin_lehner_eigenvalue(7, embedding=g.hecke_eigenvalue_field().embeddings(QQbar)[0])
|
|
2256
|
+
0.?e-18 + 1.000000000000000?*I
|
|
2257
|
+
"""
|
|
2258
|
+
if normalization not in ['arithmetic', 'analytic']:
|
|
2259
|
+
raise ValueError("unknown normalization %s" % normalization)
|
|
2260
|
+
N = self.level()
|
|
2261
|
+
if d is None:
|
|
2262
|
+
d = N
|
|
2263
|
+
d = ZZ(d)
|
|
2264
|
+
if N % d:
|
|
2265
|
+
raise ValueError("d should divide N")
|
|
2266
|
+
d = N // N.prime_to_m_part(d)
|
|
2267
|
+
|
|
2268
|
+
d1 = d2 = d3 = 1
|
|
2269
|
+
for (p, e) in d.factor():
|
|
2270
|
+
if self[p] == 0:
|
|
2271
|
+
d1 *= p**e
|
|
2272
|
+
elif self.character().conductor().valuation(p) == e:
|
|
2273
|
+
d2 *= p**e
|
|
2274
|
+
else:
|
|
2275
|
+
d3 *= p**e
|
|
2276
|
+
|
|
2277
|
+
verbose("computing W_%s using modsym, W_%s using qexp, W_%s using both" % (d1, d2, d3), level=2)
|
|
2278
|
+
w1 = self._atkin_lehner_eigenvalue_from_modsym(d1)
|
|
2279
|
+
w2 = self._atkin_lehner_eigenvalue_from_qexp(d2)
|
|
2280
|
+
w3a = self._atkin_lehner_eigenvalue_from_modsym(d3)
|
|
2281
|
+
w3b = self._atkin_lehner_eigenvalue_from_qexp(d3)
|
|
2282
|
+
assert w3a == w3b
|
|
2283
|
+
w = w1 * w2 * w3a
|
|
2284
|
+
|
|
2285
|
+
if embedding is None:
|
|
2286
|
+
R = self.hecke_eigenvalue_field()
|
|
2287
|
+
embedding = R.Hom(R).identity()
|
|
2288
|
+
else:
|
|
2289
|
+
R = embedding.codomain()
|
|
2290
|
+
|
|
2291
|
+
if normalization == 'arithmetic':
|
|
2292
|
+
return embedding(w)
|
|
2293
|
+
else:
|
|
2294
|
+
# get rid of the normalisation factors
|
|
2295
|
+
from sage.modular.dirichlet import trivial_character
|
|
2296
|
+
|
|
2297
|
+
epsd = prod([eps.extend(d) for eps in self.character().decomposition() if eps.modulus().divides(d)], trivial_character(d))
|
|
2298
|
+
epsd = epsd.primitive_character()
|
|
2299
|
+
d0 = epsd.modulus()
|
|
2300
|
+
epsdR = epsd.change_ring(embedding)
|
|
2301
|
+
if d0 > 1:
|
|
2302
|
+
try:
|
|
2303
|
+
G = epsdR.gauss_sum()
|
|
2304
|
+
except NotImplementedError:
|
|
2305
|
+
raise ValueError("Unable to compute Gauss sum. Try specifying an embedding into a larger ring")
|
|
2306
|
+
else:
|
|
2307
|
+
G = R(1)
|
|
2308
|
+
if not R(d**(self.weight() - 2)).is_square():
|
|
2309
|
+
raise ValueError("Unable to compute square root. Try specifying an embedding into a larger ring")
|
|
2310
|
+
ratio = R(d**(self.weight() - 2)).sqrt() * embedding(self.character()(crt(1, d // d0, d, N // d))) / G
|
|
2311
|
+
return embedding(w) / ratio
|
|
2312
|
+
|
|
2313
|
+
def twist(self, chi, level=None, check=True):
|
|
2314
|
+
r"""
|
|
2315
|
+
Return the twist of the newform ``self`` by the Dirichlet
|
|
2316
|
+
character ``chi``.
|
|
2317
|
+
|
|
2318
|
+
If ``self`` is a newform `f` with character `\epsilon` and
|
|
2319
|
+
`q`-expansion
|
|
2320
|
+
|
|
2321
|
+
.. MATH::
|
|
2322
|
+
|
|
2323
|
+
f(q) = \sum_{n=1}^\infty a_n q^n,
|
|
2324
|
+
|
|
2325
|
+
then the twist by `\chi` is the unique newform `f\otimes\chi`
|
|
2326
|
+
with character `\epsilon\chi^2` and `q`-expansion
|
|
2327
|
+
|
|
2328
|
+
.. MATH::
|
|
2329
|
+
|
|
2330
|
+
(f\otimes\chi)(q) = \sum_{n=1}^\infty b_n q^n
|
|
2331
|
+
|
|
2332
|
+
satisfying `b_n = \chi(n) a_n` for all but finitely many `n`.
|
|
2333
|
+
|
|
2334
|
+
INPUT:
|
|
2335
|
+
|
|
2336
|
+
- ``chi`` -- a Dirichlet character. Note that Sage must be able to
|
|
2337
|
+
determine a common base field into which both the Hecke eigenvalue
|
|
2338
|
+
field of self, and the field of values of ``chi``, can be embedded.
|
|
2339
|
+
|
|
2340
|
+
- ``level`` -- (optional) the level `N` of the twisted form. If `N` is
|
|
2341
|
+
not given, the algorithm tries to compute `N` using [AL1978]_,
|
|
2342
|
+
Theorem 3.1; if this is not possible, it returns an error. If `N` is
|
|
2343
|
+
given but incorrect, i.e. the twisted form does not have level `N`,
|
|
2344
|
+
then this function will attempt to detect this and return an error,
|
|
2345
|
+
but it may sometimes return an incorrect answer (a newform of level
|
|
2346
|
+
`N` whose first few coefficients agree with those of `f \otimes
|
|
2347
|
+
\chi`).
|
|
2348
|
+
|
|
2349
|
+
- ``check`` -- (optional) boolean; if ``True`` (default), ensure that
|
|
2350
|
+
the space of modular symbols that is computed is genuinely simple and
|
|
2351
|
+
new. This makes it less likely, but not impossible, that a wrong
|
|
2352
|
+
result is returned if an incorrect ``level`` is specified.
|
|
2353
|
+
|
|
2354
|
+
OUTPUT:
|
|
2355
|
+
|
|
2356
|
+
The form `f\otimes\chi` as an element of the set of newforms
|
|
2357
|
+
for `\Gamma_1(N)` with character `\epsilon\chi^2`.
|
|
2358
|
+
|
|
2359
|
+
EXAMPLES::
|
|
2360
|
+
|
|
2361
|
+
sage: G = DirichletGroup(3, base_ring=QQ)
|
|
2362
|
+
sage: Delta = Newforms(SL2Z, 12)[0]; Delta
|
|
2363
|
+
q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6)
|
|
2364
|
+
sage: Delta.twist(G[0]) == Delta
|
|
2365
|
+
True
|
|
2366
|
+
sage: Delta.twist(G[1]) # long time (about 5 s)
|
|
2367
|
+
q + 24*q^2 - 1472*q^4 - 4830*q^5 + O(q^6)
|
|
2368
|
+
|
|
2369
|
+
sage: M = CuspForms(Gamma1(13), 2)
|
|
2370
|
+
sage: f = M.newforms('a')[0]; f
|
|
2371
|
+
q + a0*q^2 + (-2*a0 - 4)*q^3 + (-a0 - 1)*q^4 + (2*a0 + 3)*q^5 + O(q^6)
|
|
2372
|
+
sage: f.twist(G[1])
|
|
2373
|
+
q - a0*q^2 + (-a0 - 1)*q^4 + (-2*a0 - 3)*q^5 + O(q^6)
|
|
2374
|
+
|
|
2375
|
+
sage: f = Newforms(Gamma1(30), 2, names='a')[1]; f
|
|
2376
|
+
q + a1*q^2 - a1*q^3 - q^4 + (a1 - 2)*q^5 + O(q^6)
|
|
2377
|
+
sage: f.twist(f.character())
|
|
2378
|
+
Traceback (most recent call last):
|
|
2379
|
+
...
|
|
2380
|
+
NotImplementedError: cannot calculate 5-primary part of the level of the twist of q + a1*q^2 - a1*q^3 - q^4 + (a1 - 2)*q^5 + O(q^6) by Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1
|
|
2381
|
+
sage: f.twist(f.character(), level=30)
|
|
2382
|
+
q - a1*q^2 + a1*q^3 - q^4 + (-a1 - 2)*q^5 + O(q^6)
|
|
2383
|
+
|
|
2384
|
+
TESTS:
|
|
2385
|
+
|
|
2386
|
+
We test that feeding inappropriate values of the ``level`` parameter is handled gracefully::
|
|
2387
|
+
|
|
2388
|
+
sage: chi = DirichletGroup(1)[0]
|
|
2389
|
+
sage: Delta.twist(chi, level=3)
|
|
2390
|
+
Traceback (most recent call last):
|
|
2391
|
+
...
|
|
2392
|
+
ValueError: twist of q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6) by Dirichlet character modulo 1 of conductor 1 is not a newform of level 3
|
|
2393
|
+
|
|
2394
|
+
Twisting and twisting back works::
|
|
2395
|
+
|
|
2396
|
+
sage: f = Newforms(11)[0]
|
|
2397
|
+
sage: chi = DirichletGroup(5).0
|
|
2398
|
+
sage: f.twist(chi).twist(~chi, level=11) == f
|
|
2399
|
+
True
|
|
2400
|
+
|
|
2401
|
+
AUTHORS:
|
|
2402
|
+
|
|
2403
|
+
- Peter Bruin (April 2015)
|
|
2404
|
+
"""
|
|
2405
|
+
from sage.modular.all import CuspForms
|
|
2406
|
+
R = coercion_model.common_parent(self.base_ring(), chi.base_ring())
|
|
2407
|
+
N = self.level()
|
|
2408
|
+
epsilon = self.character()
|
|
2409
|
+
chi = chi.primitive_character()
|
|
2410
|
+
if level is None:
|
|
2411
|
+
N_epsilon = epsilon.conductor()
|
|
2412
|
+
N_chi = chi.conductor()
|
|
2413
|
+
G = DirichletGroup(N_epsilon.lcm(N_chi), base_ring=R)
|
|
2414
|
+
epsilon_chi = G(epsilon) * G(chi)
|
|
2415
|
+
N_epsilon_chi = epsilon_chi.conductor()
|
|
2416
|
+
for q in N_chi.prime_divisors():
|
|
2417
|
+
# See [AL1978], Theorem 3.1.
|
|
2418
|
+
alpha = N_epsilon.valuation(q)
|
|
2419
|
+
beta = N_chi.valuation(q)
|
|
2420
|
+
gamma = N.valuation(q)
|
|
2421
|
+
delta = max(alpha + beta, 2 * beta, gamma)
|
|
2422
|
+
if delta == gamma and max(alpha + beta, 2 * beta) < gamma:
|
|
2423
|
+
continue
|
|
2424
|
+
if delta > gamma and N_epsilon_chi.valuation(q) == max(alpha, beta):
|
|
2425
|
+
continue
|
|
2426
|
+
raise NotImplementedError('cannot calculate %s-primary part of the level of the twist of %s by %s'
|
|
2427
|
+
% (q, self, chi))
|
|
2428
|
+
level = lcm([N, N_epsilon * N_chi, N_chi**2])
|
|
2429
|
+
|
|
2430
|
+
# determine the character of the twisted form
|
|
2431
|
+
G = DirichletGroup(lcm([N, chi.modulus(), level]), base_ring=R)
|
|
2432
|
+
eps_new = (G(epsilon) * G(chi)**2).restrict(level)
|
|
2433
|
+
|
|
2434
|
+
# create an ambient space
|
|
2435
|
+
D = ModularSymbols(eps_new, self.weight(), base_ring=R, sign=1).new_submodule()
|
|
2436
|
+
S = CuspForms(eps_new, self.weight(), base_ring=R)
|
|
2437
|
+
|
|
2438
|
+
# pull out the eigenspace
|
|
2439
|
+
for p in prime_range(500):
|
|
2440
|
+
if p.divides(chi.level()):
|
|
2441
|
+
continue
|
|
2442
|
+
D = (D.hecke_operator(p) - self[p] * chi(p)).kernel()
|
|
2443
|
+
if D.rank() == 1:
|
|
2444
|
+
break
|
|
2445
|
+
if D.is_zero():
|
|
2446
|
+
raise ValueError('twist of %s by %s is not a newform of level %s' % (self, chi, level))
|
|
2447
|
+
else:
|
|
2448
|
+
raise RuntimeError('unable to identify modular symbols for twist of %s by %s' % (self, chi))
|
|
2449
|
+
return Newform(S, D, names='_', check=check)
|
|
2450
|
+
|
|
2451
|
+
def minimal_twist(self, p=None):
|
|
2452
|
+
r"""
|
|
2453
|
+
Compute a pair `(g, chi)` such that `g = f \otimes \chi`, where `f` is
|
|
2454
|
+
this newform and `\chi` is a Dirichlet character, such that `g` has
|
|
2455
|
+
level as small as possible. If the optional argument `p` is given,
|
|
2456
|
+
consider only twists by Dirichlet characters of `p`-power conductor.
|
|
2457
|
+
|
|
2458
|
+
EXAMPLES::
|
|
2459
|
+
|
|
2460
|
+
sage: f = Newforms(121, 2)[3]
|
|
2461
|
+
sage: g, chi = f.minimal_twist()
|
|
2462
|
+
sage: g
|
|
2463
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6)
|
|
2464
|
+
sage: chi
|
|
2465
|
+
Dirichlet character modulo 11 of conductor 11 mapping 2 |--> -1
|
|
2466
|
+
sage: f.twist(chi, level=11) == g
|
|
2467
|
+
True
|
|
2468
|
+
|
|
2469
|
+
sage: # long time
|
|
2470
|
+
sage: f = Newforms(575, 2, names='a')[4]
|
|
2471
|
+
sage: g, chi = f.minimal_twist(5)
|
|
2472
|
+
sage: g
|
|
2473
|
+
q + a*q^2 - a*q^3 - 2*q^4 + (1/2*a + 2)*q^5 + O(q^6)
|
|
2474
|
+
sage: chi
|
|
2475
|
+
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 1/2*a
|
|
2476
|
+
sage: f.twist(chi, level=g.level()) == g
|
|
2477
|
+
True
|
|
2478
|
+
"""
|
|
2479
|
+
if p is None:
|
|
2480
|
+
# test local minimality at all primes
|
|
2481
|
+
for p in self.level().prime_divisors():
|
|
2482
|
+
g, chi = self.minimal_twist(p)
|
|
2483
|
+
if g.level() < self.level():
|
|
2484
|
+
h, tau = g.minimal_twist(p=None)
|
|
2485
|
+
M = chi.modulus().lcm(tau.modulus())
|
|
2486
|
+
return (h, chi.extend(M) * tau.extend(M))
|
|
2487
|
+
# f locally minimal at all p, hence globally minimal
|
|
2488
|
+
return (self, DirichletGroup(1, self.base_ring())(1))
|
|
2489
|
+
|
|
2490
|
+
p = ZZ(p)
|
|
2491
|
+
N = self.level()
|
|
2492
|
+
r = N.valuation(p)
|
|
2493
|
+
c = self.character().conductor().valuation(p)
|
|
2494
|
+
if not (p.is_prime() and p.divides(N)):
|
|
2495
|
+
raise ValueError("p should be prime factor of N")
|
|
2496
|
+
|
|
2497
|
+
if (r == c) or (r == 1 and c == 0):
|
|
2498
|
+
# easy cases
|
|
2499
|
+
return (self, DirichletGroup(1, self.base_ring())(1))
|
|
2500
|
+
elif r < 2 * c:
|
|
2501
|
+
# In this case we know that there is a unique chi of conductor p^u
|
|
2502
|
+
# such that self x chi has level N/p^u, where u = r-c, and this
|
|
2503
|
+
# twist is minimal.
|
|
2504
|
+
candidates = []
|
|
2505
|
+
for chi in DirichletGroup(p**(r - c), self.base_ring()):
|
|
2506
|
+
if not chi.is_primitive():
|
|
2507
|
+
continue
|
|
2508
|
+
try:
|
|
2509
|
+
g = self.twist(chi, level=N // p**(r - c))
|
|
2510
|
+
candidates.append((g, chi))
|
|
2511
|
+
except ValueError:
|
|
2512
|
+
continue
|
|
2513
|
+
|
|
2514
|
+
l = ZZ.one()
|
|
2515
|
+
while len(candidates) > 1:
|
|
2516
|
+
l = l.next_prime()
|
|
2517
|
+
if l == p:
|
|
2518
|
+
continue
|
|
2519
|
+
candidates = [(h, chi) for (h, chi) in candidates if h[l] == chi(l) * self[l]]
|
|
2520
|
+
if l > 10000 or not candidates:
|
|
2521
|
+
raise RuntimeError("bug finding minimal twist")
|
|
2522
|
+
return candidates[0]
|
|
2523
|
+
else:
|
|
2524
|
+
# The hard case. Now f might be ramified principal series, twist of
|
|
2525
|
+
# Steinberg, or supercuspidal, and the minimal twist is not unique
|
|
2526
|
+
# any more. So we use the slow, but very general, type-space
|
|
2527
|
+
# algorithm.
|
|
2528
|
+
from sage.modular.local_comp.type_space import TypeSpace
|
|
2529
|
+
T = TypeSpace(self, p)
|
|
2530
|
+
if T.is_minimal():
|
|
2531
|
+
return (self, DirichletGroup(1, self.base_ring())(1))
|
|
2532
|
+
|
|
2533
|
+
g = T.minimal_twist()
|
|
2534
|
+
epsg = g.character().extend(N)
|
|
2535
|
+
chisq = (epsg / self.character()).restrict(p**(r // 2))
|
|
2536
|
+
K = coercion_model.common_parent(self.base_ring(), g.base_ring())
|
|
2537
|
+
chis = [chi for chi in DirichletGroup(p**(r // 2), K) if chi**2 == chisq]
|
|
2538
|
+
|
|
2539
|
+
if g.has_cm() and g.cm_discriminant().prime_divisors() == [p]:
|
|
2540
|
+
# Quicker to test g than self, because g has smaller level.
|
|
2541
|
+
t = 2
|
|
2542
|
+
else:
|
|
2543
|
+
t = 1
|
|
2544
|
+
l = ZZ.one()
|
|
2545
|
+
while len(chis) > t:
|
|
2546
|
+
l = l.next_prime()
|
|
2547
|
+
if l == p:
|
|
2548
|
+
continue
|
|
2549
|
+
chis = [chi for chi in chis if g[l] == chi(l) * self[l]]
|
|
2550
|
+
if l > 10000 or not chis:
|
|
2551
|
+
raise RuntimeError("bug finding minimal twist")
|
|
2552
|
+
return (g, chis[0])
|
|
2553
|
+
|
|
2554
|
+
def local_component(self, p, twist_factor=None):
|
|
2555
|
+
"""
|
|
2556
|
+
Calculate the local component at the prime `p` of the automorphic
|
|
2557
|
+
representation attached to this newform. For more information, see the
|
|
2558
|
+
documentation of the :func:`LocalComponent` function.
|
|
2559
|
+
|
|
2560
|
+
EXAMPLES::
|
|
2561
|
+
|
|
2562
|
+
sage: f = Newform("49a")
|
|
2563
|
+
sage: f.local_component(7)
|
|
2564
|
+
Smooth representation of GL_2(Q_7) with conductor 7^2
|
|
2565
|
+
"""
|
|
2566
|
+
from sage.modular.local_comp.local_comp import LocalComponent
|
|
2567
|
+
return LocalComponent(self, p, twist_factor)
|
|
2568
|
+
|
|
2569
|
+
|
|
2570
|
+
class ModularFormElement(ModularForm_abstract, element.HeckeModuleElement):
|
|
2571
|
+
def __init__(self, parent, x, check=True):
|
|
2572
|
+
r"""
|
|
2573
|
+
An element of a space of modular forms.
|
|
2574
|
+
|
|
2575
|
+
INPUT:
|
|
2576
|
+
|
|
2577
|
+
- ``parent`` -- :class:`ModularFormsSpace` (an ambient space of modular
|
|
2578
|
+
forms)
|
|
2579
|
+
|
|
2580
|
+
- ``x`` -- a vector on the basis for parent
|
|
2581
|
+
|
|
2582
|
+
- ``check`` -- if check is ``True``, check the types of the
|
|
2583
|
+
inputs
|
|
2584
|
+
|
|
2585
|
+
OUTPUT: ``ModularFormElement`` -- a modular form
|
|
2586
|
+
|
|
2587
|
+
EXAMPLES::
|
|
2588
|
+
|
|
2589
|
+
sage: M = ModularForms(Gamma0(11),2)
|
|
2590
|
+
sage: f = M.0
|
|
2591
|
+
sage: f.parent()
|
|
2592
|
+
Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field
|
|
2593
|
+
"""
|
|
2594
|
+
from .space import ModularFormsSpace
|
|
2595
|
+
if not isinstance(parent, ModularFormsSpace):
|
|
2596
|
+
raise TypeError("First argument must be an ambient space of modular forms.")
|
|
2597
|
+
element.HeckeModuleElement.__init__(self, parent, x)
|
|
2598
|
+
|
|
2599
|
+
def _compute_q_expansion(self, prec):
|
|
2600
|
+
"""
|
|
2601
|
+
Compute the `q`-expansion of ``self`` to precision ``prec``.
|
|
2602
|
+
|
|
2603
|
+
EXAMPLES::
|
|
2604
|
+
|
|
2605
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
2606
|
+
sage: f = EllipticCurve('37a').modular_form()
|
|
2607
|
+
sage: f.q_expansion() # indirect doctest
|
|
2608
|
+
q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + O(q^6)
|
|
2609
|
+
sage: f._compute_q_expansion(10)
|
|
2610
|
+
q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + 6*q^6 - q^7 + 6*q^9 + O(q^10)
|
|
2611
|
+
"""
|
|
2612
|
+
return self.parent()._q_expansion(element=self.element(), prec=prec)
|
|
2613
|
+
|
|
2614
|
+
def _add_(self, other):
|
|
2615
|
+
"""
|
|
2616
|
+
Add ``self`` to ``other``.
|
|
2617
|
+
|
|
2618
|
+
EXAMPLES::
|
|
2619
|
+
|
|
2620
|
+
sage: f = ModularForms(DirichletGroup(17).0^2,2).2
|
|
2621
|
+
sage: g = ModularForms(DirichletGroup(17).0^2,2).1
|
|
2622
|
+
sage: f
|
|
2623
|
+
q + (-zeta8^2 + 2)*q^2 + (zeta8 + 3)*q^3 + (-2*zeta8^2 + 3)*q^4 + (-zeta8 + 5)*q^5 + O(q^6)
|
|
2624
|
+
|
|
2625
|
+
sage: g
|
|
2626
|
+
1 + (-14/73*zeta8^3 + 57/73*zeta8^2 + 13/73*zeta8 - 6/73)*q^2 + (-90/73*zeta8^3 + 64/73*zeta8^2 - 52/73*zeta8 + 24/73)*q^3 + (-81/73*zeta8^3 + 189/73*zeta8^2 - 3/73*zeta8 + 153/73)*q^4 + (72/73*zeta8^3 + 124/73*zeta8^2 + 100/73*zeta8 + 156/73)*q^5 + O(q^6)
|
|
2627
|
+
|
|
2628
|
+
sage: f+g # indirect doctest
|
|
2629
|
+
1 + q + (-14/73*zeta8^3 - 16/73*zeta8^2 + 13/73*zeta8 + 140/73)*q^2 + (-90/73*zeta8^3 + 64/73*zeta8^2 + 21/73*zeta8 + 243/73)*q^3 + (-81/73*zeta8^3 + 43/73*zeta8^2 - 3/73*zeta8 + 372/73)*q^4 + (72/73*zeta8^3 + 124/73*zeta8^2 + 27/73*zeta8 + 521/73)*q^5 + O(q^6)
|
|
2630
|
+
"""
|
|
2631
|
+
return ModularFormElement(self.parent(), self.element() + other.element())
|
|
2632
|
+
|
|
2633
|
+
def __mul__(self, other):
|
|
2634
|
+
r"""
|
|
2635
|
+
Calculate the product ``self * other``.
|
|
2636
|
+
|
|
2637
|
+
This tries to determine the
|
|
2638
|
+
characters of ``self`` and ``other``, in order to avoid having to compute a
|
|
2639
|
+
(potentially very large) Gamma1 space. Note that this might lead to
|
|
2640
|
+
a modular form that is defined with respect to a larger subgroup than
|
|
2641
|
+
the factors are.
|
|
2642
|
+
|
|
2643
|
+
An example with character::
|
|
2644
|
+
|
|
2645
|
+
sage: f = ModularForms(DirichletGroup(3).0, 3).0
|
|
2646
|
+
sage: f * f
|
|
2647
|
+
1 + 108*q^2 + 144*q^3 + 2916*q^4 + 8640*q^5 + O(q^6)
|
|
2648
|
+
sage: (f*f).parent()
|
|
2649
|
+
Modular Forms space of dimension 3 for Congruence Subgroup Gamma0(3) of weight 6 over Rational Field
|
|
2650
|
+
sage: (f*f*f).parent()
|
|
2651
|
+
Modular Forms space of dimension 4, character [-1] and weight 9 over Rational Field
|
|
2652
|
+
|
|
2653
|
+
An example where the character is computed on-the-fly::
|
|
2654
|
+
|
|
2655
|
+
sage: f = ModularForms(Gamma1(3), 5).0
|
|
2656
|
+
sage: f*f
|
|
2657
|
+
1 - 180*q^2 - 480*q^3 + 8100*q^4 + 35712*q^5 + O(q^6)
|
|
2658
|
+
sage: (f*f).parent()
|
|
2659
|
+
Modular Forms space of dimension 4 for Congruence Subgroup Gamma0(3) of weight 10 over Rational Field
|
|
2660
|
+
|
|
2661
|
+
sage: f = ModularForms(Gamma1(3), 7).0
|
|
2662
|
+
sage: f*f
|
|
2663
|
+
q^2 - 54*q^4 + 128*q^5 + O(q^6)
|
|
2664
|
+
sage: (f*f).parent()
|
|
2665
|
+
Modular Forms space of dimension 5 for Congruence Subgroup Gamma0(3) of weight 14 over Rational Field
|
|
2666
|
+
|
|
2667
|
+
An example with no character::
|
|
2668
|
+
|
|
2669
|
+
sage: f = ModularForms(Gamma1(5), 2).0
|
|
2670
|
+
sage: f*f
|
|
2671
|
+
1 + 120*q^3 - 240*q^4 + 480*q^5 + O(q^6)
|
|
2672
|
+
sage: (f*f).parent()
|
|
2673
|
+
Modular Forms space of dimension 5 for Congruence Subgroup Gamma1(5) of weight 4 over Rational Field
|
|
2674
|
+
|
|
2675
|
+
TESTS:
|
|
2676
|
+
|
|
2677
|
+
This shows that the issue at :issue:`7548` is fixed::
|
|
2678
|
+
|
|
2679
|
+
sage: M = CuspForms(Gamma0(5*3^2), 2)
|
|
2680
|
+
sage: f = M.basis()[0]
|
|
2681
|
+
sage: 2*f
|
|
2682
|
+
2*q - 2*q^4 + O(q^6)
|
|
2683
|
+
sage: f*2
|
|
2684
|
+
2*q - 2*q^4 + O(q^6)
|
|
2685
|
+
"""
|
|
2686
|
+
|
|
2687
|
+
# boring case: scalar multiplication
|
|
2688
|
+
if not isinstance(other, ModularFormElement):
|
|
2689
|
+
return element.HeckeModuleElement.__mul__(self, other)
|
|
2690
|
+
|
|
2691
|
+
# first ensure the levels are equal
|
|
2692
|
+
if self.level() != other.level():
|
|
2693
|
+
raise NotImplementedError("Cannot multiply forms of different levels")
|
|
2694
|
+
|
|
2695
|
+
# find out about characters
|
|
2696
|
+
try:
|
|
2697
|
+
eps1 = self.character()
|
|
2698
|
+
verbose("character of left is %s" % eps1)
|
|
2699
|
+
eps2 = other.character()
|
|
2700
|
+
verbose("character of right is %s" % eps2)
|
|
2701
|
+
newchar = eps1 * eps2
|
|
2702
|
+
verbose("character of product is %s" % newchar)
|
|
2703
|
+
except (NotImplementedError, ValueError):
|
|
2704
|
+
newchar = None
|
|
2705
|
+
verbose("character of product not determined")
|
|
2706
|
+
|
|
2707
|
+
# now do the math
|
|
2708
|
+
from .constructor import ModularForms
|
|
2709
|
+
if newchar is not None:
|
|
2710
|
+
verbose("creating a parent with char")
|
|
2711
|
+
newparent = ModularForms(newchar, self.weight() + other.weight(),
|
|
2712
|
+
base_ring=newchar.base_ring())
|
|
2713
|
+
verbose("parent is %s" % newparent)
|
|
2714
|
+
else:
|
|
2715
|
+
newparent = ModularForms(self.group(),
|
|
2716
|
+
self.weight() + other.weight(),
|
|
2717
|
+
base_ring=ZZ)
|
|
2718
|
+
m = newparent.sturm_bound()
|
|
2719
|
+
newqexp = self.qexp(m) * other.qexp(m)
|
|
2720
|
+
|
|
2721
|
+
return newparent.base_extend(newqexp.base_ring())(newqexp)
|
|
2722
|
+
|
|
2723
|
+
def _pow_int(self, n):
|
|
2724
|
+
"""
|
|
2725
|
+
Raises ``self`` to integer powers.
|
|
2726
|
+
|
|
2727
|
+
TESTS::
|
|
2728
|
+
|
|
2729
|
+
sage: F = ModularForms(1, 12).0
|
|
2730
|
+
sage: (F^5).qexp(20)
|
|
2731
|
+
q^5 - 120*q^6 + 7020*q^7 - 266560*q^8 + 7379190*q^9 - 158562144*q^10 + 2748847640*q^11 -
|
|
2732
|
+
39443189760*q^12 + 476711357265*q^13 - 4910778324400*q^14 + 43440479153652*q^15 -
|
|
2733
|
+
331129448133120*q^16 + 2173189785854230*q^17 - 12199334429782080*q^18 +
|
|
2734
|
+
57636170473930920*q^19 + O(q^20)
|
|
2735
|
+
sage: _ == (F.qexp(20)**5)
|
|
2736
|
+
True
|
|
2737
|
+
|
|
2738
|
+
Testing modular forms of nontrivial character::
|
|
2739
|
+
|
|
2740
|
+
sage: # long time (:issue:`39569`)
|
|
2741
|
+
sage: F = ModularForms(DirichletGroup(17).0^2, 2).2
|
|
2742
|
+
sage: F3 = F^3; F3
|
|
2743
|
+
q^3 + (-3*zeta8^2 + 6)*q^4 + (-12*zeta8^2 + 3*zeta8 + 18)*q^5 + O(q^6)
|
|
2744
|
+
sage: F3.qexp(6) == F.qexp(6)^3
|
|
2745
|
+
True
|
|
2746
|
+
sage: F3.character() == F.character()^3
|
|
2747
|
+
True
|
|
2748
|
+
|
|
2749
|
+
Testing modular forms of level greater than 1::
|
|
2750
|
+
|
|
2751
|
+
sage: for F in ModularForms(Gamma0(4), 2).gens():
|
|
2752
|
+
....: assert (F**5).qexp(10) == F.qexp(10)**5
|
|
2753
|
+
"""
|
|
2754
|
+
# shamelessly copied from above
|
|
2755
|
+
try:
|
|
2756
|
+
eps = self.character()
|
|
2757
|
+
verbose(f"character of self is {eps}")
|
|
2758
|
+
newchar = eps ** n
|
|
2759
|
+
verbose(f"character of product is {newchar}")
|
|
2760
|
+
except (NotImplementedError, ValueError):
|
|
2761
|
+
newchar = None
|
|
2762
|
+
verbose("character of product not determined")
|
|
2763
|
+
|
|
2764
|
+
from .constructor import ModularForms
|
|
2765
|
+
if newchar is not None:
|
|
2766
|
+
verbose("creating a parent with char")
|
|
2767
|
+
newparent = ModularForms(newchar, self.weight() * n,
|
|
2768
|
+
base_ring=newchar.base_ring())
|
|
2769
|
+
verbose(f"parent is {newparent}")
|
|
2770
|
+
else:
|
|
2771
|
+
newparent = ModularForms(self.group(), self.weight() * n,
|
|
2772
|
+
base_ring=ZZ)
|
|
2773
|
+
m = newparent.sturm_bound()
|
|
2774
|
+
newqexp = self.qexp(m) ** n
|
|
2775
|
+
|
|
2776
|
+
return newparent.base_extend(newqexp.base_ring())(newqexp)
|
|
2777
|
+
|
|
2778
|
+
def atkin_lehner_eigenvalue(self, d=None, embedding=None):
|
|
2779
|
+
"""
|
|
2780
|
+
Return the result of the Atkin-Lehner operator `W_d` on
|
|
2781
|
+
``self``.
|
|
2782
|
+
|
|
2783
|
+
INPUT:
|
|
2784
|
+
|
|
2785
|
+
- ``d`` -- positive integer exactly dividing the level `N` of
|
|
2786
|
+
``self``, i.e. `d` divides `N` and is coprime to `N/d`. (default: `d
|
|
2787
|
+
= N`)
|
|
2788
|
+
|
|
2789
|
+
- ``embedding`` -- ignored (but accepted for compatibility with
|
|
2790
|
+
:meth:`Newform.atkin_lehner_eigenvalue`)
|
|
2791
|
+
|
|
2792
|
+
OUTPUT:
|
|
2793
|
+
|
|
2794
|
+
The Atkin-Lehner eigenvalue of `W_d` on ``self``. If ``self`` is not an
|
|
2795
|
+
eigenform for `W_d`, a :exc:`ValueError` is raised.
|
|
2796
|
+
|
|
2797
|
+
.. SEEALSO::
|
|
2798
|
+
|
|
2799
|
+
For the conventions used to define the operator `W_d`, see
|
|
2800
|
+
:meth:`sage.modular.hecke.module.HeckeModule_free_module.atkin_lehner_operator`.
|
|
2801
|
+
|
|
2802
|
+
EXAMPLES::
|
|
2803
|
+
|
|
2804
|
+
sage: CuspForms(1, 30).0.atkin_lehner_eigenvalue()
|
|
2805
|
+
1
|
|
2806
|
+
sage: CuspForms(2, 8).0.atkin_lehner_eigenvalue()
|
|
2807
|
+
Traceback (most recent call last):
|
|
2808
|
+
...
|
|
2809
|
+
NotImplementedError: don't know how to compute Atkin-Lehner matrix acting on this space (try using a newform constructor instead)
|
|
2810
|
+
"""
|
|
2811
|
+
if d is None:
|
|
2812
|
+
d = self.level()
|
|
2813
|
+
try:
|
|
2814
|
+
f = self.parent().atkin_lehner_operator(d)(self)
|
|
2815
|
+
except NotImplementedError:
|
|
2816
|
+
raise NotImplementedError("don't know how to compute Atkin-Lehner matrix acting on this space (try using a newform constructor instead)")
|
|
2817
|
+
w = self.element().nonzero_positions()[0]
|
|
2818
|
+
t = f.element()[w] / self.element()[w]
|
|
2819
|
+
if f.element() == self.element() * t:
|
|
2820
|
+
return t
|
|
2821
|
+
else:
|
|
2822
|
+
raise ValueError("%r is not an eigenform for W_%r" % (self, d))
|
|
2823
|
+
|
|
2824
|
+
def twist(self, chi, level=None):
|
|
2825
|
+
r"""
|
|
2826
|
+
Return the twist of the modular form ``self`` by the Dirichlet
|
|
2827
|
+
character ``chi``.
|
|
2828
|
+
|
|
2829
|
+
If ``self`` is a modular form `f` with character `\epsilon`
|
|
2830
|
+
and `q`-expansion
|
|
2831
|
+
|
|
2832
|
+
.. MATH::
|
|
2833
|
+
|
|
2834
|
+
f(q) = \sum_{n=0}^\infty a_n q^n,
|
|
2835
|
+
|
|
2836
|
+
then the twist by `\chi` is a modular form `f_\chi` with
|
|
2837
|
+
character `\epsilon\chi^2` and `q`-expansion
|
|
2838
|
+
|
|
2839
|
+
.. MATH::
|
|
2840
|
+
|
|
2841
|
+
f_\chi(q) = \sum_{n=0}^\infty \chi(n) a_n q^n.
|
|
2842
|
+
|
|
2843
|
+
INPUT:
|
|
2844
|
+
|
|
2845
|
+
- ``chi`` -- a Dirichlet character
|
|
2846
|
+
|
|
2847
|
+
- ``level`` -- (optional) the level `N` of the twisted form.
|
|
2848
|
+
By default, the algorithm chooses some not necessarily
|
|
2849
|
+
minimal value for `N` using [AL1978]_, Proposition 3.1,
|
|
2850
|
+
(See also [Kob1993]_, Proposition III.3.17, for a simpler
|
|
2851
|
+
but slightly weaker bound.)
|
|
2852
|
+
|
|
2853
|
+
OUTPUT:
|
|
2854
|
+
|
|
2855
|
+
The form `f_\chi` as an element of the space of modular forms
|
|
2856
|
+
for `\Gamma_1(N)` with character `\epsilon\chi^2`.
|
|
2857
|
+
|
|
2858
|
+
EXAMPLES::
|
|
2859
|
+
|
|
2860
|
+
sage: f = CuspForms(11, 2).0
|
|
2861
|
+
sage: f.parent()
|
|
2862
|
+
Cuspidal subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field
|
|
2863
|
+
sage: f.q_expansion(6)
|
|
2864
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6)
|
|
2865
|
+
sage: eps = DirichletGroup(3).0
|
|
2866
|
+
sage: eps.parent()
|
|
2867
|
+
Group of Dirichlet characters modulo 3 with values in Cyclotomic Field of order 2 and degree 1
|
|
2868
|
+
sage: f_eps = f.twist(eps)
|
|
2869
|
+
sage: f_eps.parent()
|
|
2870
|
+
Cuspidal subspace of dimension 9 of Modular Forms space of dimension 16 for Congruence Subgroup Gamma0(99) of weight 2 over Cyclotomic Field of order 2 and degree 1
|
|
2871
|
+
sage: f_eps.q_expansion(6)
|
|
2872
|
+
q + 2*q^2 + 2*q^4 - q^5 + O(q^6)
|
|
2873
|
+
|
|
2874
|
+
Modular forms without character are supported::
|
|
2875
|
+
|
|
2876
|
+
sage: M = ModularForms(Gamma1(5), 2)
|
|
2877
|
+
sage: f = M.gen(0); f
|
|
2878
|
+
1 + 60*q^3 - 120*q^4 + 240*q^5 + O(q^6)
|
|
2879
|
+
sage: chi = DirichletGroup(2)[0]
|
|
2880
|
+
sage: f.twist(chi)
|
|
2881
|
+
60*q^3 + 240*q^5 + O(q^6)
|
|
2882
|
+
|
|
2883
|
+
The base field of the twisted form is extended if necessary::
|
|
2884
|
+
|
|
2885
|
+
sage: E4 = ModularForms(1, 4).gen(0)
|
|
2886
|
+
sage: E4.parent()
|
|
2887
|
+
Modular Forms space of dimension 1 for Modular Group SL(2,Z) of weight 4 over Rational Field
|
|
2888
|
+
sage: chi = DirichletGroup(5)[1]
|
|
2889
|
+
sage: chi.base_ring()
|
|
2890
|
+
Cyclotomic Field of order 4 and degree 2
|
|
2891
|
+
sage: E4_chi = E4.twist(chi)
|
|
2892
|
+
sage: E4_chi.parent()
|
|
2893
|
+
Modular Forms space of dimension 10, character [-1] and weight 4 over Cyclotomic Field of order 4 and degree 2
|
|
2894
|
+
|
|
2895
|
+
REFERENCES:
|
|
2896
|
+
|
|
2897
|
+
- [AL1978]_
|
|
2898
|
+
|
|
2899
|
+
- [Kob1993]_
|
|
2900
|
+
|
|
2901
|
+
AUTHORS:
|
|
2902
|
+
|
|
2903
|
+
- \L. J. P. Kilford (2009-08-28)
|
|
2904
|
+
|
|
2905
|
+
- Peter Bruin (2015-03-30)
|
|
2906
|
+
"""
|
|
2907
|
+
from sage.modular.all import CuspForms, ModularForms
|
|
2908
|
+
R = coercion_model.common_parent(self.base_ring(), chi.base_ring())
|
|
2909
|
+
N = self.level()
|
|
2910
|
+
Q = chi.modulus()
|
|
2911
|
+
try:
|
|
2912
|
+
epsilon = self.character()
|
|
2913
|
+
except ValueError:
|
|
2914
|
+
epsilon = None
|
|
2915
|
+
constructor = CuspForms if self.is_cuspidal() else ModularForms
|
|
2916
|
+
if epsilon is not None:
|
|
2917
|
+
if level is None:
|
|
2918
|
+
# See [AL1978], Proposition 3.1.
|
|
2919
|
+
level = lcm([N, epsilon.conductor() * Q, Q**2])
|
|
2920
|
+
G = DirichletGroup(level, base_ring=R)
|
|
2921
|
+
M = constructor(G(epsilon) * G(chi)**2, self.weight(), base_ring=R)
|
|
2922
|
+
else:
|
|
2923
|
+
from sage.modular.arithgroup.congroup_gamma1 import (
|
|
2924
|
+
Gamma1_constructor as Gamma1,
|
|
2925
|
+
)
|
|
2926
|
+
if level is None:
|
|
2927
|
+
# See [AL1978], Proposition 3.1.
|
|
2928
|
+
level = lcm([N, Q]) * Q
|
|
2929
|
+
M = constructor(Gamma1(level), self.weight(), base_ring=R)
|
|
2930
|
+
bound = M.sturm_bound() + 1
|
|
2931
|
+
S = PowerSeriesRing(R, 'q')
|
|
2932
|
+
f_twist = S([self[i] * chi(i) for i in range(bound)], prec=bound)
|
|
2933
|
+
return M(f_twist)
|
|
2934
|
+
|
|
2935
|
+
|
|
2936
|
+
class ModularFormElement_elliptic_curve(Newform):
|
|
2937
|
+
r"""
|
|
2938
|
+
A modular form attached to an elliptic curve over `\QQ`.
|
|
2939
|
+
"""
|
|
2940
|
+
def __init__(self, parent, E):
|
|
2941
|
+
"""
|
|
2942
|
+
Modular form attached to an elliptic curve as an element
|
|
2943
|
+
of a space of modular forms.
|
|
2944
|
+
|
|
2945
|
+
EXAMPLES::
|
|
2946
|
+
|
|
2947
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
2948
|
+
sage: E = EllipticCurve('389a')
|
|
2949
|
+
sage: f = E.modular_form()
|
|
2950
|
+
sage: f
|
|
2951
|
+
q - 2*q^2 - 2*q^3 + 2*q^4 - 3*q^5 + O(q^6)
|
|
2952
|
+
sage: f.q_expansion(10)
|
|
2953
|
+
q - 2*q^2 - 2*q^3 + 2*q^4 - 3*q^5 + 4*q^6 - 5*q^7 + q^9 + O(q^10)
|
|
2954
|
+
sage: f.parent()
|
|
2955
|
+
Modular Forms space of dimension 33 for Congruence Subgroup Gamma0(389) of weight 2 over Rational Field
|
|
2956
|
+
|
|
2957
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
2958
|
+
sage: E = EllipticCurve('37a')
|
|
2959
|
+
sage: f = E.modular_form(); f
|
|
2960
|
+
q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + O(q^6)
|
|
2961
|
+
sage: f == loads(dumps(f))
|
|
2962
|
+
True
|
|
2963
|
+
"""
|
|
2964
|
+
Newform.__init__(self, parent, E.modular_symbol_space(), names=None)
|
|
2965
|
+
self.__E = E
|
|
2966
|
+
|
|
2967
|
+
def elliptic_curve(self):
|
|
2968
|
+
"""
|
|
2969
|
+
Return elliptic curve associated to ``self``.
|
|
2970
|
+
|
|
2971
|
+
EXAMPLES::
|
|
2972
|
+
|
|
2973
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
2974
|
+
sage: E = EllipticCurve('11a')
|
|
2975
|
+
sage: f = E.modular_form()
|
|
2976
|
+
sage: f.elliptic_curve()
|
|
2977
|
+
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
|
|
2978
|
+
sage: f.elliptic_curve() is E
|
|
2979
|
+
True
|
|
2980
|
+
"""
|
|
2981
|
+
return self.__E
|
|
2982
|
+
|
|
2983
|
+
def _compute_element(self):
|
|
2984
|
+
"""
|
|
2985
|
+
Compute ``self`` as a linear combination of the basis elements
|
|
2986
|
+
of parent.
|
|
2987
|
+
|
|
2988
|
+
EXAMPLES::
|
|
2989
|
+
|
|
2990
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
2991
|
+
sage: EllipticCurve('11a1').modular_form()._compute_element()
|
|
2992
|
+
(1, 0)
|
|
2993
|
+
sage: EllipticCurve('389a1').modular_form()._compute_element()
|
|
2994
|
+
(1, -2, -2, 2, -3, 4, -5, 0, 1, 6, -4, -4, -3, 10, 6, -4, -6, -2, 5, -6, 10, 8, -4, 0, 4, 6, 4, -10, -6, -12, 4, 8, 0)
|
|
2995
|
+
"""
|
|
2996
|
+
M = self.parent()
|
|
2997
|
+
S = M.cuspidal_subspace()
|
|
2998
|
+
# return S.find_in_space( self.__E.q_expansion( S.q_expansion_basis()[0].prec() ) ) + [0] * ( M.dimension() - S.dimension() )
|
|
2999
|
+
return vector(S.find_in_space(self.__E.q_expansion(S.sturm_bound())) + [0] * (M.dimension() - S.dimension()))
|
|
3000
|
+
|
|
3001
|
+
def _compute_q_expansion(self, prec):
|
|
3002
|
+
r"""
|
|
3003
|
+
The `q`-expansion of the modular form to precision `O(q^\text{prec})`.
|
|
3004
|
+
|
|
3005
|
+
This function takes one argument, which is the integer ``prec``.
|
|
3006
|
+
|
|
3007
|
+
EXAMPLES::
|
|
3008
|
+
|
|
3009
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
3010
|
+
sage: E = EllipticCurve('11a'); f = E.modular_form()
|
|
3011
|
+
sage: f._compute_q_expansion(10)
|
|
3012
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + 2*q^6 - 2*q^7 - 2*q^9 + O(q^10)
|
|
3013
|
+
sage: f._compute_q_expansion(30)
|
|
3014
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + 2*q^6 - 2*q^7 - 2*q^9 - 2*q^10 + q^11 - 2*q^12 + 4*q^13 + 4*q^14 - q^15 - 4*q^16 - 2*q^17 + 4*q^18 + 2*q^20 + 2*q^21 - 2*q^22 - q^23 - 4*q^25 - 8*q^26 + 5*q^27 - 4*q^28 + O(q^30)
|
|
3015
|
+
sage: f._compute_q_expansion(10)
|
|
3016
|
+
q - 2*q^2 - q^3 + 2*q^4 + q^5 + 2*q^6 - 2*q^7 - 2*q^9 + O(q^10)
|
|
3017
|
+
"""
|
|
3018
|
+
return self.__E.q_expansion(prec)
|
|
3019
|
+
|
|
3020
|
+
def atkin_lehner_eigenvalue(self, d=None, embedding=None):
|
|
3021
|
+
"""
|
|
3022
|
+
Return the result of the Atkin-Lehner operator `W_d` on
|
|
3023
|
+
``self``.
|
|
3024
|
+
|
|
3025
|
+
INPUT:
|
|
3026
|
+
|
|
3027
|
+
- ``d`` -- positive integer exactly dividing the level `N` of
|
|
3028
|
+
``self``, i.e. `d` divides `N` and is coprime to `N/d`. (Defaults to
|
|
3029
|
+
`d = N` if not given.)
|
|
3030
|
+
|
|
3031
|
+
- ``embedding`` -- ignored (but accepted for compatibility with
|
|
3032
|
+
:meth:`Newform.atkin_lehner_action`)
|
|
3033
|
+
|
|
3034
|
+
OUTPUT:
|
|
3035
|
+
|
|
3036
|
+
The Atkin-Lehner eigenvalue of `W_d` on ``self``. This is either `1` or
|
|
3037
|
+
`-1`.
|
|
3038
|
+
|
|
3039
|
+
EXAMPLES::
|
|
3040
|
+
|
|
3041
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
3042
|
+
sage: EllipticCurve('57a1').newform().atkin_lehner_eigenvalue()
|
|
3043
|
+
1
|
|
3044
|
+
sage: EllipticCurve('57b1').newform().atkin_lehner_eigenvalue()
|
|
3045
|
+
-1
|
|
3046
|
+
sage: EllipticCurve('57b1').newform().atkin_lehner_eigenvalue(19)
|
|
3047
|
+
1
|
|
3048
|
+
"""
|
|
3049
|
+
if d == self.level():
|
|
3050
|
+
w = -self.__E.root_number()
|
|
3051
|
+
else:
|
|
3052
|
+
# The space of modular symbols attached to E is
|
|
3053
|
+
# one-dimensional.
|
|
3054
|
+
w = self.__E.modular_symbol_space().atkin_lehner_operator(d).matrix()[0, 0]
|
|
3055
|
+
return w
|
|
3056
|
+
|
|
3057
|
+
|
|
3058
|
+
class EisensteinSeries(ModularFormElement):
|
|
3059
|
+
"""
|
|
3060
|
+
An Eisenstein series.
|
|
3061
|
+
|
|
3062
|
+
EXAMPLES::
|
|
3063
|
+
|
|
3064
|
+
sage: E = EisensteinForms(1,12)
|
|
3065
|
+
sage: E.eisenstein_series()
|
|
3066
|
+
[691/65520 + q + 2049*q^2 + 177148*q^3 + 4196353*q^4 + 48828126*q^5 + O(q^6)]
|
|
3067
|
+
sage: E = EisensteinForms(11,2)
|
|
3068
|
+
sage: E.eisenstein_series()
|
|
3069
|
+
[5/12 + q + 3*q^2 + 4*q^3 + 7*q^4 + 6*q^5 + O(q^6)]
|
|
3070
|
+
sage: E = EisensteinForms(Gamma1(7),2)
|
|
3071
|
+
sage: E.set_precision(4)
|
|
3072
|
+
sage: E.eisenstein_series()
|
|
3073
|
+
[1/4 + q + 3*q^2 + 4*q^3 + O(q^4),
|
|
3074
|
+
1/7*zeta6 - 3/7 + q + (-2*zeta6 + 1)*q^2 + (3*zeta6 - 2)*q^3 + O(q^4),
|
|
3075
|
+
q + (-zeta6 + 2)*q^2 + (zeta6 + 2)*q^3 + O(q^4),
|
|
3076
|
+
-1/7*zeta6 - 2/7 + q + (2*zeta6 - 1)*q^2 + (-3*zeta6 + 1)*q^3 + O(q^4),
|
|
3077
|
+
q + (zeta6 + 1)*q^2 + (-zeta6 + 3)*q^3 + O(q^4)]
|
|
3078
|
+
"""
|
|
3079
|
+
def __init__(self, parent, vector, t, chi, psi):
|
|
3080
|
+
"""
|
|
3081
|
+
An Eisenstein series.
|
|
3082
|
+
|
|
3083
|
+
EXAMPLES::
|
|
3084
|
+
|
|
3085
|
+
sage: E = EisensteinForms(1,12) # indirect doctest
|
|
3086
|
+
sage: E.eisenstein_series()
|
|
3087
|
+
[691/65520 + q + 2049*q^2 + 177148*q^3 + 4196353*q^4 + 48828126*q^5 + O(q^6)]
|
|
3088
|
+
sage: E = EisensteinForms(11,2)
|
|
3089
|
+
sage: E.eisenstein_series()
|
|
3090
|
+
[5/12 + q + 3*q^2 + 4*q^3 + 7*q^4 + 6*q^5 + O(q^6)]
|
|
3091
|
+
sage: E = EisensteinForms(Gamma1(7),2)
|
|
3092
|
+
sage: E.set_precision(4)
|
|
3093
|
+
sage: E.eisenstein_series()
|
|
3094
|
+
[1/4 + q + 3*q^2 + 4*q^3 + O(q^4),
|
|
3095
|
+
1/7*zeta6 - 3/7 + q + (-2*zeta6 + 1)*q^2 + (3*zeta6 - 2)*q^3 + O(q^4),
|
|
3096
|
+
q + (-zeta6 + 2)*q^2 + (zeta6 + 2)*q^3 + O(q^4),
|
|
3097
|
+
-1/7*zeta6 - 2/7 + q + (2*zeta6 - 1)*q^2 + (-3*zeta6 + 1)*q^3 + O(q^4),
|
|
3098
|
+
q + (zeta6 + 1)*q^2 + (-zeta6 + 3)*q^3 + O(q^4)]
|
|
3099
|
+
"""
|
|
3100
|
+
N = parent.level()
|
|
3101
|
+
K = parent.base_ring()
|
|
3102
|
+
if chi.parent().modulus() != N or psi.parent().modulus() != N:
|
|
3103
|
+
raise ArithmeticError("Incompatible moduli")
|
|
3104
|
+
if chi.parent().base_ring() != K or psi.parent().base_ring() != K:
|
|
3105
|
+
raise ArithmeticError("Incompatible base rings")
|
|
3106
|
+
t = int(t)
|
|
3107
|
+
if parent.weight() == 2 and chi.is_trivial() and psi.is_trivial() and t == 1:
|
|
3108
|
+
raise ArithmeticError("If chi and psi are trivial and k=2, then t must be >1.")
|
|
3109
|
+
ModularFormElement.__init__(self, parent, vector)
|
|
3110
|
+
self.__chi = chi
|
|
3111
|
+
self.__psi = psi
|
|
3112
|
+
self.__t = t
|
|
3113
|
+
|
|
3114
|
+
def _compute_q_expansion(self, prec=None):
|
|
3115
|
+
"""
|
|
3116
|
+
Compute the `q`-expansion of ``self`` to precision ``prec``.
|
|
3117
|
+
|
|
3118
|
+
EXAMPLES::
|
|
3119
|
+
|
|
3120
|
+
sage: EisensteinForms(11,2).eisenstein_series()[0]._compute_q_expansion(10)
|
|
3121
|
+
5/12 + q + 3*q^2 + 4*q^3 + 7*q^4 + 6*q^5 + 12*q^6 + 8*q^7 + 15*q^8 + 13*q^9 + O(q^10)
|
|
3122
|
+
"""
|
|
3123
|
+
if prec is None:
|
|
3124
|
+
prec = self.parent().prec()
|
|
3125
|
+
F = self._compute(list(range(prec)))
|
|
3126
|
+
R = self.parent()._q_expansion_ring()
|
|
3127
|
+
return R(F, prec)
|
|
3128
|
+
|
|
3129
|
+
def _compute(self, X):
|
|
3130
|
+
r"""
|
|
3131
|
+
Compute the coefficients of `q^n` of the power series of self,
|
|
3132
|
+
for `n` in the list `X`. The results are not cached. (Use
|
|
3133
|
+
coefficients for cached results).
|
|
3134
|
+
|
|
3135
|
+
EXAMPLES::
|
|
3136
|
+
|
|
3137
|
+
sage: e = DirichletGroup(11).gen()
|
|
3138
|
+
sage: f = EisensteinForms(e, 3).eisenstein_series()[0]
|
|
3139
|
+
sage: f._compute([3,4,5])
|
|
3140
|
+
[-9*zeta10^3 + 1,
|
|
3141
|
+
16*zeta10^2 + 4*zeta10 + 1,
|
|
3142
|
+
25*zeta10^3 - 25*zeta10^2 + 25*zeta10 - 24]
|
|
3143
|
+
"""
|
|
3144
|
+
if self.weight() == 2 and (self.__chi.is_trivial() and self.__psi.is_trivial()):
|
|
3145
|
+
return self.__compute_weight2_trivial_character(X)
|
|
3146
|
+
else: # general case
|
|
3147
|
+
return self.__compute_general_case(X)
|
|
3148
|
+
|
|
3149
|
+
def __compute_weight2_trivial_character(self, X):
|
|
3150
|
+
r"""
|
|
3151
|
+
Compute coefficients for ``self`` an Eisenstein series of the form
|
|
3152
|
+
`E_2 - t*E_2(q^t)`. Computes `a_n` for each `n \in X`.
|
|
3153
|
+
|
|
3154
|
+
EXAMPLES::
|
|
3155
|
+
|
|
3156
|
+
sage: EisensteinForms(14,2).eisenstein_series()[0]._EisensteinSeries__compute_weight2_trivial_character([0])
|
|
3157
|
+
[1/24]
|
|
3158
|
+
sage: EisensteinForms(14,2).eisenstein_series()[0]._EisensteinSeries__compute_weight2_trivial_character([0,4,11,38])
|
|
3159
|
+
[1/24, 1, 12, 20]
|
|
3160
|
+
"""
|
|
3161
|
+
F = self.base_ring()
|
|
3162
|
+
v = []
|
|
3163
|
+
t = self.__t
|
|
3164
|
+
for n in X:
|
|
3165
|
+
if n < 0:
|
|
3166
|
+
pass
|
|
3167
|
+
elif n == 0:
|
|
3168
|
+
v.append(F(t - 1) / F(24))
|
|
3169
|
+
else:
|
|
3170
|
+
an = sigma(n, 1)
|
|
3171
|
+
if n % t == 0:
|
|
3172
|
+
an -= t * sigma(n // t, 1)
|
|
3173
|
+
v.append(an)
|
|
3174
|
+
return v
|
|
3175
|
+
|
|
3176
|
+
def __compute_general_case(self, X):
|
|
3177
|
+
r"""
|
|
3178
|
+
Return the list coefficients of `q^n` of the power series of self,
|
|
3179
|
+
for `n` in the list `X`. The results are not cached. (Use
|
|
3180
|
+
coefficients for cached results).
|
|
3181
|
+
|
|
3182
|
+
General case (except weight 2, trivial character, where this
|
|
3183
|
+
is wrong!) `\chi` is a primitive character of conductor `L`
|
|
3184
|
+
`\psi` is a primitive character of conductor `M` We have
|
|
3185
|
+
`MLt \mid N`, and
|
|
3186
|
+
|
|
3187
|
+
.. MATH::
|
|
3188
|
+
|
|
3189
|
+
E_k(chi,psi,t) =
|
|
3190
|
+
c_0 + sum_{m \geq 1}[sum_{n|m} psi(n) * chi(m/n) * n^(k-1)] q^{mt},
|
|
3191
|
+
|
|
3192
|
+
with `c_0=0` if `L>1`, and `c_0=L(1-k,psi)/2` if `L=1` (that
|
|
3193
|
+
second `L` is an `L`-function `L`).
|
|
3194
|
+
|
|
3195
|
+
EXAMPLES::
|
|
3196
|
+
|
|
3197
|
+
sage: e = DirichletGroup(11).gen()
|
|
3198
|
+
sage: f = EisensteinForms(e, 3).eisenstein_series()[0]
|
|
3199
|
+
sage: f._EisensteinSeries__compute_general_case([1])
|
|
3200
|
+
[1]
|
|
3201
|
+
sage: f._EisensteinSeries__compute_general_case([2])
|
|
3202
|
+
[4*zeta10 + 1]
|
|
3203
|
+
sage: f._EisensteinSeries__compute_general_case([0,1,2])
|
|
3204
|
+
[15/11*zeta10^3 - 9/11*zeta10^2 - 26/11*zeta10 - 10/11, 1, 4*zeta10 + 1]
|
|
3205
|
+
"""
|
|
3206
|
+
c0, chi, psi, K, n, t, L, M = self.__defining_parameters()
|
|
3207
|
+
zero = K.zero()
|
|
3208
|
+
k = self.weight()
|
|
3209
|
+
v = []
|
|
3210
|
+
for i in X:
|
|
3211
|
+
if i == 0:
|
|
3212
|
+
v.append(c0)
|
|
3213
|
+
continue
|
|
3214
|
+
if i % t != 0:
|
|
3215
|
+
v.append(zero)
|
|
3216
|
+
else:
|
|
3217
|
+
m = i // t
|
|
3218
|
+
v.append(sum([psi(d) * chi(m / d) * d ** (k - 1)
|
|
3219
|
+
for d in divisors(m)]))
|
|
3220
|
+
return v
|
|
3221
|
+
|
|
3222
|
+
@cached_method
|
|
3223
|
+
def __defining_parameters(self):
|
|
3224
|
+
r"""
|
|
3225
|
+
Return defining parameters for ``self``.
|
|
3226
|
+
|
|
3227
|
+
EXAMPLES::
|
|
3228
|
+
|
|
3229
|
+
sage: EisensteinForms(11,2).eisenstein_series()[0]._EisensteinSeries__defining_parameters()
|
|
3230
|
+
(-1/24, Dirichlet character modulo 1 of conductor 1, Dirichlet character modulo 1 of conductor 1, Rational Field, 2, 11, 1, 1)
|
|
3231
|
+
"""
|
|
3232
|
+
chi = self.__chi.primitive_character()
|
|
3233
|
+
psi = self.__psi.primitive_character()
|
|
3234
|
+
k = self.weight()
|
|
3235
|
+
t = self.__t
|
|
3236
|
+
L = chi.conductor()
|
|
3237
|
+
M = psi.conductor()
|
|
3238
|
+
K = chi.base_ring()
|
|
3239
|
+
n = K.zeta_order()
|
|
3240
|
+
if L == 1:
|
|
3241
|
+
c0 = K(-psi.bernoulli(k)) / K(2 * k)
|
|
3242
|
+
else:
|
|
3243
|
+
c0 = K.zero()
|
|
3244
|
+
return (c0, chi, psi, K, n, t, L, M)
|
|
3245
|
+
|
|
3246
|
+
def chi(self):
|
|
3247
|
+
"""
|
|
3248
|
+
Return the parameter chi associated to ``self``.
|
|
3249
|
+
|
|
3250
|
+
EXAMPLES::
|
|
3251
|
+
|
|
3252
|
+
sage: EisensteinForms(DirichletGroup(17).0,99).eisenstein_series()[1].chi()
|
|
3253
|
+
Dirichlet character modulo 17 of conductor 17 mapping 3 |--> zeta16
|
|
3254
|
+
"""
|
|
3255
|
+
return self.__chi
|
|
3256
|
+
|
|
3257
|
+
def psi(self):
|
|
3258
|
+
"""
|
|
3259
|
+
Return the parameter psi associated to ``self``.
|
|
3260
|
+
|
|
3261
|
+
EXAMPLES::
|
|
3262
|
+
|
|
3263
|
+
sage: EisensteinForms(DirichletGroup(17).0,99).eisenstein_series()[1].psi()
|
|
3264
|
+
Dirichlet character modulo 17 of conductor 1 mapping 3 |--> 1
|
|
3265
|
+
"""
|
|
3266
|
+
return self.__psi
|
|
3267
|
+
|
|
3268
|
+
def t(self):
|
|
3269
|
+
"""
|
|
3270
|
+
Return the parameter t associated to ``self``.
|
|
3271
|
+
|
|
3272
|
+
EXAMPLES::
|
|
3273
|
+
|
|
3274
|
+
sage: EisensteinForms(DirichletGroup(17).0,99).eisenstein_series()[1].t()
|
|
3275
|
+
1
|
|
3276
|
+
"""
|
|
3277
|
+
return self.__t
|
|
3278
|
+
|
|
3279
|
+
def parameters(self):
|
|
3280
|
+
"""
|
|
3281
|
+
Return chi, psi, and t, which are the defining parameters of ``self``.
|
|
3282
|
+
|
|
3283
|
+
EXAMPLES::
|
|
3284
|
+
|
|
3285
|
+
sage: EisensteinForms(DirichletGroup(17).0,99).eisenstein_series()[1].parameters()
|
|
3286
|
+
(Dirichlet character modulo 17 of conductor 17 mapping 3 |--> zeta16, Dirichlet character modulo 17 of conductor 1 mapping 3 |--> 1, 1)
|
|
3287
|
+
"""
|
|
3288
|
+
return self.__chi, self.__psi, self.__t
|
|
3289
|
+
|
|
3290
|
+
def L(self):
|
|
3291
|
+
"""
|
|
3292
|
+
Return the conductor of self.chi().
|
|
3293
|
+
|
|
3294
|
+
EXAMPLES::
|
|
3295
|
+
|
|
3296
|
+
sage: EisensteinForms(DirichletGroup(17).0,99).eisenstein_series()[1].L()
|
|
3297
|
+
17
|
|
3298
|
+
"""
|
|
3299
|
+
return self.__chi.conductor()
|
|
3300
|
+
|
|
3301
|
+
def M(self):
|
|
3302
|
+
"""
|
|
3303
|
+
Return the conductor of self.psi().
|
|
3304
|
+
|
|
3305
|
+
EXAMPLES::
|
|
3306
|
+
|
|
3307
|
+
sage: EisensteinForms(DirichletGroup(17).0,99).eisenstein_series()[1].M()
|
|
3308
|
+
1
|
|
3309
|
+
"""
|
|
3310
|
+
return self.__psi.conductor()
|
|
3311
|
+
|
|
3312
|
+
@cached_method
|
|
3313
|
+
def character(self):
|
|
3314
|
+
"""
|
|
3315
|
+
Return the character associated to ``self``.
|
|
3316
|
+
|
|
3317
|
+
EXAMPLES::
|
|
3318
|
+
|
|
3319
|
+
sage: EisensteinForms(DirichletGroup(17).0,99).eisenstein_series()[1].character()
|
|
3320
|
+
Dirichlet character modulo 17 of conductor 17 mapping 3 |--> zeta16
|
|
3321
|
+
|
|
3322
|
+
sage: chi = DirichletGroup(7)[4]
|
|
3323
|
+
sage: E = EisensteinForms(chi).eisenstein_series() ; E
|
|
3324
|
+
[-1/7*zeta6 - 2/7 + q + (2*zeta6 - 1)*q^2 + (-3*zeta6 + 1)*q^3 + (-2*zeta6 - 1)*q^4 + (5*zeta6 - 4)*q^5 + O(q^6),
|
|
3325
|
+
q + (zeta6 + 1)*q^2 + (-zeta6 + 3)*q^3 + (zeta6 + 2)*q^4 + (zeta6 + 4)*q^5 + O(q^6)]
|
|
3326
|
+
sage: E[0].character() == chi
|
|
3327
|
+
True
|
|
3328
|
+
sage: E[1].character() == chi
|
|
3329
|
+
True
|
|
3330
|
+
|
|
3331
|
+
TESTS::
|
|
3332
|
+
|
|
3333
|
+
sage: [ [ f.character() == chi for f in EisensteinForms(chi).eisenstein_series() ] for chi in DirichletGroup(17) ]
|
|
3334
|
+
[[True], [], [True, True], [], [True, True], [], [True, True], [], [True, True], [], [True, True], [], [True, True], [], [True, True], []]
|
|
3335
|
+
|
|
3336
|
+
sage: [ [ f.character() == chi for f in EisensteinForms(chi).eisenstein_series() ] for chi in DirichletGroup(16) ]
|
|
3337
|
+
[[True, True, True, True, True], [], [True, True], [], [True, True, True, True], [], [True, True], []]
|
|
3338
|
+
"""
|
|
3339
|
+
return self.__chi * self.__psi
|
|
3340
|
+
|
|
3341
|
+
def new_level(self):
|
|
3342
|
+
"""
|
|
3343
|
+
Return level at which ``self`` is new.
|
|
3344
|
+
|
|
3345
|
+
EXAMPLES::
|
|
3346
|
+
|
|
3347
|
+
sage: EisensteinForms(DirichletGroup(17).0,99).eisenstein_series()[1].level()
|
|
3348
|
+
17
|
|
3349
|
+
sage: EisensteinForms(DirichletGroup(17).0,99).eisenstein_series()[1].new_level()
|
|
3350
|
+
17
|
|
3351
|
+
sage: [ [x.level(), x.new_level()] for x in EisensteinForms(DirichletGroup(60).0^2,2).eisenstein_series() ]
|
|
3352
|
+
[[60, 2], [60, 3], [60, 2], [60, 5], [60, 2], [60, 2], [60, 2], [60, 3], [60, 2], [60, 2], [60, 2]]
|
|
3353
|
+
"""
|
|
3354
|
+
if self.__chi.is_trivial() and self.__psi.is_trivial() and self.weight() == 2:
|
|
3355
|
+
return factor(self.__t)[0][0]
|
|
3356
|
+
return self.L() * self.M()
|
|
3357
|
+
|
|
3358
|
+
|
|
3359
|
+
class GradedModularFormElement(ModuleElement):
|
|
3360
|
+
r"""
|
|
3361
|
+
The element class for ``ModularFormsRing``. A ``GradedModularFormElement`` is basically a
|
|
3362
|
+
formal sum of modular forms of different weight: `f_1 + f_2 + ... + f_n`. Note that a
|
|
3363
|
+
``GradedModularFormElement`` is not necessarily a modular form (as it can have mixed weight
|
|
3364
|
+
components).
|
|
3365
|
+
|
|
3366
|
+
A ``GradedModularFormElement`` should not be constructed directly via this class. Instead,
|
|
3367
|
+
one should use the element constructor of the parent class (``ModularFormsRing``).
|
|
3368
|
+
|
|
3369
|
+
EXAMPLES::
|
|
3370
|
+
|
|
3371
|
+
sage: M = ModularFormsRing(1)
|
|
3372
|
+
sage: D = CuspForms(1, 12).0
|
|
3373
|
+
sage: M(D).parent()
|
|
3374
|
+
Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field
|
|
3375
|
+
|
|
3376
|
+
A graded modular form can be initiated via a dictionary or a list::
|
|
3377
|
+
|
|
3378
|
+
sage: E4 = ModularForms(1, 4).0
|
|
3379
|
+
sage: M({4:E4, 12:D}) # dictionary
|
|
3380
|
+
1 + 241*q + 2136*q^2 + 6972*q^3 + 16048*q^4 + 35070*q^5 + O(q^6)
|
|
3381
|
+
sage: M([E4, D]) # list
|
|
3382
|
+
1 + 241*q + 2136*q^2 + 6972*q^3 + 16048*q^4 + 35070*q^5 + O(q^6)
|
|
3383
|
+
|
|
3384
|
+
Also, when adding two modular forms of different weights, a graded modular form element will be created::
|
|
3385
|
+
|
|
3386
|
+
sage: (E4 + D).parent()
|
|
3387
|
+
Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field
|
|
3388
|
+
sage: M([E4, D]) == E4 + D
|
|
3389
|
+
True
|
|
3390
|
+
|
|
3391
|
+
Graded modular forms elements for congruence subgroups are also supported::
|
|
3392
|
+
|
|
3393
|
+
sage: M = ModularFormsRing(Gamma0(3))
|
|
3394
|
+
sage: f = ModularForms(Gamma0(3), 4).0
|
|
3395
|
+
sage: g = ModularForms(Gamma0(3), 2).0
|
|
3396
|
+
sage: M([f, g])
|
|
3397
|
+
2 + 12*q + 36*q^2 + 252*q^3 + 84*q^4 + 72*q^5 + O(q^6)
|
|
3398
|
+
sage: M({4:f, 2:g})
|
|
3399
|
+
2 + 12*q + 36*q^2 + 252*q^3 + 84*q^4 + 72*q^5 + O(q^6)
|
|
3400
|
+
"""
|
|
3401
|
+
def __init__(self, parent, forms_datum):
|
|
3402
|
+
r"""
|
|
3403
|
+
INPUT:
|
|
3404
|
+
|
|
3405
|
+
- ``parent`` -- an object of the class ``ModularFormsRing``
|
|
3406
|
+
- ``forms_datum`` -- dictionary ``{k_1:f_1, k_2:f_2, ..., k_n:f_n}``
|
|
3407
|
+
or a list ``[f_1, f_2,..., f_n]`` where `f_i` is a modular form of
|
|
3408
|
+
weight `k_i`
|
|
3409
|
+
|
|
3410
|
+
OUTPUT: a ``GradedModularFormElement`` corresponding to `f_1 + f_2 + ... + f_n`
|
|
3411
|
+
|
|
3412
|
+
TESTS::
|
|
3413
|
+
|
|
3414
|
+
sage: M = ModularFormsRing(1)
|
|
3415
|
+
sage: E4 = ModularForms(1,4).0
|
|
3416
|
+
sage: M({6:E4})
|
|
3417
|
+
Traceback (most recent call last):
|
|
3418
|
+
...
|
|
3419
|
+
ValueError: at least one key (6) of the defining dictionary does not correspond to the weight of its value (1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)). Real weight: 4
|
|
3420
|
+
sage: M({4:'f'})
|
|
3421
|
+
Traceback (most recent call last):
|
|
3422
|
+
...
|
|
3423
|
+
ValueError: at least one value (f) of the defining dictionary is not a `ModularFormElement`
|
|
3424
|
+
sage: M({4.:E4})
|
|
3425
|
+
Traceback (most recent call last):
|
|
3426
|
+
...
|
|
3427
|
+
ValueError: at least one key (4.00000000000000) of the defining dictionary is not an integer
|
|
3428
|
+
sage: M({0:E4})
|
|
3429
|
+
Traceback (most recent call last):
|
|
3430
|
+
...
|
|
3431
|
+
TypeError: no canonical coercion from Modular Forms space of dimension 1 for Modular Group SL(2,Z) of weight 4 over Rational Field to Rational Field
|
|
3432
|
+
sage: M([E4, x]) # needs sage.symbolic
|
|
3433
|
+
Traceback (most recent call last):
|
|
3434
|
+
...
|
|
3435
|
+
TypeError: no canonical coercion from Symbolic Ring to Rational Field
|
|
3436
|
+
sage: M([E4, ModularForms(3, 6).0])
|
|
3437
|
+
Traceback (most recent call last):
|
|
3438
|
+
...
|
|
3439
|
+
ValueError: the group and/or the base ring of at least one modular form (q - 6*q^2 + 9*q^3 + 4*q^4 + 6*q^5 + O(q^6)) is not consistent with the base space
|
|
3440
|
+
sage: M({4:E4, 6:ModularForms(3, 6).0})
|
|
3441
|
+
Traceback (most recent call last):
|
|
3442
|
+
...
|
|
3443
|
+
ValueError: the group and/or the base ring of at least one modular form (q - 6*q^2 + 9*q^3 + 4*q^4 + 6*q^5 + O(q^6)) is not consistent with the base space
|
|
3444
|
+
sage: M = ModularFormsRing(Gamma0(2))
|
|
3445
|
+
sage: E4 = ModularForms(1, 4).0
|
|
3446
|
+
sage: M(E4)[4].parent()
|
|
3447
|
+
Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(2) of weight 4 over Rational Field
|
|
3448
|
+
sage: M = ModularFormsRing(Gamma1(3), base_ring=GF(7))
|
|
3449
|
+
sage: E6 = ModularForms(1, 6, base_ring=GF(7)).0
|
|
3450
|
+
sage: M(E6)[6].parent()
|
|
3451
|
+
Modular Forms space of dimension 3 for Congruence Subgroup Gamma1(3) of weight 6 over Finite Field of size 7
|
|
3452
|
+
"""
|
|
3453
|
+
forms_dictionary = {}
|
|
3454
|
+
if isinstance(forms_datum, dict):
|
|
3455
|
+
for k, f in forms_datum.items():
|
|
3456
|
+
if isinstance(k, (int, Integer)):
|
|
3457
|
+
k = ZZ(k)
|
|
3458
|
+
if k == 0:
|
|
3459
|
+
forms_dictionary[k] = parent.base_ring().coerce(f)
|
|
3460
|
+
elif isinstance(f, ModularFormElement):
|
|
3461
|
+
if f.weight() == k:
|
|
3462
|
+
if parent.group().is_subgroup(f.group()) and parent.base_ring().has_coerce_map_from(f.base_ring()):
|
|
3463
|
+
M = parent.modular_forms_of_weight(f.weight()).change_ring(parent.base_ring())
|
|
3464
|
+
forms_dictionary[k] = M(f)
|
|
3465
|
+
else:
|
|
3466
|
+
raise ValueError('the group and/or the base ring of at least one modular form (%s) is not consistent with the base space' % (f))
|
|
3467
|
+
else:
|
|
3468
|
+
raise ValueError('at least one key (%s) of the defining dictionary does not correspond to the weight of its value (%s). Real weight: %s' % (k, f, f.weight()))
|
|
3469
|
+
else:
|
|
3470
|
+
raise ValueError('at least one value (%s) of the defining dictionary is not a `ModularFormElement`' % (f))
|
|
3471
|
+
else:
|
|
3472
|
+
raise ValueError('at least one key (%s) of the defining dictionary is not an integer' % (k))
|
|
3473
|
+
elif isinstance(forms_datum, list):
|
|
3474
|
+
for f in forms_datum:
|
|
3475
|
+
if isinstance(f, ModularFormElement):
|
|
3476
|
+
chi = f.character(compute=False)
|
|
3477
|
+
if (chi is not None) and (not chi.is_trivial()):
|
|
3478
|
+
raise NotImplementedError("graded modular forms for non-trivial characters is not yet implemented")
|
|
3479
|
+
if parent.group().is_subgroup(f.group()) and parent.base_ring().has_coerce_map_from(f.base_ring()):
|
|
3480
|
+
M = parent.modular_forms_of_weight(f.weight()).change_ring(parent.base_ring())
|
|
3481
|
+
forms_dictionary[f.weight()] = M(forms_dictionary.get(f.weight(), 0) + f)
|
|
3482
|
+
else:
|
|
3483
|
+
raise ValueError('the group and/or the base ring of at least one modular form (%s) is not consistent with the base space' % (f))
|
|
3484
|
+
else:
|
|
3485
|
+
forms_dictionary[ZZ.zero()] = parent.base_ring().coerce(f)
|
|
3486
|
+
else:
|
|
3487
|
+
raise TypeError('the defining data structure should be a list or a dictionary')
|
|
3488
|
+
self._forms_dictionary = {k: f for k, f in forms_dictionary.items() if not f.is_zero()} # remove the zero values
|
|
3489
|
+
Element.__init__(self, parent)
|
|
3490
|
+
|
|
3491
|
+
def __bool__(self) -> bool:
|
|
3492
|
+
r"""
|
|
3493
|
+
Return "True" if ``self`` is nonzero and "False" otherwise.
|
|
3494
|
+
|
|
3495
|
+
EXAMPLES::
|
|
3496
|
+
|
|
3497
|
+
sage: M = ModularFormsRing(1)
|
|
3498
|
+
sage: bool(M(0))
|
|
3499
|
+
False
|
|
3500
|
+
sage: bool(M(1))
|
|
3501
|
+
True
|
|
3502
|
+
sage: bool(M(ModularForms(1,6).0))
|
|
3503
|
+
True
|
|
3504
|
+
"""
|
|
3505
|
+
return bool(self._forms_dictionary)
|
|
3506
|
+
|
|
3507
|
+
def is_zero(self) -> bool:
|
|
3508
|
+
r"""
|
|
3509
|
+
Return "True" if the graded form is 0 and "False" otherwise.
|
|
3510
|
+
|
|
3511
|
+
EXAMPLES::
|
|
3512
|
+
|
|
3513
|
+
sage: M = ModularFormsRing(1)
|
|
3514
|
+
sage: M(0).is_zero()
|
|
3515
|
+
True
|
|
3516
|
+
sage: M(1/2).is_zero()
|
|
3517
|
+
False
|
|
3518
|
+
sage: E6 = M.1
|
|
3519
|
+
sage: M(E6).is_zero()
|
|
3520
|
+
False
|
|
3521
|
+
"""
|
|
3522
|
+
return not self
|
|
3523
|
+
|
|
3524
|
+
def is_one(self) -> bool:
|
|
3525
|
+
r"""
|
|
3526
|
+
Return "True" if the graded form is 1 and "False" otherwise.
|
|
3527
|
+
|
|
3528
|
+
EXAMPLES::
|
|
3529
|
+
|
|
3530
|
+
sage: M = ModularFormsRing(1)
|
|
3531
|
+
sage: M(1).is_one()
|
|
3532
|
+
True
|
|
3533
|
+
sage: M(2).is_one()
|
|
3534
|
+
False
|
|
3535
|
+
sage: E6 = M.0
|
|
3536
|
+
sage: E6.is_one()
|
|
3537
|
+
False
|
|
3538
|
+
"""
|
|
3539
|
+
return len(self._forms_dictionary) == 1 and self[0].is_one()
|
|
3540
|
+
|
|
3541
|
+
def group(self):
|
|
3542
|
+
r"""
|
|
3543
|
+
Return the group for which ``self`` is a modular form.
|
|
3544
|
+
|
|
3545
|
+
EXAMPLES::
|
|
3546
|
+
|
|
3547
|
+
sage: M = ModularFormsRing(1)
|
|
3548
|
+
sage: E4 = M.0
|
|
3549
|
+
sage: E4.group()
|
|
3550
|
+
Modular Group SL(2,Z)
|
|
3551
|
+
sage: M5 = ModularFormsRing(Gamma1(5))
|
|
3552
|
+
sage: f = M5(ModularForms(Gamma1(5)).0);
|
|
3553
|
+
sage: f.group()
|
|
3554
|
+
Congruence Subgroup Gamma1(5)
|
|
3555
|
+
"""
|
|
3556
|
+
return self.parent().group()
|
|
3557
|
+
|
|
3558
|
+
def q_expansion(self, prec=None):
|
|
3559
|
+
r"""
|
|
3560
|
+
Return the `q`-expansion of the graded modular form up to precision
|
|
3561
|
+
``prec`` (default: 6).
|
|
3562
|
+
|
|
3563
|
+
An alias of this method is ``qexp``.
|
|
3564
|
+
|
|
3565
|
+
EXAMPLES::
|
|
3566
|
+
|
|
3567
|
+
sage: M = ModularFormsRing(1)
|
|
3568
|
+
sage: zer = M(0); zer.q_expansion()
|
|
3569
|
+
0
|
|
3570
|
+
sage: M(5/7).q_expansion()
|
|
3571
|
+
5/7
|
|
3572
|
+
sage: E4 = M.0; E4
|
|
3573
|
+
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
|
|
3574
|
+
sage: E6 = M.1; E6
|
|
3575
|
+
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)
|
|
3576
|
+
sage: F = E4 + E6; F
|
|
3577
|
+
2 - 264*q - 14472*q^2 - 116256*q^3 - 515208*q^4 - 1545264*q^5 + O(q^6)
|
|
3578
|
+
sage: F.q_expansion()
|
|
3579
|
+
2 - 264*q - 14472*q^2 - 116256*q^3 - 515208*q^4 - 1545264*q^5 + O(q^6)
|
|
3580
|
+
sage: F.q_expansion(10)
|
|
3581
|
+
2 - 264*q - 14472*q^2 - 116256*q^3 - 515208*q^4 - 1545264*q^5 - 3997728*q^6 - 8388672*q^7 - 16907400*q^8 - 29701992*q^9 + O(q^10)
|
|
3582
|
+
"""
|
|
3583
|
+
# We sum the two cases: (weight 0) + (weights k \neq 0)
|
|
3584
|
+
Pow = PowerSeriesRing(self.base_ring(), name=defaults.DEFAULT_VARIABLE)
|
|
3585
|
+
return Pow(self._forms_dictionary.get(0, Pow.zero())) + sum(f.q_expansion(prec) for k, f in self._forms_dictionary.items() if k != 0)
|
|
3586
|
+
|
|
3587
|
+
qexp = q_expansion # alias
|
|
3588
|
+
|
|
3589
|
+
def coefficients(self, X):
|
|
3590
|
+
r"""
|
|
3591
|
+
Return the coefficients `a_n` of the `q`-expansion of this modular form.
|
|
3592
|
+
|
|
3593
|
+
INPUT:
|
|
3594
|
+
|
|
3595
|
+
- ``X`` -- an iterable or an integer. If ``X`` is iterable, a list
|
|
3596
|
+
containing all `a_{X_i}` is returned. If ``X`` is an integer, it must
|
|
3597
|
+
be positive, in which case the coefficients `a_1` to `a_X` are
|
|
3598
|
+
returned in a list.
|
|
3599
|
+
|
|
3600
|
+
EXAMPLES::
|
|
3601
|
+
|
|
3602
|
+
sage: M = ModularFormsRing(1)
|
|
3603
|
+
sage: E4 = M.0; E6 = M.1
|
|
3604
|
+
sage: F = E4 + E6
|
|
3605
|
+
sage: F.coefficients([0,1,3,6])
|
|
3606
|
+
[2, -264, -116256, -3997728]
|
|
3607
|
+
sage: F.coefficients(10)
|
|
3608
|
+
[-264, -14472, -116256, -515208, -1545264, -3997728, -8388672, -16907400, -29701992, -51719472]
|
|
3609
|
+
sage: assert _ == F.coefficients(range(1, 11)) == list(F.qexp(11))[1:]
|
|
3610
|
+
|
|
3611
|
+
::
|
|
3612
|
+
|
|
3613
|
+
sage: F = ModularFormsRing(13).0
|
|
3614
|
+
sage: (F^3).coefficients(range(10, 20))
|
|
3615
|
+
[22812, 36552, 57680, 85686, 126744, 177408, 249246, 332172, 448926, 575736]
|
|
3616
|
+
"""
|
|
3617
|
+
if isinstance(X, (int, Integer)):
|
|
3618
|
+
return list(self.q_expansion(X + 1))[1:X + 1]
|
|
3619
|
+
prec = max(X)
|
|
3620
|
+
v = self.q_expansion(prec + 1)
|
|
3621
|
+
return [v[x] for x in X]
|
|
3622
|
+
|
|
3623
|
+
def _repr_(self):
|
|
3624
|
+
r"""
|
|
3625
|
+
The string representation of ``self``.
|
|
3626
|
+
|
|
3627
|
+
EXAMPLES::
|
|
3628
|
+
|
|
3629
|
+
sage: M = ModularFormsRing(Gamma0(7))
|
|
3630
|
+
sage: m = ModularForms(Gamma0(7), 14)
|
|
3631
|
+
sage: f = m.8
|
|
3632
|
+
sage: F = M(f)
|
|
3633
|
+
sage: F # indirect doctest
|
|
3634
|
+
q + 8193*q^2 + 1594324*q^3 + 67117057*q^4 + 1220703126*q^5 + O(q^6)
|
|
3635
|
+
"""
|
|
3636
|
+
return str(self.q_expansion())
|
|
3637
|
+
|
|
3638
|
+
def _latex_(self):
|
|
3639
|
+
r"""
|
|
3640
|
+
Return a latex representation of ``self``.
|
|
3641
|
+
|
|
3642
|
+
TESTS::
|
|
3643
|
+
|
|
3644
|
+
sage: M = ModularFormsRing(1)
|
|
3645
|
+
sage: latex(M.0)
|
|
3646
|
+
1 + 240 q + 2160 q^{2} + 6720 q^{3} + 17520 q^{4} + 30240 q^{5} + O(q^{6})
|
|
3647
|
+
"""
|
|
3648
|
+
return self.q_expansion()._latex_()
|
|
3649
|
+
|
|
3650
|
+
def __getitem__(self, weight):
|
|
3651
|
+
r"""
|
|
3652
|
+
Return the homogeneous component of the given graded modular form.
|
|
3653
|
+
|
|
3654
|
+
INPUT:
|
|
3655
|
+
|
|
3656
|
+
- ``weight`` -- integer corresponding to the weight of the
|
|
3657
|
+
homogeneous component of the given graded modular form
|
|
3658
|
+
|
|
3659
|
+
EXAMPLES::
|
|
3660
|
+
|
|
3661
|
+
sage: M = ModularFormsRing(1)
|
|
3662
|
+
sage: f4 = ModularForms(1, 4).0; f6 = ModularForms(1, 6).0; f8 = ModularForms(1, 8).0
|
|
3663
|
+
sage: F = M(f4) + M(f6) + M(f8)
|
|
3664
|
+
sage: F[4] # indirect doctest
|
|
3665
|
+
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
|
|
3666
|
+
sage: F[6] # indirect doctest
|
|
3667
|
+
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)
|
|
3668
|
+
sage: F[8] # indirect doctest
|
|
3669
|
+
1 + 480*q + 61920*q^2 + 1050240*q^3 + 7926240*q^4 + 37500480*q^5 + O(q^6)
|
|
3670
|
+
sage: F[10] # indirect doctest
|
|
3671
|
+
0
|
|
3672
|
+
sage: F.homogeneous_component(4)
|
|
3673
|
+
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
|
|
3674
|
+
|
|
3675
|
+
TESTS::
|
|
3676
|
+
|
|
3677
|
+
sage: M = ModularFormsRing(1)
|
|
3678
|
+
sage: f = M.0
|
|
3679
|
+
sage: f['a']
|
|
3680
|
+
Traceback (most recent call last):
|
|
3681
|
+
...
|
|
3682
|
+
KeyError: 'the weight must be an integer'
|
|
3683
|
+
sage: f[-1]
|
|
3684
|
+
Traceback (most recent call last):
|
|
3685
|
+
...
|
|
3686
|
+
ValueError: the weight must be nonnegative
|
|
3687
|
+
"""
|
|
3688
|
+
if not isinstance(weight, (int, Integer)):
|
|
3689
|
+
raise KeyError("the weight must be an integer")
|
|
3690
|
+
if weight < 0:
|
|
3691
|
+
raise ValueError("the weight must be nonnegative")
|
|
3692
|
+
return self._forms_dictionary.get(weight, self.parent().zero())
|
|
3693
|
+
homogeneous_component = __getitem__ # alias
|
|
3694
|
+
|
|
3695
|
+
def __call__(self, x, prec=None):
|
|
3696
|
+
r"""
|
|
3697
|
+
Evaluate the `q`-expansion of this graded modular form at x.
|
|
3698
|
+
|
|
3699
|
+
EXAMPLES::
|
|
3700
|
+
|
|
3701
|
+
sage: M = ModularFormsRing(1)
|
|
3702
|
+
sage: f4 = ModularForms(1, 4).0; f6 = ModularForms(1, 6).0; f8 = ModularForms(1, 8).0
|
|
3703
|
+
sage: F = M(f4) + M(f6) + M(f8); F # indirect doctest
|
|
3704
|
+
3 + 216*q + 47448*q^2 + 933984*q^3 + 7411032*q^4 + 35955216*q^5 + O(q^6)
|
|
3705
|
+
sage: q = F.q_expansion().parent().gen()
|
|
3706
|
+
sage: F(q^2) # indirect doctest
|
|
3707
|
+
3 + 216*q^2 + 47448*q^4 + 933984*q^6 + 7411032*q^8 + 35955216*q^10 + O(q^12)
|
|
3708
|
+
sage: G = M(113/19)
|
|
3709
|
+
sage: G(q) # indirect doctest
|
|
3710
|
+
113/19
|
|
3711
|
+
"""
|
|
3712
|
+
return self.q_expansion(prec)(x)
|
|
3713
|
+
|
|
3714
|
+
def _add_(self, other):
|
|
3715
|
+
r"""
|
|
3716
|
+
Addition of two ``GradedModularFormElement``.
|
|
3717
|
+
|
|
3718
|
+
TESTS::
|
|
3719
|
+
|
|
3720
|
+
sage: M = ModularFormsRing(1)
|
|
3721
|
+
sage: f4 = ModularForms(1, 4).0; f6 = ModularForms(1, 6).0; f8 = ModularForms(1, 8).0
|
|
3722
|
+
sage: F4 = M(f4); F6 = M(f6); F8 = M(f8)
|
|
3723
|
+
sage: F4 + F6 # indirect doctest
|
|
3724
|
+
2 - 264*q - 14472*q^2 - 116256*q^3 - 515208*q^4 - 1545264*q^5 + O(q^6)
|
|
3725
|
+
sage: F4 + f6 #coercion # indirect doctest
|
|
3726
|
+
2 - 264*q - 14472*q^2 - 116256*q^3 - 515208*q^4 - 1545264*q^5 + O(q^6)
|
|
3727
|
+
sage: F = F4 + F6 + F8; F # indirect doctest
|
|
3728
|
+
3 + 216*q + 47448*q^2 + 933984*q^3 + 7411032*q^4 + 35955216*q^5 + O(q^6)
|
|
3729
|
+
sage: F.parent()
|
|
3730
|
+
Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field
|
|
3731
|
+
sage: g = ModularForms(Gamma1(7), 12).0
|
|
3732
|
+
sage: F+g #sum of two forms of different type
|
|
3733
|
+
Traceback (most recent call last):
|
|
3734
|
+
...
|
|
3735
|
+
TypeError: unsupported operand parent(s) for +: 'Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field' and 'Modular Forms space of dimension 25 for Congruence Subgroup Gamma1(7) of weight 12 over Rational Field'
|
|
3736
|
+
"""
|
|
3737
|
+
GM = self.__class__
|
|
3738
|
+
f_self = self._forms_dictionary
|
|
3739
|
+
f_other = other._forms_dictionary
|
|
3740
|
+
f_sum = {k: f_self.get(k, 0) + f_other.get(k, 0) for k in set(f_self) | set(f_other)}
|
|
3741
|
+
return GM(self.parent(), f_sum)
|
|
3742
|
+
|
|
3743
|
+
def __neg__(self):
|
|
3744
|
+
r"""
|
|
3745
|
+
The negation of ``self``.
|
|
3746
|
+
|
|
3747
|
+
TESTS::
|
|
3748
|
+
|
|
3749
|
+
sage: M = ModularFormsRing(1)
|
|
3750
|
+
sage: F4 = M(ModularForms(1, 4).0); F6 = M(ModularForms(1, 6).0);
|
|
3751
|
+
sage: -F4 # indirect doctest
|
|
3752
|
+
-1 - 240*q - 2160*q^2 - 6720*q^3 - 17520*q^4 - 30240*q^5 + O(q^6)
|
|
3753
|
+
sage: F4 - F6 # indirect doctest
|
|
3754
|
+
744*q + 18792*q^2 + 129696*q^3 + 550248*q^4 + 1605744*q^5 + O(q^6)
|
|
3755
|
+
"""
|
|
3756
|
+
GM = self.__class__
|
|
3757
|
+
f_self = self._forms_dictionary
|
|
3758
|
+
minus_self = {k: -f for k, f in f_self.items()}
|
|
3759
|
+
return GM(self.parent(), minus_self)
|
|
3760
|
+
|
|
3761
|
+
def _mul_(self, other):
|
|
3762
|
+
r"""
|
|
3763
|
+
Multiplication of two ``GradedModularFormElement``.
|
|
3764
|
+
|
|
3765
|
+
INPUT:
|
|
3766
|
+
|
|
3767
|
+
- ``other`` -- a ``GradedModularFormElement``
|
|
3768
|
+
|
|
3769
|
+
OUTPUT: the ``GradedModularFormElement`` corresponding to the
|
|
3770
|
+
multiplication of ``self`` and ``other``.
|
|
3771
|
+
|
|
3772
|
+
TESTS::
|
|
3773
|
+
|
|
3774
|
+
sage: M = ModularFormsRing(1)
|
|
3775
|
+
sage: F4 = M.0; F6 = M.1;
|
|
3776
|
+
sage: F4*F6 # indirect doctest
|
|
3777
|
+
1 - 264*q - 135432*q^2 - 5196576*q^3 - 69341448*q^4 - 515625264*q^5 + O(q^6)
|
|
3778
|
+
|
|
3779
|
+
sage: E4 = EisensteinForms(1, 4).0
|
|
3780
|
+
sage: E4^2
|
|
3781
|
+
1 + 480*q + 61920*q^2 + 1050240*q^3 + 7926240*q^4 + 37500480*q^5 + O(q^6)
|
|
3782
|
+
|
|
3783
|
+
This shows that the issue at :issue:`35932` is fixed::
|
|
3784
|
+
|
|
3785
|
+
sage: (F4 + M(1))^2
|
|
3786
|
+
4 + 960*q + 66240*q^2 + 1063680*q^3 + 7961280*q^4 + 37560960*q^5 + O(q^6)
|
|
3787
|
+
"""
|
|
3788
|
+
from collections import defaultdict
|
|
3789
|
+
|
|
3790
|
+
GM = self.__class__
|
|
3791
|
+
f_self = self._forms_dictionary
|
|
3792
|
+
f_other = other._forms_dictionary
|
|
3793
|
+
f_mul = defaultdict(int)
|
|
3794
|
+
|
|
3795
|
+
for k_self in f_self:
|
|
3796
|
+
for k_other in f_other:
|
|
3797
|
+
f_mul[k_self + k_other] += f_self[k_self] * f_other[k_other]
|
|
3798
|
+
|
|
3799
|
+
return GM(self.parent(), f_mul)
|
|
3800
|
+
|
|
3801
|
+
def _lmul_(self, c):
|
|
3802
|
+
r"""
|
|
3803
|
+
The left action of the base ring on ``self``.
|
|
3804
|
+
|
|
3805
|
+
INPUT:
|
|
3806
|
+
|
|
3807
|
+
- ``c`` -- an element of the base ring of self
|
|
3808
|
+
|
|
3809
|
+
OUTPUT: a ``GradedModularFormElement``
|
|
3810
|
+
|
|
3811
|
+
TESTS::
|
|
3812
|
+
|
|
3813
|
+
sage: M = ModularFormsRing(1)
|
|
3814
|
+
sage: E4 = M(ModularForms(1, 4).0); E4
|
|
3815
|
+
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
|
|
3816
|
+
sage: 42 * E4 # indirect doctest
|
|
3817
|
+
42 + 10080*q + 90720*q^2 + 282240*q^3 + 735840*q^4 + 1270080*q^5 + O(q^6)
|
|
3818
|
+
sage: 1/5 * E4 # indirect doctest
|
|
3819
|
+
1/5 + 48*q + 432*q^2 + 1344*q^3 + 3504*q^4 + 6048*q^5 + O(q^6)
|
|
3820
|
+
sage: I*E4 # indirect doctest
|
|
3821
|
+
Traceback (most recent call last):
|
|
3822
|
+
...
|
|
3823
|
+
TypeError: unsupported operand parent(s) for *: 'Number Field in I with defining polynomial x^2 + 1 with I = 1*I' and 'Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field'
|
|
3824
|
+
"""
|
|
3825
|
+
GM = self.__class__
|
|
3826
|
+
f_self = self._forms_dictionary
|
|
3827
|
+
f_mul = {k: c * f for k, f in f_self.items()}
|
|
3828
|
+
return GM(self.parent(), f_mul)
|
|
3829
|
+
|
|
3830
|
+
def _richcmp_(self, other, op):
|
|
3831
|
+
r"""
|
|
3832
|
+
Compare ``self`` with ``other``.
|
|
3833
|
+
|
|
3834
|
+
TESTS::
|
|
3835
|
+
|
|
3836
|
+
sage: M = ModularFormsRing(1)
|
|
3837
|
+
sage: M(1) == M(1)
|
|
3838
|
+
True
|
|
3839
|
+
sage: M(1) == M(2)
|
|
3840
|
+
False
|
|
3841
|
+
sage: E4 = M.0
|
|
3842
|
+
sage: E4 == E4
|
|
3843
|
+
True
|
|
3844
|
+
sage: E6 = M.1
|
|
3845
|
+
sage: E4 == E6
|
|
3846
|
+
False
|
|
3847
|
+
sage: E4 != E6
|
|
3848
|
+
True
|
|
3849
|
+
sage: E4 < E6
|
|
3850
|
+
Traceback (most recent call last):
|
|
3851
|
+
...
|
|
3852
|
+
TypeError: invalid comparison between modular forms ring elements
|
|
3853
|
+
sage: E4 > 6
|
|
3854
|
+
Traceback (most recent call last):
|
|
3855
|
+
...
|
|
3856
|
+
TypeError: invalid comparison between modular forms ring elements
|
|
3857
|
+
sage: E4 <= E6
|
|
3858
|
+
Traceback (most recent call last):
|
|
3859
|
+
...
|
|
3860
|
+
TypeError: invalid comparison between modular forms ring elements
|
|
3861
|
+
"""
|
|
3862
|
+
if op != op_EQ and op != op_NE:
|
|
3863
|
+
raise TypeError('invalid comparison between modular forms ring elements')
|
|
3864
|
+
return richcmp(self._forms_dictionary, other._forms_dictionary, op)
|
|
3865
|
+
|
|
3866
|
+
def weight(self):
|
|
3867
|
+
r"""
|
|
3868
|
+
Return the weight of the given form if it is homogeneous (i.e. a modular form).
|
|
3869
|
+
|
|
3870
|
+
EXAMPLES::
|
|
3871
|
+
|
|
3872
|
+
sage: D = ModularForms(1,12).0; M = ModularFormsRing(1)
|
|
3873
|
+
sage: M(D).weight()
|
|
3874
|
+
12
|
|
3875
|
+
sage: M.zero().weight()
|
|
3876
|
+
0
|
|
3877
|
+
sage: e4 = ModularForms(1,4).0
|
|
3878
|
+
sage: (M(D)+e4).weight()
|
|
3879
|
+
Traceback (most recent call last):
|
|
3880
|
+
...
|
|
3881
|
+
ValueError: the given graded form is not homogeneous (not a modular form)
|
|
3882
|
+
"""
|
|
3883
|
+
if self.is_homogeneous():
|
|
3884
|
+
if self.is_zero():
|
|
3885
|
+
return ZZ.zero()
|
|
3886
|
+
return next(iter(self._forms_dictionary))
|
|
3887
|
+
else:
|
|
3888
|
+
raise ValueError("the given graded form is not homogeneous (not a modular form)")
|
|
3889
|
+
|
|
3890
|
+
def weights_list(self):
|
|
3891
|
+
r"""
|
|
3892
|
+
Return the list of the weights of all the homogeneous components of the
|
|
3893
|
+
given graded modular form.
|
|
3894
|
+
|
|
3895
|
+
EXAMPLES::
|
|
3896
|
+
|
|
3897
|
+
sage: M = ModularFormsRing(1)
|
|
3898
|
+
sage: f4 = ModularForms(1, 4).0; f6 = ModularForms(1, 6).0; f8 = ModularForms(1, 8).0
|
|
3899
|
+
sage: F4 = M(f4); F6 = M(f6); F8 = M(f8)
|
|
3900
|
+
sage: F = F4 + F6 + F8
|
|
3901
|
+
sage: F.weights_list()
|
|
3902
|
+
[4, 6, 8]
|
|
3903
|
+
sage: M(0).weights_list()
|
|
3904
|
+
[0]
|
|
3905
|
+
"""
|
|
3906
|
+
if self.is_zero():
|
|
3907
|
+
return [ZZ.zero()]
|
|
3908
|
+
return sorted(self._forms_dictionary)
|
|
3909
|
+
|
|
3910
|
+
def is_homogeneous(self) -> bool:
|
|
3911
|
+
r"""
|
|
3912
|
+
Return ``True`` if the graded modular form is homogeneous, i.e. if it
|
|
3913
|
+
is a modular forms of a certain weight.
|
|
3914
|
+
|
|
3915
|
+
An alias of this method is ``is_modular_form``
|
|
3916
|
+
|
|
3917
|
+
EXAMPLES::
|
|
3918
|
+
|
|
3919
|
+
sage: M = ModularFormsRing(1)
|
|
3920
|
+
sage: E4 = M.0; E6 = M.1;
|
|
3921
|
+
sage: E4.is_homogeneous()
|
|
3922
|
+
True
|
|
3923
|
+
sage: F = E4 + E6 # Not a modular form
|
|
3924
|
+
sage: F.is_homogeneous()
|
|
3925
|
+
False
|
|
3926
|
+
"""
|
|
3927
|
+
return len(self._forms_dictionary) <= 1
|
|
3928
|
+
is_modular_form = is_homogeneous # alias
|
|
3929
|
+
|
|
3930
|
+
def _homogeneous_to_polynomial(self, names, gens):
|
|
3931
|
+
r"""
|
|
3932
|
+
Return a polynomial `P(x_0,..., x_n)` corresponding to the given homogeneous graded form.
|
|
3933
|
+
|
|
3934
|
+
Each variable `x_i` of the returned polynomial correspond to a generator `g_i` of the
|
|
3935
|
+
list ``gens`` (following the order of the list)
|
|
3936
|
+
|
|
3937
|
+
INPUT:
|
|
3938
|
+
|
|
3939
|
+
- ``names`` -- list or tuple of names (strings), or a comma separated
|
|
3940
|
+
string
|
|
3941
|
+
- ``gens`` -- (list) a list of generator of ``self``
|
|
3942
|
+
|
|
3943
|
+
OUTPUT: a polynomial in the variables ``names``
|
|
3944
|
+
|
|
3945
|
+
TESTS::
|
|
3946
|
+
|
|
3947
|
+
sage: M = ModularFormsRing(1)
|
|
3948
|
+
sage: gens = M.gen_forms()
|
|
3949
|
+
sage: M.0._homogeneous_to_polynomial('x', gens)
|
|
3950
|
+
x0
|
|
3951
|
+
sage: M.1._homogeneous_to_polynomial('E4, E6', gens)
|
|
3952
|
+
E6
|
|
3953
|
+
sage: M(1/2).to_polynomial()
|
|
3954
|
+
1/2
|
|
3955
|
+
sage: p = ((M.0)**3 + (M.1)**2)._homogeneous_to_polynomial('x', gens); p
|
|
3956
|
+
x0^3 + x1^2
|
|
3957
|
+
sage: M(p) == (M.0)**3 + (M.1)**2
|
|
3958
|
+
True
|
|
3959
|
+
sage: (M.0 + M.1)._homogeneous_to_polynomial('x', gens)
|
|
3960
|
+
Traceback (most recent call last):
|
|
3961
|
+
...
|
|
3962
|
+
ValueError: the given graded form is not homogeneous (not a modular form)
|
|
3963
|
+
sage: E4 = ModularForms(1, 4, GF(7)).0
|
|
3964
|
+
sage: M = ModularFormsRing(1, GF(7))
|
|
3965
|
+
sage: M(E4).to_polynomial()
|
|
3966
|
+
Traceback (most recent call last):
|
|
3967
|
+
...
|
|
3968
|
+
NotImplementedError: conversion to polynomial are not implemented if the base ring is not Q
|
|
3969
|
+
"""
|
|
3970
|
+
if not self.base_ring() == QQ:
|
|
3971
|
+
raise NotImplementedError("conversion to polynomial are not implemented if the base ring is not Q")
|
|
3972
|
+
M = self.parent()
|
|
3973
|
+
k = self.weight() # only if self is homogeneous
|
|
3974
|
+
poly_parent = M.polynomial_ring(names, gens)
|
|
3975
|
+
if k == 0:
|
|
3976
|
+
return poly_parent(self[k])
|
|
3977
|
+
|
|
3978
|
+
# create the set of "weighted exponents" and compute sturm bound
|
|
3979
|
+
weights_of_generators = [gen.weight() for gen in gens]
|
|
3980
|
+
W = WeightedIntegerVectors(k, weights_of_generators).list()
|
|
3981
|
+
sturm_bound = self.group().sturm_bound(k)
|
|
3982
|
+
|
|
3983
|
+
# initialize the matrix of coefficients
|
|
3984
|
+
matrix_datum = []
|
|
3985
|
+
|
|
3986
|
+
# form the matrix of coefficients and list the monomials of weight k
|
|
3987
|
+
monomial_forms = [prod(M(gen) ** exp for exp, gen in zip(exps, gens)) for exps in W]
|
|
3988
|
+
monomial_polys = [prod(poly_gen ** exp for exp, poly_gen in zip(exps, poly_parent.gens())) for exps in W]
|
|
3989
|
+
matrix_datum = M._to_matrix(monomial_forms, prec=sturm_bound)
|
|
3990
|
+
mat = Matrix(matrix_datum).transpose()
|
|
3991
|
+
|
|
3992
|
+
# initialize the column vector of the coefficients of self
|
|
3993
|
+
coef_self = vector(self[k].coefficients(range(sturm_bound + 1))).column()
|
|
3994
|
+
|
|
3995
|
+
# solve the linear system: mat * X = coef_self
|
|
3996
|
+
soln = mat.solve_right(coef_self)
|
|
3997
|
+
|
|
3998
|
+
# initialize the polynomial associated to self
|
|
3999
|
+
poly = poly_parent.zero()
|
|
4000
|
+
for i, p in enumerate(monomial_polys):
|
|
4001
|
+
poly += soln[i, 0] * p
|
|
4002
|
+
return poly
|
|
4003
|
+
|
|
4004
|
+
def to_polynomial(self, names='x', gens=None):
|
|
4005
|
+
r"""
|
|
4006
|
+
Return a polynomial `P(x_0,..., x_n)` such that `P(g_0,..., g_n)` is equal to ``self``
|
|
4007
|
+
where `g_0, ..., g_n` is a list of generators of the parent.
|
|
4008
|
+
|
|
4009
|
+
INPUT:
|
|
4010
|
+
|
|
4011
|
+
- ``names`` -- list or tuple of names (strings), or a comma separated
|
|
4012
|
+
string; corresponds to the names of the variables
|
|
4013
|
+
- ``gens`` -- (default: ``None``) a list of generator of the parent of
|
|
4014
|
+
``self``. If set to ``None``, the list returned by
|
|
4015
|
+
:meth:`~sage.modular.modform.find_generator.ModularFormsRing.gen_forms`
|
|
4016
|
+
is used instead
|
|
4017
|
+
|
|
4018
|
+
OUTPUT: a polynomial in the variables ``names``
|
|
4019
|
+
|
|
4020
|
+
EXAMPLES::
|
|
4021
|
+
|
|
4022
|
+
sage: M = ModularFormsRing(1)
|
|
4023
|
+
sage: (M.0 + M.1).to_polynomial()
|
|
4024
|
+
x1 + x0
|
|
4025
|
+
sage: (M.0^10 + M.0 * M.1).to_polynomial()
|
|
4026
|
+
x0^10 + x0*x1
|
|
4027
|
+
|
|
4028
|
+
This method is not necessarily the inverse of
|
|
4029
|
+
:meth:`~sage.modular.modform.ring.ModularFormsRing.from_polynomial` since there may be some
|
|
4030
|
+
relations between the generators of the modular forms ring::
|
|
4031
|
+
|
|
4032
|
+
sage: M = ModularFormsRing(Gamma0(6))
|
|
4033
|
+
sage: P.<x0,x1,x2> = M.polynomial_ring()
|
|
4034
|
+
sage: M.from_polynomial(x1^2).to_polynomial()
|
|
4035
|
+
x0*x2 + 2*x1*x2 + 11*x2^2
|
|
4036
|
+
"""
|
|
4037
|
+
M = self.parent()
|
|
4038
|
+
if gens is None:
|
|
4039
|
+
gens = M.gen_forms()
|
|
4040
|
+
|
|
4041
|
+
# sum the polynomial of each homogeneous part
|
|
4042
|
+
return sum(M(self[k])._homogeneous_to_polynomial(names, gens) for k in self.weights_list())
|
|
4043
|
+
|
|
4044
|
+
def serre_derivative(self):
|
|
4045
|
+
r"""
|
|
4046
|
+
Return the Serre derivative of the given graded modular form.
|
|
4047
|
+
|
|
4048
|
+
If ``self`` is a modular form of weight `k`, then the returned modular
|
|
4049
|
+
form will be of weight `k + 2`. If the form is not homogeneous, then
|
|
4050
|
+
this method sums the Serre derivative of each homogeneous component.
|
|
4051
|
+
|
|
4052
|
+
EXAMPLES::
|
|
4053
|
+
|
|
4054
|
+
sage: M = ModularFormsRing(1)
|
|
4055
|
+
sage: E4 = M.0
|
|
4056
|
+
sage: E6 = M.1
|
|
4057
|
+
sage: DE4 = E4.serre_derivative(); DE4
|
|
4058
|
+
-1/3 + 168*q + 5544*q^2 + 40992*q^3 + 177576*q^4 + 525168*q^5 + O(q^6)
|
|
4059
|
+
sage: DE4 == (-1/3) * E6
|
|
4060
|
+
True
|
|
4061
|
+
sage: DE6 = E6.serre_derivative(); DE6
|
|
4062
|
+
-1/2 - 240*q - 30960*q^2 - 525120*q^3 - 3963120*q^4 - 18750240*q^5 + O(q^6)
|
|
4063
|
+
sage: DE6 == (-1/2) * E4^2
|
|
4064
|
+
True
|
|
4065
|
+
sage: f = E4 + E6
|
|
4066
|
+
sage: Df = f.serre_derivative(); Df
|
|
4067
|
+
-5/6 - 72*q - 25416*q^2 - 484128*q^3 - 3785544*q^4 - 18225072*q^5 + O(q^6)
|
|
4068
|
+
sage: Df == (-1/3) * E6 + (-1/2) * E4^2
|
|
4069
|
+
True
|
|
4070
|
+
sage: M(1/2).serre_derivative()
|
|
4071
|
+
0
|
|
4072
|
+
"""
|
|
4073
|
+
M = self.parent()
|
|
4074
|
+
return M(sum(M(f.serre_derivative()) for k, f in self._forms_dictionary.items() if k != 0))
|
|
4075
|
+
|
|
4076
|
+
def derivative(self, name='E2'):
|
|
4077
|
+
r"""
|
|
4078
|
+
Return the derivative `q \frac{d}{dq}` of the given graded form.
|
|
4079
|
+
|
|
4080
|
+
Note that this method returns an element of a new parent, that is a
|
|
4081
|
+
quasimodular form. If the form is not homogeneous, then this method sums
|
|
4082
|
+
the derivative of each homogeneous component.
|
|
4083
|
+
|
|
4084
|
+
INPUT:
|
|
4085
|
+
|
|
4086
|
+
- ``name``-- string (default: ``'E2'``); the name of the weight 2
|
|
4087
|
+
Eisenstein series generating the graded algebra of quasimodular forms
|
|
4088
|
+
over the ring of modular forms
|
|
4089
|
+
|
|
4090
|
+
OUTPUT: a :class:`sage.modular.quasimodform.element.QuasiModularFormsElement`
|
|
4091
|
+
|
|
4092
|
+
EXAMPLES::
|
|
4093
|
+
|
|
4094
|
+
sage: M = ModularFormsRing(1)
|
|
4095
|
+
sage: E4 = M.0; E6 = M.1
|
|
4096
|
+
sage: dE4 = E4.derivative(); dE4
|
|
4097
|
+
240*q + 4320*q^2 + 20160*q^3 + 70080*q^4 + 151200*q^5 + O(q^6)
|
|
4098
|
+
sage: dE4.parent()
|
|
4099
|
+
Ring of Quasimodular Forms for Modular Group SL(2,Z) over Rational Field
|
|
4100
|
+
sage: dE4.is_modular_form()
|
|
4101
|
+
False
|
|
4102
|
+
"""
|
|
4103
|
+
from sage.modular.quasimodform.ring import QuasiModularForms
|
|
4104
|
+
F = QuasiModularForms(self.group(), self.base_ring(), name)(self)
|
|
4105
|
+
return F.derivative()
|