passagemath-schemes 10.8.1a4__cp314-cp314t-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
- passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
- passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
- passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
- passagemath_schemes/__init__.py +3 -0
- passagemath_schemes-10.8.1a4.dist-info/METADATA +203 -0
- passagemath_schemes-10.8.1a4.dist-info/METADATA.bak +204 -0
- passagemath_schemes-10.8.1a4.dist-info/RECORD +312 -0
- passagemath_schemes-10.8.1a4.dist-info/WHEEL +6 -0
- passagemath_schemes-10.8.1a4.dist-info/top_level.txt +3 -0
- sage/all__sagemath_schemes.py +23 -0
- sage/databases/all__sagemath_schemes.py +7 -0
- sage/databases/cremona.py +1723 -0
- sage/dynamics/all__sagemath_schemes.py +2 -0
- sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
- sage/dynamics/arithmetic_dynamics/all.py +14 -0
- sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
- sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
- sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
- sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
- sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
- sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
- sage/dynamics/arithmetic_dynamics/projective_ds.py +9556 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
- sage/dynamics/arithmetic_dynamics/wehlerK3.py +2578 -0
- sage/lfunctions/all.py +18 -0
- sage/lfunctions/dokchitser.py +727 -0
- sage/lfunctions/pari.py +971 -0
- sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
- sage/lfunctions/zero_sums.pyx +1847 -0
- sage/modular/abvar/abvar.py +5132 -0
- sage/modular/abvar/abvar_ambient_jacobian.py +414 -0
- sage/modular/abvar/abvar_newform.py +246 -0
- sage/modular/abvar/all.py +8 -0
- sage/modular/abvar/constructor.py +187 -0
- sage/modular/abvar/cuspidal_subgroup.py +371 -0
- sage/modular/abvar/finite_subgroup.py +896 -0
- sage/modular/abvar/homology.py +721 -0
- sage/modular/abvar/homspace.py +989 -0
- sage/modular/abvar/lseries.py +415 -0
- sage/modular/abvar/morphism.py +935 -0
- sage/modular/abvar/torsion_point.py +274 -0
- sage/modular/abvar/torsion_subgroup.py +741 -0
- sage/modular/all.py +43 -0
- sage/modular/arithgroup/all.py +20 -0
- sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
- sage/modular/arithgroup/arithgroup_element.pyx +474 -0
- sage/modular/arithgroup/arithgroup_generic.py +1406 -0
- sage/modular/arithgroup/arithgroup_perm.py +2692 -0
- sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
- sage/modular/arithgroup/congroup.pyx +334 -0
- sage/modular/arithgroup/congroup_gamma.py +361 -0
- sage/modular/arithgroup/congroup_gamma0.py +692 -0
- sage/modular/arithgroup/congroup_gamma1.py +659 -0
- sage/modular/arithgroup/congroup_gammaH.py +1491 -0
- sage/modular/arithgroup/congroup_generic.py +630 -0
- sage/modular/arithgroup/congroup_sl2z.py +266 -0
- sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
- sage/modular/arithgroup/farey_symbol.pyx +1067 -0
- sage/modular/arithgroup/tests.py +425 -0
- sage/modular/btquotients/all.py +4 -0
- sage/modular/btquotients/btquotient.py +3736 -0
- sage/modular/btquotients/pautomorphicform.py +2564 -0
- sage/modular/buzzard.py +100 -0
- sage/modular/congroup.py +29 -0
- sage/modular/congroup_element.py +13 -0
- sage/modular/cusps.py +1107 -0
- sage/modular/cusps_nf.py +1270 -0
- sage/modular/dims.py +571 -0
- sage/modular/dirichlet.py +3310 -0
- sage/modular/drinfeld_modform/all.py +2 -0
- sage/modular/drinfeld_modform/element.py +446 -0
- sage/modular/drinfeld_modform/ring.py +773 -0
- sage/modular/drinfeld_modform/tutorial.py +236 -0
- sage/modular/etaproducts.py +1076 -0
- sage/modular/hecke/algebra.py +725 -0
- sage/modular/hecke/all.py +19 -0
- sage/modular/hecke/ambient_module.py +994 -0
- sage/modular/hecke/degenmap.py +119 -0
- sage/modular/hecke/element.py +302 -0
- sage/modular/hecke/hecke_operator.py +736 -0
- sage/modular/hecke/homspace.py +185 -0
- sage/modular/hecke/module.py +1744 -0
- sage/modular/hecke/morphism.py +139 -0
- sage/modular/hecke/submodule.py +970 -0
- sage/modular/hypergeometric_misc.cpython-314t-darwin.so +0 -0
- sage/modular/hypergeometric_misc.pxd +4 -0
- sage/modular/hypergeometric_misc.pyx +166 -0
- sage/modular/hypergeometric_motive.py +2020 -0
- sage/modular/local_comp/all.py +2 -0
- sage/modular/local_comp/liftings.py +292 -0
- sage/modular/local_comp/local_comp.py +1070 -0
- sage/modular/local_comp/smoothchar.py +1825 -0
- sage/modular/local_comp/type_space.py +748 -0
- sage/modular/modform/all.py +30 -0
- sage/modular/modform/ambient.py +817 -0
- sage/modular/modform/ambient_R.py +177 -0
- sage/modular/modform/ambient_eps.py +306 -0
- sage/modular/modform/ambient_g0.py +120 -0
- sage/modular/modform/ambient_g1.py +199 -0
- sage/modular/modform/constructor.py +545 -0
- sage/modular/modform/cuspidal_submodule.py +708 -0
- sage/modular/modform/defaults.py +14 -0
- sage/modular/modform/eis_series.py +487 -0
- sage/modular/modform/eisenstein_submodule.py +663 -0
- sage/modular/modform/element.py +4105 -0
- sage/modular/modform/half_integral.py +154 -0
- sage/modular/modform/hecke_operator_on_qexp.py +247 -0
- sage/modular/modform/j_invariant.py +47 -0
- sage/modular/modform/l_series_gross_zagier.py +127 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314t-darwin.so +0 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
- sage/modular/modform/notes.py +45 -0
- sage/modular/modform/numerical.py +514 -0
- sage/modular/modform/periods.py +14 -0
- sage/modular/modform/ring.py +1257 -0
- sage/modular/modform/space.py +1859 -0
- sage/modular/modform/submodule.py +118 -0
- sage/modular/modform/tests.py +64 -0
- sage/modular/modform/theta.py +110 -0
- sage/modular/modform/vm_basis.py +380 -0
- sage/modular/modform/weight1.py +221 -0
- sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
- sage/modular/modform_hecketriangle/abstract_space.py +2527 -0
- sage/modular/modform_hecketriangle/all.py +30 -0
- sage/modular/modform_hecketriangle/analytic_type.py +590 -0
- sage/modular/modform_hecketriangle/constructor.py +416 -0
- sage/modular/modform_hecketriangle/element.py +351 -0
- sage/modular/modform_hecketriangle/functors.py +752 -0
- sage/modular/modform_hecketriangle/graded_ring.py +541 -0
- sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
- sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3349 -0
- sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1426 -0
- sage/modular/modform_hecketriangle/readme.py +1214 -0
- sage/modular/modform_hecketriangle/series_constructor.py +580 -0
- sage/modular/modform_hecketriangle/space.py +1037 -0
- sage/modular/modform_hecketriangle/subspace.py +423 -0
- sage/modular/modsym/all.py +17 -0
- sage/modular/modsym/ambient.py +3844 -0
- sage/modular/modsym/boundary.py +1420 -0
- sage/modular/modsym/element.py +336 -0
- sage/modular/modsym/g1list.py +178 -0
- sage/modular/modsym/ghlist.py +182 -0
- sage/modular/modsym/hecke_operator.py +73 -0
- sage/modular/modsym/manin_symbol.cpython-314t-darwin.so +0 -0
- sage/modular/modsym/manin_symbol.pxd +5 -0
- sage/modular/modsym/manin_symbol.pyx +497 -0
- sage/modular/modsym/manin_symbol_list.py +1291 -0
- sage/modular/modsym/modsym.py +400 -0
- sage/modular/modsym/modular_symbols.py +384 -0
- sage/modular/modsym/p1list_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-314t-darwin.so +0 -0
- sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
- sage/modular/modsym/space.py +2468 -0
- sage/modular/modsym/subspace.py +455 -0
- sage/modular/modsym/tests.py +376 -0
- sage/modular/multiple_zeta.py +2635 -0
- sage/modular/multiple_zeta_F_algebra.py +789 -0
- sage/modular/overconvergent/all.py +6 -0
- sage/modular/overconvergent/genus0.py +1879 -0
- sage/modular/overconvergent/hecke_series.py +1187 -0
- sage/modular/overconvergent/weightspace.py +776 -0
- sage/modular/pollack_stevens/all.py +4 -0
- sage/modular/pollack_stevens/distributions.py +874 -0
- sage/modular/pollack_stevens/fund_domain.py +1572 -0
- sage/modular/pollack_stevens/manin_map.py +856 -0
- sage/modular/pollack_stevens/modsym.py +1590 -0
- sage/modular/pollack_stevens/padic_lseries.py +417 -0
- sage/modular/pollack_stevens/sigma0.py +534 -0
- sage/modular/pollack_stevens/space.py +1078 -0
- sage/modular/quasimodform/all.py +3 -0
- sage/modular/quasimodform/element.py +846 -0
- sage/modular/quasimodform/ring.py +826 -0
- sage/modular/quatalg/all.py +3 -0
- sage/modular/quatalg/brandt.py +1642 -0
- sage/modular/ssmod/all.py +8 -0
- sage/modular/ssmod/ssmod.py +827 -0
- sage/rings/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/binary_form_reduce.py +585 -0
- sage/schemes/all.py +41 -0
- sage/schemes/berkovich/all.py +6 -0
- sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
- sage/schemes/berkovich/berkovich_space.py +700 -0
- sage/schemes/curves/affine_curve.py +2924 -0
- sage/schemes/curves/all.py +33 -0
- sage/schemes/curves/closed_point.py +434 -0
- sage/schemes/curves/constructor.py +397 -0
- sage/schemes/curves/curve.py +542 -0
- sage/schemes/curves/plane_curve_arrangement.py +1283 -0
- sage/schemes/curves/point.py +463 -0
- sage/schemes/curves/projective_curve.py +3203 -0
- sage/schemes/curves/weighted_projective_curve.py +106 -0
- sage/schemes/curves/zariski_vankampen.py +1931 -0
- sage/schemes/cyclic_covers/all.py +2 -0
- sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
- sage/schemes/cyclic_covers/constructor.py +137 -0
- sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
- sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
- sage/schemes/elliptic_curves/BSD.py +991 -0
- sage/schemes/elliptic_curves/Qcurves.py +592 -0
- sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
- sage/schemes/elliptic_curves/all.py +49 -0
- sage/schemes/elliptic_curves/cardinality.py +609 -0
- sage/schemes/elliptic_curves/cm.py +1103 -0
- sage/schemes/elliptic_curves/constructor.py +1530 -0
- sage/schemes/elliptic_curves/ec_database.py +175 -0
- sage/schemes/elliptic_curves/ell_curve_isogeny.py +3971 -0
- sage/schemes/elliptic_curves/ell_egros.py +457 -0
- sage/schemes/elliptic_curves/ell_field.py +2837 -0
- sage/schemes/elliptic_curves/ell_finite_field.py +3249 -0
- sage/schemes/elliptic_curves/ell_generic.py +3760 -0
- sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
- sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
- sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
- sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
- sage/schemes/elliptic_curves/ell_point.py +4944 -0
- sage/schemes/elliptic_curves/ell_rational_field.py +7184 -0
- sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
- sage/schemes/elliptic_curves/ell_torsion.py +436 -0
- sage/schemes/elliptic_curves/ell_wp.py +352 -0
- sage/schemes/elliptic_curves/formal_group.py +760 -0
- sage/schemes/elliptic_curves/gal_reps.py +1459 -0
- sage/schemes/elliptic_curves/gal_reps_number_field.py +1663 -0
- sage/schemes/elliptic_curves/gp_simon.py +152 -0
- sage/schemes/elliptic_curves/heegner.py +7328 -0
- sage/schemes/elliptic_curves/height.py +2108 -0
- sage/schemes/elliptic_curves/hom.py +1788 -0
- sage/schemes/elliptic_curves/hom_composite.py +1084 -0
- sage/schemes/elliptic_curves/hom_fractional.py +544 -0
- sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
- sage/schemes/elliptic_curves/hom_scalar.py +531 -0
- sage/schemes/elliptic_curves/hom_sum.py +681 -0
- sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
- sage/schemes/elliptic_curves/homset.py +271 -0
- sage/schemes/elliptic_curves/isogeny_class.py +1523 -0
- sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
- sage/schemes/elliptic_curves/jacobian.py +247 -0
- sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
- sage/schemes/elliptic_curves/kraus.py +1014 -0
- sage/schemes/elliptic_curves/lseries_ell.py +915 -0
- sage/schemes/elliptic_curves/mod5family.py +105 -0
- sage/schemes/elliptic_curves/mod_poly.py +197 -0
- sage/schemes/elliptic_curves/mod_sym_num.cpython-314t-darwin.so +0 -0
- sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
- sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
- sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
- sage/schemes/elliptic_curves/padics.py +1816 -0
- sage/schemes/elliptic_curves/period_lattice.py +2234 -0
- sage/schemes/elliptic_curves/period_lattice_region.cpython-314t-darwin.so +0 -0
- sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
- sage/schemes/elliptic_curves/saturation.py +716 -0
- sage/schemes/elliptic_curves/sha_tate.py +1158 -0
- sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
- sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
- sage/schemes/hyperelliptic_curves/all.py +6 -0
- sage/schemes/hyperelliptic_curves/constructor.py +369 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1948 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +936 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
- sage/schemes/hyperelliptic_curves/invariants.py +410 -0
- sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +312 -0
- sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
- sage/schemes/hyperelliptic_curves/jacobian_generic.py +437 -0
- sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
- sage/schemes/hyperelliptic_curves/jacobian_morphism.py +878 -0
- sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
- sage/schemes/hyperelliptic_curves/mestre.py +302 -0
- sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3863 -0
- sage/schemes/jacobians/abstract_jacobian.py +277 -0
- sage/schemes/jacobians/all.py +2 -0
- sage/schemes/overview.py +161 -0
- sage/schemes/plane_conics/all.py +22 -0
- sage/schemes/plane_conics/con_field.py +1296 -0
- sage/schemes/plane_conics/con_finite_field.py +158 -0
- sage/schemes/plane_conics/con_number_field.py +456 -0
- sage/schemes/plane_conics/con_rational_field.py +406 -0
- sage/schemes/plane_conics/con_rational_function_field.py +581 -0
- sage/schemes/plane_conics/constructor.py +249 -0
- sage/schemes/plane_quartics/all.py +2 -0
- sage/schemes/plane_quartics/quartic_constructor.py +71 -0
- sage/schemes/plane_quartics/quartic_generic.py +53 -0
- sage/schemes/riemann_surfaces/all.py +1 -0
- sage/schemes/riemann_surfaces/riemann_surface.py +4177 -0
- sage_wheels/share/cremona/cremona_mini.db +0 -0
- sage_wheels/share/ellcurves/rank0 +30427 -0
- sage_wheels/share/ellcurves/rank1 +31871 -0
- sage_wheels/share/ellcurves/rank10 +6 -0
- sage_wheels/share/ellcurves/rank11 +6 -0
- sage_wheels/share/ellcurves/rank12 +1 -0
- sage_wheels/share/ellcurves/rank14 +1 -0
- sage_wheels/share/ellcurves/rank15 +1 -0
- sage_wheels/share/ellcurves/rank17 +1 -0
- sage_wheels/share/ellcurves/rank19 +1 -0
- sage_wheels/share/ellcurves/rank2 +2388 -0
- sage_wheels/share/ellcurves/rank20 +1 -0
- sage_wheels/share/ellcurves/rank21 +1 -0
- sage_wheels/share/ellcurves/rank22 +1 -0
- sage_wheels/share/ellcurves/rank23 +1 -0
- sage_wheels/share/ellcurves/rank24 +1 -0
- sage_wheels/share/ellcurves/rank28 +1 -0
- sage_wheels/share/ellcurves/rank3 +836 -0
- sage_wheels/share/ellcurves/rank4 +10 -0
- sage_wheels/share/ellcurves/rank5 +5 -0
- sage_wheels/share/ellcurves/rank6 +5 -0
- sage_wheels/share/ellcurves/rank7 +5 -0
- sage_wheels/share/ellcurves/rank8 +6 -0
- 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})
|