passagemath-schemes 10.6.40__cp314-cp314-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.

Potentially problematic release.


This version of passagemath-schemes might be problematic. Click here for more details.

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