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.
Files changed (311) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.6.47.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
  9. passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.47.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-312-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +745 -0
  29. sage/lfunctions/pari.py +818 -0
  30. sage/lfunctions/zero_sums.cpython-312-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5135 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
  34. sage/modular/abvar/abvar_newform.py +244 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +186 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +720 -0
  40. sage/modular/abvar/homspace.py +998 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +740 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-312-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1402 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-312-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +363 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +653 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1469 -0
  57. sage/modular/arithgroup/congroup_generic.py +628 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +267 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-312-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1066 -0
  61. sage/modular/arithgroup/tests.py +418 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3753 -0
  64. sage/modular/btquotients/pautomorphicform.py +2570 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1109 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +569 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1065 -0
  77. sage/modular/hecke/algebra.py +746 -0
  78. sage/modular/hecke/all.py +20 -0
  79. sage/modular/hecke/ambient_module.py +1019 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +325 -0
  82. sage/modular/hecke/hecke_operator.py +780 -0
  83. sage/modular/hecke/homspace.py +206 -0
  84. sage/modular/hecke/module.py +1767 -0
  85. sage/modular/hecke/morphism.py +174 -0
  86. sage/modular/hecke/submodule.py +989 -0
  87. sage/modular/hypergeometric_misc.cpython-312-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2017 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1071 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +815 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +124 -0
  101. sage/modular/modform/ambient_g1.py +204 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +505 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4131 -0
  108. sage/modular/modform/find_generators.py +59 -0
  109. sage/modular/modform/half_integral.py +154 -0
  110. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  111. sage/modular/modform/j_invariant.py +47 -0
  112. sage/modular/modform/l_series_gross_zagier.py +133 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-312-darwin.so +0 -0
  114. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  115. sage/modular/modform/notes.py +45 -0
  116. sage/modular/modform/numerical.py +514 -0
  117. sage/modular/modform/periods.py +14 -0
  118. sage/modular/modform/ring.py +1257 -0
  119. sage/modular/modform/space.py +1860 -0
  120. sage/modular/modform/submodule.py +118 -0
  121. sage/modular/modform/tests.py +64 -0
  122. sage/modular/modform/theta.py +110 -0
  123. sage/modular/modform/vm_basis.py +381 -0
  124. sage/modular/modform/weight1.py +220 -0
  125. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  126. sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
  127. sage/modular/modform_hecketriangle/all.py +30 -0
  128. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  129. sage/modular/modform_hecketriangle/constructor.py +416 -0
  130. sage/modular/modform_hecketriangle/element.py +351 -0
  131. sage/modular/modform_hecketriangle/functors.py +752 -0
  132. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  133. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
  135. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
  136. sage/modular/modform_hecketriangle/readme.py +1214 -0
  137. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  138. sage/modular/modform_hecketriangle/space.py +1037 -0
  139. sage/modular/modform_hecketriangle/subspace.py +423 -0
  140. sage/modular/modsym/all.py +17 -0
  141. sage/modular/modsym/ambient.py +3846 -0
  142. sage/modular/modsym/boundary.py +1420 -0
  143. sage/modular/modsym/element.py +336 -0
  144. sage/modular/modsym/g1list.py +178 -0
  145. sage/modular/modsym/ghlist.py +182 -0
  146. sage/modular/modsym/hecke_operator.py +73 -0
  147. sage/modular/modsym/manin_symbol.cpython-312-darwin.so +0 -0
  148. sage/modular/modsym/manin_symbol.pxd +5 -0
  149. sage/modular/modsym/manin_symbol.pyx +497 -0
  150. sage/modular/modsym/manin_symbol_list.py +1295 -0
  151. sage/modular/modsym/modsym.py +400 -0
  152. sage/modular/modsym/modular_symbols.py +384 -0
  153. sage/modular/modsym/p1list_nf.py +1241 -0
  154. sage/modular/modsym/relation_matrix.py +591 -0
  155. sage/modular/modsym/relation_matrix_pyx.cpython-312-darwin.so +0 -0
  156. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  157. sage/modular/modsym/space.py +2468 -0
  158. sage/modular/modsym/subspace.py +455 -0
  159. sage/modular/modsym/tests.py +375 -0
  160. sage/modular/multiple_zeta.py +2632 -0
  161. sage/modular/multiple_zeta_F_algebra.py +786 -0
  162. sage/modular/overconvergent/all.py +6 -0
  163. sage/modular/overconvergent/genus0.py +1878 -0
  164. sage/modular/overconvergent/hecke_series.py +1187 -0
  165. sage/modular/overconvergent/weightspace.py +778 -0
  166. sage/modular/pollack_stevens/all.py +4 -0
  167. sage/modular/pollack_stevens/distributions.py +874 -0
  168. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  169. sage/modular/pollack_stevens/manin_map.py +859 -0
  170. sage/modular/pollack_stevens/modsym.py +1593 -0
  171. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  172. sage/modular/pollack_stevens/sigma0.py +534 -0
  173. sage/modular/pollack_stevens/space.py +1076 -0
  174. sage/modular/quasimodform/all.py +3 -0
  175. sage/modular/quasimodform/element.py +845 -0
  176. sage/modular/quasimodform/ring.py +828 -0
  177. sage/modular/quatalg/all.py +3 -0
  178. sage/modular/quatalg/brandt.py +1642 -0
  179. sage/modular/ssmod/all.py +8 -0
  180. sage/modular/ssmod/ssmod.py +827 -0
  181. sage/rings/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  183. sage/rings/polynomial/binary_form_reduce.py +585 -0
  184. sage/schemes/all.py +41 -0
  185. sage/schemes/berkovich/all.py +6 -0
  186. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  187. sage/schemes/berkovich/berkovich_space.py +748 -0
  188. sage/schemes/curves/affine_curve.py +2928 -0
  189. sage/schemes/curves/all.py +33 -0
  190. sage/schemes/curves/closed_point.py +434 -0
  191. sage/schemes/curves/constructor.py +381 -0
  192. sage/schemes/curves/curve.py +542 -0
  193. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  194. sage/schemes/curves/point.py +463 -0
  195. sage/schemes/curves/projective_curve.py +3026 -0
  196. sage/schemes/curves/zariski_vankampen.py +1932 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +1036 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1102 -0
  208. sage/schemes/elliptic_curves/constructor.py +1552 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4787 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7335 -0
  229. sage/schemes/elliptic_curves/height.py +2109 -0
  230. sage/schemes/elliptic_curves/hom.py +1406 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  232. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  233. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  234. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  235. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  236. sage/schemes/elliptic_curves/homset.py +271 -0
  237. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  238. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  239. sage/schemes/elliptic_curves/jacobian.py +237 -0
  240. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  241. sage/schemes/elliptic_curves/kraus.py +1014 -0
  242. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  243. sage/schemes/elliptic_curves/mod5family.py +105 -0
  244. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  245. sage/schemes/elliptic_curves/mod_sym_num.cpython-312-darwin.so +0 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  247. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  248. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  249. sage/schemes/elliptic_curves/padics.py +1816 -0
  250. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  251. sage/schemes/elliptic_curves/period_lattice_region.cpython-312-darwin.so +0 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  253. sage/schemes/elliptic_curves/saturation.py +715 -0
  254. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  255. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  256. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  257. sage/schemes/hyperelliptic_curves/all.py +6 -0
  258. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  259. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  264. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  265. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  270. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  271. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  272. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  273. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  274. sage/schemes/jacobians/all.py +2 -0
  275. sage/schemes/overview.py +161 -0
  276. sage/schemes/plane_conics/all.py +22 -0
  277. sage/schemes/plane_conics/con_field.py +1296 -0
  278. sage/schemes/plane_conics/con_finite_field.py +158 -0
  279. sage/schemes/plane_conics/con_number_field.py +456 -0
  280. sage/schemes/plane_conics/con_rational_field.py +406 -0
  281. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  282. sage/schemes/plane_conics/constructor.py +249 -0
  283. sage/schemes/plane_quartics/all.py +2 -0
  284. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  285. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  286. sage/schemes/riemann_surfaces/all.py +1 -0
  287. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  288. sage_wheels/share/cremona/cremona_mini.db +0 -0
  289. sage_wheels/share/ellcurves/rank0 +30427 -0
  290. sage_wheels/share/ellcurves/rank1 +31871 -0
  291. sage_wheels/share/ellcurves/rank10 +6 -0
  292. sage_wheels/share/ellcurves/rank11 +6 -0
  293. sage_wheels/share/ellcurves/rank12 +1 -0
  294. sage_wheels/share/ellcurves/rank14 +1 -0
  295. sage_wheels/share/ellcurves/rank15 +1 -0
  296. sage_wheels/share/ellcurves/rank17 +1 -0
  297. sage_wheels/share/ellcurves/rank19 +1 -0
  298. sage_wheels/share/ellcurves/rank2 +2388 -0
  299. sage_wheels/share/ellcurves/rank20 +1 -0
  300. sage_wheels/share/ellcurves/rank21 +1 -0
  301. sage_wheels/share/ellcurves/rank22 +1 -0
  302. sage_wheels/share/ellcurves/rank23 +1 -0
  303. sage_wheels/share/ellcurves/rank24 +1 -0
  304. sage_wheels/share/ellcurves/rank28 +1 -0
  305. sage_wheels/share/ellcurves/rank3 +836 -0
  306. sage_wheels/share/ellcurves/rank4 +10 -0
  307. sage_wheels/share/ellcurves/rank5 +5 -0
  308. sage_wheels/share/ellcurves/rank6 +5 -0
  309. sage_wheels/share/ellcurves/rank7 +5 -0
  310. sage_wheels/share/ellcurves/rank8 +6 -0
  311. 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)