passagemath-schemes 10.6.40__cp314-cp314-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (314) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.6.40.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.40.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.40.dist-info/RECORD +314 -0
  9. passagemath_schemes-10.6.40.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.40.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +745 -0
  29. sage/lfunctions/pari.py +818 -0
  30. sage/lfunctions/zero_sums.cpython-314-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5135 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
  34. sage/modular/abvar/abvar_newform.py +244 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +186 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +720 -0
  40. sage/modular/abvar/homspace.py +998 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +740 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1402 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +363 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +653 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1469 -0
  57. sage/modular/arithgroup/congroup_generic.py +628 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +267 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1066 -0
  61. sage/modular/arithgroup/tests.py +418 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3753 -0
  64. sage/modular/btquotients/pautomorphicform.py +2570 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1109 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +569 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1065 -0
  77. sage/modular/hecke/algebra.py +746 -0
  78. sage/modular/hecke/all.py +20 -0
  79. sage/modular/hecke/ambient_module.py +1019 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +325 -0
  82. sage/modular/hecke/hecke_operator.py +780 -0
  83. sage/modular/hecke/homspace.py +206 -0
  84. sage/modular/hecke/module.py +1767 -0
  85. sage/modular/hecke/morphism.py +174 -0
  86. sage/modular/hecke/submodule.py +989 -0
  87. sage/modular/hypergeometric_misc.cpython-314-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2017 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1071 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +815 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +124 -0
  101. sage/modular/modform/ambient_g1.py +204 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +505 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4131 -0
  108. sage/modular/modform/find_generators.py +59 -0
  109. sage/modular/modform/half_integral.py +154 -0
  110. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  111. sage/modular/modform/j_invariant.py +47 -0
  112. sage/modular/modform/l_series_gross_zagier.py +133 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314-darwin.so +0 -0
  114. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  115. sage/modular/modform/notes.py +45 -0
  116. sage/modular/modform/numerical.py +514 -0
  117. sage/modular/modform/periods.py +14 -0
  118. sage/modular/modform/ring.py +1257 -0
  119. sage/modular/modform/space.py +1860 -0
  120. sage/modular/modform/submodule.py +118 -0
  121. sage/modular/modform/tests.py +64 -0
  122. sage/modular/modform/theta.py +110 -0
  123. sage/modular/modform/vm_basis.py +381 -0
  124. sage/modular/modform/weight1.py +220 -0
  125. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  126. sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
  127. sage/modular/modform_hecketriangle/all.py +30 -0
  128. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  129. sage/modular/modform_hecketriangle/constructor.py +416 -0
  130. sage/modular/modform_hecketriangle/element.py +351 -0
  131. sage/modular/modform_hecketriangle/functors.py +752 -0
  132. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  133. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
  135. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
  136. sage/modular/modform_hecketriangle/readme.py +1214 -0
  137. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  138. sage/modular/modform_hecketriangle/space.py +1037 -0
  139. sage/modular/modform_hecketriangle/subspace.py +423 -0
  140. sage/modular/modsym/all.py +17 -0
  141. sage/modular/modsym/ambient.py +3846 -0
  142. sage/modular/modsym/boundary.py +1420 -0
  143. sage/modular/modsym/element.py +336 -0
  144. sage/modular/modsym/g1list.py +178 -0
  145. sage/modular/modsym/ghlist.py +182 -0
  146. sage/modular/modsym/hecke_operator.py +73 -0
  147. sage/modular/modsym/manin_symbol.cpython-314-darwin.so +0 -0
  148. sage/modular/modsym/manin_symbol.pxd +5 -0
  149. sage/modular/modsym/manin_symbol.pyx +497 -0
  150. sage/modular/modsym/manin_symbol_list.py +1295 -0
  151. sage/modular/modsym/modsym.py +400 -0
  152. sage/modular/modsym/modular_symbols.py +384 -0
  153. sage/modular/modsym/p1list.cpython-314-darwin.so +0 -0
  154. sage/modular/modsym/p1list.pxd +29 -0
  155. sage/modular/modsym/p1list.pyx +1372 -0
  156. sage/modular/modsym/p1list_nf.py +1241 -0
  157. sage/modular/modsym/relation_matrix.py +591 -0
  158. sage/modular/modsym/relation_matrix_pyx.cpython-314-darwin.so +0 -0
  159. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  160. sage/modular/modsym/space.py +2468 -0
  161. sage/modular/modsym/subspace.py +455 -0
  162. sage/modular/modsym/tests.py +375 -0
  163. sage/modular/multiple_zeta.py +2632 -0
  164. sage/modular/multiple_zeta_F_algebra.py +786 -0
  165. sage/modular/overconvergent/all.py +6 -0
  166. sage/modular/overconvergent/genus0.py +1878 -0
  167. sage/modular/overconvergent/hecke_series.py +1187 -0
  168. sage/modular/overconvergent/weightspace.py +778 -0
  169. sage/modular/pollack_stevens/all.py +4 -0
  170. sage/modular/pollack_stevens/distributions.py +874 -0
  171. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  172. sage/modular/pollack_stevens/manin_map.py +859 -0
  173. sage/modular/pollack_stevens/modsym.py +1593 -0
  174. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  175. sage/modular/pollack_stevens/sigma0.py +534 -0
  176. sage/modular/pollack_stevens/space.py +1076 -0
  177. sage/modular/quasimodform/all.py +3 -0
  178. sage/modular/quasimodform/element.py +845 -0
  179. sage/modular/quasimodform/ring.py +828 -0
  180. sage/modular/quatalg/all.py +3 -0
  181. sage/modular/quatalg/brandt.py +1642 -0
  182. sage/modular/ssmod/all.py +8 -0
  183. sage/modular/ssmod/ssmod.py +827 -0
  184. sage/rings/all__sagemath_schemes.py +1 -0
  185. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  186. sage/rings/polynomial/binary_form_reduce.py +585 -0
  187. sage/schemes/all.py +41 -0
  188. sage/schemes/berkovich/all.py +6 -0
  189. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  190. sage/schemes/berkovich/berkovich_space.py +748 -0
  191. sage/schemes/curves/affine_curve.py +2928 -0
  192. sage/schemes/curves/all.py +33 -0
  193. sage/schemes/curves/closed_point.py +434 -0
  194. sage/schemes/curves/constructor.py +381 -0
  195. sage/schemes/curves/curve.py +542 -0
  196. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  197. sage/schemes/curves/point.py +463 -0
  198. sage/schemes/curves/projective_curve.py +3026 -0
  199. sage/schemes/curves/zariski_vankampen.py +1932 -0
  200. sage/schemes/cyclic_covers/all.py +2 -0
  201. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  202. sage/schemes/cyclic_covers/constructor.py +137 -0
  203. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  204. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  205. sage/schemes/elliptic_curves/BSD.py +1036 -0
  206. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  207. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  208. sage/schemes/elliptic_curves/all.py +49 -0
  209. sage/schemes/elliptic_curves/cardinality.py +609 -0
  210. sage/schemes/elliptic_curves/cm.py +1102 -0
  211. sage/schemes/elliptic_curves/constructor.py +1552 -0
  212. sage/schemes/elliptic_curves/ec_database.py +175 -0
  213. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  214. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  215. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  216. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
  217. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  218. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  219. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  220. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  221. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  222. sage/schemes/elliptic_curves/ell_point.py +4787 -0
  223. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
  224. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  225. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  226. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  227. sage/schemes/elliptic_curves/formal_group.py +760 -0
  228. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  229. sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
  230. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  231. sage/schemes/elliptic_curves/heegner.py +7335 -0
  232. sage/schemes/elliptic_curves/height.py +2109 -0
  233. sage/schemes/elliptic_curves/hom.py +1406 -0
  234. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  235. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  236. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  237. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  238. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  239. sage/schemes/elliptic_curves/homset.py +271 -0
  240. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  241. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  242. sage/schemes/elliptic_curves/jacobian.py +237 -0
  243. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  244. sage/schemes/elliptic_curves/kraus.py +1014 -0
  245. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  246. sage/schemes/elliptic_curves/mod5family.py +105 -0
  247. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  248. sage/schemes/elliptic_curves/mod_sym_num.cpython-314-darwin.so +0 -0
  249. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  250. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  251. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  252. sage/schemes/elliptic_curves/padics.py +1816 -0
  253. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  254. sage/schemes/elliptic_curves/period_lattice_region.cpython-314-darwin.so +0 -0
  255. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  256. sage/schemes/elliptic_curves/saturation.py +715 -0
  257. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  258. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  259. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  260. sage/schemes/hyperelliptic_curves/all.py +6 -0
  261. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  265. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  266. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  267. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  271. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  272. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  273. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  274. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  275. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  276. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  277. sage/schemes/jacobians/all.py +2 -0
  278. sage/schemes/overview.py +161 -0
  279. sage/schemes/plane_conics/all.py +22 -0
  280. sage/schemes/plane_conics/con_field.py +1296 -0
  281. sage/schemes/plane_conics/con_finite_field.py +158 -0
  282. sage/schemes/plane_conics/con_number_field.py +456 -0
  283. sage/schemes/plane_conics/con_rational_field.py +406 -0
  284. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  285. sage/schemes/plane_conics/constructor.py +249 -0
  286. sage/schemes/plane_quartics/all.py +2 -0
  287. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  288. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  289. sage/schemes/riemann_surfaces/all.py +1 -0
  290. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  291. sage_wheels/share/cremona/cremona_mini.db +0 -0
  292. sage_wheels/share/ellcurves/rank0 +30427 -0
  293. sage_wheels/share/ellcurves/rank1 +31871 -0
  294. sage_wheels/share/ellcurves/rank10 +6 -0
  295. sage_wheels/share/ellcurves/rank11 +6 -0
  296. sage_wheels/share/ellcurves/rank12 +1 -0
  297. sage_wheels/share/ellcurves/rank14 +1 -0
  298. sage_wheels/share/ellcurves/rank15 +1 -0
  299. sage_wheels/share/ellcurves/rank17 +1 -0
  300. sage_wheels/share/ellcurves/rank19 +1 -0
  301. sage_wheels/share/ellcurves/rank2 +2388 -0
  302. sage_wheels/share/ellcurves/rank20 +1 -0
  303. sage_wheels/share/ellcurves/rank21 +1 -0
  304. sage_wheels/share/ellcurves/rank22 +1 -0
  305. sage_wheels/share/ellcurves/rank23 +1 -0
  306. sage_wheels/share/ellcurves/rank24 +1 -0
  307. sage_wheels/share/ellcurves/rank28 +1 -0
  308. sage_wheels/share/ellcurves/rank3 +836 -0
  309. sage_wheels/share/ellcurves/rank4 +10 -0
  310. sage_wheels/share/ellcurves/rank5 +5 -0
  311. sage_wheels/share/ellcurves/rank6 +5 -0
  312. sage_wheels/share/ellcurves/rank7 +5 -0
  313. sage_wheels/share/ellcurves/rank8 +6 -0
  314. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,3846 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.libs.flint sage.libs.pari
3
+ r"""
4
+ Ambient spaces of modular symbols
5
+
6
+ This module defines the following classes. There is an abstract base
7
+ class ``ModularSymbolsAmbient``, derived from
8
+ ``space.ModularSymbolsSpace`` and ``hecke.AmbientHeckeModule``. As
9
+ this is an abstract base class, only derived classes should be
10
+ instantiated. There are five derived classes:
11
+
12
+ - ``ModularSymbolsAmbient_wtk_g0``, for modular symbols of general
13
+ weight `k` for `\Gamma_0(N)`;
14
+
15
+ - ``ModularSymbolsAmbient_wt2_g0`` (derived from
16
+ ``ModularSymbolsAmbient_wtk_g0``), for modular symbols of weight 2
17
+ for `\Gamma_0(N)`;
18
+
19
+ - ``ModularSymbolsAmbient_wtk_g1``, for modular symbols of general
20
+ weight `k` for `\Gamma_1(N)`;
21
+
22
+ - ``ModularSymbolsAmbient_wtk_gamma_h``, for modular symbols of
23
+ general weight `k` for `\Gamma_H`, where `H` is a subgroup of
24
+ `\ZZ/N\ZZ`;
25
+
26
+ - ``ModularSymbolsAmbient_wtk_eps``, for modular symbols of general
27
+ weight `k` and character `\epsilon`.
28
+
29
+ EXAMPLES:
30
+
31
+ We compute a space of modular symbols modulo 2. The dimension is
32
+ different from that of the corresponding space in characteristic
33
+ 0::
34
+
35
+ sage: M = ModularSymbols(11,4,base_ring=GF(2)); M
36
+ Modular Symbols space of dimension 7 for Gamma_0(11) of weight 4
37
+ with sign 0 over Finite Field of size 2
38
+ sage: M.basis()
39
+ ([X*Y,(1,0)], [X*Y,(1,8)], [X*Y,(1,9)], [X^2,(0,1)], [X^2,(1,8)], [X^2,(1,9)], [X^2,(1,10)])
40
+ sage: M0 = ModularSymbols(11,4,base_ring=QQ); M0
41
+ Modular Symbols space of dimension 6 for Gamma_0(11) of weight 4
42
+ with sign 0 over Rational Field
43
+ sage: M0.basis()
44
+ ([X^2,(0,1)], [X^2,(1,6)], [X^2,(1,7)], [X^2,(1,8)], [X^2,(1,9)], [X^2,(1,10)])
45
+
46
+ The characteristic polynomial of the Hecke operator `T_2` has an extra
47
+ factor `x`.
48
+
49
+ ::
50
+
51
+ sage: M.T(2).matrix().fcp('x')
52
+ (x + 1)^2 * x^5
53
+ sage: M0.T(2).matrix().fcp('x')
54
+ (x - 9)^2 * (x^2 - 2*x - 2)^2
55
+ """
56
+
57
+ ################################################################################
58
+ # Sage: Open Source Mathematical Software
59
+ #
60
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
61
+ #
62
+ # Distributed under the terms of the GNU General Public License (GPL)
63
+ #
64
+ # This code is distributed in the hope that it will be useful,
65
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
66
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
67
+ # General Public License for more details.
68
+ #
69
+ # The full text of the GPL is available at:
70
+ #
71
+ # https://www.gnu.org/licenses/
72
+ ################################################################################
73
+
74
+ import sage.modular.arithgroup.all as arithgroup
75
+
76
+ from sage.arith.misc import is_prime, divisors, number_of_divisors, crt
77
+ from sage.categories.homset import Hom
78
+ from sage.matrix.matrix_space import MatrixSpace
79
+ from sage.misc.cachefunc import cached_method
80
+ from sage.misc.latex import latex
81
+ from sage.misc.verbose import verbose
82
+ from sage.modular.arithgroup.arithgroup_element import M2Z
83
+ from sage.modular.dirichlet import DirichletCharacter, TrivialCharacter
84
+ from sage.modular.hecke.ambient_module import AmbientHeckeModule
85
+ from sage.modular.cusps import Cusp
86
+ from sage.modular.modsym.apply import apply_to_monomial
87
+ from sage.modular.modsym.manin_symbol import ManinSymbol
88
+ from sage.modular.modsym.manin_symbol_list import (ManinSymbolList_gamma0,
89
+ ManinSymbolList_gamma1,
90
+ ManinSymbolList_gamma_h,
91
+ ManinSymbolList_character)
92
+ from sage.modules.free_module import FreeModule_generic
93
+ from sage.modules.free_module_element import FreeModuleElement
94
+ from sage.rings.integer import Integer
95
+ from sage.rings.integer_ring import ZZ
96
+ from sage.rings.polynomial.multi_polynomial import MPolynomial
97
+ from sage.rings.rational_field import QQ
98
+ from sage.categories.fields import Fields
99
+ from sage.structure.factorization import Factorization
100
+ from sage.structure.formal_sum import FormalSum
101
+
102
+ from . import boundary
103
+ from . import element
104
+ from . import heilbronn
105
+ from . import modular_symbols
106
+ from . import modsym
107
+ from . import p1list
108
+ from . import relation_matrix
109
+ from .space import ModularSymbolsSpace
110
+ from . import subspace
111
+
112
+
113
+ class ModularSymbolsAmbient(ModularSymbolsSpace, AmbientHeckeModule):
114
+ r"""
115
+ An ambient space of modular symbols for a congruence subgroup of
116
+ `SL_2(\ZZ)`.
117
+
118
+ This class is an abstract base class, so only derived classes
119
+ should be instantiated.
120
+
121
+ INPUT:
122
+
123
+ - ``weight`` -- integer
124
+ - ``group`` -- a congruence subgroup
125
+ - ``sign`` -- integer; either -1, 0, or 1
126
+ - ``base_ring`` -- a commutative ring
127
+ - ``custom_init`` -- a function that is called with ``self`` as input
128
+ before any computations are done using self; this could be used
129
+ to set a custom modular symbols presentation
130
+
131
+ TESTS::
132
+
133
+ sage: ModularSymbols(11,2) == ModularSymbols(11,2)
134
+ True
135
+ sage: ModularSymbols(11,2) == ModularSymbols(11,4)
136
+ False
137
+ sage: ModularSymbols(11,2) != ModularSymbols(11,2)
138
+ False
139
+ sage: ModularSymbols(11,2) != ModularSymbols(11,4)
140
+ True
141
+ sage: hash(ModularSymbols(11,2)) != hash(ModularSymbols(11,4))
142
+ True
143
+ """
144
+ def __init__(self, group, weight, sign, base_ring,
145
+ character=None, custom_init=None, category=None):
146
+ """
147
+ Initialize a space of modular symbols.
148
+
149
+ INPUT:
150
+
151
+ - ``weight`` -- integer
152
+
153
+ - ``group`` -- a congruence subgroup
154
+
155
+ - ``sign`` -- integer, either -1, 0, or 1
156
+
157
+ - ``base_ring`` -- a commutative ring
158
+
159
+ EXAMPLES::
160
+
161
+ sage: ModularSymbols(2,2)
162
+ Modular Symbols space of dimension 1 for Gamma_0(2) of weight 2 with sign 0 over Rational Field
163
+ """
164
+ weight = int(weight)
165
+ if weight <= 1:
166
+ raise ValueError("Weight (=%s) Modular symbols of weight <= 1 not defined." % weight)
167
+ if not isinstance(group, arithgroup.CongruenceSubgroupBase):
168
+ raise TypeError("group must be a congruence subgroup")
169
+
170
+ sign = int(sign)
171
+ if base_ring not in Fields():
172
+ raise TypeError("base_ring must be a field")
173
+
174
+ if character is None and isinstance(group, arithgroup.Gamma0_class):
175
+ character = TrivialCharacter(group.level(), base_ring)
176
+
177
+ ModularSymbolsSpace.__init__(self, group, weight,
178
+ character, sign, base_ring,
179
+ category=category)
180
+
181
+ if custom_init is not None:
182
+ custom_init(self)
183
+
184
+ try:
185
+ formula = self._dimension_formula()
186
+ except NotImplementedError:
187
+ formula = None
188
+
189
+ rank = self.rank()
190
+ if formula is not None:
191
+ assert rank == formula, \
192
+ "Computed dimension (=%s) of ambient space \"%s\" doesn't match dimension formula (=%s)!\n" % (rank, self, formula) + \
193
+ "ModularSymbolsAmbient: group = %s, weight = %s, sign = %s, base_ring = %s, character = %s" % (
194
+ group, weight, sign, base_ring, character)
195
+
196
+ AmbientHeckeModule.__init__(self, base_ring, rank, group.level(), weight, category=category)
197
+
198
+ def new_submodule(self, p=None):
199
+ r"""
200
+ Return the new or `p`-new submodule of this modular symbols ambient space.
201
+
202
+ INPUT:
203
+
204
+ - ``p`` -- (default: ``None``) if not ``None``, return only
205
+ the `p`-new submodule
206
+
207
+ OUTPUT: the new or `p`-new submodule of this modular symbols ambient space
208
+
209
+ EXAMPLES::
210
+
211
+ sage: ModularSymbols(100).new_submodule()
212
+ Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 31 for Gamma_0(100) of weight 2 with sign 0 over Rational Field
213
+ sage: ModularSymbols(389).new_submodule()
214
+ Modular Symbols space of dimension 65 for Gamma_0(389) of weight 2 with sign 0 over Rational Field
215
+ """
216
+ # Check for special cases where the answer is easy.
217
+ # If not in one of those cases, use the generic code.
218
+ if self.level().is_prime() and self.weight() == 2:
219
+ return self
220
+ return AmbientHeckeModule.new_submodule(self, p=p)
221
+
222
+ def manin_symbols(self):
223
+ """
224
+ Return the list of Manin symbols for this modular symbols ambient space.
225
+
226
+ EXAMPLES::
227
+
228
+ sage: ModularSymbols(11,2).manin_symbols()
229
+ Manin Symbol List of weight 2 for Gamma0(11)
230
+ """
231
+ raise NotImplementedError
232
+
233
+ def manin_generators(self):
234
+ """
235
+ Return list of all Manin symbols for this space. These are the
236
+ generators in the presentation of this space by Manin symbols.
237
+
238
+ EXAMPLES::
239
+
240
+ sage: M = ModularSymbols(2,2)
241
+ sage: M.manin_generators()
242
+ [(0,1), (1,0), (1,1)]
243
+
244
+ ::
245
+
246
+ sage: M = ModularSymbols(1,6)
247
+ sage: M.manin_generators()
248
+ [[Y^4,(0,0)], [X*Y^3,(0,0)], [X^2*Y^2,(0,0)], [X^3*Y,(0,0)], [X^4,(0,0)]]
249
+ """
250
+ return self._manin_generators
251
+
252
+ def manin_basis(self):
253
+ r"""
254
+ Return a list of indices into the list of Manin generators (see
255
+ ``self.manin_generators()``) such that those symbols
256
+ form a basis for the quotient of the `\QQ`-vector
257
+ space spanned by Manin symbols modulo the relations.
258
+
259
+ EXAMPLES::
260
+
261
+ sage: M = ModularSymbols(2,2)
262
+ sage: M.manin_basis()
263
+ [1]
264
+ sage: [M.manin_generators()[i] for i in M.manin_basis()]
265
+ [(1,0)]
266
+ sage: M = ModularSymbols(6,2)
267
+ sage: M.manin_basis()
268
+ [1, 10, 11]
269
+ sage: [M.manin_generators()[i] for i in M.manin_basis()]
270
+ [(1,0), (3,1), (3,2)]
271
+ """
272
+ try:
273
+ return self._manin_basis
274
+ except AttributeError:
275
+ self.compute_presentation()
276
+ return self._manin_basis
277
+
278
+ def p1list(self):
279
+ """
280
+ Return a P1list of the level of this modular symbol space.
281
+
282
+ EXAMPLES::
283
+
284
+ sage: ModularSymbols(11,2).p1list()
285
+ The projective line over the integers modulo 11
286
+ """
287
+ try:
288
+ return self.__p1list
289
+ except AttributeError:
290
+ self.__p1list = p1list.P1List(self.level())
291
+ return self.__p1list
292
+
293
+ # See the file relation_matrix.py
294
+ #
295
+ # def relation_matrix(self):
296
+ # raise NotImplementedError
297
+
298
+ def compute_presentation(self):
299
+ r"""
300
+ Compute and cache the presentation of this space.
301
+
302
+ EXAMPLES::
303
+
304
+ sage: ModularSymbols(11,2).compute_presentation() # no output
305
+ """
306
+ B, basis, mod = relation_matrix.compute_presentation(
307
+ self.manin_symbols(), self.sign(),
308
+ self.base_ring())
309
+ self._manin_generators = self.manin_symbols().manin_symbol_list()
310
+ self._manin_basis = basis
311
+ self._manin_gens_to_basis = B
312
+ self._mod2term = mod
313
+
314
+ def manin_gens_to_basis(self):
315
+ r"""
316
+ Return the matrix expressing the manin symbol generators in terms of the basis.
317
+
318
+ EXAMPLES::
319
+
320
+ sage: ModularSymbols(11,2).manin_gens_to_basis()
321
+ [-1 0 0]
322
+ [ 1 0 0]
323
+ [ 0 0 0]
324
+ [ 0 0 1]
325
+ [ 0 -1 1]
326
+ [ 0 -1 0]
327
+ [ 0 0 -1]
328
+ [ 0 0 -1]
329
+ [ 0 1 -1]
330
+ [ 0 1 0]
331
+ [ 0 0 1]
332
+ [ 0 0 0]
333
+ """
334
+ try:
335
+ return self._manin_gens_to_basis
336
+ except AttributeError:
337
+ self.compute_presentation()
338
+ return self._manin_gens_to_basis
339
+
340
+ #####################################################################
341
+ # Coercion
342
+ #####################################################################
343
+ def _element_constructor_(self, x, computed_with_hecke=False):
344
+ r"""
345
+ Coerce `x` into this modular symbols space. The result is
346
+ either an element of ``self`` or a subspace of ``self``.
347
+
348
+ INPUT:
349
+
350
+ The allowed input types for `x` are as follows:
351
+
352
+ - ``Vector`` -- a vector of the same degree. This
353
+ defines the corresponding linear combination of the basis of ``self``
354
+
355
+ - ``ManinSymbol`` -- a Manin symbol of the same weight
356
+ as the space
357
+
358
+ - ``ModularSymbolsElement`` -- a modular symbol whose
359
+ ambient parent is this space of modular symbols. (TODO: make more
360
+ sophisticated)
361
+
362
+ - 0 -- the integer 0; results in the 0 modular symbol
363
+
364
+ - 3-tuple -- given a 3-tuple (i,u,v), returns the modular symbol
365
+ element defined by the Manin symbol
366
+ `[X^{i}\cdot Y^{k-2-i}, (u,v)]`, where k is the weight.
367
+ Note that we must have `0\leq i \leq k-2`.
368
+
369
+ - 2-tuple -- given a 2-tuple (u,v), returns the element defined by
370
+ the Manin symbol `[X^0 \cdot Y^{2-k}, (u,v)]`
371
+
372
+ - 2-elements list -- given a list ``[alpha, beta]``,
373
+ where `\alpha` and `\beta` are (coercible to)
374
+ cusps, return the modular symbol `\{\alpha, \beta\}`. When
375
+ the weight `k > 2` return
376
+ `Y^{k-2} \{\alpha, \beta\}`.
377
+
378
+ - 3-element list -- given a list ``[i, alpha, beta]``,
379
+ where `i` is an integer, and `\alpha`,
380
+ `\beta` are (coercible to) cusps, return the modular symbol
381
+ `X^i Y^{k-2-i} \{\alpha, \beta\}`.
382
+
383
+ If our list is ``[f, alpha, beta]``, where `f`
384
+ is a homogeneous polynomial in two variables of degree k-2 with
385
+ integer coefficients, and alpha and beta are cusps, return the
386
+ corresponding sum of modular symbols as an element of ``self``. So if
387
+ `f = \sum_{i=0}^{k-2} a_i X^i Y^{k-2-i}`, return
388
+ `\sum_{i=0}^{k-2} a_i * [ i, alpha, beta ]`.
389
+
390
+ EXAMPLES::
391
+
392
+ sage: M = ModularSymbols(37,2)
393
+
394
+ M(0) is the 0 element of the space::
395
+
396
+ sage: M(0)
397
+ 0
398
+ sage: type(M(0))
399
+ <class 'sage.modular.modsym.ambient.ModularSymbolsAmbient_wt2_g0_with_category.element_class'>
400
+
401
+ From a vector of the correct dimension we construct the
402
+ corresponding linear combination of the basis elements::
403
+
404
+ sage: M.dimension()
405
+ 5
406
+ sage: M.basis()
407
+ ((1,0), (1,23), (1,32), (1,34), (1,35))
408
+ sage: M(vector([1,2,3,4,5]))
409
+ (1,0) + 2*(1,23) + 3*(1,32) + 4*(1,34) + 5*(1,35)
410
+ sage: M(vector([1/2,2/3,3/4,4/5,5/6]))
411
+ 1/2*(1,0) + 2/3*(1,23) + 3/4*(1,32) + 4/5*(1,34) + 5/6*(1,35)
412
+
413
+ Manin symbols can be converted to elements of the space::
414
+
415
+ sage: S = M.manin_symbols()
416
+ sage: S((0,2,3))
417
+ (2,3)
418
+ sage: M( S((0,2,3)) )
419
+ (1,34) - (1,35)
420
+
421
+ However, it is easier to use one of the following forms.
422
+ Either a 3-tuple `(i,u,v)` or a 2-tuple `(u,v)` with `i=0`
423
+ assumed::
424
+
425
+ sage: M((0,2,3))
426
+ (1,34) - (1,35)
427
+ sage: M((2,3))
428
+ (1,34) - (1,35)
429
+
430
+ Or a 3-list `[i,\alpha,\beta]` where `i` is the degree and
431
+ `\alpha` and `beta` are cusps, or a 2-tuple `[\alpha,\beta]`
432
+ with `i=0` assumed::
433
+
434
+ sage: M([0,Cusp(1/2),Cusp(0)])
435
+ (1,35)
436
+ sage: M([Cusp(1/2),Cusp(0)])
437
+ (1,35)
438
+ """
439
+ if isinstance(x, FreeModuleElement):
440
+ if x.degree() != self.dimension():
441
+ raise TypeError("Incompatible degrees: x has degree "
442
+ f"{x.degree()} but modular symbols space has "
443
+ f"dimension {self.dimension()}")
444
+ return self.element_class(self, x)
445
+
446
+ elif isinstance(x, (ManinSymbol, element.ModularSymbolsElement)):
447
+ return self.element(x)
448
+
449
+ elif isinstance(x, modular_symbols.ModularSymbol):
450
+ return self(x.manin_symbol_rep())
451
+
452
+ elif isinstance(x, (int, Integer)) and x == 0:
453
+ return self.element_class(self, self.free_module()(0))
454
+
455
+ elif isinstance(x, tuple):
456
+ return self.manin_symbol(x)
457
+
458
+ elif isinstance(x, FormalSum):
459
+ return sum([c * self(y) for c, y in x], self(0))
460
+
461
+ elif isinstance(x, list):
462
+ if len(x) == 3 and isinstance(x[0], MPolynomial):
463
+ return self.modular_symbol_sum(x)
464
+ else:
465
+ return self.modular_symbol(x)
466
+
467
+ raise TypeError("No coercion of %s into %s defined." % (x, self))
468
+
469
+ def change_ring(self, R):
470
+ r"""
471
+ Change the base ring to R.
472
+
473
+ EXAMPLES::
474
+
475
+ sage: ModularSymbols(Gamma1(13), 2).change_ring(GF(17))
476
+ Modular Symbols space of dimension 15 for Gamma_1(13) of weight 2 with sign 0 over Finite Field of size 17
477
+ sage: M = ModularSymbols(DirichletGroup(5).0, 7); MM=M.change_ring(CyclotomicField(8)); MM
478
+ Modular Symbols space of dimension 6 and level 5, weight 7, character [zeta8^2], sign 0, over Cyclotomic Field of order 8 and degree 4
479
+ sage: MM.change_ring(CyclotomicField(4)) == M
480
+ True
481
+ sage: M.change_ring(QQ)
482
+ Traceback (most recent call last):
483
+ ...
484
+ TypeError: Unable to coerce zeta4 to a rational
485
+
486
+ Similarly with :meth:`base_extend`::
487
+
488
+ sage: M = ModularSymbols(DirichletGroup(5).0, 7); MM = M.base_extend(CyclotomicField(8)); MM
489
+ Modular Symbols space of dimension 6 and level 5, weight 7, character [zeta8^2], sign 0, over Cyclotomic Field of order 8 and degree 4
490
+ sage: MM.base_extend(CyclotomicField(4))
491
+ Traceback (most recent call last):
492
+ ...
493
+ TypeError: Base extension of self (over 'Cyclotomic Field of order 8 and degree 4') to ring 'Cyclotomic Field of order 4 and degree 2' not defined.
494
+ """
495
+ if self.character() is None:
496
+ return modsym.ModularSymbols(self.group(), self.weight(), self.sign(), R)
497
+ else:
498
+ return modsym.ModularSymbols(self.character(), self.weight(), self.sign(), R)
499
+
500
+ def _action_on_modular_symbols(self, g):
501
+ r"""
502
+ Return the matrix of the action of a 2x2 matrix on this space.
503
+
504
+ INPUT:
505
+
506
+ - ``g`` -- list; `g=[a,b,c,d]` where `a,b,c,d` are integers
507
+ defining a `2\times2` integer matrix
508
+
509
+ OUTPUT:
510
+
511
+ (matrix) The matrix of the action of `g` on this Modular
512
+ Symbol space, with respect to the standard basis.
513
+
514
+ .. NOTE::
515
+
516
+ Use ``_matrix_of_operator_on_modular_symbols`` for more general
517
+ operators.
518
+
519
+ EXAMPLES::
520
+
521
+ sage: M = ModularSymbols(11,4,1)
522
+ sage: M._action_on_modular_symbols([1,2,3,7])
523
+ [0 0 1 0]
524
+ [0 0 0 1]
525
+ [0 1 0 0]
526
+ [0 1 0 0]
527
+ """
528
+ if not isinstance(g, list):
529
+ raise TypeError("g must be a list")
530
+ if not len(g) == 4:
531
+ raise TypeError("g must be a list of length 4")
532
+ return self._matrix_of_operator_on_modular_symbols(self, [g])
533
+
534
+ def manin_symbol(self, x, check=True):
535
+ r"""
536
+ Construct a Manin Symbol from the given data.
537
+
538
+ INPUT:
539
+
540
+ - ``x`` -- list; either `[u,v]` or `[i,u,v]`, where `0\le
541
+ i\le k-2` where `k` is the weight, and `u`,`v` are integers
542
+ defining a valid element of `\mathbb{P}^1(N)`, where `N` is
543
+ the level
544
+
545
+ OUTPUT:
546
+
547
+ (ManinSymbol) the Manin Symbol associated to `[i;(u,v)]`, with
548
+ `i=0` if not supplied, corresponding to the monomial symbol
549
+ `[X^i*Y^{k-2-i}, (u,v)]`.
550
+
551
+ EXAMPLES::
552
+
553
+ sage: M = ModularSymbols(11,4,1)
554
+ sage: M.manin_symbol([2,5,6])
555
+ -2/3*[X^2,(1,6)] + 5/3*[X^2,(1,9)]
556
+ """
557
+ if check:
558
+ if len(x) == 2:
559
+ x = (0, x[0], x[1])
560
+ if len(x) == 3:
561
+ # Manin symbol of the form (i, u, v), which corresponds to [X^i*Y^(k-2-i), (u,v)].
562
+ if x[0] < 0 or x[0] > self.weight() - 2:
563
+ raise ValueError("The first entry of the tuple (=%s)\
564
+ must be an integer between 0 and k-2 (=%s)." % (
565
+ x, self.weight() - 2))
566
+ else:
567
+ raise ValueError("x (=%s) must be of length 2 or 3" % x)
568
+ # end check
569
+
570
+ N = self.level()
571
+ x = (x[0], x[1] % N, x[2] % N)
572
+ try:
573
+ return self.__manin_symbol[x]
574
+ except AttributeError:
575
+ self.__manin_symbol = {}
576
+ except KeyError:
577
+ pass
578
+ y = self.manin_symbols()(x)
579
+ z = self(y)
580
+ self.__manin_symbol[x] = z
581
+ return z
582
+
583
+ def _modular_symbol_0_to_alpha(self, alpha, i=0):
584
+ r"""
585
+ Return the modular symbol `\{0,\alpha\}` in this space.
586
+
587
+ INPUT:
588
+
589
+ - ``alpha`` -- rational or Infinity a cusp
590
+
591
+ - ``i`` -- integer (default: 0); the degree of the symbol
592
+
593
+ OUTPUT:
594
+
595
+ (ModularSymbol) The modular symbol `X^iY^{k-2-i}\{0,\alpha\}`.
596
+
597
+ EXAMPLES::
598
+
599
+ sage: M = ModularSymbols(11,4,1)
600
+ sage: M._modular_symbol_0_to_alpha(Cusp(3/5))
601
+ 11*[X^2,(1,4)] + 40/3*[X^2,(1,6)] - 1/3*[X^2,(1,9)]
602
+ sage: M._modular_symbol_0_to_alpha(Cusp(3/5),1)
603
+ 15/2*[X^2,(1,4)] + 20/3*[X^2,(1,6)] + 5/6*[X^2,(1,9)]
604
+ sage: M._modular_symbol_0_to_alpha(Cusp(Infinity))
605
+ 2/3*[X^2,(1,6)] - 5/3*[X^2,(1,9)]
606
+ sage: M._modular_symbol_0_to_alpha(Cusp(Infinity),1)
607
+ 0
608
+ """
609
+ if alpha.is_infinity():
610
+ return self.manin_symbol((i, 0, 1), check=False)
611
+ # v, c = arith.continued_fraction_list(alpha._rational_(), partial_convergents=True)
612
+ cf = alpha._rational_().continued_fraction()
613
+ v = list(cf)
614
+ c = [(cf.p(k), cf.q(k)) for k in range(len(cf))]
615
+ a = self(0)
616
+ one = ZZ.one()
617
+ two = ZZ(2)
618
+ if self.weight() > two:
619
+ R = ZZ['X']
620
+ X = R.gen(0)
621
+ # need to add first two terms, which aren't necessarily
622
+ # zero in this case. we do the first here, and the
623
+ # second in the k=0 case below, so as to avoid code
624
+ # duplication
625
+ a += self.manin_symbol((i, 0, 1), check=False)
626
+ for k in range(len(c)):
627
+ # matrix entries associated to this partial sum
628
+ if k == 0:
629
+ x = c[0][0]
630
+ y = -1
631
+ z = 1
632
+ w = 0
633
+ else:
634
+ x = c[k][0]
635
+ y = c[k-1][0]
636
+ z = c[k][1]
637
+ w = c[k-1][1]
638
+ if k % 2 == 0:
639
+ y = -y
640
+ w = -w
641
+
642
+ # two options here: write out the polynomial directly,
643
+ # and deal with all the separate cases, or create two
644
+ # polynomials and then exponentiate and multiply them.
645
+ # given how fast ntl/flint/etc are, the second may
646
+ # be faster.
647
+
648
+ # method 1: write out solution. this is currently
649
+ # incorrect, because it ends up doing 0^0 in the sum,
650
+ # so I'll fix it and do timings soon.
651
+ # for s in range(self.weight()-two+1):
652
+ # coeff = sum([ binomial(i,t)*binomial(self.weight()-two-i,s-t)*
653
+ # x**t * y**(i-t) * z**(s-t) *
654
+ # w**(self.weight()-two-i-s+t) for t in range(0,s) ])
655
+ # m = coeff * self.manin_symbol((s, y, w), check=False)
656
+ # a += m
657
+
658
+ # method 2
659
+ p1 = x*X+y
660
+ p2 = z*X+w
661
+ if i == 0:
662
+ p1 = R(one)
663
+ if (self.weight()-2-i == 0):
664
+ p2 = R(one)
665
+ poly = (p1**i) * (p2**(self.weight()-2-i))
666
+ for s in range(self.weight()-1): # k-2+1 = k-1
667
+ a += poly[s] * self.manin_symbol((s, z, w), check=False)
668
+ else:
669
+ for k in range(1, len(c)):
670
+ u = c[k][1]
671
+ v = c[k-1][1]
672
+ if k % 2 == 0:
673
+ v = -v
674
+ x = self.manin_symbol((i, u, v), check=False)
675
+ a += x
676
+ return a
677
+
678
+ def modular_symbol(self, x, check=True):
679
+ r"""
680
+ Create a modular symbol in this space.
681
+
682
+ INPUT:
683
+
684
+ - ``x`` -- list of either 2 or 3 entries:
685
+
686
+ - 2 entries: `[\alpha, \beta]` where `\alpha` and `\beta`
687
+ are cusps;
688
+
689
+ - 3 entries: `[i, \alpha, \beta]` where `0\le i\le k-2`
690
+ and `\alpha` and `\beta` are cusps;
691
+
692
+ - ``check`` -- boolean (default: ``True``); flag that determines
693
+ whether the input ``x`` needs processing: use check=False
694
+ for efficiency if the input ``x`` is a list of length 3 whose
695
+ first entry is an Integer, and whose second and third
696
+ entries are Cusps (see examples).
697
+
698
+ OUTPUT:
699
+
700
+ (Modular Symbol) The modular symbol `Y^{k-2}\{\alpha,
701
+ \beta\}`. or `X^i Y^{k-2-i}\{\alpha,\beta\}`.
702
+
703
+ EXAMPLES::
704
+
705
+ sage: set_modsym_print_mode('modular')
706
+ sage: M = ModularSymbols(11)
707
+ sage: M.modular_symbol([2/11, oo])
708
+ -{-1/9, 0}
709
+ sage: M.1
710
+ {-1/8, 0}
711
+ sage: M.modular_symbol([-1/8, 0])
712
+ {-1/8, 0}
713
+ sage: M.modular_symbol([0, -1/8, 0])
714
+ {-1/8, 0}
715
+ sage: M.modular_symbol([10, -1/8, 0])
716
+ Traceback (most recent call last):
717
+ ...
718
+ ValueError: The first entry of the tuple (=[10, -1/8, 0]) must be an integer between 0 and k-2 (=0).
719
+
720
+ ::
721
+
722
+ sage: N = ModularSymbols(6,4)
723
+ sage: set_modsym_print_mode('manin')
724
+ sage: N([1,Cusp(-1/4),Cusp(0)])
725
+ 17/2*[X^2,(2,3)] - 9/2*[X^2,(2,5)] + 15/2*[X^2,(3,1)] - 15/2*[X^2,(3,2)]
726
+ sage: N([1,Cusp(-1/2),Cusp(0)])
727
+ 1/2*[X^2,(2,3)] + 3/2*[X^2,(2,5)] + 3/2*[X^2,(3,1)] - 3/2*[X^2,(3,2)]
728
+
729
+ Use check=False for efficiency if the input x is a list of length 3
730
+ whose first entry is an Integer, and whose second and third entries
731
+ are cusps::
732
+
733
+ sage: M.modular_symbol([0, Cusp(2/11), Cusp(oo)], check=False)
734
+ -(1,9)
735
+
736
+ ::
737
+
738
+ sage: set_modsym_print_mode() # return to default.
739
+ """
740
+ if check:
741
+ if len(x) == 2:
742
+ x = [0, x[0], x[1]]
743
+ elif len(x) == 3:
744
+ if x[0] < 0 or x[0] > self.weight()-2:
745
+ raise ValueError("The first entry of the tuple (=%s)\
746
+ must be an integer between 0 and k-2 (=%s)." % (
747
+ x, self.weight()-2))
748
+ else:
749
+ raise ValueError("x (=%s) must be of length 2 or 3" % x)
750
+ i = Integer(x[0])
751
+ alpha = Cusp(x[1])
752
+ beta = Cusp(x[2])
753
+ else:
754
+ i = x[0]
755
+ alpha = x[1]
756
+ beta = x[2]
757
+
758
+ # Compute {0,beta} - {0,alpha}
759
+ a = self._modular_symbol_0_to_alpha(alpha, i)
760
+ b = self._modular_symbol_0_to_alpha(beta, i)
761
+ return b - a
762
+
763
+ def modular_symbol_sum(self, x, check=True):
764
+ r"""
765
+ Construct a modular symbol sum.
766
+
767
+ INPUT:
768
+
769
+ - ``x`` -- list; `[f, \alpha, \beta]` where `f =
770
+ \sum_{i=0}^{k-2} a_i X^i Y^{k-2-i}` is a homogeneous
771
+ polynomial over `\ZZ` of degree `k` and `\alpha` and `\beta`
772
+ are cusps.
773
+
774
+ - ``check`` -- boolean (default: ``True``); if ``True`` check the
775
+ validity of the input tuple ``x``
776
+
777
+ OUTPUT:
778
+
779
+ The sum `\sum_{i=0}^{k-2} a_i [ i, \alpha, \beta ]` as an
780
+ element of this modular symbol space.
781
+
782
+ EXAMPLES::
783
+
784
+ sage: M = ModularSymbols(11,4)
785
+ sage: R.<X,Y>=QQ[]
786
+ sage: M.modular_symbol_sum([X*Y,Cusp(0),Cusp(Infinity)])
787
+ -3/14*[X^2,(1,6)] + 1/14*[X^2,(1,7)] - 1/14*[X^2,(1,8)] + 1/2*[X^2,(1,9)] - 2/7*[X^2,(1,10)]
788
+ """
789
+ if check:
790
+ if len(x) != 3:
791
+ raise ValueError("%s must have length 3" % x)
792
+ f = x[0]
793
+ R = self.base_ring()['X', 'Y']
794
+ X = R.gen(0)
795
+ try:
796
+ f = R(f)
797
+ except TypeError:
798
+ raise ValueError("f must be coercible to a polynomial \
799
+ over %s" % self.base_ring())
800
+ if (not f.is_homogeneous()) or (f.degree() != self.weight()-2):
801
+ raise ValueError("f must be a homogeneous polynomial of degree k-2")
802
+ alpha = Cusp(x[1])
803
+ beta = Cusp(x[2])
804
+ else:
805
+ f = x[0]
806
+ R = self.base_ring()
807
+ X = R.gen(0)
808
+ alpha = x[1]
809
+ beta = x[2]
810
+
811
+ s = self(0)
812
+
813
+ for term in f.monomials():
814
+ deg = term.degree(X)
815
+ a = self._modular_symbol_0_to_alpha(alpha, deg)
816
+ b = self._modular_symbol_0_to_alpha(beta, deg)
817
+ s += f.monomial_coefficient(term) * (b - a)
818
+
819
+ return s
820
+
821
+ def _compute_dual_hecke_matrix(self, n):
822
+ r"""
823
+ Return the matrix of the dual Hecke operator `T(n)`.
824
+
825
+ INPUT:
826
+
827
+ - ``n`` -- positive integer
828
+
829
+ OUTPUT:
830
+
831
+ (matrix) The matrix of the dual of `T(n)`.
832
+
833
+ EXAMPLES::
834
+
835
+ sage: M = ModularSymbols(11,4,1)
836
+ sage: M._compute_dual_hecke_matrix(5)
837
+ [ 126 0 0 0]
838
+ [ 2 63 62 38]
839
+ [ 26/3 -20 -27 -4]
840
+ [-32/3 83 91 92]
841
+ """
842
+ return self.hecke_matrix(n).transpose()
843
+
844
+ def _compute_hecke_matrix_prime(self, p, rows=None):
845
+ """
846
+ Return the matrix of the Hecke operator `T(p)`.
847
+
848
+ INPUT:
849
+
850
+ - ``p`` -- integer; a prime number
851
+
852
+ - ``rows`` -- list or ``None`` (default); if not ``None``, a list of
853
+ the rows which should be computed, otherwise the complete
854
+ matrix will be computed
855
+
856
+ .. NOTE::
857
+
858
+ `p` does not have to be prime despite the function name.
859
+
860
+ OUTPUT:
861
+
862
+ (matrix) The matrix of the Hecke operator `T(p)` on this
863
+ space, with respect to its standard basis.
864
+
865
+ ALGORITHM:
866
+
867
+ Use Heilbronn-Cremona matrices if `p` is prime, else use
868
+ Heilbronn-Merel matrices.
869
+
870
+ EXAMPLES:
871
+
872
+ We first compute some examples for Gamma0(N)::
873
+
874
+ sage: m = ModularSymbols(2, weight=4)
875
+ sage: m._compute_hecke_matrix_prime(2).charpoly('x')
876
+ x^2 - 9*x + 8
877
+
878
+ ::
879
+
880
+ sage: m = ModularSymbols(1,weight=12)
881
+ sage: m._compute_hecke_matrix_prime(2).charpoly('x')
882
+ x^3 - 2001*x^2 - 97776*x - 1180224
883
+ sage: m._compute_hecke_matrix_prime(13).charpoly('x')
884
+ x^3 - 1792159238562*x^2 - 2070797989680255444*x - 598189440899986203208472
885
+
886
+ ::
887
+
888
+ sage: m = ModularSymbols(1,weight=12, sign=-1)
889
+ sage: m._compute_hecke_matrix_prime(5)
890
+ [4830]
891
+ sage: m._compute_hecke_matrix_prime(23)
892
+ [18643272]
893
+
894
+ ::
895
+
896
+ sage: m = ModularSymbols(3,4)
897
+ sage: m._compute_hecke_matrix_prime(2).charpoly('x')
898
+ x^2 - 18*x + 81
899
+
900
+ ::
901
+
902
+ sage: m = ModularSymbols(6,4)
903
+ sage: m._compute_hecke_matrix_prime(2).charpoly('x')
904
+ x^6 - 14*x^5 + 29*x^4 + 172*x^3 - 124*x^2 - 320*x + 256
905
+ sage: m._compute_hecke_matrix_prime(3).charpoly('x')
906
+ x^6 - 50*x^5 + 511*x^4 + 3012*x^3 - 801*x^2 - 9234*x + 6561
907
+
908
+ ::
909
+
910
+ sage: m = ModularSymbols(15,4, sign=-1)
911
+ sage: m._compute_hecke_matrix_prime(3).charpoly('x')
912
+ x^4 - 2*x^3 + 18*x^2 + 18*x - 243
913
+
914
+ ::
915
+
916
+ sage: m = ModularSymbols(6,4)
917
+ sage: m._compute_hecke_matrix_prime(7).charpoly('x')
918
+ x^6 - 1344*x^5 + 666240*x^4 - 140462080*x^3 + 8974602240*x^2 + 406424518656*x + 3584872677376
919
+
920
+ ::
921
+
922
+ sage: m = ModularSymbols(4,4)
923
+ sage: m._compute_hecke_matrix_prime(3).charpoly('x')
924
+ x^3 - 84*x^2 + 2352*x - 21952
925
+
926
+ We now compute some examples for modular symbols on Gamma1(N)::
927
+
928
+ sage: m = ModularSymbols(Gamma1(13),2, sign=-1)
929
+ sage: m._compute_hecke_matrix_prime(2).charpoly('x')
930
+ x^2 + 3*x + 3
931
+
932
+ The following is an example with odd weight::
933
+
934
+ sage: m = ModularSymbols(Gamma1(5),3)
935
+ sage: m._compute_hecke_matrix_prime(2).charpoly('x')
936
+ x^4 - 10*x^3 + 50*x^2 - 170*x + 289
937
+
938
+ This example has composite conductor and weight2 dividing the
939
+ conductor and nontrivial sign::
940
+
941
+ sage: m = ModularSymbols(Gamma1(9),3, sign=1)
942
+ sage: m._compute_hecke_matrix_prime(3).charpoly('x')
943
+ x^6 + 3*x^4 - 19*x^3 + 24*x^2 - 9*x
944
+
945
+ In some situations we do not need all the rows of the result, and can thereby save time::
946
+
947
+ sage: m = ModularSymbols(1,weight=12)
948
+ sage: m._compute_hecke_matrix_prime(2)
949
+ [ -24 0 0]
950
+ [ 0 -24 0]
951
+ [4860 0 2049]
952
+ sage: m._compute_hecke_matrix_prime(2,rows=[0,1])
953
+ [-24 0 0]
954
+ [ 0 -24 0]
955
+ sage: m._compute_hecke_matrix_prime(2,rows=[1,2])
956
+ [ 0 -24 0]
957
+ [4860 0 2049]
958
+ """
959
+ # note -- p doesn't have to be prime despite the function name
960
+ p = int(Integer(p)) # go through Integer so p = 2.5 gives an error.
961
+ if isinstance(rows, list):
962
+ rows = tuple(rows)
963
+ try:
964
+ return self._hecke_matrices[(p, rows)]
965
+ except AttributeError:
966
+ self._hecke_matrices = {}
967
+ except KeyError:
968
+ pass
969
+ tm = verbose("Computing Hecke operator T_%s" % p)
970
+
971
+ if is_prime(p):
972
+ H = heilbronn.HeilbronnCremona(p)
973
+ else:
974
+ H = heilbronn.HeilbronnMerel(p)
975
+
976
+ B = self.manin_basis()
977
+ if rows is not None:
978
+ B = [B[i] for i in rows]
979
+ mod2term = self._mod2term
980
+ R = self.manin_gens_to_basis()
981
+ K = self.base_ring()
982
+ W = R.new_matrix(nrows=len(B), ncols=R.nrows())
983
+ syms = self.manin_symbols()
984
+ j = 0
985
+ for i in B:
986
+ for h in H:
987
+ entries = syms.apply(i, h)
988
+ for k, x in entries:
989
+ f, s = mod2term[k]
990
+ if s:
991
+ # W[j,f] = W[j,f] + s*K(x)
992
+ W.add_to_entry(j, f, s * K(x))
993
+ j += 1
994
+ tm = verbose("start matrix multiply", tm)
995
+ if hasattr(W, '_matrix_times_matrix_dense'):
996
+ Tp = W._matrix_times_matrix_dense(R)
997
+ verbose("done matrix multiply and computing Hecke operator", tm)
998
+ else:
999
+ Tp = W * R
1000
+ tm = verbose("done matrix multiply", tm)
1001
+ Tp = Tp.dense_matrix()
1002
+ verbose("done making Hecke operator matrix dense", tm)
1003
+ self._hecke_matrices[(p, rows)] = Tp
1004
+ return Tp
1005
+
1006
+ def __heilbronn_operator(self, M, H, t=1):
1007
+ r"""
1008
+ Return the matrix function to the space `M` defined by `H`, `t`.
1009
+
1010
+ .. NOTE::
1011
+
1012
+ Users will instead use the simpler interface defined, for
1013
+ example, by ``hecke_matrix()`` (see examples).
1014
+
1015
+ INPUT:
1016
+
1017
+ - ``M`` -- ModularSymbols; codomain (a space of modular symbols)
1018
+
1019
+ - ``H`` -- list of matrices in `M_2(\ZZ)`
1020
+
1021
+ - ``t`` -- integer (default: 1)
1022
+
1023
+ OUTPUT:
1024
+
1025
+ (free module morphism) A function from the Modular Symbol
1026
+ space to the Modular Symbol space `M` defined by `t` and the
1027
+ matrices in `H`.
1028
+
1029
+ EXAMPLES::
1030
+
1031
+ sage: M = ModularSymbols(37,2)
1032
+ sage: M._ModularSymbolsAmbient__heilbronn_operator(M,HeilbronnCremona(3))
1033
+ Hecke module morphism Heilbronn operator(The Cremona-Heilbronn matrices of determinant 3,1) defined by the matrix
1034
+ [ 4 0 0 0 -1]
1035
+ [ 0 -1 2 2 -2]
1036
+ [ 0 2 -1 2 0]
1037
+ [ 0 0 0 -3 2]
1038
+ [ 0 0 0 0 1]
1039
+ Domain: Modular Symbols space of dimension 5 for Gamma_0(37) of weight ...
1040
+ Codomain: Modular Symbols space of dimension 5 for Gamma_0(37) of weight ...
1041
+
1042
+ sage: M.hecke_matrix(3)
1043
+ [ 4 0 0 0 -1]
1044
+ [ 0 -1 2 2 -2]
1045
+ [ 0 2 -1 2 0]
1046
+ [ 0 0 0 -3 2]
1047
+ [ 0 0 0 0 1]
1048
+ """
1049
+
1050
+ MS = MatrixSpace(self.base_ring(), self.dimension(), M.dimension())
1051
+ hom = self.Hom(M)
1052
+ if self.dimension() == 0 or M.dimension() == 0:
1053
+ A = MS(0)
1054
+ return hom(A, "Heilbronn operator(%s,%s)" % (H, t))
1055
+
1056
+ rows = []
1057
+ B = self.manin_basis()
1058
+ syms = self.manin_symbols()
1059
+ k = self.weight()
1060
+ for n in B:
1061
+ z = M(0)
1062
+ i, u, v = syms[n].tuple()
1063
+ # We apply each Heilbronn matrix to the
1064
+ # Manin symbol [X^i*Y^(k-2-i), (u,v)]
1065
+ for h in H:
1066
+ # Apply h to the polynomial part
1067
+ a, b, c, d = tuple(h)
1068
+ # P gives the ordered coefficients of (a*X+b*Y)^i*(c*X+d*Y)^(j-i)
1069
+ P = apply_to_monomial(i, k-2, a, b, c, d)
1070
+ # Apply h to the (u,v) part of the Manin symbol
1071
+ (uu, vv) = (u*a+v*c, u*b+v*d)
1072
+
1073
+ # For the generalized Heilbronn operator, we through away any
1074
+ # symbols for which the (u,v) part of the symbol doesn't have
1075
+ # both entries divisible by t.
1076
+ if t != 1:
1077
+ if uu % t != 0 or vv % t != 0:
1078
+ continue
1079
+ uu = uu//t
1080
+ vv = vv//t
1081
+
1082
+ # Now coerce each Manin symbol
1083
+ #
1084
+ # P[m]*[X^m*Y^(k-2-m), (uu,vv)], for m=0,...,len(P)
1085
+ #
1086
+ # into the image space M and add that to z.
1087
+ # Note that we coerce in Manin symbols as tuples.
1088
+ for m in range(len(P)):
1089
+ x = M((m, uu, vv))
1090
+ z += x*P[m]
1091
+
1092
+ rows.append(z.element())
1093
+
1094
+ A = MS(rows)
1095
+ return hom(A, "Heilbronn operator(%s,%s)" % (H, t))
1096
+
1097
+ def _repr_(self):
1098
+ r"""
1099
+ String representation of this Modular Symbols space.
1100
+
1101
+ EXAMPLES::
1102
+
1103
+ sage: m = ModularSymbols(1,weight=12)
1104
+ sage: m # indirect doctest
1105
+ Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field
1106
+ """
1107
+ return "Modular Symbols space of dimension %s and weight %s for %s with sign %s and character %s over %s" % (
1108
+ self.dimension(), self.weight(), self.group(), self.sign(), self.character()._repr_short_(), self.base_ring())
1109
+
1110
+ def _latex_(self):
1111
+ r"""
1112
+ Latex representation of this Modular Symbols space.
1113
+
1114
+ EXAMPLES::
1115
+
1116
+ sage: m = ModularSymbols(11,weight=12)
1117
+ sage: latex(m) # indirect doctest
1118
+ \mathrm{ModSym}_{12}(\Gamma_0(11),\left[1\right];\Bold{Q})
1119
+
1120
+ sage: chi = DirichletGroup(7).0
1121
+ sage: m = ModularSymbols(chi)
1122
+ sage: latex(m)
1123
+ \mathrm{ModSym}_{2}(\Gamma_1(7),\left[\zeta_{6}\right];\Bold{Q}(\zeta_{6}))
1124
+ """
1125
+ return "\\mathrm{ModSym}_{%s}(%s,%s;%s)" % (self.weight(),
1126
+ latex(self.group()),
1127
+ latex(list(self.character().values_on_gens())),
1128
+ latex(self.base_ring()))
1129
+
1130
+ def _matrix_of_operator_on_modular_symbols(self, codomain, R):
1131
+ r"""
1132
+ Return the matrix of a modular symbols operator.
1133
+
1134
+ .. NOTE::
1135
+
1136
+ Users will usually instead use the simpler interface
1137
+ defined, for example, by ``hecke_matrix()`` (see examples),
1138
+ though this function allows one to compute much more
1139
+ general operators.
1140
+
1141
+ INPUT:
1142
+
1143
+ - ``codomain`` -- space of modular symbols
1144
+
1145
+ - ``R`` -- list of lists `[a,b,c,d]` of length 4,
1146
+ which we view as elements of `GL_2(`QQ)`
1147
+
1148
+ OUTPUT:
1149
+
1150
+ The matrix of the operator
1151
+
1152
+ .. MATH::
1153
+
1154
+ x \mapsto \sum_{g in R} g.x,
1155
+
1156
+
1157
+ where `g.x` is the formal linear fractional transformation on modular
1158
+ symbols, with respect to the standard basis.
1159
+
1160
+ EXAMPLES::
1161
+
1162
+ sage: M = ModularSymbols(37,2)
1163
+ sage: M._matrix_of_operator_on_modular_symbols(M,HeilbronnCremona(3))
1164
+ [ 4 0 0 0 0]
1165
+ [ 0 -3 1 1 0]
1166
+ [ 0 3 0 5 -2]
1167
+ [ 0 -3 1 -5 3]
1168
+ [ 0 0 2 3 -3]
1169
+ """
1170
+ rows = []
1171
+ for b in self.basis():
1172
+ v = FormalSum(0, check=False)
1173
+ for c, x in b.modular_symbol_rep():
1174
+ for g in R:
1175
+ y = x.apply(g)
1176
+ v += y*c
1177
+ w = codomain(v).element()
1178
+ rows.append(w)
1179
+ M = MatrixSpace(self.base_ring(), len(rows), codomain.degree(), sparse=False)
1180
+ return M(rows)
1181
+
1182
+ def _compute_atkin_lehner_matrix(self, d):
1183
+ r"""
1184
+ Return the matrix of the Atkin-Lehner operator `W_d`.
1185
+
1186
+ INPUT:
1187
+
1188
+ - ``d`` -- integer that divides the level
1189
+
1190
+ OUTPUT: the matrix of the operator `W_d` with respect to the standard
1191
+ basis
1192
+
1193
+ EXAMPLES: An example at level 29::
1194
+
1195
+ sage: M = ModularSymbols((DirichletGroup(29,QQ).0), 2,1); M
1196
+ Modular Symbols space of dimension 4 and level 29, weight 2, character [-1], sign 1, over Rational Field
1197
+ sage: w = M._compute_atkin_lehner_matrix(29)
1198
+ sage: w^2 == 1
1199
+ True
1200
+ sage: w.fcp()
1201
+ (x - 1)^2 * (x + 1)^2
1202
+
1203
+ This doesn't work since the character is not trivial or quadratic::
1204
+
1205
+ sage: M = ModularSymbols((DirichletGroup(13).0), 2,1); M
1206
+ Modular Symbols space of dimension 0 and level 13, weight 2, character [zeta12], sign 1, over Cyclotomic Field of order 12 and degree 4
1207
+ sage: M._compute_atkin_lehner_matrix(13)
1208
+ Traceback (most recent call last):
1209
+ ...
1210
+ ValueError: Atkin-Lehner W_d only defined when d-primary part of character is trivial or quadratic
1211
+
1212
+ Note that Atkin-Lehner does make sense on `\Gamma_1(13)`,
1213
+ but doesn't commute with the Hecke operators::
1214
+
1215
+ sage: M = ModularSymbols(Gamma1(13),2)
1216
+ sage: w = M.atkin_lehner_operator(13).matrix()
1217
+ sage: t = M.T(2).matrix()
1218
+ sage: t*w == w*t
1219
+ False
1220
+ sage: t * w * ~t * ~w == M.diamond_bracket_matrix(2)
1221
+ True
1222
+ sage: w^2 == 1
1223
+ True
1224
+
1225
+ For `\Gamma_1(N)` levels, when `d` is a proper factor of `N`, the
1226
+ square of the operator `W_d` is not a scalar any more::
1227
+
1228
+ sage: M = ModularSymbols(Gamma1(10), 2)
1229
+ sage: w = M.atkin_lehner_operator(2).matrix()
1230
+ sage: w^2 == M.diamond_bracket_matrix(7)
1231
+ True
1232
+
1233
+ In higher weights, the operator is defined, but its eigenvalues are no longer roots of unity::
1234
+
1235
+ sage: M = ModularSymbols(Gamma1(13), 3)
1236
+ sage: w = M.atkin_lehner_operator(13).matrix()
1237
+ sage: w**2 == -13
1238
+ True
1239
+
1240
+ TESTS:
1241
+
1242
+ Check that signed spaces are handled gracefully::
1243
+
1244
+ sage: M = ModularSymbols(Gamma1(18), 3, sign=1)
1245
+ sage: M.atkin_lehner_operator(2).matrix().fcp()
1246
+ (x^2 + 2)^3 * (x^4 - 2*x^2 + 4)^3
1247
+ sage: M.atkin_lehner_operator(9)
1248
+ Traceback (most recent call last):
1249
+ ...
1250
+ ValueError: Atkin-Lehner operator not defined on signed space (use sign=0)
1251
+
1252
+ GammaH spaces work::
1253
+
1254
+ sage: G = GammaH(25, [6])
1255
+ sage: ModularSymbols(G, sign=0).atkin_lehner_operator().fcp()
1256
+ (x - 1)^5 * (x + 1)^6
1257
+ """
1258
+ N = self.level()
1259
+
1260
+ chi = self.character()
1261
+ if chi is not None:
1262
+ dec = [u for u in chi.decomposition() if chi.modulus().divides(d)]
1263
+ if not all((u**2).is_trivial() for u in dec):
1264
+ raise ValueError("Atkin-Lehner W_d only defined when d-primary part of character is trivial or quadratic")
1265
+
1266
+ if self.sign() != 0:
1267
+ # AL operator problematic on signed spaces
1268
+ if self.diamond_bracket_matrix(crt(-1, 1, d, N/d)) != 1:
1269
+ raise ValueError("Atkin-Lehner operator not defined on signed space (use sign=0)")
1270
+
1271
+ W = self.group().atkin_lehner_matrix(d).list()
1272
+ return self._action_on_modular_symbols(W)
1273
+
1274
+ def boundary_map(self):
1275
+ r"""
1276
+ Return the boundary map to the corresponding space of boundary modular
1277
+ symbols.
1278
+
1279
+ EXAMPLES::
1280
+
1281
+ sage: ModularSymbols(20,2).boundary_map()
1282
+ Hecke module morphism boundary map defined by the matrix
1283
+ [ 1 -1 0 0 0 0]
1284
+ [ 0 1 -1 0 0 0]
1285
+ [ 0 1 0 -1 0 0]
1286
+ [ 0 0 0 -1 1 0]
1287
+ [ 0 1 0 -1 0 0]
1288
+ [ 0 0 1 -1 0 0]
1289
+ [ 0 1 0 0 0 -1]
1290
+ Domain: Modular Symbols space of dimension 7 for Gamma_0(20) of weight ...
1291
+ Codomain: Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(20) ...
1292
+ sage: type(ModularSymbols(20,2).boundary_map())
1293
+ <class 'sage.modular.hecke.morphism.HeckeModuleMorphism_matrix'>
1294
+ """
1295
+ try:
1296
+ return self.__boundary_map
1297
+ except AttributeError:
1298
+ # compute boundary map
1299
+ B = self.boundary_space()
1300
+ I = [B(b) for b in self.basis()]
1301
+ W = MatrixSpace(self.base_ring(), len(I), B.rank(), sparse=True)
1302
+
1303
+ # Note -- the underlying elements have degree the number of distinct
1304
+ # cusps known when the element was computed. This isn't constant,
1305
+ # so we pad the elements.
1306
+ E = [x.element() for x in I]
1307
+ zero = self.base_ring()(0)
1308
+ n = int(B.dimension())
1309
+ E = sum([list(x) + [zero]*(n - len(x)) for x in E], [])
1310
+
1311
+ A = W(E)
1312
+ H = Hom(self, B)
1313
+ self.__boundary_map = H(A, "boundary map")
1314
+ return self.__boundary_map
1315
+
1316
+ def cusps(self):
1317
+ r"""
1318
+ Return the set of cusps for this modular symbols space.
1319
+
1320
+ EXAMPLES::
1321
+
1322
+ sage: ModularSymbols(20,2).cusps()
1323
+ [Infinity, 0, -1/4, 1/5, -1/2, 1/10]
1324
+ """
1325
+ try:
1326
+ return self.__cusps
1327
+ except AttributeError:
1328
+ f = self.boundary_map()
1329
+ B = f.codomain()
1330
+ C = B._known_cusps()
1331
+ self.__cusps = C
1332
+ return C
1333
+
1334
+ def boundary_space(self):
1335
+ r"""
1336
+ Return the subspace of boundary modular symbols of this modular symbols ambient space.
1337
+
1338
+ EXAMPLES::
1339
+
1340
+ sage: M = ModularSymbols(20, 2)
1341
+ sage: B = M.boundary_space(); B
1342
+ Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(20) of weight 2 over Rational Field
1343
+ sage: M.cusps()
1344
+ [Infinity, 0, -1/4, 1/5, -1/2, 1/10]
1345
+ sage: M.dimension()
1346
+ 7
1347
+ sage: B.dimension()
1348
+ 6
1349
+ """
1350
+ raise NotImplementedError
1351
+
1352
+ def cuspidal_submodule(self):
1353
+ """
1354
+ The cuspidal submodule of this modular symbols ambient space.
1355
+
1356
+ EXAMPLES::
1357
+
1358
+ sage: M = ModularSymbols(12,2,0,GF(5)) ; M
1359
+ Modular Symbols space of dimension 5 for Gamma_0(12) of weight 2 with sign 0 over Finite Field of size 5
1360
+ sage: M.cuspidal_submodule()
1361
+ Modular Symbols subspace of dimension 0 of Modular Symbols space of dimension 5 for Gamma_0(12) of weight 2 with sign 0 over Finite Field of size 5
1362
+ sage: ModularSymbols(1,24,-1).cuspidal_submodule()
1363
+ Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 2 for Gamma_0(1) of weight 24 with sign -1 over Rational Field
1364
+
1365
+ The cuspidal submodule of the cuspidal submodule is itself::
1366
+
1367
+ sage: M = ModularSymbols(389)
1368
+ sage: S = M.cuspidal_submodule()
1369
+ sage: S.cuspidal_submodule() is S
1370
+ True
1371
+ """
1372
+ try:
1373
+ return self.__cuspidal_submodule
1374
+ except AttributeError:
1375
+ try:
1376
+ if self.__is_cuspidal:
1377
+ return self
1378
+ except AttributeError:
1379
+ pass
1380
+ S = self.boundary_map().kernel()
1381
+ S._set_is_cuspidal(True)
1382
+ S._is_full_hecke_module = True
1383
+ # We know the cuspidal subspace is stable, so
1384
+ # if it's one-dimensional, it must be simple
1385
+ if S.dimension() == 1:
1386
+ S._is_simple = True
1387
+ if self.base_ring().characteristic() == 0:
1388
+ d = self._cuspidal_submodule_dimension_formula()
1389
+ if d is not None:
1390
+ assert d == S.dimension(), "According to dimension formulas the cuspidal subspace of \"%s\" has dimension %s; however, computing it using modular symbols we obtained %s, so there is a bug (please report!)." % (self, d, S.dimension())
1391
+ self.__cuspidal_submodule = S
1392
+ return self.__cuspidal_submodule
1393
+
1394
+ def _degeneracy_raising_matrix(self, M, t):
1395
+ r"""
1396
+ Return the matrix of the level-raising degeneracy map from ``self`` to M,
1397
+ of index t. This is calculated by composing the level-raising matrix
1398
+ for `t = 1` with a Hecke operator.
1399
+
1400
+ INPUT:
1401
+
1402
+ - ``M`` -- integer; a space of modular symbols whose level is an
1403
+ integer multiple of the level of ``self``
1404
+
1405
+ - ``t`` -- positive integer dividing the quotient of the two levels
1406
+
1407
+ OUTPUT:
1408
+
1409
+ (matrix) The matrix of the degeneracy map of index `t` from this space
1410
+ of level `N` to the space `M` (of level a multiple of `N`). Here `t` is
1411
+ a divisor of the quotient.
1412
+
1413
+ EXAMPLES::
1414
+
1415
+ sage: A = ModularSymbols(11, 2); B = ModularSymbols(22, 2)
1416
+ sage: A._degeneracy_raising_matrix(B, 1)
1417
+ [ 1 0 0 0 0 -1 -1]
1418
+ [ 0 1 0 -3 1 1 -1]
1419
+ [ 0 1 1 -1 -1 0 0]
1420
+ sage: A._degeneracy_raising_matrix(B, 2)
1421
+ [ 2 0 0 0 1 0 -1]
1422
+ [ 0 0 -1 3 -1 -1 1]
1423
+ [ 0 -1 -1 1 0 1 -1]
1424
+
1425
+ Check that :issue:`13198` is fixed::
1426
+
1427
+ sage: M22 = ModularSymbols(Gamma1(22), sign=1)
1428
+ sage: M2 = ModularSymbols(Gamma1(2))
1429
+ sage: d1 = M2.degeneracy_map(M22,1)
1430
+ sage: d2 = M2.degeneracy_map(M22,11)
1431
+ sage: M22.hecke_matrix(17).restrict((d1.image() + d2.image()).free_module())
1432
+ [18 0]
1433
+ [ 0 18]
1434
+ sage: S = M22.cuspidal_submodule()
1435
+ sage: S.new_submodule().intersection(S.old_submodule()) == S.zero_submodule()
1436
+ True
1437
+ """
1438
+ if t == 1:
1439
+ return self._degeneracy_raising_matrix_1(M)
1440
+ else:
1441
+ # use Hecke operator and t=1 case.
1442
+ d1 = self.degeneracy_map(M, 1).matrix()
1443
+ T = M.hecke_matrix(t)
1444
+ return (~self.base_ring()(t)) * d1 * T
1445
+
1446
+ def _degeneracy_raising_matrix_1(self, M):
1447
+ r"""
1448
+ Return the matrix of the degeneracy map to the given level
1449
+ (which must be a multiple of the level of self).
1450
+
1451
+ .. NOTE::
1452
+
1453
+ Not implemented in the base class, only in the derived classes.
1454
+
1455
+ EXAMPLES::
1456
+
1457
+ sage: M = ModularSymbols(37,4)
1458
+ sage: M._degeneracy_raising_matrix_1(ModularSymbols(74, 4))
1459
+ 20 x 58 dense matrix over Rational Field (use the '.str()' method to see the entries)
1460
+ """
1461
+ raise NotImplementedError
1462
+
1463
+ def _degeneracy_lowering_matrix(self, M, t):
1464
+ r"""
1465
+ Return the matrix of the level-lowering degeneracy map from ``self`` to M.
1466
+
1467
+ INPUT:
1468
+
1469
+ - ``M`` -- a modular symbols space whose level divides the level of
1470
+ ``self``
1471
+
1472
+ - ``t`` -- integer; a positive integer dividing the quotient of the
1473
+ levels
1474
+
1475
+ OUTPUT:
1476
+
1477
+ The matrix of the degeneracy map from this space to the space
1478
+ `M` of index `t`, where `t` is a divisor of the quotient of the levels
1479
+ of ``self`` and `M`.
1480
+
1481
+ EXAMPLES::
1482
+
1483
+ sage: M = ModularSymbols(22,2)
1484
+ sage: M._degeneracy_lowering_matrix(ModularSymbols(11, 2), 2)
1485
+ [ 1 0 0]
1486
+ [ 0 1 -1]
1487
+ [ 0 0 -1]
1488
+ [ 0 1 0]
1489
+ [ 0 0 0]
1490
+ [-1 0 1]
1491
+ [-1 0 0]
1492
+ """
1493
+ # Use Proposition 2.6.15 in Merel's 1585 paper (or Prop 15 in
1494
+ # electronic version of that paper).
1495
+ H = heilbronn.HeilbronnMerel(t)
1496
+ return self.__heilbronn_operator(M, H, t).matrix()
1497
+
1498
+ def rank(self):
1499
+ """
1500
+ Return the rank of this modular symbols ambient space.
1501
+
1502
+ OUTPUT: integer; the rank of this space of modular symbols
1503
+
1504
+ EXAMPLES::
1505
+
1506
+ sage: M = ModularSymbols(389)
1507
+ sage: M.rank()
1508
+ 65
1509
+
1510
+ ::
1511
+
1512
+ sage: ModularSymbols(11,sign=0).rank()
1513
+ 3
1514
+ sage: ModularSymbols(100,sign=0).rank()
1515
+ 31
1516
+ sage: ModularSymbols(22,sign=1).rank()
1517
+ 5
1518
+ sage: ModularSymbols(1,12).rank()
1519
+ 3
1520
+ sage: ModularSymbols(3,4).rank()
1521
+ 2
1522
+ sage: ModularSymbols(8,6,sign=-1).rank()
1523
+ 3
1524
+ """
1525
+ try:
1526
+ return self.__rank
1527
+ except AttributeError:
1528
+ self.__rank = len(self.manin_basis())
1529
+ return self.__rank
1530
+
1531
+ def eisenstein_submodule(self):
1532
+ """
1533
+ Return the Eisenstein submodule of this space of modular symbols.
1534
+
1535
+ EXAMPLES::
1536
+
1537
+ sage: ModularSymbols(20,2).eisenstein_submodule()
1538
+ Modular Symbols subspace of dimension 5 of Modular Symbols space of dimension 7 for Gamma_0(20) of weight 2 with sign 0 over Rational Field
1539
+ """
1540
+ try:
1541
+ return self.__eisenstein_submodule
1542
+ except AttributeError:
1543
+ self.__eisenstein_submodule = self.cuspidal_submodule().complement()
1544
+ return self.__eisenstein_submodule
1545
+
1546
+ def element(self, x):
1547
+ """
1548
+ Create and return an element of ``self`` from a modular symbol, if
1549
+ possible.
1550
+
1551
+ INPUT:
1552
+
1553
+ - ``x`` -- an object of one of the following types:
1554
+ ModularSymbol, ManinSymbol
1555
+
1556
+ OUTPUT: ModularSymbol - a modular symbol with parent self
1557
+
1558
+ EXAMPLES::
1559
+
1560
+ sage: M = ModularSymbols(11,4,1)
1561
+ sage: M.T(3)
1562
+ Hecke operator T_3 on Modular Symbols space of dimension 4 for Gamma_0(11) of weight 4 with sign 1 over Rational Field
1563
+ sage: M.T(3)(M.0)
1564
+ 28*[X^2,(0,1)] + 2*[X^2,(1,4)] + 2/3*[X^2,(1,6)] - 8/3*[X^2,(1,9)]
1565
+ sage: M.T(3)(M.0).element()
1566
+ (28, 2, 2/3, -8/3)
1567
+ """
1568
+ if isinstance(x, ManinSymbol):
1569
+ if not x.parent().weight() == self.weight():
1570
+ raise ArithmeticError("incompatible weights: Manin symbol\
1571
+ has weight %s, but modular symbols space has weight %s" % (
1572
+ x.parent().weight(), self.weight()))
1573
+ t = self.manin_symbols().index(x.tuple())
1574
+ if isinstance(t, tuple):
1575
+ i, scalar = t
1576
+ v = self.manin_gens_to_basis().row(i) * scalar
1577
+ else:
1578
+ v = self.manin_gens_to_basis().row(t)
1579
+ return self.element_class(self, v)
1580
+
1581
+ elif isinstance(x, element.ModularSymbolsElement):
1582
+ M = x.parent()
1583
+ if M.ambient_hecke_module() != self:
1584
+ # TODO -- sometimes do something more sophisticated here.
1585
+ raise TypeError("Modular symbol (%s) does not lie in this space." % x)
1586
+ return self(x.element())
1587
+
1588
+ else:
1589
+ raise ValueError("Cannot create element of %s from %s." % (x, self))
1590
+
1591
+ def dual_star_involution_matrix(self):
1592
+ """
1593
+ Return the matrix of the dual star involution, which is induced by
1594
+ complex conjugation on the linear dual of modular symbols.
1595
+
1596
+ EXAMPLES::
1597
+
1598
+ sage: ModularSymbols(20,2).dual_star_involution_matrix()
1599
+ [1 0 0 0 0 0 0]
1600
+ [0 1 0 0 0 0 0]
1601
+ [0 0 0 0 1 0 0]
1602
+ [0 0 0 1 0 0 0]
1603
+ [0 0 1 0 0 0 0]
1604
+ [0 0 0 0 0 1 0]
1605
+ [0 0 0 0 0 0 1]
1606
+ """
1607
+ try:
1608
+ return self.__dual_star_involution_matrix
1609
+ except AttributeError:
1610
+ pass
1611
+ self.__dual_star_involution_matrix = self.star_involution().matrix().transpose()
1612
+ return self.__dual_star_involution_matrix
1613
+
1614
+ def factorization(self):
1615
+ r"""
1616
+ Return a list of pairs `(S,e)` where `S` is spaces
1617
+ of modular symbols and ``self`` is isomorphic to the direct sum of the
1618
+ `S^e` as a module over the *anemic* Hecke algebra adjoin
1619
+ the star involution. The cuspidal `S` are all simple, but
1620
+ the Eisenstein factors need not be simple.
1621
+
1622
+ EXAMPLES::
1623
+
1624
+ sage: ModularSymbols(Gamma0(22), 2).factorization()
1625
+ (Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field)^2 *
1626
+ (Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field)^2 *
1627
+ (Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 7 for Gamma_0(22) of weight 2 with sign 0 over Rational Field)
1628
+
1629
+ ::
1630
+
1631
+ sage: ModularSymbols(1,6,0,GF(2)).factorization()
1632
+ (Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 for Gamma_0(1) of weight 6 with sign 0 over Finite Field of size 2) *
1633
+ (Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 for Gamma_0(1) of weight 6 with sign 0 over Finite Field of size 2)
1634
+
1635
+ ::
1636
+
1637
+ sage: ModularSymbols(18,2).factorization()
1638
+ (Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 7 for Gamma_0(18) of weight 2 with sign 0 over Rational Field) *
1639
+ (Modular Symbols subspace of dimension 5 of Modular Symbols space of dimension 7 for Gamma_0(18) of weight 2 with sign 0 over Rational Field)
1640
+
1641
+ ::
1642
+
1643
+ sage: M = ModularSymbols(DirichletGroup(38,CyclotomicField(3)).0^2, 2, +1); M
1644
+ Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2
1645
+ sage: M.factorization() # long time (about 8 seconds)
1646
+ (Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2) *
1647
+ (Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2) *
1648
+ (Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2) *
1649
+ (Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 7 and level 38, weight 2, character [zeta3], sign 1, over Cyclotomic Field of order 3 and degree 2)
1650
+ """
1651
+
1652
+ # EXAMPLES::
1653
+
1654
+ # sage: M = ModularSymbols(Gamma0(22), 2); M
1655
+ # Modular Symbols space of dimension 7 for Gamma_0(22) of weight 2 with sign 0 over Rational Field
1656
+ # sage: M.factorization():
1657
+ # ... print b.dimension(), b.level(), e
1658
+ # 1 11 2
1659
+ # 1 11 2
1660
+ # 1 11 2
1661
+ # 1 22 1
1662
+
1663
+ # An example with sign 1::
1664
+
1665
+ # sage: M = ModularSymbols(Gamma0(22), 2, sign=1); M
1666
+ # Modular Symbols space of dimension 5 for Gamma_0(22) of weight 2 with sign 1 over Rational Field
1667
+ # sage: for b, e in M.factorization():
1668
+ # ... print b.dimension(), b.level(), e
1669
+ # 1 11 2
1670
+ # 1 11 2
1671
+ # 1 22 1
1672
+
1673
+ # An example for Gamma1::
1674
+
1675
+ # sage: M = ModularSymbols(Gamma1(26), 2, sign=1); M
1676
+ # Modular Symbols space of dimension 33 for Gamma_1(26) of weight 2 with sign 1 over Rational Field
1677
+ # sage: for b, e in M.factorization():
1678
+ # ... print b.dimension(), b.level(), e
1679
+ # 1 13 2
1680
+ # 1 13 2
1681
+ # 1 13 2
1682
+ # 2 13 2
1683
+ # 2 13 2
1684
+ # 2 13 2
1685
+ # 2 13 2
1686
+ # 2 13 2
1687
+ # 1 26 1
1688
+ # 1 26 1
1689
+ # 1 26 1
1690
+ # 2 26 1
1691
+ # 2 26 1
1692
+
1693
+ # An example with level divisible by a square::
1694
+
1695
+ # sage: M = ModularSymbols(Gamma0(2*9),2); M
1696
+ # ???
1697
+ # sage: for b, e in M.factorization():
1698
+ # ... print b.dimension(), b.level(), e
1699
+ # ???
1700
+ try:
1701
+ return self._factorization
1702
+ except AttributeError:
1703
+ pass
1704
+
1705
+ try:
1706
+ if self._is_simple:
1707
+ return [self]
1708
+ except AttributeError:
1709
+ pass
1710
+
1711
+ D = []
1712
+
1713
+ # Treat the cuspidal and eisenstein parts separately. The
1714
+ # cuspidal part is very straightforward because of
1715
+ # Atkin-Lehner-Li theory. The eisenstein part is trickier,
1716
+ # because of E2 and that the new and old Eisenstein subspaces
1717
+ # can intersect (e.g., they do for M_2(Gamma_0(6))), even
1718
+ # in a way that involves forms other than E_2 (i.e., twists
1719
+ # of E2).
1720
+
1721
+ # 1. Cuspidal part -- compute the factors and their multiplicities
1722
+ # using Atkin-Lehner-Li.
1723
+
1724
+ # 2. Eisenstein part -- just call normal decomposition.
1725
+
1726
+ # In the special case of weight 2 we have to do a bunch of
1727
+ # annoying extra work below to deal with the Eisenstein series E_2.
1728
+
1729
+ # If the characteristic of the base ring is 2,
1730
+ # the star involution is the identity, so we
1731
+ # want to avoid adding each cuspidal submodule
1732
+ # twice.
1733
+ if self.base_ring().characteristic() == 2:
1734
+ skip_minus = True
1735
+ else:
1736
+ skip_minus = False
1737
+
1738
+ # The cuspidal part
1739
+ # We only run through spaces of level a multiple of the conductor of the character, which
1740
+ # we compute below, or set to 1 in case of Gamma_H or Gamma_1
1741
+ chi = self.character()
1742
+ cond = 1 if chi is None else chi.conductor()
1743
+ # Now actually run through the divisor levels, taking only the ones with that are
1744
+ # a multiple of the conductor.
1745
+ for d in reversed(divisors(self.level())):
1746
+ if d % cond:
1747
+ continue
1748
+ n = number_of_divisors(self.level() // d)
1749
+ M = self.modular_symbols_of_level(d)
1750
+ N = M.new_submodule().cuspidal_submodule().decomposition()
1751
+ for A in N:
1752
+ if self.sign() == 0:
1753
+ V = A.plus_submodule()
1754
+ V._is_simple = True
1755
+ D.append((V, n))
1756
+ if skip_minus:
1757
+ continue
1758
+ V = A.minus_submodule()
1759
+ V._is_simple = True
1760
+ D.append((V, n))
1761
+ else:
1762
+ A._is_simple = True
1763
+ D.append((A, n))
1764
+ # The Eisenstein part
1765
+ D.extend((E, 1) for E in
1766
+ self.eisenstein_submodule().decomposition(anemic=True))
1767
+
1768
+ r = self.dimension()
1769
+ s = sum(A.rank() * mult for A, mult in D)
1770
+ D = Factorization(D, cr=True, sort=False)
1771
+ D.sort()
1772
+ assert r == s, "bug in factorization -- self has dimension %s, but sum of dimensions of factors is %s\n%s" % (r, s, D)
1773
+ self._factorization = D
1774
+ return self._factorization
1775
+
1776
+ factor = factorization
1777
+
1778
+ def is_cuspidal(self) -> bool:
1779
+ r"""
1780
+ Return ``True`` if this space is cuspidal, else ``False``.
1781
+
1782
+ EXAMPLES::
1783
+
1784
+ sage: M = ModularSymbols(20,2)
1785
+ sage: M.is_cuspidal()
1786
+ False
1787
+ sage: S = M.cuspidal_subspace()
1788
+ sage: S.is_cuspidal()
1789
+ True
1790
+ sage: S = M.eisenstein_subspace()
1791
+ sage: S.is_cuspidal()
1792
+ False
1793
+ """
1794
+ try:
1795
+ return self.__is_cuspidal
1796
+ except AttributeError:
1797
+ S = self.ambient_hecke_module().cuspidal_submodule()
1798
+ self.__is_cuspidal = (S.dimension() == self.dimension())
1799
+ return self.__is_cuspidal
1800
+
1801
+ @cached_method
1802
+ def is_eisenstein(self) -> bool:
1803
+ r"""
1804
+ Return ``True`` if this space is Eisenstein, else ``False``.
1805
+
1806
+ EXAMPLES::
1807
+
1808
+ sage: M = ModularSymbols(20,2)
1809
+ sage: M.is_eisenstein()
1810
+ False
1811
+ sage: S = M.eisenstein_submodule()
1812
+ sage: S.is_eisenstein()
1813
+ True
1814
+ sage: S = M.cuspidal_subspace()
1815
+ sage: S.is_eisenstein()
1816
+ False
1817
+ """
1818
+ S = self.ambient_hecke_module().eisenstein_submodule()
1819
+ return self.dimension() == S.dimension()
1820
+
1821
+ def manin_symbols_basis(self):
1822
+ """
1823
+ A list of Manin symbols that form a basis for the ambient space
1824
+ ``self``.
1825
+
1826
+ OUTPUT: list of 2-tuples (if the weight is 2) or 3-tuples, which
1827
+ represent the Manin symbols basis for ``self``
1828
+
1829
+ EXAMPLES::
1830
+
1831
+ sage: m = ModularSymbols(23)
1832
+ sage: m.manin_symbols_basis()
1833
+ [(1,0), (1,17), (1,19), (1,20), (1,21)]
1834
+ sage: m = ModularSymbols(6, weight=4, sign=-1)
1835
+ sage: m.manin_symbols_basis()
1836
+ [[X^2,(2,1)]]
1837
+ """
1838
+ s = self.manin_symbols()
1839
+ return [s.manin_symbol(i) for i in self.manin_basis()]
1840
+
1841
+ def modular_symbols_of_level(self, G):
1842
+ """
1843
+ Return a space of modular symbols with the same parameters as
1844
+ this space, except the congruence subgroup is changed to `G`.
1845
+
1846
+ INPUT:
1847
+
1848
+ - ``G`` -- either a congruence subgroup or an integer to use
1849
+ as the level of such a group. The given group must either
1850
+ contain or be contained in the group defining ``self``.
1851
+
1852
+ TESTS::
1853
+
1854
+ sage: M = ModularSymbols(11)
1855
+ sage: M.modular_symbols_of_level(22)
1856
+ Modular Symbols space of dimension 7 for Gamma_0(22) of weight 2 with sign 0 over Rational Field
1857
+ sage: M.modular_symbols_of_level(Gamma1(22))
1858
+ Modular Symbols space of dimension 31 for Gamma_1(22) of weight 2 with sign 0 over Rational Field
1859
+
1860
+ sage: M = ModularSymbols(Gamma1(6))
1861
+ sage: M.modular_symbols_of_level(12)
1862
+ Modular Symbols space of dimension 9 for Gamma_1(12) of weight 2 with sign 0 over Rational Field
1863
+ sage: M.modular_symbols_of_level(Gamma0(3))
1864
+ Modular Symbols space of dimension 1 for Gamma_0(3) of weight 2 with sign 0 over Rational Field
1865
+ sage: M.modular_symbols_of_level(Gamma0(12))
1866
+ Traceback (most recent call last):
1867
+ ...
1868
+ ValueError: one subgroup must contain the other
1869
+
1870
+ sage: M = ModularSymbols(Gamma1(30),4); M
1871
+ Modular Symbols space of dimension 144 for Gamma_1(30) of weight 4 with sign 0 over Rational Field
1872
+ sage: M.modular_symbols_of_level(22)
1873
+ Traceback (most recent call last):
1874
+ ...
1875
+ ValueError: one level must divide the other
1876
+
1877
+ sage: M = ModularSymbols(GammaH(15,[7]),6)
1878
+ sage: M.modular_symbols_of_level(5)
1879
+ Modular Symbols space of dimension 4 for Gamma_0(5) of weight 6 with sign 0 over Rational Field
1880
+ sage: M.modular_symbols_of_level(30)
1881
+ Modular Symbols space of dimension 60 for Congruence Subgroup Gamma_H(30) with H generated by [7] of weight 6 with sign 0 over Rational Field
1882
+ sage: M.modular_symbols_of_level(73)
1883
+ Traceback (most recent call last):
1884
+ ...
1885
+ ValueError: one level must divide the other
1886
+ """
1887
+ if G in ZZ:
1888
+ G = self.group()._new_group_from_level(G)
1889
+ elif not (self.group().is_subgroup(G) or G.is_subgroup(self.group())):
1890
+ raise ValueError('one subgroup must contain the other')
1891
+ return modsym.ModularSymbols(G, self.weight(), self.sign(), self.base_ring())
1892
+
1893
+ def modular_symbols_of_sign(self, sign):
1894
+ r"""
1895
+ Return a space of modular symbols with the same defining
1896
+ properties (weight, level, etc.) as this space except with given
1897
+ sign.
1898
+
1899
+ INPUT:
1900
+
1901
+ - ``sign`` -- integer; a sign (`+1`, `-1` or `0`)
1902
+
1903
+ OUTPUT:
1904
+
1905
+ (ModularSymbolsAmbient) A space of modular symbols with the
1906
+ same defining properties (weight, level, etc.) as this space
1907
+ except with given sign.
1908
+
1909
+ EXAMPLES::
1910
+
1911
+ sage: M = ModularSymbols(Gamma0(11),2,sign=0)
1912
+ sage: M
1913
+ Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
1914
+ sage: M.modular_symbols_of_sign(-1)
1915
+ Modular Symbols space of dimension 1 for Gamma_0(11) of weight 2 with sign -1 over Rational Field
1916
+ sage: M = ModularSymbols(Gamma1(11),2,sign=0)
1917
+ sage: M.modular_symbols_of_sign(-1)
1918
+ Modular Symbols space of dimension 1 for Gamma_1(11) of weight 2 with sign -1 over Rational Field
1919
+ """
1920
+ if sign == self.sign():
1921
+ return self
1922
+ return modsym.ModularSymbols(self.group(), self.weight(), sign=sign, base_ring=self.base_ring())
1923
+
1924
+ def modular_symbols_of_weight(self, k):
1925
+ r"""
1926
+ Return a space of modular symbols with the same defining
1927
+ properties (weight, sign, etc.) as this space except with weight
1928
+ `k`.
1929
+
1930
+ INPUT:
1931
+
1932
+ - ``k`` -- positive integer
1933
+
1934
+ OUTPUT:
1935
+
1936
+ (ModularSymbolsAmbient) A space of modular symbols with the
1937
+ same defining properties (level, sign) as this space
1938
+ except with given weight.
1939
+
1940
+ EXAMPLES::
1941
+
1942
+ sage: M = ModularSymbols(Gamma1(6),2,sign=0)
1943
+ sage: M.modular_symbols_of_weight(3)
1944
+ Modular Symbols space of dimension 4 for Gamma_1(6) of weight 3 with sign 0 over Rational Field
1945
+ """
1946
+ if k == self.weight():
1947
+ return self
1948
+ return modsym.ModularSymbols(self.group(), weight=k, sign=self.sign(), base_ring=self.base_ring())
1949
+
1950
+ def _compute_sign_submodule(self, sign, compute_dual=True):
1951
+ r"""
1952
+ Return the subspace of ``self`` that is fixed under the star
1953
+ involution.
1954
+
1955
+ INPUT:
1956
+
1957
+ - ``sign`` -- integer (either -1 or +1)
1958
+
1959
+ - ``compute_dual`` -- boolean (default: ``True``); also
1960
+ compute dual subspace. This is useful for many algorithms.
1961
+
1962
+ OUTPUT: a subspace of modular symbols
1963
+
1964
+ EXAMPLES::
1965
+
1966
+ sage: ModularSymbols(1,12,0,GF(5)).minus_submodule() # indirect doctest
1967
+ Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Finite Field of size 5
1968
+ """
1969
+ S = self.star_involution().matrix() - self.base_ring()(sign)
1970
+ V = S.kernel()
1971
+ if compute_dual:
1972
+ Vdual = S.transpose().kernel()
1973
+ M = self.submodule(V, Vdual, check=False)
1974
+ else:
1975
+ M = self.submodule(V, check=False)
1976
+ M._set_sign(sign)
1977
+ return M
1978
+
1979
+ def star_involution(self):
1980
+ r"""
1981
+ Return the star involution on this modular symbols space.
1982
+
1983
+ OUTPUT:
1984
+
1985
+ (matrix) The matrix of the star involution on this space,
1986
+ which is induced by complex conjugation on modular symbols,
1987
+ with respect to the standard basis.
1988
+
1989
+ EXAMPLES::
1990
+
1991
+ sage: ModularSymbols(20,2).star_involution()
1992
+ Hecke module morphism Star involution on Modular Symbols space of dimension 7 for Gamma_0(20) of weight 2 with sign 0 over Rational Field defined by the matrix
1993
+ [1 0 0 0 0 0 0]
1994
+ [0 1 0 0 0 0 0]
1995
+ [0 0 0 0 1 0 0]
1996
+ [0 0 0 1 0 0 0]
1997
+ [0 0 1 0 0 0 0]
1998
+ [0 0 0 0 0 1 0]
1999
+ [0 0 0 0 0 0 1]
2000
+ Domain: Modular Symbols space of dimension 7 for Gamma_0(20) of weight ...
2001
+ Codomain: Modular Symbols space of dimension 7 for Gamma_0(20) of weight ...
2002
+ """
2003
+ try:
2004
+ return self.__star_involution
2005
+ except AttributeError:
2006
+ pass
2007
+ S = self.__heilbronn_operator(self, [[-1, 0, 0, 1]], 1)
2008
+ S.name("Star involution on %s" % self)
2009
+ self.__star_involution = S
2010
+ return self.__star_involution
2011
+
2012
+ def _compute_diamond_matrix(self, d):
2013
+ r"""
2014
+ Return the diamond bracket d operator on this modular symbols space.
2015
+
2016
+ INPUT:
2017
+
2018
+ - ``d`` -- integer
2019
+
2020
+ OUTPUT: the matrix of the diamond bracket operator on this space
2021
+
2022
+ EXAMPLES::
2023
+
2024
+ sage: e = kronecker_character(7)
2025
+ sage: M = ModularSymbols(e,2,sign=1)
2026
+ sage: D = M.diamond_bracket_operator(5); D
2027
+ Diamond bracket operator <5> on Modular Symbols space ...
2028
+ sage: D.matrix() # indirect doctest
2029
+ [-1 0 0 0]
2030
+ [ 0 -1 0 0]
2031
+ [ 0 0 -1 0]
2032
+ [ 0 0 0 -1]
2033
+ sage: [M.diamond_bracket_operator(d).matrix()[0,0] for d in [0..6]]
2034
+ [0, 1, 0, 1, 0, -1, 0]
2035
+ sage: [e(d) for d in [0..6]]
2036
+ [0, 1, 0, 1, 0, -1, 0]
2037
+
2038
+ We test that the sign issue at :issue:`8620` is fixed::
2039
+
2040
+ sage: M = Newforms(Gamma1(13),names = 'a')[0].modular_symbols(sign=0)
2041
+ sage: M.diamond_bracket_operator(4).matrix()
2042
+ [-1 1 1 -1]
2043
+ [-1 0 1 0]
2044
+ [ 0 0 0 -1]
2045
+ [ 0 0 1 -1]
2046
+
2047
+ We check that the result is correctly normalised for weight > 2::
2048
+
2049
+ sage: ModularSymbols(Gamma1(13), 5).diamond_bracket_operator(6).charpoly().factor()
2050
+ (x^2 + 1)^8 * (x^4 - x^2 + 1)^10
2051
+ """
2052
+ return self.__heilbronn_operator(self, [[d, 0, 0, d]], 1).matrix() * d**(2 - self.weight())
2053
+
2054
+ def submodule(self, M, dual_free_module=None, check=True):
2055
+ r"""
2056
+ Return the submodule with given generators or free module `M`.
2057
+
2058
+ INPUT:
2059
+
2060
+ - ``M`` -- either a submodule of this ambient free module, or
2061
+ generators for a submodule
2062
+
2063
+ - ``dual_free_module`` -- boolean (default: ``None``); this may be
2064
+ useful to speed up certain calculations; it is the corresponding
2065
+ submodule of the ambient dual module;
2066
+
2067
+ - ``check`` -- boolean (default: ``True``); if ``True``, check that `M`
2068
+ is a submodule, i.e. is invariant under all Hecke operators
2069
+
2070
+ OUTPUT: a subspace of this modular symbol space
2071
+
2072
+ EXAMPLES::
2073
+
2074
+ sage: M = ModularSymbols(11)
2075
+ sage: M.submodule([M.0])
2076
+ Traceback (most recent call last):
2077
+ ...
2078
+ ValueError: The submodule must be invariant under all Hecke operators.
2079
+ sage: M.eisenstein_submodule().basis()
2080
+ ((1,0) - 1/5*(1,9),)
2081
+ sage: M.basis()
2082
+ ((1,0), (1,8), (1,9))
2083
+ sage: M.submodule([M.0 - 1/5*M.2])
2084
+ Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
2085
+
2086
+ .. NOTE::
2087
+
2088
+ It would make more sense to only check that `M` is invariant
2089
+ under the Hecke operators with index coprime to the level.
2090
+ Unfortunately, I do not know a reasonable algorithm for
2091
+ determining whether a module is invariant under just the
2092
+ anemic Hecke algebra, since I do not know an analogue of
2093
+ the Sturm bound for the anemic Hecke algebra. - William
2094
+ Stein, 2007-07-27
2095
+ """
2096
+ if check:
2097
+ if not isinstance(M, FreeModule_generic):
2098
+ V = self.free_module()
2099
+ if not isinstance(M, (list, tuple)):
2100
+ M = M.gens()
2101
+ M = V.span([V(x.element()) for x in M])
2102
+ return subspace.ModularSymbolsSubspace(self, M, dual_free_module=dual_free_module, check=check)
2103
+
2104
+ def twisted_winding_element(self, i, eps):
2105
+ r"""
2106
+ Return the twisted winding element of given degree and character.
2107
+
2108
+ INPUT:
2109
+
2110
+ - ``i`` -- integer; `0\le i\le k-2` where `k` is the weight
2111
+
2112
+ - ``eps`` -- character; a Dirichlet character
2113
+
2114
+ OUTPUT:
2115
+
2116
+ (modular symbol) The so-called 'twisted winding element':
2117
+
2118
+ .. MATH::
2119
+
2120
+ \sum_{a \in (\ZZ/m\ZZ)^\times} \varepsilon(a) * [ i, 0, a/m ].
2121
+
2122
+ .. NOTE::
2123
+
2124
+ This will only work if the base ring of the modular symbol
2125
+ space contains the character values.
2126
+
2127
+ EXAMPLES::
2128
+
2129
+ sage: eps = DirichletGroup(5)[2]
2130
+ sage: K = eps.base_ring()
2131
+ sage: M = ModularSymbols(37,2,0,K)
2132
+ sage: M.twisted_winding_element(0,eps)
2133
+ 2*(1,23) - 2*(1,32) + 2*(1,34)
2134
+ """
2135
+ if not isinstance(eps, DirichletCharacter):
2136
+ raise TypeError("eps must be a Dirichlet character.")
2137
+ if (i < 0) or (i > self.weight() - 2):
2138
+ raise ValueError("i must be between 0 and k-2.")
2139
+
2140
+ m = eps.modulus()
2141
+ return self.sum(eps(a) * self.modular_symbol([i, Cusp(0), Cusp(a / m)])
2142
+ for a in m.coprime_integers(m))
2143
+
2144
+ ######################################################################
2145
+ # Z-module of integral modular symbols.
2146
+ #######################################################################
2147
+ def integral_structure(self, algorithm='default'):
2148
+ r"""
2149
+ Return the `\ZZ`-structure of this modular symbols
2150
+ space, generated by all integral modular symbols.
2151
+
2152
+ INPUT:
2153
+
2154
+ - ``algorithm`` -- string (default: ``'default'``, choose
2155
+ heuristically)
2156
+
2157
+ - ``'pari'`` -- use pari for the HNF computation
2158
+
2159
+ - ``'padic'`` -- use `p`-adic algorithm (only good for
2160
+ dense case)
2161
+
2162
+
2163
+ ALGORITHM: It suffices to consider lattice generated by the free
2164
+ generating symbols `X^iY^{k-2-i}.(u,v)` after quotienting
2165
+ out by the `S` (and `I`) relations, since the
2166
+ quotient by these relations is the same over any ring.
2167
+
2168
+ EXAMPLES: In weight 2 the rational basis is often integral.
2169
+
2170
+ ::
2171
+
2172
+ sage: M = ModularSymbols(11,2)
2173
+ sage: M.integral_structure()
2174
+ Free module of degree 3 and rank 3 over Integer Ring
2175
+ Echelon basis matrix:
2176
+ [1 0 0]
2177
+ [0 1 0]
2178
+ [0 0 1]
2179
+
2180
+ This is rarely the case in higher weight::
2181
+
2182
+ sage: M = ModularSymbols(6,4)
2183
+ sage: M.integral_structure()
2184
+ Free module of degree 6 and rank 6 over Integer Ring
2185
+ Echelon basis matrix:
2186
+ [ 1 0 0 0 0 0]
2187
+ [ 0 1 0 0 0 0]
2188
+ [ 0 0 1/2 1/2 1/2 1/2]
2189
+ [ 0 0 0 1 0 0]
2190
+ [ 0 0 0 0 1 0]
2191
+ [ 0 0 0 0 0 1]
2192
+
2193
+ Here is an example involving `\Gamma_1(N)`.
2194
+
2195
+ ::
2196
+
2197
+ sage: M = ModularSymbols(Gamma1(5),6)
2198
+ sage: M.integral_structure()
2199
+ Free module of degree 10 and rank 10 over Integer Ring
2200
+ Echelon basis matrix:
2201
+ [ 1 0 0 0 0 0 0 0 0 0]
2202
+ [ 0 1 0 0 0 0 0 0 0 0]
2203
+ [ 0 0 1/96 1/32 23/24 0 1/96 0 7/24 67/96]
2204
+ [ 0 0 0 1/24 23/24 0 0 1/24 1/4 17/24]
2205
+ [ 0 0 0 0 1 0 0 0 0 0]
2206
+ [ 0 0 0 0 0 1/6 0 1/48 23/48 1/3]
2207
+ [ 0 0 0 0 0 0 1/24 1/24 11/24 11/24]
2208
+ [ 0 0 0 0 0 0 0 1/16 7/16 1/2]
2209
+ [ 0 0 0 0 0 0 0 0 1/2 1/2]
2210
+ [ 0 0 0 0 0 0 0 0 0 1]
2211
+ """
2212
+ if not self.base_ring() == QQ:
2213
+ raise NotImplementedError
2214
+
2215
+ try:
2216
+ return self.__integral_structure
2217
+ except AttributeError:
2218
+ pass
2219
+
2220
+ # The attribute _mod2term is set by self.compute_presentation().
2221
+ # It is a list of pairs (n, c), such that the ith element of the list
2222
+ # is equivalent to c times the n-th basis Manin symbol.
2223
+ G = {i for i, _ in self._mod2term}
2224
+
2225
+ # Now G is a set of integer i such that these integers gives
2226
+ # indices of Manin symbols that together generate the integral
2227
+ # structure. We next obtain the corresponding list of elements
2228
+ # by passing to the quotient by the remaining relations
2229
+ # via the _manin_gens_to_basis attribute.
2230
+
2231
+ # Next we take each element of X, which gives a linear combination
2232
+ # of the basis of the underlying vector space of self, and compute
2233
+ # the Z-module they span.
2234
+
2235
+ G = sorted(G)
2236
+ B = self._manin_gens_to_basis.matrix_from_rows(list(G)).dense_matrix()
2237
+ B, d = B._clear_denom()
2238
+ if algorithm == 'default':
2239
+ # pari is much better in the weight 2 case when the input
2240
+ # matrix is extremely sparse; the p-adic algorithm is
2241
+ # terrible in the sparse case.
2242
+ if self.weight() == 2:
2243
+ algorithm = 'pari'
2244
+ else:
2245
+ algorithm = 'padic'
2246
+ if algorithm == 'pari':
2247
+ B = B.echelon_form(algorithm='pari', include_zero_rows=False)
2248
+ elif algorithm == 'padic':
2249
+ B = B.echelon_form(algorithm='padic', include_zero_rows=False)
2250
+ else:
2251
+ raise ValueError("unknown algorithm '%s'" % algorithm)
2252
+ W = B.row_module()
2253
+ if d != 1:
2254
+ W = W.scale(1/d)
2255
+ self.__integral_structure = W
2256
+ assert W.rank() == self.rank(), "there is a bug in computing integral structure on modular symbols"
2257
+ return self.__integral_structure
2258
+
2259
+ ######################################################################
2260
+ # Eigenvalues
2261
+ #######################################################################
2262
+ def compact_newform_eigenvalues(self, v, names='alpha'):
2263
+ r"""
2264
+ Return compact systems of eigenvalues for each Galois conjugacy
2265
+ class of cuspidal newforms in this ambient space.
2266
+
2267
+ INPUT:
2268
+
2269
+ - ``v`` -- list of positive integers
2270
+
2271
+ OUTPUT:
2272
+
2273
+ List of pairs (E, x), where ``E*x`` is a vector with entries the
2274
+ eigenvalues `a_n` for `n \in v`.
2275
+
2276
+ EXAMPLES::
2277
+
2278
+ sage: M = ModularSymbols(43,2,1)
2279
+ sage: X = M.compact_newform_eigenvalues(prime_range(10))
2280
+ sage: X[0][0] * X[0][1]
2281
+ (-2, -2, -4, 0)
2282
+ sage: X[1][0] * X[1][1]
2283
+ (alpha1, -alpha1, -alpha1 + 2, alpha1 - 2)
2284
+
2285
+ ::
2286
+
2287
+ sage: M = ModularSymbols(DirichletGroup(24,QQ).1,2,sign=1)
2288
+ sage: M.compact_newform_eigenvalues(prime_range(10),'a')
2289
+ [(
2290
+ [-1/2 -1/2]
2291
+ [ 1/2 -1/2]
2292
+ [ -1 1]
2293
+ [ -2 0], (1, -2*a0 - 1)
2294
+ )]
2295
+ sage: a = M.compact_newform_eigenvalues([1..10],'a')[0]
2296
+ sage: a[0]*a[1]
2297
+ (1, a0, a0 + 1, -2*a0 - 2, -2*a0 - 2, -a0 - 2, -2, 2*a0 + 4, -1, 2*a0 + 4)
2298
+ sage: M = ModularSymbols(DirichletGroup(13).0^2,2,sign=1)
2299
+ sage: M.compact_newform_eigenvalues(prime_range(10),'a')
2300
+ [(
2301
+ [ -zeta6 - 1]
2302
+ [ 2*zeta6 - 2]
2303
+ [-2*zeta6 + 1]
2304
+ [ 0], (1)
2305
+ )]
2306
+ sage: a = M.compact_newform_eigenvalues([1..10],'a')[0]
2307
+ sage: a[0]*a[1]
2308
+ (1, -zeta6 - 1, 2*zeta6 - 2, zeta6, -2*zeta6 + 1, -2*zeta6 + 4, 0, 2*zeta6 - 1, -zeta6, 3*zeta6 - 3)
2309
+ """
2310
+ if self.sign() == 0:
2311
+ raise ValueError("sign must be nonzero")
2312
+ v = list(v)
2313
+
2314
+ # Get decomposition of this space
2315
+ D = self.cuspidal_submodule().new_subspace().decomposition()
2316
+ for A in D:
2317
+ # since sign is zero and we're on the new cuspidal subspace
2318
+ # each factor is definitely simple.
2319
+ A._is_simple = True
2320
+ B = [A.dual_free_module().basis_matrix().transpose() for A in D]
2321
+
2322
+ # Normalize the names strings.
2323
+ names = ['%s%s' % (names, i) for i in range(len(B))]
2324
+
2325
+ # Find an integer i such that the i-th columns of the basis for the
2326
+ # dual modules corresponding to the factors in D are all nonzero.
2327
+ nz = None
2328
+ for i in range(self.dimension()):
2329
+ # Decide if this i works, i.e., ith row of every element of B is nonzero.
2330
+ bad = False
2331
+ for C in B:
2332
+ if C.row(i) == 0:
2333
+ # i is bad.
2334
+ bad = True
2335
+ continue
2336
+ if bad:
2337
+ continue
2338
+ # It turns out that i is not bad.
2339
+ nz = i
2340
+ break
2341
+
2342
+ if nz is not None:
2343
+ R = self.hecke_images(nz, v)
2344
+ return [(R * m, D[i].dual_eigenvector(names=names[i],
2345
+ lift=False, nz=nz))
2346
+ for i, m in enumerate(B)]
2347
+
2348
+ # No single i works, so we do something less uniform.
2349
+ ans = []
2350
+ cache = {}
2351
+ for i in range(len(D)):
2352
+ nz = D[i]._eigen_nonzero()
2353
+ if nz in cache:
2354
+ R = cache[nz]
2355
+ else:
2356
+ R = self.hecke_images(nz, v)
2357
+ cache[nz] = R
2358
+ ans.append((R * B[i], D[i].dual_eigenvector(names=names[i],
2359
+ lift=False, nz=nz)))
2360
+ return ans
2361
+
2362
+ def __pari__(self):
2363
+ """
2364
+ Return a PARI object corresponding to ``self``.
2365
+
2366
+ TESTS::
2367
+
2368
+ sage: ModularSymbols(Gamma1(5), 2).__pari__()
2369
+ Traceback (most recent call last):
2370
+ ...
2371
+ NotImplementedError: PARI modular symbols are only implemented for Gamma0(n)
2372
+ """
2373
+ raise NotImplementedError('PARI modular symbols are only implemented for Gamma0(n)')
2374
+
2375
+ def _pari_pairing(self):
2376
+ r"""
2377
+ Return the matrix of the canonical pairing between this space and
2378
+ the corresponding space of modular symbols in PARI.
2379
+
2380
+ Let `M` be an ambient space of modular symbols over a field `K`
2381
+ of characteristic 0. The corresponding space `P` in PARI is
2382
+ canonically dual to `M`, giving rise to a `K`-bilinear map
2383
+
2384
+ .. MATH::
2385
+
2386
+ E\colon M \times P \to K.
2387
+
2388
+ OUTPUT: the matrix of the bilinear map `E`
2389
+
2390
+ This is currently only implemented for spaces of modular
2391
+ symbols of trivial character.
2392
+
2393
+ EXAMPLES::
2394
+
2395
+ sage: M = ModularSymbols(Gamma0(5), 6)
2396
+ sage: P = M.__pari__()
2397
+ sage: E = M._pari_pairing(); E
2398
+ [ 0 -1 0 0]
2399
+ [ 0 0 8 -27]
2400
+ [ 8 0 0 13]
2401
+ [ 24 0 8 37]
2402
+
2403
+ The duality is compatible with (for example) Hecke operators
2404
+ and the star involution::
2405
+
2406
+ sage: M.hecke_matrix(5) * E == E * P.mshecke(5)
2407
+ True
2408
+ sage: M.star_involution().matrix() * E == E * P.msstar()
2409
+ True
2410
+ """
2411
+ if self.weight() == 2:
2412
+ return self._pari_tensor().inverse()
2413
+ from sage.matrix.constructor import matrix
2414
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
2415
+ P = self.__pari__()
2416
+ I = matrix.identity(self.rank()).__pari__()
2417
+ m = Integer(self.weight() - 2)
2418
+ R = PolynomialRing(QQ, 'x')
2419
+ x = R.gen()
2420
+
2421
+ def ev(s):
2422
+ # The Manin symbol s = X^i (c, d) corresponds to the
2423
+ # modular symbol (dX - bY)^i (-cX + aY)^(m - i) {b/d, a/c}.
2424
+ # The code below computes the canonical pairing of this
2425
+ # modular symbol with the distinguished basis of P.
2426
+ i = s.i
2427
+ a, b, c, d = s.lift_to_sl2z()
2428
+ e = [R(p) for p in P.mseval(I, matrix(2, 2, [b, a, d, c]))]
2429
+ g = (d * x - b)**i * (-c * x + a)**(m - i)
2430
+ return [sum(f[j] * g[m - j] / m.binomial(j) for j in range(m + 1))
2431
+ for f in e]
2432
+ return matrix([ev(s) for s in self.manin_symbols_basis()])
2433
+
2434
+ def _pari_tensor(self):
2435
+ r"""
2436
+ Return a matrix expressing the duality between this space and the
2437
+ corresponding space of modular symbols in PARI.
2438
+
2439
+ Let `M` be an ambient space of modular symbols over a field `K`
2440
+ of characteristic 0. The corresponding space `P` in PARI is
2441
+ canonically dual to `M`, giving rise to an element
2442
+
2443
+ .. MATH::
2444
+
2445
+ T \in P \otimes_K M.
2446
+
2447
+ OUTPUT: the matrix of the element `T \in P \otimes_K M`.
2448
+ This is the inverse of the matrix returned by
2449
+ :meth:`_pari_pairing`.
2450
+
2451
+ This is currently only implemented for spaces of modular
2452
+ symbols of trivial character.
2453
+
2454
+ EXAMPLES::
2455
+
2456
+ sage: M = ModularSymbols(Gamma0(37), 2)
2457
+ sage: P = M.__pari__()
2458
+ sage: T = M._pari_tensor(); T
2459
+ [ 1 0 0 0 0]
2460
+ [ 0 0 -1 0 0]
2461
+ [ 0 0 1 -1 0]
2462
+ [ 0 -1 0 -1 1]
2463
+ [ 0 0 0 1 -1]
2464
+
2465
+ The duality is compatible with (for example) Hecke operators
2466
+ and the star involution::
2467
+
2468
+ sage: T * M.hecke_matrix(3) == P.mshecke(3) * T
2469
+ True
2470
+ sage: T * M.star_involution().matrix() == P.msstar() * T
2471
+ True
2472
+ """
2473
+ if self.weight() != 2:
2474
+ return self._pari_pairing().inverse()
2475
+ from sage.matrix.constructor import matrix
2476
+ gens = self.__pari__().mspathgens()[0][:self.rank()].sage()
2477
+ # gens is a basis for the space of modular symbols of weight 2
2478
+ # (in the sense of Sage), and the distinguished basis of the
2479
+ # corresponding PARI space of modular symbols is dual to this.
2480
+ return matrix([self.modular_symbol(g).element() for g in gens])
2481
+
2482
+
2483
+ class ModularSymbolsAmbient_wtk_g0(ModularSymbolsAmbient):
2484
+ r"""
2485
+ Modular symbols for `\Gamma_0(N)` of integer weight
2486
+ `k > 2` over the field `F`.
2487
+
2488
+ For weight `2`, it is faster to use ``ModularSymbols_wt2_g0``.
2489
+
2490
+ INPUT:
2491
+
2492
+ - ``N`` -- integer; the level
2493
+
2494
+ - ``k`` -- integer; weight = 2
2495
+
2496
+ - ``sign`` -- integer; either -1, 0, or 1
2497
+
2498
+ - ``F`` -- field
2499
+
2500
+ EXAMPLES::
2501
+
2502
+ sage: ModularSymbols(1,12)
2503
+ Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field
2504
+ sage: ModularSymbols(1,12, sign=1).dimension()
2505
+ 2
2506
+ sage: ModularSymbols(15,4, sign=-1).dimension()
2507
+ 4
2508
+ sage: ModularSymbols(6,6).dimension()
2509
+ 10
2510
+ sage: ModularSymbols(36,4).dimension()
2511
+ 36
2512
+ """
2513
+ def __init__(self, N, k, sign, F, custom_init=None, category=None):
2514
+ r"""
2515
+ Initialize a space of modular symbols of weight `k` for
2516
+ `\Gamma_0(N)`, over `\QQ`.
2517
+
2518
+ For weight `2`, it is faster to use
2519
+ ``ModularSymbols_wt2_g0``.
2520
+
2521
+ INPUT:
2522
+
2523
+ - ``N`` -- integer; the level
2524
+
2525
+ - ``k`` -- integer; weight = 2
2526
+
2527
+ - ``sign`` -- integer; either -1, 0, or 1
2528
+
2529
+ - ``F`` -- field
2530
+
2531
+ EXAMPLES::
2532
+
2533
+ sage: ModularSymbols(1,12)
2534
+ Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field
2535
+ sage: ModularSymbols(1,12, sign=1).dimension()
2536
+ 2
2537
+ sage: ModularSymbols(15,4, sign=-1).dimension()
2538
+ 4
2539
+ sage: ModularSymbols(6,6).dimension()
2540
+ 10
2541
+ sage: ModularSymbols(36,4).dimension()
2542
+ 36
2543
+ """
2544
+ N = int(N)
2545
+ k = int(k)
2546
+ sign = int(sign)
2547
+ if sign not in [-1, 0, 1]:
2548
+ raise TypeError("sign must be an int in [-1,0,1]")
2549
+
2550
+ ModularSymbolsAmbient.__init__(self, weight=k, group=arithgroup.Gamma0(N),
2551
+ sign=sign, base_ring=F,
2552
+ custom_init=custom_init, category=category)
2553
+
2554
+ def _dimension_formula(self):
2555
+ r"""
2556
+ Return the dimension of this space using the formula.
2557
+
2558
+ EXAMPLES::
2559
+
2560
+ sage: M = ModularSymbols(37,6)
2561
+ sage: M.dimension()
2562
+ 32
2563
+ sage: M._dimension_formula()
2564
+ 32
2565
+ """
2566
+ if self.base_ring().characteristic() == 0:
2567
+ k, sign = self.weight(), self.sign()
2568
+ if sign != 0:
2569
+ return None
2570
+ if k % 2:
2571
+ return 0
2572
+ elif k > 2:
2573
+ return 2 * self.group().dimension_cusp_forms(k) + self.group().ncusps()
2574
+ else:
2575
+ return 2*self.group().dimension_cusp_forms(k) + self.group().ncusps() - 1
2576
+ else:
2577
+ raise NotImplementedError
2578
+
2579
+ def _repr_(self):
2580
+ r"""
2581
+ Return the string representation of this Modular Symbols space.
2582
+
2583
+ EXAMPLES::
2584
+
2585
+ sage: M = ModularSymbols(37,6)
2586
+ sage: M # indirect doctest
2587
+ Modular Symbols space of dimension 32 for Gamma_0(37) of weight 6 with sign 0 over Rational Field
2588
+ """
2589
+ return ("Modular Symbols space of dimension %s for Gamma_0(%s) of weight %s with sign %s " +
2590
+ "over %s") % (self.dimension(), self.level(), self.weight(), self.sign(),
2591
+ self.base_ring())
2592
+
2593
+ def _cuspidal_submodule_dimension_formula(self):
2594
+ r"""
2595
+ Return the dimension of the cuspidal subspace, using the formula.
2596
+
2597
+ EXAMPLES::
2598
+
2599
+ sage: M = ModularSymbols(37,4)
2600
+ sage: M.cuspidal_subspace().dimension()
2601
+ 18
2602
+ sage: M._cuspidal_submodule_dimension_formula()
2603
+ 18
2604
+ """
2605
+ if self.base_ring().characteristic() == 0:
2606
+ k, sign = self.weight(), self.sign()
2607
+ if sign == 0:
2608
+ m = 2
2609
+ else:
2610
+ m = 1
2611
+ return m * self.group().dimension_cusp_forms(k)
2612
+ else:
2613
+ raise NotImplementedError
2614
+
2615
+ def _degeneracy_raising_matrix_1(self, M):
2616
+ r"""
2617
+ Return the matrix of the degeneracy map (with t = 1) to level
2618
+ `N`, where `N` is a multiple of the level.
2619
+
2620
+ INPUT:
2621
+
2622
+ - ``M`` -- a space of Gamma0 modular symbols of the same weight as
2623
+ ``self``, with level an integer multiple of the level of ``self``
2624
+
2625
+ OUTPUT: the matrix of the degeneracy raising map to `M`
2626
+
2627
+ EXAMPLES::
2628
+
2629
+ sage: M = ModularSymbols(37,4)
2630
+ sage: M._degeneracy_raising_matrix_1(ModularSymbols(74, 4))
2631
+ 20 x 58 dense matrix over Rational Field (use the '.str()' method to see the entries)
2632
+ sage: M.dimension()
2633
+ 20
2634
+ sage: ModularSymbols(74,4).dimension()
2635
+ 58
2636
+ """
2637
+ level = int(M.level())
2638
+ N = self.level()
2639
+
2640
+ # 1. Find coset representatives H for Gamma_0(M.level()) \ Gamma_0(self.level())
2641
+ # (need to be careful in some small levels, cf. #13198)
2642
+
2643
+ if isinstance(M.group(), arithgroup.Gamma0_class):
2644
+ H = arithgroup.degeneracy_coset_representatives_gamma0(level, N, 1)
2645
+ elif isinstance(M.group(), arithgroup.Gamma1_class):
2646
+ H = arithgroup.degeneracy_coset_representatives_gamma1(level, N, 1)
2647
+ else:
2648
+ raise NotImplementedError("Degeneracy raising maps not implemented for GammaH levels")
2649
+
2650
+ # 2. The map is
2651
+ # [P,pi(g)] |--> sum_{h in H} [P, pi(h*g)]
2652
+ #
2653
+ MS = MatrixSpace(self.base_ring(), self.dimension(), M.dimension())
2654
+ if self.dimension() == 0 or M.dimension() == 0:
2655
+ return MS(0)
2656
+ rows = []
2657
+ B = self.manin_basis()
2658
+ syms = self.manin_symbols()
2659
+ H = [M2Z(h) for h in H]
2660
+ for n in B:
2661
+ z = M(0)
2662
+ s = syms.manin_symbol(n)
2663
+ g = M2Z(list(s.lift_to_sl2z(N)))
2664
+ i = s.i
2665
+ # We apply each matrix in H according to the above formula
2666
+ for h in H:
2667
+ hg = h*g
2668
+ z += M((i, hg[1, 0], hg[1, 1]))
2669
+ rows.append(z.element())
2670
+
2671
+ return MS(rows)
2672
+
2673
+ def _cuspidal_new_submodule_dimension_formula(self):
2674
+ r"""
2675
+ Return the dimension of the new cuspidal subspace, via the formula.
2676
+
2677
+ EXAMPLES::
2678
+
2679
+ sage: M = ModularSymbols(100,2)
2680
+ sage: M._cuspidal_new_submodule_dimension_formula()
2681
+ 2
2682
+ sage: M.cuspidal_subspace().new_subspace().dimension()
2683
+ 2
2684
+ """
2685
+ if self.base_ring().characteristic() == 0:
2686
+ k, sign = self.weight(), self.sign()
2687
+ if sign == 0:
2688
+ m = 2
2689
+ else:
2690
+ m = 1
2691
+ return m * self.group().dimension_new_cusp_forms(k)
2692
+ else:
2693
+ raise NotImplementedError
2694
+
2695
+ def boundary_space(self):
2696
+ r"""
2697
+ Return the space of boundary modular symbols for this space.
2698
+
2699
+ EXAMPLES::
2700
+
2701
+ sage: M = ModularSymbols(100,2)
2702
+ sage: M.boundary_space()
2703
+ Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(100) of weight 2 over Rational Field
2704
+ """
2705
+ try:
2706
+ return self.__boundary_space
2707
+ except AttributeError:
2708
+ pass
2709
+ self.__boundary_space = boundary.BoundarySpace_wtk_g0(
2710
+ self.level(), self.weight(), self.sign(), self.base_ring())
2711
+ return self.__boundary_space
2712
+
2713
+ def manin_symbols(self):
2714
+ r"""
2715
+ Return the Manin symbol list of this modular symbol space.
2716
+
2717
+ EXAMPLES::
2718
+
2719
+ sage: M = ModularSymbols(100,4)
2720
+ sage: M.manin_symbols()
2721
+ Manin Symbol List of weight 4 for Gamma0(100)
2722
+ sage: len(M.manin_symbols())
2723
+ 540
2724
+ """
2725
+ try:
2726
+ return self.__manin_symbols
2727
+ except AttributeError:
2728
+ self.__manin_symbols = ManinSymbolList_gamma0(
2729
+ level=self.level(), weight=self.weight())
2730
+ return self.__manin_symbols
2731
+
2732
+ def _hecke_images(self, i, v):
2733
+ """
2734
+ Return matrix whose rows are the images of the `i`-th
2735
+ standard basis vector under the Hecke operators `T_p` for
2736
+ all integers in `v`.
2737
+
2738
+ INPUT:
2739
+
2740
+ - ``i`` -- nonnegative integer
2741
+
2742
+ - ``v`` -- list of positive integer
2743
+
2744
+ OUTPUT: ``matrix`` -- whose rows are the Hecke images
2745
+
2746
+ EXAMPLES::
2747
+
2748
+ sage: M = ModularSymbols(11,4,1)
2749
+ sage: mat = M._hecke_images(0,[1,2,3,4])
2750
+ sage: M.T(1)(M.0).element() == mat[0]
2751
+ True
2752
+ sage: M.T(2)(M.0).element() == mat[1]
2753
+ True
2754
+ sage: M.T(3)(M.0).element() == mat[2]
2755
+ True
2756
+ sage: M.T(4)(M.0).element() == mat[3]
2757
+ True
2758
+
2759
+ sage: M = ModularSymbols(12,4)
2760
+ sage: mat = M._hecke_images(0,[1,2,3,4])
2761
+ sage: M.T(1)(M.0).element() == mat[0]
2762
+ True
2763
+ sage: M.T(2)(M.0).element() == mat[1]
2764
+ True
2765
+ sage: M.T(3)(M.0).element() == mat[2]
2766
+ True
2767
+ sage: M.T(4)(M.0).element() == mat[3]
2768
+ True
2769
+ """
2770
+ # Find basis vector for ambient space such that it is not in
2771
+ # the kernel of the dual space corresponding to self.
2772
+ c = self.manin_generators()[self.manin_basis()[i]]
2773
+ N = self.level()
2774
+ return heilbronn.hecke_images_gamma0_weight_k(c.u, c.v, c.i, N, self.weight(),
2775
+ v, self.manin_gens_to_basis())
2776
+
2777
+ @cached_method
2778
+ def __pari__(self):
2779
+ """
2780
+ Return a PARI object corresponding to ``self``.
2781
+
2782
+ EXAMPLES::
2783
+
2784
+ sage: ModularSymbols(Gamma0(1), 2).__pari__()
2785
+ [[[[Vecsmall([0, 1])], [0], 1, [Vecsmall([]), Vecsmall([])],
2786
+ Vecsmall([1]), Vecsmall([]), Vecsmall([])],
2787
+ 0, 0, 0, Vecsmall([1]), 0, 0, [[1, 1; [0, 1; -1, 0], 1]],
2788
+ [[1, 1; [0, -1; 1, -1], 1; [-1, 1; -1, 0], 1]], 0,
2789
+ Vecsmall([0, 0, 1, 1, 2]), [[Vecsmall([1, 0]), Vecsmall([0, 1])]],
2790
+ 0, 0, 0, [Vecsmall([1, 1]), [Vecsmall([0, 1]), 0], [Vecsmall([1, 0])]]],
2791
+ [0, [;], [[;], [;], 1, Vecsmall([])]],
2792
+ [[], Vecsmall([2, 0]), Vecsmall([0, 0]), 0, [[;], [;], 1, Vecsmall([])]]]
2793
+
2794
+ .. NOTE::
2795
+
2796
+ Spaces of modular symbols as implemented in PARI are
2797
+ canonically dual to those implemented in Sage. See
2798
+ :meth:`ModularSymbolsAmbient._pari_pairing` and
2799
+ :meth:`ModularSymbolsAmbient._pari_tensor` for how to use
2800
+ this duality.
2801
+ """
2802
+ return self.level().__pari__().msinit(self.weight(), self.sign())
2803
+
2804
+
2805
+ class ModularSymbolsAmbient_wt2_g0(ModularSymbolsAmbient_wtk_g0):
2806
+ r"""
2807
+ Modular symbols for `\Gamma_0(N)` of integer weight `2` over the field
2808
+ `F`.
2809
+
2810
+ INPUT:
2811
+
2812
+ - ``N`` -- integer; the level
2813
+
2814
+ - ``sign`` -- integer; either -1, 0, or 1
2815
+
2816
+ OUTPUT:
2817
+
2818
+ The space of modular symbols of weight `2`, trivial character, level
2819
+ `N` and given sign.
2820
+
2821
+ EXAMPLES::
2822
+
2823
+ sage: ModularSymbols(Gamma0(12),2)
2824
+ Modular Symbols space of dimension 5 for Gamma_0(12) of weight 2 with sign 0 over Rational Field
2825
+ """
2826
+ def __init__(self, N, sign, F, custom_init=None, category=None):
2827
+ """
2828
+ Initialize a space of modular symbols.
2829
+
2830
+ INPUT:
2831
+
2832
+ - ``N`` -- integer; the level
2833
+
2834
+ - ``sign`` -- integer; either -1, 0, or 1
2835
+
2836
+ OUTPUT:
2837
+
2838
+ The space of modular symbols of weight 2, trivial character,
2839
+ level N and given sign.
2840
+
2841
+ EXAMPLES::
2842
+
2843
+ sage: M = ModularSymbols(Gamma0(12),2)
2844
+ """
2845
+ ModularSymbolsAmbient_wtk_g0.__init__(self, N=N, k=2, sign=sign, F=F,
2846
+ custom_init=custom_init, category=category)
2847
+
2848
+ def _dimension_formula(self):
2849
+ r"""
2850
+ Return the dimension of this space using the formula.
2851
+
2852
+ EXAMPLES::
2853
+
2854
+ sage: M = ModularSymbols(37,6)
2855
+ sage: M.dimension()
2856
+ 32
2857
+ sage: M._dimension_formula()
2858
+ 32
2859
+ """
2860
+ if self.base_ring().characteristic() == 0:
2861
+ if self.sign() != 0:
2862
+ return None
2863
+ return 2*self.group().dimension_cusp_forms(2) + self.group().ncusps() - 1
2864
+ else:
2865
+ raise NotImplementedError
2866
+
2867
+ def _cuspidal_submodule_dimension_formula(self):
2868
+ r"""
2869
+ Return the dimension of the cuspidal subspace, using the formula.
2870
+
2871
+ EXAMPLES::
2872
+
2873
+ sage: M = ModularSymbols(37,4)
2874
+ sage: M.cuspidal_subspace().dimension()
2875
+ 18
2876
+ sage: M._cuspidal_submodule_dimension_formula()
2877
+ 18
2878
+ """
2879
+ if self.base_ring().characteristic() == 0:
2880
+ if self.sign() == 0:
2881
+ m = 2
2882
+ else:
2883
+ m = 1
2884
+ return m * self.group().dimension_cusp_forms(2)
2885
+ else:
2886
+ raise NotImplementedError
2887
+
2888
+ def _cuspidal_new_submodule_dimension_formula(self):
2889
+ r"""
2890
+ Return the dimension of the new cuspidal subspace, via the formula.
2891
+
2892
+ EXAMPLES::
2893
+
2894
+ sage: M = ModularSymbols(100,2)
2895
+ sage: M._cuspidal_new_submodule_dimension_formula()
2896
+ 2
2897
+ sage: M.cuspidal_subspace().new_subspace().dimension()
2898
+ 2
2899
+ """
2900
+ if self.base_ring().characteristic() == 0:
2901
+ if self.sign() == 0:
2902
+ m = 2
2903
+ else:
2904
+ m = 1
2905
+ return m * self.group().dimension_new_cusp_forms(2)
2906
+ else:
2907
+ raise NotImplementedError
2908
+
2909
+ def _compute_hecke_matrix_prime(self, p, rows=None):
2910
+ r"""
2911
+ Compute and return the matrix of the `p`-th Hecke operator.
2912
+
2913
+ EXAMPLES::
2914
+
2915
+ sage: m = ModularSymbols(37,2)
2916
+ sage: m._compute_hecke_matrix_prime(2).charpoly('x')
2917
+ x^5 + x^4 - 8*x^3 - 12*x^2
2918
+ """
2919
+ # note -- p doesn't have to be prime.
2920
+ if isinstance(rows, list):
2921
+ rows = tuple(rows)
2922
+ try:
2923
+ return self._hecke_matrices[(p, rows)]
2924
+ except AttributeError:
2925
+ self._hecke_matrices = {}
2926
+ except KeyError:
2927
+ pass
2928
+ tm = verbose(f"Computing Hecke operator T_{p}")
2929
+
2930
+ H = heilbronn.HeilbronnCremona(p)
2931
+ # H = heilbronn.HeilbronnMerel(p)
2932
+ B = self.manin_basis()
2933
+ if rows is not None:
2934
+ B = [B[i] for i in rows]
2935
+
2936
+ N = self.level()
2937
+ P1 = self.p1list()
2938
+ mod2term = self._mod2term
2939
+ R = self.manin_gens_to_basis()
2940
+ W = R.new_matrix(nrows=len(B), ncols=R.nrows()) # the 0 with given number of rows and cols.
2941
+ j = 0
2942
+ tm = verbose("Matrix non-reduced", tm)
2943
+ for i in B:
2944
+ # The following step is where most of the time is spent.
2945
+ c, d = P1[i]
2946
+ v = H.apply(c, d, N)
2947
+
2948
+ # v is now a list of pairs ((c,d),m), where m is the
2949
+ # number of times that (c,d) appears in the image of x
2950
+ # under the matrices in H. Also, the pairs (c,d) are
2951
+ # normalized.
2952
+ # Let ind(c,d) denote the index of the normalized pair
2953
+ # (c,d) in the fixed ordered list of elements of
2954
+ # P1(Z/NZ). Then the list of pairs (ind(c,d), m)
2955
+ # obtained from the above list defines a sparse vector
2956
+ # s, and the image of x under T_p is the product
2957
+ # of s with the matrix R defined above.
2958
+ for z, m in v:
2959
+ k = P1.index_of_normalized_pair(z[0], z[1])
2960
+ if k != -1:
2961
+ f, s = mod2term[k]
2962
+ if s != 0:
2963
+ W[j, f] = W[j, f] + s*m
2964
+ j += 1
2965
+ tm = verbose("done making non-reduced matrix", tm)
2966
+ verbose("start matrix-matrix (%s x %s) times (%s x %s) multiply to get Tp" % (W.nrows(), W.ncols(),
2967
+ R.nrows(), R.ncols()))
2968
+ if hasattr(W, '_matrix_times_matrix_dense'):
2969
+ Tp = W._matrix_times_matrix_dense(R)
2970
+ verbose("done matrix multiply and computing Hecke operator", tm)
2971
+ else:
2972
+ Tp = W * R
2973
+ tm = verbose("done multiplying", tm)
2974
+ Tp = Tp.dense_matrix()
2975
+ verbose("done making Hecke operator dense", tm)
2976
+ if rows is None:
2977
+ self._hecke_matrices[(p, rows)] = Tp
2978
+ return Tp
2979
+
2980
+ def boundary_space(self):
2981
+ r"""
2982
+ Return the space of boundary modular symbols for this space.
2983
+
2984
+ EXAMPLES::
2985
+
2986
+ sage: M = ModularSymbols(100,2)
2987
+ sage: M.boundary_space()
2988
+ Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(100) of weight 2 over Rational Field
2989
+ """
2990
+ try:
2991
+ return self.__boundary_space
2992
+ except AttributeError:
2993
+ pass
2994
+ self.__boundary_space = boundary.BoundarySpace_wtk_g0(
2995
+ self.level(), self.weight(), self.sign(), self.base_ring())
2996
+ return self.__boundary_space
2997
+
2998
+ def _hecke_image_of_ith_basis_vector(self, n, i):
2999
+ """
3000
+ Return `T_n(e_i)`, where `e_i` is the
3001
+ `i` th basis vector of this ambient space.
3002
+
3003
+ INPUT:
3004
+
3005
+ - ``n`` -- integer which should be prime
3006
+
3007
+ OUTPUT: ``modular symbol`` -- element of this ambient space
3008
+
3009
+ EXAMPLES::
3010
+
3011
+ sage: M = ModularSymbols(43,2,1)
3012
+ sage: M._hecke_image_of_ith_basis_vector(2, 0)
3013
+ 3*(1,0) - 2*(1,33)
3014
+ sage: M.hecke_operator(2)(M.0)
3015
+ 3*(1,0) - 2*(1,33)
3016
+ sage: M._hecke_image_of_ith_basis_vector(6, 1)
3017
+ 4*(1,31) - 3*(1,33) + 3*(1,39)
3018
+ sage: M.hecke_operator(6)(M.1)
3019
+ 4*(1,31) - 3*(1,33) + 3*(1,39)
3020
+ """
3021
+ c = self.manin_generators()[self.manin_basis()[i]]
3022
+ N = self.level()
3023
+ I = heilbronn.hecke_images_gamma0_weight2(c.u, c.v, N, [n],
3024
+ self.manin_gens_to_basis())
3025
+ return self(I[0])
3026
+
3027
+ def _hecke_images(self, i, v):
3028
+ """
3029
+ Return images of the `i`-th standard basis vector under the
3030
+ Hecke operators `T_p` for all integers in `v`.
3031
+
3032
+ INPUT:
3033
+
3034
+ - ``i`` -- nonnegative integer
3035
+
3036
+ - ``v`` -- list of positive integer
3037
+
3038
+ OUTPUT: matrix whose rows are the Hecke images
3039
+
3040
+ EXAMPLES::
3041
+
3042
+ sage: M = ModularSymbols(46,2,-1)
3043
+ sage: mat = M._hecke_images(1,[3,4,5,6])
3044
+ sage: v = M.basis()[1]
3045
+ sage: M.T(3)(v).element() == mat[0]
3046
+ True
3047
+ sage: M.T(4)(v).element() == mat[1]
3048
+ True
3049
+ sage: M.T(5)(v).element() == mat[2]
3050
+ True
3051
+ sage: M.T(6)(v).element() == mat[3]
3052
+ True
3053
+ """
3054
+ # Find basis vector for ambient space such that it is not in
3055
+ # the kernel of the dual space corresponding to self.
3056
+ c = self.manin_generators()[self.manin_basis()[i]]
3057
+ N = self.level()
3058
+ return heilbronn.hecke_images_gamma0_weight2(c.u, c.v, N, v,
3059
+ self.manin_gens_to_basis())
3060
+
3061
+
3062
+ class ModularSymbolsAmbient_wtk_g1(ModularSymbolsAmbient):
3063
+ r"""
3064
+ INPUT:
3065
+
3066
+ - ``level`` -- integer; the level
3067
+
3068
+ - ``weight`` -- integer; the weight = 2
3069
+
3070
+ - ``sign`` -- integer; either -1, 0, or 1
3071
+
3072
+ - ``F`` -- field
3073
+
3074
+ EXAMPLES::
3075
+
3076
+ sage: ModularSymbols(Gamma1(17),2)
3077
+ Modular Symbols space of dimension 25 for Gamma_1(17) of weight 2 with sign 0 over Rational Field
3078
+ sage: [ModularSymbols(Gamma1(7),k).dimension() for k in [2,3,4,5]]
3079
+ [5, 8, 12, 16]
3080
+
3081
+ ::
3082
+
3083
+ sage: ModularSymbols(Gamma1(7),3)
3084
+ Modular Symbols space of dimension 8 for Gamma_1(7) of weight 3 with sign 0 over Rational Field
3085
+ """
3086
+
3087
+ def __init__(self, level, weight, sign, F, custom_init=None, category=None):
3088
+ r"""
3089
+ Initialize a space of modular symbols for Gamma1(N).
3090
+
3091
+ INPUT:
3092
+
3093
+ - ``level`` -- integer; the level
3094
+
3095
+ - ``weight`` -- integer; the weight = 2
3096
+
3097
+ - ``sign`` -- integer; either -1, 0, or 1
3098
+
3099
+ - ``F`` -- field
3100
+
3101
+ EXAMPLES::
3102
+
3103
+ sage: ModularSymbols(Gamma1(17),2)
3104
+ Modular Symbols space of dimension 25 for Gamma_1(17) of weight 2 with sign 0 over Rational Field
3105
+ sage: [ModularSymbols(Gamma1(7),k).dimension() for k in [2,3,4,5]]
3106
+ [5, 8, 12, 16]
3107
+
3108
+ ::
3109
+
3110
+ sage: M = ModularSymbols(Gamma1(7),3)
3111
+ """
3112
+ ModularSymbolsAmbient.__init__(self,
3113
+ weight=weight,
3114
+ group=arithgroup.Gamma1(level),
3115
+ sign=sign,
3116
+ base_ring=F,
3117
+ custom_init=custom_init,
3118
+ category=category)
3119
+
3120
+ def _dimension_formula(self):
3121
+ r"""
3122
+ Return the dimension of this space using the formula.
3123
+
3124
+ EXAMPLES::
3125
+
3126
+ sage: M = ModularSymbols(Gamma1(7),6)
3127
+ sage: M.dimension()
3128
+ 20
3129
+ sage: M._dimension_formula()
3130
+ 20
3131
+ """
3132
+ if self.base_ring().characteristic() != 0:
3133
+ raise NotImplementedError
3134
+ level, weight, sign = self.level(), self.weight(), self.sign()
3135
+ if sign != 0:
3136
+ return None
3137
+ d = 2*self.group().dimension_cusp_forms(weight) + self.group().ncusps()
3138
+ if level == 1 and weight % 2:
3139
+ return 0
3140
+ if weight == 2:
3141
+ return d - 1
3142
+ if weight % 2 == 0:
3143
+ return d
3144
+
3145
+ # TODO: I don't know a formula for dim ModSym_k(Gamma_1(N)) for odd k!!!
3146
+
3147
+ return None
3148
+
3149
+ def _repr_(self):
3150
+ r"""
3151
+ Return a string representation of this space.
3152
+
3153
+ EXAMPLES::
3154
+
3155
+ sage: M = ModularSymbols(Gamma1(7),3)
3156
+ sage: M # indirect doctest
3157
+ Modular Symbols space of dimension 8 for Gamma_1(7) of weight 3 with sign 0 over Rational Field
3158
+ """
3159
+ return ("Modular Symbols space of dimension %s for Gamma_1(%s) of weight %s with sign %s over %s"
3160
+ % (self.dimension(), self.level(), self.weight(), self.sign(), self.base_ring()))
3161
+
3162
+ def _cuspidal_submodule_dimension_formula(self):
3163
+ r"""
3164
+ Return the dimension of the cuspidal subspace, using the formula.
3165
+
3166
+ EXAMPLES::
3167
+
3168
+ sage: M = ModularSymbols(Gamma1(11),4)
3169
+ sage: M.cuspidal_subspace().dimension()
3170
+ 20
3171
+ sage: M._cuspidal_submodule_dimension_formula()
3172
+ 20
3173
+ """
3174
+ if self.sign() == 0:
3175
+ m = 2
3176
+ else:
3177
+ m = 1
3178
+ return m * self.group().dimension_cusp_forms(self.weight())
3179
+
3180
+ def _cuspidal_new_submodule_dimension_formula(self):
3181
+ r"""
3182
+ Return the dimension of the new cuspidal subspace, via the formula.
3183
+
3184
+ EXAMPLES::
3185
+
3186
+ sage: M = ModularSymbols(Gamma1(22),2)
3187
+ sage: M._cuspidal_new_submodule_dimension_formula()
3188
+ 8
3189
+ sage: M.cuspidal_subspace().new_subspace().dimension()
3190
+ 8
3191
+ """
3192
+ if self.sign() == 0:
3193
+ m = 2
3194
+ else:
3195
+ m = 1
3196
+ return m * self.group().dimension_new_cusp_forms(self.weight())
3197
+
3198
+ def _compute_hecke_matrix_prime_power(self, p, r):
3199
+ r"""
3200
+ Compute and return the matrix of the Hecke operator `T(p^r)`.
3201
+
3202
+ EXAMPLES::
3203
+
3204
+ sage: m = ModularSymbols(Gamma1(11),2)
3205
+ sage: m._compute_hecke_matrix_prime_power(3,4).charpoly('x')
3206
+ x^11 - 291*x^10 + 30555*x^9 - 1636145*x^8 + 59637480*x^7 + 1983040928*x^6 - 401988683888*x^5 - 14142158875680*x^4 + 3243232720819520*x^3 - 103658398669404480*x^2 + 197645665452381696*x - 97215957397309696
3207
+ """
3208
+ return self._compute_hecke_matrix_prime(p**r)
3209
+
3210
+ def _degeneracy_raising_matrix_1(self, M):
3211
+ r"""
3212
+ Return the matrix of the degeneracy raising map to `M`.
3213
+
3214
+ INPUT:
3215
+
3216
+ - ``M`` -- an ambient space of Gamma1 modular symbols, of level a
3217
+ multiple of the level of self
3218
+
3219
+ OUTPUT:
3220
+
3221
+ (matrix) The matrix of the degeneracy raising matrix to the higher level.
3222
+
3223
+ EXAMPLES::
3224
+
3225
+ sage: M = ModularSymbols(Gamma1(7),3)
3226
+ sage: N = ModularSymbols(Gamma1(21), 3)
3227
+ sage: M._degeneracy_raising_matrix_1(N)
3228
+ 8 x 64 dense matrix over Rational Field (use the '.str()' method to see the entries)
3229
+ sage: M.dimension()
3230
+ 8
3231
+ sage: N.dimension()
3232
+ 64
3233
+ """
3234
+ N = self.level()
3235
+
3236
+ # 1. Find coset representatives H for Gamma_1(M.level()) \ Gamma_1(self.level())
3237
+ H = arithgroup.degeneracy_coset_representatives_gamma1(M.level(), N, 1)
3238
+ # 2. The map is
3239
+ # [P,pi(g)] |--> sum_{h in H} [P, pi(h*g)]
3240
+ #
3241
+ MS = MatrixSpace(self.base_ring(), self.dimension(), M.dimension())
3242
+ if self.dimension() == 0 or M.dimension() == 0:
3243
+ return MS(0)
3244
+ rows = []
3245
+ B = self.manin_basis()
3246
+ syms = self.manin_symbols()
3247
+ G = MatrixSpace(ZZ, 2)
3248
+ H = [G(h) for h in H]
3249
+ for n in B:
3250
+ z = M(0)
3251
+ s = syms.manin_symbol(n)
3252
+ g = G(list(s.lift_to_sl2z(N)))
3253
+ i = s.i
3254
+ # We apply each matrix in H according to the above formula
3255
+ for h in H:
3256
+ hg = h*g
3257
+ z += M((i, hg[1, 0], hg[1, 1]))
3258
+ rows.append(z.element())
3259
+
3260
+ return MS(rows)
3261
+
3262
+ def boundary_space(self):
3263
+ r"""
3264
+ Return the space of boundary modular symbols for this space.
3265
+
3266
+ EXAMPLES::
3267
+
3268
+ sage: M = ModularSymbols(100,2)
3269
+ sage: M.boundary_space()
3270
+ Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(100) of weight 2 over Rational Field
3271
+ """
3272
+ try:
3273
+ return self.__boundary_space
3274
+ except AttributeError:
3275
+ pass
3276
+ self.__boundary_space = boundary.BoundarySpace_wtk_g1(
3277
+ self.level(), self.weight(), self.sign(), self.base_ring())
3278
+ return self.__boundary_space
3279
+
3280
+ def manin_symbols(self):
3281
+ r"""
3282
+ Return the Manin symbol list of this modular symbol space.
3283
+
3284
+ EXAMPLES::
3285
+
3286
+ sage: M = ModularSymbols(Gamma1(30),4)
3287
+ sage: M.manin_symbols()
3288
+ Manin Symbol List of weight 4 for Gamma1(30)
3289
+ sage: len(M.manin_symbols())
3290
+ 1728
3291
+ """
3292
+ try:
3293
+ return self.__manin_symbols
3294
+ except AttributeError:
3295
+ self.__manin_symbols = ManinSymbolList_gamma1(
3296
+ level=self.level(), weight=self.weight())
3297
+ return self.__manin_symbols
3298
+
3299
+
3300
+ class ModularSymbolsAmbient_wtk_gamma_h(ModularSymbolsAmbient):
3301
+ def __init__(self, group, weight, sign, F, custom_init=None, category=None):
3302
+ r"""
3303
+ Initialize a space of modular symbols for `\Gamma_H(N)`.
3304
+
3305
+ INPUT:
3306
+
3307
+ - ``group`` -- a congruence subgroup `\Gamma_H(N)`
3308
+
3309
+ - ``weight`` -- integer; the weight = 2
3310
+
3311
+ - ``sign`` -- integer; either -1, 0, or 1
3312
+
3313
+ - ``F`` -- field
3314
+
3315
+ EXAMPLES::
3316
+
3317
+ sage: ModularSymbols(GammaH(15,[4]),2)
3318
+ Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(15) with H generated by [4] of weight 2 with sign 0 over Rational Field
3319
+ """
3320
+ ModularSymbolsAmbient.__init__(self,
3321
+ weight=weight, group=group,
3322
+ sign=sign, base_ring=F,
3323
+ custom_init=custom_init,
3324
+ category=category)
3325
+
3326
+ def _dimension_formula(self):
3327
+ r"""
3328
+ Return None: we have no dimension formulas for `\Gamma_H(N)` spaces.
3329
+
3330
+ EXAMPLES::
3331
+
3332
+ sage: M = ModularSymbols(GammaH(15,[4]),2)
3333
+ sage: M.dimension()
3334
+ 9
3335
+ sage: M._dimension_formula()
3336
+ """
3337
+ return
3338
+
3339
+ def _repr_(self):
3340
+ r"""
3341
+ Return a string representation of this space.
3342
+
3343
+ EXAMPLES::
3344
+
3345
+ sage: M = ModularSymbols(GammaH(15,[4]),2)
3346
+ sage: M # indirect doctest
3347
+ Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(15) with H generated by [4] of weight 2 with sign 0 over Rational Field
3348
+ """
3349
+ return ("Modular Symbols space of dimension %s for %s of weight %s with sign %s over %s"
3350
+ % (self.dimension(), self.group(), self.weight(), self.sign(), self.base_ring()))
3351
+
3352
+ def _cuspidal_submodule_dimension_formula(self):
3353
+ r"""
3354
+ Return None: we have no dimension formulas for `\Gamma_H(N)` spaces.
3355
+
3356
+ EXAMPLES::
3357
+
3358
+ sage: ModularSymbols(GammaH(15,[4]),2)._cuspidal_submodule_dimension_formula() is None
3359
+ True
3360
+ """
3361
+ return
3362
+
3363
+ def _cuspidal_new_submodule_dimension_formula(self):
3364
+ r"""
3365
+ Return None: we have no dimension formulas for `\Gamma_H(N)` spaces.
3366
+
3367
+ EXAMPLES::
3368
+
3369
+ sage: ModularSymbols(GammaH(15,[4]),2)._cuspidal_new_submodule_dimension_formula() is None
3370
+ True
3371
+ """
3372
+ return
3373
+
3374
+ def _compute_hecke_matrix_prime_power(self, p, r):
3375
+ r"""
3376
+ Return matrix of a prime-power Hecke operator.
3377
+
3378
+ EXAMPLES::
3379
+
3380
+ sage: M = ModularSymbols(GammaH(15,[4]),2)
3381
+ sage: M._compute_hecke_matrix_prime_power(2, 3)
3382
+ [10 0 5 1 0 0 0 4 0]
3383
+ [ 0 10 0 4 10 -5 -5 -4 5]
3384
+ [ 5 0 10 -4 0 0 0 -1 0]
3385
+ [ 0 0 0 -1 0 0 0 -4 0]
3386
+ [ 0 0 0 -7 5 0 10 -3 6]
3387
+ [ 0 -5 0 -6 0 10 5 -4 -1]
3388
+ [ 0 0 0 -3 10 0 5 -7 6]
3389
+ [ 0 0 0 -4 0 0 0 -1 0]
3390
+ [ 0 0 0 0 0 0 0 0 3]
3391
+ sage: M.hecke_matrix(7)^2 == M.hecke_matrix(49) + 7 * M.diamond_bracket_operator(7).matrix() # indirect doctest
3392
+ True
3393
+ """
3394
+ return self._compute_hecke_matrix_prime(p**r)
3395
+
3396
+ def _degeneracy_raising_matrix_1(self, level):
3397
+ r"""
3398
+ Return matrix of a degeneracy raising map.
3399
+
3400
+ EXAMPLES::
3401
+
3402
+ sage: ModularSymbols(GammaH(15,[4]),2)._degeneracy_raising_matrix_1(ModularSymbols(GammaH(30, [19]), 2))
3403
+ Traceback (most recent call last):
3404
+ ...
3405
+ NotImplementedError
3406
+ """
3407
+ raise NotImplementedError
3408
+
3409
+ def boundary_space(self):
3410
+ r"""
3411
+ Return the space of boundary modular symbols for this space.
3412
+
3413
+ EXAMPLES::
3414
+
3415
+ sage: M = ModularSymbols(GammaH(15,[4]),2)
3416
+ sage: M.boundary_space()
3417
+ Boundary Modular Symbols space for Congruence Subgroup Gamma_H(15) with H generated by [4] of weight 2 over Rational Field
3418
+ """
3419
+ try:
3420
+ return self.__boundary_space
3421
+ except AttributeError:
3422
+ pass
3423
+ self.__boundary_space = boundary.BoundarySpace_wtk_gamma_h(
3424
+ self.group(), self.weight(), self.sign(), self.base_ring())
3425
+ return self.__boundary_space
3426
+
3427
+ def manin_symbols(self):
3428
+ r"""
3429
+ Return the Manin symbol list of this modular symbol space.
3430
+
3431
+ EXAMPLES::
3432
+
3433
+ sage: M = ModularSymbols(GammaH(15,[4]),2)
3434
+ sage: M.manin_symbols()
3435
+ Manin Symbol List of weight 2 for Congruence Subgroup Gamma_H(15) with H generated by [4]
3436
+ sage: len(M.manin_symbols())
3437
+ 96
3438
+ """
3439
+ try:
3440
+ return self.__manin_symbols
3441
+ except AttributeError:
3442
+ self.__manin_symbols = ManinSymbolList_gamma_h(
3443
+ group=self.group(), weight=self.weight())
3444
+ return self.__manin_symbols
3445
+
3446
+
3447
+ class ModularSymbolsAmbient_wtk_eps(ModularSymbolsAmbient):
3448
+ def __init__(self, eps, weight, sign, base_ring, custom_init=None, category=None):
3449
+ """
3450
+ Space of modular symbols with given weight, character, base ring and
3451
+ sign.
3452
+
3453
+ INPUT:
3454
+
3455
+ - ``eps`` -- dirichlet.DirichletCharacter, the
3456
+ "Nebentypus" character
3457
+
3458
+ - ``weight`` -- integer; the weight = 2
3459
+
3460
+ - ``sign`` -- integer; either -1, 0, or 1
3461
+
3462
+ - ``base_ring`` -- the base ring; it must be possible to change the ring
3463
+ of the character to this base ring (not always canonically)
3464
+
3465
+ EXAMPLES::
3466
+
3467
+ sage: eps = DirichletGroup(4).gen(0)
3468
+ sage: eps.order()
3469
+ 2
3470
+ sage: ModularSymbols(eps, 2)
3471
+ Modular Symbols space of dimension 0 and level 4, weight 2, character [-1], sign 0, over Rational Field
3472
+ sage: ModularSymbols(eps, 3)
3473
+ Modular Symbols space of dimension 2 and level 4, weight 3, character [-1], sign 0, over Rational Field
3474
+
3475
+ We next create a space with character of order bigger than 2.
3476
+
3477
+ ::
3478
+
3479
+ sage: eps = DirichletGroup(5).gen(0)
3480
+ sage: eps # has order 4
3481
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4
3482
+ sage: ModularSymbols(eps, 2).dimension()
3483
+ 0
3484
+ sage: ModularSymbols(eps, 3).dimension()
3485
+ 2
3486
+
3487
+ Here is another example::
3488
+
3489
+ sage: G.<e> = DirichletGroup(5)
3490
+ sage: M = ModularSymbols(e,3)
3491
+ sage: loads(M.dumps()) == M
3492
+ True
3493
+ """
3494
+ level = eps.modulus()
3495
+ ModularSymbolsAmbient.__init__(self,
3496
+ weight=weight,
3497
+ group=arithgroup.Gamma1(level),
3498
+ sign=sign,
3499
+ base_ring=base_ring,
3500
+ character=eps.change_ring(base_ring),
3501
+ custom_init=custom_init,
3502
+ category=category)
3503
+
3504
+ def _repr_(self):
3505
+ r"""
3506
+ Return a string representation of this space.
3507
+
3508
+ EXAMPLES::
3509
+
3510
+ sage: G.<e> = DirichletGroup(5)
3511
+ sage: M = ModularSymbols(e,3)
3512
+ sage: M # indirect doctest
3513
+ Modular Symbols space of dimension 2 and level 5, weight 3, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
3514
+ """
3515
+ return ("Modular Symbols space of dimension %s and level %s, weight %s, character %s, sign %s, " +
3516
+ "over %s") % (self.dimension(), self.level(), self.weight(),
3517
+ self.character()._repr_short_(), self.sign(),
3518
+ self.base_ring())
3519
+
3520
+ def _cuspidal_submodule_dimension_formula(self):
3521
+ r"""
3522
+ Return the dimension for the cuspidal subspace of this space, given by the formula.
3523
+
3524
+ EXAMPLES::
3525
+
3526
+ sage: G.<e> = DirichletGroup(50)
3527
+ sage: M = ModularSymbols(e^2,2)
3528
+ sage: M.dimension()
3529
+ 16
3530
+ sage: M._cuspidal_submodule_dimension_formula()
3531
+ 12
3532
+ """
3533
+ if self.base_ring().characteristic() != 0:
3534
+ raise NotImplementedError
3535
+ if self.sign() == 0:
3536
+ m = 2
3537
+ else:
3538
+ m = 1
3539
+ return m * self.group().dimension_cusp_forms(self.weight(), eps=self.character())
3540
+
3541
+ def _cuspidal_new_submodule_dimension_formula(self):
3542
+ r"""
3543
+ Return the dimension for the new cuspidal subspace of this space, given by the formula.
3544
+
3545
+ EXAMPLES::
3546
+
3547
+ sage: G.<e> = DirichletGroup(50)
3548
+ sage: M = ModularSymbols(e,3)
3549
+ sage: M.dimension()
3550
+ 30
3551
+ sage: M._cuspidal_new_submodule_dimension_formula()
3552
+ 10
3553
+ """
3554
+ if self.base_ring().characteristic() != 0:
3555
+ raise NotImplementedError
3556
+ if self.sign() == 0:
3557
+ m = 2
3558
+ else:
3559
+ m = 1
3560
+ return m * self.group().dimension_new_cusp_forms(self.weight(), eps=self.character())
3561
+
3562
+ def _matrix_of_operator_on_modular_symbols(self, codomain, R, character_twist=False):
3563
+ r"""
3564
+ INPUT:
3565
+
3566
+ - ``self`` -- this space of modular symbols
3567
+
3568
+ - ``codomain`` -- space of modular symbols
3569
+
3570
+ - ``R`` -- list of lists [a,b,c,d] of length 4, which
3571
+ we view as elements of GL_2(Q)
3572
+
3573
+ OUTPUT: a matrix, which represents the operator
3574
+
3575
+ .. MATH::
3576
+
3577
+ x \mapsto \sum_{g in R} g.x,
3578
+
3579
+
3580
+ where g.x is the formal linear fractional transformation on modular
3581
+ symbols.
3582
+
3583
+ EXAMPLES::
3584
+
3585
+ sage: G.<e> = DirichletGroup(5)
3586
+ sage: M = ModularSymbols(e,3)
3587
+ sage: M.dimension()
3588
+ 2
3589
+ sage: M._matrix_of_operator_on_modular_symbols(M,HeilbronnCremona(3))
3590
+ [ 6 6]
3591
+ [ 0 10]
3592
+ """
3593
+ eps = self.character()
3594
+ rows = []
3595
+ for b in self.basis():
3596
+ v = FormalSum(0, check=False)
3597
+ for c, x in b.modular_symbol_rep():
3598
+ for g in R:
3599
+ y = x.apply(g)
3600
+ if character_twist:
3601
+ v += y*c*eps(g[0])
3602
+ else:
3603
+ v += y*c
3604
+ w = codomain(v).element()
3605
+ rows.append(w)
3606
+ M = MatrixSpace(self.base_ring(), len(rows), codomain.degree(), sparse=False)
3607
+ return M(rows)
3608
+
3609
+ def _degeneracy_raising_matrix_1(self, M):
3610
+ r"""
3611
+ Return the matrix of the degeneracy raising map to ``M``, which should
3612
+ be a space of modular symbols with level a multiple of the level of
3613
+ ``self`` and with compatible character.
3614
+
3615
+ INPUT:
3616
+
3617
+ - ``M`` -- a space of modular symbols with character, whose level
3618
+ should be an integer multiple of the level of ``self``, and whose
3619
+ character should be the Dirichlet character at that level obtained by
3620
+ extending the character of ``self``.
3621
+
3622
+ The input is *not* sanity-checked in any way -- use with care!
3623
+
3624
+ OUTPUT:
3625
+
3626
+ (matrix) The matrix of the degeneracy raising matrix to the higher level.
3627
+
3628
+ EXAMPLES::
3629
+
3630
+ sage: eps = DirichletGroup(4).gen(0)
3631
+ sage: M = ModularSymbols(eps, 3); M
3632
+ Modular Symbols space of dimension 2 and level 4, weight 3, character [-1], sign 0, over Rational Field
3633
+ sage: M._degeneracy_raising_matrix_1(ModularSymbols(eps.extend(20), 3))
3634
+ [ 1 0 0 0 -1 -1 3 1 0 2 -3 0]
3635
+ [ 0 5 1 -2 -3 3 0 4 -1 5 -7 -1]
3636
+ """
3637
+ N = self.level()
3638
+
3639
+ # 1. Find coset representatives H for Gamma_0(M.level()) \ Gamma_0(self.level())
3640
+ H = arithgroup.degeneracy_coset_representatives_gamma0(M.level(), N, 1)
3641
+ # 2. The map is
3642
+ # [P,pi(g)] |--> sum_{h in H} [P, pi(h*g)]
3643
+ #
3644
+ MS = MatrixSpace(self.base_ring(), self.dimension(), M.dimension())
3645
+ if self.dimension() == 0 or M.dimension() == 0:
3646
+ return MS(0)
3647
+ rows = []
3648
+ B = self.manin_basis()
3649
+ syms = self.manin_symbols()
3650
+ G = MatrixSpace(ZZ, 2)
3651
+ H = [G(h) for h in H]
3652
+ eps = self.character()
3653
+ # note: in my thesis I twisted by eps^(-1), which is definitely a mistake
3654
+ # since twisting by eps gives the right answer and by eps^(-1) does not.
3655
+
3656
+ for n in B:
3657
+ z = M(0)
3658
+ s = syms.manin_symbol(n)
3659
+ g = G(list(s.lift_to_sl2z(N)))
3660
+ i = s.i
3661
+ # We apply each matrix in H according to the above formula
3662
+ for h in H:
3663
+ hg = h * g
3664
+ z += eps(h[0, 0]) * M((i, hg[1, 0], hg[1, 1]))
3665
+ rows.append(z.element())
3666
+ return MS(rows)
3667
+
3668
+ def _dimension_formula(self):
3669
+ r"""
3670
+ Return None: we have no dimension formula for `\Gamma_H(N)` spaces.
3671
+
3672
+ EXAMPLES::
3673
+
3674
+ sage: eps = DirichletGroup(5).gen(0)
3675
+ sage: M = ModularSymbols(eps, 2)
3676
+ sage: M.dimension()
3677
+ 0
3678
+ sage: M._dimension_formula()
3679
+ """
3680
+ return
3681
+
3682
+ def boundary_space(self):
3683
+ r"""
3684
+ Return the space of boundary modular symbols for this space.
3685
+
3686
+ EXAMPLES::
3687
+
3688
+ sage: eps = DirichletGroup(5).gen(0)
3689
+ sage: M = ModularSymbols(eps, 2)
3690
+ sage: M.boundary_space()
3691
+ Boundary Modular Symbols space of level 5, weight 2, character [zeta4] and dimension 0 over Cyclotomic Field of order 4 and degree 2
3692
+ """
3693
+ try:
3694
+ return self.__boundary_space
3695
+ except AttributeError:
3696
+ pass
3697
+ self.__boundary_space = boundary.BoundarySpace_wtk_eps(
3698
+ self.character(), self.weight(), self.sign())
3699
+ return self.__boundary_space
3700
+
3701
+ def manin_symbols(self):
3702
+ r"""
3703
+ Return the Manin symbol list of this modular symbol space.
3704
+
3705
+ EXAMPLES::
3706
+
3707
+ sage: eps = DirichletGroup(5).gen(0)
3708
+ sage: M = ModularSymbols(eps, 2)
3709
+ sage: M.manin_symbols()
3710
+ Manin Symbol List of weight 2 for Gamma1(5) with character [zeta4]
3711
+ sage: len(M.manin_symbols())
3712
+ 6
3713
+ """
3714
+ try:
3715
+ return self.__manin_symbols
3716
+ except AttributeError:
3717
+ self.__manin_symbols = ManinSymbolList_character(
3718
+ character=self.character(), weight=self.weight())
3719
+ return self.__manin_symbols
3720
+
3721
+ def modular_symbols_of_level(self, N):
3722
+ r"""
3723
+ Return a space of modular symbols with the same parameters as
3724
+ this space except with level `N`.
3725
+
3726
+ INPUT:
3727
+
3728
+ - ``N`` -- positive integer
3729
+
3730
+ OUTPUT:
3731
+
3732
+ (Modular Symbol space) A space of modular symbols with the
3733
+ same defining properties (weight, sign, etc.) as this space
3734
+ except with level `N`.
3735
+
3736
+ EXAMPLES::
3737
+
3738
+ sage: eps = DirichletGroup(5).gen(0)
3739
+ sage: M = ModularSymbols(eps, 2); M
3740
+ Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
3741
+ sage: M.modular_symbols_of_level(15)
3742
+ Modular Symbols space of dimension 0 and level 15, weight 2, character [1, zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
3743
+ """
3744
+ if self.level() % N == 0:
3745
+ eps = self.character().restrict(N)
3746
+ elif N % self.level() == 0:
3747
+ eps = self.character().extend(N)
3748
+ else:
3749
+ raise ValueError("The level N (=%s) must be a divisor or multiple of the modulus of the character (=%s)" % (N, self.level()))
3750
+ return modsym.ModularSymbols(eps, self.weight(), self.sign(), self.base_ring())
3751
+
3752
+ def modular_symbols_of_sign(self, sign):
3753
+ r"""
3754
+ Return a space of modular symbols with the same defining
3755
+ properties (weight, level, etc.) as this space except with given
3756
+ sign.
3757
+
3758
+ INPUT:
3759
+
3760
+ - ``sign`` -- integer; a sign (`+1`, `-1` or `0`)
3761
+
3762
+ OUTPUT:
3763
+
3764
+ (ModularSymbolsAmbient) A space of modular symbols with the
3765
+ same defining properties (weight, level, etc.) as this space
3766
+ except with given sign.
3767
+
3768
+ EXAMPLES::
3769
+
3770
+ sage: eps = DirichletGroup(5).gen(0)
3771
+ sage: M = ModularSymbols(eps, 2); M
3772
+ Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
3773
+ sage: M.modular_symbols_of_sign(0) == M
3774
+ True
3775
+ sage: M.modular_symbols_of_sign(+1)
3776
+ Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign 1, over Cyclotomic Field of order 4 and degree 2
3777
+ sage: M.modular_symbols_of_sign(-1)
3778
+ Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign -1, over Cyclotomic Field of order 4 and degree 2
3779
+ """
3780
+ return modsym.ModularSymbols(self.character(), self.weight(), sign, self.base_ring())
3781
+
3782
+ def modular_symbols_of_weight(self, k):
3783
+ r"""
3784
+ Return a space of modular symbols with the same defining
3785
+ properties (weight, sign, etc.) as this space except with weight
3786
+ `k`.
3787
+
3788
+ INPUT:
3789
+
3790
+ - ``k`` -- positive integer
3791
+
3792
+ OUTPUT:
3793
+
3794
+ (ModularSymbolsAmbient) A space of modular symbols with the
3795
+ same defining properties (level, sign) as this space
3796
+ except with given weight.
3797
+
3798
+ EXAMPLES::
3799
+
3800
+ sage: eps = DirichletGroup(5).gen(0)
3801
+ sage: M = ModularSymbols(eps, 2); M
3802
+ Modular Symbols space of dimension 0 and level 5, weight 2, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
3803
+ sage: M.modular_symbols_of_weight(3)
3804
+ Modular Symbols space of dimension 2 and level 5, weight 3, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
3805
+ sage: M.modular_symbols_of_weight(2) == M
3806
+ True
3807
+ """
3808
+ return modsym.ModularSymbols(self.character(), k, self.sign(), self.base_ring())
3809
+
3810
+ def _hecke_images(self, i, v):
3811
+ """
3812
+ Return images of the `i`-th standard basis vector under the
3813
+ Hecke operators `T_p` for all integers in `v`.
3814
+
3815
+ INPUT:
3816
+
3817
+ - ``i`` -- nonnegative integer
3818
+
3819
+ - ``v`` -- list of positive integer
3820
+
3821
+ OUTPUT: ``matrix`` -- whose rows are the Hecke images
3822
+
3823
+ EXAMPLES::
3824
+
3825
+ sage: G.<e> = DirichletGroup(50,QQ)
3826
+ sage: M = ModularSymbols(e^2,2)
3827
+ sage: M.dimension()
3828
+ 15
3829
+ sage: M._hecke_images(8,list(range(1,5)))
3830
+ [ 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]
3831
+ [ 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0]
3832
+ [ 0 1 0 2 0 -1 1 1 0 0 0 0 0 0 0]
3833
+ [ 0 1 1 -1 -1 0 -1 1 1 0 1 2 0 -2 2]
3834
+ """
3835
+ if self.weight() != 2:
3836
+ raise NotImplementedError("Hecke images only implemented when the weight is 2")
3837
+ chi = self.character()
3838
+ # Find basis vector for ambient space such that it is not in
3839
+ # the kernel of the dual space corresponding to self.
3840
+ c = self.manin_generators()[self.manin_basis()[i]]
3841
+ N = self.level()
3842
+ if chi.order() > 2:
3843
+ return heilbronn.hecke_images_nonquad_character_weight2(c.u, c.v, N,
3844
+ v, chi, self.manin_gens_to_basis())
3845
+ return heilbronn.hecke_images_quad_character_weight2(c.u, c.v, N,
3846
+ v, chi, self.manin_gens_to_basis())