passagemath-schemes 10.6.40__cp314-cp314-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-schemes might be problematic. Click here for more details.
- 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.6.40.dist-info/METADATA +204 -0
- passagemath_schemes-10.6.40.dist-info/METADATA.bak +205 -0
- passagemath_schemes-10.6.40.dist-info/RECORD +314 -0
- passagemath_schemes-10.6.40.dist-info/WHEEL +6 -0
- passagemath_schemes-10.6.40.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 +9558 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314-darwin.so +0 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
- sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
- sage/lfunctions/all.py +18 -0
- sage/lfunctions/dokchitser.py +745 -0
- sage/lfunctions/pari.py +818 -0
- sage/lfunctions/zero_sums.cpython-314-darwin.so +0 -0
- sage/lfunctions/zero_sums.pyx +1847 -0
- sage/modular/abvar/abvar.py +5135 -0
- sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
- sage/modular/abvar/abvar_newform.py +244 -0
- sage/modular/abvar/all.py +8 -0
- sage/modular/abvar/constructor.py +186 -0
- sage/modular/abvar/cuspidal_subgroup.py +371 -0
- sage/modular/abvar/finite_subgroup.py +896 -0
- sage/modular/abvar/homology.py +720 -0
- sage/modular/abvar/homspace.py +998 -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 +740 -0
- sage/modular/all.py +43 -0
- sage/modular/arithgroup/all.py +20 -0
- sage/modular/arithgroup/arithgroup_element.cpython-314-darwin.so +0 -0
- sage/modular/arithgroup/arithgroup_element.pyx +474 -0
- sage/modular/arithgroup/arithgroup_generic.py +1402 -0
- sage/modular/arithgroup/arithgroup_perm.py +2692 -0
- sage/modular/arithgroup/congroup.cpython-314-darwin.so +0 -0
- sage/modular/arithgroup/congroup.pyx +334 -0
- sage/modular/arithgroup/congroup_gamma.py +363 -0
- sage/modular/arithgroup/congroup_gamma0.py +692 -0
- sage/modular/arithgroup/congroup_gamma1.py +653 -0
- sage/modular/arithgroup/congroup_gammaH.py +1469 -0
- sage/modular/arithgroup/congroup_generic.py +628 -0
- sage/modular/arithgroup/congroup_sl2z.py +267 -0
- sage/modular/arithgroup/farey_symbol.cpython-314-darwin.so +0 -0
- sage/modular/arithgroup/farey_symbol.pyx +1066 -0
- sage/modular/arithgroup/tests.py +418 -0
- sage/modular/btquotients/all.py +4 -0
- sage/modular/btquotients/btquotient.py +3753 -0
- sage/modular/btquotients/pautomorphicform.py +2570 -0
- sage/modular/buzzard.py +100 -0
- sage/modular/congroup.py +29 -0
- sage/modular/congroup_element.py +13 -0
- sage/modular/cusps.py +1109 -0
- sage/modular/cusps_nf.py +1270 -0
- sage/modular/dims.py +569 -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 +1065 -0
- sage/modular/hecke/algebra.py +746 -0
- sage/modular/hecke/all.py +20 -0
- sage/modular/hecke/ambient_module.py +1019 -0
- sage/modular/hecke/degenmap.py +119 -0
- sage/modular/hecke/element.py +325 -0
- sage/modular/hecke/hecke_operator.py +780 -0
- sage/modular/hecke/homspace.py +206 -0
- sage/modular/hecke/module.py +1767 -0
- sage/modular/hecke/morphism.py +174 -0
- sage/modular/hecke/submodule.py +989 -0
- sage/modular/hypergeometric_misc.cpython-314-darwin.so +0 -0
- sage/modular/hypergeometric_misc.pxd +4 -0
- sage/modular/hypergeometric_misc.pyx +166 -0
- sage/modular/hypergeometric_motive.py +2017 -0
- sage/modular/local_comp/all.py +2 -0
- sage/modular/local_comp/liftings.py +292 -0
- sage/modular/local_comp/local_comp.py +1071 -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 +815 -0
- sage/modular/modform/ambient_R.py +177 -0
- sage/modular/modform/ambient_eps.py +306 -0
- sage/modular/modform/ambient_g0.py +124 -0
- sage/modular/modform/ambient_g1.py +204 -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 +505 -0
- sage/modular/modform/eisenstein_submodule.py +663 -0
- sage/modular/modform/element.py +4131 -0
- sage/modular/modform/find_generators.py +59 -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 +133 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314-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 +1860 -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 +381 -0
- sage/modular/modform/weight1.py +220 -0
- sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
- sage/modular/modform_hecketriangle/abstract_space.py +2528 -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 +3352 -0
- sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -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 +3846 -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-314-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 +1295 -0
- sage/modular/modsym/modsym.py +400 -0
- sage/modular/modsym/modular_symbols.py +384 -0
- sage/modular/modsym/p1list.cpython-314-darwin.so +0 -0
- sage/modular/modsym/p1list.pxd +29 -0
- sage/modular/modsym/p1list.pyx +1372 -0
- sage/modular/modsym/p1list_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-314-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 +375 -0
- sage/modular/multiple_zeta.py +2632 -0
- sage/modular/multiple_zeta_F_algebra.py +786 -0
- sage/modular/overconvergent/all.py +6 -0
- sage/modular/overconvergent/genus0.py +1878 -0
- sage/modular/overconvergent/hecke_series.py +1187 -0
- sage/modular/overconvergent/weightspace.py +778 -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 +859 -0
- sage/modular/pollack_stevens/modsym.py +1593 -0
- sage/modular/pollack_stevens/padic_lseries.py +417 -0
- sage/modular/pollack_stevens/sigma0.py +534 -0
- sage/modular/pollack_stevens/space.py +1076 -0
- sage/modular/quasimodform/all.py +3 -0
- sage/modular/quasimodform/element.py +845 -0
- sage/modular/quasimodform/ring.py +828 -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 +748 -0
- sage/schemes/curves/affine_curve.py +2928 -0
- sage/schemes/curves/all.py +33 -0
- sage/schemes/curves/closed_point.py +434 -0
- sage/schemes/curves/constructor.py +381 -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 +3026 -0
- sage/schemes/curves/zariski_vankampen.py +1932 -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 +1036 -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 +1102 -0
- sage/schemes/elliptic_curves/constructor.py +1552 -0
- sage/schemes/elliptic_curves/ec_database.py +175 -0
- sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
- sage/schemes/elliptic_curves/ell_egros.py +459 -0
- sage/schemes/elliptic_curves/ell_field.py +2836 -0
- sage/schemes/elliptic_curves/ell_finite_field.py +3359 -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 +4787 -0
- sage/schemes/elliptic_curves/ell_rational_field.py +7368 -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 +1669 -0
- sage/schemes/elliptic_curves/gp_simon.py +152 -0
- sage/schemes/elliptic_curves/heegner.py +7335 -0
- sage/schemes/elliptic_curves/height.py +2109 -0
- sage/schemes/elliptic_curves/hom.py +1406 -0
- sage/schemes/elliptic_curves/hom_composite.py +934 -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 +682 -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 +1521 -0
- sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
- sage/schemes/elliptic_curves/jacobian.py +237 -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 +943 -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-314-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-314-darwin.so +0 -0
- sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
- sage/schemes/elliptic_curves/saturation.py +715 -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 +291 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -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 +315 -0
- sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
- sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
- sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
- sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -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 +3871 -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 +580 -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 +73 -0
- sage/schemes/riemann_surfaces/all.py +1 -0
- sage/schemes/riemann_surfaces/riemann_surface.py +4117 -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
|
Binary file
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
r"""
|
|
3
|
+
Helper functions for congruence subgroups
|
|
4
|
+
|
|
5
|
+
This file contains optimized Cython implementations of a few functions related
|
|
6
|
+
to the standard congruence subgroups `\Gamma_0, \Gamma_1, \Gamma_H`. These
|
|
7
|
+
functions are for internal use by routines elsewhere in the Sage library.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# ****************************************************************************
|
|
11
|
+
# This program is free software: you can redistribute it and/or modify
|
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
|
13
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
14
|
+
# (at your option) any later version.
|
|
15
|
+
# https://www.gnu.org/licenses/
|
|
16
|
+
# ****************************************************************************
|
|
17
|
+
|
|
18
|
+
from cysignals.memory cimport check_allocarray, sig_free
|
|
19
|
+
|
|
20
|
+
from sage.matrix.matrix_dense cimport Matrix_dense
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from sage.matrix.matrix_integer_dense import Matrix_integer_dense as MatrixClass
|
|
24
|
+
except ImportError:
|
|
25
|
+
from sage.matrix.matrix_generic_dense import Matrix_generic_dense as MatrixClass
|
|
26
|
+
|
|
27
|
+
import random
|
|
28
|
+
from .congroup_gamma1 import Gamma1_constructor as Gamma1
|
|
29
|
+
from .congroup_gamma0 import Gamma0_constructor as Gamma0
|
|
30
|
+
|
|
31
|
+
cimport sage.rings.fast_arith
|
|
32
|
+
import sage.rings.fast_arith
|
|
33
|
+
cdef sage.rings.fast_arith.arith_int arith_int
|
|
34
|
+
arith_int = sage.rings.fast_arith.arith_int()
|
|
35
|
+
from sage.modular.modsym.p1list import lift_to_sl2z
|
|
36
|
+
from sage.matrix.matrix_space import MatrixSpace
|
|
37
|
+
from sage.rings.integer_ring import ZZ
|
|
38
|
+
Mat2Z = MatrixSpace(ZZ, 2)
|
|
39
|
+
|
|
40
|
+
cdef Matrix_dense genS, genT, genI
|
|
41
|
+
|
|
42
|
+
genS = MatrixClass(Mat2Z, [0, -1, 1, 0], True, True)
|
|
43
|
+
genT = MatrixClass(Mat2Z, [1, 1, 0, 1], True, True)
|
|
44
|
+
genI = MatrixClass(Mat2Z, [1, 0, 0, 1], True, True)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# This is the C version of a function formerly implemented in python in
|
|
48
|
+
# sage.modular.congroup. It is orders of magnitude faster (e.g., 30
|
|
49
|
+
# times). The key speedup is in replacing looping through the
|
|
50
|
+
# elements of the Python list R with looping through the elements of a
|
|
51
|
+
# C-array.
|
|
52
|
+
|
|
53
|
+
def degeneracy_coset_representatives_gamma0(int N, int M, int t):
|
|
54
|
+
r"""
|
|
55
|
+
Let `N` be a positive integer and `M` a divisor of `N`. Let `t` be a
|
|
56
|
+
divisor of `N/M`, and let `T` be the `2 \times 2` matrix `(1, 0; 0, t)`.
|
|
57
|
+
This function returns representatives for the orbit set `\Gamma_0(N)
|
|
58
|
+
\backslash T \Gamma_0(M)`, where `\Gamma_0(N)` acts on the left on `T
|
|
59
|
+
\Gamma_0(M)`.
|
|
60
|
+
|
|
61
|
+
INPUT:
|
|
62
|
+
|
|
63
|
+
- ``N`` -- integer
|
|
64
|
+
- ``M`` -- integer (divisor of `N`)
|
|
65
|
+
- ``t`` -- integer (divisor of `N/M`)
|
|
66
|
+
|
|
67
|
+
OUTPUT:
|
|
68
|
+
|
|
69
|
+
list -- list of lists ``[a,b,c,d]``, where ``[a,b,c,d]`` should be viewed
|
|
70
|
+
as a 2x2 matrix.
|
|
71
|
+
|
|
72
|
+
This function is used for computation of degeneracy maps between
|
|
73
|
+
spaces of modular symbols, hence its name.
|
|
74
|
+
|
|
75
|
+
We use that `T^{-1} \cdot (a,b;c,d) \cdot T = (a,bt; c/t,d)`, that the
|
|
76
|
+
group `T^{-1} \Gamma_0(N) T` is contained in `\Gamma_0(M)`, and that
|
|
77
|
+
`\Gamma_0(N) T` is contained in `T \Gamma_0(M)`.
|
|
78
|
+
|
|
79
|
+
ALGORITHM:
|
|
80
|
+
|
|
81
|
+
1. Compute representatives for `\Gamma_0(N/t,t)` inside of `\Gamma_0(M)`:
|
|
82
|
+
|
|
83
|
+
+ COSET EQUIVALENCE: Two right cosets represented by `[a,b;c,d]` and
|
|
84
|
+
`[a',b';c',d']` of `\Gamma_0(N/t,t)` in `\SL_2(\ZZ)` are equivalent if
|
|
85
|
+
and only if `(a,b)=(a',b')` as points of `\mathbf{P}^1(\ZZ/t\ZZ)`,
|
|
86
|
+
i.e., `ab' \cong ba' \pmod{t}`, and `(c,d) = (c',d')` as points of
|
|
87
|
+
`\mathbf{P}^1(\ZZ/(N/t)\ZZ)`.
|
|
88
|
+
|
|
89
|
+
+ ALGORITHM to list all cosets:
|
|
90
|
+
|
|
91
|
+
a) Compute the number of cosets.
|
|
92
|
+
b) Compute a random element `x` of `\Gamma_0(M)`.
|
|
93
|
+
c) Check if x is equivalent to anything generated so far; if not, add x
|
|
94
|
+
to the list.
|
|
95
|
+
d) Continue until the list is as long as the bound
|
|
96
|
+
computed in step (a).
|
|
97
|
+
|
|
98
|
+
2. There is a bijection between `\Gamma_0(N)\backslash T \Gamma_0(M)` and
|
|
99
|
+
`\Gamma_0(N/t,t) \backslash \Gamma_0(M)` given by `T r \leftrightarrow
|
|
100
|
+
r`. Consequently we obtain coset representatives for
|
|
101
|
+
`\Gamma_0(N)\backslash T \Gamma_0(M)` by left multiplying by `T` each
|
|
102
|
+
coset representative of `\Gamma_0(N/t,t) \backslash \Gamma_0(M)` found
|
|
103
|
+
in step 1.
|
|
104
|
+
|
|
105
|
+
EXAMPLES::
|
|
106
|
+
|
|
107
|
+
sage: from sage.modular.arithgroup.all import degeneracy_coset_representatives_gamma0
|
|
108
|
+
sage: len(degeneracy_coset_representatives_gamma0(13, 1, 1))
|
|
109
|
+
14
|
|
110
|
+
sage: len(degeneracy_coset_representatives_gamma0(13, 13, 1))
|
|
111
|
+
1
|
|
112
|
+
sage: len(degeneracy_coset_representatives_gamma0(13, 1, 13))
|
|
113
|
+
14
|
|
114
|
+
"""
|
|
115
|
+
if N % M != 0:
|
|
116
|
+
raise ArithmeticError(f"M (={M}) must be a divisor of N (={N})")
|
|
117
|
+
|
|
118
|
+
if (N // M) % t != 0:
|
|
119
|
+
raise ArithmeticError(f"t (={t}) must be a divisor of N/M (={N//M})")
|
|
120
|
+
|
|
121
|
+
cdef int n, i, j, k, aa, bb, cc, dd, g, Ndivt, halfmax, is_new
|
|
122
|
+
cdef int* R
|
|
123
|
+
|
|
124
|
+
# total number of coset representatives that we'll find
|
|
125
|
+
n = Gamma0(N).index() / Gamma0(M).index()
|
|
126
|
+
k = 0 # number found so far
|
|
127
|
+
Ndivt = N // t
|
|
128
|
+
R = <int*>check_allocarray(4 * n, sizeof(int))
|
|
129
|
+
halfmax = 2*(n+10)
|
|
130
|
+
while k < n:
|
|
131
|
+
# try to find another coset representative.
|
|
132
|
+
cc = M*random.randrange(-halfmax, halfmax+1)
|
|
133
|
+
dd = random.randrange(-halfmax, halfmax+1)
|
|
134
|
+
g = arith_int.c_xgcd_int(-cc, dd, &bb, &aa)
|
|
135
|
+
if g == 0:
|
|
136
|
+
continue
|
|
137
|
+
cc = cc // g
|
|
138
|
+
if cc % M != 0:
|
|
139
|
+
continue
|
|
140
|
+
dd = dd // g
|
|
141
|
+
# Test if we've found a new coset representative.
|
|
142
|
+
is_new = 1
|
|
143
|
+
for i in range(k):
|
|
144
|
+
j = 4*i
|
|
145
|
+
if (R[j+1]*aa - R[j]*bb) % t == 0 and \
|
|
146
|
+
(R[j+3]*cc - R[j+2]*dd) % Ndivt == 0:
|
|
147
|
+
is_new = 0
|
|
148
|
+
break
|
|
149
|
+
# If our matrix is new add it to the list.
|
|
150
|
+
if is_new:
|
|
151
|
+
R[4*k] = aa
|
|
152
|
+
R[4*k+1] = bb
|
|
153
|
+
R[4*k+2] = cc
|
|
154
|
+
R[4*k+3] = dd
|
|
155
|
+
k = k + 1
|
|
156
|
+
|
|
157
|
+
# Return the list left multiplied by T.
|
|
158
|
+
S = []
|
|
159
|
+
for i in range(k):
|
|
160
|
+
j = 4*i
|
|
161
|
+
S.append([R[j], R[j+1], R[j+2]*t, R[j+3]*t])
|
|
162
|
+
sig_free(R)
|
|
163
|
+
return S
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def degeneracy_coset_representatives_gamma1(int N, int M, int t):
|
|
167
|
+
r"""
|
|
168
|
+
Let `N` be a positive integer and `M` a divisor of `N`. Let `t` be a
|
|
169
|
+
divisor of `N/M`, and let `T` be the `2 \times 2` matrix `(1,0; 0,t)`.
|
|
170
|
+
This function returns representatives for the orbit set `\Gamma_1(N)
|
|
171
|
+
\backslash T \Gamma_1(M)`, where `\Gamma_1(N)` acts on the left on `T
|
|
172
|
+
\Gamma_1(M)`.
|
|
173
|
+
|
|
174
|
+
INPUT:
|
|
175
|
+
|
|
176
|
+
- ``N`` -- integer
|
|
177
|
+
- ``M`` -- integer (divisor of `N`)
|
|
178
|
+
- ``t`` -- integer (divisor of `N/M`)
|
|
179
|
+
|
|
180
|
+
OUTPUT:
|
|
181
|
+
|
|
182
|
+
list -- list of lists ``[a,b,c,d]``, where ``[a,b,c,d]`` should be viewed
|
|
183
|
+
as a 2x2 matrix.
|
|
184
|
+
|
|
185
|
+
This function is used for computation of degeneracy maps between
|
|
186
|
+
spaces of modular symbols, hence its name.
|
|
187
|
+
|
|
188
|
+
ALGORITHM:
|
|
189
|
+
|
|
190
|
+
Everything is the same as for
|
|
191
|
+
:func:`~degeneracy_coset_representatives_gamma0`, except for coset
|
|
192
|
+
equivalence. Here `\Gamma_1(N/t,t)` consists of matrices that are of the
|
|
193
|
+
form `(1,*; 0,1) \bmod N/t` and `(1,0; *,1) \bmod t`.
|
|
194
|
+
|
|
195
|
+
COSET EQUIVALENCE: Two right cosets represented by `[a,b;c,d]` and
|
|
196
|
+
`[a',b';c',d']` of `\Gamma_1(N/t,t)` in `\SL_2(\ZZ)` are equivalent if
|
|
197
|
+
and only if
|
|
198
|
+
|
|
199
|
+
.. MATH::
|
|
200
|
+
|
|
201
|
+
a \cong a' \pmod{t},
|
|
202
|
+
b \cong b' \pmod{t},
|
|
203
|
+
c \cong c' \pmod{N/t},
|
|
204
|
+
d \cong d' \pmod{N/t}.
|
|
205
|
+
|
|
206
|
+
EXAMPLES::
|
|
207
|
+
|
|
208
|
+
sage: from sage.modular.arithgroup.all import degeneracy_coset_representatives_gamma1
|
|
209
|
+
sage: len(degeneracy_coset_representatives_gamma1(13, 1, 1))
|
|
210
|
+
168
|
|
211
|
+
sage: len(degeneracy_coset_representatives_gamma1(13, 13, 1))
|
|
212
|
+
1
|
|
213
|
+
sage: len(degeneracy_coset_representatives_gamma1(13, 1, 13))
|
|
214
|
+
168
|
|
215
|
+
"""
|
|
216
|
+
if N % M != 0:
|
|
217
|
+
raise ArithmeticError(f"M (={M}) must be a divisor of N (={N})")
|
|
218
|
+
|
|
219
|
+
if (N // M) % t != 0:
|
|
220
|
+
raise ArithmeticError(f"t (={t}) must be a divisor of N/M (={N//M})")
|
|
221
|
+
|
|
222
|
+
cdef int d, g, i, j, k, n, aa, bb, cc, dd, Ndivt, halfmax, is_new
|
|
223
|
+
cdef int* R
|
|
224
|
+
|
|
225
|
+
# total number of coset representatives that we'll find
|
|
226
|
+
n = Gamma1(N).index() / Gamma1(M).index()
|
|
227
|
+
d = arith_int.c_gcd_int(t, N // t)
|
|
228
|
+
n = n // d
|
|
229
|
+
k = 0 # number found so far
|
|
230
|
+
Ndivt = N // t
|
|
231
|
+
R = <int*>check_allocarray(4 * n, sizeof(int))
|
|
232
|
+
halfmax = 2*(n+10)
|
|
233
|
+
while k < n:
|
|
234
|
+
# try to find another coset representative.
|
|
235
|
+
cc = M * random.randrange(-halfmax, halfmax + 1)
|
|
236
|
+
dd = 1 + M * random.randrange(-halfmax, halfmax + 1)
|
|
237
|
+
g = arith_int.c_xgcd_int(-cc, dd, &bb, &aa)
|
|
238
|
+
if g == 0:
|
|
239
|
+
continue
|
|
240
|
+
cc = cc // g
|
|
241
|
+
if cc % M != 0:
|
|
242
|
+
continue
|
|
243
|
+
dd = dd // g
|
|
244
|
+
if M != 1 and dd % M != 1:
|
|
245
|
+
continue
|
|
246
|
+
# Test if we've found a new coset representative.
|
|
247
|
+
is_new = 1
|
|
248
|
+
for i in range(k):
|
|
249
|
+
j = 4*i
|
|
250
|
+
if (R[j] - aa) % t == 0 and \
|
|
251
|
+
(R[j+1] - bb) % t == 0 and \
|
|
252
|
+
(R[j+2] - cc) % Ndivt == 0 and \
|
|
253
|
+
(R[j+3] - dd) % Ndivt == 0:
|
|
254
|
+
is_new = 0
|
|
255
|
+
break
|
|
256
|
+
# If our matrix is new add it to the list.
|
|
257
|
+
if is_new:
|
|
258
|
+
if k > n:
|
|
259
|
+
sig_free(R)
|
|
260
|
+
raise RuntimeError("bug!!")
|
|
261
|
+
R[4*k] = aa
|
|
262
|
+
R[4*k+1] = bb
|
|
263
|
+
R[4*k+2] = cc
|
|
264
|
+
R[4*k+3] = dd
|
|
265
|
+
k = k + 1
|
|
266
|
+
|
|
267
|
+
# Return the list left multiplied by T.
|
|
268
|
+
S = []
|
|
269
|
+
for i in range(k):
|
|
270
|
+
j = 4*i
|
|
271
|
+
S.append([R[j], R[j+1], R[j+2]*t, R[j+3]*t])
|
|
272
|
+
sig_free(R)
|
|
273
|
+
return S
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def generators_helper(coset_reps, level):
|
|
277
|
+
r"""
|
|
278
|
+
Helper function for generators of Gamma0, Gamma1 and GammaH.
|
|
279
|
+
|
|
280
|
+
These are computed using coset representatives, via an "inverse
|
|
281
|
+
Todd-Coxeter" algorithm, and generators for `\SL_2(\ZZ)`.
|
|
282
|
+
|
|
283
|
+
ALGORITHM: Given coset representatives for a finite index subgroup `G` of
|
|
284
|
+
`\SL_2(\ZZ)` we compute generators for `G` as follows. Let `R` be a set of
|
|
285
|
+
coset representatives for `G`. Let `S, T \in \SL_2(\ZZ)` be defined by
|
|
286
|
+
`(0,-1; 1,0)` and `(1,1,0,1)`, respectively.
|
|
287
|
+
Define maps `s, t: R \to G` as follows. If `r \in R`, then there exists a
|
|
288
|
+
unique `r' \in R` such that `GrS = Gr'`. Let `s(r) = rSr'^{-1}`. Likewise,
|
|
289
|
+
there is a unique `r'` such that `GrT = Gr'` and we let `t(r) = rTr'^{-1}`.
|
|
290
|
+
Note that `s(r)` and `t(r)` are in `G` for all `r`. Then `G` is generated
|
|
291
|
+
by `s(R)\cup t(R)`.
|
|
292
|
+
|
|
293
|
+
There are more sophisticated algorithms using group actions on trees (and
|
|
294
|
+
Farey symbols) that give smaller generating sets -- this code is now
|
|
295
|
+
deprecated in favour of the newer implementation based on Farey symbols.
|
|
296
|
+
|
|
297
|
+
EXAMPLES::
|
|
298
|
+
|
|
299
|
+
sage: Gamma0(7).generators(algorithm='todd-coxeter') # indirect doctest
|
|
300
|
+
[
|
|
301
|
+
[1 1] [-1 0] [ 1 -1] [1 0] [1 1] [-3 -1] [-2 -1] [-5 -1]
|
|
302
|
+
[0 1], [ 0 -1], [ 0 1], [7 1], [0 1], [ 7 2], [ 7 3], [21 4],
|
|
303
|
+
<BLANKLINE>
|
|
304
|
+
[-4 -1] [-1 0] [ 1 0]
|
|
305
|
+
[21 5], [ 7 -1], [-7 1]
|
|
306
|
+
]
|
|
307
|
+
"""
|
|
308
|
+
cdef Matrix_dense x, y, z, v, vSmod, vTmod
|
|
309
|
+
|
|
310
|
+
crs = coset_reps.list()
|
|
311
|
+
try:
|
|
312
|
+
reps = [MatrixClass(Mat2Z, lift_to_sl2z(c, d, level),
|
|
313
|
+
False, True) for c, d in crs]
|
|
314
|
+
except Exception:
|
|
315
|
+
raise ArithmeticError("Error lifting to SL2Z: level=%s crs=%s" % (level, crs))
|
|
316
|
+
ans = []
|
|
317
|
+
cdef Py_ssize_t i
|
|
318
|
+
for i in range(len(crs)):
|
|
319
|
+
x = reps[i]
|
|
320
|
+
v = MatrixClass(Mat2Z, [crs[i][0], crs[i][1], 0, 0],
|
|
321
|
+
False, True)
|
|
322
|
+
vSmod = (v*genS)
|
|
323
|
+
vTmod = (v*genT)
|
|
324
|
+
y_index = coset_reps.normalize(vSmod[0, 0], vSmod[0, 1])
|
|
325
|
+
z_index = coset_reps.normalize(vTmod[0, 0], vTmod[0, 1])
|
|
326
|
+
y_index = crs.index(y_index)
|
|
327
|
+
z_index = crs.index(z_index)
|
|
328
|
+
y = reps[y_index]
|
|
329
|
+
z = reps[z_index]
|
|
330
|
+
y = y.inverse_of_unit()
|
|
331
|
+
z = z.inverse_of_unit()
|
|
332
|
+
ans.append(x*genS*y)
|
|
333
|
+
ans.append(x*genT*z)
|
|
334
|
+
return [x for x in ans if x != genI]
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
r"""
|
|
3
|
+
Congruence subgroup `\Gamma(N)`
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# ****************************************************************************
|
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
# https://www.gnu.org/licenses/
|
|
12
|
+
# ****************************************************************************
|
|
13
|
+
|
|
14
|
+
from sage.arith.misc import gcd
|
|
15
|
+
from sage.groups.matrix_gps.finitely_generated import MatrixGroup
|
|
16
|
+
from sage.matrix.constructor import matrix
|
|
17
|
+
from sage.misc.misc_c import prod
|
|
18
|
+
from sage.modular.cusps import Cusp
|
|
19
|
+
from sage.rings.finite_rings.integer_mod_ring import Zmod
|
|
20
|
+
from sage.rings.integer import GCD_list
|
|
21
|
+
from sage.rings.integer_ring import ZZ
|
|
22
|
+
from sage.rings.rational_field import QQ
|
|
23
|
+
from sage.structure.richcmp import richcmp_method, richcmp
|
|
24
|
+
|
|
25
|
+
from .congroup_generic import CongruenceSubgroup
|
|
26
|
+
from .congroup_sl2z import SL2Z
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
_gamma_cache = {}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def Gamma_constructor(N):
|
|
33
|
+
r"""
|
|
34
|
+
Return the congruence subgroup `\Gamma(N)`.
|
|
35
|
+
|
|
36
|
+
EXAMPLES::
|
|
37
|
+
|
|
38
|
+
sage: Gamma(5) # indirect doctest
|
|
39
|
+
Congruence Subgroup Gamma(5)
|
|
40
|
+
sage: G = Gamma(23)
|
|
41
|
+
sage: G is Gamma(23)
|
|
42
|
+
True
|
|
43
|
+
sage: TestSuite(G).run()
|
|
44
|
+
|
|
45
|
+
Test global uniqueness::
|
|
46
|
+
|
|
47
|
+
sage: G = Gamma(17)
|
|
48
|
+
sage: G is loads(dumps(G))
|
|
49
|
+
True
|
|
50
|
+
sage: G2 = sage.modular.arithgroup.congroup_gamma.Gamma_class(17)
|
|
51
|
+
sage: G == G2
|
|
52
|
+
True
|
|
53
|
+
sage: G is G2
|
|
54
|
+
False
|
|
55
|
+
"""
|
|
56
|
+
if N == 1:
|
|
57
|
+
return SL2Z
|
|
58
|
+
try:
|
|
59
|
+
return _gamma_cache[N]
|
|
60
|
+
except KeyError:
|
|
61
|
+
_gamma_cache[N] = Gamma_class(N)
|
|
62
|
+
return _gamma_cache[N]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@richcmp_method
|
|
66
|
+
class Gamma_class(CongruenceSubgroup):
|
|
67
|
+
r"""
|
|
68
|
+
The principal congruence subgroup `\Gamma(N)`.
|
|
69
|
+
"""
|
|
70
|
+
def _repr_(self):
|
|
71
|
+
"""
|
|
72
|
+
Return the string representation of ``self``.
|
|
73
|
+
|
|
74
|
+
EXAMPLES::
|
|
75
|
+
|
|
76
|
+
sage: Gamma(133)._repr_()
|
|
77
|
+
'Congruence Subgroup Gamma(133)'
|
|
78
|
+
"""
|
|
79
|
+
return "Congruence Subgroup Gamma(%s)" % self.level()
|
|
80
|
+
|
|
81
|
+
def _latex_(self):
|
|
82
|
+
r"""
|
|
83
|
+
Return the \LaTeX representation of ``self``.
|
|
84
|
+
|
|
85
|
+
EXAMPLES::
|
|
86
|
+
|
|
87
|
+
sage: Gamma(20)._latex_()
|
|
88
|
+
'\\Gamma(20)'
|
|
89
|
+
sage: latex(Gamma(20))
|
|
90
|
+
\Gamma(20)
|
|
91
|
+
"""
|
|
92
|
+
return "\\Gamma(%s)" % self.level()
|
|
93
|
+
|
|
94
|
+
def __reduce__(self):
|
|
95
|
+
"""
|
|
96
|
+
Used for pickling ``self``.
|
|
97
|
+
|
|
98
|
+
EXAMPLES::
|
|
99
|
+
|
|
100
|
+
sage: Gamma(5).__reduce__()
|
|
101
|
+
(<function Gamma_constructor at ...>, (5,))
|
|
102
|
+
"""
|
|
103
|
+
return Gamma_constructor, (self.level(),)
|
|
104
|
+
|
|
105
|
+
def __richcmp__(self, other, op):
|
|
106
|
+
r"""
|
|
107
|
+
Compare ``self`` to ``other``.
|
|
108
|
+
|
|
109
|
+
EXAMPLES::
|
|
110
|
+
|
|
111
|
+
sage: Gamma(3) == SymmetricGroup(8) # needs sage.groups
|
|
112
|
+
False
|
|
113
|
+
sage: Gamma(3) == Gamma1(3)
|
|
114
|
+
False
|
|
115
|
+
sage: Gamma(5) < Gamma(6)
|
|
116
|
+
True
|
|
117
|
+
sage: Gamma(5) == Gamma(5)
|
|
118
|
+
True
|
|
119
|
+
sage: Gamma(3) == Gamma(3).as_permutation_group() # needs sage.groups
|
|
120
|
+
True
|
|
121
|
+
"""
|
|
122
|
+
if isinstance(other, Gamma_class):
|
|
123
|
+
return richcmp(self.level(), other.level(), op)
|
|
124
|
+
else:
|
|
125
|
+
return NotImplemented
|
|
126
|
+
|
|
127
|
+
def index(self):
|
|
128
|
+
r"""
|
|
129
|
+
Return the index of ``self`` in the full modular group. This is given by
|
|
130
|
+
|
|
131
|
+
.. MATH::
|
|
132
|
+
|
|
133
|
+
\prod_{\substack{p \mid N \\ \text{$p$ prime}}}\left(p^{3e}-p^{3e-2}\right).
|
|
134
|
+
|
|
135
|
+
EXAMPLES::
|
|
136
|
+
|
|
137
|
+
sage: [Gamma(n).index() for n in [1..19]]
|
|
138
|
+
[1, 6, 24, 48, 120, 144, 336, 384, 648, 720, 1320, 1152, 2184, 2016, 2880, 3072, 4896, 3888, 6840]
|
|
139
|
+
sage: Gamma(32041).index()
|
|
140
|
+
32893086819240
|
|
141
|
+
"""
|
|
142
|
+
return prod([p**(3*e-2)*(p*p-1) for (p,e) in self.level().factor()])
|
|
143
|
+
|
|
144
|
+
def _contains_sl2(self, a, b, c, d):
|
|
145
|
+
r"""
|
|
146
|
+
EXAMPLES::
|
|
147
|
+
|
|
148
|
+
sage: G = Gamma(5)
|
|
149
|
+
sage: [1, 0, -10, 1] in G
|
|
150
|
+
True
|
|
151
|
+
sage: 1 in G
|
|
152
|
+
True
|
|
153
|
+
sage: SL2Z([26, 5, 5, 1]) in G
|
|
154
|
+
True
|
|
155
|
+
sage: SL2Z([1, 1, 6, 7]) in G
|
|
156
|
+
False
|
|
157
|
+
"""
|
|
158
|
+
N = self.level()
|
|
159
|
+
# don't need to check d == 1 as this is automatic from det
|
|
160
|
+
return ((a % N == 1) and (b % N == 0) and (c % N == 0))
|
|
161
|
+
|
|
162
|
+
def ncusps(self):
|
|
163
|
+
r"""
|
|
164
|
+
Return the number of cusps of this subgroup `\Gamma(N)`.
|
|
165
|
+
|
|
166
|
+
EXAMPLES::
|
|
167
|
+
|
|
168
|
+
sage: [Gamma(n).ncusps() for n in [1..19]]
|
|
169
|
+
[1, 3, 4, 6, 12, 12, 24, 24, 36, 36, 60, 48, 84, 72, 96, 96, 144, 108, 180]
|
|
170
|
+
sage: Gamma(30030).ncusps()
|
|
171
|
+
278691840
|
|
172
|
+
sage: Gamma(2^30).ncusps()
|
|
173
|
+
432345564227567616
|
|
174
|
+
"""
|
|
175
|
+
n = self.level()
|
|
176
|
+
if n == 1:
|
|
177
|
+
return ZZ(1)
|
|
178
|
+
if n == 2:
|
|
179
|
+
return ZZ(3)
|
|
180
|
+
return prod([p**(2*e) - p**(2*e-2) for (p,e) in n.factor()])//2
|
|
181
|
+
|
|
182
|
+
def nirregcusps(self):
|
|
183
|
+
r"""
|
|
184
|
+
Return the number of irregular cusps of ``self``. For principal
|
|
185
|
+
congruence subgroups this is always 0.
|
|
186
|
+
|
|
187
|
+
EXAMPLES::
|
|
188
|
+
|
|
189
|
+
sage: Gamma(17).nirregcusps()
|
|
190
|
+
0
|
|
191
|
+
"""
|
|
192
|
+
return 0
|
|
193
|
+
|
|
194
|
+
def _find_cusps(self):
|
|
195
|
+
r"""
|
|
196
|
+
Calculate the reduced representatives of the equivalence classes of
|
|
197
|
+
cusps for this group. Adapted from code by Ron Evans.
|
|
198
|
+
|
|
199
|
+
EXAMPLES::
|
|
200
|
+
|
|
201
|
+
sage: Gamma(8).cusps() # indirect doctest
|
|
202
|
+
[0, 1/4, 1/3, 3/8, 1/2, 2/3, 3/4, 1, 4/3, 3/2, 5/3, 2, 7/3, 5/2, 8/3, 3, 7/2, 11/3, 4, 14/3, 5, 6, 7, Infinity]
|
|
203
|
+
"""
|
|
204
|
+
n = self.level()
|
|
205
|
+
C = [QQ(x) for x in range(n)]
|
|
206
|
+
|
|
207
|
+
n0 = n//2
|
|
208
|
+
n1 = (n+1)//2
|
|
209
|
+
|
|
210
|
+
for r in range(1, n1):
|
|
211
|
+
if r > 1 and gcd(r,n) == 1:
|
|
212
|
+
C.append(ZZ(r)/ZZ(n))
|
|
213
|
+
if n0 == n/2 and gcd(r,n0) == 1:
|
|
214
|
+
C.append(ZZ(r)/ZZ(n0))
|
|
215
|
+
|
|
216
|
+
for s in range(2,n1):
|
|
217
|
+
for r in range(1, 1+n):
|
|
218
|
+
if GCD_list([s,r,n]) == 1:
|
|
219
|
+
# GCD_list is ~40x faster than gcd, since gcd wastes loads
|
|
220
|
+
# of time initialising a Sequence type.
|
|
221
|
+
u,v = _lift_pair(r,s,n)
|
|
222
|
+
C.append(ZZ(u)/ZZ(v))
|
|
223
|
+
|
|
224
|
+
return [Cusp(x) for x in sorted(C)] + [Cusp(1,0)]
|
|
225
|
+
|
|
226
|
+
def reduce_cusp(self, c):
|
|
227
|
+
r"""
|
|
228
|
+
Calculate the unique reduced representative of the equivalence of the
|
|
229
|
+
cusp `c` modulo this group. The reduced representative of an
|
|
230
|
+
equivalence class is the unique cusp in the class of the form `u/v`
|
|
231
|
+
with `u, v \ge 0` coprime, `v` minimal, and `u` minimal for that `v`.
|
|
232
|
+
|
|
233
|
+
EXAMPLES::
|
|
234
|
+
|
|
235
|
+
sage: Gamma(5).reduce_cusp(1/5)
|
|
236
|
+
Infinity
|
|
237
|
+
sage: Gamma(5).reduce_cusp(7/8)
|
|
238
|
+
3/2
|
|
239
|
+
sage: Gamma(6).reduce_cusp(4/3)
|
|
240
|
+
2/3
|
|
241
|
+
|
|
242
|
+
TESTS::
|
|
243
|
+
|
|
244
|
+
sage: G = Gamma(50)
|
|
245
|
+
sage: all(c == G.reduce_cusp(c) for c in G.cusps())
|
|
246
|
+
True
|
|
247
|
+
|
|
248
|
+
We test that :issue:`36163` is fixed::
|
|
249
|
+
|
|
250
|
+
sage: Gamma(7).reduce_cusp(Cusp(6,7))
|
|
251
|
+
Infinity
|
|
252
|
+
"""
|
|
253
|
+
N = self.level()
|
|
254
|
+
c = Cusp(c)
|
|
255
|
+
u,v = c.numerator() % N, c.denominator() % N
|
|
256
|
+
if (v > N//2) or (2*v == N and u > N//2):
|
|
257
|
+
u,v = -u,-v
|
|
258
|
+
u,v = _lift_pair(u,v,N)
|
|
259
|
+
return Cusp(u,v)
|
|
260
|
+
|
|
261
|
+
def are_equivalent(self, x, y, trans=False):
|
|
262
|
+
r"""
|
|
263
|
+
Check if the cusps `x` and `y` are equivalent under the action of this group.
|
|
264
|
+
|
|
265
|
+
ALGORITHM: The cusps `u_1 / v_1` and `u_2 / v_2` are equivalent modulo
|
|
266
|
+
`\Gamma(N)` if and only if `(u_1, v_1) = \pm (u_2, v_2) \bmod N`.
|
|
267
|
+
|
|
268
|
+
EXAMPLES::
|
|
269
|
+
|
|
270
|
+
sage: Gamma(7).are_equivalent(Cusp(2/3), Cusp(5/4))
|
|
271
|
+
True
|
|
272
|
+
"""
|
|
273
|
+
if trans:
|
|
274
|
+
return CongruenceSubgroup.are_equivalent(self, x,y,trans=trans)
|
|
275
|
+
N = self.level()
|
|
276
|
+
u1,v1 = (x.numerator() % N, x.denominator() % N)
|
|
277
|
+
u2,v2 = (y.numerator(), y.denominator())
|
|
278
|
+
|
|
279
|
+
return ((u1,v1) == (u2 % N, v2 % N)) or ((u1,v1) == (-u2 % N, -v2 % N))
|
|
280
|
+
|
|
281
|
+
def nu3(self):
|
|
282
|
+
r"""
|
|
283
|
+
Return the number of elliptic points of order 3 for this arithmetic
|
|
284
|
+
subgroup. Since this subgroup is `\Gamma(N)` for `N \ge 2`, there are
|
|
285
|
+
no such points, so we return 0.
|
|
286
|
+
|
|
287
|
+
EXAMPLES::
|
|
288
|
+
|
|
289
|
+
sage: Gamma(89).nu3()
|
|
290
|
+
0
|
|
291
|
+
"""
|
|
292
|
+
return 0
|
|
293
|
+
|
|
294
|
+
# We don't need to override nu2, since the default nu2 implementation knows
|
|
295
|
+
# that nu2 = 0 for odd subgroups.
|
|
296
|
+
|
|
297
|
+
def image_mod_n(self):
|
|
298
|
+
r"""
|
|
299
|
+
Return the image of this group modulo `N`, as a subgroup of `SL(2, \ZZ
|
|
300
|
+
/ N\ZZ)`. This is just the trivial subgroup.
|
|
301
|
+
|
|
302
|
+
EXAMPLES::
|
|
303
|
+
|
|
304
|
+
sage: Gamma(3).image_mod_n()
|
|
305
|
+
Matrix group over Ring of integers modulo 3 with 1 generators (
|
|
306
|
+
[1 0]
|
|
307
|
+
[0 1]
|
|
308
|
+
)
|
|
309
|
+
"""
|
|
310
|
+
return MatrixGroup([matrix(Zmod(self.level()), 2, 2, 1)])
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def is_Gamma(x):
|
|
314
|
+
r"""
|
|
315
|
+
Return ``True`` if x is a congruence subgroup of type Gamma.
|
|
316
|
+
|
|
317
|
+
EXAMPLES::
|
|
318
|
+
|
|
319
|
+
sage: from sage.modular.arithgroup.all import Gamma_class
|
|
320
|
+
sage: isinstance(Gamma0(13), Gamma_class)
|
|
321
|
+
False
|
|
322
|
+
sage: isinstance(Gamma(4), Gamma_class)
|
|
323
|
+
True
|
|
324
|
+
"""
|
|
325
|
+
from sage.misc.superseded import deprecation
|
|
326
|
+
deprecation(38035, "The function is_Gamma is deprecated; use 'isinstance(..., Gamma_class)' instead.")
|
|
327
|
+
return isinstance(x, Gamma_class)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def _lift_pair(U, V, N):
|
|
331
|
+
r"""
|
|
332
|
+
Utility function. Given integers ``U, V, N``, with `N \ge 1` and `{\rm
|
|
333
|
+
gcd}(U, V, N) = 1`, return a pair `(u, v)` congruent to `(U, V) \bmod N`,
|
|
334
|
+
such that `{\rm gcd}(u,v) = 1`, `u, v \ge 0`, `v` is as small as possible,
|
|
335
|
+
and `u` is as small as possible for that `v`.
|
|
336
|
+
|
|
337
|
+
*Warning*: As this function is for internal use, it does not do a
|
|
338
|
+
preliminary sanity check on its input, for efficiency. It will recover
|
|
339
|
+
reasonably gracefully if ``(U, V, N)`` are not coprime, but only after
|
|
340
|
+
wasting quite a lot of cycles!
|
|
341
|
+
|
|
342
|
+
EXAMPLES::
|
|
343
|
+
|
|
344
|
+
sage: from sage.modular.arithgroup.congroup_gamma import _lift_pair
|
|
345
|
+
sage: _lift_pair(2,4,7)
|
|
346
|
+
(9, 4)
|
|
347
|
+
sage: _lift_pair(2,4,8) # don't do this
|
|
348
|
+
Traceback (most recent call last):
|
|
349
|
+
...
|
|
350
|
+
ValueError: (U, V, N) must be coprime
|
|
351
|
+
"""
|
|
352
|
+
u = U % N
|
|
353
|
+
v = V % N
|
|
354
|
+
if v == 0:
|
|
355
|
+
if u == 1 or u == N-1:
|
|
356
|
+
return (1,0)
|
|
357
|
+
else:
|
|
358
|
+
v = N
|
|
359
|
+
while gcd(u, v) > 1:
|
|
360
|
+
u = u+N
|
|
361
|
+
if u > N*v:
|
|
362
|
+
raise ValueError("(U, V, N) must be coprime")
|
|
363
|
+
return (u, v)
|