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,2225 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.graphs
|
|
3
|
+
r"""
|
|
4
|
+
Elements of graded rings of modular forms for Hecke triangle groups
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
- Jonas Jermann (2013): initial version
|
|
9
|
+
"""
|
|
10
|
+
# ****************************************************************************
|
|
11
|
+
# Copyright (C) 2013-2014 Jonas Jermann <jjermann2@gmail.com>
|
|
12
|
+
#
|
|
13
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
14
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
15
|
+
# the License, or (at your option) any later version.
|
|
16
|
+
# https://www.gnu.org/licenses/
|
|
17
|
+
# ****************************************************************************
|
|
18
|
+
|
|
19
|
+
from sage.functions.log import exp
|
|
20
|
+
from sage.misc.cachefunc import cached_method
|
|
21
|
+
from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
|
|
22
|
+
from sage.misc.lazy_import import lazy_import
|
|
23
|
+
from sage.modules.free_module_element import vector
|
|
24
|
+
from sage.rings.big_oh import O
|
|
25
|
+
from sage.rings.infinity import infinity
|
|
26
|
+
from sage.rings.integer_ring import ZZ
|
|
27
|
+
from sage.rings.laurent_series_ring_element import LaurentSeries
|
|
28
|
+
from sage.structure.element import CommutativeAlgebraElement
|
|
29
|
+
from sage.structure.parent_gens import localvars
|
|
30
|
+
from sage.structure.richcmp import op_NE, op_EQ
|
|
31
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
32
|
+
|
|
33
|
+
lazy_import("sage.functions.log", "exp")
|
|
34
|
+
lazy_import("sage.rings.number_field.number_field", "QuadraticField")
|
|
35
|
+
lazy_import("sage.symbolic.constants", "pi")
|
|
36
|
+
|
|
37
|
+
from .constructor import rational_type, FormsSpace, FormsRing
|
|
38
|
+
from .series_constructor import MFSeriesConstructor
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _in_HyperbolicPlane(x):
|
|
42
|
+
try:
|
|
43
|
+
from sage.geometry.hyperbolic_space.hyperbolic_interface import HyperbolicPlane
|
|
44
|
+
except ImportError:
|
|
45
|
+
return False
|
|
46
|
+
return x in HyperbolicPlane()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# Warning: We choose CommutativeAlgebraElement because we want the
|
|
50
|
+
# corresponding operations (e.g. __pow__) even though the category
|
|
51
|
+
# (and class) of the parent is in some cases not
|
|
52
|
+
# CommutativeAlgebras but Modules
|
|
53
|
+
class FormsRingElement(CommutativeAlgebraElement, UniqueRepresentation,
|
|
54
|
+
metaclass=InheritComparisonClasscallMetaclass):
|
|
55
|
+
r"""
|
|
56
|
+
Element of a FormsRing.
|
|
57
|
+
"""
|
|
58
|
+
from .analytic_type import AnalyticType
|
|
59
|
+
AT = AnalyticType()
|
|
60
|
+
|
|
61
|
+
@staticmethod
|
|
62
|
+
def __classcall__(cls, parent, rat):
|
|
63
|
+
r"""
|
|
64
|
+
Return a (cached) instance with canonical parameters.
|
|
65
|
+
|
|
66
|
+
EXAMPLES::
|
|
67
|
+
|
|
68
|
+
sage: # needs sage.symbolic
|
|
69
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring_element import FormsRingElement
|
|
70
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import ModularFormsRing
|
|
71
|
+
sage: x, d = var("x","d")
|
|
72
|
+
sage: el = FormsRingElement(ModularFormsRing(), x*d)
|
|
73
|
+
sage: el.rat()
|
|
74
|
+
x*d
|
|
75
|
+
sage: el.rat().parent()
|
|
76
|
+
Fraction Field of Multivariate Polynomial Ring in x, y, z, d over Integer Ring
|
|
77
|
+
"""
|
|
78
|
+
rat = parent.rat_field()(rat)
|
|
79
|
+
# rat.reduce() <- maybe add this for the nonexact case
|
|
80
|
+
|
|
81
|
+
return super().__classcall__(cls, parent, rat)
|
|
82
|
+
|
|
83
|
+
def __init__(self, parent, rat):
|
|
84
|
+
r"""
|
|
85
|
+
Element of a FormsRing ``parent`` corresponding to the rational
|
|
86
|
+
function ``rat`` evaluated at ``x=f_rho``, ``y=f_i``, ``z=E2``
|
|
87
|
+
and ``d`` by the formal parameter from ``parent.coeff_ring()``.
|
|
88
|
+
|
|
89
|
+
The functions ``f_rho, f_i, E2`` can be obtained from
|
|
90
|
+
``self.parent().graded_ring()``.
|
|
91
|
+
|
|
92
|
+
.. NOTE::
|
|
93
|
+
|
|
94
|
+
If ``n=Infinity`` then the variable ``x`` refers to ``E4`` instead
|
|
95
|
+
of ``f_rho=1``.
|
|
96
|
+
|
|
97
|
+
INPUT:
|
|
98
|
+
|
|
99
|
+
- ``parent`` -- (non abstract) instance of ``FormsRing_abstract``
|
|
100
|
+
|
|
101
|
+
- ``rat`` -- a rational function in ``parent.rat_field()``, the
|
|
102
|
+
fraction field of the polynomial ring in ``x,y,z,d`` over the base
|
|
103
|
+
ring of ``parent``
|
|
104
|
+
|
|
105
|
+
OUTPUT:
|
|
106
|
+
|
|
107
|
+
An element of ``parent``. If ``rat`` does not correspond to such
|
|
108
|
+
an element an exception is raised.
|
|
109
|
+
|
|
110
|
+
EXAMPLES::
|
|
111
|
+
|
|
112
|
+
sage: # needs sage.symbolic
|
|
113
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
114
|
+
sage: x, y, z, d = var("x,y,z,d")
|
|
115
|
+
sage: MR = QuasiModularFormsRing(n=5)
|
|
116
|
+
sage: el = MR(x^3*d + y*z); el
|
|
117
|
+
f_rho^3*d + f_i*E2
|
|
118
|
+
sage: el.rat()
|
|
119
|
+
x^3*d + y*z
|
|
120
|
+
sage: el.parent()
|
|
121
|
+
QuasiModularFormsRing(n=5) over Integer Ring
|
|
122
|
+
sage: el.rat().parent()
|
|
123
|
+
Fraction Field of Multivariate Polynomial Ring in x, y, z, d over Integer Ring
|
|
124
|
+
sage: MR = QuasiModularFormsRing(n=infinity)
|
|
125
|
+
sage: el = MR(d*x*(x-y^2)); el
|
|
126
|
+
-E4*f_i^2*d + E4^2*d
|
|
127
|
+
sage: el.rat()
|
|
128
|
+
-x*y^2*d + x^2*d
|
|
129
|
+
sage: el.parent()
|
|
130
|
+
QuasiModularFormsRing(n=+Infinity) over Integer Ring
|
|
131
|
+
"""
|
|
132
|
+
self._rat = rat
|
|
133
|
+
(elem, homo, self._weight, self._ep, self._analytic_type) = rational_type(rat, parent.hecke_n(), parent.base_ring())
|
|
134
|
+
|
|
135
|
+
if not (elem and
|
|
136
|
+
self._analytic_type <= parent.analytic_type()):
|
|
137
|
+
raise ValueError("{} does not correspond to an element of the {}.".format(rat, parent))
|
|
138
|
+
|
|
139
|
+
super().__init__(parent)
|
|
140
|
+
|
|
141
|
+
# Unfortunately the polynomial ring does not give unique
|
|
142
|
+
# representations of elements (with respect to ==)
|
|
143
|
+
def _richcmp_(self, other, op):
|
|
144
|
+
r"""
|
|
145
|
+
Return whether ``self`` is equal to ``other``.
|
|
146
|
+
|
|
147
|
+
They are considered equal if the corresponding rational
|
|
148
|
+
functions are equal and the groups match up.
|
|
149
|
+
|
|
150
|
+
EXAMPLES::
|
|
151
|
+
|
|
152
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import MeromorphicModularFormsRing
|
|
153
|
+
sage: x, y, z, d = MeromorphicModularFormsRing().pol_ring().gens()
|
|
154
|
+
sage: MeromorphicModularFormsRing(n=3)(x) == MeromorphicModularFormsRing(n=4)(x)
|
|
155
|
+
False
|
|
156
|
+
sage: MeromorphicModularFormsRing()(-1/x) is MeromorphicModularFormsRing()(1/(-x))
|
|
157
|
+
True
|
|
158
|
+
sage: MeromorphicModularFormsRing(base_ring=CC)(-1/x) == MeromorphicModularFormsRing()(1/(-x))
|
|
159
|
+
True
|
|
160
|
+
"""
|
|
161
|
+
if op not in [op_EQ, op_NE]:
|
|
162
|
+
return NotImplemented
|
|
163
|
+
|
|
164
|
+
if self.group() == other.group():
|
|
165
|
+
if self.group().is_arithmetic():
|
|
166
|
+
b = (self.rat().subs(d=self.group().dvalue()) ==
|
|
167
|
+
other.rat().subs(d=other.group().dvalue()))
|
|
168
|
+
else:
|
|
169
|
+
b = (self.rat() == other.rat())
|
|
170
|
+
|
|
171
|
+
return b == (op == op_EQ)
|
|
172
|
+
|
|
173
|
+
def _repr_(self):
|
|
174
|
+
r"""
|
|
175
|
+
Return the string representation of ``self``.
|
|
176
|
+
|
|
177
|
+
EXAMPLES::
|
|
178
|
+
|
|
179
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
180
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
181
|
+
sage: QuasiModularFormsRing(n=5)(x^3*z - d*y) # needs sage.symbolic
|
|
182
|
+
f_rho^3*E2 - f_i*d
|
|
183
|
+
|
|
184
|
+
sage: QuasiModularFormsRing(n=infinity)(x) # needs sage.symbolic
|
|
185
|
+
E4
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
return self._rat_repr()
|
|
189
|
+
|
|
190
|
+
def _rat_repr(self):
|
|
191
|
+
r"""
|
|
192
|
+
Return a string representation of ``self`` as a rational function in the generators.
|
|
193
|
+
|
|
194
|
+
EXAMPLES::
|
|
195
|
+
|
|
196
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
|
|
197
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
198
|
+
sage: QuasiModularForms(n=5, k=6, ep=-1)(x^3*z)._rat_repr() # needs sage.symbolic
|
|
199
|
+
'f_rho^3*E2'
|
|
200
|
+
|
|
201
|
+
sage: QuasiModularForms(n=infinity, k=10)(x*(x-y^2)*z)._rat_repr() # needs sage.symbolic
|
|
202
|
+
'-E4*f_i^2*E2 + E4^2*E2'
|
|
203
|
+
"""
|
|
204
|
+
if self.hecke_n() == infinity:
|
|
205
|
+
with localvars(self.parent()._pol_ring, "E4, f_i, E2, d"):
|
|
206
|
+
pol_str = str(self._rat)
|
|
207
|
+
else:
|
|
208
|
+
with localvars(self.parent()._pol_ring, "f_rho, f_i, E2, d"):
|
|
209
|
+
pol_str = str(self._rat)
|
|
210
|
+
|
|
211
|
+
return pol_str
|
|
212
|
+
|
|
213
|
+
def _qexp_repr(self):
|
|
214
|
+
r"""
|
|
215
|
+
Return a string representation of ``self`` as a Fourier series.
|
|
216
|
+
|
|
217
|
+
EXAMPLES::
|
|
218
|
+
|
|
219
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
220
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
221
|
+
sage: MR = QuasiModularFormsRing(n=5)
|
|
222
|
+
sage: MR.disp_prec(3)
|
|
223
|
+
sage: MR(x^3*z-d*y)._qexp_repr() # needs sage.symbolic
|
|
224
|
+
'-d + 1 + ((65*d + 33)/(200*d))*q + ((1755*d + 1437)/(320000*d^2))*q^2 + O(q^3)'
|
|
225
|
+
|
|
226
|
+
sage: QuasiModularFormsRing(n=infinity)(x*(x-y^2)*z)._qexp_repr() # needs sage.symbolic
|
|
227
|
+
'64*q - 3840*q^3 - 16384*q^4 + O(q^5)'
|
|
228
|
+
"""
|
|
229
|
+
|
|
230
|
+
# For now the series constructor doesn't behave well for non exact bases... :(
|
|
231
|
+
if (self.group().is_arithmetic() or not self.base_ring().is_exact()):
|
|
232
|
+
return str(self.q_expansion_fixed_d().add_bigoh(self.parent()._disp_prec))
|
|
233
|
+
else:
|
|
234
|
+
return str(self.q_expansion().add_bigoh(self.parent()._disp_prec))
|
|
235
|
+
|
|
236
|
+
def _latex_(self):
|
|
237
|
+
r"""
|
|
238
|
+
Return the LaTeX representation of ``self``.
|
|
239
|
+
|
|
240
|
+
EXAMPLES::
|
|
241
|
+
|
|
242
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
243
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
244
|
+
sage: latex(QuasiModularFormsRing(n=5)(x^3*z - d*y)) # needs sage.symbolic
|
|
245
|
+
f_{\rho}^{3} E_{2} - f_{i} d
|
|
246
|
+
|
|
247
|
+
sage: from sage.modular.modform_hecketriangle.space import CuspForms
|
|
248
|
+
sage: latex(CuspForms(k=12)(x^3 - y^2)) # needs sage.symbolic
|
|
249
|
+
f_{\rho}^{3} - f_{i}^{2}
|
|
250
|
+
|
|
251
|
+
sage: latex(QuasiModularFormsRing(n=infinity)(x*(x-y^2)*z)) # needs sage.symbolic
|
|
252
|
+
-E_{4} f_{i}^{2} E_{2} + E_{4}^{2} E_{2}
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
from sage.misc.latex import latex
|
|
256
|
+
|
|
257
|
+
if (self.hecke_n() == infinity):
|
|
258
|
+
with localvars(self.parent()._pol_ring, "E4, f_i, E2, d"):
|
|
259
|
+
latex_str = latex(self._rat)
|
|
260
|
+
else:
|
|
261
|
+
with localvars(self.parent()._pol_ring, "f_rho, f_i, E2, d"):
|
|
262
|
+
latex_str = latex(self._rat)
|
|
263
|
+
|
|
264
|
+
return latex_str
|
|
265
|
+
|
|
266
|
+
def group(self):
|
|
267
|
+
r"""
|
|
268
|
+
Return the (Hecke triangle) group of ``self.parent()``.
|
|
269
|
+
|
|
270
|
+
EXAMPLES::
|
|
271
|
+
|
|
272
|
+
sage: from sage.modular.modform_hecketriangle.space import ModularForms
|
|
273
|
+
sage: ModularForms(n=12, k=4).E4().group()
|
|
274
|
+
Hecke triangle group for n = 12
|
|
275
|
+
"""
|
|
276
|
+
|
|
277
|
+
return self.parent().group()
|
|
278
|
+
|
|
279
|
+
def hecke_n(self):
|
|
280
|
+
r"""
|
|
281
|
+
Return the parameter ``n`` of the (Hecke triangle) group of ``self.parent()``.
|
|
282
|
+
|
|
283
|
+
EXAMPLES::
|
|
284
|
+
|
|
285
|
+
sage: from sage.modular.modform_hecketriangle.space import ModularForms
|
|
286
|
+
sage: ModularForms(n=12, k=6).E6().hecke_n()
|
|
287
|
+
12
|
|
288
|
+
"""
|
|
289
|
+
|
|
290
|
+
return self.parent().hecke_n()
|
|
291
|
+
|
|
292
|
+
def base_ring(self):
|
|
293
|
+
r"""
|
|
294
|
+
Return base ring of ``self.parent()``.
|
|
295
|
+
|
|
296
|
+
EXAMPLES::
|
|
297
|
+
|
|
298
|
+
sage: from sage.modular.modform_hecketriangle.space import ModularForms
|
|
299
|
+
sage: ModularForms(n=12, k=4, base_ring=CC).E4().base_ring()
|
|
300
|
+
Complex Field with 53 bits of precision
|
|
301
|
+
"""
|
|
302
|
+
|
|
303
|
+
return self.parent().base_ring()
|
|
304
|
+
|
|
305
|
+
def coeff_ring(self):
|
|
306
|
+
r"""
|
|
307
|
+
Return coefficient ring of ``self``.
|
|
308
|
+
|
|
309
|
+
EXAMPLES::
|
|
310
|
+
|
|
311
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import ModularFormsRing
|
|
312
|
+
sage: ModularFormsRing().E6().coeff_ring()
|
|
313
|
+
Fraction Field of Univariate Polynomial Ring in d over Integer Ring
|
|
314
|
+
"""
|
|
315
|
+
|
|
316
|
+
return self.parent().coeff_ring()
|
|
317
|
+
|
|
318
|
+
def rat(self):
|
|
319
|
+
r"""
|
|
320
|
+
Return the rational function representing ``self``.
|
|
321
|
+
|
|
322
|
+
EXAMPLES::
|
|
323
|
+
|
|
324
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import ModularFormsRing
|
|
325
|
+
sage: ModularFormsRing(n=12).Delta().rat()
|
|
326
|
+
x^30*d - x^18*y^2*d
|
|
327
|
+
"""
|
|
328
|
+
|
|
329
|
+
return self._rat
|
|
330
|
+
|
|
331
|
+
def _reduce_d(self):
|
|
332
|
+
r"""
|
|
333
|
+
Return a new version of ``self`` where `d` is replaced by its value in
|
|
334
|
+
the presentation of ``self`` as a rational function in the polynomial generators.
|
|
335
|
+
|
|
336
|
+
The new element still compares equal to the old one but the corresponding
|
|
337
|
+
rational function no longer contains any ``d`` (in the arithmetic cases).
|
|
338
|
+
|
|
339
|
+
EXAMPLES::
|
|
340
|
+
|
|
341
|
+
sage: from sage.modular.modform_hecketriangle.space import ModularForms, WeakModularForms
|
|
342
|
+
sage: Delta = ModularForms().Delta()
|
|
343
|
+
sage: Delta.rat()
|
|
344
|
+
x^3*d - y^2*d
|
|
345
|
+
sage: Delta2 = Delta._reduce_d()
|
|
346
|
+
sage: Delta2.rat()
|
|
347
|
+
(x^3 - y^2)/1728
|
|
348
|
+
sage: Delta == Delta2
|
|
349
|
+
True
|
|
350
|
+
"""
|
|
351
|
+
|
|
352
|
+
if not self.group().is_arithmetic():
|
|
353
|
+
return self
|
|
354
|
+
|
|
355
|
+
d = self.parent().get_d(fix_d=True)
|
|
356
|
+
return self.parent()(self._rat.subs(d=d))
|
|
357
|
+
|
|
358
|
+
def is_homogeneous(self) -> bool:
|
|
359
|
+
r"""
|
|
360
|
+
Return whether ``self`` is homogeneous.
|
|
361
|
+
|
|
362
|
+
EXAMPLES::
|
|
363
|
+
|
|
364
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
365
|
+
sage: QuasiModularFormsRing(n=12).Delta().is_homogeneous()
|
|
366
|
+
True
|
|
367
|
+
sage: QuasiModularFormsRing(n=12).Delta().parent().is_homogeneous()
|
|
368
|
+
False
|
|
369
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
370
|
+
sage: QuasiModularFormsRing(n=12)(x^3+y^2+z+d).is_homogeneous() # needs sage.symbolic
|
|
371
|
+
False
|
|
372
|
+
|
|
373
|
+
sage: QuasiModularFormsRing(n=infinity)(x*(x-y^2)+y^4).is_homogeneous() # needs sage.symbolic
|
|
374
|
+
True
|
|
375
|
+
"""
|
|
376
|
+
return self._weight is not None
|
|
377
|
+
|
|
378
|
+
def weight(self):
|
|
379
|
+
r"""
|
|
380
|
+
Return the weight of ``self``.
|
|
381
|
+
|
|
382
|
+
EXAMPLES::
|
|
383
|
+
|
|
384
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
385
|
+
sage: from sage.modular.modform_hecketriangle.space import ModularForms
|
|
386
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
387
|
+
sage: QuasiModularFormsRing()(x+y).weight() is None # needs sage.symbolic
|
|
388
|
+
True
|
|
389
|
+
sage: ModularForms(n=18).f_i().weight()
|
|
390
|
+
9/4
|
|
391
|
+
sage: ModularForms(n=infinity).f_inf().weight()
|
|
392
|
+
4
|
|
393
|
+
"""
|
|
394
|
+
|
|
395
|
+
return self._weight
|
|
396
|
+
|
|
397
|
+
def ep(self):
|
|
398
|
+
r"""
|
|
399
|
+
Return the multiplier of ``self``.
|
|
400
|
+
|
|
401
|
+
EXAMPLES::
|
|
402
|
+
|
|
403
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
404
|
+
sage: from sage.modular.modform_hecketriangle.space import ModularForms
|
|
405
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
406
|
+
sage: QuasiModularFormsRing()(x+y).ep() is None # needs sage.symbolic
|
|
407
|
+
True
|
|
408
|
+
sage: ModularForms(n=18).f_i().ep()
|
|
409
|
+
-1
|
|
410
|
+
sage: ModularForms(n=infinity).E2().ep()
|
|
411
|
+
-1
|
|
412
|
+
"""
|
|
413
|
+
|
|
414
|
+
return self._ep
|
|
415
|
+
|
|
416
|
+
def degree(self):
|
|
417
|
+
r"""
|
|
418
|
+
Return the degree of ``self`` in the graded ring.
|
|
419
|
+
If ``self`` is not homogeneous, then ``(None, None)``
|
|
420
|
+
is returned.
|
|
421
|
+
|
|
422
|
+
EXAMPLES::
|
|
423
|
+
|
|
424
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
425
|
+
sage: from sage.modular.modform_hecketriangle.space import ModularForms
|
|
426
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
427
|
+
sage: QuasiModularFormsRing()(x+y).degree() == (None, None) # needs sage.symbolic
|
|
428
|
+
True
|
|
429
|
+
sage: ModularForms(n=18).f_i().degree()
|
|
430
|
+
(9/4, -1)
|
|
431
|
+
sage: ModularForms(n=infinity).f_rho().degree()
|
|
432
|
+
(0, 1)
|
|
433
|
+
"""
|
|
434
|
+
return (self._weight, self._ep)
|
|
435
|
+
|
|
436
|
+
def is_modular(self) -> bool:
|
|
437
|
+
r"""
|
|
438
|
+
Return whether ``self`` (resp. its homogeneous components)
|
|
439
|
+
transform like modular forms.
|
|
440
|
+
|
|
441
|
+
EXAMPLES::
|
|
442
|
+
|
|
443
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
444
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
|
|
445
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
446
|
+
sage: QuasiModularFormsRing(n=5)(x^2+y-d).is_modular() # needs sage.symbolic
|
|
447
|
+
True
|
|
448
|
+
sage: QuasiModularFormsRing(n=5)(x^2+y-d+z).is_modular() # needs sage.symbolic
|
|
449
|
+
False
|
|
450
|
+
sage: QuasiModularForms(n=18).f_i().is_modular()
|
|
451
|
+
True
|
|
452
|
+
sage: QuasiModularForms(n=18).E2().is_modular()
|
|
453
|
+
False
|
|
454
|
+
sage: QuasiModularForms(n=infinity).f_inf().is_modular()
|
|
455
|
+
True
|
|
456
|
+
"""
|
|
457
|
+
return not (self.AT("quasi") <= self._analytic_type)
|
|
458
|
+
|
|
459
|
+
def is_weakly_holomorphic(self) -> bool:
|
|
460
|
+
r"""
|
|
461
|
+
Return whether ``self`` is weakly holomorphic.
|
|
462
|
+
|
|
463
|
+
This means that ``self`` has at most a power of ``f_inf``
|
|
464
|
+
in its denominator.
|
|
465
|
+
|
|
466
|
+
EXAMPLES::
|
|
467
|
+
|
|
468
|
+
sage: # needs sage.symbolic
|
|
469
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
470
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms
|
|
471
|
+
sage: x, y, z, d = var("x,y,z,d")
|
|
472
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)(x/(x^5-y^2)+z).is_weakly_holomorphic()
|
|
473
|
+
True
|
|
474
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)(x^2+y/x-d).is_weakly_holomorphic()
|
|
475
|
+
False
|
|
476
|
+
sage: QuasiMeromorphicModularForms(n=18).J_inv().is_weakly_holomorphic()
|
|
477
|
+
True
|
|
478
|
+
sage: QuasiMeromorphicModularForms(n=infinity, k=-4)(1/x).is_weakly_holomorphic()
|
|
479
|
+
True
|
|
480
|
+
sage: QuasiMeromorphicModularForms(n=infinity, k=-2)(1/y).is_weakly_holomorphic()
|
|
481
|
+
False
|
|
482
|
+
"""
|
|
483
|
+
|
|
484
|
+
return self.AT("weak", "quasi") >= self._analytic_type
|
|
485
|
+
|
|
486
|
+
def is_holomorphic(self) -> bool:
|
|
487
|
+
r"""
|
|
488
|
+
Return whether ``self`` is holomorphic
|
|
489
|
+
in the sense that the denominator of ``self``
|
|
490
|
+
is constant.
|
|
491
|
+
|
|
492
|
+
EXAMPLES::
|
|
493
|
+
|
|
494
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
495
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms
|
|
496
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
497
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)((y^3-z^5)/(x^5-y^2)+y-d).is_holomorphic() # needs sage.symbolic
|
|
498
|
+
False
|
|
499
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)(x^2+y-d+z).is_holomorphic() # needs sage.symbolic
|
|
500
|
+
True
|
|
501
|
+
sage: QuasiMeromorphicModularForms(n=18).J_inv().is_holomorphic()
|
|
502
|
+
False
|
|
503
|
+
sage: QuasiMeromorphicModularForms(n=18).f_i().is_holomorphic()
|
|
504
|
+
True
|
|
505
|
+
sage: QuasiMeromorphicModularForms(n=infinity).f_inf().is_holomorphic()
|
|
506
|
+
True
|
|
507
|
+
"""
|
|
508
|
+
|
|
509
|
+
return self.AT("holo", "quasi") >= self._analytic_type
|
|
510
|
+
|
|
511
|
+
def is_cuspidal(self) -> bool:
|
|
512
|
+
r"""
|
|
513
|
+
Return whether ``self`` is cuspidal.
|
|
514
|
+
|
|
515
|
+
This means that ``self`` is holomorphic and ``f_inf``
|
|
516
|
+
divides the numerator.
|
|
517
|
+
|
|
518
|
+
EXAMPLES::
|
|
519
|
+
|
|
520
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
521
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
|
|
522
|
+
sage: x, y, z, d = var("x,y,z,d") # needs sage.symbolic
|
|
523
|
+
sage: QuasiModularFormsRing(n=5)(y^3-z^5).is_cuspidal() # needs sage.symbolic
|
|
524
|
+
False
|
|
525
|
+
sage: QuasiModularFormsRing(n=5)(z*x^5-z*y^2).is_cuspidal() # needs sage.symbolic
|
|
526
|
+
True
|
|
527
|
+
sage: QuasiModularForms(n=18).Delta().is_cuspidal()
|
|
528
|
+
True
|
|
529
|
+
sage: QuasiModularForms(n=18).f_rho().is_cuspidal()
|
|
530
|
+
False
|
|
531
|
+
sage: QuasiModularForms(n=infinity).f_inf().is_cuspidal()
|
|
532
|
+
False
|
|
533
|
+
sage: QuasiModularForms(n=infinity).Delta().is_cuspidal()
|
|
534
|
+
True
|
|
535
|
+
"""
|
|
536
|
+
return self.AT("cusp", "quasi") >= self._analytic_type
|
|
537
|
+
|
|
538
|
+
def is_zero(self) -> bool:
|
|
539
|
+
r"""
|
|
540
|
+
Return whether ``self`` is the zero function.
|
|
541
|
+
|
|
542
|
+
EXAMPLES::
|
|
543
|
+
|
|
544
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiModularFormsRing
|
|
545
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
|
|
546
|
+
sage: QuasiModularFormsRing(n=5)(1).is_zero()
|
|
547
|
+
False
|
|
548
|
+
sage: QuasiModularFormsRing(n=5)(0).is_zero()
|
|
549
|
+
True
|
|
550
|
+
sage: QuasiModularForms(n=18).zero().is_zero()
|
|
551
|
+
True
|
|
552
|
+
sage: QuasiModularForms(n=18).Delta().is_zero()
|
|
553
|
+
False
|
|
554
|
+
sage: QuasiModularForms(n=infinity).f_rho().is_zero()
|
|
555
|
+
False
|
|
556
|
+
"""
|
|
557
|
+
return self.AT(["quasi"]) >= self._analytic_type
|
|
558
|
+
|
|
559
|
+
def analytic_type(self):
|
|
560
|
+
r"""
|
|
561
|
+
Return the analytic type of ``self``.
|
|
562
|
+
|
|
563
|
+
EXAMPLES::
|
|
564
|
+
|
|
565
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
566
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms
|
|
567
|
+
|
|
568
|
+
sage: # needs sage.symbolic
|
|
569
|
+
sage: x, y, z, d = var("x,y,z,d")
|
|
570
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)(x/z+d).analytic_type()
|
|
571
|
+
quasi meromorphic modular
|
|
572
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)((y^3-z^5)/(x^5-y^2)+y-d).analytic_type()
|
|
573
|
+
quasi weakly holomorphic modular
|
|
574
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)(x^2+y-d).analytic_type()
|
|
575
|
+
modular
|
|
576
|
+
|
|
577
|
+
sage: QuasiMeromorphicModularForms(n=18).J_inv().analytic_type()
|
|
578
|
+
weakly holomorphic modular
|
|
579
|
+
sage: QuasiMeromorphicModularForms(n=18).f_inf().analytic_type()
|
|
580
|
+
cuspidal
|
|
581
|
+
sage: QuasiMeromorphicModularForms(n=infinity).f_inf().analytic_type()
|
|
582
|
+
modular
|
|
583
|
+
"""
|
|
584
|
+
return self._analytic_type
|
|
585
|
+
|
|
586
|
+
def numerator(self):
|
|
587
|
+
r"""
|
|
588
|
+
Return the numerator of ``self``.
|
|
589
|
+
|
|
590
|
+
I.e. the (properly reduced) new form corresponding to
|
|
591
|
+
the numerator of ``self.rat()``.
|
|
592
|
+
|
|
593
|
+
Note that the parent of ``self`` might (probably will) change.
|
|
594
|
+
|
|
595
|
+
EXAMPLES::
|
|
596
|
+
|
|
597
|
+
sage: # needs sage.symbolic
|
|
598
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
599
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms
|
|
600
|
+
sage: x, y, z, d = var("x,y,z,d")
|
|
601
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)((y^3-z^5)/(x^5-y^2)+y-d).numerator()
|
|
602
|
+
f_rho^5*f_i - f_rho^5*d - E2^5 + f_i^2*d
|
|
603
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)((y^3-z^5)/(x^5-y^2)+y-d).numerator().parent()
|
|
604
|
+
QuasiModularFormsRing(n=5) over Integer Ring
|
|
605
|
+
sage: QuasiMeromorphicModularForms(n=5, k=-2, ep=-1)(x/y).numerator()
|
|
606
|
+
1 + 7/(100*d)*q + 21/(160000*d^2)*q^2 + 1043/(192000000*d^3)*q^3 + 45479/(1228800000000*d^4)*q^4 + O(q^5)
|
|
607
|
+
sage: QuasiMeromorphicModularForms(n=5, k=-2, ep=-1)(x/y).numerator().parent()
|
|
608
|
+
QuasiModularForms(n=5, k=4/3, ep=1) over Integer Ring
|
|
609
|
+
sage: (QuasiMeromorphicModularForms(n=infinity, k=-2, ep=-1)(y/x)).numerator()
|
|
610
|
+
1 - 24*q + 24*q^2 - 96*q^3 + 24*q^4 + O(q^5)
|
|
611
|
+
sage: (QuasiMeromorphicModularForms(n=infinity, k=-2, ep=-1)(y/x)).numerator().parent()
|
|
612
|
+
QuasiModularForms(n=+Infinity, k=2, ep=-1) over Integer Ring
|
|
613
|
+
"""
|
|
614
|
+
|
|
615
|
+
res = self.parent().rat_field()(self._rat.numerator())
|
|
616
|
+
# In general the numerator has a different weight than the original function...
|
|
617
|
+
new_parent = self.parent().extend_type(ring=True).reduce_type(["holo", "quasi"])
|
|
618
|
+
return new_parent(res).reduce()
|
|
619
|
+
|
|
620
|
+
def denominator(self):
|
|
621
|
+
r"""
|
|
622
|
+
Return the denominator of ``self``.
|
|
623
|
+
I.e. the (properly reduced) new form corresponding to
|
|
624
|
+
the numerator of ``self.rat()``.
|
|
625
|
+
|
|
626
|
+
Note that the parent of ``self`` might (probably will) change.
|
|
627
|
+
|
|
628
|
+
EXAMPLES::
|
|
629
|
+
|
|
630
|
+
sage: # needs sage.symbolic
|
|
631
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
632
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms
|
|
633
|
+
sage: x, y, z, d = var("x,y,z,d")
|
|
634
|
+
sage: QuasiMeromorphicModularFormsRing(n=5).Delta().full_reduce().denominator()
|
|
635
|
+
1 + O(q^5)
|
|
636
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)((y^3-z^5)/(x^5-y^2)+y-d).denominator()
|
|
637
|
+
f_rho^5 - f_i^2
|
|
638
|
+
sage: QuasiMeromorphicModularFormsRing(n=5)((y^3-z^5)/(x^5-y^2)+y-d).denominator().parent()
|
|
639
|
+
QuasiModularFormsRing(n=5) over Integer Ring
|
|
640
|
+
sage: QuasiMeromorphicModularForms(n=5, k=-2, ep=-1)(x/y).denominator()
|
|
641
|
+
1 - 13/(40*d)*q - 351/(64000*d^2)*q^2 - 13819/(76800000*d^3)*q^3 - 1163669/(491520000000*d^4)*q^4 + O(q^5)
|
|
642
|
+
sage: QuasiMeromorphicModularForms(n=5, k=-2, ep=-1)(x/y).denominator().parent()
|
|
643
|
+
QuasiModularForms(n=5, k=10/3, ep=-1) over Integer Ring
|
|
644
|
+
sage: (QuasiMeromorphicModularForms(n=infinity, k=-6, ep=-1)(y/(x*(x-y^2)))).denominator()
|
|
645
|
+
-64*q - 512*q^2 - 768*q^3 + 4096*q^4 + O(q^5)
|
|
646
|
+
sage: (QuasiMeromorphicModularForms(n=infinity, k=-6, ep=-1)(y/(x*(x-y^2)))).denominator().parent()
|
|
647
|
+
QuasiModularForms(n=+Infinity, k=8, ep=1) over Integer Ring
|
|
648
|
+
"""
|
|
649
|
+
|
|
650
|
+
res = self.parent().rat_field()(self._rat.denominator())
|
|
651
|
+
# In general the denominator has a different weight than the original function...
|
|
652
|
+
new_parent = self.parent().extend_type("holo", ring=True).reduce_type(["holo", "quasi"])
|
|
653
|
+
return new_parent(res).reduce()
|
|
654
|
+
|
|
655
|
+
def _add_(self, other):
|
|
656
|
+
r"""
|
|
657
|
+
Return the sum of ``self`` and ``other``.
|
|
658
|
+
|
|
659
|
+
EXAMPLES::
|
|
660
|
+
|
|
661
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
662
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms
|
|
663
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=7)
|
|
664
|
+
sage: E2 = MR.E2().full_reduce()
|
|
665
|
+
sage: E4 = MR.E4().full_reduce()
|
|
666
|
+
sage: E6 = MR.E6().full_reduce()
|
|
667
|
+
sage: Delta = MR.Delta().full_reduce()
|
|
668
|
+
sage: J_inv = MR.J_inv().full_reduce()
|
|
669
|
+
sage: ring_el = MR(1/x+1).full_reduce()
|
|
670
|
+
|
|
671
|
+
sage: (Delta^2*E2 + E6*E4^2).parent()
|
|
672
|
+
QuasiModularFormsRing(n=7) over Integer Ring
|
|
673
|
+
sage: E4 + Delta
|
|
674
|
+
f_rho^15*d - f_rho^8*f_i^2*d + f_rho^5
|
|
675
|
+
sage: (E4 + QQ(1) + ring_el).parent()
|
|
676
|
+
MeromorphicModularFormsRing(n=7) over Integer Ring
|
|
677
|
+
sage: (E4^3 + 1.1*Delta).parent()
|
|
678
|
+
ModularForms(n=7, k=12, ep=1) over Real Field with 53 bits of precision
|
|
679
|
+
sage: (E4 + FractionField(PolynomialRing(CC,'d')).gen()).parent()
|
|
680
|
+
ModularFormsRing(n=7) over Complex Field with 53 bits of precision
|
|
681
|
+
|
|
682
|
+
sage: subspace = MR.reduce_type(["holo"], degree=(12,1)).subspace([Delta, E6^2])
|
|
683
|
+
sage: gen0 = subspace.gen(0)
|
|
684
|
+
sage: gen1 = subspace.gen(1)
|
|
685
|
+
sage: subspace2 = MR.reduce_type(["holo"], degree=(12,1)).subspace([Delta, Delta + E6^2])
|
|
686
|
+
sage: gen2 = subspace2.gen(0)
|
|
687
|
+
sage: gen3 = subspace2.gen(1)
|
|
688
|
+
|
|
689
|
+
sage: (gen0 + gen1).parent()
|
|
690
|
+
Subspace of dimension 2 of ModularForms(n=7, k=12, ep=1) over Integer Ring
|
|
691
|
+
sage: (gen0 + Delta*J_inv).parent()
|
|
692
|
+
WeakModularForms(n=7, k=12, ep=1) over Integer Ring
|
|
693
|
+
sage: gen0 + E2
|
|
694
|
+
f_rho^15*d - f_rho^8*f_i^2*d + E2
|
|
695
|
+
sage: (gen0 + E2).parent()
|
|
696
|
+
QuasiModularFormsRing(n=7) over Integer Ring
|
|
697
|
+
sage: gen2 + ring_el
|
|
698
|
+
(f_rho^16*d - f_rho^9*f_i^2*d + f_rho + 1)/f_rho
|
|
699
|
+
sage: (gen0 + int(1)).parent()
|
|
700
|
+
ModularFormsRing(n=7) over Integer Ring
|
|
701
|
+
|
|
702
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiCuspForms, ModularForms
|
|
703
|
+
sage: MF = ModularForms(k=20, ep=1)
|
|
704
|
+
sage: QCF = QuasiCuspForms(k=20, ep=1)
|
|
705
|
+
sage: el1 = QCF((MF.Delta()*MF.E2()^4))
|
|
706
|
+
sage: el1 = QCF.subspace([el1])(el1)
|
|
707
|
+
sage: el2 = MF(MF.E4()^2*MF.E6()^2)
|
|
708
|
+
sage: el2 = MF.subspace([el2])(el2)
|
|
709
|
+
sage: el3 = el1 + el2 # long time
|
|
710
|
+
sage: el3 # long time
|
|
711
|
+
1 - 527*q - 201288*q^2 + 61120668*q^3 + 20946799216*q^4 + O(q^5)
|
|
712
|
+
sage: el3.parent() # long time
|
|
713
|
+
Subspace of dimension 2 of QuasiModularForms(n=3, k=20, ep=1) over Integer Ring
|
|
714
|
+
|
|
715
|
+
sage: MF = ModularForms(n=infinity)
|
|
716
|
+
sage: MF.E4() + MF.f_rho()
|
|
717
|
+
E4 + 1
|
|
718
|
+
sage: (MF.E4() + MF.f_rho()).parent()
|
|
719
|
+
ModularFormsRing(n=+Infinity) over Integer Ring
|
|
720
|
+
sage: MF.E4() + MF.f_i()^2
|
|
721
|
+
2 - 32*q + 736*q^2 - 896*q^3 + 6368*q^4 + O(q^5)
|
|
722
|
+
sage: (MF.E4() + MF.f_i()^2).parent()
|
|
723
|
+
ModularForms(n=+Infinity, k=4, ep=1) over Integer Ring
|
|
724
|
+
|
|
725
|
+
sage: el = ModularForms(n=3).Delta() + MF.E4()*MF.E6()
|
|
726
|
+
sage: el
|
|
727
|
+
(E4*f_i^4 - 2*E4^2*f_i^2 + E4^3 + 4096*E4^2*f_i)/4096
|
|
728
|
+
sage: el.parent()
|
|
729
|
+
ModularFormsRing(n=+Infinity) over Integer Ring
|
|
730
|
+
"""
|
|
731
|
+
return self.parent()(self._rat + other._rat)
|
|
732
|
+
|
|
733
|
+
def _sub_(self, other):
|
|
734
|
+
r"""
|
|
735
|
+
Return the difference of ``self`` and ``other``.
|
|
736
|
+
|
|
737
|
+
EXAMPLES::
|
|
738
|
+
|
|
739
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
740
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms, ModularForms
|
|
741
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=7)
|
|
742
|
+
sage: E2 = MR.E2().full_reduce()
|
|
743
|
+
sage: E4 = MR.E4().full_reduce()
|
|
744
|
+
sage: E6 = MR.E6().full_reduce()
|
|
745
|
+
sage: Delta = MR.Delta().full_reduce()
|
|
746
|
+
sage: J_inv = MR.J_inv().full_reduce()
|
|
747
|
+
sage: ring_el = MR(1/x+1).full_reduce()
|
|
748
|
+
|
|
749
|
+
sage: E6^2-E4^3
|
|
750
|
+
-1/d*q - 17/(56*d^2)*q^2 - 88887/(2458624*d^3)*q^3 - 941331/(481890304*d^4)*q^4 + O(q^5)
|
|
751
|
+
sage: (E6^2-E4^3).parent()
|
|
752
|
+
ModularForms(n=7, k=12, ep=1) over Integer Ring
|
|
753
|
+
sage: (E4 - int(1)).parent()
|
|
754
|
+
ModularFormsRing(n=7) over Integer Ring
|
|
755
|
+
sage: E4 - FractionField(PolynomialRing(CC,'d')).gen()
|
|
756
|
+
f_rho^5 - d
|
|
757
|
+
sage: ((E4+E6)-E6).parent()
|
|
758
|
+
ModularFormsRing(n=7) over Integer Ring
|
|
759
|
+
|
|
760
|
+
sage: subspace = MR.reduce_type(["holo"], degree=(12,1)).subspace([Delta, E6^2])
|
|
761
|
+
sage: gen0 = subspace.gen(0)
|
|
762
|
+
sage: gen1 = subspace.gen(1)
|
|
763
|
+
sage: subspace2 = MR.reduce_type(["holo"], degree=(12,1)).subspace([Delta, Delta + E6^2])
|
|
764
|
+
sage: gen2 = subspace2.gen(0)
|
|
765
|
+
sage: gen3 = subspace2.gen(1)
|
|
766
|
+
|
|
767
|
+
sage: (gen0 - gen2).parent()
|
|
768
|
+
Subspace of dimension 2 of ModularForms(n=7, k=12, ep=1) over Integer Ring
|
|
769
|
+
sage: (gen2 - ring_el).parent()
|
|
770
|
+
MeromorphicModularFormsRing(n=7) over Integer Ring
|
|
771
|
+
sage: (gen0 - 1.1).parent()
|
|
772
|
+
ModularFormsRing(n=7) over Real Field with 53 bits of precision
|
|
773
|
+
|
|
774
|
+
sage: MF = ModularForms(n=infinity)
|
|
775
|
+
sage: MF.E4() - MF.f_i()^2
|
|
776
|
+
64*q - 512*q^2 + 1792*q^3 - 4096*q^4 + O(q^5)
|
|
777
|
+
sage: (MF.E4() - MF.f_i()^2).parent()
|
|
778
|
+
ModularForms(n=+Infinity, k=4, ep=1) over Integer Ring
|
|
779
|
+
|
|
780
|
+
sage: el = ModularForms(n=3).Delta() - MF.E4()
|
|
781
|
+
sage: el
|
|
782
|
+
(E4*f_i^4 - 2*E4^2*f_i^2 + E4^3 - 4096*E4)/4096
|
|
783
|
+
sage: el.parent()
|
|
784
|
+
ModularFormsRing(n=+Infinity) over Integer Ring
|
|
785
|
+
"""
|
|
786
|
+
# reduce at the end? See example "sage: ((E4+E6)-E6).parent()"
|
|
787
|
+
return self.parent()(self._rat - other._rat)
|
|
788
|
+
|
|
789
|
+
def _neg_(self):
|
|
790
|
+
r"""
|
|
791
|
+
Return the negation of ``self``.
|
|
792
|
+
|
|
793
|
+
EXAMPLES::
|
|
794
|
+
|
|
795
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
796
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=8)
|
|
797
|
+
sage: Delta = MR.Delta().full_reduce()
|
|
798
|
+
|
|
799
|
+
sage: -Delta
|
|
800
|
+
-q - 41/(128*d)*q^2 - 10887/(262144*d^2)*q^3 - 131447/(50331648*d^3)*q^4 + O(q^5)
|
|
801
|
+
sage: parent(-Delta)
|
|
802
|
+
CuspForms(n=8, k=12, ep=1) over Integer Ring
|
|
803
|
+
|
|
804
|
+
Negation should be exactly the same as multiplication by -1::
|
|
805
|
+
|
|
806
|
+
sage: (-Delta) == (-1) * Delta
|
|
807
|
+
True
|
|
808
|
+
sage: parent(-Delta) is parent((-1) * Delta)
|
|
809
|
+
True
|
|
810
|
+
"""
|
|
811
|
+
return self.parent()(-self._rat)
|
|
812
|
+
|
|
813
|
+
def _mul_(self, other):
|
|
814
|
+
r"""
|
|
815
|
+
Return the product of ``self`` and ``other``.
|
|
816
|
+
|
|
817
|
+
Note that the parent might (probably will) change.
|
|
818
|
+
|
|
819
|
+
If ``parent.has_reduce_hom() == True`` then
|
|
820
|
+
the result is reduced to be an element of
|
|
821
|
+
the corresponding forms space if possible.
|
|
822
|
+
|
|
823
|
+
In particular this is the case if both ``self``
|
|
824
|
+
and ``other`` are (homogeneous) elements of a
|
|
825
|
+
forms space.
|
|
826
|
+
|
|
827
|
+
EXAMPLES::
|
|
828
|
+
|
|
829
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
830
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms, ModularForms
|
|
831
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=8)
|
|
832
|
+
sage: E2 = MR.E2().full_reduce()
|
|
833
|
+
sage: E4 = MR.E4().full_reduce()
|
|
834
|
+
sage: E6 = MR.E6().full_reduce()
|
|
835
|
+
sage: Delta = MR.Delta().full_reduce()
|
|
836
|
+
sage: J_inv = MR.J_inv().full_reduce()
|
|
837
|
+
sage: ring_el = MR(1/x+1).full_reduce()
|
|
838
|
+
|
|
839
|
+
sage: (1*Delta).parent()
|
|
840
|
+
CuspForms(n=8, k=12, ep=1) over Integer Ring
|
|
841
|
+
sage: (1.1*Delta).parent()
|
|
842
|
+
ModularForms(n=8, k=12, ep=1) over Real Field with 53 bits of precision
|
|
843
|
+
sage: (E2*E4).parent()
|
|
844
|
+
QuasiModularForms(n=8, k=6, ep=-1) over Integer Ring
|
|
845
|
+
sage: E4^2
|
|
846
|
+
1 + 15/(32*d)*q + 3255/(32768*d^2)*q^2 + 105445/(8388608*d^3)*q^3 + 36379615/(34359738368*d^4)*q^4 + O(q^5)
|
|
847
|
+
sage: (E4^2).parent()
|
|
848
|
+
ModularForms(n=8, k=8, ep=1) over Integer Ring
|
|
849
|
+
sage: (1.1*E4).parent()
|
|
850
|
+
ModularForms(n=8, k=4, ep=1) over Real Field with 53 bits of precision
|
|
851
|
+
sage: (J_inv*ring_el).parent()
|
|
852
|
+
MeromorphicModularFormsRing(n=8) over Integer Ring
|
|
853
|
+
sage: (E4*FractionField(PolynomialRing(CC,'d')).gen()).parent()
|
|
854
|
+
ModularForms(n=8, k=4, ep=1) over Complex Field with 53 bits of precision
|
|
855
|
+
|
|
856
|
+
sage: subspace = MR.reduce_type(["holo"], degree=(12,1)).subspace([Delta, E6^2])
|
|
857
|
+
sage: gen0 = subspace.gen(0)
|
|
858
|
+
sage: gen1 = subspace.gen(1)
|
|
859
|
+
sage: subspace2 = MR.reduce_type(["holo"], degree=(12,1)).subspace([Delta, Delta + E6^2])
|
|
860
|
+
sage: gen2 = subspace2.gen(0)
|
|
861
|
+
sage: gen3 = subspace2.gen(1)
|
|
862
|
+
|
|
863
|
+
sage: (gen0 * gen1).parent()
|
|
864
|
+
ModularForms(n=8, k=24, ep=1) over Integer Ring
|
|
865
|
+
sage: (gen0 * Delta*J_inv).parent()
|
|
866
|
+
WeakModularForms(n=8, k=24, ep=1) over Integer Ring
|
|
867
|
+
sage: (gen0 * Delta*J_inv).reduced_parent()
|
|
868
|
+
CuspForms(n=8, k=24, ep=1) over Integer Ring
|
|
869
|
+
sage: (gen0 * E2).parent()
|
|
870
|
+
QuasiModularForms(n=8, k=14, ep=-1) over Integer Ring
|
|
871
|
+
sage: gen2 * ring_el
|
|
872
|
+
f_rho^18*d + f_rho^17*d - f_rho^10*f_i^2*d - f_rho^9*f_i^2*d
|
|
873
|
+
sage: (gen2 * ring_el).parent()
|
|
874
|
+
MeromorphicModularFormsRing(n=8) over Integer Ring
|
|
875
|
+
sage: (1.1*gen0).parent()
|
|
876
|
+
ModularForms(n=8, k=12, ep=1) over Real Field with 53 bits of precision
|
|
877
|
+
|
|
878
|
+
sage: MF = ModularForms(n=infinity)
|
|
879
|
+
sage: MF.E4()*MF.f_inf()
|
|
880
|
+
q + 8*q^2 + 12*q^3 - 64*q^4 + O(q^5)
|
|
881
|
+
sage: (MF.E4()*MF.f_inf()).parent()
|
|
882
|
+
ModularForms(n=+Infinity, k=8, ep=1) over Integer Ring
|
|
883
|
+
|
|
884
|
+
sage: el = ModularForms(n=3).E2()*MF.E6()
|
|
885
|
+
sage: el
|
|
886
|
+
1 - 8*q - 272*q^2 - 1760*q^3 - 2560*q^4 + O(q^5)
|
|
887
|
+
sage: el.parent()
|
|
888
|
+
QuasiModularForms(n=+Infinity, k=8, ep=1) over Integer Ring
|
|
889
|
+
"""
|
|
890
|
+
res = self.parent().rat_field()(self._rat * other._rat)
|
|
891
|
+
new_parent = self.parent().extend_type(ring=True)
|
|
892
|
+
# The product of two homogeneous elements is homogeneous
|
|
893
|
+
return new_parent(res).reduce()
|
|
894
|
+
|
|
895
|
+
def _div_(self, other):
|
|
896
|
+
r"""
|
|
897
|
+
Return the division of ``self`` by ``other``.
|
|
898
|
+
|
|
899
|
+
Note that the parent might (probably will) change.
|
|
900
|
+
|
|
901
|
+
If ``parent.has_reduce_hom() == True`` then
|
|
902
|
+
the result is reduced to be an element of
|
|
903
|
+
the corresponding forms space if possible.
|
|
904
|
+
|
|
905
|
+
In particular this is the case if both ``self``
|
|
906
|
+
and ``other`` are (homogeneous) elements of a
|
|
907
|
+
forms space.
|
|
908
|
+
|
|
909
|
+
EXAMPLES::
|
|
910
|
+
|
|
911
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
912
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms, ModularForms
|
|
913
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=8)
|
|
914
|
+
sage: E2 = MR.E2().full_reduce()
|
|
915
|
+
sage: E4 = MR.E4().full_reduce()
|
|
916
|
+
sage: E6 = MR.E6().full_reduce()
|
|
917
|
+
sage: Delta = MR.Delta().full_reduce()
|
|
918
|
+
sage: J_inv = MR.J_inv().full_reduce()
|
|
919
|
+
sage: ring_el = MR(1/x+1).full_reduce()
|
|
920
|
+
|
|
921
|
+
sage: (1/Delta).parent()
|
|
922
|
+
MeromorphicModularForms(n=8, k=-12, ep=1) over Integer Ring
|
|
923
|
+
sage: (1.1/Delta).parent()
|
|
924
|
+
MeromorphicModularForms(n=8, k=-12, ep=1) over Real Field with 53 bits of precision
|
|
925
|
+
sage: (Delta/Delta).parent()
|
|
926
|
+
MeromorphicModularForms(n=8, k=0, ep=1) over Integer Ring
|
|
927
|
+
sage: 1/E4
|
|
928
|
+
1 - 15/(64*d)*q + 2145/(65536*d^2)*q^2 - 59545/(16777216*d^3)*q^3 + 22622585/(68719476736*d^4)*q^4 + O(q^5)
|
|
929
|
+
sage: (ring_el/J_inv).parent()
|
|
930
|
+
MeromorphicModularFormsRing(n=8) over Integer Ring
|
|
931
|
+
sage: (FractionField(PolynomialRing(CC,'d')).gen()/E4).parent()
|
|
932
|
+
MeromorphicModularForms(n=8, k=-4, ep=1) over Complex Field with 53 bits of precision
|
|
933
|
+
|
|
934
|
+
sage: (E4^(-2)).parent()
|
|
935
|
+
MeromorphicModularForms(n=8, k=-8, ep=1) over Integer Ring
|
|
936
|
+
sage: ((E4.as_ring_element())^(-2)).parent() == (E4^(-2)).parent()
|
|
937
|
+
True
|
|
938
|
+
sage: (MR(x)^(-3)).parent()
|
|
939
|
+
QuasiMeromorphicModularFormsRing(n=8) over Integer Ring
|
|
940
|
+
|
|
941
|
+
sage: subspace = MR.reduce_type(["holo"], degree=(12,1)).subspace([Delta, E6^2])
|
|
942
|
+
sage: gen0 = subspace.gen(0)
|
|
943
|
+
sage: gen1 = subspace.gen(1)
|
|
944
|
+
sage: subspace2 = MR.reduce_type(["holo"], degree=(12,1)).subspace([Delta, Delta + E6^2])
|
|
945
|
+
sage: gen2 = subspace2.gen(0)
|
|
946
|
+
sage: gen3 = subspace2.gen(1)
|
|
947
|
+
|
|
948
|
+
sage: (gen0 / gen1).parent()
|
|
949
|
+
MeromorphicModularForms(n=8, k=0, ep=1) over Integer Ring
|
|
950
|
+
sage: (gen0 / Delta).parent()
|
|
951
|
+
MeromorphicModularForms(n=8, k=0, ep=1) over Integer Ring
|
|
952
|
+
sage: ring_el / gen2
|
|
953
|
+
(f_rho + 1)/(f_rho^19*d - f_rho^11*f_i^2*d)
|
|
954
|
+
sage: (ring_el / gen2).parent()
|
|
955
|
+
MeromorphicModularFormsRing(n=8) over Integer Ring
|
|
956
|
+
sage: (1.1/gen0).parent()
|
|
957
|
+
MeromorphicModularForms(n=8, k=-12, ep=1) over Real Field with 53 bits of precision
|
|
958
|
+
|
|
959
|
+
sage: MF = ModularForms(n=infinity)
|
|
960
|
+
sage: MF.f_i()/MF.E4()
|
|
961
|
+
1 - 40*q + 552*q^2 - 4896*q^3 + 33320*q^4 + O(q^5)
|
|
962
|
+
sage: (MF.f_i()/MF.E4()).parent()
|
|
963
|
+
MeromorphicModularForms(n=+Infinity, k=-2, ep=-1) over Integer Ring
|
|
964
|
+
sage: MF.f_i()/(MF.E4() + MF.f_i()^2)
|
|
965
|
+
1/2 - 4*q - 236*q^2 - 2128*q^3 + 49428*q^4 + O(q^5)
|
|
966
|
+
sage: (MF.f_i()/(MF.E4() + MF.f_i()^2)).parent()
|
|
967
|
+
MeromorphicModularForms(n=+Infinity, k=-2, ep=-1) over Integer Ring
|
|
968
|
+
|
|
969
|
+
sage: el = ModularForms(n=3).E2()/MF.E2()
|
|
970
|
+
sage: el
|
|
971
|
+
1 + 8*q + 48*q^2 + 480*q^3 + 4448*q^4 + O(q^5)
|
|
972
|
+
sage: el.parent()
|
|
973
|
+
QuasiMeromorphicModularForms(n=+Infinity, k=0, ep=1) over Integer Ring
|
|
974
|
+
"""
|
|
975
|
+
res = self.parent().rat_field()(self._rat / other._rat)
|
|
976
|
+
new_parent = self.parent().extend_type("mero", ring=True)
|
|
977
|
+
# The division of two homogeneous elements is homogeneous
|
|
978
|
+
return new_parent(res).reduce()
|
|
979
|
+
|
|
980
|
+
def sqrt(self):
|
|
981
|
+
r"""
|
|
982
|
+
Return the square root of ``self`` if it exists.
|
|
983
|
+
|
|
984
|
+
I.e. the element corresponding to ``sqrt(self.rat())``.
|
|
985
|
+
|
|
986
|
+
Whether this works or not depends on whether
|
|
987
|
+
``sqrt(self.rat())`` works and coerces into
|
|
988
|
+
``self.parent().rat_field()``.
|
|
989
|
+
|
|
990
|
+
Note that the parent might (probably will) change.
|
|
991
|
+
|
|
992
|
+
If ``parent.has_reduce_hom() == True`` then
|
|
993
|
+
the result is reduced to be an element of
|
|
994
|
+
the corresponding forms space if possible.
|
|
995
|
+
|
|
996
|
+
In particular this is the case if ``self``
|
|
997
|
+
is a (homogeneous) element of a forms space.
|
|
998
|
+
|
|
999
|
+
EXAMPLES::
|
|
1000
|
+
|
|
1001
|
+
sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
|
|
1002
|
+
sage: E2 = QuasiModularForms(k=2, ep=-1).E2()
|
|
1003
|
+
sage: (E2^2).sqrt()
|
|
1004
|
+
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 + O(q^5)
|
|
1005
|
+
sage: (E2^2).sqrt() == E2
|
|
1006
|
+
True
|
|
1007
|
+
"""
|
|
1008
|
+
res = self._rat.sqrt()
|
|
1009
|
+
assert res.parent() is self.parent().rat_field()
|
|
1010
|
+
# new_parent = self.parent().extend_type(ring=True)
|
|
1011
|
+
# The sqrt of a homogeneous element is homogeneous if it exists
|
|
1012
|
+
new_parent = self.parent().extend_type(ring=True)
|
|
1013
|
+
return new_parent(res).reduce()
|
|
1014
|
+
|
|
1015
|
+
def diff_op(self, op, new_parent=None):
|
|
1016
|
+
r"""
|
|
1017
|
+
Return the differential operator ``op`` applied to ``self``.
|
|
1018
|
+
If ``parent.has_reduce_hom() == True`` then the result
|
|
1019
|
+
is reduced to be an element of the corresponding forms
|
|
1020
|
+
space if possible.
|
|
1021
|
+
|
|
1022
|
+
INPUT:
|
|
1023
|
+
|
|
1024
|
+
- ``op`` -- an element of ``self.parent().diff_alg()``.
|
|
1025
|
+
I.e. an element of the algebra over ``QQ``
|
|
1026
|
+
of differential operators generated
|
|
1027
|
+
by ``X, Y, Z, dX, dY, DZ``, where e.g. ``X``
|
|
1028
|
+
corresponds to the multiplication by ``x``
|
|
1029
|
+
(resp. ``f_rho``) and ``dX`` corresponds to ``d/dx``.
|
|
1030
|
+
|
|
1031
|
+
To expect a homogeneous result after applying
|
|
1032
|
+
the operator to a homogeneous element it should
|
|
1033
|
+
should be homogeneous operator (with respect
|
|
1034
|
+
to the usual, special grading).
|
|
1035
|
+
|
|
1036
|
+
- ``new_parent`` -- try to convert the result to the specified
|
|
1037
|
+
``new_parent``. If ``new_parent == None`` (default)
|
|
1038
|
+
then the parent is extended to a "quasi meromorphic" ring.
|
|
1039
|
+
|
|
1040
|
+
OUTPUT: the new element
|
|
1041
|
+
|
|
1042
|
+
EXAMPLES::
|
|
1043
|
+
|
|
1044
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
1045
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=8, red_hom=True)
|
|
1046
|
+
sage: (X,Y,Z,dX,dY,dZ) = MR.diff_alg().gens()
|
|
1047
|
+
sage: n = MR.hecke_n()
|
|
1048
|
+
sage: mul_op = 4/(n-2)*X*dX + 2*n/(n-2)*Y*dY + 2*Z*dZ
|
|
1049
|
+
sage: der_op = MR._derivative_op()
|
|
1050
|
+
sage: ser_op = MR._serre_derivative_op()
|
|
1051
|
+
sage: der_op == ser_op + (n-2)/(4*n)*Z*mul_op
|
|
1052
|
+
True
|
|
1053
|
+
|
|
1054
|
+
sage: Delta = MR.Delta().full_reduce()
|
|
1055
|
+
sage: E2 = MR.E2().full_reduce()
|
|
1056
|
+
sage: Delta.diff_op(mul_op) == 12*Delta
|
|
1057
|
+
True
|
|
1058
|
+
sage: Delta.diff_op(mul_op).parent()
|
|
1059
|
+
QuasiMeromorphicModularForms(n=8, k=12, ep=1) over Integer Ring
|
|
1060
|
+
sage: Delta.diff_op(mul_op, Delta.parent()).parent()
|
|
1061
|
+
CuspForms(n=8, k=12, ep=1) over Integer Ring
|
|
1062
|
+
sage: E2.diff_op(mul_op, E2.parent()) == 2*E2
|
|
1063
|
+
True
|
|
1064
|
+
sage: Delta.diff_op(Z*mul_op, Delta.parent().extend_type("quasi", ring=True)) == 12*E2*Delta
|
|
1065
|
+
True
|
|
1066
|
+
|
|
1067
|
+
sage: ran_op = X + Y*X*dY*dX + dZ + dX^2
|
|
1068
|
+
sage: Delta.diff_op(ran_op)
|
|
1069
|
+
f_rho^19*d + 306*f_rho^16*d - f_rho^11*f_i^2*d - 20*f_rho^10*f_i^2*d - 90*f_rho^8*f_i^2*d
|
|
1070
|
+
sage: E2.diff_op(ran_op)
|
|
1071
|
+
f_rho*E2 + 1
|
|
1072
|
+
|
|
1073
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=infinity, red_hom=True)
|
|
1074
|
+
sage: (X,Y,Z,dX,dY,dZ) = MR.diff_alg().gens()
|
|
1075
|
+
sage: mul_op = 4*X*dX + 2*Y*dY + 2*Z*dZ
|
|
1076
|
+
sage: der_op = MR._derivative_op()
|
|
1077
|
+
sage: ser_op = MR._serre_derivative_op()
|
|
1078
|
+
sage: der_op == ser_op + Z/4*mul_op
|
|
1079
|
+
True
|
|
1080
|
+
|
|
1081
|
+
sage: Delta = MR.Delta().full_reduce()
|
|
1082
|
+
sage: E2 = MR.E2().full_reduce()
|
|
1083
|
+
sage: Delta.diff_op(mul_op) == 12*Delta
|
|
1084
|
+
True
|
|
1085
|
+
sage: Delta.diff_op(mul_op).parent()
|
|
1086
|
+
QuasiMeromorphicModularForms(n=+Infinity, k=12, ep=1) over Integer Ring
|
|
1087
|
+
sage: Delta.diff_op(mul_op, Delta.parent()).parent()
|
|
1088
|
+
CuspForms(n=+Infinity, k=12, ep=1) over Integer Ring
|
|
1089
|
+
sage: E2.diff_op(mul_op, E2.parent()) == 2*E2
|
|
1090
|
+
True
|
|
1091
|
+
sage: Delta.diff_op(Z*mul_op, Delta.parent().extend_type("quasi", ring=True)) == 12*E2*Delta
|
|
1092
|
+
True
|
|
1093
|
+
|
|
1094
|
+
sage: ran_op = X + Y*X*dY*dX + dZ + dX^2
|
|
1095
|
+
sage: Delta.diff_op(ran_op)
|
|
1096
|
+
-E4^3*f_i^2*d + E4^4*d - 4*E4^2*f_i^2*d - 2*f_i^2*d + 6*E4*d
|
|
1097
|
+
sage: E2.diff_op(ran_op)
|
|
1098
|
+
E4*E2 + 1
|
|
1099
|
+
"""
|
|
1100
|
+
x, y, z, d = self.parent().rat_field().gens()
|
|
1101
|
+
X, Y, Z, dX, dY, dZ = self.parent().diff_alg().gens()
|
|
1102
|
+
L = op.monomials()
|
|
1103
|
+
new_rat = 0
|
|
1104
|
+
for mon in L:
|
|
1105
|
+
mon_summand = self._rat
|
|
1106
|
+
mon_summand = mon_summand.derivative(x, mon.degree(dX))
|
|
1107
|
+
mon_summand = mon_summand.derivative(y, mon.degree(dY))
|
|
1108
|
+
mon_summand = mon_summand.derivative(z, mon.degree(dZ))
|
|
1109
|
+
mon_summand *= x**(mon.degree(X))
|
|
1110
|
+
mon_summand *= y**(mon.degree(Y))
|
|
1111
|
+
mon_summand *= z**(mon.degree(Z))
|
|
1112
|
+
new_rat += op.monomial_coefficient(mon) * mon_summand
|
|
1113
|
+
res = self.parent().rat_field()(new_rat)
|
|
1114
|
+
if (new_parent is None):
|
|
1115
|
+
new_parent = self.parent().extend_type(["quasi", "mero"], ring=True)
|
|
1116
|
+
return new_parent(res).reduce()
|
|
1117
|
+
|
|
1118
|
+
# note that this is qd/dq, resp 1/(2*pi*i)*d/dtau
|
|
1119
|
+
def derivative(self):
|
|
1120
|
+
r"""
|
|
1121
|
+
Return the derivative ``d/dq = lambda/(2*pi*i) d/dtau`` of ``self``.
|
|
1122
|
+
|
|
1123
|
+
Note that the parent might (probably will) change.
|
|
1124
|
+
In particular its analytic type will be extended
|
|
1125
|
+
to contain "quasi".
|
|
1126
|
+
|
|
1127
|
+
If ``parent.has_reduce_hom() == True`` then
|
|
1128
|
+
the result is reduced to be an element of
|
|
1129
|
+
the corresponding forms space if possible.
|
|
1130
|
+
|
|
1131
|
+
In particular this is the case if ``self``
|
|
1132
|
+
is a (homogeneous) element of a forms space.
|
|
1133
|
+
|
|
1134
|
+
EXAMPLES::
|
|
1135
|
+
|
|
1136
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
1137
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=7, red_hom=True)
|
|
1138
|
+
sage: n = MR.hecke_n()
|
|
1139
|
+
sage: E2 = MR.E2().full_reduce()
|
|
1140
|
+
sage: E6 = MR.E6().full_reduce()
|
|
1141
|
+
sage: f_rho = MR.f_rho().full_reduce()
|
|
1142
|
+
sage: f_i = MR.f_i().full_reduce()
|
|
1143
|
+
sage: f_inf = MR.f_inf().full_reduce()
|
|
1144
|
+
|
|
1145
|
+
sage: derivative(f_rho) == 1/n * (f_rho*E2 - f_i)
|
|
1146
|
+
True
|
|
1147
|
+
sage: derivative(f_i) == 1/2 * (f_i*E2 - f_rho**(n-1))
|
|
1148
|
+
True
|
|
1149
|
+
sage: derivative(f_inf) == f_inf * E2
|
|
1150
|
+
True
|
|
1151
|
+
sage: derivative(f_inf).parent()
|
|
1152
|
+
QuasiCuspForms(n=7, k=38/5, ep=-1) over Integer Ring
|
|
1153
|
+
sage: derivative(E2) == (n-2)/(4*n) * (E2**2 - f_rho**(n-2))
|
|
1154
|
+
True
|
|
1155
|
+
sage: derivative(E2).parent()
|
|
1156
|
+
QuasiModularForms(n=7, k=4, ep=1) over Integer Ring
|
|
1157
|
+
|
|
1158
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=infinity, red_hom=True)
|
|
1159
|
+
sage: E2 = MR.E2().full_reduce()
|
|
1160
|
+
sage: E4 = MR.E4().full_reduce()
|
|
1161
|
+
sage: E6 = MR.E6().full_reduce()
|
|
1162
|
+
sage: f_i = MR.f_i().full_reduce()
|
|
1163
|
+
sage: f_inf = MR.f_inf().full_reduce()
|
|
1164
|
+
|
|
1165
|
+
sage: derivative(E4) == E4 * (E2 - f_i)
|
|
1166
|
+
True
|
|
1167
|
+
sage: derivative(f_i) == 1/2 * (f_i*E2 - E4)
|
|
1168
|
+
True
|
|
1169
|
+
sage: derivative(f_inf) == f_inf * E2
|
|
1170
|
+
True
|
|
1171
|
+
sage: derivative(f_inf).parent()
|
|
1172
|
+
QuasiModularForms(n=+Infinity, k=6, ep=-1) over Integer Ring
|
|
1173
|
+
sage: derivative(E2) == 1/4 * (E2**2 - E4)
|
|
1174
|
+
True
|
|
1175
|
+
sage: derivative(E2).parent()
|
|
1176
|
+
QuasiModularForms(n=+Infinity, k=4, ep=1) over Integer Ring
|
|
1177
|
+
"""
|
|
1178
|
+
|
|
1179
|
+
return self.diff_op(self.parent()._derivative_op(), self.parent().extend_type("quasi", ring=True))
|
|
1180
|
+
|
|
1181
|
+
def serre_derivative(self):
|
|
1182
|
+
r"""
|
|
1183
|
+
Return the Serre derivative of ``self``.
|
|
1184
|
+
|
|
1185
|
+
Note that the parent might (probably will) change.
|
|
1186
|
+
However a modular element is returned if ``self``
|
|
1187
|
+
was already modular.
|
|
1188
|
+
|
|
1189
|
+
If ``parent.has_reduce_hom() == True`` then
|
|
1190
|
+
the result is reduced to be an element of
|
|
1191
|
+
the corresponding forms space if possible.
|
|
1192
|
+
|
|
1193
|
+
In particular this is the case if ``self``
|
|
1194
|
+
is a (homogeneous) element of a forms space.
|
|
1195
|
+
|
|
1196
|
+
EXAMPLES::
|
|
1197
|
+
|
|
1198
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
1199
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=7, red_hom=True)
|
|
1200
|
+
sage: n = MR.hecke_n()
|
|
1201
|
+
sage: Delta = MR.Delta().full_reduce()
|
|
1202
|
+
sage: E2 = MR.E2().full_reduce()
|
|
1203
|
+
sage: E4 = MR.E4().full_reduce()
|
|
1204
|
+
sage: E6 = MR.E6().full_reduce()
|
|
1205
|
+
sage: f_rho = MR.f_rho().full_reduce()
|
|
1206
|
+
sage: f_i = MR.f_i().full_reduce()
|
|
1207
|
+
sage: f_inf = MR.f_inf().full_reduce()
|
|
1208
|
+
|
|
1209
|
+
sage: f_rho.serre_derivative() == -1/n * f_i
|
|
1210
|
+
True
|
|
1211
|
+
sage: f_i.serre_derivative() == -1/2 * E4 * f_rho
|
|
1212
|
+
True
|
|
1213
|
+
sage: f_inf.serre_derivative() == 0
|
|
1214
|
+
True
|
|
1215
|
+
sage: E2.serre_derivative() == -(n-2)/(4*n) * (E2^2 + E4)
|
|
1216
|
+
True
|
|
1217
|
+
sage: E4.serre_derivative() == -(n-2)/n * E6
|
|
1218
|
+
True
|
|
1219
|
+
sage: E6.serre_derivative() == -1/2 * E4^2 - (n-3)/n * E6^2 / E4
|
|
1220
|
+
True
|
|
1221
|
+
sage: E6.serre_derivative().parent()
|
|
1222
|
+
ModularForms(n=7, k=8, ep=1) over Integer Ring
|
|
1223
|
+
|
|
1224
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=infinity, red_hom=True)
|
|
1225
|
+
sage: Delta = MR.Delta().full_reduce()
|
|
1226
|
+
sage: E2 = MR.E2().full_reduce()
|
|
1227
|
+
sage: E4 = MR.E4().full_reduce()
|
|
1228
|
+
sage: E6 = MR.E6().full_reduce()
|
|
1229
|
+
sage: f_i = MR.f_i().full_reduce()
|
|
1230
|
+
sage: f_inf = MR.f_inf().full_reduce()
|
|
1231
|
+
|
|
1232
|
+
sage: E4.serre_derivative() == -E4 * f_i
|
|
1233
|
+
True
|
|
1234
|
+
sage: f_i.serre_derivative() == -1/2 * E4
|
|
1235
|
+
True
|
|
1236
|
+
sage: f_inf.serre_derivative() == 0
|
|
1237
|
+
True
|
|
1238
|
+
sage: E2.serre_derivative() == -1/4 * (E2^2 + E4)
|
|
1239
|
+
True
|
|
1240
|
+
sage: E4.serre_derivative() == -E6
|
|
1241
|
+
True
|
|
1242
|
+
sage: E6.serre_derivative() == -1/2 * E4^2 - E6^2 / E4
|
|
1243
|
+
True
|
|
1244
|
+
sage: E6.serre_derivative().parent()
|
|
1245
|
+
ModularForms(n=+Infinity, k=8, ep=1) over Integer Ring
|
|
1246
|
+
"""
|
|
1247
|
+
|
|
1248
|
+
return self.diff_op(self.parent()._serre_derivative_op(), self.parent().extend_type(ring=True))
|
|
1249
|
+
|
|
1250
|
+
@cached_method
|
|
1251
|
+
def order_at(self, tau=infinity):
|
|
1252
|
+
r"""
|
|
1253
|
+
Return the (overall) order of ``self`` at ``tau`` if easily possible:
|
|
1254
|
+
Namely if ``tau`` is ``infinity`` or congruent to ``i`` resp. ``rho``.
|
|
1255
|
+
|
|
1256
|
+
It is possible to determine the order of points from :class:`HyperbolicPlane`.
|
|
1257
|
+
In this case the coordinates of the upper half plane model are used.
|
|
1258
|
+
|
|
1259
|
+
If ``self`` is homogeneous and modular then the rational function
|
|
1260
|
+
``self.rat()`` is used. Otherwise only ``tau=infinity`` is supported
|
|
1261
|
+
by using the Fourier expansion with increasing precision
|
|
1262
|
+
(until the order can be determined).
|
|
1263
|
+
|
|
1264
|
+
The function is mainly used to be able to work with the correct
|
|
1265
|
+
precision for Laurent series.
|
|
1266
|
+
|
|
1267
|
+
.. NOTE::
|
|
1268
|
+
|
|
1269
|
+
For quasi forms one cannot deduce the analytic type from
|
|
1270
|
+
this order at ``infinity`` since the analytic order is defined by the
|
|
1271
|
+
behavior on each quasi part and not by their linear combination.
|
|
1272
|
+
|
|
1273
|
+
EXAMPLES::
|
|
1274
|
+
|
|
1275
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
1276
|
+
sage: MR = QuasiMeromorphicModularFormsRing(red_hom=True)
|
|
1277
|
+
sage: (MR.Delta()^3).order_at(infinity)
|
|
1278
|
+
3
|
|
1279
|
+
sage: MR.E2().order_at(infinity)
|
|
1280
|
+
0
|
|
1281
|
+
sage: (MR.J_inv()^2).order_at(infinity)
|
|
1282
|
+
-2
|
|
1283
|
+
sage: x,y,z,d = MR.pol_ring().gens()
|
|
1284
|
+
sage: el = MR((z^3-y)^2/(x^3-y^2)).full_reduce()
|
|
1285
|
+
sage: el
|
|
1286
|
+
108*q + 11664*q^2 + 502848*q^3 + 12010464*q^4 + O(q^5)
|
|
1287
|
+
sage: el.order_at(infinity)
|
|
1288
|
+
1
|
|
1289
|
+
sage: el.parent()
|
|
1290
|
+
QuasiWeakModularForms(n=3, k=0, ep=1) over Integer Ring
|
|
1291
|
+
sage: el.is_holomorphic()
|
|
1292
|
+
False
|
|
1293
|
+
sage: MR((z-y)^2+(x-y)^3).order_at(infinity)
|
|
1294
|
+
2
|
|
1295
|
+
sage: MR((x-y)^10).order_at(infinity)
|
|
1296
|
+
10
|
|
1297
|
+
sage: MR.zero().order_at(infinity)
|
|
1298
|
+
+Infinity
|
|
1299
|
+
sage: (MR(x*y^2)/MR.J_inv()).order_at(i)
|
|
1300
|
+
2
|
|
1301
|
+
sage: (MR(x*y^2)/MR.J_inv()).order_at(MR.group().rho())
|
|
1302
|
+
-2
|
|
1303
|
+
|
|
1304
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=infinity, red_hom=True)
|
|
1305
|
+
sage: (MR.Delta()^3*MR.E4()).order_at(infinity)
|
|
1306
|
+
3
|
|
1307
|
+
sage: MR.E2().order_at(infinity)
|
|
1308
|
+
0
|
|
1309
|
+
sage: (MR.J_inv()^2/MR.E4()).order_at(infinity)
|
|
1310
|
+
-2
|
|
1311
|
+
sage: el = MR((z^3-x*y)^2/(x^2*(x-y^2))).full_reduce()
|
|
1312
|
+
sage: el
|
|
1313
|
+
4*q - 304*q^2 + 8128*q^3 - 106144*q^4 + O(q^5)
|
|
1314
|
+
sage: el.order_at(infinity)
|
|
1315
|
+
1
|
|
1316
|
+
sage: el.parent()
|
|
1317
|
+
QuasiWeakModularForms(n=+Infinity, k=0, ep=1) over Integer Ring
|
|
1318
|
+
sage: el.is_holomorphic()
|
|
1319
|
+
False
|
|
1320
|
+
sage: MR((z-x)^2+(x-y)^3).order_at(infinity)
|
|
1321
|
+
2
|
|
1322
|
+
sage: MR((x-y)^10).order_at(infinity)
|
|
1323
|
+
10
|
|
1324
|
+
sage: MR.zero().order_at(infinity)
|
|
1325
|
+
+Infinity
|
|
1326
|
+
|
|
1327
|
+
sage: (MR.j_inv()*MR.f_i()^3).order_at(-1)
|
|
1328
|
+
1
|
|
1329
|
+
sage: (MR.j_inv()*MR.f_i()^3).order_at(i)
|
|
1330
|
+
3
|
|
1331
|
+
sage: (1/MR.f_inf()^2).order_at(-1)
|
|
1332
|
+
0
|
|
1333
|
+
|
|
1334
|
+
sage: p = HyperbolicPlane().PD().get_point(I) # needs sage.symbolic
|
|
1335
|
+
sage: MR((x-y)^10).order_at(p) # needs sage.symbolic
|
|
1336
|
+
10
|
|
1337
|
+
sage: MR.zero().order_at(p) # needs sage.symbolic
|
|
1338
|
+
+Infinity
|
|
1339
|
+
"""
|
|
1340
|
+
|
|
1341
|
+
i = QuadraticField(-1, 'I').gen()
|
|
1342
|
+
|
|
1343
|
+
# if tau is a point of HyperbolicPlane then we use it's coordinates in the UHP model
|
|
1344
|
+
if _in_HyperbolicPlane(tau):
|
|
1345
|
+
tau = tau.to_model('UHP').coordinates()
|
|
1346
|
+
|
|
1347
|
+
if self.is_zero():
|
|
1348
|
+
return infinity
|
|
1349
|
+
|
|
1350
|
+
if (self.is_homogeneous() and self.is_modular()):
|
|
1351
|
+
rat = self.parent().rat_field()(self._rat)
|
|
1352
|
+
R = self.parent().pol_ring()
|
|
1353
|
+
numerator = R(rat.numerator())
|
|
1354
|
+
denom = R(rat.denominator())
|
|
1355
|
+
x, y, z, d = R.gens()
|
|
1356
|
+
n = self.hecke_n()
|
|
1357
|
+
|
|
1358
|
+
if (tau == i):
|
|
1359
|
+
f_pol = y
|
|
1360
|
+
# This includes the case rho=1 resp. n=infinity
|
|
1361
|
+
elif (tau == self.group().rho() or tau == -self.group().rho().conjugate()):
|
|
1362
|
+
f_pol = x
|
|
1363
|
+
# We intentionally leave out the d-factor!
|
|
1364
|
+
elif (tau == infinity):
|
|
1365
|
+
if (n == infinity):
|
|
1366
|
+
f_pol = x - y**2
|
|
1367
|
+
else:
|
|
1368
|
+
f_pol = x**n - y**2
|
|
1369
|
+
elif (tau.imag() > 0):
|
|
1370
|
+
if (self.group().in_FD(tau)):
|
|
1371
|
+
raise NotImplementedError("Orders at general points (here: tau={}) are not yet implemented!".format(tau))
|
|
1372
|
+
else:
|
|
1373
|
+
w = self.group().get_FD(tau)[1]
|
|
1374
|
+
return self.order_at(w)
|
|
1375
|
+
else:
|
|
1376
|
+
raise ValueError("tau={} does not lie in the extended upper half plane!").format(tau)
|
|
1377
|
+
|
|
1378
|
+
order_f = 0
|
|
1379
|
+
# There seems to be a bug in Singular, for now this "try, except" is a workaround
|
|
1380
|
+
# Also numerator /= f_pol doesn't seem to return an element of R for non-exact rings...
|
|
1381
|
+
try:
|
|
1382
|
+
while (f_pol.divides(numerator)):
|
|
1383
|
+
numerator = numerator.quo_rem(f_pol)[0]
|
|
1384
|
+
# numerator /= f_pol
|
|
1385
|
+
numerator = R(numerator)
|
|
1386
|
+
order_f += 1
|
|
1387
|
+
except TypeError:
|
|
1388
|
+
pass
|
|
1389
|
+
try:
|
|
1390
|
+
while (f_pol.divides(denom)):
|
|
1391
|
+
denom = denom.quo_rem(f_pol)[0]
|
|
1392
|
+
# denom /= f_pol
|
|
1393
|
+
denom = R(denom)
|
|
1394
|
+
order_f -= 1
|
|
1395
|
+
except TypeError:
|
|
1396
|
+
pass
|
|
1397
|
+
|
|
1398
|
+
return order_f
|
|
1399
|
+
else:
|
|
1400
|
+
if tau != infinity:
|
|
1401
|
+
raise NotImplementedError("Only the order at infinity is supported for non-homogeneous or quasi forms!")
|
|
1402
|
+
|
|
1403
|
+
num_val = prec_num_bound = 1 # (self.parent()._prec/ZZ(2)).ceil()
|
|
1404
|
+
denom_val = prec_denom_bound = 1 # (self.parent()._prec/ZZ(2)).ceil()
|
|
1405
|
+
|
|
1406
|
+
while (num_val >= prec_num_bound):
|
|
1407
|
+
prec_num_bound *= 2
|
|
1408
|
+
num_val = self.numerator().q_expansion(prec=prec_num_bound, fix_prec=True).valuation()
|
|
1409
|
+
while (denom_val >= prec_denom_bound):
|
|
1410
|
+
prec_denom_bound *= 2
|
|
1411
|
+
denom_val = self.denominator().q_expansion(prec=prec_denom_bound, fix_prec=True).valuation()
|
|
1412
|
+
|
|
1413
|
+
return num_val - denom_val
|
|
1414
|
+
|
|
1415
|
+
def as_ring_element(self):
|
|
1416
|
+
r"""
|
|
1417
|
+
Coerce ``self`` into the graded ring of its parent.
|
|
1418
|
+
|
|
1419
|
+
EXAMPLES::
|
|
1420
|
+
|
|
1421
|
+
sage: from sage.modular.modform_hecketriangle.space import CuspForms
|
|
1422
|
+
sage: Delta = CuspForms(k=12).Delta()
|
|
1423
|
+
sage: Delta.parent()
|
|
1424
|
+
CuspForms(n=3, k=12, ep=1) over Integer Ring
|
|
1425
|
+
sage: Delta.as_ring_element()
|
|
1426
|
+
f_rho^3*d - f_i^2*d
|
|
1427
|
+
sage: Delta.as_ring_element().parent()
|
|
1428
|
+
CuspFormsRing(n=3) over Integer Ring
|
|
1429
|
+
|
|
1430
|
+
sage: CuspForms(n=infinity, k=12).Delta().as_ring_element()
|
|
1431
|
+
-E4^2*f_i^2*d + E4^3*d
|
|
1432
|
+
"""
|
|
1433
|
+
|
|
1434
|
+
return self.parent().graded_ring()(self._rat)
|
|
1435
|
+
|
|
1436
|
+
def reduce(self, force=False):
|
|
1437
|
+
r"""
|
|
1438
|
+
In case ``self.parent().has_reduce_hom() == True``
|
|
1439
|
+
(or ``force==True``) and ``self`` is homogeneous
|
|
1440
|
+
the converted element lying in the corresponding
|
|
1441
|
+
homogeneous_part is returned.
|
|
1442
|
+
|
|
1443
|
+
Otherwise ``self`` is returned.
|
|
1444
|
+
|
|
1445
|
+
EXAMPLES::
|
|
1446
|
+
|
|
1447
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import ModularFormsRing
|
|
1448
|
+
sage: E2 = ModularFormsRing(n=7).E2().reduce()
|
|
1449
|
+
sage: E2.parent()
|
|
1450
|
+
QuasiModularFormsRing(n=7) over Integer Ring
|
|
1451
|
+
sage: E2 = ModularFormsRing(n=7, red_hom=True).E2().reduce()
|
|
1452
|
+
sage: E2.parent()
|
|
1453
|
+
QuasiModularForms(n=7, k=2, ep=-1) over Integer Ring
|
|
1454
|
+
sage: ModularFormsRing(n=7)(x+1).reduce().parent()
|
|
1455
|
+
ModularFormsRing(n=7) over Integer Ring
|
|
1456
|
+
sage: E2 = ModularFormsRing(n=7).E2().reduce(force=True)
|
|
1457
|
+
sage: E2.parent()
|
|
1458
|
+
QuasiModularForms(n=7, k=2, ep=-1) over Integer Ring
|
|
1459
|
+
sage: ModularFormsRing(n=7)(x+1).reduce(force=True).parent()
|
|
1460
|
+
ModularFormsRing(n=7) over Integer Ring
|
|
1461
|
+
|
|
1462
|
+
sage: y = var("y")
|
|
1463
|
+
sage: ModularFormsRing(n=infinity)(x-y^2).reduce(force=True)
|
|
1464
|
+
64*q - 512*q^2 + 1792*q^3 - 4096*q^4 + O(q^5)
|
|
1465
|
+
"""
|
|
1466
|
+
|
|
1467
|
+
if (force or self.parent().has_reduce_hom()) and self.is_homogeneous():
|
|
1468
|
+
return self.parent().homogeneous_part(self._weight, self._ep)(self._rat)
|
|
1469
|
+
else:
|
|
1470
|
+
return self
|
|
1471
|
+
|
|
1472
|
+
def reduced_parent(self):
|
|
1473
|
+
r"""
|
|
1474
|
+
Return the space with the analytic type of ``self``.
|
|
1475
|
+
If ``self`` is homogeneous the corresponding ``FormsSpace`` is returned.
|
|
1476
|
+
|
|
1477
|
+
I.e. return the smallest known ambient space of ``self``.
|
|
1478
|
+
|
|
1479
|
+
EXAMPLES::
|
|
1480
|
+
|
|
1481
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
1482
|
+
sage: Delta = QuasiMeromorphicModularFormsRing(n=7).Delta()
|
|
1483
|
+
sage: Delta.parent()
|
|
1484
|
+
QuasiMeromorphicModularFormsRing(n=7) over Integer Ring
|
|
1485
|
+
sage: Delta.reduced_parent()
|
|
1486
|
+
CuspForms(n=7, k=12, ep=1) over Integer Ring
|
|
1487
|
+
sage: el = QuasiMeromorphicModularFormsRing()(x+1)
|
|
1488
|
+
sage: el.parent()
|
|
1489
|
+
QuasiMeromorphicModularFormsRing(n=3) over Integer Ring
|
|
1490
|
+
sage: el.reduced_parent()
|
|
1491
|
+
ModularFormsRing(n=3) over Integer Ring
|
|
1492
|
+
|
|
1493
|
+
sage: y = var("y")
|
|
1494
|
+
sage: QuasiMeromorphicModularFormsRing(n=infinity)(x-y^2).reduced_parent()
|
|
1495
|
+
ModularForms(n=+Infinity, k=4, ep=1) over Integer Ring
|
|
1496
|
+
sage: QuasiMeromorphicModularFormsRing(n=infinity)(x*(x-y^2)).reduced_parent()
|
|
1497
|
+
CuspForms(n=+Infinity, k=8, ep=1) over Integer Ring
|
|
1498
|
+
"""
|
|
1499
|
+
|
|
1500
|
+
if self.is_homogeneous():
|
|
1501
|
+
return FormsSpace(self.analytic_type(), self.group(), self.base_ring(), self.weight(), self.ep())
|
|
1502
|
+
else:
|
|
1503
|
+
return FormsRing(self.analytic_type(), self.group(), self.base_ring(), self.parent().has_reduce_hom())
|
|
1504
|
+
|
|
1505
|
+
def full_reduce(self):
|
|
1506
|
+
r"""
|
|
1507
|
+
Convert ``self`` into its reduced parent.
|
|
1508
|
+
|
|
1509
|
+
EXAMPLES::
|
|
1510
|
+
|
|
1511
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
1512
|
+
sage: Delta = QuasiMeromorphicModularFormsRing().Delta()
|
|
1513
|
+
sage: Delta
|
|
1514
|
+
f_rho^3*d - f_i^2*d
|
|
1515
|
+
sage: Delta.full_reduce()
|
|
1516
|
+
q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5)
|
|
1517
|
+
sage: Delta.full_reduce().parent() == Delta.reduced_parent()
|
|
1518
|
+
True
|
|
1519
|
+
|
|
1520
|
+
sage: QuasiMeromorphicModularFormsRing().Delta().full_reduce().parent()
|
|
1521
|
+
CuspForms(n=3, k=12, ep=1) over Integer Ring
|
|
1522
|
+
"""
|
|
1523
|
+
|
|
1524
|
+
return self.reduced_parent()(self._rat)
|
|
1525
|
+
|
|
1526
|
+
# precision is actually accuracy, maybe add "real precision" meaning number of rel. coef
|
|
1527
|
+
@cached_method
|
|
1528
|
+
def _q_expansion_cached(self, prec, fix_d, subs_d, d_num_prec, fix_prec=False):
|
|
1529
|
+
"""
|
|
1530
|
+
Return the Fourier expansion of ``self`` (cached).
|
|
1531
|
+
Don't call this function, instead use :meth:`q_expansion`.
|
|
1532
|
+
Also see :meth:`q_expansion` for a description of the arguments.
|
|
1533
|
+
|
|
1534
|
+
Regarding the additional option ``subs_d``:
|
|
1535
|
+
Caching doesn't distinguish between ``True`` and ``1``. If ``fix_d`` is
|
|
1536
|
+
not boolean then ``subs_d=fix_d`` should be set make that distinction.
|
|
1537
|
+
|
|
1538
|
+
EXAMPLES::
|
|
1539
|
+
|
|
1540
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import WeakModularFormsRing
|
|
1541
|
+
sage: J_inv = WeakModularFormsRing(red_hom=True).J_inv()
|
|
1542
|
+
sage: J_inv._q_expansion_cached(prec=5, fix_d=False, subs_d=None, d_num_prec=53, fix_prec=False) == J_inv.q_expansion()
|
|
1543
|
+
True
|
|
1544
|
+
sage: J_inv._q_expansion_cached(prec=5, fix_d=True, subs_d=None, d_num_prec=53, fix_prec=False) == J_inv.q_expansion_fixed_d()
|
|
1545
|
+
True
|
|
1546
|
+
"""
|
|
1547
|
+
if not fix_prec:
|
|
1548
|
+
if ((not self.is_zero()) and prec <= self.order_at(infinity)):
|
|
1549
|
+
from warnings import warn
|
|
1550
|
+
warn("precision too low to determine any coefficient!")
|
|
1551
|
+
|
|
1552
|
+
# This should _exactly_ ensure the given precision O(q^prec):
|
|
1553
|
+
prec += self.denominator().order_at(infinity) + max(-self.order_at(infinity), 0)
|
|
1554
|
+
|
|
1555
|
+
# The result will have "max(prec-self.order_at(infinity),0)" significant coefficients
|
|
1556
|
+
# So adding the following line to the above one
|
|
1557
|
+
# would instead give "prec" many significant coefficients:
|
|
1558
|
+
# prec += self.order_at(infinity)
|
|
1559
|
+
|
|
1560
|
+
SC = MFSeriesConstructor(self.group(), prec)
|
|
1561
|
+
formal_d = self.parent().get_d()
|
|
1562
|
+
formal_q = self.parent().get_q(prec)
|
|
1563
|
+
|
|
1564
|
+
if (self.hecke_n() == infinity):
|
|
1565
|
+
X = SC.E4_ZZ().base_extend(formal_d.parent())
|
|
1566
|
+
else:
|
|
1567
|
+
X = SC.f_rho_ZZ().base_extend(formal_d.parent())
|
|
1568
|
+
Y = SC.f_i_ZZ().base_extend(formal_d.parent())
|
|
1569
|
+
|
|
1570
|
+
if (self.parent().is_modular()):
|
|
1571
|
+
# z does not appear in self._rat but we need to specialize it for
|
|
1572
|
+
# the evaluation to land in the correct parent
|
|
1573
|
+
qexp = self._rat.subs(x=X, y=Y, z=0, d=formal_d)
|
|
1574
|
+
else:
|
|
1575
|
+
Z = SC.E2_ZZ().base_extend(formal_d.parent())
|
|
1576
|
+
qexp = self._rat.subs(x=X, y=Y, z=Z, d=formal_d)
|
|
1577
|
+
|
|
1578
|
+
qexp = (qexp + O(formal_q**prec)).parent()(qexp)
|
|
1579
|
+
qexp = qexp(formal_q / formal_d)
|
|
1580
|
+
cur_prec = qexp.prec()
|
|
1581
|
+
|
|
1582
|
+
if (subs_d):
|
|
1583
|
+
fix_d = subs_d
|
|
1584
|
+
d = self.parent().get_d(fix_d, d_num_prec)
|
|
1585
|
+
q = self.parent().get_q(prec, fix_d, d_num_prec)
|
|
1586
|
+
|
|
1587
|
+
qexp = sum([(qexp.coefficients()[m]).subs(d=d) * q**qexp.exponents()[m] for m in range(len(qexp.coefficients()))])
|
|
1588
|
+
if (cur_prec != infinity):
|
|
1589
|
+
qexp += O(q**cur_prec)
|
|
1590
|
+
else:
|
|
1591
|
+
qexp = (qexp + O(q)).parent()(qexp)
|
|
1592
|
+
|
|
1593
|
+
return qexp
|
|
1594
|
+
|
|
1595
|
+
def q_expansion(self, prec=None, fix_d=False, d_num_prec=None, fix_prec=False):
|
|
1596
|
+
"""
|
|
1597
|
+
Return the Fourier expansion of ``self``.
|
|
1598
|
+
|
|
1599
|
+
INPUT:
|
|
1600
|
+
|
|
1601
|
+
- ``prec`` -- integer, the desired output precision O(q^prec).
|
|
1602
|
+
Default: ``None`` in which case the default precision
|
|
1603
|
+
of ``self.parent()`` is used.
|
|
1604
|
+
|
|
1605
|
+
- ``fix_d`` -- if ``False`` (default) a formal parameter is used for
|
|
1606
|
+
``d``. If ``True`` then the numerical value of ``d`` is used
|
|
1607
|
+
(resp. an exact value if the group is arithmetic).
|
|
1608
|
+
Otherwise the given value is used for ``d``.
|
|
1609
|
+
|
|
1610
|
+
- ``d_num_prec`` -- the precision to be used if a numerical value for
|
|
1611
|
+
``d`` is substituted (default: ``None``), otherwise the default
|
|
1612
|
+
numerical precision of ``self.parent()`` is used
|
|
1613
|
+
|
|
1614
|
+
- ``fix_prec`` -- if ``fix_prec`` is not ``False`` (default)
|
|
1615
|
+
then the precision of the ``MFSeriesConstructor`` is
|
|
1616
|
+
increased such that the output has exactly the specified
|
|
1617
|
+
precision O(q^prec).
|
|
1618
|
+
|
|
1619
|
+
OUTPUT: the Fourier expansion of ``self`` as a ``FormalPowerSeries`` or ``FormalLaurentSeries``
|
|
1620
|
+
|
|
1621
|
+
EXAMPLES::
|
|
1622
|
+
|
|
1623
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import WeakModularFormsRing, QuasiModularFormsRing
|
|
1624
|
+
sage: j_inv = WeakModularFormsRing(red_hom=True).j_inv()
|
|
1625
|
+
sage: j_inv.q_expansion(prec=3)
|
|
1626
|
+
q^-1 + 31/(72*d) + 1823/(27648*d^2)*q + 10495/(2519424*d^3)*q^2 + O(q^3)
|
|
1627
|
+
|
|
1628
|
+
sage: E2 = QuasiModularFormsRing(n=5, red_hom=True).E2()
|
|
1629
|
+
sage: E2.q_expansion(prec=3)
|
|
1630
|
+
1 - 9/(200*d)*q - 369/(320000*d^2)*q^2 + O(q^3)
|
|
1631
|
+
sage: E2.q_expansion(prec=3, fix_d=1)
|
|
1632
|
+
1 - 9/200*q - 369/320000*q^2 + O(q^3)
|
|
1633
|
+
|
|
1634
|
+
sage: E6 = WeakModularFormsRing(n=5, red_hom=True).E6().full_reduce()
|
|
1635
|
+
sage: Delta = WeakModularFormsRing(n=5, red_hom=True).Delta().full_reduce()
|
|
1636
|
+
sage: E6.q_expansion(prec=3).prec() == 3
|
|
1637
|
+
True
|
|
1638
|
+
sage: (Delta/(E2^3-E6)).q_expansion(prec=3).prec() == 3
|
|
1639
|
+
True
|
|
1640
|
+
sage: (Delta/(E2^3-E6)^3).q_expansion(prec=3).prec() == 3
|
|
1641
|
+
True
|
|
1642
|
+
sage: ((E2^3-E6)/Delta^2).q_expansion(prec=3).prec() == 3
|
|
1643
|
+
True
|
|
1644
|
+
sage: ((E2^3-E6)^3/Delta).q_expansion(prec=3).prec() == 3
|
|
1645
|
+
True
|
|
1646
|
+
|
|
1647
|
+
sage: x,y = var("x,y")
|
|
1648
|
+
sage: el = WeakModularFormsRing()((x+1)/(x^3-y^2))
|
|
1649
|
+
sage: el.q_expansion(prec=2, fix_prec = True)
|
|
1650
|
+
2*d*q^-1 + O(1)
|
|
1651
|
+
sage: el.q_expansion(prec=2)
|
|
1652
|
+
2*d*q^-1 + 1/6 + 119/(41472*d)*q + O(q^2)
|
|
1653
|
+
|
|
1654
|
+
sage: j_inv = WeakModularFormsRing(n=infinity, red_hom=True).j_inv()
|
|
1655
|
+
sage: j_inv.q_expansion(prec=3)
|
|
1656
|
+
q^-1 + 3/(8*d) + 69/(1024*d^2)*q + 1/(128*d^3)*q^2 + O(q^3)
|
|
1657
|
+
|
|
1658
|
+
sage: E2 = QuasiModularFormsRing(n=infinity, red_hom=True).E2()
|
|
1659
|
+
sage: E2.q_expansion(prec=3)
|
|
1660
|
+
1 - 1/(8*d)*q - 1/(512*d^2)*q^2 + O(q^3)
|
|
1661
|
+
sage: E2.q_expansion(prec=3, fix_d=1)
|
|
1662
|
+
1 - 1/8*q - 1/512*q^2 + O(q^3)
|
|
1663
|
+
|
|
1664
|
+
sage: E4 = WeakModularFormsRing(n=infinity, red_hom=True).E4().full_reduce()
|
|
1665
|
+
sage: Delta = WeakModularFormsRing(n=infinity, red_hom=True).Delta().full_reduce()
|
|
1666
|
+
sage: E4.q_expansion(prec=3).prec() == 3
|
|
1667
|
+
True
|
|
1668
|
+
sage: (Delta/(E2^2-E4)).q_expansion(prec=3).prec() == 3
|
|
1669
|
+
True
|
|
1670
|
+
sage: (Delta/(E2^2-E4)^3).q_expansion(prec=3).prec() == 3
|
|
1671
|
+
True
|
|
1672
|
+
sage: ((E2^2-E4)/Delta^2).q_expansion(prec=3).prec() == 3
|
|
1673
|
+
True
|
|
1674
|
+
sage: ((E2^2-E4)^3/Delta).q_expansion(prec=3).prec() == 3
|
|
1675
|
+
True
|
|
1676
|
+
|
|
1677
|
+
sage: x,y = var("x,y")
|
|
1678
|
+
sage: el = WeakModularFormsRing(n=infinity)((x+1)/(x-y^2))
|
|
1679
|
+
sage: el.q_expansion(prec=2, fix_prec = True)
|
|
1680
|
+
2*d*q^-1 + O(1)
|
|
1681
|
+
sage: el.q_expansion(prec=2)
|
|
1682
|
+
2*d*q^-1 + 1/2 + 39/(512*d)*q + O(q^2)
|
|
1683
|
+
"""
|
|
1684
|
+
|
|
1685
|
+
if prec is None:
|
|
1686
|
+
prec = self.parent().default_prec()
|
|
1687
|
+
if d_num_prec is None:
|
|
1688
|
+
d_num_prec = self.parent().default_num_prec()
|
|
1689
|
+
if not isinstance(fix_d, bool):
|
|
1690
|
+
subs_d = fix_d
|
|
1691
|
+
fix_d = None
|
|
1692
|
+
else:
|
|
1693
|
+
subs_d = None
|
|
1694
|
+
|
|
1695
|
+
return self._q_expansion_cached(prec, fix_d, subs_d, d_num_prec, fix_prec)
|
|
1696
|
+
|
|
1697
|
+
def q_expansion_fixed_d(self, prec=None, d_num_prec=None, fix_prec=False):
|
|
1698
|
+
"""
|
|
1699
|
+
Return the Fourier expansion of ``self``.
|
|
1700
|
+
|
|
1701
|
+
The numerical (or exact) value for ``d`` is substituted.
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
INPUT:
|
|
1705
|
+
|
|
1706
|
+
- ``prec`` -- integer; the desired output precision O(q^prec).
|
|
1707
|
+
Default: ``None``, in which case the default precision of
|
|
1708
|
+
``self.parent()`` is used.
|
|
1709
|
+
|
|
1710
|
+
- ``d_num_prec`` -- the precision to be used if a numerical value for
|
|
1711
|
+
``d`` is substituted (default: ``None``), otherwise the default
|
|
1712
|
+
numerical precision of ``self.parent()`` is used
|
|
1713
|
+
|
|
1714
|
+
- ``fix_prec`` -- if ``fix_prec`` is not ``False`` (default)
|
|
1715
|
+
then the precision of the ``MFSeriesConstructor`` is
|
|
1716
|
+
increased such that the output has exactly the specified
|
|
1717
|
+
precision O(q^prec).
|
|
1718
|
+
|
|
1719
|
+
OUTPUT: the Fourier expansion of ``self`` as a ``FormalPowerSeries`` or
|
|
1720
|
+
``FormalLaurentSeries``
|
|
1721
|
+
|
|
1722
|
+
EXAMPLES::
|
|
1723
|
+
|
|
1724
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import WeakModularFormsRing, QuasiModularFormsRing
|
|
1725
|
+
sage: j_inv = WeakModularFormsRing(red_hom=True).j_inv()
|
|
1726
|
+
sage: j_inv.q_expansion_fixed_d(prec=3)
|
|
1727
|
+
q^-1 + 744 + 196884*q + 21493760*q^2 + O(q^3)
|
|
1728
|
+
|
|
1729
|
+
sage: E2 = QuasiModularFormsRing(n=5, red_hom=True).E2()
|
|
1730
|
+
sage: E2.q_expansion_fixed_d(prec=3)
|
|
1731
|
+
1.000000000000... - 6.380956565426...*q - 23.18584547617...*q^2 + O(q^3)
|
|
1732
|
+
|
|
1733
|
+
sage: x,y = var("x,y")
|
|
1734
|
+
sage: WeakModularFormsRing()((x+1)/(x^3-y^2)).q_expansion_fixed_d(prec=2, fix_prec = True)
|
|
1735
|
+
1/864*q^-1 + O(1)
|
|
1736
|
+
sage: WeakModularFormsRing()((x+1)/(x^3-y^2)).q_expansion_fixed_d(prec=2)
|
|
1737
|
+
1/864*q^-1 + 1/6 + 119/24*q + O(q^2)
|
|
1738
|
+
|
|
1739
|
+
sage: j_inv = WeakModularFormsRing(n=infinity, red_hom=True).j_inv()
|
|
1740
|
+
sage: j_inv.q_expansion_fixed_d(prec=3)
|
|
1741
|
+
q^-1 + 24 + 276*q + 2048*q^2 + O(q^3)
|
|
1742
|
+
|
|
1743
|
+
sage: E2 = QuasiModularFormsRing(n=infinity, red_hom=True).E2()
|
|
1744
|
+
sage: E2.q_expansion_fixed_d(prec=3)
|
|
1745
|
+
1 - 8*q - 8*q^2 + O(q^3)
|
|
1746
|
+
|
|
1747
|
+
sage: x,y = var("x,y")
|
|
1748
|
+
sage: WeakModularFormsRing(n=infinity)((x+1)/(x-y^2)).q_expansion_fixed_d(prec=2, fix_prec = True)
|
|
1749
|
+
1/32*q^-1 + O(1)
|
|
1750
|
+
sage: WeakModularFormsRing(n=infinity)((x+1)/(x-y^2)).q_expansion_fixed_d(prec=2)
|
|
1751
|
+
1/32*q^-1 + 1/2 + 39/8*q + O(q^2)
|
|
1752
|
+
|
|
1753
|
+
sage: (WeakModularFormsRing(n=14).J_inv()^3).q_expansion_fixed_d(prec=2)
|
|
1754
|
+
2.933373093...e-6*q^-3 + 0.0002320999814...*q^-2 + 0.009013529265...*q^-1 + 0.2292916854... + 4.303583833...*q + O(q^2)
|
|
1755
|
+
"""
|
|
1756
|
+
|
|
1757
|
+
return self.q_expansion(prec, True, d_num_prec, fix_prec)
|
|
1758
|
+
|
|
1759
|
+
def q_expansion_vector(self, min_exp=None, max_exp=None, prec=None, **kwargs):
|
|
1760
|
+
r"""
|
|
1761
|
+
Return (part of) the Laurent series expansion of ``self`` as a vector.
|
|
1762
|
+
|
|
1763
|
+
INPUT:
|
|
1764
|
+
|
|
1765
|
+
- ``min_exp`` -- integer specifying the first coefficient to be
|
|
1766
|
+
used for the vector. Default: ``None``, meaning that
|
|
1767
|
+
the first non-trivial coefficient is used.
|
|
1768
|
+
|
|
1769
|
+
- ``max_exp`` -- integer specifying the last coefficient to be
|
|
1770
|
+
used for the vector. Default: ``None``, meaning that
|
|
1771
|
+
the default precision + 1 is used.
|
|
1772
|
+
|
|
1773
|
+
- ``prec`` -- integer specifying the precision of the underlying
|
|
1774
|
+
Laurent series. Default: ``None``, meaning that ``max_exp + 1`` is
|
|
1775
|
+
used.
|
|
1776
|
+
|
|
1777
|
+
OUTPUT:
|
|
1778
|
+
|
|
1779
|
+
A vector of size ``max_exp - min_exp`` over the coefficient ring of ``self``,
|
|
1780
|
+
determined by the corresponding Laurent series coefficients.
|
|
1781
|
+
|
|
1782
|
+
EXAMPLES::
|
|
1783
|
+
|
|
1784
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import WeakModularFormsRing
|
|
1785
|
+
sage: f = WeakModularFormsRing(red_hom=True).j_inv()^3
|
|
1786
|
+
sage: f.q_expansion(prec=3)
|
|
1787
|
+
q^-3 + 31/(24*d)*q^-2 + 20845/(27648*d^2)*q^-1 + 7058345/(26873856*d^3) + 30098784355/(495338913792*d^4)*q + 175372747465/(17832200896512*d^5)*q^2 + O(q^3)
|
|
1788
|
+
sage: v = f.q_expansion_vector(max_exp=1, prec=3)
|
|
1789
|
+
sage: v
|
|
1790
|
+
(1, 31/(24*d), 20845/(27648*d^2), 7058345/(26873856*d^3), 30098784355/(495338913792*d^4))
|
|
1791
|
+
sage: v.parent()
|
|
1792
|
+
Vector space of dimension 5 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
|
|
1793
|
+
sage: f.q_expansion_vector(min_exp=1, max_exp=2)
|
|
1794
|
+
(30098784355/(495338913792*d^4), 175372747465/(17832200896512*d^5))
|
|
1795
|
+
sage: f.q_expansion_vector(min_exp=1, max_exp=2, fix_d=True)
|
|
1796
|
+
(541778118390, 151522053809760)
|
|
1797
|
+
|
|
1798
|
+
sage: f = WeakModularFormsRing(n=infinity, red_hom=True).j_inv()^3
|
|
1799
|
+
sage: f.q_expansion_fixed_d(prec=3)
|
|
1800
|
+
q^-3 + 72*q^-2 + 2556*q^-1 + 59712 + 1033974*q + 14175648*q^2 + O(q^3)
|
|
1801
|
+
sage: v = f.q_expansion_vector(max_exp=1, prec=3, fix_d=True)
|
|
1802
|
+
sage: v
|
|
1803
|
+
(1, 72, 2556, 59712, 1033974)
|
|
1804
|
+
sage: v.parent()
|
|
1805
|
+
Vector space of dimension 5 over Rational Field
|
|
1806
|
+
sage: f.q_expansion_vector(min_exp=1, max_exp=2)
|
|
1807
|
+
(516987/(8388608*d^4), 442989/(33554432*d^5))
|
|
1808
|
+
"""
|
|
1809
|
+
|
|
1810
|
+
if (max_exp is None):
|
|
1811
|
+
max_exp = self.parent().default_prec() - 1
|
|
1812
|
+
else:
|
|
1813
|
+
max_exp = ZZ(max_exp)
|
|
1814
|
+
if (prec is None):
|
|
1815
|
+
prec = max_exp + 1
|
|
1816
|
+
else:
|
|
1817
|
+
prec = ZZ(prec)
|
|
1818
|
+
if (prec < max_exp + 1):
|
|
1819
|
+
raise ValueError("The specified precision is too low: {} < {}".format(prec, max_exp + 1))
|
|
1820
|
+
|
|
1821
|
+
qexp = self.q_expansion(prec=prec, **kwargs)
|
|
1822
|
+
|
|
1823
|
+
if min_exp is None:
|
|
1824
|
+
min_exp = qexp.valuation()
|
|
1825
|
+
else:
|
|
1826
|
+
min_exp = ZZ(min_exp)
|
|
1827
|
+
|
|
1828
|
+
return vector([qexp[m] for m in range(min_exp, max_exp + 1)])
|
|
1829
|
+
|
|
1830
|
+
def evaluate(self, tau, prec=None, num_prec=None, check=False):
|
|
1831
|
+
r"""
|
|
1832
|
+
Try to return ``self`` evaluated at a point ``tau``
|
|
1833
|
+
in the upper half plane, where ``self`` is interpreted
|
|
1834
|
+
as a function in ``tau``, where ``q=exp(2*pi*i*tau)``.
|
|
1835
|
+
|
|
1836
|
+
Note that this interpretation might not make sense
|
|
1837
|
+
(and fail) for certain (many) choices of
|
|
1838
|
+
(``base_ring``, ``tau.parent()``).
|
|
1839
|
+
|
|
1840
|
+
It is possible to evaluate at points of :class:`HyperbolicPlane`.
|
|
1841
|
+
In this case the coordinates of the upper half plane model are used.
|
|
1842
|
+
|
|
1843
|
+
To obtain a precise and fast result the parameters
|
|
1844
|
+
``prec`` and ``num_prec`` both have to be considered/balanced.
|
|
1845
|
+
A high ``prec`` value is usually quite costly.
|
|
1846
|
+
|
|
1847
|
+
INPUT:
|
|
1848
|
+
|
|
1849
|
+
- ``tau`` -- ``infinity`` or an element of the upper
|
|
1850
|
+
half plane. E.g. with parent ``AA`` or ``CC``.
|
|
1851
|
+
|
|
1852
|
+
- ``prec`` -- integer, namely the precision used for the
|
|
1853
|
+
Fourier expansion. If ``prec == None`` (default)
|
|
1854
|
+
then the default precision of ``self.parent()`` is used
|
|
1855
|
+
|
|
1856
|
+
- ``num_prec`` -- integer, namely the minimal numerical precision
|
|
1857
|
+
used for ``tau`` and ``d``. If ``num_prec == None``
|
|
1858
|
+
(default) then the default numerical precision of
|
|
1859
|
+
``self.parent()`` is used.
|
|
1860
|
+
|
|
1861
|
+
- ``check`` -- if ``True`` then the order of ``tau`` is checked.
|
|
1862
|
+
Otherwise the order is only considered for
|
|
1863
|
+
``tau = infinity, i, rho, -1/rho``. Default: ``False``.
|
|
1864
|
+
|
|
1865
|
+
OUTPUT:
|
|
1866
|
+
|
|
1867
|
+
The (numerical) evaluated function value.
|
|
1868
|
+
|
|
1869
|
+
|
|
1870
|
+
ALGORITHM:
|
|
1871
|
+
|
|
1872
|
+
#. If the order of ``self`` at ``tau`` is known and nonzero:
|
|
1873
|
+
Return ``0`` resp. ``infinity``.
|
|
1874
|
+
|
|
1875
|
+
#. Else if ``tau==infinity`` and the order is zero:
|
|
1876
|
+
Return the constant Fourier coefficient of ``self``.
|
|
1877
|
+
|
|
1878
|
+
#. Else if ``self`` is homogeneous and modular:
|
|
1879
|
+
|
|
1880
|
+
#. Because of the (modular) transformation property
|
|
1881
|
+
of ``self`` the evaluation at ``tau`` is given by
|
|
1882
|
+
the evaluation at ``w`` multiplied by ``aut_factor(A,w)``.
|
|
1883
|
+
|
|
1884
|
+
#. The evaluation at ``w`` is calculated by
|
|
1885
|
+
evaluating the truncated Fourier expansion of
|
|
1886
|
+
``self`` at ``q(w)``.
|
|
1887
|
+
|
|
1888
|
+
Note that this is much faster and more precise
|
|
1889
|
+
than a direct evaluation at ``tau``.
|
|
1890
|
+
|
|
1891
|
+
#. Else if ``self`` is exactly ``E2``:
|
|
1892
|
+
|
|
1893
|
+
#. The same procedure as before is applied (with
|
|
1894
|
+
the aut_factor from the corresponding modular
|
|
1895
|
+
space).
|
|
1896
|
+
|
|
1897
|
+
#. Except that at the end a correction term for
|
|
1898
|
+
the quasimodular form ``E2`` of the form
|
|
1899
|
+
``4*lambda/(2*pi*i)*n/(n-2) * c*(c*w + d)``
|
|
1900
|
+
(resp. ``4/(pi*i) * c*(c*w + d)`` for ``n=infinity``)
|
|
1901
|
+
has to be added, where ``lambda = 2*cos(pi/n)``
|
|
1902
|
+
(resp ``lambda = 2`` for ``n=infinity``) and
|
|
1903
|
+
``c,d`` are the lower entries of the matrix ``A``.
|
|
1904
|
+
|
|
1905
|
+
#. Else:
|
|
1906
|
+
|
|
1907
|
+
#. Evaluate ``f_rho, f_i, E2`` at ``tau``
|
|
1908
|
+
using the above procedures.
|
|
1909
|
+
If ``n=infinity`` use ``E4`` instead of ``f_rho``.
|
|
1910
|
+
|
|
1911
|
+
#. Substitute ``x=f_rho(tau), y=f_i(tau), z=E2(tau)``
|
|
1912
|
+
and the numerical value of ``d`` for ``d``
|
|
1913
|
+
in ``self.rat()``. If ``n=infinity`` then
|
|
1914
|
+
substitute ``x=E4(tau)`` instead.
|
|
1915
|
+
|
|
1916
|
+
EXAMPLES::
|
|
1917
|
+
|
|
1918
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
1919
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
1920
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=5, red_hom=True)
|
|
1921
|
+
sage: f_rho = MR.f_rho().full_reduce()
|
|
1922
|
+
sage: f_i = MR.f_i().full_reduce()
|
|
1923
|
+
sage: f_inf = MR.f_inf().full_reduce()
|
|
1924
|
+
sage: E2 = MR.E2().full_reduce()
|
|
1925
|
+
sage: E4 = MR.E4().full_reduce()
|
|
1926
|
+
sage: rho = MR.group().rho()
|
|
1927
|
+
|
|
1928
|
+
sage: f_rho(rho)
|
|
1929
|
+
0
|
|
1930
|
+
sage: f_rho(rho + 1e-100) # since rho == rho + 1e-100
|
|
1931
|
+
0
|
|
1932
|
+
sage: f_rho(rho + 1e-6)
|
|
1933
|
+
2.525...e-10 - 3.884...e-6*I
|
|
1934
|
+
sage: f_i(i)
|
|
1935
|
+
0
|
|
1936
|
+
sage: f_i(i + 1e-1000) # rel tol 5e-2
|
|
1937
|
+
-6.08402217494586e-14 - 4.10147008296517e-1000*I
|
|
1938
|
+
sage: f_inf(infinity)
|
|
1939
|
+
0
|
|
1940
|
+
|
|
1941
|
+
sage: i = I = QuadraticField(-1, 'I').gen()
|
|
1942
|
+
sage: z = -1/(-1/(2*i+30)-1)
|
|
1943
|
+
sage: z
|
|
1944
|
+
2/965*I + 934/965
|
|
1945
|
+
sage: E4(z)
|
|
1946
|
+
32288.05588811... - 118329.8566016...*I
|
|
1947
|
+
sage: E4(z, prec=30, num_prec=100) # long time
|
|
1948
|
+
32288.0558872351130041311053... - 118329.856600349999751420381...*I
|
|
1949
|
+
sage: E2(z)
|
|
1950
|
+
409.3144737105... + 100.6926857489...*I
|
|
1951
|
+
sage: E2(z, prec=30, num_prec=100) # long time
|
|
1952
|
+
409.314473710489761254584951... + 100.692685748952440684513866...*I
|
|
1953
|
+
sage: (E2^2-E4)(z)
|
|
1954
|
+
125111.2655383... + 200759.8039479...*I
|
|
1955
|
+
sage: (E2^2-E4)(z, prec=30, num_prec=100) # long time
|
|
1956
|
+
125111.265538336196262200469... + 200759.803948009905410385699...*I
|
|
1957
|
+
|
|
1958
|
+
sage: (E2^2-E4)(infinity)
|
|
1959
|
+
0
|
|
1960
|
+
sage: (1/(E2^2-E4))(infinity)
|
|
1961
|
+
+Infinity
|
|
1962
|
+
sage: ((E2^2-E4)/f_inf)(infinity)
|
|
1963
|
+
-3/(10*d)
|
|
1964
|
+
|
|
1965
|
+
sage: G = HeckeTriangleGroup(n=8)
|
|
1966
|
+
sage: MR = QuasiMeromorphicModularFormsRing(group=G, red_hom=True)
|
|
1967
|
+
sage: f_rho = MR.f_rho().full_reduce()
|
|
1968
|
+
sage: f_i = MR.f_i().full_reduce()
|
|
1969
|
+
sage: E2 = MR.E2().full_reduce()
|
|
1970
|
+
|
|
1971
|
+
sage: z = AlgebraicField()(1/10+13/10*I)
|
|
1972
|
+
sage: A = G.V(4)
|
|
1973
|
+
sage: S = G.S()
|
|
1974
|
+
sage: T = G.T()
|
|
1975
|
+
sage: A == (T*S)**3*T
|
|
1976
|
+
True
|
|
1977
|
+
sage: az = A.acton(z)
|
|
1978
|
+
sage: az == (A[0,0]*z + A[0,1]) / (A[1,0]*z + A[1,1])
|
|
1979
|
+
True
|
|
1980
|
+
|
|
1981
|
+
sage: f_rho(z)
|
|
1982
|
+
1.03740476727... + 0.0131941034523...*I
|
|
1983
|
+
sage: f_rho(az)
|
|
1984
|
+
-2.29216470688... - 1.46235057536...*I
|
|
1985
|
+
sage: k = f_rho.weight()
|
|
1986
|
+
sage: aut_fact = f_rho.ep()^3 * (((T*S)**2*T).acton(z)/AlgebraicField()(i))**k * (((T*S)*T).acton(z)/AlgebraicField()(i))**k * (T.acton(z)/AlgebraicField()(i))**k
|
|
1987
|
+
sage: abs(aut_fact - f_rho.parent().aut_factor(A, z)) < 1e-12
|
|
1988
|
+
True
|
|
1989
|
+
sage: aut_fact * f_rho(z)
|
|
1990
|
+
-2.29216470688... - 1.46235057536...*I
|
|
1991
|
+
|
|
1992
|
+
sage: f_rho.parent().default_num_prec(1000)
|
|
1993
|
+
sage: f_rho.parent().default_prec(300)
|
|
1994
|
+
sage: (f_rho.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*z/G.lam())) # long time
|
|
1995
|
+
1.0374047672719462149821251... + 0.013194103452368974597290332...*I
|
|
1996
|
+
sage: (f_rho.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*az/G.lam())) # long time
|
|
1997
|
+
-2.2921647068881834598616367... - 1.4623505753697635207183406...*I
|
|
1998
|
+
|
|
1999
|
+
sage: f_i(z)
|
|
2000
|
+
0.667489320423... - 0.118902824870...*I
|
|
2001
|
+
sage: f_i(az)
|
|
2002
|
+
14.5845388476... - 28.4604652892...*I
|
|
2003
|
+
sage: k = f_i.weight()
|
|
2004
|
+
sage: aut_fact = f_i.ep()^3 * (((T*S)**2*T).acton(z)/AlgebraicField()(i))**k * (((T*S)*T).acton(z)/AlgebraicField()(i))**k * (T.acton(z)/AlgebraicField()(i))**k
|
|
2005
|
+
sage: abs(aut_fact - f_i.parent().aut_factor(A, z)) < 1e-12
|
|
2006
|
+
True
|
|
2007
|
+
sage: aut_fact * f_i(z)
|
|
2008
|
+
14.5845388476... - 28.4604652892...*I
|
|
2009
|
+
|
|
2010
|
+
sage: f_i.parent().default_num_prec(1000)
|
|
2011
|
+
sage: f_i.parent().default_prec(300)
|
|
2012
|
+
sage: (f_i.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*z/G.lam())) # long time
|
|
2013
|
+
0.66748932042300250077433252... - 0.11890282487028677063054267...*I
|
|
2014
|
+
sage: (f_i.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*az/G.lam())) # long time
|
|
2015
|
+
14.584538847698600875918891... - 28.460465289220303834894855...*I
|
|
2016
|
+
|
|
2017
|
+
sage: f = f_rho*E2
|
|
2018
|
+
sage: f(z)
|
|
2019
|
+
0.966024386418... - 0.0138894699429...*I
|
|
2020
|
+
sage: f(az)
|
|
2021
|
+
-15.9978074989... - 29.2775758341...*I
|
|
2022
|
+
sage: k = f.weight()
|
|
2023
|
+
sage: aut_fact = f.ep()^3 * (((T*S)**2*T).acton(z)/AlgebraicField()(i))**k * (((T*S)*T).acton(z)/AlgebraicField()(i))**k * (T.acton(z)/AlgebraicField()(i))**k
|
|
2024
|
+
sage: abs(aut_fact - f.parent().aut_factor(A, z)) < 1e-12
|
|
2025
|
+
True
|
|
2026
|
+
sage: k2 = f_rho.weight()
|
|
2027
|
+
sage: aut_fact2 = f_rho.ep() * (((T*S)**2*T).acton(z)/AlgebraicField()(i))**k2 * (((T*S)*T).acton(z)/AlgebraicField()(i))**k2 * (T.acton(z)/AlgebraicField()(i))**k2
|
|
2028
|
+
sage: abs(aut_fact2 - f_rho.parent().aut_factor(A, z)) < 1e-12
|
|
2029
|
+
True
|
|
2030
|
+
sage: cor_term = (4 * G.n() / (G.n()-2) * A.c() * (A.c()*z+A.d())) / (2*pi*i).n(1000) * G.lam()
|
|
2031
|
+
sage: aut_fact*f(z) + cor_term*aut_fact2*f_rho(z)
|
|
2032
|
+
-15.9978074989... - 29.2775758341...*I
|
|
2033
|
+
|
|
2034
|
+
sage: f.parent().default_num_prec(1000)
|
|
2035
|
+
sage: f.parent().default_prec(300)
|
|
2036
|
+
sage: (f.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*z/G.lam())) # long time
|
|
2037
|
+
0.96602438641867296777809436... - 0.013889469942995530807311503...*I
|
|
2038
|
+
sage: (f.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*az/G.lam())) # long time
|
|
2039
|
+
-15.997807498958825352887040... - 29.277575834123246063432206...*I
|
|
2040
|
+
|
|
2041
|
+
sage: MR = QuasiMeromorphicModularFormsRing(n=infinity, red_hom=True)
|
|
2042
|
+
sage: f_i = MR.f_i().full_reduce()
|
|
2043
|
+
sage: f_inf = MR.f_inf().full_reduce()
|
|
2044
|
+
sage: E2 = MR.E2().full_reduce()
|
|
2045
|
+
sage: E4 = MR.E4().full_reduce()
|
|
2046
|
+
|
|
2047
|
+
sage: f_i(i)
|
|
2048
|
+
0
|
|
2049
|
+
sage: f_i(i + 1e-1000)
|
|
2050
|
+
2.991...e-12 - 3.048...e-1000*I
|
|
2051
|
+
sage: f_inf(infinity)
|
|
2052
|
+
0
|
|
2053
|
+
|
|
2054
|
+
sage: z = -1/(-1/(2*i+30)-1)
|
|
2055
|
+
sage: E4(z, prec=15)
|
|
2056
|
+
804.0722034... + 211.9278206...*I
|
|
2057
|
+
sage: E4(z, prec=30, num_prec=100) # long time
|
|
2058
|
+
803.928382417... + 211.889914044...*I
|
|
2059
|
+
sage: E2(z)
|
|
2060
|
+
2.438455612... - 39.48442265...*I
|
|
2061
|
+
sage: E2(z, prec=30, num_prec=100) # long time
|
|
2062
|
+
2.43968197227756036957475... - 39.4842637577742677851431...*I
|
|
2063
|
+
sage: (E2^2-E4)(z)
|
|
2064
|
+
-2265.442515... - 380.3197877...*I
|
|
2065
|
+
sage: (E2^2-E4)(z, prec=30, num_prec=100) # long time
|
|
2066
|
+
-2265.44251550679807447320... - 380.319787790548788238792...*I
|
|
2067
|
+
|
|
2068
|
+
sage: (E2^2-E4)(infinity)
|
|
2069
|
+
0
|
|
2070
|
+
sage: (1/(E2^2-E4))(infinity)
|
|
2071
|
+
+Infinity
|
|
2072
|
+
sage: ((E2^2-E4)/f_inf)(infinity)
|
|
2073
|
+
-1/(2*d)
|
|
2074
|
+
|
|
2075
|
+
sage: G = HeckeTriangleGroup(n=Infinity)
|
|
2076
|
+
sage: z = AlgebraicField()(1/10+13/10*I)
|
|
2077
|
+
sage: A = G.V(4)
|
|
2078
|
+
sage: S = G.S()
|
|
2079
|
+
sage: T = G.T()
|
|
2080
|
+
sage: A == (T*S)**3*T
|
|
2081
|
+
True
|
|
2082
|
+
sage: az = A.acton(z)
|
|
2083
|
+
sage: az == (A[0,0]*z + A[0,1]) / (A[1,0]*z + A[1,1])
|
|
2084
|
+
True
|
|
2085
|
+
|
|
2086
|
+
sage: f_i(z)
|
|
2087
|
+
0.6208853409... - 0.1212525492...*I
|
|
2088
|
+
sage: f_i(az)
|
|
2089
|
+
6.103314419... + 20.42678597...*I
|
|
2090
|
+
sage: k = f_i.weight()
|
|
2091
|
+
sage: aut_fact = f_i.ep()^3 * (((T*S)**2*T).acton(z)/AlgebraicField()(i))**k * (((T*S)*T).acton(z)/AlgebraicField()(i))**k * (T.acton(z)/AlgebraicField()(i))**k
|
|
2092
|
+
sage: abs(aut_fact - f_i.parent().aut_factor(A, z)) < 1e-12
|
|
2093
|
+
True
|
|
2094
|
+
sage: aut_fact * f_i(z)
|
|
2095
|
+
6.103314419... + 20.42678597...*I
|
|
2096
|
+
|
|
2097
|
+
sage: f_i.parent().default_num_prec(1000)
|
|
2098
|
+
sage: f_i.parent().default_prec(300)
|
|
2099
|
+
sage: (f_i.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*z/G.lam())) # long time
|
|
2100
|
+
0.620885340917559158572271... - 0.121252549240996430425967...*I
|
|
2101
|
+
sage: (f_i.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*az/G.lam())) # long time
|
|
2102
|
+
6.10331441975198186745017... + 20.4267859728657976382684...*I
|
|
2103
|
+
|
|
2104
|
+
sage: f = f_i*E2
|
|
2105
|
+
sage: f(z)
|
|
2106
|
+
0.5349190275... - 0.1322370856...*I
|
|
2107
|
+
sage: f(az)
|
|
2108
|
+
-140.4711702... + 469.0793692...*I
|
|
2109
|
+
sage: k = f.weight()
|
|
2110
|
+
sage: aut_fact = f.ep()^3 * (((T*S)**2*T).acton(z)/AlgebraicField()(i))**k * (((T*S)*T).acton(z)/AlgebraicField()(i))**k * (T.acton(z)/AlgebraicField()(i))**k
|
|
2111
|
+
sage: abs(aut_fact - f.parent().aut_factor(A, z)) < 1e-12
|
|
2112
|
+
True
|
|
2113
|
+
sage: k2 = f_i.weight()
|
|
2114
|
+
sage: aut_fact2 = f_i.ep() * (((T*S)**2*T).acton(z)/AlgebraicField()(i))**k2 * (((T*S)*T).acton(z)/AlgebraicField()(i))**k2 * (T.acton(z)/AlgebraicField()(i))**k2
|
|
2115
|
+
sage: abs(aut_fact2 - f_i.parent().aut_factor(A, z)) < 1e-12
|
|
2116
|
+
True
|
|
2117
|
+
sage: cor_term = (4 * A.c() * (A.c()*z+A.d())) / (2*pi*i).n(1000) * G.lam()
|
|
2118
|
+
sage: aut_fact*f(z) + cor_term*aut_fact2*f_i(z)
|
|
2119
|
+
-140.4711702... + 469.0793692...*I
|
|
2120
|
+
|
|
2121
|
+
sage: f.parent().default_num_prec(1000)
|
|
2122
|
+
sage: f.parent().default_prec(300)
|
|
2123
|
+
sage: (f.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*z/G.lam())) # long time
|
|
2124
|
+
0.534919027587592616802582... - 0.132237085641931661668338...*I
|
|
2125
|
+
|
|
2126
|
+
sage: (f.q_expansion_fixed_d().polynomial())(exp((2*pi*i).n(1000)*az/G.lam())) # long time
|
|
2127
|
+
-140.471170232432551196978... + 469.079369280804086032719...*I
|
|
2128
|
+
|
|
2129
|
+
It is possible to evaluate at points of :class:`HyperbolicPlane`::
|
|
2130
|
+
|
|
2131
|
+
sage: # needs sage.symbolic
|
|
2132
|
+
sage: p = HyperbolicPlane().PD().get_point(-I/2)
|
|
2133
|
+
sage: bool(p.to_model('UHP').coordinates() == I/3)
|
|
2134
|
+
True
|
|
2135
|
+
sage: E4(p) == E4(I/3)
|
|
2136
|
+
True
|
|
2137
|
+
sage: p = HyperbolicPlane().PD().get_point(I)
|
|
2138
|
+
sage: f_inf(p, check=True) == 0
|
|
2139
|
+
True
|
|
2140
|
+
sage: (1/(E2^2-E4))(p) == infinity
|
|
2141
|
+
True
|
|
2142
|
+
"""
|
|
2143
|
+
|
|
2144
|
+
i = QuadraticField(-1, 'I').gen()
|
|
2145
|
+
|
|
2146
|
+
# if tau is a point of HyperbolicPlane then we use it's coordinates in the UHP model
|
|
2147
|
+
if _in_HyperbolicPlane(tau):
|
|
2148
|
+
tau = tau.to_model('UHP').coordinates()
|
|
2149
|
+
|
|
2150
|
+
if (prec is None):
|
|
2151
|
+
prec = self.parent().default_prec()
|
|
2152
|
+
if (num_prec is None):
|
|
2153
|
+
num_prec = self.parent().default_num_prec()
|
|
2154
|
+
|
|
2155
|
+
# In case the order is known
|
|
2156
|
+
try:
|
|
2157
|
+
if (check or tau == infinity or tau == i or
|
|
2158
|
+
tau == self.group().rho() or
|
|
2159
|
+
tau == -self.group().rho().conjugate()):
|
|
2160
|
+
order_tau = self.order_at(tau)
|
|
2161
|
+
|
|
2162
|
+
if order_tau > 0:
|
|
2163
|
+
return ZZ(0)
|
|
2164
|
+
elif (order_tau < 0):
|
|
2165
|
+
return infinity
|
|
2166
|
+
elif (tau == infinity):
|
|
2167
|
+
return self.q_expansion(prec=1)[0]
|
|
2168
|
+
except (TypeError, NotImplementedError):
|
|
2169
|
+
pass
|
|
2170
|
+
|
|
2171
|
+
# The general case
|
|
2172
|
+
num_prec = max(ZZ(getattr(tau, 'prec', lambda: num_prec)()), num_prec)
|
|
2173
|
+
|
|
2174
|
+
tau = tau.n(num_prec)
|
|
2175
|
+
(x, y, z, d) = self.parent().rat_field().gens()
|
|
2176
|
+
|
|
2177
|
+
if (self.is_homogeneous() and self.is_modular()):
|
|
2178
|
+
q_exp = self.q_expansion_fixed_d(prec=prec, d_num_prec=num_prec)
|
|
2179
|
+
(A, w) = self.group().get_FD(tau)
|
|
2180
|
+
aut_factor = self.reduce(force=True).parent().aut_factor(A, w)
|
|
2181
|
+
if (type(q_exp) is LaurentSeries):
|
|
2182
|
+
return q_exp.laurent_polynomial()(exp((2 * pi * i).n(num_prec) / self.group().lam() * w)) * aut_factor
|
|
2183
|
+
else:
|
|
2184
|
+
return q_exp.polynomial()(exp((2 * pi * i).n(num_prec) / self.group().lam() * w)) * aut_factor
|
|
2185
|
+
elif self._rat == z:
|
|
2186
|
+
E2 = self.parent().graded_ring().E2().reduce(force=True)
|
|
2187
|
+
(A, w) = self.group().get_FD(tau)
|
|
2188
|
+
aut_factor = E2.parent().aut_factor(A, w)
|
|
2189
|
+
E2_wvalue = E2.q_expansion_fixed_d(prec=prec, d_num_prec=num_prec).polynomial()(exp((2 * pi * i).n(num_prec) / self.group().lam() * w))
|
|
2190
|
+
if (self.hecke_n() == infinity):
|
|
2191
|
+
E2_cor_term = 4 * self.group().lam() / (2 * pi * i).n(num_prec) * A.c() * (A.c() * w + A.d())
|
|
2192
|
+
else:
|
|
2193
|
+
E2_cor_term = 4 * self.group().lam() / (2 * pi * i).n(num_prec) * self.hecke_n() / (self.hecke_n() - 2) * A.c() * (A.c() * w + A.d())
|
|
2194
|
+
return E2_wvalue * aut_factor + E2_cor_term
|
|
2195
|
+
else:
|
|
2196
|
+
f_i = self.parent().graded_ring().f_i()
|
|
2197
|
+
E2 = self.parent().graded_ring().E2()
|
|
2198
|
+
dval = self.parent().group().dvalue().n(num_prec)
|
|
2199
|
+
if (self.hecke_n() == infinity):
|
|
2200
|
+
E4 = self.parent().graded_ring().E4()
|
|
2201
|
+
return self._rat.subs(x=E4(tau), y=f_i(tau), z=E2(tau), d=dval)
|
|
2202
|
+
else:
|
|
2203
|
+
f_rho = self.parent().graded_ring().f_rho()
|
|
2204
|
+
return self._rat.subs(x=f_rho(tau), y=f_i(tau), z=E2(tau), d=dval)
|
|
2205
|
+
|
|
2206
|
+
def __call__(self, tau, prec=None, num_prec=None, check=False):
|
|
2207
|
+
r"""
|
|
2208
|
+
Try to return ``self`` evaluated at a point ``tau``
|
|
2209
|
+
in the upper half plane, where ``self`` is interpreted
|
|
2210
|
+
as a function in ``tau``, where ``q=exp(2*pi*i*tau)``.
|
|
2211
|
+
|
|
2212
|
+
See :meth:`.evaluate` for more details.
|
|
2213
|
+
|
|
2214
|
+
EXAMPLES::
|
|
2215
|
+
|
|
2216
|
+
sage: from sage.modular.modform_hecketriangle.graded_ring import QuasiMeromorphicModularFormsRing
|
|
2217
|
+
sage: E4 = QuasiMeromorphicModularFormsRing(n=5, red_hom=True).E4().full_reduce()
|
|
2218
|
+
sage: z = -1/(-1/(2*i+30)-1)
|
|
2219
|
+
sage: E4(z)
|
|
2220
|
+
32288.05588811... - 118329.8566016...*I
|
|
2221
|
+
sage: E4(z) == E4.evaluate(z)
|
|
2222
|
+
True
|
|
2223
|
+
"""
|
|
2224
|
+
|
|
2225
|
+
return self.evaluate(tau, prec, num_prec, check)
|