passagemath-schemes 10.6.47__cp312-cp312-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.6.47.dist-info/METADATA +204 -0
- passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
- passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
- passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
- passagemath_schemes-10.6.47.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 +9558 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-312-darwin.so +0 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
- sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
- sage/lfunctions/all.py +18 -0
- sage/lfunctions/dokchitser.py +745 -0
- sage/lfunctions/pari.py +818 -0
- sage/lfunctions/zero_sums.cpython-312-darwin.so +0 -0
- sage/lfunctions/zero_sums.pyx +1847 -0
- sage/modular/abvar/abvar.py +5135 -0
- sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
- sage/modular/abvar/abvar_newform.py +244 -0
- sage/modular/abvar/all.py +8 -0
- sage/modular/abvar/constructor.py +186 -0
- sage/modular/abvar/cuspidal_subgroup.py +371 -0
- sage/modular/abvar/finite_subgroup.py +896 -0
- sage/modular/abvar/homology.py +720 -0
- sage/modular/abvar/homspace.py +998 -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 +740 -0
- sage/modular/all.py +43 -0
- sage/modular/arithgroup/all.py +20 -0
- sage/modular/arithgroup/arithgroup_element.cpython-312-darwin.so +0 -0
- sage/modular/arithgroup/arithgroup_element.pyx +474 -0
- sage/modular/arithgroup/arithgroup_generic.py +1402 -0
- sage/modular/arithgroup/arithgroup_perm.py +2692 -0
- sage/modular/arithgroup/congroup.cpython-312-darwin.so +0 -0
- sage/modular/arithgroup/congroup.pyx +334 -0
- sage/modular/arithgroup/congroup_gamma.py +363 -0
- sage/modular/arithgroup/congroup_gamma0.py +692 -0
- sage/modular/arithgroup/congroup_gamma1.py +653 -0
- sage/modular/arithgroup/congroup_gammaH.py +1469 -0
- sage/modular/arithgroup/congroup_generic.py +628 -0
- sage/modular/arithgroup/congroup_sl2z.py +267 -0
- sage/modular/arithgroup/farey_symbol.cpython-312-darwin.so +0 -0
- sage/modular/arithgroup/farey_symbol.pyx +1066 -0
- sage/modular/arithgroup/tests.py +418 -0
- sage/modular/btquotients/all.py +4 -0
- sage/modular/btquotients/btquotient.py +3753 -0
- sage/modular/btquotients/pautomorphicform.py +2570 -0
- sage/modular/buzzard.py +100 -0
- sage/modular/congroup.py +29 -0
- sage/modular/congroup_element.py +13 -0
- sage/modular/cusps.py +1109 -0
- sage/modular/cusps_nf.py +1270 -0
- sage/modular/dims.py +569 -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 +1065 -0
- sage/modular/hecke/algebra.py +746 -0
- sage/modular/hecke/all.py +20 -0
- sage/modular/hecke/ambient_module.py +1019 -0
- sage/modular/hecke/degenmap.py +119 -0
- sage/modular/hecke/element.py +325 -0
- sage/modular/hecke/hecke_operator.py +780 -0
- sage/modular/hecke/homspace.py +206 -0
- sage/modular/hecke/module.py +1767 -0
- sage/modular/hecke/morphism.py +174 -0
- sage/modular/hecke/submodule.py +989 -0
- sage/modular/hypergeometric_misc.cpython-312-darwin.so +0 -0
- sage/modular/hypergeometric_misc.pxd +4 -0
- sage/modular/hypergeometric_misc.pyx +166 -0
- sage/modular/hypergeometric_motive.py +2017 -0
- sage/modular/local_comp/all.py +2 -0
- sage/modular/local_comp/liftings.py +292 -0
- sage/modular/local_comp/local_comp.py +1071 -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 +815 -0
- sage/modular/modform/ambient_R.py +177 -0
- sage/modular/modform/ambient_eps.py +306 -0
- sage/modular/modform/ambient_g0.py +124 -0
- sage/modular/modform/ambient_g1.py +204 -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 +505 -0
- sage/modular/modform/eisenstein_submodule.py +663 -0
- sage/modular/modform/element.py +4131 -0
- sage/modular/modform/find_generators.py +59 -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 +133 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.cpython-312-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 +1860 -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 +381 -0
- sage/modular/modform/weight1.py +220 -0
- sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
- sage/modular/modform_hecketriangle/abstract_space.py +2528 -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 +3352 -0
- sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -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 +3846 -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-312-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 +1295 -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-312-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 +375 -0
- sage/modular/multiple_zeta.py +2632 -0
- sage/modular/multiple_zeta_F_algebra.py +786 -0
- sage/modular/overconvergent/all.py +6 -0
- sage/modular/overconvergent/genus0.py +1878 -0
- sage/modular/overconvergent/hecke_series.py +1187 -0
- sage/modular/overconvergent/weightspace.py +778 -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 +859 -0
- sage/modular/pollack_stevens/modsym.py +1593 -0
- sage/modular/pollack_stevens/padic_lseries.py +417 -0
- sage/modular/pollack_stevens/sigma0.py +534 -0
- sage/modular/pollack_stevens/space.py +1076 -0
- sage/modular/quasimodform/all.py +3 -0
- sage/modular/quasimodform/element.py +845 -0
- sage/modular/quasimodform/ring.py +828 -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 +748 -0
- sage/schemes/curves/affine_curve.py +2928 -0
- sage/schemes/curves/all.py +33 -0
- sage/schemes/curves/closed_point.py +434 -0
- sage/schemes/curves/constructor.py +381 -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 +3026 -0
- sage/schemes/curves/zariski_vankampen.py +1932 -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 +1036 -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 +1102 -0
- sage/schemes/elliptic_curves/constructor.py +1552 -0
- sage/schemes/elliptic_curves/ec_database.py +175 -0
- sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
- sage/schemes/elliptic_curves/ell_egros.py +459 -0
- sage/schemes/elliptic_curves/ell_field.py +2836 -0
- sage/schemes/elliptic_curves/ell_finite_field.py +3359 -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 +4787 -0
- sage/schemes/elliptic_curves/ell_rational_field.py +7368 -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 +1669 -0
- sage/schemes/elliptic_curves/gp_simon.py +152 -0
- sage/schemes/elliptic_curves/heegner.py +7335 -0
- sage/schemes/elliptic_curves/height.py +2109 -0
- sage/schemes/elliptic_curves/hom.py +1406 -0
- sage/schemes/elliptic_curves/hom_composite.py +934 -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 +682 -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 +1521 -0
- sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
- sage/schemes/elliptic_curves/jacobian.py +237 -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 +943 -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-312-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-312-darwin.so +0 -0
- sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
- sage/schemes/elliptic_curves/saturation.py +715 -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 +291 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -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 +315 -0
- sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
- sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
- sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
- sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -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 +3871 -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 +580 -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 +73 -0
- sage/schemes/riemann_surfaces/all.py +1 -0
- sage/schemes/riemann_surfaces/riemann_surface.py +4117 -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,845 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.libs.flint
|
|
3
|
+
"""
|
|
4
|
+
Elements of quasimodular forms rings
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
- DAVID AYOTTE (2021-03-18): initial version
|
|
9
|
+
- Seewoo Lee (2023-09): coefficients method
|
|
10
|
+
"""
|
|
11
|
+
# ****************************************************************************
|
|
12
|
+
# Copyright (C) 2021 David Ayotte
|
|
13
|
+
# 2023 Seewoo Lee <seewoo5@berkeley.edu>
|
|
14
|
+
#
|
|
15
|
+
#
|
|
16
|
+
# This program is free software: you can redistribute it and/or modify
|
|
17
|
+
# it under the terms of the GNU General Public License as published by
|
|
18
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
19
|
+
# (at your option) any later version.
|
|
20
|
+
# https://www.gnu.org/licenses/
|
|
21
|
+
# ****************************************************************************
|
|
22
|
+
|
|
23
|
+
from sage.modular.arithgroup.congroup_sl2z import SL2Z_class
|
|
24
|
+
from sage.modular.modform.constructor import EisensteinForms
|
|
25
|
+
from sage.modular.modform.eis_series import eisenstein_series_qexp
|
|
26
|
+
from sage.modular.modform.element import GradedModularFormElement
|
|
27
|
+
|
|
28
|
+
from sage.structure.element import ModuleElement
|
|
29
|
+
from sage.structure.richcmp import richcmp, op_NE, op_EQ
|
|
30
|
+
|
|
31
|
+
from sage.rings.integer import Integer
|
|
32
|
+
from sage.rings.polynomial.polynomial_element import Polynomial
|
|
33
|
+
from sage.rings.integer_ring import ZZ
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class QuasiModularFormsElement(ModuleElement):
|
|
37
|
+
r"""
|
|
38
|
+
A quasimodular forms ring element. Such an element is described by
|
|
39
|
+
SageMath as a polynomial
|
|
40
|
+
|
|
41
|
+
.. MATH::
|
|
42
|
+
|
|
43
|
+
F = f_0 + f_1 E_2 + f_2 E_2^2 + \cdots + f_m E_2^m
|
|
44
|
+
|
|
45
|
+
where each `f_i` a graded modular form element
|
|
46
|
+
(see :class:`~sage.modular.modform.element.GradedModularFormElement`)
|
|
47
|
+
|
|
48
|
+
For an integer `k`, we say that `F` is homogeneous of weight `k` if
|
|
49
|
+
it lies in an homogeneous component of degree `k` of the graded ring
|
|
50
|
+
of quasimodular forms.
|
|
51
|
+
|
|
52
|
+
EXAMPLES::
|
|
53
|
+
|
|
54
|
+
sage: QM = QuasiModularForms(1)
|
|
55
|
+
sage: QM.gens()
|
|
56
|
+
(1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
|
|
57
|
+
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
|
|
58
|
+
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6))
|
|
59
|
+
sage: QM.0 + QM.1
|
|
60
|
+
2 + 216*q + 2088*q^2 + 6624*q^3 + 17352*q^4 + 30096*q^5 + O(q^6)
|
|
61
|
+
sage: QM.0 * QM.1
|
|
62
|
+
1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6)
|
|
63
|
+
sage: (QM.0)^2
|
|
64
|
+
1 - 48*q + 432*q^2 + 3264*q^3 + 9456*q^4 + 21600*q^5 + O(q^6)
|
|
65
|
+
sage: QM.0 == QM.1
|
|
66
|
+
False
|
|
67
|
+
|
|
68
|
+
Quasimodular forms ring element can be created via a polynomial in `E2` over the ring of modular forms::
|
|
69
|
+
|
|
70
|
+
sage: E2 = QM.polygen()
|
|
71
|
+
sage: E2.parent()
|
|
72
|
+
Univariate Polynomial Ring in E2 over Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field
|
|
73
|
+
sage: QM(E2)
|
|
74
|
+
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
|
|
75
|
+
sage: M = QM.modular_forms_subring()
|
|
76
|
+
sage: QM(M.0 * E2 + M.1 * E2^2)
|
|
77
|
+
2 - 336*q + 4320*q^2 + 398400*q^3 - 3772992*q^4 - 89283168*q^5 + O(q^6)
|
|
78
|
+
|
|
79
|
+
One may convert a quasimodular form into a multivariate polynomial in the
|
|
80
|
+
generators of the ring by calling
|
|
81
|
+
:meth:`~sage.modular.quasimodform.element.QuasiModularFormsElement.polynomial`::
|
|
82
|
+
|
|
83
|
+
sage: QM = QuasiModularForms(1)
|
|
84
|
+
sage: F = QM.0^2 + QM.1^2 + QM.0*QM.1*QM.2
|
|
85
|
+
sage: F.polynomial()
|
|
86
|
+
E2*E4*E6 + E4^2 + E2^2
|
|
87
|
+
|
|
88
|
+
If the group is not the full modular group, the default names of the
|
|
89
|
+
generators are given by ``Ek_i`` and ``Sk_i`` to denote the `i`-th basis
|
|
90
|
+
element of the weight `k` Eisenstein subspace and cuspidal subspace
|
|
91
|
+
respectively (for more details, see the documentation of
|
|
92
|
+
:meth:`~sage.modular.quasimodform.ring.QuasiModularFormsRing.polynomial_ring`) ::
|
|
93
|
+
|
|
94
|
+
sage: QM = QuasiModularForms(Gamma1(4))
|
|
95
|
+
sage: F = (QM.0^4)*(QM.1^3) + QM.3
|
|
96
|
+
sage: F.polynomial()
|
|
97
|
+
-512*E2^4*E2_1^3 + E2^4*E3_0^2 + 48*E2^4*E3_1^2 + E3_0
|
|
98
|
+
"""
|
|
99
|
+
def __init__(self, parent, polynomial):
|
|
100
|
+
r"""
|
|
101
|
+
INPUT:
|
|
102
|
+
|
|
103
|
+
- ``parent`` -- a quasimodular forms ring
|
|
104
|
+
- ``polynomial`` -- a polynomial `f_0 + f_1 E_2 + ... + f_n E_2^n` where
|
|
105
|
+
each `f_i` are modular forms ring elements and `E_2` correspond to the
|
|
106
|
+
weight 2 Eisenstein series
|
|
107
|
+
|
|
108
|
+
OUTPUT: ``QuasiModularFormsElement``
|
|
109
|
+
|
|
110
|
+
TESTS::
|
|
111
|
+
|
|
112
|
+
sage: QM = QuasiModularForms(1)
|
|
113
|
+
sage: QM.element_class(QM, 'E2')
|
|
114
|
+
Traceback (most recent call last):
|
|
115
|
+
...
|
|
116
|
+
TypeError: 'polynomial' argument should be of type 'Polynomial'
|
|
117
|
+
sage: x = polygen(QQ)
|
|
118
|
+
sage: QM.element_class(QM, x^2 + 1)
|
|
119
|
+
Traceback (most recent call last):
|
|
120
|
+
...
|
|
121
|
+
ValueError: at least one coefficient is not a 'GradedModularFormElement'
|
|
122
|
+
"""
|
|
123
|
+
if not isinstance(polynomial, Polynomial):
|
|
124
|
+
raise TypeError("'polynomial' argument should be of type 'Polynomial'")
|
|
125
|
+
for f in polynomial.coefficients():
|
|
126
|
+
if not isinstance(f, GradedModularFormElement):
|
|
127
|
+
raise ValueError("at least one coefficient is not a 'GradedModularFormElement'")
|
|
128
|
+
self._polynomial = polynomial
|
|
129
|
+
ModuleElement.__init__(self, parent)
|
|
130
|
+
|
|
131
|
+
def q_expansion(self, prec=6):
|
|
132
|
+
r"""
|
|
133
|
+
Return the `q`-expansion of the given quasimodular form up to precision
|
|
134
|
+
``prec`` (default: 6).
|
|
135
|
+
|
|
136
|
+
An alias of this method is ``qexp``.
|
|
137
|
+
|
|
138
|
+
EXAMPLES::
|
|
139
|
+
|
|
140
|
+
sage: QM = QuasiModularForms()
|
|
141
|
+
sage: E2 = QM.0
|
|
142
|
+
sage: E2.q_expansion()
|
|
143
|
+
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
|
|
144
|
+
sage: E2.q_expansion(prec=10)
|
|
145
|
+
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 - 288*q^6 - 192*q^7 - 360*q^8 - 312*q^9 + O(q^10)
|
|
146
|
+
"""
|
|
147
|
+
E2 = eisenstein_series_qexp(2, prec=prec, K=self.base_ring(), normalization='constant') # normalization -> to force integer coefficients
|
|
148
|
+
coefficients = self._polynomial.coefficients(sparse=False)
|
|
149
|
+
return sum(f.q_expansion(prec=prec) * E2**idx for idx, f in enumerate(coefficients))
|
|
150
|
+
|
|
151
|
+
qexp = q_expansion # alias
|
|
152
|
+
|
|
153
|
+
def _repr_(self):
|
|
154
|
+
r"""
|
|
155
|
+
String representation of ``self``.
|
|
156
|
+
|
|
157
|
+
TESTS::
|
|
158
|
+
|
|
159
|
+
sage: QM = QuasiModularForms()
|
|
160
|
+
sage: QM.0
|
|
161
|
+
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
|
|
162
|
+
sage: QM.1
|
|
163
|
+
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
|
|
164
|
+
sage: QM.2
|
|
165
|
+
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)
|
|
166
|
+
"""
|
|
167
|
+
return str(self.q_expansion())
|
|
168
|
+
|
|
169
|
+
def _latex_(self):
|
|
170
|
+
r"""
|
|
171
|
+
Return a latex representation of ``self``.
|
|
172
|
+
|
|
173
|
+
TESTS::
|
|
174
|
+
|
|
175
|
+
sage: QM = QuasiModularForms(1)
|
|
176
|
+
sage: latex(QM.0)
|
|
177
|
+
1 - 24 q - 72 q^{2} - 96 q^{3} - 168 q^{4} - 144 q^{5} + O(q^{6})
|
|
178
|
+
"""
|
|
179
|
+
return self.q_expansion()._latex_()
|
|
180
|
+
|
|
181
|
+
def _richcmp_(self, other, op):
|
|
182
|
+
r"""
|
|
183
|
+
Compare ``self`` with ``other``.
|
|
184
|
+
|
|
185
|
+
TESTS::
|
|
186
|
+
|
|
187
|
+
sage: QM = QuasiModularForms(1)
|
|
188
|
+
sage: QM.0 == QM.1
|
|
189
|
+
False
|
|
190
|
+
sage: QM.0 == QM.0
|
|
191
|
+
True
|
|
192
|
+
sage: QM.0 != QM.1
|
|
193
|
+
True
|
|
194
|
+
sage: QM.0 != QM.0
|
|
195
|
+
False
|
|
196
|
+
sage: QM.0 < QM.1
|
|
197
|
+
Traceback (most recent call last):
|
|
198
|
+
...
|
|
199
|
+
TypeError: invalid comparison between quasimodular forms ring elements
|
|
200
|
+
"""
|
|
201
|
+
if op != op_EQ and op != op_NE:
|
|
202
|
+
raise TypeError('invalid comparison between quasimodular forms ring elements')
|
|
203
|
+
return richcmp(self._polynomial, other._polynomial, op)
|
|
204
|
+
|
|
205
|
+
def _add_(self, other):
|
|
206
|
+
r"""
|
|
207
|
+
Addition of two ``QuasiModularFormElement``.
|
|
208
|
+
|
|
209
|
+
INPUT:
|
|
210
|
+
|
|
211
|
+
- ``other`` -- ``QuasiModularFormElement``
|
|
212
|
+
|
|
213
|
+
OUTPUT: a ``QuasiModularFormElement``
|
|
214
|
+
|
|
215
|
+
TESTS::
|
|
216
|
+
|
|
217
|
+
sage: QM = QuasiModularForms(1)
|
|
218
|
+
sage: QM.0 + QM.1
|
|
219
|
+
2 + 216*q + 2088*q^2 + 6624*q^3 + 17352*q^4 + 30096*q^5 + O(q^6)
|
|
220
|
+
sage: QM.0 + (QM.1 + QM.2) == (QM.0 + QM.1) + QM.2
|
|
221
|
+
True
|
|
222
|
+
sage: QM = QuasiModularForms(5)
|
|
223
|
+
sage: QM.0 + QM.1 + QM.2 + QM.3
|
|
224
|
+
3 - 17*q - 54*q^2 - 62*q^3 - 98*q^4 + 137*q^5 + O(q^6)
|
|
225
|
+
"""
|
|
226
|
+
return self.__class__(self.parent(), self._polynomial + other._polynomial)
|
|
227
|
+
|
|
228
|
+
def __neg__(self):
|
|
229
|
+
r"""
|
|
230
|
+
The negation of ``self``.
|
|
231
|
+
|
|
232
|
+
TESTS::
|
|
233
|
+
|
|
234
|
+
sage: -QuasiModularForms(1).0
|
|
235
|
+
-1 + 24*q + 72*q^2 + 96*q^3 + 168*q^4 + 144*q^5 + O(q^6)
|
|
236
|
+
sage: QuasiModularForms(1).0 - QuasiModularForms(1).0
|
|
237
|
+
0
|
|
238
|
+
sage: -QuasiModularForms(Gamma1(2)).2
|
|
239
|
+
-1 - 240*q^2 - 2160*q^4 + O(q^6)
|
|
240
|
+
"""
|
|
241
|
+
return self.__class__(self.parent(), -self._polynomial)
|
|
242
|
+
|
|
243
|
+
def _mul_(self, other):
|
|
244
|
+
r"""
|
|
245
|
+
The multiplication of two ``QuasiModularFormElement``.
|
|
246
|
+
|
|
247
|
+
INPUT:
|
|
248
|
+
|
|
249
|
+
- ``other`` -- ``QuasiModularFormElement``
|
|
250
|
+
|
|
251
|
+
OUTPUT: a ``QuasiModularFormElement``
|
|
252
|
+
|
|
253
|
+
TESTS::
|
|
254
|
+
|
|
255
|
+
sage: QM = QuasiModularForms(1)
|
|
256
|
+
sage: QM.0 * QM.1
|
|
257
|
+
1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6)
|
|
258
|
+
sage: (QM.0 * QM.1) * QM.2 == QM.0 * (QM.1 * QM.2)
|
|
259
|
+
True
|
|
260
|
+
sage: QM = QuasiModularForms(Gamma1(5))
|
|
261
|
+
sage: QM.0 * QM.1 * QM.2
|
|
262
|
+
q - 24*q^2 - 66*q^3 - 189*q^4 - 1917*q^5 + O(q^6)
|
|
263
|
+
"""
|
|
264
|
+
return self.__class__(self.parent(), self._polynomial * other._polynomial)
|
|
265
|
+
|
|
266
|
+
def _lmul_(self, c):
|
|
267
|
+
r"""
|
|
268
|
+
The left action of the base ring on ``self``.
|
|
269
|
+
|
|
270
|
+
INPUT:
|
|
271
|
+
|
|
272
|
+
- ``other`` -- ``QuasiModularFormElement``
|
|
273
|
+
|
|
274
|
+
OUTPUT: a ``QuasiModularFormElement``
|
|
275
|
+
|
|
276
|
+
TESTS::
|
|
277
|
+
|
|
278
|
+
sage: QM = QuasiModularForms(1)
|
|
279
|
+
sage: (1/2) * QM.0
|
|
280
|
+
1/2 - 12*q - 36*q^2 - 48*q^3 - 84*q^4 - 72*q^5 + O(q^6)
|
|
281
|
+
sage: QM.0 * (3/2)
|
|
282
|
+
3/2 - 36*q - 108*q^2 - 144*q^3 - 252*q^4 - 216*q^5 + O(q^6)
|
|
283
|
+
sage: (5/2) * QuasiModularForms(Gamma0(7)).0 * (3/2)
|
|
284
|
+
15/4 - 90*q - 270*q^2 - 360*q^3 - 630*q^4 - 540*q^5 + O(q^6)
|
|
285
|
+
"""
|
|
286
|
+
return self.__class__(self.parent(), c * self._polynomial)
|
|
287
|
+
|
|
288
|
+
def __bool__(self):
|
|
289
|
+
r"""
|
|
290
|
+
Return whether ``self`` is nonzero.
|
|
291
|
+
|
|
292
|
+
EXAMPLES::
|
|
293
|
+
|
|
294
|
+
sage: QM = QuasiModularForms(1)
|
|
295
|
+
sage: bool(QM(0))
|
|
296
|
+
False
|
|
297
|
+
sage: bool(QM(1))
|
|
298
|
+
True
|
|
299
|
+
sage: bool(QM.0)
|
|
300
|
+
True
|
|
301
|
+
"""
|
|
302
|
+
return bool(self._polynomial)
|
|
303
|
+
|
|
304
|
+
def depth(self):
|
|
305
|
+
r"""
|
|
306
|
+
Return the depth of this quasimodular form.
|
|
307
|
+
|
|
308
|
+
Note that the quasimodular form must be homogeneous of weight
|
|
309
|
+
`k`. Recall that the *depth* is the integer `p` such that
|
|
310
|
+
|
|
311
|
+
.. MATH::
|
|
312
|
+
|
|
313
|
+
f = f_0 + f_1 E_2 + \cdots + f_p E_2^p,
|
|
314
|
+
|
|
315
|
+
where `f_i` is a modular form of weight `k - 2i` and `f_p` is
|
|
316
|
+
nonzero.
|
|
317
|
+
|
|
318
|
+
EXAMPLES::
|
|
319
|
+
|
|
320
|
+
sage: QM = QuasiModularForms(1)
|
|
321
|
+
sage: E2, E4, E6 = QM.gens()
|
|
322
|
+
sage: E2.depth()
|
|
323
|
+
1
|
|
324
|
+
sage: F = E4^2 + E6*E2 + E4*E2^2 + E2^4
|
|
325
|
+
sage: F.depth()
|
|
326
|
+
4
|
|
327
|
+
sage: QM(7/11).depth()
|
|
328
|
+
0
|
|
329
|
+
|
|
330
|
+
TESTS::
|
|
331
|
+
|
|
332
|
+
sage: QM = QuasiModularForms(1)
|
|
333
|
+
sage: (QM.0 + QM.1).depth()
|
|
334
|
+
Traceback (most recent call last):
|
|
335
|
+
...
|
|
336
|
+
ValueError: the given graded quasiform is not an homogeneous element
|
|
337
|
+
"""
|
|
338
|
+
if not self.is_homogeneous():
|
|
339
|
+
raise ValueError("the given graded quasiform is not an "
|
|
340
|
+
"homogeneous element")
|
|
341
|
+
return self._polynomial.degree()
|
|
342
|
+
|
|
343
|
+
def is_zero(self) -> bool:
|
|
344
|
+
r"""
|
|
345
|
+
Return whether the given quasimodular form is zero.
|
|
346
|
+
|
|
347
|
+
EXAMPLES::
|
|
348
|
+
|
|
349
|
+
sage: QM = QuasiModularForms(1)
|
|
350
|
+
sage: QM.zero().is_zero()
|
|
351
|
+
True
|
|
352
|
+
sage: QM(0).is_zero()
|
|
353
|
+
True
|
|
354
|
+
sage: QM(1/2).is_zero()
|
|
355
|
+
False
|
|
356
|
+
sage: (QM.0).is_zero()
|
|
357
|
+
False
|
|
358
|
+
sage: QM = QuasiModularForms(Gamma0(2))
|
|
359
|
+
sage: QM(0).is_zero()
|
|
360
|
+
True
|
|
361
|
+
"""
|
|
362
|
+
return not self
|
|
363
|
+
|
|
364
|
+
def is_one(self) -> bool:
|
|
365
|
+
r"""
|
|
366
|
+
Return whether the given quasimodular form is 1, i.e. the
|
|
367
|
+
multiplicative identity.
|
|
368
|
+
|
|
369
|
+
EXAMPLES::
|
|
370
|
+
|
|
371
|
+
sage: QM = QuasiModularForms(1)
|
|
372
|
+
sage: QM.one().is_one()
|
|
373
|
+
True
|
|
374
|
+
sage: QM(1).is_one()
|
|
375
|
+
True
|
|
376
|
+
sage: (QM.0).is_one()
|
|
377
|
+
False
|
|
378
|
+
sage: QM = QuasiModularForms(Gamma0(2))
|
|
379
|
+
sage: QM(1).is_one()
|
|
380
|
+
True
|
|
381
|
+
"""
|
|
382
|
+
return self._polynomial.is_one()
|
|
383
|
+
|
|
384
|
+
def is_graded_modular_form(self) -> bool:
|
|
385
|
+
r"""
|
|
386
|
+
Return whether the given quasimodular form is a
|
|
387
|
+
graded modular form element
|
|
388
|
+
(see :class:`~sage.modular.modform.element.GradedModularFormElement`).
|
|
389
|
+
|
|
390
|
+
EXAMPLES::
|
|
391
|
+
|
|
392
|
+
sage: QM = QuasiModularForms(1)
|
|
393
|
+
sage: (QM.0).is_graded_modular_form()
|
|
394
|
+
False
|
|
395
|
+
sage: (QM.1).is_graded_modular_form()
|
|
396
|
+
True
|
|
397
|
+
sage: (QM.1 + QM.0^2).is_graded_modular_form()
|
|
398
|
+
False
|
|
399
|
+
sage: (QM.1^2 + QM.2).is_graded_modular_form()
|
|
400
|
+
True
|
|
401
|
+
sage: QM = QuasiModularForms(Gamma0(6))
|
|
402
|
+
sage: (QM.0).is_graded_modular_form()
|
|
403
|
+
False
|
|
404
|
+
sage: (QM.1 + QM.2 + QM.1 * QM.3).is_graded_modular_form()
|
|
405
|
+
True
|
|
406
|
+
sage: QM.zero().is_graded_modular_form()
|
|
407
|
+
True
|
|
408
|
+
sage: QM = QuasiModularForms(Gamma0(6))
|
|
409
|
+
sage: (QM.0).is_graded_modular_form()
|
|
410
|
+
False
|
|
411
|
+
sage: (QM.0 + QM.1*QM.2 + QM.3).is_graded_modular_form()
|
|
412
|
+
False
|
|
413
|
+
sage: (QM.1*QM.2 + QM.3).is_graded_modular_form()
|
|
414
|
+
True
|
|
415
|
+
|
|
416
|
+
.. NOTE::
|
|
417
|
+
|
|
418
|
+
A graded modular form in SageMath is not necessarily a modular form
|
|
419
|
+
as it can have mixed weight components. To check for modular forms
|
|
420
|
+
only, see the method :meth:`is_modular_form`.
|
|
421
|
+
"""
|
|
422
|
+
return self._polynomial.degree() <= 0
|
|
423
|
+
|
|
424
|
+
def is_modular_form(self) -> bool:
|
|
425
|
+
r"""
|
|
426
|
+
Return whether the given quasimodular form is a modular form.
|
|
427
|
+
|
|
428
|
+
EXAMPLES::
|
|
429
|
+
|
|
430
|
+
sage: QM = QuasiModularForms(1)
|
|
431
|
+
sage: (QM.0).is_modular_form()
|
|
432
|
+
False
|
|
433
|
+
sage: (QM.1).is_modular_form()
|
|
434
|
+
True
|
|
435
|
+
sage: (QM.1 + QM.2).is_modular_form() # mixed weight components
|
|
436
|
+
False
|
|
437
|
+
sage: QM.zero().is_modular_form()
|
|
438
|
+
True
|
|
439
|
+
sage: QM = QuasiModularForms(Gamma0(4))
|
|
440
|
+
sage: (QM.0).is_modular_form()
|
|
441
|
+
False
|
|
442
|
+
sage: (QM.1).is_modular_form()
|
|
443
|
+
True
|
|
444
|
+
"""
|
|
445
|
+
return self._polynomial.degree() <= 0 and self._polynomial[0].is_modular_form()
|
|
446
|
+
|
|
447
|
+
def polynomial(self, names=None):
|
|
448
|
+
r"""
|
|
449
|
+
Return a multivariate polynomial such that every variable corresponds to
|
|
450
|
+
a generator of the ring, ordered by the method:
|
|
451
|
+
:meth:`~sage.modular.quasimodform.ring.QuasiModularForms.gens`.
|
|
452
|
+
|
|
453
|
+
An alias of this method is ``to_polynomial``.
|
|
454
|
+
|
|
455
|
+
INPUT:
|
|
456
|
+
|
|
457
|
+
- ``names``-- string (default: ``None``); list or tuple of names
|
|
458
|
+
(strings), or a comma separated string. Defines the names for the
|
|
459
|
+
generators of the multivariate polynomial ring. The default names are
|
|
460
|
+
of the form ``ABCk`` where ``k`` is a number corresponding to the
|
|
461
|
+
weight of the form ``ABC``.
|
|
462
|
+
|
|
463
|
+
OUTPUT: a multivariate polynomial in the variables ``names``
|
|
464
|
+
|
|
465
|
+
EXAMPLES::
|
|
466
|
+
|
|
467
|
+
sage: QM = QuasiModularForms(1)
|
|
468
|
+
sage: (QM.0 + QM.1).polynomial()
|
|
469
|
+
E4 + E2
|
|
470
|
+
sage: (1/2 + QM.0 + 2*QM.1^2 + QM.0*QM.2).polynomial()
|
|
471
|
+
E2*E6 + 2*E4^2 + E2 + 1/2
|
|
472
|
+
|
|
473
|
+
Check that :issue:`34569` is fixed::
|
|
474
|
+
|
|
475
|
+
sage: QM = QuasiModularForms(Gamma1(3))
|
|
476
|
+
sage: QM.ngens()
|
|
477
|
+
5
|
|
478
|
+
sage: (QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).polynomial()
|
|
479
|
+
E3_1*E4_0 + E2_0*E3_0 + E2 + E2_0
|
|
480
|
+
"""
|
|
481
|
+
P = self.parent().polynomial_ring(names)
|
|
482
|
+
poly_gens = P.gens()
|
|
483
|
+
E2 = poly_gens[0]
|
|
484
|
+
poly_gens = poly_gens[1:]
|
|
485
|
+
modform_poly_gens = self.parent().modular_forms_subring().polynomial_ring(names='x').gens()
|
|
486
|
+
subs_dictionary = {}
|
|
487
|
+
for idx, g in enumerate(modform_poly_gens):
|
|
488
|
+
subs_dictionary[g] = poly_gens[idx]
|
|
489
|
+
return sum(f.to_polynomial().subs(subs_dictionary) * E2 ** exp for exp, f in enumerate(self._polynomial.coefficients(sparse=False)))
|
|
490
|
+
|
|
491
|
+
to_polynomial = polynomial # alias
|
|
492
|
+
|
|
493
|
+
def weights_list(self):
|
|
494
|
+
r"""
|
|
495
|
+
Return the list of the weights of all the graded components of the given
|
|
496
|
+
graded quasimodular form.
|
|
497
|
+
|
|
498
|
+
EXAMPLES::
|
|
499
|
+
|
|
500
|
+
sage: QM = QuasiModularForms(1)
|
|
501
|
+
sage: (QM.0).weights_list()
|
|
502
|
+
[2]
|
|
503
|
+
sage: (QM.0 + QM.1 + QM.2).weights_list()
|
|
504
|
+
[2, 4, 6]
|
|
505
|
+
sage: (QM.0 * QM.1 + QM.2).weights_list()
|
|
506
|
+
[6]
|
|
507
|
+
sage: QM(1/2).weights_list()
|
|
508
|
+
[0]
|
|
509
|
+
sage: QM = QuasiModularForms(Gamma1(3))
|
|
510
|
+
sage: (QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).weights_list()
|
|
511
|
+
[2, 5, 7]
|
|
512
|
+
"""
|
|
513
|
+
return sorted(self.homogeneous_components().keys())
|
|
514
|
+
|
|
515
|
+
def is_homogeneous(self) -> bool:
|
|
516
|
+
r"""
|
|
517
|
+
Return whether the graded quasimodular form is a homogeneous element,
|
|
518
|
+
that is, it lives in a unique graded components of the parent of
|
|
519
|
+
``self``.
|
|
520
|
+
|
|
521
|
+
EXAMPLES::
|
|
522
|
+
|
|
523
|
+
sage: QM = QuasiModularForms(1)
|
|
524
|
+
sage: E2, E4, E6 = QM.gens()
|
|
525
|
+
sage: (E2).is_homogeneous()
|
|
526
|
+
True
|
|
527
|
+
sage: (E2 + E4).is_homogeneous()
|
|
528
|
+
False
|
|
529
|
+
sage: (E2 * E4 + E6).is_homogeneous()
|
|
530
|
+
True
|
|
531
|
+
sage: QM(1).is_homogeneous()
|
|
532
|
+
True
|
|
533
|
+
sage: (1 + E2).is_homogeneous()
|
|
534
|
+
False
|
|
535
|
+
sage: F = E6^3 + E4^4*E2 + (E4^2*E6)*E2^2 + (E4^3 + E6^2)*E2^3
|
|
536
|
+
sage: F.is_homogeneous()
|
|
537
|
+
True
|
|
538
|
+
"""
|
|
539
|
+
k = None
|
|
540
|
+
for i, c in enumerate(self._polynomial.coefficients(sparse=False)):
|
|
541
|
+
if c:
|
|
542
|
+
if not c.is_homogeneous():
|
|
543
|
+
return False
|
|
544
|
+
if k is None:
|
|
545
|
+
k = c.weight() + 2*i
|
|
546
|
+
continue
|
|
547
|
+
if c.weight() + 2*i != k:
|
|
548
|
+
return False
|
|
549
|
+
return True
|
|
550
|
+
|
|
551
|
+
def weight(self):
|
|
552
|
+
r"""
|
|
553
|
+
Return the weight of the given quasimodular form.
|
|
554
|
+
|
|
555
|
+
Note that the given form must be homogeneous. An alias of this method is
|
|
556
|
+
``degree``.
|
|
557
|
+
|
|
558
|
+
EXAMPLES::
|
|
559
|
+
|
|
560
|
+
sage: QM = QuasiModularForms(1)
|
|
561
|
+
sage: (QM.0).weight()
|
|
562
|
+
2
|
|
563
|
+
sage: (QM.0 * QM.1 + QM.2).weight()
|
|
564
|
+
6
|
|
565
|
+
sage: QM(1/2).weight()
|
|
566
|
+
0
|
|
567
|
+
sage: (QM.0).degree()
|
|
568
|
+
2
|
|
569
|
+
sage: (QM.0 + QM.1).weight()
|
|
570
|
+
Traceback (most recent call last):
|
|
571
|
+
...
|
|
572
|
+
ValueError: the given graded quasiform is not an homogeneous element
|
|
573
|
+
"""
|
|
574
|
+
if self.is_homogeneous():
|
|
575
|
+
return (self._polynomial.leading_coefficient().weight()
|
|
576
|
+
+ 2*self._polynomial.degree())
|
|
577
|
+
else:
|
|
578
|
+
raise ValueError("the given graded quasiform is not an homogeneous \
|
|
579
|
+
element")
|
|
580
|
+
|
|
581
|
+
degree = weight # alias
|
|
582
|
+
|
|
583
|
+
def homogeneous_components(self):
|
|
584
|
+
r"""
|
|
585
|
+
Return a dictionary where the values are the homogeneous components of
|
|
586
|
+
the given graded form and the keys are the weights of those components.
|
|
587
|
+
|
|
588
|
+
EXAMPLES::
|
|
589
|
+
|
|
590
|
+
sage: QM = QuasiModularForms(1)
|
|
591
|
+
sage: (QM.0).homogeneous_components()
|
|
592
|
+
{2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)}
|
|
593
|
+
sage: (QM.0 + QM.1 + QM.2).homogeneous_components()
|
|
594
|
+
{2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
|
|
595
|
+
4: 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
|
|
596
|
+
6: 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)}
|
|
597
|
+
sage: (1 + QM.0).homogeneous_components()
|
|
598
|
+
{0: 1, 2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)}
|
|
599
|
+
sage: QM5 = QuasiModularForms(Gamma1(3))
|
|
600
|
+
sage: F = QM.1 + QM.1*QM.2 + QM.1*QM.0 + (QM.1 + QM.2^2)*QM.0^3
|
|
601
|
+
sage: F.homogeneous_components()
|
|
602
|
+
{4: 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
|
|
603
|
+
6: 1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6),
|
|
604
|
+
10: 2 - 96*q - 149040*q^2 - 4986240*q^3 - 67535952*q^4 - 538187328*q^5 + O(q^6),
|
|
605
|
+
18: 1 - 1080*q + 294840*q^2 - 902880*q^3 - 452402280*q^4 + 105456816*q^5 + O(q^6)}
|
|
606
|
+
sage: F = QM.zero()
|
|
607
|
+
sage: F.homogeneous_components()
|
|
608
|
+
{0: 0}
|
|
609
|
+
sage: F = QM(42/13)
|
|
610
|
+
sage: F.homogeneous_components()
|
|
611
|
+
{0: 42/13}
|
|
612
|
+
"""
|
|
613
|
+
QM = self.parent()
|
|
614
|
+
if self.is_zero():
|
|
615
|
+
return {ZZ(0): self}
|
|
616
|
+
components = {}
|
|
617
|
+
E2 = self.parent().weight_2_eisenstein_series()
|
|
618
|
+
for i, c in enumerate(self._polynomial.coefficients(sparse=False)):
|
|
619
|
+
if c:
|
|
620
|
+
forms = c._forms_dictionary
|
|
621
|
+
for k in forms.keys():
|
|
622
|
+
try:
|
|
623
|
+
components[ZZ(k + 2*i)] += QM(forms[k]*(E2**i))
|
|
624
|
+
except KeyError:
|
|
625
|
+
components[ZZ(k + 2*i)] = QM(forms[k]*(E2**i))
|
|
626
|
+
return components
|
|
627
|
+
|
|
628
|
+
def __getitem__(self, weight):
|
|
629
|
+
r"""
|
|
630
|
+
Return the homogeneous component of the given quasimodular form ring
|
|
631
|
+
element.
|
|
632
|
+
|
|
633
|
+
An alias of this method is ``homogeneous_component``.
|
|
634
|
+
|
|
635
|
+
EXAMPLES::
|
|
636
|
+
|
|
637
|
+
sage: QM = QuasiModularForms(1)
|
|
638
|
+
sage: E2, E4, E6 = QM.gens()
|
|
639
|
+
sage: F = E2 + E4*E6 + E2^3*E6
|
|
640
|
+
sage: F[2]
|
|
641
|
+
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
|
|
642
|
+
sage: F[10]
|
|
643
|
+
1 - 264*q - 135432*q^2 - 5196576*q^3 - 69341448*q^4 - 515625264*q^5 + O(q^6)
|
|
644
|
+
sage: F[12]
|
|
645
|
+
1 - 576*q + 21168*q^2 + 308736*q^3 - 15034608*q^4 - 39208320*q^5 + O(q^6)
|
|
646
|
+
sage: F[4]
|
|
647
|
+
0
|
|
648
|
+
sage: F.homogeneous_component(2)
|
|
649
|
+
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
|
|
650
|
+
|
|
651
|
+
TESTS::
|
|
652
|
+
|
|
653
|
+
sage: F[x] # needs sage.symbolic
|
|
654
|
+
Traceback (most recent call last):
|
|
655
|
+
...
|
|
656
|
+
KeyError: 'the weight must be an integer'
|
|
657
|
+
sage: F[-1]
|
|
658
|
+
Traceback (most recent call last):
|
|
659
|
+
...
|
|
660
|
+
ValueError: the weight must be nonnegative
|
|
661
|
+
"""
|
|
662
|
+
if not isinstance(weight, (int, Integer)):
|
|
663
|
+
raise KeyError("the weight must be an integer")
|
|
664
|
+
if weight < 0:
|
|
665
|
+
raise ValueError("the weight must be nonnegative")
|
|
666
|
+
return self.homogeneous_components().get(weight, self.parent().zero())
|
|
667
|
+
|
|
668
|
+
homogeneous_component = __getitem__ # alias
|
|
669
|
+
|
|
670
|
+
def serre_derivative(self):
|
|
671
|
+
r"""
|
|
672
|
+
Return the Serre derivative of the given quasimodular form.
|
|
673
|
+
|
|
674
|
+
If the form is not homogeneous, then this method sums the Serre
|
|
675
|
+
derivative of each homogeneous component.
|
|
676
|
+
|
|
677
|
+
EXAMPLES::
|
|
678
|
+
|
|
679
|
+
sage: QM = QuasiModularForms(1)
|
|
680
|
+
sage: E2, E4, E6 = QM.gens()
|
|
681
|
+
sage: DE2 = E2.serre_derivative(); DE2
|
|
682
|
+
-1/6 - 16*q - 216*q^2 - 832*q^3 - 2248*q^4 - 4320*q^5 + O(q^6)
|
|
683
|
+
sage: DE2 == (-E2^2 - E4)/12
|
|
684
|
+
True
|
|
685
|
+
sage: DE4 = E4.serre_derivative(); DE4
|
|
686
|
+
-1/3 + 168*q + 5544*q^2 + 40992*q^3 + 177576*q^4 + 525168*q^5 + O(q^6)
|
|
687
|
+
sage: DE4 == (-1/3) * E6
|
|
688
|
+
True
|
|
689
|
+
sage: DE6 = E6.serre_derivative(); DE6
|
|
690
|
+
-1/2 - 240*q - 30960*q^2 - 525120*q^3 - 3963120*q^4 - 18750240*q^5 + O(q^6)
|
|
691
|
+
sage: DE6 == (-1/2) * E4^2
|
|
692
|
+
True
|
|
693
|
+
|
|
694
|
+
The Serre derivative raises the weight of homogeneous elements by 2::
|
|
695
|
+
|
|
696
|
+
sage: F = E6 + E4 * E2
|
|
697
|
+
sage: F.weight()
|
|
698
|
+
6
|
|
699
|
+
sage: F.serre_derivative().weight()
|
|
700
|
+
8
|
|
701
|
+
|
|
702
|
+
Check that :issue:`34569` is fixed::
|
|
703
|
+
|
|
704
|
+
sage: QM = QuasiModularForms(Gamma1(3))
|
|
705
|
+
sage: E2 = QM.weight_2_eisenstein_series()
|
|
706
|
+
sage: E2.serre_derivative()
|
|
707
|
+
-1/6 - 16*q - 216*q^2 - 832*q^3 - 2248*q^4 - 4320*q^5 + O(q^6)
|
|
708
|
+
sage: F = QM.0 + QM.1*QM.2
|
|
709
|
+
"""
|
|
710
|
+
# initial variables:
|
|
711
|
+
QM = self.parent()
|
|
712
|
+
R = QM.base_ring()
|
|
713
|
+
E2 = QM.gen(0)
|
|
714
|
+
if isinstance(QM.group(), SL2Z_class):
|
|
715
|
+
E4 = QM.gen(1)
|
|
716
|
+
else:
|
|
717
|
+
E4 = QM(EisensteinForms(group=1, weight=4, base_ring=R).gen(0))
|
|
718
|
+
|
|
719
|
+
# compute the derivative of E2: q*dE2/dq
|
|
720
|
+
E2deriv = R(12).inverse_of_unit() * (E2 ** 2 - E4)
|
|
721
|
+
|
|
722
|
+
# sum the Serre derivative of each monomial of the form: f * E2^n
|
|
723
|
+
# they are equal to:
|
|
724
|
+
# [E2^n * serre_deriv(f)] + [n * f * E2^(n-1) * D(E2)] - [n/6 * f * E2^(n+1)]
|
|
725
|
+
# = A + B - C
|
|
726
|
+
der = QM.zero()
|
|
727
|
+
u6 = R(6).inverse_of_unit()
|
|
728
|
+
for n, f in enumerate(self._polynomial.coefficients(sparse=False)):
|
|
729
|
+
if n == 0:
|
|
730
|
+
der += QM(f.serre_derivative())
|
|
731
|
+
else:
|
|
732
|
+
A = (E2 ** n) * f.serre_derivative()
|
|
733
|
+
B = R(n) * f * E2 ** (n - 1) * E2deriv
|
|
734
|
+
C = R(n) * u6 * E2 ** (n + 1) * f
|
|
735
|
+
der += QM(A + B - C)
|
|
736
|
+
return der
|
|
737
|
+
|
|
738
|
+
def derivative(self):
|
|
739
|
+
r"""
|
|
740
|
+
Return the derivative `q \frac{d}{dq}` of the given quasimodular form.
|
|
741
|
+
|
|
742
|
+
If the form is not homogeneous, then this method sums the derivative of
|
|
743
|
+
each homogeneous component.
|
|
744
|
+
|
|
745
|
+
EXAMPLES::
|
|
746
|
+
|
|
747
|
+
sage: QM = QuasiModularForms(1)
|
|
748
|
+
sage: E2, E4, E6 = QM.gens()
|
|
749
|
+
sage: dE2 = E2.derivative(); dE2
|
|
750
|
+
-24*q - 144*q^2 - 288*q^3 - 672*q^4 - 720*q^5 + O(q^6)
|
|
751
|
+
sage: dE2 == (E2^2 - E4)/12 # Ramanujan identity
|
|
752
|
+
True
|
|
753
|
+
sage: dE4 = E4.derivative(); dE4
|
|
754
|
+
240*q + 4320*q^2 + 20160*q^3 + 70080*q^4 + 151200*q^5 + O(q^6)
|
|
755
|
+
sage: dE4 == (E2 * E4 - E6)/3 # Ramanujan identity
|
|
756
|
+
True
|
|
757
|
+
sage: dE6 = E6.derivative(); dE6
|
|
758
|
+
-504*q - 33264*q^2 - 368928*q^3 - 2130912*q^4 - 7877520*q^5 + O(q^6)
|
|
759
|
+
sage: dE6 == (E2 * E6 - E4^2)/2 # Ramanujan identity
|
|
760
|
+
True
|
|
761
|
+
|
|
762
|
+
Note that the derivative of a modular form is not necessarily a modular form::
|
|
763
|
+
|
|
764
|
+
sage: dE4.is_modular_form()
|
|
765
|
+
False
|
|
766
|
+
sage: dE4.weight()
|
|
767
|
+
6
|
|
768
|
+
"""
|
|
769
|
+
QM = self.parent()
|
|
770
|
+
E2 = QM.gen(0)
|
|
771
|
+
R = self.base_ring()
|
|
772
|
+
u = R(12).inverse_of_unit()
|
|
773
|
+
hom_comp = self.homogeneous_components()
|
|
774
|
+
|
|
775
|
+
return sum(f.serre_derivative() + R(k) * u * f * E2 for k, f in hom_comp.items())
|
|
776
|
+
|
|
777
|
+
def _compute(self, X):
|
|
778
|
+
r"""
|
|
779
|
+
Compute the coefficients of `q^n` of the `q`-expansion of this,
|
|
780
|
+
graded quasimodular form for `n` in the list `X`.
|
|
781
|
+
|
|
782
|
+
The results are not cached. (Use coefficients for cached results).
|
|
783
|
+
|
|
784
|
+
EXAMPLES::
|
|
785
|
+
|
|
786
|
+
sage: E2 = QuasiModularForms(1).0
|
|
787
|
+
sage: E2.q_expansion(10)
|
|
788
|
+
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 - 288*q^6 - 192*q^7 - 360*q^8 - 312*q^9 + O(q^10)
|
|
789
|
+
sage: E2._compute([3, 6])
|
|
790
|
+
[-96, -288]
|
|
791
|
+
sage: E2._compute([])
|
|
792
|
+
[]
|
|
793
|
+
"""
|
|
794
|
+
if not isinstance(X, list) or not X:
|
|
795
|
+
return []
|
|
796
|
+
bound = max(X)
|
|
797
|
+
q_exp = self.q_expansion(bound + 1)
|
|
798
|
+
return [q_exp[i] for i in X]
|
|
799
|
+
|
|
800
|
+
def coefficients(self, X):
|
|
801
|
+
r"""
|
|
802
|
+
Return the coefficients of `q^n` of the `q`-expansion of this,
|
|
803
|
+
graded quasimodular form for `n` in the list `X`.
|
|
804
|
+
|
|
805
|
+
If X is an integer, return coefficients for indices from 1
|
|
806
|
+
to X. This method caches the result.
|
|
807
|
+
|
|
808
|
+
EXAMPLES::
|
|
809
|
+
|
|
810
|
+
sage: E2, E4 = QuasiModularForms(1).0, QuasiModularForms(1).1
|
|
811
|
+
sage: f = E2^2
|
|
812
|
+
sage: g = E2^3 * E4
|
|
813
|
+
sage: f.coefficients(10)
|
|
814
|
+
[-48, 432, 3264, 9456, 21600, 39744, 66432, 105840, 147984, 220320]
|
|
815
|
+
sage: f.coefficients([0,1])
|
|
816
|
+
[1, -48]
|
|
817
|
+
sage: f.coefficients([0,1,2,3])
|
|
818
|
+
[1, -48, 432, 3264]
|
|
819
|
+
sage: f.coefficients([2,3])
|
|
820
|
+
[432, 3264]
|
|
821
|
+
sage: g.coefficients(10)
|
|
822
|
+
[168,
|
|
823
|
+
-13608,
|
|
824
|
+
210336,
|
|
825
|
+
1805496,
|
|
826
|
+
-22562064,
|
|
827
|
+
-322437024,
|
|
828
|
+
-2063087808,
|
|
829
|
+
-9165872520,
|
|
830
|
+
-32250917496,
|
|
831
|
+
-96383477232]
|
|
832
|
+
sage: g.coefficients([3, 7])
|
|
833
|
+
[210336, -2063087808]
|
|
834
|
+
"""
|
|
835
|
+
try:
|
|
836
|
+
self.__coefficients
|
|
837
|
+
except AttributeError:
|
|
838
|
+
self.__coefficients = {}
|
|
839
|
+
if isinstance(X, Integer):
|
|
840
|
+
X = list(range(1, X + 1))
|
|
841
|
+
Y = [n for n in X if n not in self.__coefficients]
|
|
842
|
+
v = self._compute(Y)
|
|
843
|
+
for i in range(len(v)):
|
|
844
|
+
self.__coefficients[Y[i]] = v[i]
|
|
845
|
+
return [self.__coefficients[x] for x in X]
|