passagemath-schemes 10.6.47__cp312-cp312-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) 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.47.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
  9. passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.47.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-312-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-312-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-312-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-312-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-312-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-312-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-312-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-312-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_nf.py +1241 -0
  154. sage/modular/modsym/relation_matrix.py +591 -0
  155. sage/modular/modsym/relation_matrix_pyx.cpython-312-darwin.so +0 -0
  156. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  157. sage/modular/modsym/space.py +2468 -0
  158. sage/modular/modsym/subspace.py +455 -0
  159. sage/modular/modsym/tests.py +375 -0
  160. sage/modular/multiple_zeta.py +2632 -0
  161. sage/modular/multiple_zeta_F_algebra.py +786 -0
  162. sage/modular/overconvergent/all.py +6 -0
  163. sage/modular/overconvergent/genus0.py +1878 -0
  164. sage/modular/overconvergent/hecke_series.py +1187 -0
  165. sage/modular/overconvergent/weightspace.py +778 -0
  166. sage/modular/pollack_stevens/all.py +4 -0
  167. sage/modular/pollack_stevens/distributions.py +874 -0
  168. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  169. sage/modular/pollack_stevens/manin_map.py +859 -0
  170. sage/modular/pollack_stevens/modsym.py +1593 -0
  171. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  172. sage/modular/pollack_stevens/sigma0.py +534 -0
  173. sage/modular/pollack_stevens/space.py +1076 -0
  174. sage/modular/quasimodform/all.py +3 -0
  175. sage/modular/quasimodform/element.py +845 -0
  176. sage/modular/quasimodform/ring.py +828 -0
  177. sage/modular/quatalg/all.py +3 -0
  178. sage/modular/quatalg/brandt.py +1642 -0
  179. sage/modular/ssmod/all.py +8 -0
  180. sage/modular/ssmod/ssmod.py +827 -0
  181. sage/rings/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  183. sage/rings/polynomial/binary_form_reduce.py +585 -0
  184. sage/schemes/all.py +41 -0
  185. sage/schemes/berkovich/all.py +6 -0
  186. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  187. sage/schemes/berkovich/berkovich_space.py +748 -0
  188. sage/schemes/curves/affine_curve.py +2928 -0
  189. sage/schemes/curves/all.py +33 -0
  190. sage/schemes/curves/closed_point.py +434 -0
  191. sage/schemes/curves/constructor.py +381 -0
  192. sage/schemes/curves/curve.py +542 -0
  193. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  194. sage/schemes/curves/point.py +463 -0
  195. sage/schemes/curves/projective_curve.py +3026 -0
  196. sage/schemes/curves/zariski_vankampen.py +1932 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +1036 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1102 -0
  208. sage/schemes/elliptic_curves/constructor.py +1552 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4787 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7335 -0
  229. sage/schemes/elliptic_curves/height.py +2109 -0
  230. sage/schemes/elliptic_curves/hom.py +1406 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  232. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  233. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  234. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  235. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  236. sage/schemes/elliptic_curves/homset.py +271 -0
  237. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  238. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  239. sage/schemes/elliptic_curves/jacobian.py +237 -0
  240. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  241. sage/schemes/elliptic_curves/kraus.py +1014 -0
  242. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  243. sage/schemes/elliptic_curves/mod5family.py +105 -0
  244. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  245. sage/schemes/elliptic_curves/mod_sym_num.cpython-312-darwin.so +0 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  247. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  248. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  249. sage/schemes/elliptic_curves/padics.py +1816 -0
  250. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  251. sage/schemes/elliptic_curves/period_lattice_region.cpython-312-darwin.so +0 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  253. sage/schemes/elliptic_curves/saturation.py +715 -0
  254. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  255. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  256. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  257. sage/schemes/hyperelliptic_curves/all.py +6 -0
  258. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  259. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  264. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  265. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  270. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  271. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  272. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  273. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  274. sage/schemes/jacobians/all.py +2 -0
  275. sage/schemes/overview.py +161 -0
  276. sage/schemes/plane_conics/all.py +22 -0
  277. sage/schemes/plane_conics/con_field.py +1296 -0
  278. sage/schemes/plane_conics/con_finite_field.py +158 -0
  279. sage/schemes/plane_conics/con_number_field.py +456 -0
  280. sage/schemes/plane_conics/con_rational_field.py +406 -0
  281. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  282. sage/schemes/plane_conics/constructor.py +249 -0
  283. sage/schemes/plane_quartics/all.py +2 -0
  284. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  285. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  286. sage/schemes/riemann_surfaces/all.py +1 -0
  287. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  288. sage_wheels/share/cremona/cremona_mini.db +0 -0
  289. sage_wheels/share/ellcurves/rank0 +30427 -0
  290. sage_wheels/share/ellcurves/rank1 +31871 -0
  291. sage_wheels/share/ellcurves/rank10 +6 -0
  292. sage_wheels/share/ellcurves/rank11 +6 -0
  293. sage_wheels/share/ellcurves/rank12 +1 -0
  294. sage_wheels/share/ellcurves/rank14 +1 -0
  295. sage_wheels/share/ellcurves/rank15 +1 -0
  296. sage_wheels/share/ellcurves/rank17 +1 -0
  297. sage_wheels/share/ellcurves/rank19 +1 -0
  298. sage_wheels/share/ellcurves/rank2 +2388 -0
  299. sage_wheels/share/ellcurves/rank20 +1 -0
  300. sage_wheels/share/ellcurves/rank21 +1 -0
  301. sage_wheels/share/ellcurves/rank22 +1 -0
  302. sage_wheels/share/ellcurves/rank23 +1 -0
  303. sage_wheels/share/ellcurves/rank24 +1 -0
  304. sage_wheels/share/ellcurves/rank28 +1 -0
  305. sage_wheels/share/ellcurves/rank3 +836 -0
  306. sage_wheels/share/ellcurves/rank4 +10 -0
  307. sage_wheels/share/ellcurves/rank5 +5 -0
  308. sage_wheels/share/ellcurves/rank6 +5 -0
  309. sage_wheels/share/ellcurves/rank7 +5 -0
  310. sage_wheels/share/ellcurves/rank8 +6 -0
  311. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,1420 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.libs.flint sage.libs.pari
3
+ r"""
4
+ Space of boundary modular symbols
5
+
6
+ Used mainly for computing the cuspidal subspace of modular symbols. The space
7
+ of boundary symbols of sign 0 is isomorphic as a Hecke module to the dual of
8
+ the space of Eisenstein series, but this does not give a useful method of
9
+ computing Eisenstein series, since there is no easy way to extract the constant
10
+ terms.
11
+
12
+ We represent boundary modular symbols as a sum of Manin symbols of the form
13
+ `[P, u/v]`, where `u/v` is a cusp for our group `G`. The group of boundary
14
+ modular symbols naturally embeds into a vector space `B_k(G)` (see Stein,
15
+ section 8.4, or Merel, section 1.4, where this space is called `\CC[\Gamma
16
+ \backslash \QQ]_k`, for a definition), which is a finite dimensional `\QQ`
17
+ vector space, of dimension equal to the number of cusps for `G` (if `k` is
18
+ even), or the number of regular cusps (if `k` is odd). The embedding
19
+ takes `[P, u/v]` to `P(u,v)\cdot [(u,v)]`. We represent the basis vectors by
20
+ pairs `[(u,v)]` with u, v coprime. On `B_k(G)`, we have the relations
21
+
22
+ .. MATH::
23
+
24
+ [\gamma \cdot (u,v)] = [(u,v)]
25
+
26
+ for all `\gamma \in G` and
27
+
28
+ .. MATH::
29
+
30
+ [(\lambda u, \lambda v)] = \operatorname{sign}(\lambda)^k [(u,v)]
31
+
32
+
33
+ for all `\lambda \in \QQ^\times`.
34
+
35
+ It's possible for these relations to kill a class, i.e., for a pair `[(u,v)]`
36
+ to be 0. For example, when `N=4` and `k=3` then `(-1,-2)` is equivalent mod
37
+ `\Gamma_1(4)` to `(1,2)` since `2=-2 \bmod 4` and `1=-1 \bmod 2`. But since `k`
38
+ is odd, `[(-1,-2)]` is also equivalent to `-[(1,2)]`. Thus this symbol is
39
+ equivalent to its negative, hence 0 (notice that this wouldn't be the case in
40
+ characteristic 2). This happens for any irregular cusp when the weight is odd;
41
+ there are no irregular cusps on `\Gamma_1(N)` except when `N = 4`, but there
42
+ can be more on `\Gamma_H` groups. See also prop 2.30 of Stein's Ph.D. thesis.
43
+
44
+ In addition, in the case that our space is of sign `\sigma = 1` or `-1`, we
45
+ also have the relation `[(-u,v)] = \sigma \cdot [(u,v)]`. This relation can
46
+ also combine with the above to kill a cusp class - for instance, take (u,v) =
47
+ (1,3) for `\Gamma_1(5)`. Then since the cusp `\tfrac{1}{3}` is
48
+ `\Gamma_1(5)`-equivalent to the cusp `-\tfrac{1}{3}`, we have that `[(1,3)] =
49
+ [(-1,3)]`. Now, on the minus subspace, we also have that `[(-1,3)] = -[(1,3)]`,
50
+ which means this class must vanish. Notice that this cannot be used to show
51
+ that `[(1,0)]` or `[(0,1)]` is 0.
52
+
53
+ .. NOTE::
54
+
55
+ Special care must be taken when working with the images of the cusps 0 and
56
+ `\infty` in `B_k(G)`. For all cusps *except* 0 and `\infty`, multiplying the
57
+ cusp by -1 corresponds to taking `[(u,v)]` to `[(-u,v)]` in `B_k(G)`. This
58
+ means that `[(u,v)]` is equivalent to `[(-u,v)]` whenever `\tfrac{u}{v}` is
59
+ equivalent to `-\tfrac{u}{v}`, except in the case of 0 and `\infty`. We
60
+ have the following conditions for `[(1,0)]` and `[(0,1)]`:
61
+
62
+ - `[(0,1)] = \sigma \cdot [(0,1)]`, so `[(0,1)]` is 0 exactly when `\sigma =
63
+ -1`.
64
+
65
+ - `[(1,0)] = \sigma \cdot [(-1,0)]` and `[(1,0)] = (-1)^k [(-1,0)]`, so
66
+ `[(1,0)] = 0` whenever `\sigma \ne (-1)^k`.
67
+
68
+ .. NOTE::
69
+
70
+ For all the spaces of boundary symbols below, no work is done to determine
71
+ the cusps for G at creation time. Instead, cusps are added as they are
72
+ discovered in the course of computation. As a result, the rank of a space
73
+ can change as a computation proceeds.
74
+
75
+ REFERENCES:
76
+
77
+ - Merel, "Universal Fourier expansions of modular
78
+ forms." Springer LNM 1585 (1994), pg. 59-95.
79
+
80
+ - Stein, "Modular Forms, a computational approach." AMS (2007).
81
+ """
82
+ # ****************************************************************************
83
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
84
+ #
85
+ # This program is free software: you can redistribute it and/or modify
86
+ # it under the terms of the GNU General Public License as published by
87
+ # the Free Software Foundation, either version 2 of the License, or
88
+ # (at your option) any later version.
89
+ # https://www.gnu.org/licenses/
90
+ # ****************************************************************************
91
+
92
+
93
+ import sage.modular.arithgroup.all as arithgroup
94
+ import sage.modular.hecke.all as hecke
95
+ from sage.categories.rings import Rings
96
+ from sage.misc.repr import repr_lincomb
97
+ from sage.modular import cusps, dirichlet
98
+ from sage.modular.modsym.manin_symbol import ManinSymbol
99
+ from sage.modules import free_module
100
+ from sage.modules.free_module_element import FreeModuleElement
101
+ from sage.rings.rational_field import Q as QQ
102
+ from sage.structure.richcmp import richcmp, richcmp_method
103
+
104
+ from . import element
105
+
106
+
107
+ class BoundarySpaceElement(hecke.HeckeModuleElement):
108
+ def __init__(self, parent, x):
109
+ """
110
+ Create a boundary symbol.
111
+
112
+ INPUT:
113
+
114
+ - ``parent`` -- BoundarySpace; a space of boundary
115
+ modular symbols
116
+
117
+ - ``x`` -- dictionary with integer keys and values in the
118
+ base field of parent
119
+
120
+ EXAMPLES::
121
+
122
+ sage: B = ModularSymbols(Gamma0(32), sign=-1).boundary_space()
123
+ sage: B(Cusp(1,8))
124
+ [1/8]
125
+ sage: B.0
126
+ [1/8]
127
+ sage: type(B.0)
128
+ <class 'sage.modular.modsym.boundary.BoundarySpaceElement'>
129
+ """
130
+ self.__x = x
131
+ self.__vec = parent.free_module()(x)
132
+ hecke.HeckeModuleElement.__init__(self, parent, self.__vec)
133
+
134
+ def coordinate_vector(self):
135
+ r"""
136
+ Return ``self`` as a vector on the `\QQ`-vector space with basis
137
+ ``self.parent()._known_cusps()``.
138
+
139
+ EXAMPLES::
140
+
141
+ sage: B = ModularSymbols(18,4,sign=1).boundary_space()
142
+ sage: x = B(Cusp(1/2)) ; x
143
+ [1/2]
144
+ sage: x.coordinate_vector()
145
+ (1)
146
+ sage: ((18/5)*x).coordinate_vector()
147
+ (18/5)
148
+ sage: B(Cusp(0))
149
+ [0]
150
+ sage: x.coordinate_vector()
151
+ (1)
152
+ sage: x = B(Cusp(1/2)) ; x
153
+ [1/2]
154
+ sage: x.coordinate_vector()
155
+ (1, 0)
156
+ """
157
+ return self.__vec
158
+
159
+ def _repr_(self):
160
+ """
161
+ Return the string representation of ``self``.
162
+
163
+ EXAMPLES::
164
+
165
+ sage: ModularSymbols(Gamma0(11), 2).boundary_space()(Cusp(0))._repr_()
166
+ '[0]'
167
+ sage: (-6*ModularSymbols(Gamma0(11), 2).boundary_space()(Cusp(0)))._repr_()
168
+ '-6*[0]'
169
+ """
170
+ return repr_lincomb([('[' + repr(self.parent()._known_gens[i]) + ']', c)
171
+ for i, c in sorted(self.__x.items())])
172
+
173
+ # can't inherit arithmetic operations from HeckeModule, because basis
174
+ # dimension might change!
175
+
176
+ def _add_(self, other):
177
+ """
178
+ Return ``self + other``. Assumes that other is a BoundarySpaceElement.
179
+
180
+ EXAMPLES::
181
+
182
+ sage: B = ModularSymbols(Gamma1(16), 4).boundary_space()
183
+ sage: x = B(Cusp(2/7)) ; y = B(Cusp(13/16))
184
+ sage: x + y # indirect doctest
185
+ [2/7] + [13/16]
186
+ sage: x + x # indirect doctest
187
+ 2*[2/7]
188
+ """
189
+ z = dict(other.__x)
190
+ for i, c in self.__x.items():
191
+ if i in z:
192
+ z[i] += c
193
+ else:
194
+ z[i] = c
195
+ return BoundarySpaceElement(self.parent(), z)
196
+
197
+ def _sub_(self, other):
198
+ """
199
+ Return ``self - other``. Assumes that other is a BoundarySpaceElement.
200
+
201
+ EXAMPLES::
202
+
203
+ sage: B = ModularSymbols(Gamma1(16), 4).boundary_space()
204
+ sage: x = B(Cusp(2/7)) ; y = B(Cusp(13/16))
205
+ sage: x - y # indirect doctest
206
+ [2/7] - [13/16]
207
+ sage: x - x # indirect doctest
208
+ 0
209
+ """
210
+ z = dict(self.__x)
211
+ for i, c in other.__x.items():
212
+ if i in z:
213
+ z[i] -= c
214
+ else:
215
+ z[i] = -c
216
+ return BoundarySpaceElement(self.parent(), z)
217
+
218
+ def _rmul_(self, other):
219
+ r"""
220
+ Return ``self * other``.
221
+
222
+ Assumes that other can be coerced into
223
+ ``self.parent().base_ring()``.
224
+
225
+ EXAMPLES::
226
+
227
+ sage: B = ModularSymbols(Gamma1(16), 4).boundary_space()
228
+ sage: x = B(Cusp(2/7))
229
+ sage: x*5 # indirect doctest
230
+ 5*[2/7]
231
+ sage: x*-3/5 # indirect doctest
232
+ -3/5*[2/7]
233
+ """
234
+ x = {}
235
+ for i, c in self.__x.items():
236
+ x[i] = c * other
237
+ return BoundarySpaceElement(self.parent(), x)
238
+
239
+ def _lmul_(self, other):
240
+ r"""
241
+ Return ``other * self``.
242
+
243
+ Assumes that other can be coerced into
244
+ ``self.parent().base_ring()``.
245
+
246
+ EXAMPLES::
247
+
248
+ sage: B = ModularSymbols(Gamma1(16), 4).boundary_space()
249
+ sage: x = B(Cusp(13/16))
250
+ sage: 11*x # indirect doctest
251
+ 11*[13/16]
252
+ sage: 1/3*x # indirect doctest
253
+ 1/3*[13/16]
254
+ """
255
+ x = {}
256
+ for i, c in self.__x.items():
257
+ x[i] = other * c
258
+ return BoundarySpaceElement(self.parent(), x)
259
+
260
+ def __neg__(self):
261
+ """
262
+ Return -self.
263
+
264
+ EXAMPLES::
265
+
266
+ sage: B = ModularSymbols(Gamma1(16), 4).boundary_space()
267
+ sage: x = B(Cusp(2/7))
268
+ sage: -x # indirect doctest
269
+ -[2/7]
270
+ sage: -x + x # indirect doctest
271
+ 0
272
+ """
273
+ return self * (-1)
274
+
275
+
276
+ @richcmp_method
277
+ class BoundarySpace(hecke.HeckeModule_generic):
278
+ def __init__(self,
279
+ group=arithgroup.Gamma0(1),
280
+ weight=2,
281
+ sign=0,
282
+ base_ring=QQ,
283
+ character=None):
284
+ """
285
+ Space of boundary symbols for a congruence subgroup of SL_2(Z).
286
+
287
+ This class is an abstract base class, so only derived classes
288
+ should be instantiated.
289
+
290
+ INPUT:
291
+
292
+ - ``weight`` -- integer; the weight
293
+
294
+ - ``group`` -- arithgroup.congroup_generic.CongruenceSubgroup, a
295
+ congruence subgroup
296
+
297
+ - ``sign`` -- integer; either -1, 0, or 1
298
+
299
+ - ``base_ring`` -- commutative ring (defaults to the rational numbers)
300
+
301
+ EXAMPLES::
302
+
303
+ sage: B = ModularSymbols(Gamma0(11),2).boundary_space()
304
+ sage: isinstance(B, sage.modular.modsym.boundary.BoundarySpace)
305
+ True
306
+ sage: B == loads(dumps(B))
307
+ True
308
+ """
309
+ weight = int(weight)
310
+ if weight <= 1:
311
+ raise ArithmeticError("weight must be at least 2")
312
+ if not isinstance(group, arithgroup.CongruenceSubgroupBase):
313
+ raise TypeError("group must be a congruence subgroup")
314
+ sign = int(sign)
315
+ if base_ring not in Rings().Commutative():
316
+ raise TypeError("base_ring must be a commutative ring")
317
+ if character is None and isinstance(group, arithgroup.Gamma0_class):
318
+ character = dirichlet.TrivialCharacter(group.level(), base_ring)
319
+ (self.__group, self.__weight, self.__character,
320
+ self.__sign, self.__base_ring) = (group, weight,
321
+ character, sign, base_ring)
322
+ self._known_gens = []
323
+ self._zero_cusps = []
324
+ hecke.HeckeModule_generic.__init__(self, base_ring, group.level())
325
+
326
+ def __richcmp__(self, other, op):
327
+ """
328
+ EXAMPLES::
329
+
330
+ sage: B2 = ModularSymbols(11, 2).boundary_space()
331
+ sage: B4 = ModularSymbols(11, 4).boundary_space()
332
+ sage: B2 == B4
333
+ False
334
+ sage: B2 == ModularSymbols(17, 2).boundary_space()
335
+ False
336
+ """
337
+ if type(self) is not type(other):
338
+ return NotImplemented
339
+
340
+ return richcmp((self.group(), self.weight(), self.character()),
341
+ (other.group(), other.weight(), other.character()),
342
+ op)
343
+
344
+ def _known_cusps(self) -> list:
345
+ """
346
+ Return the list of non-vanishing cusps found so far.
347
+
348
+ EXAMPLES::
349
+
350
+ sage: B = ModularSymbols(Gamma1(12), 4).boundary_space()
351
+ sage: B._known_cusps()
352
+ []
353
+ sage: ls = [ B(Cusp(i,10)) for i in range(10) ]
354
+ sage: B._known_cusps()
355
+ [0, 1/10, 1/5]
356
+ """
357
+ return list(self._known_gens)
358
+
359
+ def is_ambient(self) -> bool:
360
+ """
361
+ Return ``True`` if ``self`` is a space of boundary symbols
362
+ associated to an ambient space of modular symbols.
363
+
364
+ EXAMPLES::
365
+
366
+ sage: M = ModularSymbols(Gamma1(6), 4)
367
+ sage: M.is_ambient()
368
+ True
369
+ sage: M.boundary_space().is_ambient()
370
+ True
371
+ """
372
+ return True
373
+
374
+ def group(self):
375
+ """
376
+ Return the congruence subgroup associated to this space of boundary
377
+ modular symbols.
378
+
379
+ EXAMPLES::
380
+
381
+ sage: ModularSymbols(GammaH(14,[9]), 2).boundary_space().group()
382
+ Congruence Subgroup Gamma_H(14) with H generated by [9]
383
+ """
384
+ return self.__group
385
+
386
+ def weight(self):
387
+ """
388
+ Return the weight of this space of boundary modular symbols.
389
+
390
+ EXAMPLES::
391
+
392
+ sage: ModularSymbols(Gamma1(9), 5).boundary_space().weight()
393
+ 5
394
+ """
395
+ return self.__weight
396
+
397
+ def character(self):
398
+ """
399
+ Return the Dirichlet character associated to this space of boundary
400
+ modular symbols.
401
+
402
+ EXAMPLES::
403
+
404
+ sage: ModularSymbols(DirichletGroup(7).0, 6).boundary_space().character()
405
+ Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6
406
+ """
407
+ return self.__character
408
+
409
+ def sign(self):
410
+ """
411
+ Return the sign of the complex conjugation involution on this space
412
+ of boundary modular symbols.
413
+
414
+ EXAMPLES::
415
+
416
+ sage: ModularSymbols(13,2,sign=-1).boundary_space().sign()
417
+ -1
418
+ """
419
+ return self.__sign
420
+
421
+ def gen(self, i=0):
422
+ """
423
+ Return the i-th generator of this space.
424
+
425
+ EXAMPLES::
426
+
427
+ sage: B = ModularSymbols(Gamma0(24), 4).boundary_space()
428
+ sage: B.gen(0)
429
+ Traceback (most recent call last):
430
+ ...
431
+ ValueError: only 0 generators known for
432
+ Space of Boundary Modular Symbols for
433
+ Congruence Subgroup Gamma0(24) of weight 4 over Rational Field
434
+ sage: B(Cusp(1/3))
435
+ [1/3]
436
+ sage: B.gen(0)
437
+ [1/3]
438
+ """
439
+ if i >= len(self._known_gens) or i < 0:
440
+ raise ValueError("only %s generators known for %s" % (len(self._known_gens), self))
441
+ return BoundarySpaceElement(self, {i: 1})
442
+
443
+ def free_module(self):
444
+ """
445
+ Return the underlying free module for ``self``.
446
+
447
+ EXAMPLES::
448
+
449
+ sage: B = ModularSymbols(Gamma1(7), 5, sign=-1).boundary_space()
450
+ sage: B.free_module()
451
+ Sparse vector space of dimension 0 over Rational Field
452
+ sage: x = B(Cusp(0)) ; y = B(Cusp(1/7)) ; B.free_module()
453
+ Sparse vector space of dimension 1 over Rational Field
454
+ """
455
+ return free_module.FreeModule(self.__base_ring, len(self._known_gens), sparse=True)
456
+
457
+ def rank(self):
458
+ """
459
+ The rank of the space generated by boundary symbols that have been
460
+ found so far in the course of computing the boundary map.
461
+
462
+ .. warning::
463
+
464
+ This number may change as more elements are coerced into
465
+ this space!! (This is an implementation detail that will
466
+ likely change.)
467
+
468
+ EXAMPLES::
469
+
470
+ sage: M = ModularSymbols(Gamma0(72), 2) ; B = M.boundary_space()
471
+ sage: B.rank()
472
+ 0
473
+ sage: _ = [ B(x) for x in M.basis() ]
474
+ sage: B.rank()
475
+ 16
476
+
477
+ Test that :issue:`7837` is fixed::
478
+
479
+ sage: ModularSymbols(Gamma1(4),7).boundary_map().codomain().dimension()
480
+ 2
481
+ sage: ModularSymbols(Gamma1(4),7, sign=1).boundary_map().codomain().dimension()
482
+ 1
483
+ sage: ModularSymbols(Gamma1(4),7, sign=-1).boundary_map().codomain().dimension()
484
+ 1
485
+ """
486
+ return len(self._known_gens)
487
+
488
+ #####################################################################
489
+ # Coercion
490
+ #####################################################################
491
+
492
+ def _coerce_in_manin_symbol(self, x):
493
+ """
494
+ Coerce the Manin symbol x into ``self``. (That is, return the image of
495
+ x under the boundary map.)
496
+
497
+ Assumes that x is associated to the same space of modular symbols
498
+ as ``self``.
499
+
500
+ EXAMPLES::
501
+
502
+ sage: M = ModularSymbols(Gamma1(5), 4) ; B = M.boundary_space()
503
+ sage: [ B(x) for x in M.basis() ]
504
+ [-[2/5], -[Infinity], -[1/3], -[-1/4], -[-1/4], -[-1/4]]
505
+ sage: [ B._coerce_in_manin_symbol(x) for x in M.manin_symbols_basis() ]
506
+ [-[2/5], -[Infinity], -[1/3], -[-1/4], -[-1/4], -[-1/4]]
507
+ """
508
+ i = x.i
509
+ alpha, beta = x.endpoints(self.level())
510
+ if self.weight() == 2:
511
+ return self(alpha) - self(beta)
512
+ if i == 0:
513
+ return self(alpha)
514
+ elif i == self.weight() - 2:
515
+ return -self(beta)
516
+ else:
517
+ return self(0)
518
+
519
+ def __call__(self, x):
520
+ """
521
+ Coerce x into a boundary symbol space.
522
+
523
+ If x is a modular symbol (with the same group, weight, character,
524
+ sign, and base field), this returns the image of that modular
525
+ symbol under the boundary map.
526
+
527
+ EXAMPLES::
528
+
529
+ sage: M = ModularSymbols(Gamma0(15), 2) ; B = M.boundary_space()
530
+ sage: B(M.0)
531
+ [Infinity] - [0]
532
+ sage: B(Cusp(1))
533
+ [0]
534
+ sage: B(Cusp(oo))
535
+ [Infinity]
536
+ sage: B(7)
537
+ Traceback (most recent call last):
538
+ ...
539
+ TypeError: Coercion of 7 (of type <class 'sage.rings.integer.Integer'>) into Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(15) of weight 2 over Rational Field not (yet) defined.
540
+ """
541
+ from .ambient import ModularSymbolsAmbient
542
+ if isinstance(x, int) and x == 0:
543
+ return BoundarySpaceElement(self, {})
544
+
545
+ elif isinstance(x, cusps.Cusp):
546
+ return self._coerce_cusp(x)
547
+
548
+ elif isinstance(x, ManinSymbol):
549
+ return self._coerce_in_manin_symbol(x)
550
+
551
+ elif isinstance(x, element.ModularSymbolsElement):
552
+ M = x.parent()
553
+ if not isinstance(M, ModularSymbolsAmbient):
554
+ raise TypeError("x (=%s) must be an element of a space of modular symbols of type ModularSymbolsAmbient" % x)
555
+ if M.level() != self.level():
556
+ raise TypeError("x (=%s) must have level %s but has level %s" % (
557
+ x, self.level(), M.level()))
558
+ S = x.manin_symbol_rep()
559
+ if len(S) == 0:
560
+ return self(0)
561
+ return sum([c * self._coerce_in_manin_symbol(v) for c, v in S])
562
+
563
+ elif isinstance(x, FreeModuleElement):
564
+ y = dict(enumerate(x))
565
+ return BoundarySpaceElement(self, y)
566
+
567
+ raise TypeError("Coercion of %s (of type %s) into %s not (yet) defined." % (x, type(x), self))
568
+
569
+ def _repr_(self):
570
+ """
571
+ Return the string representation of ``self``.
572
+
573
+ EXAMPLES::
574
+
575
+ sage: sage.modular.modsym.boundary.BoundarySpace(Gamma0(3), 2)._repr_()
576
+ 'Space of Boundary Modular Symbols of weight 2 for Congruence Subgroup Gamma0(3) with sign 0 and character [1] over Rational Field'
577
+ """
578
+ return ("Space of Boundary Modular Symbols of weight %s for" +
579
+ " %s with sign %s and character %s over %s") % (
580
+ self.weight(), self.group(), self.sign(),
581
+ self.character()._repr_short_(), self.base_ring())
582
+
583
+ def _cusp_index(self, cusp):
584
+ """
585
+ Return the index of the (unique) cusp in self._known_cusps()
586
+ equivalent to cusp, or one of the following special values:
587
+
588
+ - ``-1`` if ``cusp`` is not equivalent to any cusp
589
+ found so far.
590
+ - ``-2`` if ``cusp`` is equivalent to a cusp that's known to vanish
591
+ from the relations in this space.
592
+
593
+ EXAMPLES::
594
+
595
+ sage: B = ModularSymbols(Gamma0(21), 4).boundary_space()
596
+ sage: B._cusp_index(Cusp(0))
597
+ -1
598
+ sage: _ = B(Cusp(oo))
599
+ sage: _ = B(Cusp(0))
600
+ sage: B._cusp_index(Cusp(0))
601
+ 1
602
+ """
603
+ g = self._known_gens
604
+ for i in range(len(g)):
605
+ if self._is_equiv(cusp, g[i]):
606
+ return i
607
+ if any(self._is_equiv(cusp, x) for x in self._zero_cusps):
608
+ return -2
609
+ return -1
610
+
611
+
612
+ class BoundarySpace_wtk_g0(BoundarySpace):
613
+ def __init__(self, level, weight, sign, F):
614
+ """
615
+ Initialize a space of boundary symbols of weight k for Gamma_0(N)
616
+ over base field F.
617
+
618
+ INPUT:
619
+
620
+ - ``level`` -- integer; the level
621
+
622
+ - ``weight`` -- integer; weight = 2
623
+
624
+ - ``sign`` -- integer; either -1, 0, or 1
625
+
626
+ - ``F`` -- field
627
+
628
+ EXAMPLES::
629
+
630
+ sage: B = ModularSymbols(Gamma0(2), 5).boundary_space()
631
+ sage: type(B)
632
+ <class 'sage.modular.modsym.boundary.BoundarySpace_wtk_g0_with_category'>
633
+ sage: B == loads(dumps(B))
634
+ True
635
+ """
636
+ level = int(level)
637
+ sign = int(sign)
638
+ weight = int(weight)
639
+ if sign not in [-1, 0, 1]:
640
+ raise ArithmeticError("sign must be an int in [-1,0,1]")
641
+ if level <= 0:
642
+ raise ArithmeticError("level must be positive")
643
+ BoundarySpace.__init__(self,
644
+ weight=weight,
645
+ group=arithgroup.Gamma0(level),
646
+ sign=sign,
647
+ base_ring=F)
648
+
649
+ def _repr_(self):
650
+ """
651
+ Return the string representation of ``self``.
652
+
653
+ EXAMPLES::
654
+
655
+ sage: B = ModularSymbols(Gamma0(97), 3).boundary_space()
656
+ sage: B._repr_()
657
+ 'Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(97) of weight 3 over Rational Field'
658
+ """
659
+ return ("Space of Boundary Modular Symbols for %s of weight %s over %s"
660
+ % (self.group(), self.weight(), self.base_ring()))
661
+
662
+ def _coerce_cusp(self, c):
663
+ """
664
+ Coerce the cusp c into this boundary symbol space.
665
+
666
+ EXAMPLES::
667
+
668
+ sage: B = ModularSymbols(Gamma0(17), 6).boundary_space()
669
+ sage: B._coerce_cusp(Cusp(0))
670
+ [0]
671
+ sage: B = ModularSymbols(Gamma0(17), 6, sign=-1).boundary_space()
672
+ sage: B._coerce_cusp(Cusp(0))
673
+ 0
674
+ sage: B = ModularSymbols(Gamma0(16), 4).boundary_space()
675
+ sage: [ B(Cusp(i,4)) for i in range(4) ]
676
+ [[0], [1/4], [1/2], [3/4]]
677
+ sage: B = ModularSymbols(Gamma0(16), 4, sign=1).boundary_space()
678
+ sage: [ B(Cusp(i,4)) for i in range(4) ]
679
+ [[0], [1/4], [1/2], [1/4]]
680
+ sage: B = ModularSymbols(Gamma0(16), 4, sign=-1).boundary_space()
681
+ sage: [ B(Cusp(i,4)) for i in range(4) ]
682
+ [0, [1/4], 0, -[1/4]]
683
+ """
684
+ if self.weight() % 2:
685
+ return self(0)
686
+
687
+ # see if we've already found this cusp
688
+ i = self._cusp_index(c)
689
+ if i != -1:
690
+ if i == -2:
691
+ return self(0)
692
+ return BoundarySpaceElement(self, {i: 1})
693
+
694
+ # see if we've already found -c
695
+ sign = self.sign()
696
+ if sign != 0:
697
+ i2 = self._cusp_index(-c)
698
+ if i2 != -1:
699
+ if i2 == -2:
700
+ return self(0)
701
+ else:
702
+ return BoundarySpaceElement(self, {i2: sign})
703
+
704
+ # found a new cusp class
705
+ g = self._known_gens
706
+ g.append(c)
707
+
708
+ # See if the new cusp is killed by sign relations. The
709
+ # relevant relations (for cusps other than 0 and Infinity)
710
+ # are:
711
+ #
712
+ # [(u,v)] = (-1)^k [(-u,-v)]
713
+ # [(u,v)] = [gamma * (u,v)]
714
+ # [(-u,v)] = sign * [(u,v)]
715
+ #
716
+ # So since k is always even on Gamma0, we have that [(u,v)] =
717
+ # 0 from the above relations exactly when (u,v) = gamma*(-u,v)
718
+ # and the sign is -1.
719
+ if sign == -1:
720
+ # NOTE: this code looks wrong. One should do the
721
+ # following:
722
+ #
723
+ # - if c is 0, if the sign is -1, append & return 0
724
+ # - if c is Infinity, then if the sign
725
+ # is not equal to (-1)**self.weight(), then
726
+ # append & return 0
727
+ # - otherwise, if the sign is -1, and c is
728
+ # equivalent to -c, append & return 0.
729
+ #
730
+ # Interestingly, the code below does precisely that.
731
+ # (It's important to recall that for Gamma0, odd weight
732
+ # spaces are 0.)
733
+ if self._is_equiv(c, -c):
734
+ self._zero_cusps.append(c)
735
+ del self._known_gens[-1]
736
+ return self(0)
737
+
738
+ return BoundarySpaceElement(self, {(len(g) - 1): 1})
739
+
740
+ def _is_equiv(self, c1, c2):
741
+ """
742
+ Determine whether or not c1 and c2 are equivalent for ``self``.
743
+
744
+ EXAMPLES::
745
+
746
+ sage: B = ModularSymbols(Gamma0(24), 6).boundary_space()
747
+ sage: B._is_equiv(Cusp(0), Cusp(oo))
748
+ False
749
+ sage: B._is_equiv(Cusp(0), Cusp(1))
750
+ True
751
+ """
752
+ return c1.is_gamma0_equiv(c2, self.level())
753
+
754
+
755
+ class BoundarySpace_wtk_g1(BoundarySpace):
756
+ def __init__(self, level, weight, sign, F):
757
+ """
758
+ Initialize a space of boundary modular symbols for Gamma1(N).
759
+
760
+ INPUT:
761
+
762
+ - ``level`` -- integer; the level
763
+
764
+ - ``weight`` -- integer; the weight = 2
765
+
766
+ - ``sign`` -- integer; either -1, 0, or 1
767
+
768
+ - ``F`` -- base ring
769
+
770
+ EXAMPLES::
771
+
772
+ sage: from sage.modular.modsym.boundary import BoundarySpace_wtk_g1
773
+ sage: B = BoundarySpace_wtk_g1(17, 2, 0, QQ) ; B
774
+ Boundary Modular Symbols space for Gamma_1(17) of weight 2 over Rational Field
775
+ sage: B == loads(dumps(B))
776
+ True
777
+ """
778
+ level = int(level)
779
+ sign = int(sign)
780
+ if sign not in [-1, 0, 1]:
781
+ raise ArithmeticError("sign must be an int in [-1,0,1]")
782
+ if level <= 0:
783
+ raise ArithmeticError("level must be positive")
784
+
785
+ BoundarySpace.__init__(self,
786
+ weight=weight,
787
+ group=arithgroup.Gamma1(level),
788
+ sign=sign,
789
+ base_ring=F)
790
+
791
+ def _repr_(self):
792
+ """
793
+ Return the string representation of ``self``.
794
+
795
+ EXAMPLES::
796
+
797
+ sage: ModularSymbols(Gamma1(5), 3, sign=1).boundary_space()._repr_()
798
+ 'Boundary Modular Symbols space for Gamma_1(5) of weight 3 over Rational Field'
799
+ """
800
+ return ("Boundary Modular Symbols space for Gamma_1(%s) of weight %s " +
801
+ "over %s") % (self.level(), self.weight(), self.base_ring())
802
+
803
+ def _is_equiv(self, c1, c2):
804
+ """
805
+ Return whether c1 and c2 are equivalent cusps for ``self``.
806
+
807
+ EXAMPLES::
808
+
809
+ sage: B = ModularSymbols(Gamma1(10), 4).boundary_space()
810
+ sage: B._is_equiv(Cusp(0), Cusp(1/5))
811
+ (False, 0)
812
+ sage: B._is_equiv(Cusp(4/5), Cusp(1/5))
813
+ (True, -1)
814
+ sage: B._is_equiv(Cusp(-4/5), Cusp(1/5))
815
+ (True, 1)
816
+ """
817
+ return c1.is_gamma1_equiv(c2, self.level())
818
+
819
+ def _cusp_index(self, cusp):
820
+ """
821
+ Return a pair (i, t), where i is the index of the first cusp in
822
+ self._known_cusps() which is equivalent to cusp, and t is 1 or -1
823
+ as cusp is Gamma1-equivalent to plus or minus
824
+ self._known_cusps()[i]. If cusp is not equivalent to any known
825
+ cusp, return (-1, 0); if cusp is equivalent to a cusp that is known to
826
+ vanish, return (-2, 0).
827
+
828
+ EXAMPLES::
829
+
830
+ sage: B = ModularSymbols(Gamma1(11),2).boundary_space()
831
+ sage: B._cusp_index(Cusp(1/11))
832
+ (-1, 0)
833
+ sage: B._cusp_index(Cusp(10/11))
834
+ (-1, 0)
835
+ sage: B._coerce_cusp(Cusp(1/11))
836
+ [1/11]
837
+ sage: B._cusp_index(Cusp(1/11))
838
+ (0, 1)
839
+ sage: B._cusp_index(Cusp(10/11))
840
+ (0, -1)
841
+ """
842
+ g = self._known_gens
843
+ for i in range(len(g)):
844
+ t, eps = self._is_equiv(cusp, g[i])
845
+ if t:
846
+ return i, eps
847
+ if any(self._is_equiv(cusp, c)[0] for c in self._zero_cusps):
848
+ return (-2, 0)
849
+ return -1, 0
850
+
851
+ def _coerce_cusp(self, c):
852
+ """
853
+ Coerce a cusp into this boundary symbol space.
854
+
855
+ EXAMPLES::
856
+
857
+ sage: B = ModularSymbols(Gamma1(4), 4).boundary_space()
858
+ sage: B._coerce_cusp(Cusp(1/2))
859
+ [1/2]
860
+ sage: B._coerce_cusp(Cusp(1/4))
861
+ [1/4]
862
+ sage: B._coerce_cusp(Cusp(3/4))
863
+ [1/4]
864
+ sage: B = ModularSymbols(Gamma1(5), 3, sign=-1).boundary_space()
865
+ sage: B._coerce_cusp(Cusp(0))
866
+ 0
867
+ sage: B._coerce_cusp(Cusp(oo))
868
+ [Infinity]
869
+ sage: B = ModularSymbols(Gamma1(2), 3, sign=-1).boundary_space()
870
+ sage: B._coerce_cusp(Cusp(0))
871
+ 0
872
+ sage: B._coerce_cusp(Cusp(oo))
873
+ 0
874
+ sage: B = ModularSymbols(Gamma1(7), 3).boundary_space()
875
+ sage: [ B(Cusp(i,7)) for i in range(7) ]
876
+ [[0], [1/7], [2/7], [3/7], -[3/7], -[2/7], -[1/7]]
877
+ sage: B._is_equiv(Cusp(1,6), Cusp(5,6))
878
+ (True, 1)
879
+ sage: B._is_equiv(Cusp(1,6), Cusp(0))
880
+ (True, -1)
881
+ sage: B(Cusp(0))
882
+ [0]
883
+ sage: B = ModularSymbols(Gamma1(7), 3, sign=1).boundary_space()
884
+ sage: [ B(Cusp(i,7)) for i in range(7) ]
885
+ [[0], 0, 0, 0, 0, 0, 0]
886
+ sage: B = ModularSymbols(Gamma1(7), 3, sign=-1).boundary_space()
887
+ sage: [ B(Cusp(i,7)) for i in range(7) ]
888
+ [0, [1/7], [2/7], [3/7], -[3/7], -[2/7], -[1/7]]
889
+ """
890
+ N = self.level()
891
+ k = self.weight()
892
+ sign = self.sign()
893
+ i, eps = self._cusp_index(c)
894
+ if i != -1:
895
+ if i == -2:
896
+ return self(0)
897
+ else:
898
+ return BoundarySpaceElement(self, {i: eps**k})
899
+
900
+ if sign != 0:
901
+ i2, eps = self._cusp_index(-c)
902
+ if i2 != -1:
903
+ if i2 == -2:
904
+ return self(0)
905
+ else:
906
+ return BoundarySpaceElement(self, {i2: sign * (eps**k)})
907
+
908
+ # found a new cusp class
909
+ g = self._known_gens
910
+ g.append(c)
911
+
912
+ # Does cusp class vanish because of irregularity? For Gamma1 groups
913
+ # this occurs if and only if N = 4 and c is equivalent to 1/2.
914
+
915
+ if N == 4 and k % 2:
916
+ if self._is_equiv(c, (1, 2))[0]:
917
+ self._zero_cusps.append(c)
918
+ del self._known_gens[-1]
919
+ return self(0)
920
+
921
+ # Does class vanish because of sign relations? The relevant
922
+ # relations are
923
+ #
924
+ # [(u,v)] = (-1)^k [(-u,-v)]
925
+ # [(u,v)] = sign * [(-u,v)]
926
+ # [(u,v)] = eps * (-1)^k [(-u,v)]
927
+ #
928
+ # where, in the last line, (u,v) is Gamma1-equivalent to
929
+ # (-u,v) or (u,-v) as eps is 1 or -1.
930
+ #
931
+ # Thus (other than for 0 and Infinity), we have that [(u,v)]
932
+ # can only be killed by sign relations when:
933
+ #
934
+ # - (u,v) is Gamma1-equivalent to (-u,v) or (u,-v), and
935
+ # - eps is 1 and sign is -1, or eps is -1 and sign is not
936
+ # (-1)^k.
937
+ #
938
+ if sign:
939
+ if (c.is_infinity() and sign != (-1)**self.weight()) or \
940
+ (c.is_zero() and sign == -1):
941
+ self._zero_cusps.append(c)
942
+ del self._known_gens[-1]
943
+ return self(0)
944
+ elif (not c.is_infinity() and not c.is_zero()):
945
+ t, eps = self._is_equiv(c, -c)
946
+ if t and ((eps == 1 and sign == -1) or
947
+ (eps == -1 and sign != (-1)**self.weight())):
948
+ self._zero_cusps.append(c)
949
+ del self._known_gens[-1]
950
+ return self(0)
951
+
952
+ return BoundarySpaceElement(self, {(len(g) - 1): 1})
953
+
954
+
955
+ class BoundarySpace_wtk_gamma_h(BoundarySpace):
956
+ def __init__(self, group, weight, sign, F):
957
+ """
958
+ Initialize a space of boundary modular symbols for GammaH(N).
959
+
960
+ INPUT:
961
+
962
+ - ``group`` -- congruence subgroup Gamma_H(N)
963
+
964
+ - ``weight`` -- integer; the weight = 2
965
+
966
+ - ``sign`` -- integer; either -1, 0, or 1
967
+
968
+ - ``F`` -- base ring
969
+
970
+ EXAMPLES::
971
+
972
+ sage: from sage.modular.modsym.boundary import BoundarySpace_wtk_gamma_h
973
+ sage: B = BoundarySpace_wtk_gamma_h(GammaH(13,[3]), 2, 0, QQ) ; B
974
+ Boundary Modular Symbols space for Congruence Subgroup Gamma_H(13) with H generated by [3] of weight 2 over Rational Field
975
+ sage: B == loads(dumps(B))
976
+ True
977
+
978
+ A test case from :issue:`6072`::
979
+
980
+ sage: ModularSymbols(GammaH(8,[5]), 3).boundary_map()
981
+ Hecke module morphism boundary map defined by the matrix
982
+ [-1 0 0 0]
983
+ [ 0 -1 0 0]
984
+ [ 0 0 -1 0]
985
+ [ 0 0 0 -1]
986
+ Domain: Modular Symbols space of dimension 4 for Congruence Subgroup ...
987
+ Codomain: Boundary Modular Symbols space for Congruence Subgroup Gamma_H(8) ...
988
+ """
989
+ sign = int(sign)
990
+ if sign not in [-1, 0, 1]:
991
+ raise ArithmeticError("sign must be an int in [-1,0,1]")
992
+
993
+ BoundarySpace.__init__(self,
994
+ weight=weight,
995
+ group=group,
996
+ sign=sign,
997
+ base_ring=F)
998
+
999
+ def _repr_(self):
1000
+ """
1001
+ Return the string representation of ``self``.
1002
+
1003
+ EXAMPLES::
1004
+
1005
+ sage: ModularSymbols(GammaH(7,[2]), 4).boundary_space()._repr_()
1006
+ 'Boundary Modular Symbols space for Congruence Subgroup Gamma_H(7) with H generated by [2] of weight 4 over Rational Field'
1007
+ """
1008
+ return ("Boundary Modular Symbols space for %s of weight %s " +
1009
+ "over %s") % (self.group(), self.weight(), self.base_ring())
1010
+
1011
+ def _is_equiv(self, c1, c2):
1012
+ """
1013
+ Return a pair of the form (b, t), where b is ``True`` if c1 and c2 are
1014
+ equivalent cusps for ``self``, and ``False`` otherwise, and t gives extra
1015
+ information about the equivalence between c1 and c2.
1016
+
1017
+ EXAMPLES::
1018
+
1019
+ sage: B = ModularSymbols(GammaH(7,[2]), 4).boundary_space()
1020
+ sage: B._is_equiv(Cusp(0), Cusp(1/7))
1021
+ (False, 0)
1022
+ sage: B._is_equiv(Cusp(2/7), Cusp(1/7))
1023
+ (True, 1)
1024
+ sage: B._is_equiv(Cusp(3/7), Cusp(1/7))
1025
+ (True, -1)
1026
+ """
1027
+ return c1.is_gamma_h_equiv(c2, self.group())
1028
+
1029
+ def _cusp_index(self, cusp):
1030
+ """
1031
+ Return a pair (i, t), where i is the index of the first cusp in
1032
+ self._known_cusps() which is equivalent to cusp, and t is 1 or -1 as
1033
+ cusp is GammaH-equivalent to plus or minus self._known_cusps()[i]. If
1034
+ cusp is not equivalent to any known cusp, return (-1, 0); if cusp is
1035
+ equivalent to a cusp known to vanish, return (-2, 0).
1036
+
1037
+ EXAMPLES::
1038
+
1039
+ sage: M = ModularSymbols(GammaH(9,[4]), 3)
1040
+ sage: B = M.boundary_space()
1041
+ sage: B._cusp_index(Cusp(0))
1042
+ (-1, 0)
1043
+ sage: _ = [ B(x) for x in M.basis() ]
1044
+ sage: B._cusp_index(Cusp(0))
1045
+ (1, -1)
1046
+ sage: B._cusp_index(Cusp(5/6))
1047
+ (3, 1)
1048
+ """
1049
+ g = self._known_gens
1050
+ for i in range(len(g)):
1051
+ t, eps = self._is_equiv(cusp, g[i])
1052
+ if t:
1053
+ return i, eps
1054
+ if any(self._is_equiv(cusp, c)[0] for c in self._zero_cusps):
1055
+ return -2, 0
1056
+ return -1, 0
1057
+
1058
+ def _coerce_cusp(self, c):
1059
+ """
1060
+ Coerce the cusp c into ``self``.
1061
+
1062
+ EXAMPLES::
1063
+
1064
+ sage: B = ModularSymbols(GammaH(10,[9]), 2).boundary_space()
1065
+ sage: B(Cusp(0))
1066
+ [0]
1067
+ sage: B(Cusp(1/3))
1068
+ [1/3]
1069
+ sage: B(Cusp(1/13))
1070
+ [1/3]
1071
+ sage: B = ModularSymbols(GammaH(25, [6]), 2).boundary_space()
1072
+ sage: B._coerce_cusp(Cusp(0))
1073
+ [0]
1074
+
1075
+ ::
1076
+
1077
+ sage: B = ModularSymbols(GammaH(11,[3]), 3).boundary_space()
1078
+ sage: [ B(Cusp(i,11)) for i in range(11) ]
1079
+ [[0],
1080
+ [1/11],
1081
+ -[1/11],
1082
+ [1/11],
1083
+ [1/11],
1084
+ [1/11],
1085
+ -[1/11],
1086
+ -[1/11],
1087
+ -[1/11],
1088
+ [1/11],
1089
+ -[1/11]]
1090
+ sage: B._is_equiv(Cusp(0), Cusp(1,11))
1091
+ (False, 0)
1092
+ sage: B._is_equiv(Cusp(oo), Cusp(1,11))
1093
+ (True, 1)
1094
+ sage: B = ModularSymbols(GammaH(11,[3]), 3, sign=1).boundary_space()
1095
+ sage: [ B(Cusp(i,11)) for i in range(11) ]
1096
+ [[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1097
+ sage: B = ModularSymbols(GammaH(11,[3]), 3, sign=-1).boundary_space()
1098
+ sage: [ B(Cusp(i,11)) for i in range(11) ]
1099
+ [0,
1100
+ [1/11],
1101
+ -[1/11],
1102
+ [1/11],
1103
+ [1/11],
1104
+ [1/11],
1105
+ -[1/11],
1106
+ -[1/11],
1107
+ -[1/11],
1108
+ [1/11],
1109
+ -[1/11]]
1110
+
1111
+ Test that :issue:`6072` is fixed. ::
1112
+
1113
+ sage: G = GammaH(8,[3])
1114
+
1115
+ sage: B2 = G.modular_symbols(weight=2).boundary_space()
1116
+ sage: B2._coerce_cusp(Cusp(1/4))
1117
+ [1/4]
1118
+
1119
+ sage: B3 = G.modular_symbols(weight=3).boundary_space()
1120
+ sage: B3._coerce_cusp(Cusp(1/4))
1121
+ 0
1122
+
1123
+ sage: G = GammaH(10, [9])
1124
+ sage: B3 = G.modular_symbols(weight=3).boundary_space()
1125
+ sage: [B3(x) for x in G.cusps()]
1126
+ [0, 0, 0, 0, 0, 0, 0, 0]
1127
+ sage: B3.rank()
1128
+ 0
1129
+
1130
+ Test that :issue:`25268` is fixed::
1131
+
1132
+ sage: G = GammaH(20, [13])
1133
+ sage: A = ModularSymbols(G, 3)
1134
+ sage: S = A.cuspidal_submodule()
1135
+ sage: S.dimension()
1136
+ 8
1137
+ """
1138
+ k = self.weight()
1139
+ sign = self.sign()
1140
+ i, eps = self._cusp_index(c)
1141
+ if i != -1:
1142
+ if i == -2:
1143
+ return self(0)
1144
+ else:
1145
+ return BoundarySpaceElement(self, {i: eps**k})
1146
+
1147
+ if sign != 0:
1148
+ i2, eps = self._cusp_index(-c)
1149
+ if i2 != -1:
1150
+ if i2 == -2:
1151
+ return self(0)
1152
+ else:
1153
+ return BoundarySpaceElement(self, {i2: sign * (eps**k)})
1154
+
1155
+ # found a new cusp class
1156
+ g = self._known_gens
1157
+ g.append(c)
1158
+
1159
+ # Does the cusp class vanish because the cusp is irregular?
1160
+
1161
+ if k % 2:
1162
+ if self.group().is_even() or not self.group().is_regular_cusp(c):
1163
+ self._zero_cusps.append(c)
1164
+ del self._known_gens[-1]
1165
+ return self(0)
1166
+
1167
+ # Does class vanish because of sign relations? The relevant
1168
+ # relations are
1169
+ #
1170
+ # [(u,v)] = (-1)^k [(-u,-v)]
1171
+ # [(u,v)] = sign * [(-u,v)]
1172
+ # [(u,v)] = eps * (-1)^k [(-u,v)]
1173
+ #
1174
+ # where, in the last line, (u,v) is GammaH-equivalent to
1175
+ # (-u,v) or (u,-v) as eps is 1 or -1.
1176
+ #
1177
+ # Thus (other than for 0 and Infinity), we have that [(u,v)]
1178
+ # can only be killed by sign relations when:
1179
+ #
1180
+ # - (u,v) is GammaH-equivalent to (-u,v) or (u,-v), and
1181
+ # - eps is 1 and sign is -1, or eps is -1 and sign is not
1182
+ # (-1)^k.
1183
+ #
1184
+ # (Notice that while this description looks identical to that
1185
+ # of Gamma1, it differs in that the condition of being GammaH
1186
+ # equivalent is weaker than that of being Gamma1 equivalent
1187
+ # when H is larger than {1}.)
1188
+ #
1189
+ if sign:
1190
+ if (c.is_infinity() and sign != (-1)**self.weight()) or \
1191
+ (c.is_zero() and sign == -1):
1192
+ self._zero_cusps.append(c)
1193
+ del self._known_gens[-1]
1194
+ return self(0)
1195
+ elif (not c.is_infinity() and not c.is_zero()):
1196
+ t, eps = self._is_equiv(c, -c)
1197
+ if t and ((eps == 1 and sign == -1) or
1198
+ (eps == -1 and sign != (-1)**self.weight())):
1199
+ self._zero_cusps.append(c)
1200
+ del self._known_gens[-1]
1201
+ return self(0)
1202
+
1203
+ return BoundarySpaceElement(self, {(len(g) - 1): 1})
1204
+
1205
+
1206
+ class BoundarySpace_wtk_eps(BoundarySpace):
1207
+ def __init__(self, eps, weight, sign=0):
1208
+ """
1209
+ Space of boundary modular symbols with given weight, character, and
1210
+ sign.
1211
+
1212
+ INPUT:
1213
+
1214
+ - ``eps`` -- dirichlet.DirichletCharacter, the
1215
+ "Nebentypus" character
1216
+
1217
+ - ``weight`` -- integer; the weight = 2
1218
+
1219
+ - ``sign`` -- integer; either -1, 0, or 1
1220
+
1221
+ EXAMPLES::
1222
+
1223
+ sage: B = ModularSymbols(DirichletGroup(6).0, 4).boundary_space() ; B
1224
+ Boundary Modular Symbols space of level 6, weight 4, character [-1] and dimension 0 over Rational Field
1225
+ sage: type(B)
1226
+ <class 'sage.modular.modsym.boundary.BoundarySpace_wtk_eps_with_category'>
1227
+ sage: B == loads(dumps(B))
1228
+ True
1229
+ """
1230
+ level = eps.modulus()
1231
+ sign = int(sign)
1232
+ self.__eps = eps
1233
+ if sign not in [-1, 0, 1]:
1234
+ raise ArithmeticError("sign must be an int in [-1,0,1]")
1235
+ if level <= 0:
1236
+ raise ArithmeticError("level must be positive")
1237
+ BoundarySpace.__init__(self,
1238
+ weight=weight,
1239
+ group=arithgroup.Gamma1(level),
1240
+ sign=sign,
1241
+ base_ring=eps.base_ring(),
1242
+ character=eps)
1243
+
1244
+ def _repr_(self):
1245
+ """
1246
+ Return the string representation of ``self``.
1247
+
1248
+ EXAMPLES::
1249
+
1250
+ sage: ModularSymbols(DirichletGroup(6).0, 4).boundary_space()._repr_()
1251
+ 'Boundary Modular Symbols space of level 6, weight 4, character [-1] and dimension 0 over Rational Field'
1252
+ """
1253
+ return ("Boundary Modular Symbols space of level %s, weight %s, character %s " +
1254
+ "and dimension %s over %s") % (self.level(), self.weight(),
1255
+ self.character()._repr_short_(),
1256
+ self.rank(),
1257
+ self.base_ring())
1258
+
1259
+ def _is_equiv(self, c1, c2):
1260
+ """
1261
+ Return a pair (b, t), where b is ``True`` if c1 and c2 are equivalent
1262
+ cusps for ``self``, and ``False`` otherwise, and t gives extra
1263
+ information about the equivalence of c1 and c2.
1264
+
1265
+ EXAMPLES::
1266
+
1267
+ sage: B = ModularSymbols(DirichletGroup(12).1, 3).boundary_space()
1268
+ sage: B._is_equiv(Cusp(0), Cusp(1/3))
1269
+ (False, None)
1270
+ sage: B._is_equiv(Cusp(2/3), Cusp(1/3))
1271
+ (True, 5)
1272
+ sage: B._is_equiv(Cusp(3/4), Cusp(1/4))
1273
+ (True, 7)
1274
+ """
1275
+ return c1.is_gamma0_equiv(c2, self.level(), transformation=True)
1276
+
1277
+ def _cusp_index(self, cusp):
1278
+ """
1279
+ Return a pair (i, s), where i is the index of the first cusp in
1280
+ self._known_cusps() which is equivalent to cusp, and such that cusp is
1281
+ Gamma0-equivalent to self.character()(s) times self._known_cusps()[i].
1282
+ If cusp is not equivalent to any known cusp, return (-1, 0); if cusp is
1283
+ equivalent to a cusp known to vanish, return (-2, 0).
1284
+
1285
+ EXAMPLES::
1286
+
1287
+ sage: B = ModularSymbols(DirichletGroup(11).0**3, 5).boundary_space()
1288
+ sage: B._cusp_index(Cusp(0))
1289
+ (-1, 0)
1290
+ sage: B._coerce_cusp(Cusp(0))
1291
+ [0]
1292
+ sage: B._cusp_index(Cusp(0))
1293
+ (0, 1)
1294
+ sage: B._coerce_cusp(Cusp(1,11))
1295
+ [1/11]
1296
+ sage: B._cusp_index(Cusp(2,11))
1297
+ (1, -zeta10^2)
1298
+ """
1299
+ g = self._known_gens
1300
+ for i in range(len(g)):
1301
+ t, s = self._is_equiv(cusp, g[i])
1302
+ if t:
1303
+ return i, self.__eps(s)
1304
+ if any(self._is_equiv(cusp, c)[0] for c in self._zero_cusps):
1305
+ return (-2, 0)
1306
+ return -1, 0
1307
+
1308
+ def _coerce_cusp(self, c):
1309
+ """
1310
+ Coerce the cusp c into ``self``.
1311
+
1312
+ EXAMPLES::
1313
+
1314
+ sage: B = ModularSymbols(DirichletGroup(13).0**3, 5, sign=0).boundary_space()
1315
+ sage: [ B(Cusp(i,13)) for i in range(13) ]
1316
+ [[0],
1317
+ [1/13],
1318
+ -zeta4*[1/13],
1319
+ [1/13],
1320
+ -[1/13],
1321
+ -zeta4*[1/13],
1322
+ -zeta4*[1/13],
1323
+ zeta4*[1/13],
1324
+ zeta4*[1/13],
1325
+ [1/13],
1326
+ -[1/13],
1327
+ zeta4*[1/13],
1328
+ -[1/13]]
1329
+ sage: B._is_equiv(Cusp(oo), Cusp(1,13))
1330
+ (True, 1)
1331
+ sage: B._is_equiv(Cusp(0), Cusp(1,13))
1332
+ (False, None)
1333
+ sage: B = ModularSymbols(DirichletGroup(13).0**3, 5, sign=1).boundary_space()
1334
+ sage: [ B(Cusp(i,13)) for i in range(13) ]
1335
+ [[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1336
+ sage: B._coerce_cusp(Cusp(oo))
1337
+ 0
1338
+ sage: B = ModularSymbols(DirichletGroup(13).0**3, 5, sign=-1).boundary_space()
1339
+ sage: [ B(Cusp(i,13)) for i in range(13) ]
1340
+ [0,
1341
+ [1/13],
1342
+ -zeta4*[1/13],
1343
+ [1/13],
1344
+ -[1/13],
1345
+ -zeta4*[1/13],
1346
+ -zeta4*[1/13],
1347
+ zeta4*[1/13],
1348
+ zeta4*[1/13],
1349
+ [1/13],
1350
+ -[1/13],
1351
+ zeta4*[1/13],
1352
+ -[1/13]]
1353
+ sage: B = ModularSymbols(DirichletGroup(13).0**4, 5, sign=1).boundary_space()
1354
+ sage: B._coerce_cusp(Cusp(0))
1355
+ [0]
1356
+ sage: B = ModularSymbols(DirichletGroup(13).0**4, 5, sign=-1).boundary_space()
1357
+ sage: B._coerce_cusp(Cusp(0))
1358
+ 0
1359
+ """
1360
+ sign = self.sign()
1361
+ i, eps = self._cusp_index(c)
1362
+ if i != -1:
1363
+ if i == -2:
1364
+ return self(0)
1365
+ else:
1366
+ return BoundarySpaceElement(self, {i: eps})
1367
+
1368
+ if sign != 0:
1369
+ i2, eps = self._cusp_index(-c)
1370
+ if i2 != -1:
1371
+ if i2 == -2:
1372
+ return self(0)
1373
+ else:
1374
+ return BoundarySpaceElement(self, {i2: sign * eps})
1375
+
1376
+ # found a new cusp class
1377
+ g = self._known_gens
1378
+ g.append(c)
1379
+
1380
+ # Does cusp vanish because of stabiliser?
1381
+ s = arithgroup.Gamma0(self.level()).cusp_data(c)[0]
1382
+ if self.__eps(s[1, 1]) != 1:
1383
+ self._zero_cusps.append(c)
1384
+ del self._known_gens[-1]
1385
+ return self(0)
1386
+
1387
+ # Does class vanish because of sign relations? The relevant
1388
+ # relations are
1389
+ #
1390
+ # [(u,v)] = (-1)^k [(-u,-v)]
1391
+ # [(u,v)] = sign * [(-u,v)]
1392
+ # [(u,v)] = eps(d) * [(-u,v)]
1393
+ #
1394
+ # where, in the last line, eps is the character defining
1395
+ # our space, and [a,b;c,d] takes (u,v) to (-u,v).
1396
+ #
1397
+ # Thus (other than for 0 and Infinity), we have that [(u,v)]
1398
+ # can only be killed by sign relations when the sign is not
1399
+ # equal to eps(d).
1400
+ #
1401
+ if sign:
1402
+ if c.is_zero():
1403
+ if sign == -1:
1404
+ self._zero_cusps.append(c)
1405
+ del self._known_gens[-1]
1406
+ return self(0)
1407
+ elif c.is_infinity():
1408
+ if sign != (-1)**self.weight():
1409
+ self._zero_cusps.append(c)
1410
+ del self._known_gens[-1]
1411
+ return self(0)
1412
+ else:
1413
+ t, s = self._is_equiv(c, -c)
1414
+ if t:
1415
+ if sign != self.__eps(s):
1416
+ self._zero_cusps.append(c)
1417
+ del self._known_gens[-1]
1418
+ return self(0)
1419
+
1420
+ return BoundarySpaceElement(self, {(len(g) - 1): 1})