passagemath-schemes 10.6.38__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.

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