passagemath-schemes 10.8.1a4__cp314-cp314t-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.8.1a4.dist-info/METADATA +203 -0
  7. passagemath_schemes-10.8.1a4.dist-info/METADATA.bak +204 -0
  8. passagemath_schemes-10.8.1a4.dist-info/RECORD +312 -0
  9. passagemath_schemes-10.8.1a4.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.8.1a4.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9556 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2578 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +727 -0
  29. sage/lfunctions/pari.py +971 -0
  30. sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5132 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +414 -0
  34. sage/modular/abvar/abvar_newform.py +246 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +187 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +721 -0
  40. sage/modular/abvar/homspace.py +989 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +741 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1406 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +361 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +659 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1491 -0
  57. sage/modular/arithgroup/congroup_generic.py +630 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +266 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1067 -0
  61. sage/modular/arithgroup/tests.py +425 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3736 -0
  64. sage/modular/btquotients/pautomorphicform.py +2564 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1107 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +571 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1076 -0
  77. sage/modular/hecke/algebra.py +725 -0
  78. sage/modular/hecke/all.py +19 -0
  79. sage/modular/hecke/ambient_module.py +994 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +302 -0
  82. sage/modular/hecke/hecke_operator.py +736 -0
  83. sage/modular/hecke/homspace.py +185 -0
  84. sage/modular/hecke/module.py +1744 -0
  85. sage/modular/hecke/morphism.py +139 -0
  86. sage/modular/hecke/submodule.py +970 -0
  87. sage/modular/hypergeometric_misc.cpython-314t-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2020 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1070 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +817 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +120 -0
  101. sage/modular/modform/ambient_g1.py +199 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +487 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4105 -0
  108. sage/modular/modform/half_integral.py +154 -0
  109. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  110. sage/modular/modform/j_invariant.py +47 -0
  111. sage/modular/modform/l_series_gross_zagier.py +127 -0
  112. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314t-darwin.so +0 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  114. sage/modular/modform/notes.py +45 -0
  115. sage/modular/modform/numerical.py +514 -0
  116. sage/modular/modform/periods.py +14 -0
  117. sage/modular/modform/ring.py +1257 -0
  118. sage/modular/modform/space.py +1859 -0
  119. sage/modular/modform/submodule.py +118 -0
  120. sage/modular/modform/tests.py +64 -0
  121. sage/modular/modform/theta.py +110 -0
  122. sage/modular/modform/vm_basis.py +380 -0
  123. sage/modular/modform/weight1.py +221 -0
  124. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  125. sage/modular/modform_hecketriangle/abstract_space.py +2527 -0
  126. sage/modular/modform_hecketriangle/all.py +30 -0
  127. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  128. sage/modular/modform_hecketriangle/constructor.py +416 -0
  129. sage/modular/modform_hecketriangle/element.py +351 -0
  130. sage/modular/modform_hecketriangle/functors.py +752 -0
  131. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  132. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  133. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3349 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1426 -0
  135. sage/modular/modform_hecketriangle/readme.py +1214 -0
  136. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  137. sage/modular/modform_hecketriangle/space.py +1037 -0
  138. sage/modular/modform_hecketriangle/subspace.py +423 -0
  139. sage/modular/modsym/all.py +17 -0
  140. sage/modular/modsym/ambient.py +3844 -0
  141. sage/modular/modsym/boundary.py +1420 -0
  142. sage/modular/modsym/element.py +336 -0
  143. sage/modular/modsym/g1list.py +178 -0
  144. sage/modular/modsym/ghlist.py +182 -0
  145. sage/modular/modsym/hecke_operator.py +73 -0
  146. sage/modular/modsym/manin_symbol.cpython-314t-darwin.so +0 -0
  147. sage/modular/modsym/manin_symbol.pxd +5 -0
  148. sage/modular/modsym/manin_symbol.pyx +497 -0
  149. sage/modular/modsym/manin_symbol_list.py +1291 -0
  150. sage/modular/modsym/modsym.py +400 -0
  151. sage/modular/modsym/modular_symbols.py +384 -0
  152. sage/modular/modsym/p1list_nf.py +1241 -0
  153. sage/modular/modsym/relation_matrix.py +591 -0
  154. sage/modular/modsym/relation_matrix_pyx.cpython-314t-darwin.so +0 -0
  155. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  156. sage/modular/modsym/space.py +2468 -0
  157. sage/modular/modsym/subspace.py +455 -0
  158. sage/modular/modsym/tests.py +376 -0
  159. sage/modular/multiple_zeta.py +2635 -0
  160. sage/modular/multiple_zeta_F_algebra.py +789 -0
  161. sage/modular/overconvergent/all.py +6 -0
  162. sage/modular/overconvergent/genus0.py +1879 -0
  163. sage/modular/overconvergent/hecke_series.py +1187 -0
  164. sage/modular/overconvergent/weightspace.py +776 -0
  165. sage/modular/pollack_stevens/all.py +4 -0
  166. sage/modular/pollack_stevens/distributions.py +874 -0
  167. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  168. sage/modular/pollack_stevens/manin_map.py +856 -0
  169. sage/modular/pollack_stevens/modsym.py +1590 -0
  170. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  171. sage/modular/pollack_stevens/sigma0.py +534 -0
  172. sage/modular/pollack_stevens/space.py +1078 -0
  173. sage/modular/quasimodform/all.py +3 -0
  174. sage/modular/quasimodform/element.py +846 -0
  175. sage/modular/quasimodform/ring.py +826 -0
  176. sage/modular/quatalg/all.py +3 -0
  177. sage/modular/quatalg/brandt.py +1642 -0
  178. sage/modular/ssmod/all.py +8 -0
  179. sage/modular/ssmod/ssmod.py +827 -0
  180. sage/rings/all__sagemath_schemes.py +1 -0
  181. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/binary_form_reduce.py +585 -0
  183. sage/schemes/all.py +41 -0
  184. sage/schemes/berkovich/all.py +6 -0
  185. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  186. sage/schemes/berkovich/berkovich_space.py +700 -0
  187. sage/schemes/curves/affine_curve.py +2924 -0
  188. sage/schemes/curves/all.py +33 -0
  189. sage/schemes/curves/closed_point.py +434 -0
  190. sage/schemes/curves/constructor.py +397 -0
  191. sage/schemes/curves/curve.py +542 -0
  192. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  193. sage/schemes/curves/point.py +463 -0
  194. sage/schemes/curves/projective_curve.py +3203 -0
  195. sage/schemes/curves/weighted_projective_curve.py +106 -0
  196. sage/schemes/curves/zariski_vankampen.py +1931 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +991 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1103 -0
  208. sage/schemes/elliptic_curves/constructor.py +1530 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3971 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +457 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2837 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3249 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4944 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7184 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1663 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7328 -0
  229. sage/schemes/elliptic_curves/height.py +2108 -0
  230. sage/schemes/elliptic_curves/hom.py +1788 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +1084 -0
  232. sage/schemes/elliptic_curves/hom_fractional.py +544 -0
  233. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  234. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  235. sage/schemes/elliptic_curves/hom_sum.py +681 -0
  236. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  237. sage/schemes/elliptic_curves/homset.py +271 -0
  238. sage/schemes/elliptic_curves/isogeny_class.py +1523 -0
  239. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  240. sage/schemes/elliptic_curves/jacobian.py +247 -0
  241. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  242. sage/schemes/elliptic_curves/kraus.py +1014 -0
  243. sage/schemes/elliptic_curves/lseries_ell.py +915 -0
  244. sage/schemes/elliptic_curves/mod5family.py +105 -0
  245. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.cpython-314t-darwin.so +0 -0
  247. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  248. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  249. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  250. sage/schemes/elliptic_curves/padics.py +1816 -0
  251. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.cpython-314t-darwin.so +0 -0
  253. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  254. sage/schemes/elliptic_curves/saturation.py +716 -0
  255. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  256. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  257. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  258. sage/schemes/hyperelliptic_curves/all.py +6 -0
  259. sage/schemes/hyperelliptic_curves/constructor.py +369 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1948 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +936 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  265. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +312 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_generic.py +437 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +878 -0
  271. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  272. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  273. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3863 -0
  274. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  275. sage/schemes/jacobians/all.py +2 -0
  276. sage/schemes/overview.py +161 -0
  277. sage/schemes/plane_conics/all.py +22 -0
  278. sage/schemes/plane_conics/con_field.py +1296 -0
  279. sage/schemes/plane_conics/con_finite_field.py +158 -0
  280. sage/schemes/plane_conics/con_number_field.py +456 -0
  281. sage/schemes/plane_conics/con_rational_field.py +406 -0
  282. sage/schemes/plane_conics/con_rational_function_field.py +581 -0
  283. sage/schemes/plane_conics/constructor.py +249 -0
  284. sage/schemes/plane_quartics/all.py +2 -0
  285. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  286. sage/schemes/plane_quartics/quartic_generic.py +53 -0
  287. sage/schemes/riemann_surfaces/all.py +1 -0
  288. sage/schemes/riemann_surfaces/riemann_surface.py +4177 -0
  289. sage_wheels/share/cremona/cremona_mini.db +0 -0
  290. sage_wheels/share/ellcurves/rank0 +30427 -0
  291. sage_wheels/share/ellcurves/rank1 +31871 -0
  292. sage_wheels/share/ellcurves/rank10 +6 -0
  293. sage_wheels/share/ellcurves/rank11 +6 -0
  294. sage_wheels/share/ellcurves/rank12 +1 -0
  295. sage_wheels/share/ellcurves/rank14 +1 -0
  296. sage_wheels/share/ellcurves/rank15 +1 -0
  297. sage_wheels/share/ellcurves/rank17 +1 -0
  298. sage_wheels/share/ellcurves/rank19 +1 -0
  299. sage_wheels/share/ellcurves/rank2 +2388 -0
  300. sage_wheels/share/ellcurves/rank20 +1 -0
  301. sage_wheels/share/ellcurves/rank21 +1 -0
  302. sage_wheels/share/ellcurves/rank22 +1 -0
  303. sage_wheels/share/ellcurves/rank23 +1 -0
  304. sage_wheels/share/ellcurves/rank24 +1 -0
  305. sage_wheels/share/ellcurves/rank28 +1 -0
  306. sage_wheels/share/ellcurves/rank3 +836 -0
  307. sage_wheels/share/ellcurves/rank4 +10 -0
  308. sage_wheels/share/ellcurves/rank5 +5 -0
  309. sage_wheels/share/ellcurves/rank6 +5 -0
  310. sage_wheels/share/ellcurves/rank7 +5 -0
  311. sage_wheels/share/ellcurves/rank8 +6 -0
  312. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,1257 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.combinat sage.libs.flint sage.libs.pari
3
+ """
4
+ Graded rings of modular forms
5
+
6
+ This module contains functions to find generators for the graded ring of
7
+ modular forms of given level.
8
+
9
+ AUTHORS:
10
+
11
+ - William Stein (2007-08-24): first version
12
+ - David Ayotte (2021-06): implemented category and Parent/Element frameworks
13
+ """
14
+ # ****************************************************************************
15
+ # Copyright (C) 2007 William Stein
16
+ # 2021 David Ayotte
17
+ #
18
+ # This program is free software: you can redistribute it and/or modify
19
+ # it under the terms of the GNU General Public License as published by
20
+ # the Free Software Foundation, either version 2 of the License, or
21
+ # (at your option) any later version.
22
+ # https://www.gnu.org/licenses/
23
+ # ****************************************************************************
24
+
25
+ from random import shuffle
26
+
27
+ from sage.categories.graded_algebras import GradedAlgebras
28
+ from sage.matrix.constructor import Matrix
29
+ from sage.misc.cachefunc import cached_method
30
+ from sage.misc.misc_c import prod
31
+ from sage.misc.verbose import verbose
32
+ from sage.modular.arithgroup.congroup_gamma0 import Gamma0_constructor as Gamma0
33
+ from sage.modular.arithgroup.congroup_generic import CongruenceSubgroupBase
34
+ from sage.rings.integer import Integer
35
+ from sage.rings.integer_ring import ZZ
36
+ from sage.rings.polynomial.multi_polynomial import MPolynomial
37
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
38
+ from sage.rings.polynomial.term_order import TermOrder
39
+ from sage.rings.power_series_poly import PowerSeries_poly
40
+ from sage.rings.rational_field import QQ
41
+ from sage.structure.parent import Parent
42
+ from sage.structure.richcmp import richcmp_method, richcmp
43
+
44
+ from .constructor import ModularForms
45
+ from .element import ModularFormElement, GradedModularFormElement
46
+ from .space import ModularFormsSpace
47
+
48
+
49
+ def _span_of_forms_in_weight(forms, weight, prec,
50
+ stop_dim=None, use_random=False):
51
+ r"""
52
+ Utility function. Given a nonempty list of pairs ``(k,f)``, where `k` is an
53
+ integer and `f` is a power series, and a weight l, return all weight l
54
+ forms obtained by multiplying together the given forms.
55
+
56
+ INPUT:
57
+
58
+ - ``forms`` -- list of pairs `(k, f)` with k an integer and f a power
59
+ series (all over the same base ring)
60
+ - ``weight`` -- integer
61
+ - ``prec`` -- integer (less than or equal to the precision of all the
62
+ forms in ``forms``); precision to use in power series computations
63
+ - ``stop_dim`` -- integer; stop as soon as we have enough forms to span
64
+ a submodule of this rank (a saturated one if the base ring is `\ZZ`).
65
+ Ignored if ``use_random`` is ``False``.
66
+ - ``use_random`` -- which algorithm to use. If ``True``, tries random
67
+ products of the generators of the appropriate weight until a
68
+ large enough submodule is found (determined by ``stop_dim``). If
69
+ ``False``, just tries everything.
70
+
71
+ Note that if the given forms do generate the whole space, then
72
+ ``use_random=True`` will often be quicker (particularly if the weight is
73
+ large); but if the forms don't generate, the randomized algorithm is no
74
+ help and will actually be substantially slower, because it needs to do
75
+ repeated echelon form calls to check if vectors are in a submodule, while
76
+ the non-randomized algorithm just echelonizes one enormous matrix at the
77
+ end.
78
+
79
+ EXAMPLES::
80
+
81
+ sage: import sage.modular.modform.ring as f
82
+ sage: forms = [(4, 240*eisenstein_series_qexp(4, 5)),
83
+ ....: (6, 504*eisenstein_series_qexp(6, 5))]
84
+ sage: f._span_of_forms_in_weight(forms, 12, prec=5)
85
+ Vector space of degree 5 and dimension 2 over Rational Field
86
+ Basis matrix:
87
+ [ 1 0 196560 16773120 398034000]
88
+ [ 0 1 -24 252 -1472]
89
+ sage: f._span_of_forms_in_weight(forms, 24, prec=5)
90
+ Vector space of degree 5 and dimension 3 over Rational Field
91
+ Basis matrix:
92
+ [ 1 0 0 52416000 39007332000]
93
+ [ 0 1 0 195660 12080128]
94
+ [ 0 0 1 -48 1080]
95
+ sage: ModularForms(1, 24).q_echelon_basis(prec=5)
96
+ [1 + 52416000*q^3 + 39007332000*q^4 + O(q^5),
97
+ q + 195660*q^3 + 12080128*q^4 + O(q^5),
98
+ q^2 - 48*q^3 + 1080*q^4 + O(q^5)]
99
+
100
+ Test the alternative randomized algorithm::
101
+
102
+ sage: f._span_of_forms_in_weight(forms, 24, prec=5,
103
+ ....: use_random=True, stop_dim=3)
104
+ Vector space of degree 5 and dimension 3 over Rational Field
105
+ Basis matrix:
106
+ [ 1 0 0 52416000 39007332000]
107
+ [ 0 1 0 195660 12080128]
108
+ [ 0 0 1 -48 1080]
109
+ """
110
+ t = verbose('multiplying forms up to weight %s' % weight)
111
+ # Algorithm: run through the monomials of the appropriate weight, and build
112
+ # up the vector space they span.
113
+
114
+ n = len(forms)
115
+ R = forms[0][1].base_ring()
116
+ V = R ** prec
117
+ W = V.zero_submodule()
118
+ shortforms = [f[1].truncate_powerseries(prec) for f in forms]
119
+
120
+ # List of weights
121
+ from sage.combinat.integer_vector_weighted import WeightedIntegerVectors
122
+ wts = list(WeightedIntegerVectors(weight, [f[0] for f in forms]))
123
+ t = verbose("calculated weight list", t)
124
+ N = len(wts)
125
+
126
+ if use_random:
127
+ if stop_dim is None:
128
+ raise ValueError("stop_dim must be provided if use_random is True")
129
+ shuffle(wts)
130
+
131
+ for c in range(N):
132
+ w = V(prod(shortforms[i]**wts[c][i] for i in range(n)).padded_list(prec))
133
+ if w in W:
134
+ continue
135
+ W = V.span(list(W.gens()) + [w])
136
+ if stop_dim and W.rank() == stop_dim:
137
+ if R != ZZ or W.index_in_saturation() == 1:
138
+ verbose("Succeeded after %s of %s" % (c, N), t)
139
+ return W
140
+ verbose("Nothing worked", t)
141
+ return W
142
+
143
+ G = [V(prod(forms[i][1]**c[i] for i in range(n)).padded_list(prec))
144
+ for c in wts]
145
+ t = verbose(f'found {N} candidates', t)
146
+ W = V.span(G)
147
+ verbose(f'span has dimension {W.rank()}', t)
148
+ return W
149
+
150
+
151
+ @richcmp_method
152
+ class ModularFormsRing(Parent):
153
+ r"""
154
+ The ring of modular forms (of weights 0 or at least 2) for a congruence
155
+ subgroup of `\SL_2(\ZZ)`, with coefficients in a specified base ring.
156
+
157
+ EXAMPLES::
158
+
159
+ sage: ModularFormsRing(Gamma1(13))
160
+ Ring of Modular Forms for Congruence Subgroup Gamma1(13) over Rational Field
161
+ sage: m = ModularFormsRing(4); m
162
+ Ring of Modular Forms for Congruence Subgroup Gamma0(4) over Rational Field
163
+ sage: m.modular_forms_of_weight(2)
164
+ Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(4) of weight 2 over Rational Field
165
+ sage: m.modular_forms_of_weight(10)
166
+ Modular Forms space of dimension 6 for Congruence Subgroup Gamma0(4) of weight 10 over Rational Field
167
+ sage: m == loads(dumps(m))
168
+ True
169
+ sage: m.generators()
170
+ [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10)),
171
+ (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10))]
172
+ sage: m.q_expansion_basis(2,10)
173
+ [1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10),
174
+ q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)]
175
+ sage: m.q_expansion_basis(3,10)
176
+ []
177
+ sage: m.q_expansion_basis(10,10)
178
+ [1 + 10560*q^6 + 3960*q^8 + O(q^10),
179
+ q - 8056*q^7 - 30855*q^9 + O(q^10),
180
+ q^2 - 796*q^6 - 8192*q^8 + O(q^10),
181
+ q^3 + 66*q^7 + 832*q^9 + O(q^10),
182
+ q^4 + 40*q^6 + 528*q^8 + O(q^10),
183
+ q^5 + 20*q^7 + 190*q^9 + O(q^10)]
184
+
185
+ Elements of modular forms ring can be initiated via multivariate polynomials (see :meth:`from_polynomial`)::
186
+
187
+ sage: M = ModularFormsRing(1)
188
+ sage: M.ngens()
189
+ 2
190
+ sage: E4, E6 = polygens(QQ, 'E4, E6')
191
+ sage: M(E4)
192
+ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
193
+ sage: M(E6)
194
+ 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)
195
+ sage: M((E4^3 - E6^2)/1728)
196
+ q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6)
197
+ """
198
+
199
+ Element = GradedModularFormElement
200
+
201
+ def __init__(self, group, base_ring=QQ) -> None:
202
+ r"""
203
+ INPUT:
204
+
205
+ - ``group`` -- a congruence subgroup of `\SL_2(\ZZ)`, or a
206
+ positive integer `N` (interpreted as `\Gamma_0(N)`)
207
+
208
+ - ``base_ring`` -- ring (default: `\QQ`); a base ring, which
209
+ should be `\QQ`, `\ZZ`, or the integers mod `p` for some prime
210
+ `p`
211
+
212
+ TESTS:
213
+
214
+ Check that :issue:`15037` is fixed::
215
+
216
+ sage: ModularFormsRing(3.4)
217
+ Traceback (most recent call last):
218
+ ...
219
+ ValueError: group (=3.40000000000000) should be a congruence subgroup
220
+ sage: ModularFormsRing(Gamma0(2), base_ring=PolynomialRing(ZZ, 'x'))
221
+ Traceback (most recent call last):
222
+ ...
223
+ ValueError: base ring (=Univariate Polynomial Ring in x over Integer Ring) should be QQ, ZZ or a finite prime field
224
+
225
+ ::
226
+
227
+ sage: TestSuite(ModularFormsRing(1)).run()
228
+ sage: TestSuite(ModularFormsRing(Gamma0(6))).run()
229
+ sage: TestSuite(ModularFormsRing(Gamma1(4))).run()
230
+
231
+ .. TODO::
232
+
233
+ - Add graded modular forms over non-trivial Dirichlet character;
234
+ - makes gen_forms returns modular forms over base rings other than `QQ`;
235
+ - implement binary operations between two forms with different groups.
236
+ """
237
+ if isinstance(group, (int, Integer)):
238
+ group = Gamma0(group)
239
+ elif not isinstance(group, CongruenceSubgroupBase):
240
+ raise ValueError("group (=%s) should be a congruence subgroup" % group)
241
+
242
+ if base_ring != ZZ and not base_ring.is_field() and not base_ring.is_finite():
243
+ raise ValueError("base ring (=%s) should be QQ, ZZ or a finite prime field" % base_ring)
244
+
245
+ self.__group = group
246
+ self.__cached_maxweight = ZZ(-1)
247
+ self.__cached_gens = []
248
+ self.__cached_cusp_maxweight = ZZ(-1)
249
+ self.__cached_cusp_gens = []
250
+ cat = GradedAlgebras(base_ring).Commutative()
251
+ Parent.__init__(self, base=base_ring, category=cat)
252
+
253
+ def change_ring(self, base_ring):
254
+ r"""
255
+ Return a ring of modular forms over a new base ring of the same
256
+ congruence subgroup.
257
+
258
+ INPUT:
259
+
260
+ - ``base_ring`` -- a base ring, which should be `\QQ`, `\ZZ`, or
261
+ the integers mod `p` for some prime `p`
262
+
263
+ EXAMPLES::
264
+
265
+ sage: M = ModularFormsRing(11); M
266
+ Ring of Modular Forms for Congruence Subgroup Gamma0(11) over Rational Field
267
+ sage: M.change_ring(Zmod(7))
268
+ Ring of Modular Forms for Congruence Subgroup Gamma0(11) over Ring of integers modulo 7
269
+ sage: M.change_ring(ZZ)
270
+ Ring of Modular Forms for Congruence Subgroup Gamma0(11) over Integer Ring
271
+ """
272
+ return ModularFormsRing(self.group(), base_ring=base_ring)
273
+
274
+ def some_elements(self) -> list:
275
+ r"""
276
+ Return some elements of this ring.
277
+
278
+ EXAMPLES::
279
+
280
+ sage: ModularFormsRing(1).some_elements()
281
+ [1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
282
+ 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]
283
+ """
284
+ return [self(f) for f in self.gen_forms()]
285
+
286
+ def group(self):
287
+ r"""
288
+ Return the congruence subgroup of this ring of modular forms.
289
+
290
+ EXAMPLES::
291
+
292
+ sage: R = ModularFormsRing(Gamma1(13))
293
+ sage: R.group() is Gamma1(13)
294
+ True
295
+ """
296
+ return self.__group
297
+
298
+ def gen(self, i):
299
+ r"""
300
+ Return the `i`-th generator of this ring.
301
+
302
+ INPUT:
303
+
304
+ - ``i`` -- integer
305
+
306
+ OUTPUT: an instance of :class:`~sage.modular.modform.GradedModularFormElement`
307
+
308
+ EXAMPLES::
309
+
310
+ sage: M = ModularFormsRing(1)
311
+ sage: E4 = M.0; E4 # indirect doctest
312
+ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
313
+ sage: E6 = M.1; E6 # indirect doctest
314
+ 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)
315
+ """
316
+ if self.base_ring() is not QQ:
317
+ raise NotImplementedError("the base ring of the given ring of modular form should be QQ")
318
+ return self(self.gen_forms()[i])
319
+
320
+ def ngens(self) -> int:
321
+ r"""
322
+ Return the number of generators of this ring.
323
+
324
+ EXAMPLES::
325
+
326
+ sage: ModularFormsRing(1).ngens()
327
+ 2
328
+ sage: ModularFormsRing(Gamma0(2)).ngens()
329
+ 2
330
+ sage: ModularFormsRing(Gamma1(13)).ngens() # long time
331
+ 33
332
+
333
+ .. WARNING::
334
+
335
+ Computing the number of generators of a graded ring of modular form for a certain
336
+ congruence subgroup can be very long.
337
+ """
338
+ return len(self.gen_forms())
339
+
340
+ def polynomial_ring(self, names, gens=None):
341
+ r"""
342
+ Return a polynomial ring of which this ring of modular forms is
343
+ a quotient.
344
+
345
+ INPUT:
346
+
347
+ - ``names`` -- a list or tuple of names (strings), or a comma
348
+ separated string; consists in the names of the polynomial
349
+ ring variables
350
+ - ``gens`` -- list of modular forms generating this ring
351
+ (default: ``None``); if ``gens`` is ``None`` then the list of
352
+ generators returned by the method
353
+ :meth:`~sage.modular.modform.find_generator.ModularFormsRing.gen_forms`
354
+ is used instead. Note that we do not check if the list is
355
+ indeed a generating set.
356
+
357
+ OUTPUT: a multivariate polynomial ring in the variable
358
+ ``names``. Each variable of the polynomial ring correspond to a
359
+ generator given in the list ``gens`` (following the ordering of
360
+ the list).
361
+
362
+ EXAMPLES::
363
+
364
+ sage: M = ModularFormsRing(1)
365
+ sage: gens = M.gen_forms()
366
+ sage: M.polynomial_ring('E4, E6', gens)
367
+ Multivariate Polynomial Ring in E4, E6 over Rational Field
368
+ sage: M = ModularFormsRing(Gamma0(8))
369
+ sage: gens = M.gen_forms()
370
+ sage: M.polynomial_ring('g', gens)
371
+ Multivariate Polynomial Ring in g0, g1, g2 over Rational Field
372
+
373
+ The degrees of the variables are the weights of the
374
+ corresponding forms::
375
+
376
+ sage: M = ModularFormsRing(1)
377
+ sage: P.<E4, E6> = M.polynomial_ring()
378
+ sage: E4.degree()
379
+ 4
380
+ sage: E6.degree()
381
+ 6
382
+ sage: (E4*E6).degree()
383
+ 10
384
+ """
385
+ if gens is None:
386
+ gens = self.gen_forms()
387
+ degs = [f.weight() for f in gens]
388
+ return PolynomialRing(self.base_ring(), len(gens), names,
389
+ order=TermOrder('wdeglex', degs))
390
+
391
+ def _generators_variables_dictionary(self, poly_parent, gens):
392
+ r"""
393
+ Return a dictionary giving an association between polynomial
394
+ ring generators and generators of modular forms ring.
395
+
396
+ INPUT:
397
+
398
+ - ``poly_parent`` -- a polynomial ring
399
+ - ``gen`` -- list of generators of the modular forms ring
400
+
401
+ TESTS::
402
+
403
+ sage: M = ModularFormsRing(Gamma0(6))
404
+ sage: P = QQ['x, y, z']
405
+ sage: M._generators_variables_dictionary(P, M.gen_forms())
406
+ {z: q^2 - 2*q^3 + 3*q^4 + O(q^6),
407
+ y: q + 5*q^3 - 2*q^4 + 6*q^5 + O(q^6),
408
+ x: 1 + 24*q^3 + O(q^6)}
409
+ """
410
+ if poly_parent.base_ring() != self.base_ring():
411
+ raise ValueError('the base ring of `poly_parent` must be the same as the base ring of the modular forms ring')
412
+ nb_var = poly_parent.ngens()
413
+ nb_gens = self.ngens()
414
+ if nb_var != nb_gens:
415
+ raise ValueError('the number of variables (%s) must be equal to'
416
+ ' the number of generators of the modular forms'
417
+ ' ring (%s)' % (nb_var, self.ngens()))
418
+ return {poly_parent.gen(i): self(gens[i]) for i in range(nb_var)}
419
+
420
+ def from_polynomial(self, polynomial, gens=None):
421
+ r"""
422
+ Return a graded modular form constructed by evaluating a given
423
+ multivariate polynomial at a set of generators.
424
+
425
+ INPUT:
426
+
427
+ - ``polynomial`` -- a multivariate polynomial. The variables
428
+ names of the polynomial should be different from ``'q'``. The
429
+ number of variable of this polynomial should equal the number
430
+ of given generators.
431
+ - ``gens`` -- list of modular forms generating this ring
432
+ (default: ``None``); if ``gens`` is ``None`` then the list of
433
+ generators returned by the method
434
+ :meth:`~sage.modular.modform.find_generator.ModularFormsRing.gen_forms`
435
+ is used instead. Note that we do not check if the list is
436
+ indeed a generating set.
437
+
438
+ OUTPUT: a ``GradedModularFormElement`` given by the polynomial
439
+ relation ``polynomial``
440
+
441
+ EXAMPLES::
442
+
443
+ sage: M = ModularFormsRing(1)
444
+ sage: x,y = polygens(QQ, 'x,y')
445
+ sage: M.from_polynomial(x^2+y^3)
446
+ 2 - 1032*q + 774072*q^2 - 77047584*q^3 - 11466304584*q^4 - 498052467504*q^5 + O(q^6)
447
+ sage: M = ModularFormsRing(Gamma0(6))
448
+ sage: M.ngens()
449
+ 3
450
+ sage: x,y,z = polygens(QQ, 'x,y,z')
451
+ sage: M.from_polynomial(x+y+z)
452
+ 1 + q + q^2 + 27*q^3 + q^4 + 6*q^5 + O(q^6)
453
+ sage: M.0 + M.1 + M.2
454
+ 1 + q + q^2 + 27*q^3 + q^4 + 6*q^5 + O(q^6)
455
+ sage: P = x.parent()
456
+ sage: M.from_polynomial(P(1/2))
457
+ 1/2
458
+
459
+ Note that the number of variables must be equal to the number of
460
+ generators::
461
+
462
+ sage: x, y = polygens(QQ, 'x, y')
463
+ sage: M(x + y)
464
+ Traceback (most recent call last):
465
+ ...
466
+ ValueError: the number of variables (2) must be equal to the number of generators of the modular forms ring (3)
467
+
468
+ TESTS::
469
+
470
+ sage: x,y = polygens(GF(7), 'x, y')
471
+ sage: ModularFormsRing(1, GF(7))(x)
472
+ Traceback (most recent call last):
473
+ ...
474
+ NotImplementedError: conversion from polynomial is not implemented if the base ring is not Q
475
+
476
+ ..TODO::
477
+
478
+ * add conversion for symbolic expressions?
479
+ """
480
+ if not self.base_ring() == QQ: # this comes from the method gens_form
481
+ raise NotImplementedError("conversion from polynomial is not implemented if the base ring is not Q")
482
+ if not isinstance(polynomial, MPolynomial):
483
+ raise TypeError('`polynomial` must be a multivariate polynomial')
484
+ if gens is None:
485
+ gens = self.gen_forms()
486
+ dict = self._generators_variables_dictionary(polynomial.parent(), gens)
487
+ if polynomial.is_constant():
488
+ return self(polynomial.constant_coefficient())
489
+ return polynomial.substitute(dict)
490
+
491
+ def _element_constructor_(self, forms_datum):
492
+ r"""
493
+ Return the graded modular form corresponding to the given data.
494
+
495
+ INPUT:
496
+
497
+ - ``forms_datum`` -- dictionary, list, ModularFormElement,
498
+ GradedModularFormElement, RingElement, or Multivariate polynomial; try
499
+ to coerce ``forms_datum`` into ``self``
500
+
501
+ TESTS::
502
+
503
+ sage: M = ModularFormsRing(1)
504
+ sage: E4 = ModularForms(1,4).0; E6 = ModularForms(1,6).0
505
+ sage: M([E4, E6])
506
+ 2 - 264*q - 14472*q^2 - 116256*q^3 - 515208*q^4 - 1545264*q^5 + O(q^6)
507
+ sage: M([E4, E4])
508
+ 2 + 480*q + 4320*q^2 + 13440*q^3 + 35040*q^4 + 60480*q^5 + O(q^6)
509
+ sage: M({4:E4, 6:E6})
510
+ 2 - 264*q - 14472*q^2 - 116256*q^3 - 515208*q^4 - 1545264*q^5 + O(q^6)
511
+ sage: M(E4)
512
+ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
513
+ sage: x,y = polygens(QQ, 'x,y')
514
+ sage: M(x^2+x^3 + x*y + y^6)
515
+ 4 - 2088*q + 3816216*q^2 - 2296935072*q^3 + 720715388184*q^4 - 77528994304752*q^5 + O(q^6)
516
+ sage: f = ModularForms(3, 10).0
517
+ sage: M(f)
518
+ Traceback (most recent call last):
519
+ ...
520
+ ValueError: the group (Congruence Subgroup Gamma0(3)) and/or the base ring (Rational Field) of the given modular form is not consistent with the base space: Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field
521
+ sage: M = ModularFormsRing(1, base_ring=ZZ)
522
+ sage: M(ModularForms(1,4).0)
523
+ Traceback (most recent call last):
524
+ ...
525
+ ValueError: the group (Modular Group SL(2,Z)) and/or the base ring (Rational Field) of the given modular form is not consistent with the base space: Ring of Modular Forms for Modular Group SL(2,Z) over Integer Ring
526
+ sage: M('x')
527
+ Traceback (most recent call last):
528
+ ...
529
+ TypeError: the defining data structure should be a single modular form, a ring element, a list of modular forms, a multivariate polynomial or a dictionary
530
+ sage: P.<t> = PowerSeriesRing(QQ)
531
+ sage: e = 1 + 240*t + 2160*t^2 + 6720*t^3 + 17520*t^4 + 30240*t^5 + O(t^6)
532
+ sage: ModularFormsRing(1)(e)
533
+ Traceback (most recent call last):
534
+ ...
535
+ NotImplementedError: conversion from q-expansion not yet implemented
536
+ """
537
+ if isinstance(forms_datum, (dict, list)):
538
+ forms_dictionary = forms_datum
539
+ elif isinstance(forms_datum, self.element_class):
540
+ forms_dictionary = forms_datum._forms_dictionary
541
+ elif isinstance(forms_datum, ModularFormElement):
542
+ if self.group().is_subgroup(forms_datum.group()) and self.base_ring().has_coerce_map_from(forms_datum.base_ring()):
543
+ forms_dictionary = {forms_datum.weight(): forms_datum}
544
+ else:
545
+ raise ValueError('the group (%s) and/or the base ring (%s) of the given modular form is not consistent with the base space: %s' % (forms_datum.group(), forms_datum.base_ring(), self))
546
+ elif forms_datum in self.base_ring():
547
+ forms_dictionary = {0: forms_datum}
548
+ elif isinstance(forms_datum, MPolynomial):
549
+ return self.from_polynomial(forms_datum)
550
+ elif isinstance(forms_datum, PowerSeries_poly):
551
+ raise NotImplementedError("conversion from q-expansion not yet implemented")
552
+ else:
553
+ raise TypeError('the defining data structure should be a single modular form, a ring element, a list of modular forms, a multivariate polynomial or a dictionary')
554
+ return self.element_class(self, forms_dictionary)
555
+
556
+ def zero(self):
557
+ r"""
558
+ Return the zero element of this ring.
559
+
560
+ EXAMPLES::
561
+
562
+ sage: M = ModularFormsRing(1)
563
+ sage: zer = M.zero(); zer
564
+ 0
565
+ sage: zer.is_zero()
566
+ True
567
+ sage: E4 = ModularForms(1,4).0; E4
568
+ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
569
+ sage: E4 + zer
570
+ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
571
+ sage: zer * E4
572
+ 0
573
+ sage: E4 * zer
574
+ 0
575
+ """
576
+ return self.element_class(self, {})
577
+
578
+ def one(self):
579
+ r"""
580
+ Return the one element of this ring.
581
+
582
+ EXAMPLES::
583
+
584
+ sage: M = ModularFormsRing(1)
585
+ sage: u = M.one(); u
586
+ 1
587
+ sage: u.is_one()
588
+ True
589
+ sage: u + u
590
+ 2
591
+ sage: E4 = ModularForms(1,4).0; E4
592
+ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
593
+ sage: E4 * u
594
+ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
595
+ """
596
+ return self.element_class(self, {0: self.base_ring().one()})
597
+
598
+ def _coerce_map_from_(self, M):
599
+ r"""
600
+ Return ``True`` if there is a coercion map from ``M`` to this
601
+ ring.
602
+
603
+ TESTS::
604
+
605
+ sage: M = ModularFormsRing(1)
606
+ sage: E6 = ModularForms(1,6).0
607
+ sage: D = ModularForms(1,12).1
608
+ sage: M(D) + E6
609
+ 2 - 282744/691*q + 122757768/691*q^2 + 11521760544/691*q^3 + 274576933512/691*q^4 + 3198130142256/691*q^5 + O(q^6)
610
+ sage: D + M(E6)
611
+ 2 - 282744/691*q + 122757768/691*q^2 + 11521760544/691*q^3 + 274576933512/691*q^4 + 3198130142256/691*q^5 + O(q^6)
612
+ sage: 14 + M(D)
613
+ 15 + 65520/691*q + 134250480/691*q^2 + 11606736960/691*q^3 + 274945048560/691*q^4 + 3199218815520/691*q^5 + O(q^6)
614
+ sage: M(D) + 53
615
+ 54 + 65520/691*q + 134250480/691*q^2 + 11606736960/691*q^3 + 274945048560/691*q^4 + 3199218815520/691*q^5 + O(q^6)
616
+ """
617
+ if isinstance(M, ModularFormsSpace):
618
+ if M.group() == self.group() and self.has_coerce_map_from(M.base_ring()):
619
+ return True
620
+ return self.base_ring().has_coerce_map_from(M)
621
+
622
+ def __richcmp__(self, other, op) -> bool:
623
+ r"""
624
+ Compare ``self`` to ``other``.
625
+
626
+ Rings are equal if and only if their groups and base rings are.
627
+
628
+ EXAMPLES::
629
+
630
+ sage: ModularFormsRing(3) == 3
631
+ False
632
+ sage: ModularFormsRing(Gamma0(3)) == ModularFormsRing(Gamma0(7))
633
+ False
634
+ sage: ModularFormsRing(Gamma0(3)) == ModularFormsRing(Gamma0(3))
635
+ True
636
+ """
637
+ if not isinstance(other, ModularFormsRing):
638
+ return NotImplemented
639
+
640
+ return richcmp((self.group(), self.base_ring()),
641
+ (other.group(), other.base_ring()), op)
642
+
643
+ def _repr_(self) -> str:
644
+ r"""
645
+ Return the string representation of ``self``.
646
+
647
+ EXAMPLES::
648
+
649
+ sage: ModularFormsRing(Gamma0(13))._repr_()
650
+ 'Ring of Modular Forms for Congruence Subgroup Gamma0(13) over Rational Field'
651
+ sage: ModularFormsRing(Gamma1(13), base_ring=ZZ)._repr_()
652
+ 'Ring of Modular Forms for Congruence Subgroup Gamma1(13) over Integer Ring'
653
+ """
654
+ return "Ring of Modular Forms for %s over %s" % (self.group(), self.base_ring())
655
+
656
+ def modular_forms_of_weight(self, weight):
657
+ """
658
+ Return the space of modular forms of the given weight and the
659
+ same congruence subgroup.
660
+
661
+ EXAMPLES::
662
+
663
+ sage: R = ModularFormsRing(13)
664
+ sage: R.modular_forms_of_weight(10)
665
+ Modular Forms space of dimension 11 for Congruence Subgroup Gamma0(13) of weight 10 over Rational Field
666
+ sage: ModularFormsRing(Gamma1(13)).modular_forms_of_weight(3)
667
+ Modular Forms space of dimension 20 for Congruence Subgroup Gamma1(13) of weight 3 over Rational Field
668
+ """
669
+ return ModularForms(self.group(), weight)
670
+
671
+ def generators(self, maxweight=8, prec=10, start_gens=[],
672
+ start_weight=2) -> list:
673
+ r"""
674
+ Return a list of generators of this ring as a list of pairs
675
+ `(k, f)` where `k` is an integer and `f` is a univariate power
676
+ series in `q` corresponding to the `q`-expansion of a modular
677
+ form of weight `k`.
678
+
679
+ More precisely, if `R` is the base ring of self, then this
680
+ function calculates a set of modular forms which generate the
681
+ `R`-algebra of all modular forms of weight up to ``maxweight``
682
+ with coefficients in `R`.
683
+
684
+ INPUT:
685
+
686
+ - ``maxweight`` -- integer (default: 8); check up to this weight
687
+ for generators
688
+
689
+ - ``prec`` -- integer (default: 10); return `q`-expansions to
690
+ this precision
691
+
692
+ - ``start_gens`` -- list (default: ``[]``); list of pairs
693
+ `(k, f)`, or triples `(k, f, F)`, where:
694
+
695
+ - `k` is an integer,
696
+ - `f` is the `q`-expansion of a modular form of weight `k`,
697
+ as a power series over the base ring of self,
698
+ - `F` (if provided) is a modular form object corresponding to F.
699
+
700
+ If this list is nonempty, we find a minimal generating set containing
701
+ these forms. If `F` is not supplied, then `f` needs to have
702
+ sufficiently large precision (an error will be raised if this is not
703
+ the case); otherwise, more terms will be calculated from the modular
704
+ form object `F`.
705
+
706
+ - ``start_weight`` -- integer (default: 2); calculate the graded
707
+ subalgebra of forms of weight at least ``start_weight``
708
+
709
+ OUTPUT:
710
+
711
+ a list of pairs (k, f), where f is the `q`-expansion to precision
712
+ ``prec`` of a modular form of weight k.
713
+
714
+ .. SEEALSO::
715
+
716
+ :meth:`gen_forms`, which does exactly the same thing, but returns
717
+ Sage modular form objects rather than bare power series, and keeps
718
+ track of a lifting to characteristic 0 when the base ring is a
719
+ finite field.
720
+
721
+ .. NOTE::
722
+
723
+ If called with the default values of ``start_gens`` (an empty list)
724
+ and ``start_weight`` (2), the values will be cached for re-use on
725
+ subsequent calls to this function. (This cache is shared with
726
+ :meth:`gen_forms`). If called with non-default values for these
727
+ parameters, caching will be disabled.
728
+
729
+ EXAMPLES::
730
+
731
+ sage: ModularFormsRing(SL2Z).generators()
732
+ [(4, 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + 60480*q^6 + 82560*q^7 + 140400*q^8 + 181680*q^9 + O(q^10)),
733
+ (6, 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 - 4058208*q^6 - 8471232*q^7 - 17047800*q^8 - 29883672*q^9 + O(q^10))]
734
+ sage: s = ModularFormsRing(SL2Z).generators(maxweight=5, prec=3); s
735
+ [(4, 1 + 240*q + 2160*q^2 + O(q^3))]
736
+ sage: s[0][1].parent()
737
+ Power Series Ring in q over Rational Field
738
+
739
+ sage: ModularFormsRing(1).generators(prec=4)
740
+ [(4, 1 + 240*q + 2160*q^2 + 6720*q^3 + O(q^4)),
741
+ (6, 1 - 504*q - 16632*q^2 - 122976*q^3 + O(q^4))]
742
+ sage: ModularFormsRing(2).generators(prec=12)
743
+ [(2, 1 + 24*q + 24*q^2 + 96*q^3 + 24*q^4 + 144*q^5 + 96*q^6 + 192*q^7 + 24*q^8 + 312*q^9 + 144*q^10 + 288*q^11 + O(q^12)),
744
+ (4, 1 + 240*q^2 + 2160*q^4 + 6720*q^6 + 17520*q^8 + 30240*q^10 + O(q^12))]
745
+ sage: ModularFormsRing(4).generators(maxweight=2, prec=20)
746
+ [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + 144*q^10 + 96*q^12 + 192*q^14 + 24*q^16 + 312*q^18 + O(q^20)),
747
+ (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + 12*q^11 + 14*q^13 + 24*q^15 + 18*q^17 + 20*q^19 + O(q^20))]
748
+
749
+ Here we see that for ``\Gamma_0(11)`` taking a basis of forms in weights 2
750
+ and 4 is enough to generate everything up to weight 12 (and probably
751
+ everything else).::
752
+
753
+ sage: v = ModularFormsRing(11).generators(maxweight=12)
754
+ sage: len(v)
755
+ 3
756
+ sage: [k for k, _ in v]
757
+ [2, 2, 4]
758
+ sage: from sage.modular.dims import dimension_modular_forms
759
+ sage: dimension_modular_forms(11,2)
760
+ 2
761
+ sage: dimension_modular_forms(11,4)
762
+ 4
763
+
764
+ For congruence subgroups not containing -1, we miss out some forms since we
765
+ can't calculate weight 1 forms at present, but we can still find generators
766
+ for the ring of forms of weight `\ge 2`::
767
+
768
+ sage: ModularFormsRing(Gamma1(4)).generators(prec=10, maxweight=10)
769
+ [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10)),
770
+ (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)),
771
+ (3, 1 + 12*q^2 + 64*q^3 + 60*q^4 + 160*q^6 + 384*q^7 + 252*q^8 + O(q^10)),
772
+ (3, q + 4*q^2 + 8*q^3 + 16*q^4 + 26*q^5 + 32*q^6 + 48*q^7 + 64*q^8 + 73*q^9 + O(q^10))]
773
+
774
+ Using different base rings will change the generators::
775
+
776
+ sage: ModularFormsRing(Gamma0(13)).generators(maxweight=12, prec=4)
777
+ [(2, 1 + 2*q + 6*q^2 + 8*q^3 + O(q^4)),
778
+ (4, 1 + O(q^4)), (4, q + O(q^4)),
779
+ (4, q^2 + O(q^4)), (4, q^3 + O(q^4)),
780
+ (6, 1 + O(q^4)),
781
+ (6, q + O(q^4))]
782
+ sage: ModularFormsRing(Gamma0(13),base_ring=ZZ).generators(maxweight=12, prec=4)
783
+ [(2, 1 + 2*q + 6*q^2 + 8*q^3 + O(q^4)),
784
+ (4, q + 4*q^2 + 10*q^3 + O(q^4)),
785
+ (4, 2*q^2 + 5*q^3 + O(q^4)),
786
+ (4, q^2 + O(q^4)),
787
+ (4, -2*q^3 + O(q^4)),
788
+ (6, O(q^4)),
789
+ (6, O(q^4)),
790
+ (12, O(q^4))]
791
+ sage: [k for k,f in ModularFormsRing(1, QQ).generators(maxweight=12)]
792
+ [4, 6]
793
+ sage: [k for k,f in ModularFormsRing(1, ZZ).generators(maxweight=12)]
794
+ [4, 6, 12]
795
+ sage: [k for k,f in ModularFormsRing(1, Zmod(5)).generators(maxweight=12)]
796
+ [4, 6]
797
+ sage: [k for k,f in ModularFormsRing(1, Zmod(2)).generators(maxweight=12)]
798
+ [4, 6, 12]
799
+
800
+ An example where ``start_gens`` are specified::
801
+
802
+ sage: M = ModularForms(11, 2); f = (M.0 + M.1).qexp(8)
803
+ sage: ModularFormsRing(11).generators(start_gens = [(2, f)])
804
+ Traceback (most recent call last):
805
+ ...
806
+ ValueError: Requested precision cannot be higher than precision of approximate starting generators!
807
+ sage: f = (M.0 + M.1).qexp(10); f
808
+ 1 + 17/5*q + 26/5*q^2 + 43/5*q^3 + 94/5*q^4 + 77/5*q^5 + 154/5*q^6 + 86/5*q^7 + 36*q^8 + 146/5*q^9 + O(q^10)
809
+ sage: ModularFormsRing(11).generators(start_gens = [(2, f)])
810
+ [(2, 1 + 17/5*q + 26/5*q^2 + 43/5*q^3 + 94/5*q^4 + 77/5*q^5 + 154/5*q^6 + 86/5*q^7 + 36*q^8 + 146/5*q^9 + O(q^10)),
811
+ (2, 1 + 12*q^2 + 12*q^3 + 12*q^4 + 12*q^5 + 24*q^6 + 24*q^7 + 36*q^8 + 36*q^9 + O(q^10)),
812
+ (4, 1 + O(q^10))]
813
+ """
814
+ sgs = []
815
+ for x in start_gens:
816
+ if len(x) == 2:
817
+ if x[1].prec() < prec:
818
+ raise ValueError("Requested precision cannot be higher"
819
+ " than precision of approximate starting "
820
+ "generators!")
821
+ sgs.append((x[0], x[1], None))
822
+ else:
823
+ sgs.append(x)
824
+
825
+ G = self._find_generators(maxweight, tuple(sgs), start_weight)
826
+
827
+ ret = []
828
+ # Returned generators may be a funny mixture of precisions if
829
+ # start_gens has been used.
830
+ for k, f, F in G:
831
+ if f.prec() < prec:
832
+ f = F.qexp(prec).change_ring(self.base_ring())
833
+ else:
834
+ f = f.truncate_powerseries(prec)
835
+ ret.append((k, f))
836
+
837
+ return ret
838
+
839
+ def gen_forms(self, maxweight=8, start_gens=[], start_weight=2) -> list:
840
+ r"""
841
+ Return a list of modular forms generating this ring (as an algebra
842
+ over the appropriate base ring).
843
+
844
+ This method differs from :meth:`generators` only in that it returns
845
+ graded modular form objects, rather than bare `q`-expansions.
846
+
847
+ INPUT:
848
+
849
+ - ``maxweight`` -- integer (default: 8); calculate forms
850
+ generating all forms up to this weight
851
+
852
+ - ``start_gens`` -- list (default: ``[]``); a list of
853
+ modular forms. If this list is nonempty, we find a minimal
854
+ generating set containing these forms.
855
+
856
+ - ``start_weight`` -- integer (default: 2); calculate the graded
857
+ subalgebra of forms of weight at least ``start_weight``
858
+
859
+ .. NOTE::
860
+
861
+ If called with the default values of ``start_gens`` (an empty list)
862
+ and ``start_weight`` (2), the values will be cached for re-use on
863
+ subsequent calls to this function. (This cache is shared with
864
+ :meth:`generators`). If called with non-default values for these
865
+ parameters, caching will be disabled.
866
+
867
+ EXAMPLES::
868
+
869
+ sage: A = ModularFormsRing(Gamma0(11), Zmod(5)).gen_forms(); A
870
+ [1 + 12*q^2 + 12*q^3 + 12*q^4 + 12*q^5 + O(q^6),
871
+ q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6),
872
+ q - 9*q^4 - 10*q^5 + O(q^6)]
873
+ sage: A[0].parent()
874
+ Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field
875
+ """
876
+ sgs = tuple((F.weight(), None, F) for F in start_gens)
877
+ G = self._find_generators(maxweight, sgs, start_weight)
878
+ return [F for k, f, F in G]
879
+
880
+ gens = gen_forms
881
+
882
+ def _find_generators(self, maxweight, start_gens, start_weight) -> list:
883
+ r"""
884
+ Return a list of triples `(k, f, F)` where `F` is a modular
885
+ form of weight `k` and `f` is its `q`-expansion coerced into the
886
+ base ring of self.
887
+
888
+ For internal use. This function is called by :meth:`generators`
889
+ and :meth:`gen_forms`.
890
+
891
+ INPUT:
892
+
893
+ - ``maxweight`` -- maximum weight to try
894
+ - ``start_weight`` -- minimum weight to try
895
+ - ``start_gens`` -- a sequence of tuples of the form `(k, f, F)`, where
896
+ `F` is a modular form of weight `k` and `f` is its `q`-expansion
897
+ coerced into ``self.base_ring()``. Either (but not both) of `f` and `F`
898
+ may be ``None``.
899
+
900
+ OUTPUT: list of tuples, formatted as with ``start_gens``
901
+
902
+ EXAMPLES::
903
+
904
+ sage: R = ModularFormsRing(Gamma1(4))
905
+ sage: R._find_generators(8, (), 2)
906
+ [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^9), 1 + 24*q^2 + 24*q^4 + O(q^6)),
907
+ (2, q + 4*q^3 + 6*q^5 + 8*q^7 + O(q^9), q + 4*q^3 + 6*q^5 + O(q^6)),
908
+ (3, 1 + 12*q^2 + 64*q^3 + 60*q^4 + 160*q^6 + 384*q^7 + 252*q^8 + O(q^9), 1 + 12*q^2 + 64*q^3 + 60*q^4 + O(q^6)),
909
+ (3, q + 4*q^2 + 8*q^3 + 16*q^4 + 26*q^5 + 32*q^6 + 48*q^7 + 64*q^8 + O(q^9), q + 4*q^2 + 8*q^3 + 16*q^4 + 26*q^5 + O(q^6))]
910
+ """
911
+ default_params = (start_gens == () and start_weight == 2)
912
+
913
+ if default_params and self.__cached_maxweight != -1:
914
+ verbose("Already know generators up to weight %s -- using those" % self.__cached_maxweight)
915
+
916
+ if self.__cached_maxweight >= maxweight:
917
+ return [(k, f, F) for k, f, F in self.__cached_gens if k <= maxweight]
918
+
919
+ start_gens = self.__cached_gens
920
+ start_weight = self.__cached_maxweight + 1
921
+
922
+ if self.group().is_even():
923
+ increment = 2
924
+ else:
925
+ increment = 1
926
+
927
+ working_prec = self.modular_forms_of_weight(maxweight).sturm_bound()
928
+
929
+ # parse the list of start gens
930
+ G = []
931
+ for x in start_gens:
932
+ k, f, F = x
933
+ if F is None and f.prec() < working_prec:
934
+ raise ValueError("Need start gens to precision at least %s" % working_prec)
935
+ elif f is None or f.prec() < working_prec:
936
+ f = F.qexp(working_prec).change_ring(self.base_ring())
937
+ G.append((k, f, F))
938
+
939
+ k = start_weight
940
+ if increment == 2 and (k % 2) == 1:
941
+ k += 1
942
+
943
+ while k <= maxweight:
944
+
945
+ if self.modular_forms_of_weight(k).dimension() == 0:
946
+ k += increment
947
+ continue
948
+
949
+ verbose('Looking at k = %s' % k)
950
+ M = self.modular_forms_of_weight(k)
951
+
952
+ # 1. Multiply together all forms in G that give an element
953
+ # of M.
954
+ if G:
955
+ F = _span_of_forms_in_weight(G, k, M.sturm_bound(), None, False)
956
+ else:
957
+ F = (self.base_ring() ** M.sturm_bound()).zero_submodule()
958
+
959
+ # 2. If the dimension of the span of the result is equal
960
+ # to the dimension of M, increment k.
961
+ if F.rank() == M.dimension():
962
+ if self.base_ring().is_field() or F.index_in_saturation() == 1:
963
+ # TODO: Do something clever if the submodule's of the right
964
+ # rank but not saturated -- avoid triggering needless
965
+ # modular symbol computations.
966
+ verbose('Nothing new in weight %s' % k)
967
+ k += increment
968
+ continue
969
+
970
+ # 3. If the dimension is less, compute a basis for G, and
971
+ # try adding basis elements of M into G.
972
+
973
+ verbose("Known generators span a subspace of dimension %s of space of dimension %s" % (F.dimension(), M.dimension()))
974
+ if self.base_ring() == ZZ:
975
+ verbose("saturation index is %s" % F.index_in_saturation())
976
+
977
+ t = verbose("Computing more modular forms at weight %s" % k)
978
+ kprec = M.sturm_bound()
979
+ if self.base_ring() == QQ:
980
+ B = M.q_echelon_basis(working_prec)
981
+ else:
982
+ B = M.q_integral_basis(working_prec)
983
+ t = verbose("done computing forms", t)
984
+ V = F.ambient_module().submodule_with_basis([f.padded_list(kprec) for f in B])
985
+ Q = V / F
986
+ for q in Q.gens():
987
+ try:
988
+ qc = V.coordinates(Q.lift(q))
989
+ except AttributeError:
990
+ # work around a silly free module bug
991
+ qc = V.coordinates(q.lift())
992
+ qcZZ = [ZZ(_) for _ in qc] # lift to ZZ so we can define F
993
+ f = sum([B[i] * qcZZ[i] for i in range(len(B))])
994
+ F = M(f)
995
+ G.append((k, f.change_ring(self.base_ring()), F))
996
+
997
+ verbose('added %s new generators' % Q.ngens(), t)
998
+ k += increment
999
+
1000
+ if default_params:
1001
+ self.__cached_maxweight = maxweight
1002
+ self.__cached_gens = G
1003
+
1004
+ return G
1005
+
1006
+ @cached_method
1007
+ def q_expansion_basis(self, weight, prec=None, use_random=True):
1008
+ r"""
1009
+ Return a basis of `q`-expansions for the space of modular forms
1010
+ of the given weight for this group, calculated using the ring
1011
+ generators given by ``find_generators``.
1012
+
1013
+ INPUT:
1014
+
1015
+ - ``weight`` -- the weight
1016
+ - ``prec`` -- integer (default: ``None``); power series
1017
+ precision. If ``None``, the precision defaults to the Sturm
1018
+ bound for the requested level and weight.
1019
+ - ``use_random`` -- boolean (default: ``True``); whether or not to
1020
+ use a randomized algorithm when building up the space of forms
1021
+ at the given weight from known generators of small weight.
1022
+
1023
+ EXAMPLES::
1024
+
1025
+ sage: m = ModularFormsRing(Gamma0(4))
1026
+ sage: m.q_expansion_basis(2,10)
1027
+ [1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10),
1028
+ q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)]
1029
+ sage: m.q_expansion_basis(3,10)
1030
+ []
1031
+
1032
+ sage: X = ModularFormsRing(SL2Z)
1033
+ sage: X.q_expansion_basis(12, 10)
1034
+ [1 + 196560*q^2 + 16773120*q^3 + 398034000*q^4 + 4629381120*q^5 + 34417656000*q^6 + 187489935360*q^7 + 814879774800*q^8 + 2975551488000*q^9 + O(q^10),
1035
+ q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 - 16744*q^7 + 84480*q^8 - 113643*q^9 + O(q^10)]
1036
+
1037
+ We calculate a basis of a massive modular forms space, in two ways.
1038
+ Using this module is about twice as fast as Sage's generic code. ::
1039
+
1040
+ sage: A = ModularFormsRing(11).q_expansion_basis(30, prec=40) # long time (5s)
1041
+ sage: B = ModularForms(Gamma0(11), 30).q_echelon_basis(prec=40) # long time (9s)
1042
+ sage: A == B # long time
1043
+ True
1044
+
1045
+ Check that absurdly small values of ``prec`` don't mess things up::
1046
+
1047
+ sage: ModularFormsRing(11).q_expansion_basis(10, prec=5)
1048
+ [1 + O(q^5), q + O(q^5), q^2 + O(q^5), q^3 + O(q^5),
1049
+ q^4 + O(q^5), O(q^5), O(q^5), O(q^5), O(q^5), O(q^5)]
1050
+ """
1051
+ d = self.modular_forms_of_weight(weight).dimension()
1052
+ if d == 0:
1053
+ return []
1054
+
1055
+ if prec is None:
1056
+ prec = self.modular_forms_of_weight(weight).sturm_bound()
1057
+
1058
+ working_prec = max(prec, self.modular_forms_of_weight(weight).sturm_bound())
1059
+
1060
+ gen_weight = min(6, weight)
1061
+
1062
+ while True:
1063
+ verbose("Trying to generate the %s-dimensional space at weight %s using generators of weight up to %s" % (d, weight, gen_weight))
1064
+ G = self.generators(maxweight=gen_weight, prec=working_prec)
1065
+ V = _span_of_forms_in_weight(G, weight, prec=working_prec, use_random=use_random, stop_dim=d)
1066
+ if V.rank() == d and (self.base_ring().is_field() or V.index_in_saturation() == 1):
1067
+ break
1068
+ gen_weight += 1
1069
+ verbose("Need more generators: trying again with generators of weight up to %s" % gen_weight)
1070
+
1071
+ R = G[0][1].parent()
1072
+ return [R(list(x), prec=prec) for x in V.gens()]
1073
+
1074
+ def cuspidal_ideal_generators(self, maxweight=8, prec=None):
1075
+ r"""
1076
+ Return a set of generators for the ideal of cuspidal forms in
1077
+ this ring, as a module over the whole ring.
1078
+
1079
+ EXAMPLES::
1080
+
1081
+ sage: ModularFormsRing(Gamma0(3)).cuspidal_ideal_generators(maxweight=12)
1082
+ [(6, q - 6*q^2 + 9*q^3 + 4*q^4 + O(q^5), q - 6*q^2 + 9*q^3 + 4*q^4 + 6*q^5 + O(q^6))]
1083
+ sage: [k for k,f,F in ModularFormsRing(13, base_ring=ZZ).cuspidal_ideal_generators(maxweight=14)]
1084
+ [4, 4, 4, 6, 6, 12]
1085
+ """
1086
+ working_prec = self.modular_forms_of_weight(maxweight).sturm_bound()
1087
+
1088
+ if self.__cached_cusp_maxweight > -1:
1089
+ k = self.__cached_cusp_maxweight + 1
1090
+ verbose("Already calculated cusp gens up to weight %s -- using those" % (k-1))
1091
+
1092
+ # we may need to increase the precision of the cached cusp
1093
+ # generators
1094
+ G = []
1095
+ for j, f, F in self.__cached_cusp_gens:
1096
+ if f.prec() >= working_prec:
1097
+ f = F.qexp(working_prec).change_ring(self.base_ring())
1098
+ G.append((j, f, F))
1099
+ else:
1100
+ k = 2
1101
+ G = []
1102
+
1103
+ while k <= maxweight:
1104
+ t = verbose(f"Looking for cusp generators in weight {k}")
1105
+
1106
+ kprec = self.modular_forms_of_weight(k).sturm_bound()
1107
+
1108
+ flist = []
1109
+
1110
+ for j, f, F in G:
1111
+ for g in self.q_expansion_basis(k - j, prec=kprec):
1112
+ flist.append(g*f)
1113
+ A = self.base_ring() ** kprec
1114
+ W = A.span([A(f.padded_list(kprec)) for f in flist])
1115
+
1116
+ S = self.modular_forms_of_weight(k).cuspidal_submodule()
1117
+ if (W.rank() == S.dimension()
1118
+ and (self.base_ring().is_field() or W.index_in_saturation() == 1)):
1119
+ verbose("Nothing new in weight %s" % k, t)
1120
+ k += 1
1121
+ continue
1122
+
1123
+ t = verbose("Known cusp generators span a submodule of dimension %s of space of dimension %s" % (W.rank(), S.dimension()), t)
1124
+
1125
+ B = S.q_integral_basis(prec=working_prec)
1126
+ V = A.span([A(f.change_ring(self.base_ring()).padded_list(kprec)) for f in B])
1127
+ Q = V/W
1128
+
1129
+ for q in Q.gens():
1130
+ try:
1131
+ qc = V.coordinates(Q.lift(q))
1132
+ except AttributeError:
1133
+ # work around a silly free module bug
1134
+ qc = V.coordinates(q.lift())
1135
+ qcZZ = [ZZ(_) for _ in qc] # lift to ZZ so we can define F
1136
+ f = sum([B[i] * qcZZ[i] for i in range(len(B))])
1137
+ F = S(f)
1138
+ G.append((k, f.change_ring(self.base_ring()), F))
1139
+
1140
+ verbose('added %s new generators' % Q.ngens(), t)
1141
+ k += 1
1142
+
1143
+ self.__cached_cusp_maxweight = maxweight
1144
+ self.__cached_cusp_gens = G
1145
+
1146
+ if prec is None:
1147
+ return G
1148
+ elif prec <= working_prec:
1149
+ return [(k, f.truncate_powerseries(prec), F) for k, f, F in G]
1150
+ else:
1151
+ # user wants increased precision, so we may as well cache that
1152
+ Gnew = [(k, F.qexp(prec).change_ring(self.base_ring()), F) for k, f, F in G]
1153
+ self.__cached_cusp_gens = Gnew
1154
+ return Gnew
1155
+
1156
+ def cuspidal_submodule_q_expansion_basis(self, weight, prec=None):
1157
+ r"""
1158
+ Return a basis of `q`-expansions for the space of cusp forms of
1159
+ weight ``weight`` for this group.
1160
+
1161
+ INPUT:
1162
+
1163
+ - ``weight`` -- the weight
1164
+ - ``prec`` -- integer (default: ``None``) precision of
1165
+ `q`-expansions to return
1166
+
1167
+ ALGORITHM: Uses the method :meth:`cuspidal_ideal_generators` to
1168
+ calculate generators of the ideal of cusp forms inside this ring. Then
1169
+ multiply these up to weight ``weight`` using the generators of the
1170
+ whole modular form space returned by :meth:`q_expansion_basis`.
1171
+
1172
+ EXAMPLES::
1173
+
1174
+ sage: R = ModularFormsRing(Gamma0(3))
1175
+ sage: R.cuspidal_submodule_q_expansion_basis(20)
1176
+ [q - 8532*q^6 - 88442*q^7 + O(q^8), q^2 + 207*q^6 + 24516*q^7 + O(q^8),
1177
+ q^3 + 456*q^6 + O(q^8), q^4 - 135*q^6 - 926*q^7 + O(q^8), q^5 + 18*q^6 + 135*q^7 + O(q^8)]
1178
+
1179
+ We compute a basis of a space of very large weight, quickly (using this
1180
+ module) and slowly (using modular symbols), and verify that the answers
1181
+ are the same. ::
1182
+
1183
+ sage: A = R.cuspidal_submodule_q_expansion_basis(80, prec=30) # long time (1s on sage.math, 2013)
1184
+ sage: B = R.modular_forms_of_weight(80).cuspidal_submodule().q_expansion_basis(prec=30) # long time (19s on sage.math, 2013)
1185
+ sage: A == B # long time
1186
+ True
1187
+ """
1188
+ d = self.modular_forms_of_weight(weight).cuspidal_submodule().dimension()
1189
+ if d == 0:
1190
+ return []
1191
+
1192
+ minprec = self.modular_forms_of_weight(weight).sturm_bound()
1193
+ if prec is None:
1194
+ prec = working_prec = minprec
1195
+ else:
1196
+ working_prec = max(prec, minprec)
1197
+
1198
+ gen_weight = min(6, weight)
1199
+
1200
+ while True:
1201
+ verbose("Trying to generate the %s-dimensional cuspidal submodule at weight %s using generators of weight up to %s" % (d, weight, gen_weight))
1202
+ G = self.cuspidal_ideal_generators(maxweight=gen_weight, prec=working_prec)
1203
+
1204
+ flist = []
1205
+ for j, f, F in G:
1206
+ for g in self.q_expansion_basis(weight - j, prec=working_prec):
1207
+ flist.append(g*f)
1208
+
1209
+ A = self.base_ring() ** working_prec
1210
+ W = A.span([A(f.padded_list(working_prec)) for f in flist])
1211
+ if W.rank() == d and (self.base_ring().is_field() or W.index_in_saturation() == 1):
1212
+ break
1213
+ gen_weight += 1
1214
+ verbose("Need more generators: trying again with generators of weight up to %s" % gen_weight)
1215
+
1216
+ R = G[0][1].parent()
1217
+ return [R(list(x), prec=prec) for x in W.gens()]
1218
+
1219
+ def _to_matrix(self, gens=None, prec=None):
1220
+ r"""
1221
+ Return a matrix corresponding to the `q`-expansion of the generators to the given precision.
1222
+
1223
+ INPUT:
1224
+
1225
+ - ``gens`` -- (default: ``None``) a list of generators. If not provided,
1226
+ the list returned by :meth:`ModularFormsRing.gen_forms`
1227
+ is used instead.
1228
+ - ``prec`` -- (default: ``None``) precision to compute up to, or the Sturm
1229
+ bound if not provided.
1230
+
1231
+ OUTPUT: A matrix.
1232
+
1233
+ TESTS::
1234
+
1235
+ sage: M = ModularFormsRing(1)
1236
+ sage: E4 = M.0; E6 = M.1
1237
+ sage: gens = [E4^3, E6^2]; gens
1238
+ [1 + 720*q + 179280*q^2 + 16954560*q^3 + 396974160*q^4 + 4632858720*q^5 + O(q^6),
1239
+ 1 - 1008*q + 220752*q^2 + 16519104*q^3 + 399517776*q^4 + 4624512480*q^5 + O(q^6)]
1240
+ sage: M._to_matrix(gens)
1241
+ [ 1 720]
1242
+ [ 1 -1008]
1243
+ sage: M._to_matrix(gens, 6)
1244
+ [ 1 720 179280 16954560 396974160 4632858720 34413301440]
1245
+ [ 1 -1008 220752 16519104 399517776 4624512480 34423752384]
1246
+ """
1247
+ if gens is None:
1248
+ gens = self.gen_forms()
1249
+
1250
+ if prec is None:
1251
+ # we do not default to prec=6 because this is an internal
1252
+ # function and is usually used to write other forms as a
1253
+ # linear combination of generators, in which case using
1254
+ # the Sturm bound is more reasonable
1255
+ prec = max(gen.group().sturm_bound(gen.weight()) for gen in gens)
1256
+
1257
+ return Matrix(gen.coefficients(range(prec + 1)) for gen in gens)