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,846 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.combinat sage.libs.flint
3
+ """
4
+ Elements of quasimodular forms rings
5
+
6
+ AUTHORS:
7
+
8
+ - DAVID AYOTTE (2021-03-18): initial version
9
+ - Seewoo Lee (2023-09): coefficients method
10
+ """
11
+ # ****************************************************************************
12
+ # Copyright (C) 2021 David Ayotte
13
+ # 2023 Seewoo Lee <seewoo5@berkeley.edu>
14
+ #
15
+ #
16
+ # This program is free software: you can redistribute it and/or modify
17
+ # it under the terms of the GNU General Public License as published by
18
+ # the Free Software Foundation, either version 2 of the License, or
19
+ # (at your option) any later version.
20
+ # https://www.gnu.org/licenses/
21
+ # ****************************************************************************
22
+ from typing import Self
23
+
24
+ from sage.modular.arithgroup.congroup_sl2z import SL2Z_class
25
+ from sage.modular.modform.constructor import EisensteinForms
26
+ from sage.modular.modform.eis_series import eisenstein_series_qexp
27
+ from sage.modular.modform.element import GradedModularFormElement
28
+
29
+ from sage.structure.element import ModuleElement
30
+ from sage.structure.richcmp import richcmp, op_NE, op_EQ
31
+
32
+ from sage.rings.integer import Integer
33
+ from sage.rings.polynomial.polynomial_element import Polynomial
34
+ from sage.rings.integer_ring import ZZ
35
+
36
+
37
+ class QuasiModularFormsElement(ModuleElement):
38
+ r"""
39
+ A quasimodular forms ring element. Such an element is described by
40
+ SageMath as a polynomial
41
+
42
+ .. MATH::
43
+
44
+ F = f_0 + f_1 E_2 + f_2 E_2^2 + \cdots + f_m E_2^m
45
+
46
+ where each `f_i` a graded modular form element
47
+ (see :class:`~sage.modular.modform.element.GradedModularFormElement`)
48
+
49
+ For an integer `k`, we say that `F` is homogeneous of weight `k` if
50
+ it lies in an homogeneous component of degree `k` of the graded ring
51
+ of quasimodular forms.
52
+
53
+ EXAMPLES::
54
+
55
+ sage: QM = QuasiModularForms(1)
56
+ sage: QM.gens()
57
+ (1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
58
+ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
59
+ 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6))
60
+ sage: QM.0 + QM.1
61
+ 2 + 216*q + 2088*q^2 + 6624*q^3 + 17352*q^4 + 30096*q^5 + O(q^6)
62
+ sage: QM.0 * QM.1
63
+ 1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6)
64
+ sage: (QM.0)^2
65
+ 1 - 48*q + 432*q^2 + 3264*q^3 + 9456*q^4 + 21600*q^5 + O(q^6)
66
+ sage: QM.0 == QM.1
67
+ False
68
+
69
+ Quasimodular forms ring element can be created via a polynomial in `E2` over the ring of modular forms::
70
+
71
+ sage: E2 = QM.polygen()
72
+ sage: E2.parent()
73
+ Univariate Polynomial Ring in E2 over Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field
74
+ sage: QM(E2)
75
+ 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
76
+ sage: M = QM.modular_forms_subring()
77
+ sage: QM(M.0 * E2 + M.1 * E2^2)
78
+ 2 - 336*q + 4320*q^2 + 398400*q^3 - 3772992*q^4 - 89283168*q^5 + O(q^6)
79
+
80
+ One may convert a quasimodular form into a multivariate polynomial in the
81
+ generators of the ring by calling
82
+ :meth:`~sage.modular.quasimodform.element.QuasiModularFormsElement.polynomial`::
83
+
84
+ sage: QM = QuasiModularForms(1)
85
+ sage: F = QM.0^2 + QM.1^2 + QM.0*QM.1*QM.2
86
+ sage: F.polynomial()
87
+ E2*E4*E6 + E4^2 + E2^2
88
+
89
+ If the group is not the full modular group, the default names of the
90
+ generators are given by ``Ek_i`` and ``Sk_i`` to denote the `i`-th basis
91
+ element of the weight `k` Eisenstein subspace and cuspidal subspace
92
+ respectively (for more details, see the documentation of
93
+ :meth:`~sage.modular.quasimodform.ring.QuasiModularFormsRing.polynomial_ring`) ::
94
+
95
+ sage: QM = QuasiModularForms(Gamma1(4))
96
+ sage: F = (QM.0^4)*(QM.1^3) + QM.3
97
+ sage: F.polynomial()
98
+ -512*E2^4*E2_1^3 + E2^4*E3_0^2 + 48*E2^4*E3_1^2 + E3_0
99
+ """
100
+ def __init__(self, parent, polynomial) -> None:
101
+ r"""
102
+ INPUT:
103
+
104
+ - ``parent`` -- a quasimodular forms ring
105
+ - ``polynomial`` -- a polynomial `f_0 + f_1 E_2 + ... + f_n E_2^n` where
106
+ each `f_i` are modular forms ring elements and `E_2` correspond to the
107
+ weight 2 Eisenstein series
108
+
109
+ OUTPUT: ``QuasiModularFormsElement``
110
+
111
+ TESTS::
112
+
113
+ sage: QM = QuasiModularForms(1)
114
+ sage: QM.element_class(QM, 'E2')
115
+ Traceback (most recent call last):
116
+ ...
117
+ TypeError: 'polynomial' argument should be of type 'Polynomial'
118
+ sage: x = polygen(QQ)
119
+ sage: QM.element_class(QM, x^2 + 1)
120
+ Traceback (most recent call last):
121
+ ...
122
+ ValueError: at least one coefficient is not a 'GradedModularFormElement'
123
+ """
124
+ if not isinstance(polynomial, Polynomial):
125
+ raise TypeError("'polynomial' argument should be of type 'Polynomial'")
126
+ for f in polynomial.coefficients():
127
+ if not isinstance(f, GradedModularFormElement):
128
+ raise ValueError("at least one coefficient is not a 'GradedModularFormElement'")
129
+ self._polynomial = polynomial
130
+ ModuleElement.__init__(self, parent)
131
+
132
+ def q_expansion(self, prec=6):
133
+ r"""
134
+ Return the `q`-expansion of the given quasimodular form up to precision
135
+ ``prec`` (default: 6).
136
+
137
+ An alias of this method is ``qexp``.
138
+
139
+ EXAMPLES::
140
+
141
+ sage: QM = QuasiModularForms()
142
+ sage: E2 = QM.0
143
+ sage: E2.q_expansion()
144
+ 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
145
+ sage: E2.q_expansion(prec=10)
146
+ 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 - 288*q^6 - 192*q^7 - 360*q^8 - 312*q^9 + O(q^10)
147
+ """
148
+ E2 = eisenstein_series_qexp(2, prec=prec, K=self.base_ring(), normalization='constant') # normalization -> to force integer coefficients
149
+ coefficients = self._polynomial.coefficients(sparse=False)
150
+ return sum(f.q_expansion(prec=prec) * E2**idx for idx, f in enumerate(coefficients))
151
+
152
+ qexp = q_expansion # alias
153
+
154
+ def _repr_(self) -> str:
155
+ r"""
156
+ String representation of ``self``.
157
+
158
+ TESTS::
159
+
160
+ sage: QM = QuasiModularForms()
161
+ sage: QM.0
162
+ 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
163
+ sage: QM.1
164
+ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
165
+ sage: QM.2
166
+ 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)
167
+ """
168
+ return str(self.q_expansion())
169
+
170
+ def _latex_(self) -> str:
171
+ r"""
172
+ Return a latex representation of ``self``.
173
+
174
+ TESTS::
175
+
176
+ sage: QM = QuasiModularForms(1)
177
+ sage: latex(QM.0)
178
+ 1 - 24 q - 72 q^{2} - 96 q^{3} - 168 q^{4} - 144 q^{5} + O(q^{6})
179
+ """
180
+ return self.q_expansion()._latex_()
181
+
182
+ def _richcmp_(self, other, op) -> bool:
183
+ r"""
184
+ Compare ``self`` with ``other``.
185
+
186
+ TESTS::
187
+
188
+ sage: QM = QuasiModularForms(1)
189
+ sage: QM.0 == QM.1
190
+ False
191
+ sage: QM.0 == QM.0
192
+ True
193
+ sage: QM.0 != QM.1
194
+ True
195
+ sage: QM.0 != QM.0
196
+ False
197
+ sage: QM.0 < QM.1
198
+ Traceback (most recent call last):
199
+ ...
200
+ TypeError: invalid comparison between quasimodular forms ring elements
201
+ """
202
+ if op != op_EQ and op != op_NE:
203
+ raise TypeError('invalid comparison between quasimodular forms ring elements')
204
+ return richcmp(self._polynomial, other._polynomial, op)
205
+
206
+ def _add_(self, other) -> Self:
207
+ r"""
208
+ Addition of two ``QuasiModularFormElement``.
209
+
210
+ INPUT:
211
+
212
+ - ``other`` -- ``QuasiModularFormElement``
213
+
214
+ OUTPUT: a ``QuasiModularFormElement``
215
+
216
+ TESTS::
217
+
218
+ sage: QM = QuasiModularForms(1)
219
+ sage: QM.0 + QM.1
220
+ 2 + 216*q + 2088*q^2 + 6624*q^3 + 17352*q^4 + 30096*q^5 + O(q^6)
221
+ sage: QM.0 + (QM.1 + QM.2) == (QM.0 + QM.1) + QM.2
222
+ True
223
+ sage: QM = QuasiModularForms(5)
224
+ sage: QM.0 + QM.1 + QM.2 + QM.3
225
+ 3 - 17*q - 54*q^2 - 62*q^3 - 98*q^4 + 137*q^5 + O(q^6)
226
+ """
227
+ return self.__class__(self.parent(), self._polynomial + other._polynomial)
228
+
229
+ def __neg__(self) -> Self:
230
+ r"""
231
+ The negation of ``self``.
232
+
233
+ TESTS::
234
+
235
+ sage: -QuasiModularForms(1).0
236
+ -1 + 24*q + 72*q^2 + 96*q^3 + 168*q^4 + 144*q^5 + O(q^6)
237
+ sage: QuasiModularForms(1).0 - QuasiModularForms(1).0
238
+ 0
239
+ sage: -QuasiModularForms(Gamma1(2)).2
240
+ -1 - 240*q^2 - 2160*q^4 + O(q^6)
241
+ """
242
+ return self.__class__(self.parent(), -self._polynomial)
243
+
244
+ def _mul_(self, other) -> Self:
245
+ r"""
246
+ The multiplication of two ``QuasiModularFormElement``.
247
+
248
+ INPUT:
249
+
250
+ - ``other`` -- ``QuasiModularFormElement``
251
+
252
+ OUTPUT: a ``QuasiModularFormElement``
253
+
254
+ TESTS::
255
+
256
+ sage: QM = QuasiModularForms(1)
257
+ sage: QM.0 * QM.1
258
+ 1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6)
259
+ sage: (QM.0 * QM.1) * QM.2 == QM.0 * (QM.1 * QM.2)
260
+ True
261
+ sage: QM = QuasiModularForms(Gamma1(5))
262
+ sage: QM.0 * QM.1 * QM.2
263
+ q - 24*q^2 - 66*q^3 - 189*q^4 - 1917*q^5 + O(q^6)
264
+ """
265
+ return self.__class__(self.parent(), self._polynomial * other._polynomial)
266
+
267
+ def _lmul_(self, c) -> Self:
268
+ r"""
269
+ The left action of the base ring on ``self``.
270
+
271
+ INPUT:
272
+
273
+ - ``other`` -- ``QuasiModularFormElement``
274
+
275
+ OUTPUT: a ``QuasiModularFormElement``
276
+
277
+ TESTS::
278
+
279
+ sage: QM = QuasiModularForms(1)
280
+ sage: (1/2) * QM.0
281
+ 1/2 - 12*q - 36*q^2 - 48*q^3 - 84*q^4 - 72*q^5 + O(q^6)
282
+ sage: QM.0 * (3/2)
283
+ 3/2 - 36*q - 108*q^2 - 144*q^3 - 252*q^4 - 216*q^5 + O(q^6)
284
+ sage: (5/2) * QuasiModularForms(Gamma0(7)).0 * (3/2)
285
+ 15/4 - 90*q - 270*q^2 - 360*q^3 - 630*q^4 - 540*q^5 + O(q^6)
286
+ """
287
+ return self.__class__(self.parent(), c * self._polynomial)
288
+
289
+ def __bool__(self) -> bool:
290
+ r"""
291
+ Return whether ``self`` is nonzero.
292
+
293
+ EXAMPLES::
294
+
295
+ sage: QM = QuasiModularForms(1)
296
+ sage: bool(QM(0))
297
+ False
298
+ sage: bool(QM(1))
299
+ True
300
+ sage: bool(QM.0)
301
+ True
302
+ """
303
+ return bool(self._polynomial)
304
+
305
+ def depth(self):
306
+ r"""
307
+ Return the depth of this quasimodular form.
308
+
309
+ Note that the quasimodular form must be homogeneous of weight
310
+ `k`. Recall that the *depth* is the integer `p` such that
311
+
312
+ .. MATH::
313
+
314
+ f = f_0 + f_1 E_2 + \cdots + f_p E_2^p,
315
+
316
+ where `f_i` is a modular form of weight `k - 2i` and `f_p` is
317
+ nonzero.
318
+
319
+ EXAMPLES::
320
+
321
+ sage: QM = QuasiModularForms(1)
322
+ sage: E2, E4, E6 = QM.gens()
323
+ sage: E2.depth()
324
+ 1
325
+ sage: F = E4^2 + E6*E2 + E4*E2^2 + E2^4
326
+ sage: F.depth()
327
+ 4
328
+ sage: QM(7/11).depth()
329
+ 0
330
+
331
+ TESTS::
332
+
333
+ sage: QM = QuasiModularForms(1)
334
+ sage: (QM.0 + QM.1).depth()
335
+ Traceback (most recent call last):
336
+ ...
337
+ ValueError: the given graded quasiform is not an homogeneous element
338
+ """
339
+ if not self.is_homogeneous():
340
+ raise ValueError("the given graded quasiform is not an "
341
+ "homogeneous element")
342
+ return self._polynomial.degree()
343
+
344
+ def is_zero(self) -> bool:
345
+ r"""
346
+ Return whether the given quasimodular form is zero.
347
+
348
+ EXAMPLES::
349
+
350
+ sage: QM = QuasiModularForms(1)
351
+ sage: QM.zero().is_zero()
352
+ True
353
+ sage: QM(0).is_zero()
354
+ True
355
+ sage: QM(1/2).is_zero()
356
+ False
357
+ sage: (QM.0).is_zero()
358
+ False
359
+ sage: QM = QuasiModularForms(Gamma0(2))
360
+ sage: QM(0).is_zero()
361
+ True
362
+ """
363
+ return not self
364
+
365
+ def is_one(self) -> bool:
366
+ r"""
367
+ Return whether the given quasimodular form is 1, i.e. the
368
+ multiplicative identity.
369
+
370
+ EXAMPLES::
371
+
372
+ sage: QM = QuasiModularForms(1)
373
+ sage: QM.one().is_one()
374
+ True
375
+ sage: QM(1).is_one()
376
+ True
377
+ sage: (QM.0).is_one()
378
+ False
379
+ sage: QM = QuasiModularForms(Gamma0(2))
380
+ sage: QM(1).is_one()
381
+ True
382
+ """
383
+ return self._polynomial.is_one()
384
+
385
+ def is_graded_modular_form(self) -> bool:
386
+ r"""
387
+ Return whether the given quasimodular form is a
388
+ graded modular form element
389
+ (see :class:`~sage.modular.modform.element.GradedModularFormElement`).
390
+
391
+ EXAMPLES::
392
+
393
+ sage: QM = QuasiModularForms(1)
394
+ sage: (QM.0).is_graded_modular_form()
395
+ False
396
+ sage: (QM.1).is_graded_modular_form()
397
+ True
398
+ sage: (QM.1 + QM.0^2).is_graded_modular_form()
399
+ False
400
+ sage: (QM.1^2 + QM.2).is_graded_modular_form()
401
+ True
402
+ sage: QM = QuasiModularForms(Gamma0(6))
403
+ sage: (QM.0).is_graded_modular_form()
404
+ False
405
+ sage: (QM.1 + QM.2 + QM.1 * QM.3).is_graded_modular_form()
406
+ True
407
+ sage: QM.zero().is_graded_modular_form()
408
+ True
409
+ sage: QM = QuasiModularForms(Gamma0(6))
410
+ sage: (QM.0).is_graded_modular_form()
411
+ False
412
+ sage: (QM.0 + QM.1*QM.2 + QM.3).is_graded_modular_form()
413
+ False
414
+ sage: (QM.1*QM.2 + QM.3).is_graded_modular_form()
415
+ True
416
+
417
+ .. NOTE::
418
+
419
+ A graded modular form in SageMath is not necessarily a modular form
420
+ as it can have mixed weight components. To check for modular forms
421
+ only, see the method :meth:`is_modular_form`.
422
+ """
423
+ return self._polynomial.degree() <= 0
424
+
425
+ def is_modular_form(self) -> bool:
426
+ r"""
427
+ Return whether the given quasimodular form is a modular form.
428
+
429
+ EXAMPLES::
430
+
431
+ sage: QM = QuasiModularForms(1)
432
+ sage: (QM.0).is_modular_form()
433
+ False
434
+ sage: (QM.1).is_modular_form()
435
+ True
436
+ sage: (QM.1 + QM.2).is_modular_form() # mixed weight components
437
+ False
438
+ sage: QM.zero().is_modular_form()
439
+ True
440
+ sage: QM = QuasiModularForms(Gamma0(4))
441
+ sage: (QM.0).is_modular_form()
442
+ False
443
+ sage: (QM.1).is_modular_form()
444
+ True
445
+ """
446
+ return self._polynomial.degree() <= 0 and self._polynomial[0].is_modular_form()
447
+
448
+ def polynomial(self, names=None):
449
+ r"""
450
+ Return a multivariate polynomial such that every variable corresponds to
451
+ a generator of the ring, ordered by the method:
452
+ :meth:`~sage.modular.quasimodform.ring.QuasiModularForms.gens`.
453
+
454
+ An alias of this method is ``to_polynomial``.
455
+
456
+ INPUT:
457
+
458
+ - ``names``-- string (default: ``None``); list or tuple of names
459
+ (strings), or a comma separated string. Defines the names for the
460
+ generators of the multivariate polynomial ring. The default names are
461
+ of the form ``ABCk`` where ``k`` is a number corresponding to the
462
+ weight of the form ``ABC``.
463
+
464
+ OUTPUT: a multivariate polynomial in the variables ``names``
465
+
466
+ EXAMPLES::
467
+
468
+ sage: QM = QuasiModularForms(1)
469
+ sage: (QM.0 + QM.1).polynomial()
470
+ E4 + E2
471
+ sage: (1/2 + QM.0 + 2*QM.1^2 + QM.0*QM.2).polynomial()
472
+ E2*E6 + 2*E4^2 + E2 + 1/2
473
+
474
+ Check that :issue:`34569` is fixed::
475
+
476
+ sage: QM = QuasiModularForms(Gamma1(3))
477
+ sage: QM.ngens()
478
+ 5
479
+ sage: (QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).polynomial()
480
+ E3_1*E4_0 + E2_0*E3_0 + E2 + E2_0
481
+ """
482
+ P = self.parent().polynomial_ring(names)
483
+ poly_gens = P.gens()
484
+ E2 = poly_gens[0]
485
+ poly_gens = poly_gens[1:]
486
+ modform_poly_gens = self.parent().modular_forms_subring().polynomial_ring(names='x').gens()
487
+ subs_dictionary = {}
488
+ for idx, g in enumerate(modform_poly_gens):
489
+ subs_dictionary[g] = poly_gens[idx]
490
+ return sum(f.to_polynomial().subs(subs_dictionary) * E2 ** exp for exp, f in enumerate(self._polynomial.coefficients(sparse=False)))
491
+
492
+ to_polynomial = polynomial # alias
493
+
494
+ def weights_list(self) -> list[Integer]:
495
+ r"""
496
+ Return the list of the weights of all the graded components of the given
497
+ graded quasimodular form.
498
+
499
+ EXAMPLES::
500
+
501
+ sage: QM = QuasiModularForms(1)
502
+ sage: (QM.0).weights_list()
503
+ [2]
504
+ sage: (QM.0 + QM.1 + QM.2).weights_list()
505
+ [2, 4, 6]
506
+ sage: (QM.0 * QM.1 + QM.2).weights_list()
507
+ [6]
508
+ sage: QM(1/2).weights_list()
509
+ [0]
510
+ sage: QM = QuasiModularForms(Gamma1(3))
511
+ sage: (QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).weights_list()
512
+ [2, 5, 7]
513
+ """
514
+ return sorted(self.homogeneous_components().keys())
515
+
516
+ def is_homogeneous(self) -> bool:
517
+ r"""
518
+ Return whether the graded quasimodular form is a homogeneous element,
519
+ that is, it lives in a unique graded components of the parent of
520
+ ``self``.
521
+
522
+ EXAMPLES::
523
+
524
+ sage: QM = QuasiModularForms(1)
525
+ sage: E2, E4, E6 = QM.gens()
526
+ sage: (E2).is_homogeneous()
527
+ True
528
+ sage: (E2 + E4).is_homogeneous()
529
+ False
530
+ sage: (E2 * E4 + E6).is_homogeneous()
531
+ True
532
+ sage: QM(1).is_homogeneous()
533
+ True
534
+ sage: (1 + E2).is_homogeneous()
535
+ False
536
+ sage: F = E6^3 + E4^4*E2 + (E4^2*E6)*E2^2 + (E4^3 + E6^2)*E2^3
537
+ sage: F.is_homogeneous()
538
+ True
539
+ """
540
+ k = None
541
+ for i, c in enumerate(self._polynomial.coefficients(sparse=False)):
542
+ if c:
543
+ if not c.is_homogeneous():
544
+ return False
545
+ if k is None:
546
+ k = c.weight() + 2*i
547
+ continue
548
+ if c.weight() + 2*i != k:
549
+ return False
550
+ return True
551
+
552
+ def weight(self) -> Integer:
553
+ r"""
554
+ Return the weight of the given quasimodular form.
555
+
556
+ Note that the given form must be homogeneous. An alias of this method is
557
+ ``degree``.
558
+
559
+ EXAMPLES::
560
+
561
+ sage: QM = QuasiModularForms(1)
562
+ sage: (QM.0).weight()
563
+ 2
564
+ sage: (QM.0 * QM.1 + QM.2).weight()
565
+ 6
566
+ sage: QM(1/2).weight()
567
+ 0
568
+ sage: (QM.0).degree()
569
+ 2
570
+ sage: (QM.0 + QM.1).weight()
571
+ Traceback (most recent call last):
572
+ ...
573
+ ValueError: the given graded quasiform is not an homogeneous element
574
+ """
575
+ if self.is_homogeneous():
576
+ return (self._polynomial.leading_coefficient().weight()
577
+ + 2*self._polynomial.degree())
578
+ raise ValueError("the given graded quasiform is not an homogeneous "
579
+ "element")
580
+
581
+ degree = weight # alias
582
+
583
+ def homogeneous_components(self) -> dict[Integer, Self]:
584
+ r"""
585
+ Return a dictionary where the values are the homogeneous components of
586
+ the given graded form and the keys are the weights of those components.
587
+
588
+ EXAMPLES::
589
+
590
+ sage: QM = QuasiModularForms(1)
591
+ sage: (QM.0).homogeneous_components()
592
+ {2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)}
593
+ sage: (QM.0 + QM.1 + QM.2).homogeneous_components()
594
+ {2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
595
+ 4: 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
596
+ 6: 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)}
597
+ sage: (1 + QM.0).homogeneous_components()
598
+ {0: 1, 2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)}
599
+ sage: QM5 = QuasiModularForms(Gamma1(3))
600
+ sage: F = QM.1 + QM.1*QM.2 + QM.1*QM.0 + (QM.1 + QM.2^2)*QM.0^3
601
+ sage: F.homogeneous_components()
602
+ {4: 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
603
+ 6: 1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6),
604
+ 10: 2 - 96*q - 149040*q^2 - 4986240*q^3 - 67535952*q^4 - 538187328*q^5 + O(q^6),
605
+ 18: 1 - 1080*q + 294840*q^2 - 902880*q^3 - 452402280*q^4 + 105456816*q^5 + O(q^6)}
606
+ sage: F = QM.zero()
607
+ sage: F.homogeneous_components()
608
+ {0: 0}
609
+ sage: F = QM(42/13)
610
+ sage: F.homogeneous_components()
611
+ {0: 42/13}
612
+ """
613
+ QM = self.parent()
614
+ if self.is_zero():
615
+ return {ZZ.zero(): self}
616
+ components: dict[Integer, Self] = {}
617
+ E2 = self.parent().weight_2_eisenstein_series()
618
+ for i, c in enumerate(self._polynomial.coefficients(sparse=False)):
619
+ if c:
620
+ forms = c._forms_dictionary
621
+ for k in forms:
622
+ try:
623
+ components[ZZ(k + 2*i)] += QM(forms[k]*(E2**i))
624
+ except KeyError:
625
+ components[ZZ(k + 2*i)] = QM(forms[k]*(E2**i))
626
+ return components
627
+
628
+ def __getitem__(self, weight) -> Self | None:
629
+ r"""
630
+ Return the homogeneous component of the given quasimodular form ring
631
+ element.
632
+
633
+ An alias of this method is ``homogeneous_component``.
634
+
635
+ EXAMPLES::
636
+
637
+ sage: QM = QuasiModularForms(1)
638
+ sage: E2, E4, E6 = QM.gens()
639
+ sage: F = E2 + E4*E6 + E2^3*E6
640
+ sage: F[2]
641
+ 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
642
+ sage: F[10]
643
+ 1 - 264*q - 135432*q^2 - 5196576*q^3 - 69341448*q^4 - 515625264*q^5 + O(q^6)
644
+ sage: F[12]
645
+ 1 - 576*q + 21168*q^2 + 308736*q^3 - 15034608*q^4 - 39208320*q^5 + O(q^6)
646
+ sage: F[4]
647
+ 0
648
+ sage: F.homogeneous_component(2)
649
+ 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
650
+
651
+ TESTS::
652
+
653
+ sage: F[x] # needs sage.symbolic
654
+ Traceback (most recent call last):
655
+ ...
656
+ KeyError: 'the weight must be an integer'
657
+ sage: F[-1]
658
+ Traceback (most recent call last):
659
+ ...
660
+ ValueError: the weight must be nonnegative
661
+ """
662
+ if not isinstance(weight, (int, Integer)):
663
+ raise KeyError("the weight must be an integer")
664
+ if weight < 0:
665
+ raise ValueError("the weight must be nonnegative")
666
+ return self.homogeneous_components().get(Integer(weight),
667
+ self.parent().zero())
668
+
669
+ homogeneous_component = __getitem__ # alias
670
+
671
+ def serre_derivative(self) -> Self:
672
+ r"""
673
+ Return the Serre derivative of the given quasimodular form.
674
+
675
+ If the form is not homogeneous, then this method sums the Serre
676
+ derivative of each homogeneous component.
677
+
678
+ EXAMPLES::
679
+
680
+ sage: QM = QuasiModularForms(1)
681
+ sage: E2, E4, E6 = QM.gens()
682
+ sage: DE2 = E2.serre_derivative(); DE2
683
+ -1/6 - 16*q - 216*q^2 - 832*q^3 - 2248*q^4 - 4320*q^5 + O(q^6)
684
+ sage: DE2 == (-E2^2 - E4)/12
685
+ True
686
+ sage: DE4 = E4.serre_derivative(); DE4
687
+ -1/3 + 168*q + 5544*q^2 + 40992*q^3 + 177576*q^4 + 525168*q^5 + O(q^6)
688
+ sage: DE4 == (-1/3) * E6
689
+ True
690
+ sage: DE6 = E6.serre_derivative(); DE6
691
+ -1/2 - 240*q - 30960*q^2 - 525120*q^3 - 3963120*q^4 - 18750240*q^5 + O(q^6)
692
+ sage: DE6 == (-1/2) * E4^2
693
+ True
694
+
695
+ The Serre derivative raises the weight of homogeneous elements by 2::
696
+
697
+ sage: F = E6 + E4 * E2
698
+ sage: F.weight()
699
+ 6
700
+ sage: F.serre_derivative().weight()
701
+ 8
702
+
703
+ Check that :issue:`34569` is fixed::
704
+
705
+ sage: QM = QuasiModularForms(Gamma1(3))
706
+ sage: E2 = QM.weight_2_eisenstein_series()
707
+ sage: E2.serre_derivative()
708
+ -1/6 - 16*q - 216*q^2 - 832*q^3 - 2248*q^4 - 4320*q^5 + O(q^6)
709
+ sage: F = QM.0 + QM.1*QM.2
710
+ """
711
+ # initial variables:
712
+ QM = self.parent()
713
+ R = QM.base_ring()
714
+ E2 = QM.gen(0)
715
+ if isinstance(QM.group(), SL2Z_class):
716
+ E4 = QM.gen(1)
717
+ else:
718
+ E4 = QM(EisensteinForms(group=1, weight=4, base_ring=R).gen(0))
719
+
720
+ # compute the derivative of E2: q*dE2/dq
721
+ E2deriv = R(12).inverse_of_unit() * (E2 ** 2 - E4)
722
+
723
+ # sum the Serre derivative of each monomial of the form: f * E2^n
724
+ # they are equal to:
725
+ # [E2^n * serre_deriv(f)] + [n * f * E2^(n-1) * D(E2)] - [n/6 * f * E2^(n+1)]
726
+ # = A + B - C
727
+ der = QM.zero()
728
+ u6 = R(6).inverse_of_unit()
729
+ for n, f in enumerate(self._polynomial.coefficients(sparse=False)):
730
+ if n == 0:
731
+ der += QM(f.serre_derivative())
732
+ else:
733
+ A = (E2 ** n) * f.serre_derivative()
734
+ B = R(n) * f * E2 ** (n - 1) * E2deriv
735
+ C = R(n) * u6 * E2 ** (n + 1) * f
736
+ der += QM(A + B - C)
737
+ return der
738
+
739
+ def derivative(self) -> Self:
740
+ r"""
741
+ Return the derivative `q \frac{d}{dq}` of the given quasimodular form.
742
+
743
+ If the form is not homogeneous, then this method sums the derivative of
744
+ each homogeneous component.
745
+
746
+ EXAMPLES::
747
+
748
+ sage: QM = QuasiModularForms(1)
749
+ sage: E2, E4, E6 = QM.gens()
750
+ sage: dE2 = E2.derivative(); dE2
751
+ -24*q - 144*q^2 - 288*q^3 - 672*q^4 - 720*q^5 + O(q^6)
752
+ sage: dE2 == (E2^2 - E4)/12 # Ramanujan identity
753
+ True
754
+ sage: dE4 = E4.derivative(); dE4
755
+ 240*q + 4320*q^2 + 20160*q^3 + 70080*q^4 + 151200*q^5 + O(q^6)
756
+ sage: dE4 == (E2 * E4 - E6)/3 # Ramanujan identity
757
+ True
758
+ sage: dE6 = E6.derivative(); dE6
759
+ -504*q - 33264*q^2 - 368928*q^3 - 2130912*q^4 - 7877520*q^5 + O(q^6)
760
+ sage: dE6 == (E2 * E6 - E4^2)/2 # Ramanujan identity
761
+ True
762
+
763
+ Note that the derivative of a modular form is not necessarily a modular form::
764
+
765
+ sage: dE4.is_modular_form()
766
+ False
767
+ sage: dE4.weight()
768
+ 6
769
+ """
770
+ QM = self.parent()
771
+ E2 = QM.gen(0)
772
+ R = self.base_ring()
773
+ u = R(12).inverse_of_unit()
774
+ hom_comp = self.homogeneous_components()
775
+
776
+ return sum(f.serre_derivative() + R(k) * u * f * E2 for k, f in hom_comp.items())
777
+
778
+ def _compute(self, X: list) -> list:
779
+ r"""
780
+ Compute the coefficients of `q^n` of the `q`-expansion of this,
781
+ graded quasimodular form for `n` in the list `X`.
782
+
783
+ The results are not cached. (Use coefficients for cached results).
784
+
785
+ EXAMPLES::
786
+
787
+ sage: E2 = QuasiModularForms(1).0
788
+ sage: E2.q_expansion(10)
789
+ 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 - 288*q^6 - 192*q^7 - 360*q^8 - 312*q^9 + O(q^10)
790
+ sage: E2._compute([3, 6])
791
+ [-96, -288]
792
+ sage: E2._compute([])
793
+ []
794
+ """
795
+ if not isinstance(X, list) or not X:
796
+ return []
797
+ bound = max(X)
798
+ q_exp = self.q_expansion(bound + 1)
799
+ return [q_exp[i] for i in X]
800
+
801
+ def coefficients(self, X):
802
+ r"""
803
+ Return the coefficients of `q^n` of the `q`-expansion of this,
804
+ graded quasimodular form for `n` in the list `X`.
805
+
806
+ If X is an integer, return coefficients for indices from 1
807
+ to X. This method caches the result.
808
+
809
+ EXAMPLES::
810
+
811
+ sage: E2, E4 = QuasiModularForms(1).0, QuasiModularForms(1).1
812
+ sage: f = E2^2
813
+ sage: g = E2^3 * E4
814
+ sage: f.coefficients(10)
815
+ [-48, 432, 3264, 9456, 21600, 39744, 66432, 105840, 147984, 220320]
816
+ sage: f.coefficients([0,1])
817
+ [1, -48]
818
+ sage: f.coefficients([0,1,2,3])
819
+ [1, -48, 432, 3264]
820
+ sage: f.coefficients([2,3])
821
+ [432, 3264]
822
+ sage: g.coefficients(10)
823
+ [168,
824
+ -13608,
825
+ 210336,
826
+ 1805496,
827
+ -22562064,
828
+ -322437024,
829
+ -2063087808,
830
+ -9165872520,
831
+ -32250917496,
832
+ -96383477232]
833
+ sage: g.coefficients([3, 7])
834
+ [210336, -2063087808]
835
+ """
836
+ try:
837
+ self.__coefficients
838
+ except AttributeError:
839
+ self.__coefficients = {}
840
+ if isinstance(X, Integer):
841
+ X = list(range(1, X + 1))
842
+ Y = [n for n in X if n not in self.__coefficients]
843
+ v = self._compute(Y)
844
+ for i in range(len(v)):
845
+ self.__coefficients[Y[i]] = v[i]
846
+ return [self.__coefficients[x] for x in X]