passagemath-schemes 10.8.1a4__cp314-cp314t-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) 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.8.1a4.dist-info/METADATA +203 -0
  7. passagemath_schemes-10.8.1a4.dist-info/METADATA.bak +204 -0
  8. passagemath_schemes-10.8.1a4.dist-info/RECORD +312 -0
  9. passagemath_schemes-10.8.1a4.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.8.1a4.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 +9556 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2578 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +727 -0
  29. sage/lfunctions/pari.py +971 -0
  30. sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5132 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +414 -0
  34. sage/modular/abvar/abvar_newform.py +246 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +187 -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 +721 -0
  40. sage/modular/abvar/homspace.py +989 -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 +741 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1406 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +361 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +659 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1491 -0
  57. sage/modular/arithgroup/congroup_generic.py +630 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +266 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1067 -0
  61. sage/modular/arithgroup/tests.py +425 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3736 -0
  64. sage/modular/btquotients/pautomorphicform.py +2564 -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 +1107 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +571 -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 +1076 -0
  77. sage/modular/hecke/algebra.py +725 -0
  78. sage/modular/hecke/all.py +19 -0
  79. sage/modular/hecke/ambient_module.py +994 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +302 -0
  82. sage/modular/hecke/hecke_operator.py +736 -0
  83. sage/modular/hecke/homspace.py +185 -0
  84. sage/modular/hecke/module.py +1744 -0
  85. sage/modular/hecke/morphism.py +139 -0
  86. sage/modular/hecke/submodule.py +970 -0
  87. sage/modular/hypergeometric_misc.cpython-314t-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 +2020 -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 +1070 -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 +817 -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 +120 -0
  101. sage/modular/modform/ambient_g1.py +199 -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 +487 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4105 -0
  108. sage/modular/modform/half_integral.py +154 -0
  109. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  110. sage/modular/modform/j_invariant.py +47 -0
  111. sage/modular/modform/l_series_gross_zagier.py +127 -0
  112. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314t-darwin.so +0 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  114. sage/modular/modform/notes.py +45 -0
  115. sage/modular/modform/numerical.py +514 -0
  116. sage/modular/modform/periods.py +14 -0
  117. sage/modular/modform/ring.py +1257 -0
  118. sage/modular/modform/space.py +1859 -0
  119. sage/modular/modform/submodule.py +118 -0
  120. sage/modular/modform/tests.py +64 -0
  121. sage/modular/modform/theta.py +110 -0
  122. sage/modular/modform/vm_basis.py +380 -0
  123. sage/modular/modform/weight1.py +221 -0
  124. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  125. sage/modular/modform_hecketriangle/abstract_space.py +2527 -0
  126. sage/modular/modform_hecketriangle/all.py +30 -0
  127. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  128. sage/modular/modform_hecketriangle/constructor.py +416 -0
  129. sage/modular/modform_hecketriangle/element.py +351 -0
  130. sage/modular/modform_hecketriangle/functors.py +752 -0
  131. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  132. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  133. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3349 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1426 -0
  135. sage/modular/modform_hecketriangle/readme.py +1214 -0
  136. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  137. sage/modular/modform_hecketriangle/space.py +1037 -0
  138. sage/modular/modform_hecketriangle/subspace.py +423 -0
  139. sage/modular/modsym/all.py +17 -0
  140. sage/modular/modsym/ambient.py +3844 -0
  141. sage/modular/modsym/boundary.py +1420 -0
  142. sage/modular/modsym/element.py +336 -0
  143. sage/modular/modsym/g1list.py +178 -0
  144. sage/modular/modsym/ghlist.py +182 -0
  145. sage/modular/modsym/hecke_operator.py +73 -0
  146. sage/modular/modsym/manin_symbol.cpython-314t-darwin.so +0 -0
  147. sage/modular/modsym/manin_symbol.pxd +5 -0
  148. sage/modular/modsym/manin_symbol.pyx +497 -0
  149. sage/modular/modsym/manin_symbol_list.py +1291 -0
  150. sage/modular/modsym/modsym.py +400 -0
  151. sage/modular/modsym/modular_symbols.py +384 -0
  152. sage/modular/modsym/p1list_nf.py +1241 -0
  153. sage/modular/modsym/relation_matrix.py +591 -0
  154. sage/modular/modsym/relation_matrix_pyx.cpython-314t-darwin.so +0 -0
  155. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  156. sage/modular/modsym/space.py +2468 -0
  157. sage/modular/modsym/subspace.py +455 -0
  158. sage/modular/modsym/tests.py +376 -0
  159. sage/modular/multiple_zeta.py +2635 -0
  160. sage/modular/multiple_zeta_F_algebra.py +789 -0
  161. sage/modular/overconvergent/all.py +6 -0
  162. sage/modular/overconvergent/genus0.py +1879 -0
  163. sage/modular/overconvergent/hecke_series.py +1187 -0
  164. sage/modular/overconvergent/weightspace.py +776 -0
  165. sage/modular/pollack_stevens/all.py +4 -0
  166. sage/modular/pollack_stevens/distributions.py +874 -0
  167. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  168. sage/modular/pollack_stevens/manin_map.py +856 -0
  169. sage/modular/pollack_stevens/modsym.py +1590 -0
  170. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  171. sage/modular/pollack_stevens/sigma0.py +534 -0
  172. sage/modular/pollack_stevens/space.py +1078 -0
  173. sage/modular/quasimodform/all.py +3 -0
  174. sage/modular/quasimodform/element.py +846 -0
  175. sage/modular/quasimodform/ring.py +826 -0
  176. sage/modular/quatalg/all.py +3 -0
  177. sage/modular/quatalg/brandt.py +1642 -0
  178. sage/modular/ssmod/all.py +8 -0
  179. sage/modular/ssmod/ssmod.py +827 -0
  180. sage/rings/all__sagemath_schemes.py +1 -0
  181. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/binary_form_reduce.py +585 -0
  183. sage/schemes/all.py +41 -0
  184. sage/schemes/berkovich/all.py +6 -0
  185. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  186. sage/schemes/berkovich/berkovich_space.py +700 -0
  187. sage/schemes/curves/affine_curve.py +2924 -0
  188. sage/schemes/curves/all.py +33 -0
  189. sage/schemes/curves/closed_point.py +434 -0
  190. sage/schemes/curves/constructor.py +397 -0
  191. sage/schemes/curves/curve.py +542 -0
  192. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  193. sage/schemes/curves/point.py +463 -0
  194. sage/schemes/curves/projective_curve.py +3203 -0
  195. sage/schemes/curves/weighted_projective_curve.py +106 -0
  196. sage/schemes/curves/zariski_vankampen.py +1931 -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 +991 -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 +1103 -0
  208. sage/schemes/elliptic_curves/constructor.py +1530 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3971 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +457 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2837 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3249 -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 +4944 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7184 -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 +1663 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7328 -0
  229. sage/schemes/elliptic_curves/height.py +2108 -0
  230. sage/schemes/elliptic_curves/hom.py +1788 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +1084 -0
  232. sage/schemes/elliptic_curves/hom_fractional.py +544 -0
  233. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  234. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  235. sage/schemes/elliptic_curves/hom_sum.py +681 -0
  236. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  237. sage/schemes/elliptic_curves/homset.py +271 -0
  238. sage/schemes/elliptic_curves/isogeny_class.py +1523 -0
  239. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  240. sage/schemes/elliptic_curves/jacobian.py +247 -0
  241. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  242. sage/schemes/elliptic_curves/kraus.py +1014 -0
  243. sage/schemes/elliptic_curves/lseries_ell.py +915 -0
  244. sage/schemes/elliptic_curves/mod5family.py +105 -0
  245. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.cpython-314t-darwin.so +0 -0
  247. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  248. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  249. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  250. sage/schemes/elliptic_curves/padics.py +1816 -0
  251. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.cpython-314t-darwin.so +0 -0
  253. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  254. sage/schemes/elliptic_curves/saturation.py +716 -0
  255. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  256. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  257. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  258. sage/schemes/hyperelliptic_curves/all.py +6 -0
  259. sage/schemes/hyperelliptic_curves/constructor.py +369 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1948 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +936 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  265. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +312 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_generic.py +437 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +878 -0
  271. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  272. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  273. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3863 -0
  274. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  275. sage/schemes/jacobians/all.py +2 -0
  276. sage/schemes/overview.py +161 -0
  277. sage/schemes/plane_conics/all.py +22 -0
  278. sage/schemes/plane_conics/con_field.py +1296 -0
  279. sage/schemes/plane_conics/con_finite_field.py +158 -0
  280. sage/schemes/plane_conics/con_number_field.py +456 -0
  281. sage/schemes/plane_conics/con_rational_field.py +406 -0
  282. sage/schemes/plane_conics/con_rational_function_field.py +581 -0
  283. sage/schemes/plane_conics/constructor.py +249 -0
  284. sage/schemes/plane_quartics/all.py +2 -0
  285. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  286. sage/schemes/plane_quartics/quartic_generic.py +53 -0
  287. sage/schemes/riemann_surfaces/all.py +1 -0
  288. sage/schemes/riemann_surfaces/riemann_surface.py +4177 -0
  289. sage_wheels/share/cremona/cremona_mini.db +0 -0
  290. sage_wheels/share/ellcurves/rank0 +30427 -0
  291. sage_wheels/share/ellcurves/rank1 +31871 -0
  292. sage_wheels/share/ellcurves/rank10 +6 -0
  293. sage_wheels/share/ellcurves/rank11 +6 -0
  294. sage_wheels/share/ellcurves/rank12 +1 -0
  295. sage_wheels/share/ellcurves/rank14 +1 -0
  296. sage_wheels/share/ellcurves/rank15 +1 -0
  297. sage_wheels/share/ellcurves/rank17 +1 -0
  298. sage_wheels/share/ellcurves/rank19 +1 -0
  299. sage_wheels/share/ellcurves/rank2 +2388 -0
  300. sage_wheels/share/ellcurves/rank20 +1 -0
  301. sage_wheels/share/ellcurves/rank21 +1 -0
  302. sage_wheels/share/ellcurves/rank22 +1 -0
  303. sage_wheels/share/ellcurves/rank23 +1 -0
  304. sage_wheels/share/ellcurves/rank24 +1 -0
  305. sage_wheels/share/ellcurves/rank28 +1 -0
  306. sage_wheels/share/ellcurves/rank3 +836 -0
  307. sage_wheels/share/ellcurves/rank4 +10 -0
  308. sage_wheels/share/ellcurves/rank5 +5 -0
  309. sage_wheels/share/ellcurves/rank6 +5 -0
  310. sage_wheels/share/ellcurves/rank7 +5 -0
  311. sage_wheels/share/ellcurves/rank8 +6 -0
  312. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,2527 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.combinat sage.graphs
3
+ r"""
4
+ 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
+ from sage.matrix.constructor import matrix
19
+ from sage.misc.cachefunc import cached_method
20
+ from sage.misc.lazy_import import lazy_import
21
+ from sage.modules.free_module_element import FreeModuleElement
22
+ from sage.modules.free_module_element import vector
23
+ from sage.rings.infinity import infinity
24
+ from sage.rings.integer import Integer
25
+ from sage.rings.integer_ring import ZZ
26
+ from sage.rings.laurent_series_ring import LaurentSeriesRing
27
+ from sage.rings.polynomial.polynomial_ring import PolynomialRing_generic
28
+ from sage.rings.power_series_ring import PowerSeriesRing_generic
29
+ from sage.rings.rational_field import QQ
30
+ from sage.structure.element import parent
31
+
32
+ from .abstract_ring import FormsRing_abstract
33
+
34
+ lazy_import('sage.rings.imaginary_unit', 'I')
35
+ lazy_import('sage.rings.lazy_series_ring', ('LazyLaurentSeriesRing', 'LazyPowerSeriesRing'))
36
+ lazy_import('sage.rings.qqbar', 'QQbar')
37
+
38
+
39
+ class FormsSpace_abstract(FormsRing_abstract):
40
+ r"""
41
+ Abstract (Hecke) forms space.
42
+
43
+ This should never be called directly. Instead one should
44
+ instantiate one of the derived classes of this class.
45
+ """
46
+
47
+ from .element import FormsElement
48
+ Element = FormsElement
49
+
50
+ def __init__(self, group, base_ring, k, ep, n):
51
+ r"""
52
+ Abstract (Hecke) forms space.
53
+
54
+ INPUT:
55
+
56
+ - ``group`` -- the Hecke triangle group (default: ``HeckeTriangleGroup(3)``)
57
+
58
+ - ``k`` -- the weight (default: `0`)
59
+
60
+ - ``ep`` -- the epsilon (default: ``None``); if ``None``, then `k(n-2)`
61
+ has to be divisible by `2` and ``ep=(-1)^(k*(n-2)/2)`` is used
62
+
63
+ - ``base_ring`` -- the base_ring (default: `\Z`)
64
+
65
+ OUTPUT: the corresponding abstract (Hecke) forms space
66
+
67
+ EXAMPLES::
68
+
69
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
70
+ sage: MF = ModularForms(n=5, base_ring=ZZ, k=6, ep=-1)
71
+ sage: MF
72
+ ModularForms(n=5, k=6, ep=-1) over Integer Ring
73
+ sage: MF.group()
74
+ Hecke triangle group for n = 5
75
+ sage: MF.base_ring()
76
+ Integer Ring
77
+ sage: MF.weight()
78
+ 6
79
+ sage: MF.ep()
80
+ -1
81
+ sage: MF.has_reduce_hom()
82
+ True
83
+ sage: MF.is_homogeneous()
84
+ True
85
+ """
86
+ # from space import canonical_parameters
87
+ # (group, base_ring, k, ep, n) = canonical_parameters(group, base_ring, k, ep, n)
88
+
89
+ super().__init__(group=group, base_ring=base_ring, red_hom=True, n=n)
90
+ # self.register_embedding(self.hom(lambda f: f.parent().graded_ring()(f), codomain=self.graded_ring()))
91
+
92
+ self._weight = k
93
+ self._ep = ep
94
+ (self._l1, self._l2) = self.weight_parameters()
95
+ self._module = None
96
+ self._ambient_space = self
97
+
98
+ def _repr_(self):
99
+ r"""
100
+ Return the string representation of ``self``.
101
+
102
+ EXAMPLES::
103
+
104
+ sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
105
+ sage: QuasiModularForms(n=4, k=2, ep=-1)
106
+ QuasiModularForms(n=4, k=2, ep=-1) over Integer Ring
107
+ """
108
+
109
+ return "{}Forms(n={}, k={}, ep={}) over {}".format(self._analytic_type.analytic_space_name(), self._group.n(), self._weight, self._ep, self._base_ring)
110
+
111
+ def _latex_(self):
112
+ r"""
113
+ Return the LaTeX representation of ``self``.
114
+
115
+ EXAMPLES::
116
+
117
+ sage: from sage.modular.modform_hecketriangle.space import QuasiWeakModularForms
118
+ sage: latex(QuasiWeakModularForms())
119
+ QM^!_{ n=3 }(0,\ 1)(\Bold{Z})
120
+ """
121
+
122
+ from sage.misc.latex import latex
123
+ return r"{}_{{ n={} }}({},\ {})({})".format(self._analytic_type.latex_space_name(), self._group.n(), self._weight, self._ep, latex(self._base_ring))
124
+
125
+ def _element_constructor_(self, el):
126
+ r"""
127
+ Return ``el`` coerced into this forms space.
128
+
129
+ EXAMPLES::
130
+
131
+ sage: from sage.modular.modform_hecketriangle.graded_ring import MeromorphicModularFormsRing
132
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms, QuasiWeakModularForms
133
+ sage: MF = ModularForms(k=12, ep=1)
134
+ sage: (x,y,z,d) = MF.pol_ring().gens()
135
+
136
+ sage: Delta = MeromorphicModularFormsRing().Delta()
137
+ sage: Delta.parent()
138
+ MeromorphicModularFormsRing(n=3) over Integer Ring
139
+ sage: MF(Delta)
140
+ q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5)
141
+ sage: MF(Delta).parent() == MF
142
+ True
143
+
144
+ sage: E2 = MF.E2()
145
+ sage: e2 = QuasiWeakModularForms(n=infinity, k=2, ep=-1)(E2)
146
+ sage: e2
147
+ 1 - 24*q^2 - 72*q^4 + O(q^5)
148
+ sage: e2.parent()
149
+ QuasiWeakModularForms(n=+Infinity, k=2, ep=-1) over Integer Ring
150
+ sage: e2.as_ring_element()
151
+ (-f_i + 3*E2)/2
152
+ sage: MF(x^3)
153
+ 1 + 720*q + 179280*q^2 + 16954560*q^3 + 396974160*q^4 + O(q^5)
154
+ sage: MF(x^3).parent() == MF
155
+ True
156
+
157
+ sage: qexp = Delta.q_expansion(prec=2)
158
+ sage: qexp
159
+ q + O(q^2)
160
+ sage: qexp.parent()
161
+ Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
162
+ sage: MF(qexp)
163
+ q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5)
164
+ sage: MF(qexp) == MF(Delta)
165
+ True
166
+
167
+ sage: QF = QuasiWeakModularForms(n=8, k=10/3, ep=-1)
168
+ sage: QF.default_prec(2)
169
+ sage: el2 = QF.quasi_part_gens(min_exp=-1)[4]
170
+ sage: el2.reduced_parent()
171
+ QuasiWeakModularForms(n=8, k=10/3, ep=-1) over Integer Ring
172
+ sage: prec = QF.required_laurent_prec(min_exp=-1)
173
+ sage: qexp2 = el2.q_expansion(prec=prec)
174
+ sage: qexp2
175
+ q^-1 - 19/(64*d) - 7497/(262144*d^2)*q + 15889/(8388608*d^3)*q^2 + 543834047/(1649267441664*d^4)*q^3 + 711869853/(43980465111040*d^5)*q^4 + O(q^5)
176
+ sage: qexp2.parent()
177
+ Laurent Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
178
+ sage: QF(qexp2)
179
+ q^-1 - 19/(64*d) - 7497/(262144*d^2)*q + O(q^2)
180
+ sage: QF(qexp2).reduced_parent()
181
+ QuasiWeakModularForms(n=8, k=10/3, ep=-1) over Integer Ring
182
+ sage: QF(qexp2) == el2
183
+ True
184
+
185
+ sage: QF = QuasiWeakModularForms(n=infinity, k=2, ep=-1)
186
+ sage: el3 = QF.f_i() + QF.f_i()^3/QF.E4()
187
+ sage: prec = QF.required_laurent_prec(order_1=-1)
188
+ sage: qexp3 = el3.q_expansion(prec=prec)
189
+ sage: qexp3
190
+ 2 - 7/(4*d)*q + 195/(256*d^2)*q^2 - 903/(4096*d^3)*q^3 + 41987/(1048576*d^4)*q^4 - 181269/(33554432*d^5)*q^5 + O(q^6)
191
+ sage: QF.construct_quasi_form(qexp3, check=False) == el3
192
+ False
193
+ sage: QF.construct_quasi_form(qexp3, order_1=-1) == el3
194
+ True
195
+
196
+ sage: MF([0,1]) == MF(Delta)
197
+ True
198
+ sage: MF([1,0]) == MF(x^3) - 720*MF(Delta)
199
+ True
200
+
201
+ sage: vec = MF(Delta).coordinate_vector()
202
+ sage: vec
203
+ (0, 1)
204
+ sage: vec.parent()
205
+ Vector space of dimension 2 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
206
+ sage: vec in MF.module()
207
+ True
208
+ sage: MF(vec) == MF(Delta)
209
+ True
210
+
211
+ sage: subspace = MF.subspace([MF(Delta)])
212
+ sage: subspace
213
+ Subspace of dimension 1 of ModularForms(n=3, k=12, ep=1) over Integer Ring
214
+ sage: subspace(MF(Delta)) == subspace(d*(x^3-y^2)) == subspace(qexp) == subspace([0,1]) == subspace(vec) == subspace.gen()
215
+ True
216
+ sage: subspace(MF(Delta)).parent() == subspace(d*(x^3-y^2)).parent() == subspace(qexp).parent() == subspace([0,1]).parent() == subspace(vec).parent()
217
+ True
218
+ sage: subspace([1]) == subspace.gen()
219
+ True
220
+ sage: ssvec = subspace(vec).coordinate_vector()
221
+ sage: ssvec
222
+ (1)
223
+ sage: ssvec.parent()
224
+ Vector space of dimension 1 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
225
+ sage: ambvec = subspace(vec).ambient_coordinate_vector()
226
+ sage: ambvec
227
+ (0, 1)
228
+ sage: ambvec.parent()
229
+ Vector space of degree 2 and dimension 1 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
230
+ Basis matrix:
231
+ [0 1]
232
+ sage: subspace(ambvec) == subspace(vec) and subspace(ambvec).parent() == subspace(vec).parent()
233
+ True
234
+ """
235
+
236
+ from .graded_ring_element import FormsRingElement
237
+ if isinstance(el, FormsRingElement):
238
+ if (self.hecke_n() == infinity and el.hecke_n() == ZZ(3)):
239
+ el_f = el._reduce_d()._rat
240
+ (x,y,z,d) = self.pol_ring().gens()
241
+
242
+ num_sub = el_f.numerator().subs( x=(y**2 + 3*x)/ZZ(4), y=(9*x*y - y**3)/ZZ(8), z=(3*z - y)/ZZ(2))
243
+ denom_sub = el_f.denominator().subs( x=(y**2 + 3*x)/ZZ(4), y=(9*x*y - y**3)/ZZ(8), z=(3*z - y)/ZZ(2))
244
+ new_num = num_sub.numerator()*denom_sub.denominator()
245
+ new_denom = denom_sub.numerator()*num_sub.denominator()
246
+
247
+ el = self._rat_field(new_num) / self._rat_field(new_denom)
248
+ elif self.group() == el.group():
249
+ el = el._rat
250
+ else:
251
+ raise ValueError("{} has group {} != {}".format(el, el.group(), self.group()))
252
+ return self.element_class(self, el)
253
+ # This assumes that the series corresponds to a _weakly
254
+ # holomorphic_ (quasi) form. It also assumes that the form is
255
+ # holomorphic at -1 for n=infinity (this assumption however
256
+ # can be changed in construct_form
257
+ # resp. construct_quasi_form))
258
+ P = parent(el)
259
+ if isinstance(P, (LaurentSeriesRing, PowerSeriesRing_generic,
260
+ LazyLaurentSeriesRing, LazyPowerSeriesRing)):
261
+ if self.is_modular():
262
+ return self.construct_form(el)
263
+ else:
264
+ return self.construct_quasi_form(el)
265
+ if isinstance(el, FreeModuleElement) and (self.module() is P or self.ambient_module() is P):
266
+ return self.element_from_ambient_coordinates(el)
267
+ if not self.is_ambient() and isinstance(el, (list, tuple, FreeModuleElement)) and len(el) == self.rank():
268
+ try:
269
+ return self.element_from_coordinates(el)
270
+ except (ArithmeticError, TypeError):
271
+ pass
272
+ if self.ambient_module() and self.ambient_module().has_coerce_map_from(P):
273
+ return self.element_from_ambient_coordinates(self.ambient_module()(el))
274
+ if isinstance(el, (list, tuple)) and len(el) == self.degree():
275
+ try:
276
+ return self.element_from_ambient_coordinates(el)
277
+ except (ArithmeticError, TypeError):
278
+ pass
279
+
280
+ return self.element_class(self, el)
281
+
282
+ def _coerce_map_from_(self, S):
283
+ r"""
284
+ Return whether or not there exists a coercion from ``S`` to ``self``.
285
+
286
+ EXAMPLES::
287
+
288
+ sage: from sage.modular.modform_hecketriangle.space import QuasiWeakModularForms, ModularForms, CuspForms, ZeroForm
289
+ sage: MF1 = QuasiWeakModularForms(n=4, base_ring=CC, k=0, ep=1)
290
+ sage: MF2 = ModularForms(n=4, k=24, ep=1)
291
+ sage: MF3 = ModularForms(n=4, k=24, ep=-1)
292
+ sage: MF4 = CuspForms(n=4, k=0, ep=1)
293
+ sage: MF5 = ZeroForm(n=4, k=10, ep=-1)
294
+ sage: MF6 = QuasiWeakModularForms(n=3, k=24, ep=1)
295
+ sage: MF7 = QuasiWeakModularForms(n=infinity, k=24, ep=1)
296
+ sage: subspace1 = MF3.subspace([MF3.gen(0), MF3.gen(1)])
297
+ sage: subspace2 = MF3.subspace([MF3.gen(2)])
298
+ sage: subspace3 = MF3.subspace([MF3.gen(0), MF3.gen(0)+MF3.gen(2)])
299
+
300
+ sage: MF2.has_coerce_map_from(MF3)
301
+ False
302
+ sage: MF1.has_coerce_map_from(MF4)
303
+ True
304
+ sage: MF4.has_coerce_map_from(MF5)
305
+ True
306
+ sage: MF4.has_coerce_map_from(ZZ)
307
+ False
308
+ sage: MF1.has_coerce_map_from(ZZ)
309
+ True
310
+ sage: MF7.has_coerce_map_from(MF6)
311
+ True
312
+ sage: MF7.has_coerce_map_from(MF2)
313
+ False
314
+ sage: MF3.has_coerce_map_from(subspace1)
315
+ True
316
+ sage: subspace1.has_coerce_map_from(MF3)
317
+ False
318
+ sage: subspace3.has_coerce_map_from(subspace1)
319
+ False
320
+ sage: subspace3.has_coerce_map_from(subspace2)
321
+ True
322
+ """
323
+ from .space import ZeroForm
324
+ from .subspace import SubSpaceForms
325
+ if isinstance(S, ZeroForm):
326
+ return True
327
+ if (isinstance(S, SubSpaceForms)
328
+ and isinstance(self, SubSpaceForms)):
329
+ if (self.ambient_space().has_coerce_map_from(S.ambient_space())):
330
+ S2 = S.change_ambient_space(self.ambient_space())
331
+ return self.module().has_coerce_map_from(S2.module())
332
+ else:
333
+ return False
334
+ elif (isinstance(S, FormsSpace_abstract)
335
+ and self.graded_ring().has_coerce_map_from(S.graded_ring())
336
+ and S.weight() == self._weight
337
+ and S.ep() == self._ep
338
+ and not isinstance(self, SubSpaceForms)):
339
+ return True
340
+ else:
341
+ return self.contains_coeff_ring() \
342
+ and self.coeff_ring().has_coerce_map_from(S)
343
+
344
+ # Since forms spaces are modules instead of rings
345
+ # we have to manually define one().
346
+ # one() allows to take the power 0 of an element
347
+ @cached_method
348
+ def one(self):
349
+ r"""
350
+ Return the one element from the corresponding space of constant forms.
351
+
352
+ .. NOTE:: The one element does not lie in ``self`` in general.
353
+
354
+ EXAMPLES::
355
+
356
+ sage: from sage.modular.modform_hecketriangle.space import CuspForms
357
+ sage: MF = CuspForms(k=12)
358
+ sage: MF.Delta()^0 == MF.one()
359
+ True
360
+ sage: (MF.Delta()^0).parent()
361
+ ModularForms(n=3, k=0, ep=1) over Integer Ring
362
+ """
363
+ return self.extend_type("holo", ring=True)(1).reduce()
364
+
365
+ def is_ambient(self) -> bool:
366
+ r"""
367
+ Return whether ``self`` is an ambient space.
368
+
369
+ EXAMPLES::
370
+
371
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
372
+ sage: MF = ModularForms(k=12)
373
+ sage: MF.is_ambient()
374
+ True
375
+ sage: MF.subspace([MF.gen(0)]).is_ambient()
376
+ False
377
+ """
378
+ return self._ambient_space == self
379
+
380
+ def ambient_space(self):
381
+ r"""
382
+ Return the ambient space of ``self``.
383
+
384
+ EXAMPLES::
385
+
386
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
387
+ sage: MF = ModularForms(k=12)
388
+ sage: MF.ambient_space()
389
+ ModularForms(n=3, k=12, ep=1) over Integer Ring
390
+ sage: MF.ambient_space() == MF
391
+ True
392
+ sage: subspace = MF.subspace([MF.gen(0)])
393
+ sage: subspace
394
+ Subspace of dimension 1 of ModularForms(n=3, k=12, ep=1) over Integer Ring
395
+ sage: subspace.ambient_space() == MF
396
+ True
397
+ """
398
+
399
+ return self._ambient_space
400
+
401
+ def module(self):
402
+ r"""
403
+ Return the module associated to ``self``.
404
+
405
+ EXAMPLES::
406
+
407
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
408
+ sage: MF = ModularForms(k=12)
409
+ sage: MF.module()
410
+ Vector space of dimension 2 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
411
+ sage: subspace = MF.subspace([MF.gen(0)])
412
+ sage: subspace.module()
413
+ Vector space of degree 2 and dimension 1 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
414
+ Basis matrix:
415
+ [1 0]
416
+ """
417
+
418
+ return self._module
419
+
420
+ def ambient_module(self):
421
+ r"""
422
+ Return the module associated to the ambient space of ``self``.
423
+
424
+ EXAMPLES::
425
+
426
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
427
+ sage: MF = ModularForms(k=12)
428
+ sage: MF.ambient_module()
429
+ Vector space of dimension 2 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
430
+ sage: MF.ambient_module() == MF.module()
431
+ True
432
+ sage: subspace = MF.subspace([MF.gen(0)])
433
+ sage: subspace.ambient_module() == MF.module()
434
+ True
435
+ """
436
+
437
+ return self._ambient_space._module
438
+
439
+ def subspace(self, basis):
440
+ r"""
441
+ Return the subspace of ``self`` generated by ``basis``.
442
+
443
+ EXAMPLES::
444
+
445
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
446
+ sage: MF = ModularForms(k=24)
447
+ sage: MF.dimension()
448
+ 3
449
+ sage: subspace = MF.subspace([MF.gen(0), MF.gen(1)])
450
+ sage: subspace
451
+ Subspace of dimension 2 of ModularForms(n=3, k=24, ep=1) over Integer Ring
452
+ """
453
+
454
+ from .subspace import SubSpaceForms
455
+ return SubSpaceForms(self, basis)
456
+
457
+ def change_ring(self, new_base_ring):
458
+ r"""
459
+ Return the same space as ``self`` but over a new base ring ``new_base_ring``.
460
+
461
+ EXAMPLES::
462
+
463
+ sage: from sage.modular.modform_hecketriangle.space import CuspForms
464
+ sage: CuspForms(n=5, k=24).change_ring(CC)
465
+ CuspForms(n=5, k=24, ep=1) over Complex Field with 53 bits of precision
466
+ """
467
+
468
+ return self.__class__.__base__(self.group(), new_base_ring, self.weight(), self.ep())
469
+
470
+ def construction(self):
471
+ r"""
472
+ Return a functor that constructs ``self`` (used by the coercion machinery).
473
+
474
+ EXAMPLES::
475
+
476
+ sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
477
+ sage: QuasiModularForms(n=4, k=2, ep=1, base_ring=CC).construction()
478
+ (QuasiModularFormsFunctor(n=4, k=2, ep=1),
479
+ BaseFacade(Complex Field with 53 bits of precision))
480
+
481
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
482
+ sage: MF=ModularForms(k=12)
483
+ sage: MF.subspace([MF.gen(1)]).construction()
484
+ (FormsSubSpaceFunctor with 1 generator for the ModularFormsFunctor(n=3, k=12, ep=1), BaseFacade(Integer Ring))
485
+ """
486
+
487
+ from .functors import FormsSubSpaceFunctor, FormsSpaceFunctor, BaseFacade
488
+ ambient_space_functor = FormsSpaceFunctor(self._analytic_type, self._group, self._weight, self._ep)
489
+
490
+ if (self.is_ambient()):
491
+ return (ambient_space_functor, BaseFacade(self._base_ring))
492
+ else:
493
+ return (FormsSubSpaceFunctor(ambient_space_functor, self._basis), BaseFacade(self._base_ring))
494
+
495
+ @cached_method
496
+ def weight(self):
497
+ r"""
498
+ Return the weight of (elements of) ``self``.
499
+
500
+ EXAMPLES::
501
+
502
+ sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
503
+ sage: QuasiModularForms(n=16, k=16/7, ep=-1).weight()
504
+ 16/7
505
+ """
506
+
507
+ return self._weight
508
+
509
+ @cached_method
510
+ def ep(self):
511
+ r"""
512
+ Return the multiplier of (elements of) ``self``.
513
+
514
+ EXAMPLES::
515
+
516
+ sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
517
+ sage: QuasiModularForms(n=16, k=16/7, ep=-1).ep()
518
+ -1
519
+ """
520
+
521
+ return self._ep
522
+
523
+ @cached_method
524
+ def contains_coeff_ring(self):
525
+ r"""
526
+ Return whether ``self`` contains its coefficient ring.
527
+
528
+ EXAMPLES::
529
+
530
+ sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
531
+ sage: QuasiModularForms(k=0, ep=1, n=8).contains_coeff_ring()
532
+ True
533
+ sage: QuasiModularForms(k=0, ep=-1, n=8).contains_coeff_ring()
534
+ False
535
+ """
536
+
537
+ return ((self.AT("holo") <= self._analytic_type) and (self.weight() == QQ(0)) and (self.ep() == ZZ(1)))
538
+
539
+ def element_from_coordinates(self, vec):
540
+ r"""
541
+ If ``self`` has an associated free module, then return the element of ``self``
542
+ corresponding to the given coordinate vector ``vec``. Otherwise raise an exception.
543
+
544
+ INPUT:
545
+
546
+ - ``vec`` -- a coordinate vector with respect to ``self.gens()``
547
+
548
+ OUTPUT: an element of ``self`` corresponding to the coordinate vector ``vec``
549
+
550
+ EXAMPLES::
551
+
552
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
553
+ sage: MF = ModularForms(k=24)
554
+ sage: MF.dimension()
555
+ 3
556
+ sage: el = MF.element_from_coordinates([1,1,1])
557
+ sage: el
558
+ 1 + q + q^2 + 52611612*q^3 + 39019413208*q^4 + O(q^5)
559
+ sage: el == MF.gen(0) + MF.gen(1) + MF.gen(2)
560
+ True
561
+ sage: el.parent() == MF
562
+ True
563
+
564
+ sage: subspace = MF.subspace([MF.gen(0), MF.gen(1)])
565
+ sage: el = subspace.element_from_coordinates([1,1])
566
+ sage: el
567
+ 1 + q + 52611660*q^3 + 39019412128*q^4 + O(q^5)
568
+ sage: el == subspace.gen(0) + subspace.gen(1)
569
+ True
570
+ sage: el.parent() == subspace
571
+ True
572
+ """
573
+ if not self.module():
574
+ raise ValueError(f"no free module defined for {self}")
575
+ basis = self.gens()
576
+ assert len(basis) == len(vec)
577
+ # vec = self.module()(self.module().linear_combination_of_basis(vec))
578
+ # this also handles the trivial case (dimension 0)
579
+ return self(sum([vec[k] * basis[k] for k in range(len(vec))]))
580
+
581
+ def element_from_ambient_coordinates(self, vec):
582
+ r"""
583
+ If ``self`` has an associated free module, then return the element of ``self``
584
+ corresponding to the given ``vec``. Otherwise raise an exception.
585
+
586
+ INPUT:
587
+
588
+ - ``vec`` -- an element of ``self.module()`` or ``self.ambient_module()``
589
+
590
+ OUTPUT: an element of ``self`` corresponding to ``vec``
591
+
592
+ EXAMPLES::
593
+
594
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
595
+ sage: MF = ModularForms(k=24)
596
+ sage: MF.dimension()
597
+ 3
598
+ sage: el = MF.element_from_ambient_coordinates([1,1,1])
599
+ sage: el == MF.element_from_coordinates([1,1,1])
600
+ True
601
+ sage: el.parent() == MF
602
+ True
603
+
604
+ sage: subspace = MF.subspace([MF.gen(0), MF.gen(1)])
605
+ sage: el = subspace.element_from_ambient_coordinates([1,1,0])
606
+ sage: el
607
+ 1 + q + 52611660*q^3 + 39019412128*q^4 + O(q^5)
608
+ sage: el.parent() == subspace
609
+ True
610
+ """
611
+
612
+ return self(self.ambient_space().element_from_coordinates(vec))
613
+
614
+ def homogeneous_part(self, k, ep):
615
+ r"""
616
+ Since ``self`` already is a homogeneous component return ``self``
617
+ unless the degree differs in which case a :exc:`ValueError` is raised.
618
+
619
+ EXAMPLES::
620
+
621
+ sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms
622
+ sage: MF = QuasiMeromorphicModularForms(n=6, k=4)
623
+ sage: MF == MF.homogeneous_part(4,1)
624
+ True
625
+ sage: MF.homogeneous_part(5,1)
626
+ Traceback (most recent call last):
627
+ ...
628
+ ValueError: QuasiMeromorphicModularForms(n=6, k=4, ep=1) over Integer Ring already is homogeneous with degree (4, 1) != (5, 1)!
629
+ """
630
+
631
+ if (k == self._weight and ep == self._ep):
632
+ return self
633
+ else:
634
+ raise ValueError("{} already is homogeneous with degree ({}, {}) != ({}, {})!".format(self, self._weight, self._ep, k, ep))
635
+
636
+ def weight_parameters(self):
637
+ r"""
638
+ Check whether ``self`` has a valid weight and multiplier.
639
+
640
+ If not then an exception is raised. Otherwise the two weight
641
+ parameters corresponding to the weight and multiplier of ``self``
642
+ are returned.
643
+
644
+ The weight parameters are e.g. used to calculate dimensions
645
+ or precisions of Fourier expansion.
646
+
647
+ EXAMPLES::
648
+
649
+ sage: from sage.modular.modform_hecketriangle.space import MeromorphicModularForms
650
+ sage: MF = MeromorphicModularForms(n=18, k=-7, ep=-1)
651
+ sage: MF.weight_parameters()
652
+ (-3, 17)
653
+ sage: (MF._l1, MF._l2) == MF.weight_parameters()
654
+ True
655
+ sage: (k, ep) = (MF.weight(), MF.ep())
656
+ sage: n = MF.hecke_n()
657
+ sage: k == 4*(n*MF._l1 + MF._l2)/(n-2) + (1-ep)*n/(n-2)
658
+ True
659
+
660
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
661
+ sage: MF = ModularForms(n=5, k=12, ep=1)
662
+ sage: MF.weight_parameters()
663
+ (1, 4)
664
+ sage: (MF._l1, MF._l2) == MF.weight_parameters()
665
+ True
666
+ sage: (k, ep) = (MF.weight(), MF.ep())
667
+ sage: n = MF.hecke_n()
668
+ sage: k == 4*(n*MF._l1 + MF._l2)/(n-2) + (1-ep)*n/(n-2)
669
+ True
670
+ sage: MF.dimension() == MF._l1 + 1
671
+ True
672
+
673
+ sage: MF = ModularForms(n=infinity, k=8, ep=1)
674
+ sage: MF.weight_parameters()
675
+ (2, 0)
676
+ sage: MF.dimension() == MF._l1 + 1
677
+ True
678
+ """
679
+
680
+ n = self._group.n()
681
+ k = self._weight
682
+ ep = self._ep
683
+ if (n == infinity):
684
+ num = (k-(1-ep)) / ZZ(4)
685
+ else:
686
+ num = (k-(1-ep)*ZZ(n)/ZZ(n-2)) * ZZ(n-2) / ZZ(4)
687
+ if (num.is_integral()):
688
+ num = ZZ(num)
689
+ if (n == infinity):
690
+ # TODO: Figure out what to do in this case
691
+ # (l1 and l2 are no longer defined in an analog/unique way)
692
+ # l2 = num % ZZ(2)
693
+ # l1 = ((num-l2)/ZZ(2)).numerator()
694
+ # TODO: The correct generalization seems (l1,l2) = (0,num)
695
+ l2 = ZZ.zero()
696
+ l1 = num
697
+ else:
698
+ l2 = num % n
699
+ l1 = ((num-l2)/n).numerator()
700
+ else:
701
+ raise ValueError("Invalid or non-occurring weight k={}, ep={}!".format(k,ep))
702
+ return (l1, l2)
703
+
704
+ # TODO: this only makes sense for modular forms,
705
+ # resp. needs a big adjustment for quasi modular forms
706
+ def aut_factor(self, gamma, t):
707
+ r"""
708
+ The automorphy factor of ``self``.
709
+
710
+ INPUT:
711
+
712
+ - ``gamma`` -- an element of the group of ``self``
713
+
714
+ - ``t`` -- an element of the upper half plane
715
+
716
+ EXAMPLES::
717
+
718
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
719
+ sage: MF = ModularForms(n=8, k=4, ep=1)
720
+ sage: full_factor = lambda mat, t: (mat[1][0]*t+mat[1][1])**4
721
+ sage: T = MF.group().T()
722
+ sage: S = MF.group().S()
723
+ sage: i = AlgebraicField()(i)
724
+ sage: z = 1 + i/2
725
+
726
+ sage: MF.aut_factor(S, z)
727
+ 3/2*I - 7/16
728
+ sage: MF.aut_factor(-T^(-2), z)
729
+ 1
730
+ sage: MF.aut_factor(MF.group().V(6), z)
731
+ 173.2640595631...? + 343.8133289126...?*I
732
+ sage: MF.aut_factor(S, z) == full_factor(S, z)
733
+ True
734
+ sage: MF.aut_factor(T, z) == full_factor(T, z)
735
+ True
736
+ sage: MF.aut_factor(MF.group().V(6), z) == full_factor(MF.group().V(6), z)
737
+ True
738
+
739
+ sage: MF = ModularForms(n=7, k=14/5, ep=-1)
740
+ sage: T = MF.group().T()
741
+ sage: S = MF.group().S()
742
+
743
+ sage: MF.aut_factor(S, z)
744
+ 1.3655215324256...? + 0.056805991182877...?*I
745
+ sage: MF.aut_factor(-T^(-2), z)
746
+ 1
747
+ sage: MF.aut_factor(S, z) == MF.ep() * (z/i)^MF.weight()
748
+ True
749
+ sage: MF.aut_factor(MF.group().V(6), z)
750
+ 13.23058830577...? + 15.71786610686...?*I
751
+ """
752
+
753
+ if (gamma.is_translation()):
754
+ return ZZ(1)
755
+ elif (gamma.is_reflection()):
756
+ return self._ep * (t/QQbar(I))**self._weight
757
+ else:
758
+ L = list(gamma.word_S_T()[0])
759
+ aut_f = ZZ(1)
760
+ while (len(L) > 0):
761
+ M = L.pop(-1)
762
+ aut_f *= self.aut_factor(M, t)
763
+ t = M.acton(t)
764
+ return aut_f
765
+
766
+ @cached_method
767
+ def F_simple(self, order_1=ZZ.zero()):
768
+ r"""
769
+ Return a (the most) simple normalized element of ``self``
770
+ corresponding to the weight parameters ``l1=self._l1`` and
771
+ ``l2=self._l2``. If the element does not lie in ``self`` the
772
+ type of its parent is extended accordingly.
773
+
774
+ The main part of the element is given by the ``(l1 - order_1)``-th power
775
+ of ``f_inf``, up to a small holomorphic correction factor.
776
+
777
+ INPUT:
778
+
779
+ - ``order_1`` -- an integer (default: 0) denoting the desired order at
780
+ ``-1`` in the case ``n = infinity``. If ``n != infinity`` the
781
+ parameter is ignored.
782
+
783
+ EXAMPLES::
784
+
785
+ sage: from sage.modular.modform_hecketriangle.space import WeakModularForms
786
+ sage: MF = WeakModularForms(n=18, k=-7, ep=-1)
787
+ sage: MF.disp_prec(1)
788
+ sage: MF.F_simple()
789
+ q^-3 + 16/(81*d)*q^-2 - 4775/(104976*d^2)*q^-1 - 14300/(531441*d^3) + O(q)
790
+ sage: MF.F_simple() == MF.f_inf()^MF._l1 * MF.f_rho()^MF._l2 * MF.f_i()
791
+ True
792
+
793
+ sage: from sage.modular.modform_hecketriangle.space import CuspForms, ModularForms
794
+ sage: MF = CuspForms(n=5, k=2, ep=-1)
795
+ sage: MF._l1
796
+ -1
797
+ sage: MF.F_simple().parent()
798
+ WeakModularForms(n=5, k=2, ep=-1) over Integer Ring
799
+
800
+ sage: MF = ModularForms(n=infinity, k=8, ep=1)
801
+ sage: MF.F_simple().reduced_parent()
802
+ ModularForms(n=+Infinity, k=8, ep=1) over Integer Ring
803
+ sage: MF.F_simple()
804
+ q^2 - 16*q^3 + 120*q^4 + O(q^5)
805
+ sage: MF.F_simple(order_1=2)
806
+ 1 + 32*q + 480*q^2 + 4480*q^3 + 29152*q^4 + O(q^5)
807
+ """
808
+
809
+ (x,y,z,d) = self.rat_field().gens()
810
+ n = self.hecke_n()
811
+
812
+ if (n == infinity):
813
+ order_1 = ZZ(order_1)
814
+ order_inf = self._l1 - order_1
815
+
816
+ finf_pol = d*(x - y**2)
817
+ rat = finf_pol**order_inf * x**order_1 * y**(ZZ(1-self._ep)/ZZ(2))
818
+ else:
819
+ order_inf = self._l1
820
+ order_1 = order_inf
821
+
822
+ finf_pol = d*(x**n - y**2)
823
+ rat = finf_pol**self._l1 * x**self._l2 * y**(ZZ(1-self._ep)/ZZ(2))
824
+
825
+ if (order_inf > 0 and order_1 > 0):
826
+ new_space = self.extend_type("cusp")
827
+ elif (order_inf >= 0 and order_1 >= 0):
828
+ new_space = self.extend_type("holo")
829
+ else:
830
+ new_space = self.extend_type("weak")
831
+
832
+ return new_space(rat)
833
+
834
+ def Faber_pol(self, m, order_1=ZZ.zero(), fix_d=False, d_num_prec=None):
835
+ r"""
836
+ Return the ``m``-th Faber polynomial of ``self``.
837
+
838
+ Namely a polynomial ``P(q)`` such that ``P(J_inv)*F_simple(order_1)``
839
+ has a Fourier expansion of the form ``q^m + O(q^(order_inf + 1))``.
840
+ where ``order_inf = self._l1 - order_1`` and ``d^(order_inf - m)*P(q)``
841
+ is a monic polynomial of degree ``order_inf - m``.
842
+
843
+ If ``n=infinity`` a non-trivial order of ``-1`` can be specified through the
844
+ parameter ``order_1`` (default: 0). Otherwise it is ignored.
845
+
846
+ The Faber polynomials are e.g. used to construct a basis of weakly holomorphic
847
+ forms and to recover such forms from their initial Fourier coefficients.
848
+
849
+ INPUT:
850
+
851
+ - ``m`` -- an integer ``m <= order_inf = self._l1 - order_1``
852
+
853
+ - ``order_1`` -- the order at ``-1`` of F_simple (default: 0);
854
+ this parameter is ignored if ``n != infinity``
855
+
856
+ - ``fix_d`` -- if ``False`` (default) a formal parameter is used for
857
+ ``d``. If ``True`` then the numerical value of ``d`` is used (resp.
858
+ an exact value if the group is arithmetic). Otherwise the given
859
+ value is used for ``d``.
860
+
861
+ - ``d_num_prec`` -- the precision to be used if a numerical value for
862
+ ``d`` is substituted (default: ``None``), otherwise the default
863
+ numerical precision of ``self.parent()`` is used
864
+
865
+ OUTPUT: the corresponding Faber polynomial ``P(q)``
866
+
867
+ EXAMPLES::
868
+
869
+ sage: from sage.modular.modform_hecketriangle.space import WeakModularForms
870
+ sage: MF = WeakModularForms(n=5, k=62/3, ep=-1)
871
+ sage: MF.weight_parameters()
872
+ (2, 3)
873
+
874
+ sage: MF.Faber_pol(2)
875
+ 1
876
+ sage: MF.Faber_pol(1)
877
+ 1/d*q - 19/(100*d)
878
+ sage: MF.Faber_pol(0)
879
+ 1/d^2*q^2 - 117/(200*d^2)*q + 9113/(320000*d^2)
880
+ sage: MF.Faber_pol(-2)
881
+ 1/d^4*q^4 - 11/(8*d^4)*q^3 + 41013/(80000*d^4)*q^2 - 2251291/(48000000*d^4)*q + 1974089431/(4915200000000*d^4)
882
+ sage: (MF.Faber_pol(2)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1+2)
883
+ q^2 - 41/(200*d)*q^3 + O(q^4)
884
+ sage: (MF.Faber_pol(1)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1+1)
885
+ q + O(q^3)
886
+ sage: (MF.Faber_pol(0)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1+1)
887
+ 1 + O(q^3)
888
+ sage: (MF.Faber_pol(-2)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1+1)
889
+ q^-2 + O(q^3)
890
+
891
+ sage: MF.Faber_pol(2, fix_d=1)
892
+ 1
893
+ sage: MF.Faber_pol(1, fix_d=1)
894
+ q - 19/100
895
+ sage: MF.Faber_pol(-2, fix_d=1)
896
+ q^4 - 11/8*q^3 + 41013/80000*q^2 - 2251291/48000000*q + 1974089431/4915200000000
897
+ sage: (MF.Faber_pol(2, fix_d=1)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1+2, fix_d=1)
898
+ q^2 - 41/200*q^3 + O(q^4)
899
+ sage: (MF.Faber_pol(-2)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1+1, fix_d=1)
900
+ q^-2 + O(q^3)
901
+
902
+ sage: MF = WeakModularForms(n=4, k=-2, ep=1)
903
+ sage: MF.weight_parameters()
904
+ (-1, 3)
905
+
906
+ sage: MF.Faber_pol(-1)
907
+ 1
908
+ sage: MF.Faber_pol(-2, fix_d=True)
909
+ 256*q - 184
910
+ sage: MF.Faber_pol(-3, fix_d=True)
911
+ 65536*q^2 - 73728*q + 14364
912
+ sage: (MF.Faber_pol(-1, fix_d=True)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1+2, fix_d=True)
913
+ q^-1 + 80 + O(q)
914
+ sage: (MF.Faber_pol(-2, fix_d=True)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1+2, fix_d=True)
915
+ q^-2 + 400 + O(q)
916
+ sage: (MF.Faber_pol(-3)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1+2, fix_d=True)
917
+ q^-3 + 2240 + O(q)
918
+
919
+ sage: MF = WeakModularForms(n=infinity, k=14, ep=-1)
920
+ sage: MF.Faber_pol(3)
921
+ 1
922
+ sage: MF.Faber_pol(2)
923
+ 1/d*q + 3/(8*d)
924
+ sage: MF.Faber_pol(1)
925
+ 1/d^2*q^2 + 75/(1024*d^2)
926
+ sage: MF.Faber_pol(0)
927
+ 1/d^3*q^3 - 3/(8*d^3)*q^2 + 3/(512*d^3)*q + 41/(4096*d^3)
928
+ sage: MF.Faber_pol(-1)
929
+ 1/d^4*q^4 - 3/(4*d^4)*q^3 + 81/(1024*d^4)*q^2 + 9075/(8388608*d^4)
930
+ sage: (MF.Faber_pol(-1)(MF.J_inv())*MF.F_simple()).q_expansion(prec=MF._l1 + 1)
931
+ q^-1 + O(q^4)
932
+
933
+ sage: MF.Faber_pol(3, order_1=-1)
934
+ 1/d*q + 3/(4*d)
935
+ sage: MF.Faber_pol(1, order_1=2)
936
+ 1
937
+ sage: MF.Faber_pol(0, order_1=2)
938
+ 1/d*q - 3/(8*d)
939
+ sage: MF.Faber_pol(-1, order_1=2)
940
+ 1/d^2*q^2 - 3/(4*d^2)*q + 81/(1024*d^2)
941
+ sage: (MF.Faber_pol(-1, order_1=2)(MF.J_inv())*MF.F_simple(order_1=2)).q_expansion(prec=MF._l1 + 1)
942
+ q^-1 - 9075/(8388608*d^4)*q^3 + O(q^4)
943
+ """
944
+
945
+ m = ZZ(m)
946
+ if (self.hecke_n() == infinity):
947
+ order_1 = ZZ(order_1)
948
+ order_inf = self._l1 - order_1
949
+ else:
950
+ order_inf = self._l1
951
+ order_1 = order_inf
952
+
953
+ if (m > order_inf):
954
+ raise ValueError("Invalid basis index: m = {} > {} = order_inf!".format(m, order_inf))
955
+
956
+ prec = 2*order_inf - m + 1
957
+ d = self.get_d(fix_d=fix_d, d_num_prec=d_num_prec)
958
+ q = self.get_q(prec=prec, fix_d=fix_d, d_num_prec=d_num_prec)
959
+
960
+ simple_qexp = self.F_simple(order_1=order_1).q_expansion(prec=prec, fix_d=fix_d, d_num_prec=d_num_prec)
961
+ J_qexp = self.J_inv().q_expansion(prec=order_inf - m, fix_d=fix_d, d_num_prec=d_num_prec)
962
+
963
+ # The precision could be infinity, otherwise we could do this:
964
+ # assert temp_reminder.prec() == 1
965
+ temp_reminder = (1 / simple_qexp / q**(-m)).add_bigoh(1)
966
+
967
+ fab_pol = q.parent()([])
968
+ while (len(temp_reminder.coefficients()) > 0):
969
+ temp_coeff = temp_reminder.coefficients()[0]
970
+ temp_exp = -temp_reminder.exponents()[0]
971
+ fab_pol += temp_coeff * (q/d)**temp_exp
972
+
973
+ temp_reminder -= temp_coeff * (J_qexp/d)**temp_exp
974
+ # The first term is zero only up to numerical errors,
975
+ # so we manually have to remove it
976
+ if (not d.parent().is_exact()):
977
+ temp_reminder = temp_reminder.truncate_neg(-temp_exp+1)
978
+
979
+ return fab_pol.polynomial()
980
+
981
+ # very similar to Faber_pol: faber_pol(q)=Faber_pol(d*q)
982
+ def faber_pol(self, m, order_1=ZZ.zero(), fix_d=False, d_num_prec=None):
983
+ r"""
984
+ If ``n=infinity`` a non-trivial order of ``-1`` can be specified through the
985
+ parameter ``order_1`` (default: 0). Otherwise it is ignored.
986
+ Return the `m`-th Faber polynomial of ``self``
987
+ with a different normalization based on ``j_inv``
988
+ instead of ``J_inv``.
989
+
990
+ Namely a polynomial ``p(q)`` such that ``p(j_inv)*F_simple()``
991
+ has a Fourier expansion of the form ``q^m + O(q^(order_inf + 1))``.
992
+ where ``order_inf = self._l1 - order_1`` and ``p(q)`` is a
993
+ monic polynomial of degree ``order_inf - m``.
994
+
995
+ If ``n=infinity`` a non-trivial order of ``-1`` can be specified through the
996
+ parameter ``order_1`` (default: 0). Otherwise it is ignored.
997
+
998
+ The relation to ``Faber_pol`` is: ``faber_pol(q) = Faber_pol(d*q)``.
999
+
1000
+ INPUT:
1001
+
1002
+ - ``m`` -- integer; ``m <= self._l1 - order_1``
1003
+
1004
+ - ``order_1`` -- the order at ``-1`` of ``F_simple`` (default: 0);
1005
+ this parameter is ignored if ``n != infinity``
1006
+
1007
+ - ``fix_d`` -- if ``False`` (default) a formal parameter is used for
1008
+ ``d``. If ``True`` then the numerical value of ``d`` is used (resp.
1009
+ an exact value if the group is arithmetic). Otherwise the given value
1010
+ is used for ``d``.
1011
+
1012
+ - ``d_num_prec`` -- the precision to be used if a numerical value for
1013
+ ``d`` is substituted (default: ``None``), otherwise the default
1014
+ numerical precision of ``self.parent()`` is used
1015
+
1016
+ OUTPUT: the corresponding Faber polynomial ``p(q)``
1017
+
1018
+ EXAMPLES::
1019
+
1020
+ sage: from sage.modular.modform_hecketriangle.space import WeakModularForms
1021
+ sage: MF = WeakModularForms(n=5, k=62/3, ep=-1)
1022
+ sage: MF.weight_parameters()
1023
+ (2, 3)
1024
+
1025
+ sage: MF.faber_pol(2)
1026
+ 1
1027
+ sage: MF.faber_pol(1)
1028
+ q - 19/(100*d)
1029
+ sage: MF.faber_pol(0)
1030
+ q^2 - 117/(200*d)*q + 9113/(320000*d^2)
1031
+ sage: MF.faber_pol(-2)
1032
+ q^4 - 11/(8*d)*q^3 + 41013/(80000*d^2)*q^2 - 2251291/(48000000*d^3)*q + 1974089431/(4915200000000*d^4)
1033
+ sage: (MF.faber_pol(2)(MF.j_inv())*MF.F_simple()).q_expansion(prec=MF._l1+2)
1034
+ q^2 - 41/(200*d)*q^3 + O(q^4)
1035
+ sage: (MF.faber_pol(1)(MF.j_inv())*MF.F_simple()).q_expansion(prec=MF._l1+1)
1036
+ q + O(q^3)
1037
+ sage: (MF.faber_pol(0)(MF.j_inv())*MF.F_simple()).q_expansion(prec=MF._l1+1)
1038
+ 1 + O(q^3)
1039
+ sage: (MF.faber_pol(-2)(MF.j_inv())*MF.F_simple()).q_expansion(prec=MF._l1+1)
1040
+ q^-2 + O(q^3)
1041
+
1042
+ sage: MF = WeakModularForms(n=4, k=-2, ep=1)
1043
+ sage: MF.weight_parameters()
1044
+ (-1, 3)
1045
+
1046
+ sage: MF.faber_pol(-1)
1047
+ 1
1048
+ sage: MF.faber_pol(-2, fix_d=True)
1049
+ q - 184
1050
+ sage: MF.faber_pol(-3, fix_d=True)
1051
+ q^2 - 288*q + 14364
1052
+ sage: (MF.faber_pol(-1, fix_d=True)(MF.j_inv())*MF.F_simple()).q_expansion(prec=MF._l1+2, fix_d=True)
1053
+ q^-1 + 80 + O(q)
1054
+ sage: (MF.faber_pol(-2, fix_d=True)(MF.j_inv())*MF.F_simple()).q_expansion(prec=MF._l1+2, fix_d=True)
1055
+ q^-2 + 400 + O(q)
1056
+ sage: (MF.faber_pol(-3)(MF.j_inv())*MF.F_simple()).q_expansion(prec=MF._l1+2, fix_d=True)
1057
+ q^-3 + 2240 + O(q)
1058
+
1059
+ sage: MF = WeakModularForms(n=infinity, k=14, ep=-1)
1060
+ sage: MF.faber_pol(3)
1061
+ 1
1062
+ sage: MF.faber_pol(2)
1063
+ q + 3/(8*d)
1064
+ sage: MF.faber_pol(1)
1065
+ q^2 + 75/(1024*d^2)
1066
+ sage: MF.faber_pol(0)
1067
+ q^3 - 3/(8*d)*q^2 + 3/(512*d^2)*q + 41/(4096*d^3)
1068
+ sage: MF.faber_pol(-1)
1069
+ q^4 - 3/(4*d)*q^3 + 81/(1024*d^2)*q^2 + 9075/(8388608*d^4)
1070
+ sage: (MF.faber_pol(-1)(MF.j_inv())*MF.F_simple()).q_expansion(prec=MF._l1 + 1)
1071
+ q^-1 + O(q^4)
1072
+
1073
+ sage: MF.faber_pol(3, order_1=-1)
1074
+ q + 3/(4*d)
1075
+ sage: MF.faber_pol(1, order_1=2)
1076
+ 1
1077
+ sage: MF.faber_pol(0, order_1=2)
1078
+ q - 3/(8*d)
1079
+ sage: MF.faber_pol(-1, order_1=2)
1080
+ q^2 - 3/(4*d)*q + 81/(1024*d^2)
1081
+ sage: (MF.faber_pol(-1, order_1=2)(MF.j_inv())*MF.F_simple(order_1=2)).q_expansion(prec=MF._l1 + 1)
1082
+ q^-1 - 9075/(8388608*d^4)*q^3 + O(q^4)
1083
+ """
1084
+
1085
+ m = ZZ(m)
1086
+ if (self.hecke_n() == infinity):
1087
+ order_1 = ZZ(order_1)
1088
+ order_inf = self._l1 - order_1
1089
+ else:
1090
+ order_inf = self._l1
1091
+ order_1 = order_inf
1092
+
1093
+ if (m > order_inf):
1094
+ raise ValueError("Invalid basis index: m = {} > {} = order_inf!".format(m, order_inf))
1095
+
1096
+ prec = 2*order_inf - m + 1
1097
+ d = self.get_d(fix_d=fix_d, d_num_prec=d_num_prec)
1098
+ q = self.get_q(prec=prec, fix_d=fix_d, d_num_prec=d_num_prec)
1099
+
1100
+ simple_qexp = self.F_simple(order_1=order_1).q_expansion(prec=prec, fix_d=fix_d, d_num_prec=d_num_prec)
1101
+ j_qexp = self.j_inv().q_expansion(prec=order_inf - m, fix_d=fix_d, d_num_prec=d_num_prec)
1102
+
1103
+ # The precision could be infinity, otherwise we could do this:
1104
+ # assert temp_reminder.prec() == 1
1105
+ temp_reminder = (1 / simple_qexp / q**(-m)).add_bigoh(1)
1106
+
1107
+ fab_pol = q.parent()([])
1108
+ while (len(temp_reminder.coefficients()) > 0):
1109
+ temp_coeff = temp_reminder.coefficients()[0]
1110
+ temp_exp = -temp_reminder.exponents()[0]
1111
+ fab_pol += temp_coeff*q**temp_exp
1112
+
1113
+ temp_reminder -= temp_coeff*j_qexp**temp_exp
1114
+ # The first term is zero only up to numerical errors,
1115
+ # so we manually have to remove it
1116
+ if not d.parent().is_exact():
1117
+ temp_reminder = temp_reminder.truncate_neg(-temp_exp+1)
1118
+
1119
+ return fab_pol.polynomial()
1120
+
1121
+ def F_basis_pol(self, m, order_1=ZZ.zero()):
1122
+ r"""
1123
+ Return a polynomial corresponding to the basis element of
1124
+ the corresponding space of weakly holomorphic forms of
1125
+ the same degree as ``self``. The basis element is determined
1126
+ by the property that the Fourier expansion is of the form
1127
+ ``q^m + O(q^(order_inf + 1))``, where ``order_inf = self._l1 - order_1``.
1128
+
1129
+ If ``n=infinity`` a non-trivial order of ``-1`` can be specified through
1130
+ the parameter ``order_1`` (default: 0). Otherwise it is ignored.
1131
+
1132
+ INPUT:
1133
+
1134
+ - ``m`` -- integer; ``m <= self._l1``
1135
+
1136
+ - ``order_1`` -- the order at ``-1`` of ``F_simple`` (default: 0);
1137
+ this parameter is ignored if ``n != infinity``
1138
+
1139
+ OUTPUT:
1140
+
1141
+ A polynomial in ``x,y,z,d``, corresponding to ``f_rho, f_i, E2``
1142
+ and the (possibly) transcendental parameter ``d``.
1143
+
1144
+ EXAMPLES::
1145
+
1146
+ sage: from sage.modular.modform_hecketriangle.space import WeakModularForms
1147
+ sage: MF = WeakModularForms(n=5, k=62/3, ep=-1)
1148
+ sage: MF.weight_parameters()
1149
+ (2, 3)
1150
+
1151
+ sage: MF.F_basis_pol(2)
1152
+ x^13*y*d^2 - 2*x^8*y^3*d^2 + x^3*y^5*d^2
1153
+ sage: MF.F_basis_pol(1) * 100
1154
+ 81*x^13*y*d - 62*x^8*y^3*d - 19*x^3*y^5*d
1155
+ sage: MF.F_basis_pol(0)
1156
+ (141913*x^13*y + 168974*x^8*y^3 + 9113*x^3*y^5)/320000
1157
+
1158
+ sage: MF(MF.F_basis_pol(2)).q_expansion(prec=MF._l1+2)
1159
+ q^2 - 41/(200*d)*q^3 + O(q^4)
1160
+ sage: MF(MF.F_basis_pol(1)).q_expansion(prec=MF._l1+1)
1161
+ q + O(q^3)
1162
+ sage: MF(MF.F_basis_pol(0)).q_expansion(prec=MF._l1+1)
1163
+ 1 + O(q^3)
1164
+ sage: MF(MF.F_basis_pol(-2)).q_expansion(prec=MF._l1+1)
1165
+ q^-2 + O(q^3)
1166
+ sage: MF(MF.F_basis_pol(-2)).parent()
1167
+ WeakModularForms(n=5, k=62/3, ep=-1) over Integer Ring
1168
+
1169
+ sage: MF = WeakModularForms(n=4, k=-2, ep=1)
1170
+ sage: MF.weight_parameters()
1171
+ (-1, 3)
1172
+
1173
+ sage: MF.F_basis_pol(-1)
1174
+ x^3/(x^4*d - y^2*d)
1175
+ sage: MF.F_basis_pol(-2)
1176
+ (9*x^7 + 23*x^3*y^2)/(32*x^8*d^2 - 64*x^4*y^2*d^2 + 32*y^4*d^2)
1177
+
1178
+ sage: MF(MF.F_basis_pol(-1)).q_expansion(prec=MF._l1+2)
1179
+ q^-1 + 5/(16*d) + O(q)
1180
+ sage: MF(MF.F_basis_pol(-2)).q_expansion(prec=MF._l1+2)
1181
+ q^-2 + 25/(4096*d^2) + O(q)
1182
+
1183
+ sage: MF = WeakModularForms(n=infinity, k=14, ep=-1)
1184
+ sage: MF.F_basis_pol(3)
1185
+ -y^7*d^3 + 3*x*y^5*d^3 - 3*x^2*y^3*d^3 + x^3*y*d^3
1186
+ sage: MF.F_basis_pol(2)
1187
+ (3*y^7*d^2 - 17*x*y^5*d^2 + 25*x^2*y^3*d^2 - 11*x^3*y*d^2)/(-8)
1188
+ sage: MF.F_basis_pol(1)
1189
+ (-75*y^7*d + 225*x*y^5*d - 1249*x^2*y^3*d + 1099*x^3*y*d)/1024
1190
+ sage: MF.F_basis_pol(0)
1191
+ (41*y^7 - 147*x*y^5 - 1365*x^2*y^3 - 2625*x^3*y)/(-4096)
1192
+ sage: MF.F_basis_pol(-1)
1193
+ (-9075*y^9 + 36300*x*y^7 - 718002*x^2*y^5 - 4928052*x^3*y^3 - 2769779*x^4*y)/(8388608*y^2*d - 8388608*x*d)
1194
+
1195
+ sage: MF.F_basis_pol(3, order_1=-1)
1196
+ (-3*y^9*d^3 + 16*x*y^7*d^3 - 30*x^2*y^5*d^3 + 24*x^3*y^3*d^3 - 7*x^4*y*d^3)/(-4*x)
1197
+ sage: MF.F_basis_pol(1, order_1=2)
1198
+ -x^2*y^3*d + x^3*y*d
1199
+ sage: MF.F_basis_pol(0, order_1=2)
1200
+ (-3*x^2*y^3 - 5*x^3*y)/(-8)
1201
+ sage: MF.F_basis_pol(-1, order_1=2)
1202
+ (-81*x^2*y^5 - 606*x^3*y^3 - 337*x^4*y)/(1024*y^2*d - 1024*x*d)
1203
+ """
1204
+
1205
+ (x,y,z,d) = self.rat_field().gens()
1206
+ n = self._group.n()
1207
+
1208
+ if (n == infinity):
1209
+ order_1 = ZZ(order_1)
1210
+ order_inf = self._l1 - order_1
1211
+ finf_pol = d*(x-y**2)
1212
+ jinv_pol = x/(x-y**2)
1213
+ rat = finf_pol**order_inf * x**order_1 * y**(ZZ(1-self._ep)/ZZ(2)) * self.Faber_pol(m, order_1)(jinv_pol)
1214
+ else:
1215
+ order_inf = self._l1
1216
+ order_1 = order_inf
1217
+ finf_pol = d*(x**n-y**2)
1218
+ jinv_pol = x**n/(x**n-y**2)
1219
+ rat = finf_pol**order_inf * x**self._l2 * y**(ZZ(1-self._ep)/ZZ(2)) * self.Faber_pol(m)(jinv_pol)
1220
+
1221
+ return rat
1222
+
1223
+ def F_basis(self, m, order_1=ZZ.zero()):
1224
+ r"""
1225
+ Return a weakly holomorphic element of ``self``
1226
+ (extended if necessarily) determined by the property that
1227
+ the Fourier expansion is of the form is of the form
1228
+ ``q^m + O(q^(order_inf + 1))``, where ``order_inf = self._l1 - order_1``.
1229
+
1230
+ In particular for all ``m <= order_inf`` these elements form
1231
+ a basis of the space of weakly holomorphic modular forms
1232
+ of the corresponding degree in case ``n!=infinity``.
1233
+
1234
+ If ``n=infinity`` a non-trivial order of ``-1`` can be specified through
1235
+ the parameter ``order_1`` (default: 0). Otherwise it is ignored.
1236
+
1237
+ INPUT:
1238
+
1239
+ - ``m`` -- integer; ``m <= self._l1``
1240
+
1241
+ - ``order_1`` -- the order at ``-1`` of ``F_simple`` (default: 0);
1242
+ this parameter is ignored if ``n != infinity``
1243
+
1244
+ OUTPUT:
1245
+
1246
+ The corresponding element in (possibly an extension of) ``self``.
1247
+ Note that the order at ``-1`` of the resulting element may be
1248
+ bigger than ``order_1`` (rare).
1249
+
1250
+ EXAMPLES::
1251
+
1252
+ sage: from sage.modular.modform_hecketriangle.space import WeakModularForms, CuspForms
1253
+ sage: MF = WeakModularForms(n=5, k=62/3, ep=-1)
1254
+ sage: MF.disp_prec(MF._l1+2)
1255
+ sage: MF.weight_parameters()
1256
+ (2, 3)
1257
+
1258
+ sage: MF.F_basis(2)
1259
+ q^2 - 41/(200*d)*q^3 + O(q^4)
1260
+ sage: MF.F_basis(1)
1261
+ q - 13071/(640000*d^2)*q^3 + O(q^4)
1262
+ sage: MF.F_basis(0)
1263
+ 1 - 277043/(192000000*d^3)*q^3 + O(q^4)
1264
+ sage: MF.F_basis(-2)
1265
+ q^-2 - 162727620113/(40960000000000000*d^5)*q^3 + O(q^4)
1266
+ sage: MF.F_basis(-2).parent() == MF
1267
+ True
1268
+
1269
+ sage: MF = CuspForms(n=4, k=-2, ep=1)
1270
+ sage: MF.weight_parameters()
1271
+ (-1, 3)
1272
+
1273
+ sage: MF.F_basis(-1).parent()
1274
+ WeakModularForms(n=4, k=-2, ep=1) over Integer Ring
1275
+ sage: MF.F_basis(-1).parent().disp_prec(MF._l1+2)
1276
+ sage: MF.F_basis(-1)
1277
+ q^-1 + 80 + O(q)
1278
+ sage: MF.F_basis(-2)
1279
+ q^-2 + 400 + O(q)
1280
+
1281
+ sage: MF = WeakModularForms(n=infinity, k=14, ep=-1)
1282
+ sage: MF.F_basis(3)
1283
+ q^3 - 48*q^4 + O(q^5)
1284
+ sage: MF.F_basis(2)
1285
+ q^2 - 1152*q^4 + O(q^5)
1286
+ sage: MF.F_basis(1)
1287
+ q - 18496*q^4 + O(q^5)
1288
+ sage: MF.F_basis(0)
1289
+ 1 - 224280*q^4 + O(q^5)
1290
+ sage: MF.F_basis(-1)
1291
+ q^-1 - 2198304*q^4 + O(q^5)
1292
+
1293
+ sage: MF.F_basis(3, order_1=-1)
1294
+ q^3 + O(q^5)
1295
+ sage: MF.F_basis(1, order_1=2)
1296
+ q - 300*q^3 - 4096*q^4 + O(q^5)
1297
+ sage: MF.F_basis(0, order_1=2)
1298
+ 1 - 24*q^2 - 2048*q^3 - 98328*q^4 + O(q^5)
1299
+ sage: MF.F_basis(-1, order_1=2)
1300
+ q^-1 - 18150*q^3 - 1327104*q^4 + O(q^5)
1301
+ """
1302
+
1303
+ basis_pol = self.F_basis_pol(m, order_1=order_1)
1304
+
1305
+ if (self.hecke_n() == infinity):
1306
+ (x,y,z,d) = self.pol_ring().gens()
1307
+ if (x.divides(basis_pol.numerator()) and m > 0):
1308
+ new_space = self.extend_type("cusp")
1309
+ elif (x.divides(basis_pol.denominator()) or m < 0):
1310
+ new_space = self.extend_type("weak")
1311
+ else:
1312
+ new_space = self.extend_type("holo")
1313
+ else:
1314
+ if (m > 0):
1315
+ new_space = self.extend_type("cusp")
1316
+ elif (m >= 0):
1317
+ new_space = self.extend_type("holo")
1318
+ else:
1319
+ new_space = self.extend_type("weak")
1320
+
1321
+ return new_space(basis_pol)
1322
+
1323
+ def _canonical_min_exp(self, min_exp, order_1):
1324
+ r"""
1325
+ Return an adjusted value of ``min_exp`` and ``order_1`` corresponding
1326
+ to the analytic type of ``self``.
1327
+
1328
+ EXAMPLES::
1329
+
1330
+ sage: from sage.modular.modform_hecketriangle.space import CuspForms
1331
+ sage: CF = CuspForms(n=5, k=16, ep=1)
1332
+ sage: CF._canonical_min_exp(-2, 0)
1333
+ (1, 0)
1334
+
1335
+ sage: CF = CuspForms(n=infinity, k=10, ep=-1)
1336
+ sage: CF._canonical_min_exp(-2, -2)
1337
+ (1, 1)
1338
+ """
1339
+
1340
+ min_exp = ZZ(min_exp)
1341
+ order_1 = ZZ(order_1)
1342
+ if self.is_holomorphic():
1343
+ if self.is_cuspidal():
1344
+ min_exp = max(min_exp, 1)
1345
+ order_1 = max(order_1, 1)
1346
+ else:
1347
+ min_exp = max(min_exp, 0)
1348
+ order_1 = max(order_1, 0)
1349
+
1350
+ if (self.hecke_n() != infinity):
1351
+ order_1 = ZZ.zero()
1352
+
1353
+ return (min_exp, order_1)
1354
+
1355
+ def quasi_part_gens(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ.zero()) -> tuple:
1356
+ r"""
1357
+ Return a basis in ``self`` of the subspace of (quasi) weakly
1358
+ holomorphic forms which satisfy the specified properties on
1359
+ the quasi parts and the initial Fourier coefficient.
1360
+
1361
+ INPUT:
1362
+
1363
+ - ``r`` -- an integer or ``None`` (default), indicating the desired
1364
+ power of ``E2``; if ``r`` is ``None`` then all possible powers
1365
+ (``r``) are chosen
1366
+
1367
+ - ``min_exp`` -- integer (default: 0); a lower bound for the first
1368
+ non-trivial Fourier coefficient of the generators
1369
+
1370
+ - ``max_exp`` -- integer or ``infinity`` (default) giving an upper
1371
+ bound for the first non-trivial Fourier coefficient of the
1372
+ generators. If ``max_exp==infinity`` then no upper bound is assumed.
1373
+
1374
+ - ``order_1`` -- a lower bound for the order at ``-1`` of all quasi
1375
+ parts of the basis elements (default: 0). If ``n!=infinity`` this
1376
+ parameter is ignored.
1377
+
1378
+ OUTPUT:
1379
+
1380
+ A basis in ``self`` of the subspace of forms which are modular
1381
+ after dividing by ``E2^r`` and which have a Fourier expansion
1382
+ of the form ``q^m + O(q^(m+1))`` with ``min_exp <= m <=
1383
+ max_exp`` for each quasi part (and at least the specified
1384
+ order at ``-1`` in case ``n=infinity``). Note that linear
1385
+ combinations of forms/quasi parts maybe have a higher order at
1386
+ infinity than ``max_exp``.
1387
+
1388
+ EXAMPLES::
1389
+
1390
+ sage: from sage.modular.modform_hecketriangle.space import QuasiWeakModularForms
1391
+ sage: QF = QuasiWeakModularForms(n=8, k=10/3, ep=-1)
1392
+ sage: QF.default_prec(1)
1393
+ sage: QF.quasi_part_gens(min_exp=-1)
1394
+ (q^-1 + O(q), 1 + O(q), q^-1 - 9/(128*d) + O(q),
1395
+ 1 + O(q), q^-1 - 19/(64*d) + O(q), q^-1 + 1/(64*d) + O(q))
1396
+
1397
+ sage: QF.quasi_part_gens(min_exp=-1, max_exp=-1)
1398
+ (q^-1 + O(q), q^-1 - 9/(128*d) + O(q),
1399
+ q^-1 - 19/(64*d) + O(q), q^-1 + 1/(64*d) + O(q))
1400
+ sage: QF.quasi_part_gens(min_exp=-2, r=1)
1401
+ (q^-2 - 9/(128*d)*q^-1 - 261/(131072*d^2) + O(q),
1402
+ q^-1 - 9/(128*d) + O(q), 1 + O(q))
1403
+
1404
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
1405
+ sage: MF = ModularForms(k=36)
1406
+ sage: MF.quasi_part_gens(min_exp=2)
1407
+ (q^2 + 194184*q^4 + O(q^5), q^3 - 72*q^4 + O(q^5))
1408
+
1409
+ sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms
1410
+ sage: MF = QuasiModularForms(n=5, k=6, ep=-1)
1411
+ sage: MF.default_prec(2)
1412
+ sage: MF.dimension()
1413
+ 3
1414
+ sage: MF.quasi_part_gens(r=0)
1415
+ (1 - 37/(200*d)*q + O(q^2),)
1416
+ sage: MF.quasi_part_gens(r=0)[0] == MF.E6()
1417
+ True
1418
+ sage: MF.quasi_part_gens(r=1)
1419
+ (1 + 33/(200*d)*q + O(q^2),)
1420
+ sage: MF.quasi_part_gens(r=1)[0] == MF.E2()*MF.E4()
1421
+ True
1422
+ sage: MF.quasi_part_gens(r=2)
1423
+ ()
1424
+ sage: MF.quasi_part_gens(r=3)
1425
+ (1 - 27/(200*d)*q + O(q^2),)
1426
+ sage: MF.quasi_part_gens(r=3)[0] == MF.E2()^3
1427
+ True
1428
+
1429
+ sage: from sage.modular.modform_hecketriangle.space import QuasiCuspForms, CuspForms
1430
+ sage: MF = QuasiCuspForms(n=5, k=18, ep=-1)
1431
+ sage: MF.default_prec(4)
1432
+ sage: MF.dimension()
1433
+ 8
1434
+ sage: MF.quasi_part_gens(r=0)
1435
+ (q - 34743/(640000*d^2)*q^3 + O(q^4), q^2 - 69/(200*d)*q^3 + O(q^4))
1436
+ sage: MF.quasi_part_gens(r=1)
1437
+ (q - 9/(200*d)*q^2 + 37633/(640000*d^2)*q^3 + O(q^4),
1438
+ q^2 + 1/(200*d)*q^3 + O(q^4))
1439
+ sage: MF.quasi_part_gens(r=2)
1440
+ (q - 1/(4*d)*q^2 - 24903/(640000*d^2)*q^3 + O(q^4),)
1441
+ sage: MF.quasi_part_gens(r=3)
1442
+ (q + 1/(10*d)*q^2 - 7263/(640000*d^2)*q^3 + O(q^4),)
1443
+ sage: MF.quasi_part_gens(r=4)
1444
+ (q - 11/(20*d)*q^2 + 53577/(640000*d^2)*q^3 + O(q^4),)
1445
+ sage: MF.quasi_part_gens(r=5)
1446
+ (q - 1/(5*d)*q^2 + 4017/(640000*d^2)*q^3 + O(q^4),)
1447
+
1448
+ sage: MF.quasi_part_gens(r=1)[0] == MF.E2() * CuspForms(n=5, k=16, ep=1).gen(0)
1449
+ True
1450
+ sage: MF.quasi_part_gens(r=1)[1] == MF.E2() * CuspForms(n=5, k=16, ep=1).gen(1)
1451
+ True
1452
+ sage: MF.quasi_part_gens(r=3)[0] == MF.E2()^3 * MF.Delta()
1453
+ True
1454
+
1455
+ sage: MF = QuasiCuspForms(n=infinity, k=18, ep=-1)
1456
+ sage: MF.quasi_part_gens(r=1, min_exp=-2) == MF.quasi_part_gens(r=1, min_exp=1)
1457
+ True
1458
+ sage: MF.quasi_part_gens(r=1)
1459
+ (q - 8*q^2 - 8*q^3 + 5952*q^4 + O(q^5),
1460
+ q^2 - 8*q^3 + 208*q^4 + O(q^5),
1461
+ q^3 - 16*q^4 + O(q^5))
1462
+
1463
+ sage: MF = QuasiWeakModularForms(n=infinity, k=4, ep=1)
1464
+ sage: MF.quasi_part_gens(r=2, min_exp=2, order_1=-2)[0] == MF.E2()^2 * MF.E4()^(-2) * MF.f_inf()^2
1465
+ True
1466
+ sage: [v.order_at(-1) for v in MF.quasi_part_gens(r=0, min_exp=2, order_1=-2)]
1467
+ [-2, -2]
1468
+ """
1469
+ if not self.is_weakly_holomorphic():
1470
+ from warnings import warn
1471
+ warn("This function only determines generators of (quasi) weakly modular forms!")
1472
+
1473
+ min_exp, order_1 = self._canonical_min_exp(min_exp, order_1)
1474
+
1475
+ # For modular forms spaces the quasi parts are all zero except for r=0
1476
+ if self.is_modular():
1477
+ r = ZZ(r)
1478
+ if r:
1479
+ return ()
1480
+
1481
+ # The lower bounds on the powers of f_inf and E4 determine
1482
+ # how large powers of E2 we can fit in...
1483
+ n = self.hecke_n()
1484
+ if n == infinity:
1485
+ max_numerator_weight = self._weight - 4*min_exp - 4*order_1 + 4
1486
+ else:
1487
+ max_numerator_weight = self._weight - 4*n/(n-2)*min_exp + 4
1488
+
1489
+ # If r is not specified we gather all generators for all possible r's
1490
+ if r is None:
1491
+ gens = []
1492
+ for rnew in range(QQ(max_numerator_weight / ZZ(2)).floor() + 1):
1493
+ gens.extend(self.quasi_part_gens(r=rnew, min_exp=min_exp, max_exp=max_exp, order_1=order_1))
1494
+ return tuple(gens)
1495
+
1496
+ r = ZZ(r)
1497
+ if r < 0 or 2*r > max_numerator_weight:
1498
+ return ()
1499
+
1500
+ E2 = self.E2()
1501
+ ambient_weak_space = self.graded_ring().reduce_type("weak",
1502
+ degree=(self._weight-QQ(2*r), self._ep*(-1)**r))
1503
+ order_inf = ambient_weak_space._l1 - order_1
1504
+
1505
+ if max_exp == infinity:
1506
+ max_exp = order_inf
1507
+ elif max_exp < min_exp:
1508
+ return ()
1509
+ else:
1510
+ max_exp = min(ZZ(max_exp), order_inf)
1511
+
1512
+ return tuple(self(ambient_weak_space.F_basis(m, order_1=order_1) * E2**r)
1513
+ for m in range(min_exp, max_exp + 1))
1514
+
1515
+ def quasi_part_dimension(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ.zero()):
1516
+ r"""
1517
+ Return the dimension of the subspace of ``self`` generated by
1518
+ ``self.quasi_part_gens(r, min_exp, max_exp, order_1)``.
1519
+
1520
+ See :meth:`quasi_part_gens` for more details.
1521
+
1522
+ EXAMPLES::
1523
+
1524
+ sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms, QuasiCuspForms, QuasiWeakModularForms
1525
+ sage: MF = QuasiModularForms(n=5, k=6, ep=-1)
1526
+ sage: [v.as_ring_element() for v in MF.gens()]
1527
+ [f_rho^2*f_i, f_rho^3*E2, E2^3]
1528
+ sage: MF.dimension()
1529
+ 3
1530
+ sage: MF.quasi_part_dimension(r=0)
1531
+ 1
1532
+ sage: MF.quasi_part_dimension(r=1)
1533
+ 1
1534
+ sage: MF.quasi_part_dimension(r=2)
1535
+ 0
1536
+ sage: MF.quasi_part_dimension(r=3)
1537
+ 1
1538
+
1539
+ sage: MF = QuasiCuspForms(n=5, k=18, ep=-1)
1540
+ sage: MF.dimension()
1541
+ 8
1542
+ sage: MF.quasi_part_dimension(r=0)
1543
+ 2
1544
+ sage: MF.quasi_part_dimension(r=1)
1545
+ 2
1546
+ sage: MF.quasi_part_dimension(r=2)
1547
+ 1
1548
+ sage: MF.quasi_part_dimension(r=3)
1549
+ 1
1550
+ sage: MF.quasi_part_dimension(r=4)
1551
+ 1
1552
+ sage: MF.quasi_part_dimension(r=5)
1553
+ 1
1554
+ sage: MF.quasi_part_dimension(min_exp=2, max_exp=2)
1555
+ 2
1556
+
1557
+ sage: MF = QuasiCuspForms(n=infinity, k=18, ep=-1)
1558
+ sage: MF.quasi_part_dimension(r=1, min_exp=-2)
1559
+ 3
1560
+ sage: MF.quasi_part_dimension()
1561
+ 12
1562
+ sage: MF.quasi_part_dimension(order_1=3)
1563
+ 2
1564
+
1565
+ sage: MF = QuasiWeakModularForms(n=infinity, k=4, ep=1)
1566
+ sage: MF.quasi_part_dimension(min_exp=2, order_1=-2)
1567
+ 4
1568
+ sage: [v.order_at(-1) for v in MF.quasi_part_gens(r=0, min_exp=2, order_1=-2)]
1569
+ [-2, -2]
1570
+ """
1571
+
1572
+ if (not self.is_weakly_holomorphic()):
1573
+ from warnings import warn
1574
+ warn("This function only determines the dimension of some (quasi) weakly subspace!")
1575
+
1576
+ (min_exp, order_1) = self._canonical_min_exp(min_exp, order_1)
1577
+
1578
+ # For modular forms spaces the quasi parts are all zero except for r=0
1579
+ if self.is_modular():
1580
+ r = ZZ.zero()
1581
+ if r != 0:
1582
+ return ZZ.zero()
1583
+
1584
+ # The lower bounds on the powers of f_inf and E4 determine
1585
+ # how large powers of E2 we can fit in...
1586
+ n = self.hecke_n()
1587
+ if (n == infinity):
1588
+ max_numerator_weight = self._weight - 4*min_exp - 4*order_1 + 4
1589
+ else:
1590
+ max_numerator_weight = self._weight - 4*n/(n-2)*min_exp + 4
1591
+
1592
+ # If r is not specified we calculate the total dimension over all possible r's
1593
+ if r is None:
1594
+ return sum([self.quasi_part_dimension(r=rnew, min_exp=min_exp, max_exp=max_exp, order_1=order_1) for rnew in range(QQ(max_numerator_weight/ZZ(2)).floor() + 1)])
1595
+
1596
+ r = ZZ(r)
1597
+ if (r < 0 or 2*r > max_numerator_weight):
1598
+ return ZZ.zero()
1599
+
1600
+ k = self._weight - QQ(2*r)
1601
+ ep = self._ep * (-1)**r
1602
+ if (n == infinity):
1603
+ num = (k - (1-ep)) / ZZ(4)
1604
+ l2 = order_1
1605
+ order_inf = ZZ(num) - order_1
1606
+ else:
1607
+ num = ZZ((k-(1-ep)*ZZ(n)/ZZ(n-2)) * ZZ(n-2) / ZZ(4))
1608
+ l2 = num % n
1609
+ order_inf = ((num - l2) / n).numerator()
1610
+
1611
+ if (max_exp == infinity):
1612
+ max_exp = order_inf
1613
+ elif (max_exp < min_exp):
1614
+ return ZZ.zero()
1615
+ else:
1616
+ max_exp = min(ZZ(max_exp), order_inf)
1617
+
1618
+ return max(ZZ.zero(), max_exp - min_exp + 1)
1619
+
1620
+ def construct_form(self, laurent_series, order_1=ZZ.zero(), check=True, rationalize=False):
1621
+ r"""
1622
+ Try to construct an element of ``self`` with the given Fourier
1623
+ expansion. The assumption is made that the specified Fourier
1624
+ expansion corresponds to a weakly holomorphic modular form.
1625
+
1626
+ If the precision is too low to determine the
1627
+ element an exception is raised.
1628
+
1629
+ INPUT:
1630
+
1631
+ - ``laurent_series`` -- a Laurent or Power series
1632
+
1633
+ - ``order_1`` -- a lower bound for the order at ``-1`` of the form
1634
+ (default: 0). If ``n!=infinity`` this parameter is ignored.
1635
+
1636
+ - ``check`` -- if ``True`` (default) then the series expansion of the
1637
+ constructed form is compared against the given series
1638
+
1639
+ - ``rationalize`` -- if ``True`` (default: ``False``) then the series
1640
+ is "rationalized" beforehand. Note that in non-exact or
1641
+ non-arithmetic cases this is experimental and extremely unreliable!
1642
+
1643
+ OUTPUT:
1644
+
1645
+ If possible: An element of ``self`` with the same initial
1646
+ Fourier expansion as ``laurent_series``.
1647
+
1648
+ Note: For modular spaces it is also possible to call
1649
+ ``self(laurent_series)`` instead.
1650
+
1651
+ EXAMPLES::
1652
+
1653
+ sage: from sage.modular.modform_hecketriangle.space import CuspForms
1654
+ sage: Delta = CuspForms(k=12).Delta()
1655
+ sage: qexp = Delta.q_expansion(prec=2)
1656
+ sage: qexp.parent()
1657
+ Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
1658
+ sage: qexp
1659
+ q + O(q^2)
1660
+ sage: CuspForms(k=12).construct_form(qexp) == Delta
1661
+ True
1662
+
1663
+ sage: from sage.modular.modform_hecketriangle.space import WeakModularForms
1664
+ sage: J_inv = WeakModularForms(n=7).J_inv()
1665
+ sage: qexp2 = J_inv.q_expansion(prec=1)
1666
+ sage: qexp2.parent()
1667
+ Laurent Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
1668
+ sage: qexp2
1669
+ d*q^-1 + 151/392 + O(q)
1670
+ sage: WeakModularForms(n=7).construct_form(qexp2) == J_inv
1671
+ True
1672
+
1673
+ sage: MF = WeakModularForms(n=5, k=62/3, ep=-1)
1674
+ sage: MF.default_prec(MF._l1+1)
1675
+ sage: d = MF.get_d()
1676
+ sage: MF.weight_parameters()
1677
+ (2, 3)
1678
+ sage: el2 = d*MF.F_basis(2) + 2*MF.F_basis(1) + MF.F_basis(-2)
1679
+ sage: qexp2 = el2.q_expansion()
1680
+ sage: qexp2.parent()
1681
+ Laurent Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
1682
+ sage: qexp2
1683
+ q^-2 + 2*q + d*q^2 + O(q^3)
1684
+ sage: WeakModularForms(n=5, k=62/3, ep=-1).construct_form(qexp2) == el2
1685
+ True
1686
+
1687
+ sage: MF = WeakModularForms(n=infinity, k=-2, ep=-1)
1688
+ sage: el3 = MF.f_i()/MF.f_inf() + MF.f_i()*MF.f_inf()/MF.E4()^2
1689
+ sage: MF.quasi_part_dimension(min_exp=-1, order_1=-2)
1690
+ 3
1691
+ sage: prec = MF._l1 + 3
1692
+ sage: qexp3 = el3.q_expansion(prec)
1693
+ sage: qexp3
1694
+ q^-1 - 1/(4*d) + ((1024*d^2 - 33)/(1024*d^2))*q + O(q^2)
1695
+ sage: MF.construct_form(qexp3, order_1=-2) == el3
1696
+ True
1697
+ sage: MF.construct_form(el3.q_expansion(prec + 1), order_1=-3) == el3
1698
+ True
1699
+
1700
+ sage: WF = WeakModularForms(n=14)
1701
+ sage: qexp = WF.J_inv().q_expansion_fixed_d(d_num_prec=1000)
1702
+ sage: qexp.parent()
1703
+ Laurent Series Ring in q over Real Field with 1000 bits of precision
1704
+ sage: WF.construct_form(qexp, rationalize=True) == WF.J_inv()
1705
+ doctest:...: UserWarning: Using an experimental rationalization of coefficients, please check the result for correctness!
1706
+ True
1707
+ """
1708
+
1709
+ base_ring = laurent_series.base_ring()
1710
+ if isinstance(base_ring.base(), PolynomialRing_generic):
1711
+ if not (self.coeff_ring().has_coerce_map_from(base_ring)):
1712
+ raise ValueError("The Laurent coefficients don't coerce into the coefficient ring of self!")
1713
+ elif rationalize:
1714
+ laurent_series = self.rationalize_series(laurent_series)
1715
+ else:
1716
+ raise ValueError("The Laurent coefficients are not in the proper form yet. Try rationalize_series(laurent_series) beforehand (experimental).")
1717
+
1718
+ order_1 = self._canonical_min_exp(0, order_1)[1]
1719
+ order_inf = self._l1 - order_1
1720
+
1721
+ if (laurent_series.prec() < order_inf + 1):
1722
+ raise ValueError("Insufficient precision: {} < {} = order_inf!".format(laurent_series.prec(), order_inf + 1))
1723
+
1724
+ new_series = laurent_series.add_bigoh(order_inf + 1)
1725
+ coefficients = new_series.coefficients()
1726
+ exponents = new_series.exponents()
1727
+
1728
+ if (len(coefficients) == 0):
1729
+ return self(0)
1730
+
1731
+ rat = sum([coefficients[j] * self.F_basis_pol(exponents[j], order_1=order_1)
1732
+ for j in range(ZZ(len(coefficients)))])
1733
+
1734
+ el = self(rat)
1735
+
1736
+ if (check):
1737
+ prec = min(laurent_series.prec(), laurent_series.exponents()[-1] + 1)
1738
+ if (el.q_expansion(prec=prec) != laurent_series):
1739
+ raise ValueError("The Laurent series {} does not correspond to a form of {}".format(laurent_series, self.reduce_type(["weak"])))
1740
+
1741
+ return el
1742
+
1743
+ @cached_method
1744
+ def _quasi_form_matrix(self, min_exp=0, order_1=ZZ.zero(), incr_prec_by=0):
1745
+ r"""
1746
+ Return a base change matrix which transforms coordinate vectors
1747
+ with respect to a certain basis into a vector corresponding to
1748
+ Laurent coefficients of a series.
1749
+
1750
+ This is a helper function used to construct weakly holomorphic quasi
1751
+ forms based on their initial Laurent coefficients
1752
+ (see :meth:`construct_quasi_form`).
1753
+
1754
+ INPUT:
1755
+
1756
+ - ``min_exp`` -- integer (default: 0), namely the lower bound for the
1757
+ order at infinity resp. the exponent of the Laurent series
1758
+
1759
+ - ``order_1`` -- a lower bound for the order at ``-1`` of all quasi
1760
+ parts of the subspace (default: 0). If ``n!=infinity`` this parameter
1761
+ is ignored.
1762
+
1763
+ - ``incr_prec_by`` -- integer (default: 0) which specifies how much the
1764
+ precision should be increased compared to the size of the
1765
+ corresponding basis
1766
+
1767
+ OUTPUT: the corresponding base change matrix
1768
+
1769
+ EXAMPLES::
1770
+
1771
+ sage: from sage.modular.modform_hecketriangle.space import QuasiWeakModularForms, ModularForms, QuasiModularForms
1772
+ sage: QF = QuasiWeakModularForms(n=8, k=10/3, ep=-1)
1773
+ sage: A = QF._quasi_form_matrix(min_exp=-1)
1774
+ sage: A[3]
1775
+ (-1215/(65536*d^3), -2171/(131072*d^2), 134099/(16777216*d^3), -811/(131072*d^2), 15889/(8388608*d^3), -8851/(8388608*d^3))
1776
+
1777
+ sage: MF = ModularForms(k=36)
1778
+ sage: MF._quasi_form_matrix(min_exp=2)
1779
+ [1 0]
1780
+ [0 1]
1781
+
1782
+ sage: QuasiModularForms(k=2)._quasi_form_matrix()
1783
+ [1]
1784
+
1785
+ sage: QF = QuasiWeakModularForms(n=infinity, k=-2, ep=-1)
1786
+ sage: A = QF._quasi_form_matrix(min_exp=-1, order_1=0)
1787
+ sage: A
1788
+ [ 1 1]
1789
+ [-1/(4*d) 0]
1790
+ """
1791
+
1792
+ (min_exp, order_1) = self._canonical_min_exp(min_exp, order_1)
1793
+
1794
+ order_inf = self._l1 - order_1
1795
+
1796
+ # We have to add + 1 to get a correct upper bound in all cases
1797
+ # since corresponding weak space might have a higher l1 (+1) than
1798
+ # ``self``, even if the weight is smaller
1799
+ max_exp = order_inf + 1
1800
+
1801
+ basis = self.quasi_part_gens(min_exp=min_exp, max_exp=max_exp, order_1=order_1)
1802
+
1803
+ column_size = len(basis)
1804
+ # a non-trivial incr_prec_by will be added in case the resulting matrix does not have full rank
1805
+ row_size = column_size + incr_prec_by
1806
+ prec = row_size + min_exp
1807
+
1808
+ coeff_ring = self.coeff_ring()
1809
+ A = matrix(coeff_ring, row_size, 0)
1810
+
1811
+ for gen in basis:
1812
+ A = A.augment(gen.q_expansion_vector(min_exp=min_exp, max_exp=prec-1))
1813
+
1814
+ # So far this case never happened but potentially A could be singular!
1815
+ # In this case we want to increase the row size until A has maximal
1816
+ # rank (i.e. column size).
1817
+
1818
+ # This is done up increasing the precision of everything by about 20%
1819
+ # of the column size until A has maximal rank:
1820
+ if (A.rank() < column_size):
1821
+ if (incr_prec_by == 0):
1822
+ from sage.misc.verbose import verbose
1823
+ verbose("Encountered a base change matrix with not-yet-maximal rank (rare, please report)!")
1824
+ incr_prec_by += column_size//ZZ(5) + 1
1825
+ return self._quasi_form_matrix(min_exp=min_exp, order_1=order_1, incr_prec_by=incr_prec_by)
1826
+ elif (incr_prec_by == 0):
1827
+ return A
1828
+
1829
+ # At this point the matrix has maximal rank but might be too big.
1830
+ # Since we are interested in the (exact) required size resp. precision
1831
+ # we have to decrease the (row) size as much as possible while keeping
1832
+ # maximal rank. We cannot simply choose pivots/etc since we want to
1833
+ # keep a simple correspondence to Fourier coefficients!
1834
+
1835
+ # We start by using an initial binary search to delete some unnecessary rows:
1836
+ while (A.rank() == column_size):
1837
+ row_size = A.dimensions()[0]
1838
+
1839
+ # to avoid infinite loops
1840
+ if (row_size == column_size):
1841
+ return A
1842
+
1843
+ B = A
1844
+ A = A.delete_rows(list(range(column_size + (row_size-column_size)//2 - 1, row_size)))
1845
+
1846
+ # Next we simply delete row by row. Note that A is still modified here...
1847
+ while (B.rank() == column_size):
1848
+ A = B
1849
+ row_size = B.dimensions()[0]
1850
+ B = B.delete_rows([row_size-1])
1851
+
1852
+ return A
1853
+
1854
+ def required_laurent_prec(self, min_exp=0, order_1=ZZ.zero()):
1855
+ r"""
1856
+ Return an upper bound for the required precision for Laurent series to
1857
+ uniquely determine a corresponding (quasi) form in ``self`` with the given
1858
+ lower bound ``min_exp`` for the order at infinity (for each quasi part).
1859
+
1860
+ .. NOTE::
1861
+
1862
+ For ``n=infinity`` only the holomorphic case (``min_exp >= 0``)
1863
+ is supported (in particular a nonnegative order at ``-1`` is assumed).
1864
+
1865
+ INPUT:
1866
+
1867
+ - ``min_exp`` -- integer (default: 0); namely the lower bound for the
1868
+ order at infinity resp. the exponent of the Laurent series
1869
+
1870
+ - ``order_1`` -- a lower bound for the order at ``-1`` for all quasi
1871
+ parts (default: 0). If ``n!=infinity`` this parameter is ignored.
1872
+
1873
+ OUTPUT:
1874
+
1875
+ An integer, namely an upper bound for the number of required
1876
+ Laurent coefficients. The bound should be precise or at least
1877
+ pretty sharp.
1878
+
1879
+ EXAMPLES::
1880
+
1881
+ sage: from sage.modular.modform_hecketriangle.space import QuasiWeakModularForms, ModularForms, QuasiModularForms
1882
+ sage: QF = QuasiWeakModularForms(n=8, k=10/3, ep=-1)
1883
+ sage: QF.required_laurent_prec(min_exp=-1)
1884
+ 5
1885
+
1886
+ sage: MF = ModularForms(k=36)
1887
+ sage: MF.required_laurent_prec(min_exp=2)
1888
+ 4
1889
+
1890
+ sage: QuasiModularForms(k=2).required_laurent_prec()
1891
+ 1
1892
+
1893
+ sage: QuasiWeakModularForms(n=infinity, k=2, ep=-1).required_laurent_prec(order_1=-1)
1894
+ 6
1895
+ """
1896
+
1897
+ (min_exp, order_1) = self._canonical_min_exp(min_exp, order_1)
1898
+
1899
+ return self._quasi_form_matrix(min_exp=min_exp, order_1=order_1).dimensions()[0] + min_exp
1900
+
1901
+ def construct_quasi_form(self, laurent_series, order_1=ZZ.zero(), check=True, rationalize=False):
1902
+ r"""
1903
+ Try to construct an element of ``self`` with the given Fourier
1904
+ expansion. The assumption is made that the specified Fourier
1905
+ expansion corresponds to a weakly holomorphic quasi modular form.
1906
+
1907
+ If the precision is too low to determine the
1908
+ element an exception is raised.
1909
+
1910
+ INPUT:
1911
+
1912
+ - ``laurent_series`` -- a Laurent or Power series
1913
+
1914
+ - ``order_1`` -- a lower bound for the order at ``-1`` for all quasi
1915
+ parts of the form (default: 0). If ``n!=infinity`` this parameter is
1916
+ ignored.
1917
+
1918
+ - ``check`` -- if ``True`` (default) then the series expansion of the
1919
+ constructed form is compared against the given (rationalized) series.
1920
+
1921
+ - ``rationalize`` -- if ``True`` (default: ``False``) then the series
1922
+ is "rationalized" beforehand. Note that in non-exact or
1923
+ non-arithmetic cases this is experimental and extremely unreliable!
1924
+
1925
+ OUTPUT:
1926
+
1927
+ If possible: An element of ``self`` with the same initial
1928
+ Fourier expansion as ``laurent_series``.
1929
+
1930
+ Note: For non modular spaces it is also possible to call
1931
+ ``self(laurent_series)`` instead. Also note that this function works
1932
+ much faster if a corresponding (cached) ``q_basis`` is available.
1933
+
1934
+ EXAMPLES::
1935
+
1936
+ sage: from sage.modular.modform_hecketriangle.space import QuasiWeakModularForms, ModularForms, QuasiModularForms, QuasiCuspForms
1937
+ sage: QF = QuasiWeakModularForms(n=8, k=10/3, ep=-1)
1938
+ sage: el = QF.quasi_part_gens(min_exp=-1)[4]
1939
+ sage: prec = QF.required_laurent_prec(min_exp=-1)
1940
+ sage: prec
1941
+ 5
1942
+ sage: qexp = el.q_expansion(prec=prec)
1943
+ sage: qexp
1944
+ q^-1 - 19/(64*d) - 7497/(262144*d^2)*q + 15889/(8388608*d^3)*q^2 + 543834047/(1649267441664*d^4)*q^3 + 711869853/(43980465111040*d^5)*q^4 + O(q^5)
1945
+ sage: qexp.parent()
1946
+ Laurent Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
1947
+ sage: constructed_el = QF.construct_quasi_form(qexp)
1948
+ sage: constructed_el.parent()
1949
+ QuasiWeakModularForms(n=8, k=10/3, ep=-1) over Integer Ring
1950
+ sage: el == constructed_el
1951
+ True
1952
+
1953
+ If a q_basis is available the construction uses a different algorithm which we also check::
1954
+
1955
+ sage: basis = QF.q_basis(min_exp=-1)
1956
+ sage: QF(qexp) == constructed_el
1957
+ True
1958
+
1959
+ sage: MF = ModularForms(k=36)
1960
+ sage: el2 = MF.quasi_part_gens(min_exp=2)[1]
1961
+ sage: prec = MF.required_laurent_prec(min_exp=2)
1962
+ sage: prec
1963
+ 4
1964
+ sage: qexp2 = el2.q_expansion(prec=prec + 1)
1965
+ sage: qexp2
1966
+ q^3 - 1/(24*d)*q^4 + O(q^5)
1967
+ sage: qexp2.parent()
1968
+ Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
1969
+ sage: constructed_el2 = MF.construct_quasi_form(qexp2)
1970
+ sage: constructed_el2.parent()
1971
+ ModularForms(n=3, k=36, ep=1) over Integer Ring
1972
+ sage: el2 == constructed_el2
1973
+ True
1974
+
1975
+ sage: QF = QuasiModularForms(k=2)
1976
+ sage: q = QF.get_q()
1977
+ sage: qexp3 = 1 + O(q)
1978
+ sage: QF(qexp3)
1979
+ 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 + O(q^5)
1980
+ sage: QF(qexp3) == QF.E2()
1981
+ True
1982
+
1983
+ sage: QF = QuasiWeakModularForms(n=infinity, k=2, ep=-1)
1984
+ sage: el4 = QF.f_i() + QF.f_i()^3/QF.E4()
1985
+ sage: prec = QF.required_laurent_prec(order_1=-1)
1986
+ sage: qexp4 = el4.q_expansion(prec=prec)
1987
+ sage: qexp4
1988
+ 2 - 7/(4*d)*q + 195/(256*d^2)*q^2 - 903/(4096*d^3)*q^3 + 41987/(1048576*d^4)*q^4 - 181269/(33554432*d^5)*q^5 + O(q^6)
1989
+ sage: QF.construct_quasi_form(qexp4, check=False) == el4
1990
+ False
1991
+ sage: QF.construct_quasi_form(qexp4, order_1=-1) == el4
1992
+ True
1993
+
1994
+ sage: QF = QuasiCuspForms(n=8, k=22/3, ep=-1)
1995
+ sage: el = QF(QF.f_inf()*QF.E2())
1996
+ sage: qexp = el.q_expansion_fixed_d(d_num_prec=1000)
1997
+ sage: qexp.parent()
1998
+ Power Series Ring in q over Real Field with 1000 bits of precision
1999
+ sage: QF.construct_quasi_form(qexp, rationalize=True) == el
2000
+ True
2001
+ """
2002
+
2003
+ base_ring = laurent_series.base_ring()
2004
+ if isinstance(base_ring.base(), PolynomialRing_generic):
2005
+ if not (self.coeff_ring().has_coerce_map_from(base_ring)):
2006
+ raise ValueError("The Laurent coefficients don't coerce into the coefficient ring of self!")
2007
+ elif rationalize:
2008
+ laurent_series = self.rationalize_series(laurent_series)
2009
+ else:
2010
+ raise ValueError("The Laurent coefficients are not in the proper form yet. Try rationalize_series(laurent_series) beforehand (experimental).")
2011
+
2012
+ prec = min(laurent_series.prec(), laurent_series.exponents()[-1] + 1)
2013
+
2014
+ min_exp1 = laurent_series.exponents()[0]
2015
+ (min_exp, order_1) = self._canonical_min_exp(min_exp1, order_1)
2016
+
2017
+ if (min_exp != min_exp1):
2018
+ raise ValueError("Due to the behavior at infinity the given Laurent series cannot possibly be an element of {}".format(self))
2019
+
2020
+ # if a q_basis is available we can construct the form much faster
2021
+ if (self.q_basis.is_in_cache(min_exp=min_exp, order_1=order_1)):
2022
+ basis = self.q_basis(min_exp=min_exp, order_1=order_1)
2023
+ size = len(basis)
2024
+
2025
+ if (prec < min_exp + size):
2026
+ raise ValueError("Insufficient precision: {} < {}!".format(laurent_series.prec(), min_exp + size))
2027
+
2028
+ b = vector(self.coeff_ring(), [laurent_series[m] for m in range(min_exp, min_exp + len(basis))])
2029
+
2030
+ el = self(sum([b[k]*basis[k] for k in range(len(basis))]))
2031
+ else:
2032
+ A = self._quasi_form_matrix(min_exp=min_exp, order_1=order_1)
2033
+ row_size = A.dimensions()[0]
2034
+
2035
+ if (prec < min_exp + row_size):
2036
+ raise ValueError("Insufficient precision: {} < {}!".format(laurent_series.prec(), min_exp + row_size))
2037
+
2038
+ b = vector(self.coeff_ring(), [laurent_series[m] for m in range(min_exp, min_exp + row_size)])
2039
+ try:
2040
+ coord_vector = A.solve_right(b)
2041
+ except ValueError:
2042
+ raise ValueError("The Laurent series {} does not correspond to a (quasi) form of {}".format(laurent_series, self.reduce_type(["quasi", "weak"])))
2043
+
2044
+ order_inf = self._l1 - order_1
2045
+
2046
+ # We have to add + 1 to get a correct upper bound in all cases
2047
+ # since corresponding weak space might have a higher l1 (+1) than
2048
+ # ``self``, even if the weight is smaller
2049
+ max_exp = order_inf + 1
2050
+ basis = self.quasi_part_gens(min_exp=min_exp, max_exp=max_exp, order_1=order_1)
2051
+
2052
+ el = self(sum([coord_vector[k]*basis[k] for k in range(len(coord_vector))]))
2053
+
2054
+ if (check):
2055
+ if (el.q_expansion(prec=prec) != laurent_series):
2056
+ raise ValueError("The Laurent series {} does not correspond to a form of {}".format(laurent_series, self.reduce_type(["quasi", "weak"])))
2057
+
2058
+ return el
2059
+
2060
+ @cached_method
2061
+ def q_basis(self, m=None, min_exp=0, order_1=ZZ.zero()):
2062
+ r"""
2063
+ Try to return a (basis) element of ``self`` with a Laurent series of the form
2064
+ ``q^m + O(q^N)``, where ``N=self.required_laurent_prec(min_exp)``.
2065
+
2066
+ If ``m==None`` the whole basis (with varying ``m``'s) is returned if it exists.
2067
+
2068
+ INPUT:
2069
+
2070
+ - ``m`` -- integer, indicating the desired initial Laurent exponent
2071
+ of the element. If ``m==None`` (default) then the whole basis is
2072
+ returned.
2073
+
2074
+ - ``min_exp`` -- integer (default: 0); the minimal Laurent exponent
2075
+ (for each quasi part) of the subspace of ``self`` which should be
2076
+ considered
2077
+
2078
+ - ``order_1`` -- a lower bound for the order at ``-1`` of all quasi
2079
+ parts of the subspace (default: 0). If ``n!=infinity`` this parameter
2080
+ is ignored.
2081
+
2082
+ OUTPUT:
2083
+
2084
+ The corresponding basis (if ``m==None``) resp. the corresponding basis vector (if ``m!=None``).
2085
+ If the basis resp. element doesn't exist an exception is raised.
2086
+
2087
+ EXAMPLES::
2088
+
2089
+ sage: from sage.modular.modform_hecketriangle.space import QuasiWeakModularForms, ModularForms, QuasiModularForms
2090
+ sage: QF = QuasiWeakModularForms(n=8, k=10/3, ep=-1)
2091
+ sage: QF.default_prec(QF.required_laurent_prec(min_exp=-1))
2092
+ sage: q_basis = QF.q_basis(min_exp=-1)
2093
+ sage: q_basis
2094
+ [q^-1 + O(q^5), 1 + O(q^5), q + O(q^5), q^2 + O(q^5), q^3 + O(q^5), q^4 + O(q^5)]
2095
+ sage: QF.q_basis(m=-1, min_exp=-1)
2096
+ q^-1 + O(q^5)
2097
+
2098
+ sage: MF = ModularForms(k=36)
2099
+ sage: MF.q_basis() == list(MF.gens())
2100
+ True
2101
+
2102
+ sage: QF = QuasiModularForms(k=6)
2103
+ sage: QF.required_laurent_prec()
2104
+ 3
2105
+ sage: QF.q_basis()
2106
+ [1 - 20160*q^3 - 158760*q^4 + O(q^5), q - 60*q^3 - 248*q^4 + O(q^5), q^2 + 8*q^3 + 30*q^4 + O(q^5)]
2107
+
2108
+ sage: QF = QuasiWeakModularForms(n=infinity, k=-2, ep=-1)
2109
+ sage: QF.q_basis(order_1=-1)
2110
+ [1 - 168*q^2 + 2304*q^3 - 19320*q^4 + O(q^5),
2111
+ q - 18*q^2 + 180*q^3 - 1316*q^4 + O(q^5)]
2112
+ """
2113
+ if (not self.is_weakly_holomorphic()):
2114
+ from warnings import warn
2115
+ warn("This function only determines elements / a basis of (quasi) weakly modular forms!")
2116
+
2117
+ (min_exp, order_1) = self._canonical_min_exp(min_exp, order_1)
2118
+ order_inf = self._l1 - order_1
2119
+
2120
+ if (m is None):
2121
+ A = self._quasi_form_matrix(min_exp=min_exp, order_1=order_1)
2122
+
2123
+ # If A is square it should automatically be invertible (by the previous procedures)
2124
+ if (A.is_square()):
2125
+ B = A.inverse()
2126
+
2127
+ max_exp = order_inf + 1
2128
+ basis = self.quasi_part_gens(min_exp=min_exp, max_exp=max_exp, order_1=order_1)
2129
+
2130
+ column_len = A.dimensions()[1]
2131
+ q_basis = []
2132
+ for k in range(column_len):
2133
+ el = self(sum([B[l][k] * basis[l] for l in range(column_len)]))
2134
+ q_basis += [el]
2135
+
2136
+ return q_basis
2137
+ else:
2138
+ raise ValueError("Unfortunately a q_basis doesn't exist in this case (this is rare/interesting, please report)")
2139
+ else:
2140
+ if (m < min_exp):
2141
+ raise ValueError("Index out of range: m={} < {}=min_exp".format(m, min_exp))
2142
+
2143
+ # If the whole basis is available, then use it
2144
+ if (self.q_basis.is_in_cache(min_exp=min_exp, order_1=order_1)):
2145
+ q_basis = self.q_basis(min_exp=min_exp, order_1=order_1)
2146
+
2147
+ column_len = len(q_basis)
2148
+ if (m >= column_len + min_exp):
2149
+ raise ValueError("Index out of range: m={} >= {}=dimension + min_exp".format(m, column_len + min_exp))
2150
+
2151
+ return q_basis[m - min_exp]
2152
+
2153
+ row_len = self.required_laurent_prec(min_exp=min_exp, order_1=order_1) - min_exp
2154
+ if (m >= row_len + min_exp):
2155
+ raise ValueError("Index out of range: m={} >= {}=required_precision + min_exp".format(m, row_len + min_exp))
2156
+
2157
+ A = self._quasi_form_matrix(min_exp=min_exp, order_1=order_1)
2158
+ b = vector(self.coeff_ring(), row_len)
2159
+ b[m - min_exp] = 1
2160
+ try:
2161
+ coord_vector = A.solve_right(b)
2162
+ except ValueError:
2163
+ raise ValueError("Unfortunately the q_basis vector (m={}, min_exp={}) doesn't exist in this case (this is rare/interesting, please report)".format(m, min_exp))
2164
+
2165
+ max_exp = order_inf + 1
2166
+ basis = self.quasi_part_gens(min_exp=min_exp, max_exp=max_exp, order_1=order_1)
2167
+
2168
+ column_len = A.dimensions()[1]
2169
+ return self(sum([coord_vector[l] * basis[l]
2170
+ for l in range(column_len)]))
2171
+
2172
+ def rationalize_series(self, laurent_series, coeff_bound=1e-10, denom_factor=ZZ(1)):
2173
+ r"""
2174
+ Try to return a Laurent series with coefficients in ``self.coeff_ring()``
2175
+ that matches the given Laurent series.
2176
+
2177
+ We give our best but there is absolutely no guarantee that it will work!
2178
+
2179
+ INPUT:
2180
+
2181
+ - ``laurent_series`` -- a Laurent series. If the Laurent coefficients
2182
+ already coerce into ``self.coeff_ring()`` with a formal parameter
2183
+ then the Laurent series is returned as is.
2184
+
2185
+ Otherwise it is assumed that the series is normalized in the sense
2186
+ that the first non-trivial coefficient is a power of ``d`` (e.g.
2187
+ ``1``).
2188
+
2189
+ - ``coeff_bound`` -- either ``None`` resp. ``0`` or a positive real
2190
+ number (default: ``1e-10``). If specified ``coeff_bound`` gives a
2191
+ lower bound for the size of the initial Laurent coefficients. If a
2192
+ coefficient is smaller it is assumed to be zero.
2193
+
2194
+ For calculations with very small coefficients (less than ``1e-10``)
2195
+ ``coeff_bound`` should be set to something even smaller or just ``0``.
2196
+
2197
+ Non-exact calculations often produce nonzero coefficients which are
2198
+ supposed to be zero. In those cases this parameter helps a lot.
2199
+
2200
+ - ``denom_factor`` -- integer (default: 1) whose factor might occur in
2201
+ the denominator of the given Laurent coefficients (in addition to
2202
+ naturally occurring factors).
2203
+
2204
+ OUTPUT:
2205
+
2206
+ A Laurent series over ``self.coeff_ring()`` corresponding to the given
2207
+ Laurent series.
2208
+
2209
+ EXAMPLES::
2210
+
2211
+ sage: from sage.modular.modform_hecketriangle.space import WeakModularForms, ModularForms, QuasiCuspForms
2212
+ sage: WF = WeakModularForms(n=14)
2213
+ sage: qexp = WF.J_inv().q_expansion_fixed_d(d_num_prec=1000)
2214
+ sage: qexp.parent()
2215
+ Laurent Series Ring in q over Real Field with 1000 bits of precision
2216
+ sage: qexp_int = WF.rationalize_series(qexp)
2217
+ sage: qexp_int.add_bigoh(3)
2218
+ d*q^-1 + 37/98 + 2587/(38416*d)*q + 899/(117649*d^2)*q^2 + O(q^3)
2219
+ sage: qexp_int == WF.J_inv().q_expansion()
2220
+ True
2221
+ sage: WF.rationalize_series(qexp_int) == qexp_int
2222
+ True
2223
+ sage: WF(qexp_int) == WF.J_inv()
2224
+ True
2225
+
2226
+ sage: WF.rationalize_series(qexp.parent()(1))
2227
+ 1
2228
+ sage: WF.rationalize_series(qexp_int.parent()(1)).parent()
2229
+ Laurent Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
2230
+
2231
+ sage: MF = ModularForms(n=infinity, k=4)
2232
+ sage: qexp = MF.E4().q_expansion_fixed_d()
2233
+ sage: qexp.parent()
2234
+ Power Series Ring in q over Rational Field
2235
+ sage: qexp_int = MF.rationalize_series(qexp)
2236
+ sage: qexp_int.parent()
2237
+ Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
2238
+ sage: qexp_int == MF.E4().q_expansion()
2239
+ True
2240
+ sage: MF.rationalize_series(qexp_int) == qexp_int
2241
+ True
2242
+ sage: MF(qexp_int) == MF.E4()
2243
+ True
2244
+
2245
+ sage: QF = QuasiCuspForms(n=8, k=22/3, ep=-1)
2246
+ sage: el = QF(QF.f_inf()*QF.E2())
2247
+ sage: qexp = el.q_expansion_fixed_d(d_num_prec=1000)
2248
+ sage: qexp.parent()
2249
+ Power Series Ring in q over Real Field with 1000 bits of precision
2250
+ sage: qexp_int = QF.rationalize_series(qexp)
2251
+ sage: qexp_int.parent()
2252
+ Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
2253
+ sage: qexp_int == el.q_expansion()
2254
+ True
2255
+ sage: QF.rationalize_series(qexp_int) == qexp_int
2256
+ True
2257
+ sage: QF(qexp_int) == el
2258
+ True
2259
+ """
2260
+
2261
+ from sage.misc.misc_c import prod
2262
+ from sage.rings.fast_arith import prime_range
2263
+ from warnings import warn
2264
+
2265
+ denom_factor = ZZ(denom_factor)
2266
+ base_ring = laurent_series.base_ring()
2267
+ series_prec = laurent_series.prec()
2268
+
2269
+ # If the coefficients already coerce to our coefficient ring
2270
+ # and are in polynomial form we simply return the Laurent series
2271
+ if (isinstance(base_ring.base(), PolynomialRing_generic)):
2272
+ if (self.coeff_ring().has_coerce_map_from(base_ring)):
2273
+ return laurent_series
2274
+ else:
2275
+ raise ValueError("The Laurent coefficients don't coerce into the coefficient ring of self!")
2276
+ # Else the case that the Laurent series is exact but the group is non-arithmetic
2277
+ # shouldn't occur (except for trivial cases)
2278
+ elif (base_ring.is_exact() and not self.group().is_arithmetic()):
2279
+ prec = self.default_num_prec()
2280
+ dvalue = self.group().dvalue().n(prec)
2281
+ # For arithmetic groups the coefficients are exact though (so is d)
2282
+ elif (base_ring.is_exact()):
2283
+ prec = self.default_num_prec()
2284
+ dvalue = self.group().dvalue()
2285
+ else:
2286
+ prec = laurent_series.base_ring().prec()
2287
+ dvalue = self.group().dvalue().n(prec)
2288
+
2289
+ # This messes up doctests! :-(
2290
+ warn("Using an experimental rationalization of coefficients, please check the result for correctness!")
2291
+
2292
+ d = self.get_d()
2293
+ q = self.get_q()
2294
+
2295
+ if (not base_ring.is_exact() and coeff_bound):
2296
+ coeff_bound = base_ring(coeff_bound)
2297
+ num_q = laurent_series.parent().gen()
2298
+ laurent_series = sum([laurent_series[i]*num_q**i for i in range(laurent_series.exponents()[0], laurent_series.exponents()[-1]+1) if laurent_series[i].abs() > coeff_bound]).add_bigoh(series_prec)
2299
+
2300
+ first_exp = laurent_series.exponents()[0]
2301
+ first_coeff = laurent_series[first_exp]
2302
+ d_power = (first_coeff.abs().n(prec).log()/dvalue.n(prec).log()).round()
2303
+
2304
+ if (first_coeff < 0):
2305
+ return -self.rationalize_series(-laurent_series, coeff_bound=coeff_bound)
2306
+ elif (first_exp + d_power != 0):
2307
+ cor_factor = dvalue**(-(first_exp + d_power))
2308
+ return d**(first_exp + d_power) * self.rationalize_series(cor_factor * laurent_series, coeff_bound=coeff_bound)
2309
+ else:
2310
+ if (base_ring.is_exact() and self.group().is_arithmetic()):
2311
+ tolerance = 0
2312
+ else:
2313
+ tolerance = 10*ZZ(1).n(prec).ulp()
2314
+
2315
+ if (first_coeff * dvalue**first_exp - ZZ(1)) > tolerance:
2316
+ raise ValueError("The Laurent series is not normalized correctly!")
2317
+
2318
+ # TODO: This is not a good enough estimate, see e.g. E12
2319
+ # (however for exact base rings + arithmetic groups we don't need it)
2320
+ def denominator_estimate(m):
2321
+ cor_exp = max(-first_exp, 0)
2322
+ m += cor_exp
2323
+
2324
+ if self.group().is_arithmetic():
2325
+ return ZZ(1/dvalue)**m
2326
+
2327
+ hecke_n = self.hecke_n()
2328
+ bad_factors = [fac for fac in Integer(m).factorial().factor() if (fac[0] % hecke_n) not in [1, hecke_n-1] and fac[0] > 2]
2329
+ bad_factorial = prod([fac[0]**fac[1] for fac in bad_factors])
2330
+
2331
+ return ZZ(2**(6*m) * hecke_n**(2*m) * prod([ p**m for p in prime_range(m+1) if hecke_n % p == 0 and p > 2 ]) * bad_factorial)**(cor_exp + 1)
2332
+
2333
+ def rationalize_coefficient(coeff, m):
2334
+ # TODO: figure out a correct bound for the required precision
2335
+ if (not self.group().is_arithmetic() and denominator_estimate(m).log(2).n().ceil() > prec):
2336
+ warn("The precision from coefficient m={} on is too low!".format(m))
2337
+
2338
+ rational_coeff = coeff * dvalue**m
2339
+
2340
+ if (base_ring.is_exact() and self.group().is_arithmetic() and rational_coeff in QQ):
2341
+ rational_coeff = QQ(rational_coeff)
2342
+ else:
2343
+ int_estimate = denominator_estimate(m) * denom_factor * rational_coeff
2344
+ rational_coeff = int_estimate.round() / denominator_estimate(m) / denom_factor
2345
+
2346
+ return rational_coeff / d**m
2347
+
2348
+ return sum([rationalize_coefficient(laurent_series[m], m) * q**m
2349
+ for m in range(first_exp, laurent_series.exponents()[-1] + 1)]).add_bigoh(series_prec)
2350
+
2351
+ # DEFAULT METHODS (should be overwritten in concrete classes)
2352
+
2353
+ def _an_element_(self):
2354
+ r"""
2355
+ Return an element of ``self``.
2356
+
2357
+ EXAMPLES::
2358
+
2359
+ sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms
2360
+ sage: el = QuasiMeromorphicModularForms(k=2, ep=-1).an_element()
2361
+ sage: el.parent()
2362
+ QuasiMeromorphicModularForms(n=3, k=2, ep=-1) over Integer Ring
2363
+ sage: el.is_zero()
2364
+ True
2365
+ sage: el
2366
+ O(q^5)
2367
+ """
2368
+ # this seems ok, so might as well leave it as is for everything
2369
+ return self(ZZ.zero())
2370
+ # return self.F_simple()
2371
+
2372
+ @cached_method
2373
+ def dimension(self):
2374
+ r"""
2375
+ Return the dimension of ``self``.
2376
+
2377
+ .. NOTE::
2378
+
2379
+ This method should be overloaded by subclasses.
2380
+
2381
+ EXAMPLES::
2382
+
2383
+ sage: from sage.modular.modform_hecketriangle.space import QuasiMeromorphicModularForms
2384
+ sage: QuasiMeromorphicModularForms(k=2, ep=-1).dimension()
2385
+ +Infinity
2386
+ """
2387
+
2388
+ return infinity
2389
+
2390
+ def rank(self):
2391
+ r"""
2392
+ Return the rank of ``self``.
2393
+
2394
+ EXAMPLES::
2395
+
2396
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
2397
+ sage: MF = ModularForms(n=4, k=24, ep=-1)
2398
+ sage: MF.rank()
2399
+ 3
2400
+ sage: MF.subspace([MF.gen(0), MF.gen(2)]).rank()
2401
+ 2
2402
+ """
2403
+
2404
+ return self.dimension()
2405
+
2406
+ def degree(self):
2407
+ r"""
2408
+ Return the degree of ``self``.
2409
+
2410
+ EXAMPLES::
2411
+
2412
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
2413
+ sage: MF = ModularForms(n=4, k=24, ep=-1)
2414
+ sage: MF.degree()
2415
+ 3
2416
+ sage: MF.subspace([MF.gen(0), MF.gen(2)]).degree() # defined in subspace.py
2417
+ 3
2418
+ """
2419
+
2420
+ return self.dimension()
2421
+
2422
+ def coordinate_vector(self, v):
2423
+ r"""
2424
+ This method should be overloaded by subclasses.
2425
+
2426
+ Return the coordinate vector of the element ``v``
2427
+ with respect to ``self.gens()``.
2428
+
2429
+ NOTE:
2430
+
2431
+ Elements use this method (from their parent)
2432
+ to calculate their coordinates.
2433
+
2434
+ INPUT:
2435
+
2436
+ - ``v`` -- an element of ``self``
2437
+
2438
+ EXAMPLES::
2439
+
2440
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
2441
+ sage: MF = ModularForms(n=4, k=24, ep=-1)
2442
+ sage: MF.coordinate_vector(MF.gen(0)).parent() # defined in space.py
2443
+ Vector space of dimension 3 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
2444
+ sage: MF.coordinate_vector(MF.gen(0)) # defined in space.py
2445
+ (1, 0, 0)
2446
+ sage: subspace = MF.subspace([MF.gen(0), MF.gen(2)])
2447
+ sage: subspace.coordinate_vector(subspace.gen(0)).parent() # defined in subspace.py
2448
+ Vector space of dimension 2 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
2449
+ sage: subspace.coordinate_vector(subspace.gen(0)) # defined in subspace.py
2450
+ (1, 0)
2451
+ """
2452
+
2453
+ raise NotImplementedError("No coordinate vector is implemented yet for {}!".format(self))
2454
+
2455
+ @cached_method
2456
+ def ambient_coordinate_vector(self, v):
2457
+ r"""
2458
+ Return the coordinate vector of the element ``v``
2459
+ in ``self.module()`` with respect to the basis
2460
+ from ``self.ambient_space``.
2461
+
2462
+ NOTE:
2463
+
2464
+ Elements use this method (from their parent)
2465
+ to calculate their coordinates.
2466
+
2467
+ INPUT:
2468
+
2469
+ - ``v`` -- an element of ``self``
2470
+
2471
+ EXAMPLES::
2472
+
2473
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
2474
+ sage: MF = ModularForms(n=4, k=24, ep=-1)
2475
+ sage: MF.ambient_coordinate_vector(MF.gen(0)).parent()
2476
+ Vector space of dimension 3 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
2477
+ sage: MF.ambient_coordinate_vector(MF.gen(0))
2478
+ (1, 0, 0)
2479
+ sage: subspace = MF.subspace([MF.gen(0), MF.gen(2)])
2480
+ sage: subspace.ambient_coordinate_vector(subspace.gen(0)).parent()
2481
+ Vector space of degree 3 and dimension 2 over Fraction Field of Univariate Polynomial Ring in d over Integer Ring
2482
+ Basis matrix:
2483
+ [1 0 0]
2484
+ [0 0 1]
2485
+ sage: subspace.ambient_coordinate_vector(subspace.gen(0))
2486
+ (1, 0, 0)
2487
+ """
2488
+
2489
+ return self.module()(self.ambient_space().coordinate_vector(v))
2490
+
2491
+ def gens(self) -> tuple:
2492
+ r"""
2493
+ This method should be overloaded by subclasses.
2494
+
2495
+ Return a basis of ``self`` as a tuple.
2496
+
2497
+ Note that the coordinate vector of elements of ``self``
2498
+ are with respect to this basis.
2499
+
2500
+ EXAMPLES::
2501
+
2502
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
2503
+ sage: ModularForms(k=12).gens() # defined in space.py
2504
+ (1 + 196560*q^2 + 16773120*q^3 + 398034000*q^4 + O(q^5),
2505
+ q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5))
2506
+ """
2507
+ raise NotImplementedError(f"No generators are implemented yet for {self}!")
2508
+
2509
+ def gen(self, k=0):
2510
+ r"""
2511
+ Return the ``k``-th basis element of ``self``
2512
+ if possible (default: ``k=0``).
2513
+
2514
+ EXAMPLES::
2515
+
2516
+ sage: from sage.modular.modform_hecketriangle.space import ModularForms
2517
+ sage: ModularForms(k=12).gen(1).parent()
2518
+ ModularForms(n=3, k=12, ep=1) over Integer Ring
2519
+ sage: ModularForms(k=12).gen(1)
2520
+ q - 24*q^2 + 252*q^3 - 1472*q^4 + O(q^5)
2521
+ """
2522
+
2523
+ k = ZZ(k)
2524
+ if k >= 0 and k < self.dimension():
2525
+ return self.gens()[k]
2526
+ else:
2527
+ raise ValueError("Invalid index: k={} does not satisfy 0 <= k <= {}!".format(k, self.dimension()))