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,1067 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# distutils: sources = sage/modular/arithgroup/sl2z.cpp sage/modular/arithgroup/farey.cpp
|
|
3
|
+
# distutils: language = c++
|
|
4
|
+
# distutils: extra_compile_args = -std=c++17
|
|
5
|
+
# sage.doctest: needs sage.libs.pari
|
|
6
|
+
r"""
|
|
7
|
+
Farey symbol for arithmetic subgroups of `\PSL_2(\ZZ)`
|
|
8
|
+
|
|
9
|
+
AUTHORS:
|
|
10
|
+
|
|
11
|
+
- Hartmut Monien (08 - 2011)
|
|
12
|
+
|
|
13
|
+
based on the *KFarey* package by Chris Kurth. Implemented as C++ module
|
|
14
|
+
for speed.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# ****************************************************************************
|
|
18
|
+
# Copyright (C) 2011 Hartmut Monien <monien@th.physik.uni-bonn.de>
|
|
19
|
+
#
|
|
20
|
+
# This program is free software: you can redistribute it and/or modify
|
|
21
|
+
# it under the terms of the GNU General Public License as published by
|
|
22
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
23
|
+
# (at your option) any later version.
|
|
24
|
+
# https://www.gnu.org/licenses/
|
|
25
|
+
# ****************************************************************************
|
|
26
|
+
|
|
27
|
+
from cpython.object cimport PyObject_RichCompare
|
|
28
|
+
from itertools import groupby
|
|
29
|
+
from cysignals.signals cimport sig_on, sig_off
|
|
30
|
+
|
|
31
|
+
from sage.libs.gmpxx cimport *
|
|
32
|
+
|
|
33
|
+
from sage.rings.real_mpfr import RR
|
|
34
|
+
from sage.rings.cc import CC
|
|
35
|
+
from sage.rings.integer cimport Integer
|
|
36
|
+
from sage.rings.infinity import infinity
|
|
37
|
+
from .congroup_gammaH import GammaH_class
|
|
38
|
+
from .congroup_gamma1 import Gamma1_class
|
|
39
|
+
from .congroup_gamma0 import Gamma0_class
|
|
40
|
+
from .congroup_gamma import Gamma_class
|
|
41
|
+
from .congroup_sl2z import SL2Z
|
|
42
|
+
from sage.modular.cusps import Cusp
|
|
43
|
+
|
|
44
|
+
from sage.misc.decorators import options
|
|
45
|
+
from sage.misc.cachefunc import cached_method
|
|
46
|
+
from sage.structure.richcmp cimport richcmp_not_equal
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
cdef extern from "sl2z.hpp":
|
|
50
|
+
cppclass cpp_SL2Z "SL2Z":
|
|
51
|
+
cpp_SL2Z(int, int, int, int)
|
|
52
|
+
cpp_SL2Z(mpz_class, mpz_class, mpz_class, mpz_class)
|
|
53
|
+
mpz_class a()
|
|
54
|
+
mpz_class b()
|
|
55
|
+
mpz_class c()
|
|
56
|
+
mpz_class d()
|
|
57
|
+
|
|
58
|
+
cdef extern from "farey.hpp":
|
|
59
|
+
cppclass is_element_Gamma0:
|
|
60
|
+
is_element_Gamma0(int)
|
|
61
|
+
cppclass is_element_Gamma1:
|
|
62
|
+
is_element_Gamma1(int)
|
|
63
|
+
cppclass is_element_Gamma:
|
|
64
|
+
is_element_Gamma(int)
|
|
65
|
+
cppclass is_element_GammaH:
|
|
66
|
+
is_element_GammaH(int, object)
|
|
67
|
+
cppclass cpp_farey "FareySymbol":
|
|
68
|
+
cpp_farey()
|
|
69
|
+
cpp_farey(object)
|
|
70
|
+
cpp_farey(object, is_element_Gamma*)
|
|
71
|
+
cpp_farey(object, is_element_Gamma0*)
|
|
72
|
+
cpp_farey(object, is_element_Gamma1*)
|
|
73
|
+
cpp_farey(object, is_element_GammaH*)
|
|
74
|
+
size_t genus()
|
|
75
|
+
size_t index()
|
|
76
|
+
size_t level()
|
|
77
|
+
size_t nu2()
|
|
78
|
+
size_t nu3()
|
|
79
|
+
object is_element(mpz_t, mpz_t, mpz_t, mpz_t)
|
|
80
|
+
object word_problem(mpz_t, mpz_t, mpz_t, mpz_t, cpp_SL2Z *)
|
|
81
|
+
size_t get_cusp_class(mpz_t, mpz_t)
|
|
82
|
+
object get_cusps()
|
|
83
|
+
object get_cusp_widths()
|
|
84
|
+
object get_transformation_to_cusp(mpz_t, mpz_t)
|
|
85
|
+
object get_fractions()
|
|
86
|
+
object get_coset()
|
|
87
|
+
object get_generators()
|
|
88
|
+
object get_pairings()
|
|
89
|
+
object get_paired_sides()
|
|
90
|
+
object get_pairing_matrices()
|
|
91
|
+
object dumps()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
cdef class Farey:
|
|
95
|
+
r"""
|
|
96
|
+
A class for calculating Farey symbols of arithmetics subgroups of
|
|
97
|
+
`\PSL_2(\ZZ)`.
|
|
98
|
+
|
|
99
|
+
The arithmetic subgroup can be either any of
|
|
100
|
+
the congruence subgroups implemented in Sage, i.e. Gamma, Gamma0,
|
|
101
|
+
Gamma1 and GammaH or a subgroup of `\PSL_2(\ZZ)` which is
|
|
102
|
+
given by a user written helper class defining membership in that
|
|
103
|
+
group.
|
|
104
|
+
|
|
105
|
+
REFERENCES:
|
|
106
|
+
|
|
107
|
+
- Ravi S. Kulkarni, ''An arithmetic-geometric method in the study of the
|
|
108
|
+
subgroups of the modular group'', `Amer. J. Math., 113(6):1053--1133,
|
|
109
|
+
1991. <http://www.jstor.org/stable/2374900>`_
|
|
110
|
+
|
|
111
|
+
INPUT:
|
|
112
|
+
|
|
113
|
+
- ``G`` -- an arithmetic subgroup of `\PSL_2(\ZZ)`
|
|
114
|
+
|
|
115
|
+
EXAMPLES:
|
|
116
|
+
|
|
117
|
+
Create a Farey symbol for the group `\Gamma_0(11)`::
|
|
118
|
+
|
|
119
|
+
sage: f = FareySymbol(Gamma0(11)); f
|
|
120
|
+
FareySymbol(Congruence Subgroup Gamma0(11))
|
|
121
|
+
|
|
122
|
+
Calculate the generators::
|
|
123
|
+
|
|
124
|
+
sage: f.generators()
|
|
125
|
+
[
|
|
126
|
+
[1 1] [ 7 -2] [ 8 -3] [-1 0]
|
|
127
|
+
[0 1], [11 -3], [11 -4], [ 0 -1]
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
Pickling the FareySymbol and recovering it::
|
|
131
|
+
|
|
132
|
+
sage: f == loads(dumps(f))
|
|
133
|
+
True
|
|
134
|
+
|
|
135
|
+
Calculate the index of `\Gamma_H(33, [2, 5])` in
|
|
136
|
+
`\PSL_2(\ZZ)` via FareySymbol::
|
|
137
|
+
|
|
138
|
+
sage: FareySymbol(GammaH(33, [2, 5])).index()
|
|
139
|
+
48
|
|
140
|
+
|
|
141
|
+
Calculate the generators of `\Gamma_1(4)`::
|
|
142
|
+
|
|
143
|
+
sage: FareySymbol(Gamma1(4)).generators()
|
|
144
|
+
[
|
|
145
|
+
[1 1] [-3 1]
|
|
146
|
+
[0 1], [-4 1]
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
Calculate the generators of the :meth:`example
|
|
150
|
+
<sage.modular.arithgroup.arithgroup_perm.HsuExample10>` of an
|
|
151
|
+
index 10 arithmetic subgroup given by Tim Hsu::
|
|
152
|
+
|
|
153
|
+
sage: from sage.modular.arithgroup.arithgroup_perm import HsuExample10 # needs sage.groups
|
|
154
|
+
sage: FareySymbol(HsuExample10()).generators() # needs sage.groups
|
|
155
|
+
[
|
|
156
|
+
[1 2] [-2 1] [ 4 -3]
|
|
157
|
+
[0 1], [-7 3], [ 3 -2]
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
Calculate the generators of the group `\Gamma' =
|
|
161
|
+
\Gamma_0(8)\cap\Gamma_1(4)` using a helper class to define group membership::
|
|
162
|
+
|
|
163
|
+
sage: class GPrime:
|
|
164
|
+
....: def __contains__(self, M):
|
|
165
|
+
....: return M in Gamma0(8) and M in Gamma1(4)
|
|
166
|
+
|
|
167
|
+
sage: FareySymbol(GPrime()).generators()
|
|
168
|
+
[
|
|
169
|
+
[1 1] [ 5 -1] [ 5 -2]
|
|
170
|
+
[0 1], [16 -3], [ 8 -3]
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
Calculate cusps of arithmetic subgroup defined via permutation group::
|
|
174
|
+
|
|
175
|
+
sage: # needs sage.groups
|
|
176
|
+
sage: L = SymmetricGroup(4)('(1, 2, 3)')
|
|
177
|
+
sage: R = SymmetricGroup(4)('(1, 2, 4)')
|
|
178
|
+
sage: FareySymbol(ArithmeticSubgroup_Permutation(L, R)).cusps()
|
|
179
|
+
[-1, Infinity]
|
|
180
|
+
|
|
181
|
+
Calculate the left coset representation of `\Gamma_H(8, [3])`::
|
|
182
|
+
|
|
183
|
+
sage: FareySymbol(GammaH(8, [3])).coset_reps()
|
|
184
|
+
[
|
|
185
|
+
[1 0] [ 4 -1] [ 3 -1] [ 2 -1] [ 1 -1] [ 3 -1] [ 2 -1] [-1 0]
|
|
186
|
+
[0 1], [ 1 0], [ 1 0], [ 1 0], [ 1 0], [ 4 -1], [ 3 -1], [ 3 -1],
|
|
187
|
+
[ 1 -1] [-1 0] [ 0 -1] [-1 0]
|
|
188
|
+
[ 2 -1], [ 2 -1], [ 1 -1], [ 1 -1]
|
|
189
|
+
]
|
|
190
|
+
"""
|
|
191
|
+
cdef cpp_farey *this_ptr
|
|
192
|
+
cdef object group
|
|
193
|
+
|
|
194
|
+
def __cinit__(self, group, data=None):
|
|
195
|
+
r"""
|
|
196
|
+
Initialize FareySymbol::
|
|
197
|
+
|
|
198
|
+
sage: FareySymbol(Gamma0(23))
|
|
199
|
+
FareySymbol(Congruence Subgroup Gamma0(23))
|
|
200
|
+
"""
|
|
201
|
+
self.group = group
|
|
202
|
+
# if data is present we want to restore
|
|
203
|
+
if data is not None:
|
|
204
|
+
sig_on()
|
|
205
|
+
self.this_ptr = new cpp_farey(data)
|
|
206
|
+
sig_off()
|
|
207
|
+
return
|
|
208
|
+
# to accelerate the calculation of the FareySymbol
|
|
209
|
+
# we implement the tests for the standard congruence groups
|
|
210
|
+
# in the c++ module. For a general group the test if an element
|
|
211
|
+
# of SL2Z is in the group the python __contains__ attribute
|
|
212
|
+
# of the group is called
|
|
213
|
+
cdef int p
|
|
214
|
+
if hasattr(group, "level"):
|
|
215
|
+
p = group.level()
|
|
216
|
+
if group == SL2Z:
|
|
217
|
+
sig_on()
|
|
218
|
+
self.this_ptr = new cpp_farey()
|
|
219
|
+
sig_off()
|
|
220
|
+
elif isinstance(group, Gamma0_class):
|
|
221
|
+
sig_on()
|
|
222
|
+
self.this_ptr = new cpp_farey(group, new is_element_Gamma0(p))
|
|
223
|
+
sig_off()
|
|
224
|
+
elif isinstance(group, Gamma1_class):
|
|
225
|
+
sig_on()
|
|
226
|
+
self.this_ptr = new cpp_farey(group, new is_element_Gamma1(p))
|
|
227
|
+
sig_off()
|
|
228
|
+
elif isinstance(group, Gamma_class):
|
|
229
|
+
sig_on()
|
|
230
|
+
self.this_ptr = new cpp_farey(group, new is_element_Gamma(p))
|
|
231
|
+
sig_off()
|
|
232
|
+
elif isinstance(group, GammaH_class):
|
|
233
|
+
sig_on()
|
|
234
|
+
l = group._GammaH_class__H
|
|
235
|
+
self.this_ptr = new cpp_farey(group, new is_element_GammaH(p, l))
|
|
236
|
+
sig_off()
|
|
237
|
+
else:
|
|
238
|
+
sig_on()
|
|
239
|
+
self.this_ptr = new cpp_farey(group)
|
|
240
|
+
sig_off()
|
|
241
|
+
|
|
242
|
+
def __dealloc__(self):
|
|
243
|
+
r"""
|
|
244
|
+
Remove reference to FareySymbol.
|
|
245
|
+
|
|
246
|
+
TESTS::
|
|
247
|
+
|
|
248
|
+
sage: F = FareySymbol(Gamma0(23))
|
|
249
|
+
sage: del F
|
|
250
|
+
"""
|
|
251
|
+
del self.this_ptr
|
|
252
|
+
|
|
253
|
+
@cached_method
|
|
254
|
+
def pairing_matrices_to_tietze_index(self):
|
|
255
|
+
r"""
|
|
256
|
+
Obtain the translation table from pairing matrices
|
|
257
|
+
to generators.
|
|
258
|
+
|
|
259
|
+
The result is cached.
|
|
260
|
+
|
|
261
|
+
OUTPUT:
|
|
262
|
+
|
|
263
|
+
a list where the `i`-th entry is a nonzero integer `k`,
|
|
264
|
+
such that if `k > 0` then the `i`-th pairing matrix is (up to sign)
|
|
265
|
+
the `(k-1)`-th generator and, if `k < 0`, then the `i`-th pairing
|
|
266
|
+
matrix is (up to sign) the inverse of the `(-k-1)`-th generator.
|
|
267
|
+
|
|
268
|
+
EXAMPLES::
|
|
269
|
+
|
|
270
|
+
sage: F = Gamma0(40).farey_symbol()
|
|
271
|
+
sage: table = F.pairing_matrices_to_tietze_index()
|
|
272
|
+
sage: table[12]
|
|
273
|
+
(-2, -1)
|
|
274
|
+
sage: F.pairing_matrices()[12]
|
|
275
|
+
[ 3 -1]
|
|
276
|
+
[ 40 -13]
|
|
277
|
+
sage: F.generators()[1]**-1
|
|
278
|
+
[ -3 1]
|
|
279
|
+
[-40 13]
|
|
280
|
+
"""
|
|
281
|
+
gens_dict = {g: i+1 for i, g in enumerate(self.generators())}
|
|
282
|
+
ans = []
|
|
283
|
+
for pm in self.pairing_matrices():
|
|
284
|
+
a, b, c, d = pm.matrix().list()
|
|
285
|
+
newval = gens_dict.get(SL2Z([a, b, c, d]))
|
|
286
|
+
if newval is not None:
|
|
287
|
+
ans.append((newval, 1))
|
|
288
|
+
continue
|
|
289
|
+
newval = gens_dict.get(SL2Z([-a, -b, -c, -d]))
|
|
290
|
+
if newval is not None:
|
|
291
|
+
ans.append((newval, -1))
|
|
292
|
+
continue
|
|
293
|
+
newval = gens_dict.get(SL2Z([d, -b, -c, a]))
|
|
294
|
+
if newval is not None:
|
|
295
|
+
ans.append((-newval, 1))
|
|
296
|
+
continue
|
|
297
|
+
newval = gens_dict.get(SL2Z([-d, b, c, -a]))
|
|
298
|
+
if newval is not None:
|
|
299
|
+
ans.append((-newval, -1))
|
|
300
|
+
continue
|
|
301
|
+
raise RuntimeError("This should have not happened")
|
|
302
|
+
return ans
|
|
303
|
+
|
|
304
|
+
@cached_method
|
|
305
|
+
def _get_minus_one(self):
|
|
306
|
+
r"""
|
|
307
|
+
If -I belongs to ``self``, return a Tietze word representing it.
|
|
308
|
+
Otherwise return ``[]``.
|
|
309
|
+
|
|
310
|
+
EXAMPLES::
|
|
311
|
+
|
|
312
|
+
sage: Gamma1(30).farey_symbol()._get_minus_one()
|
|
313
|
+
[]
|
|
314
|
+
sage: G = Gamma0(30).farey_symbol()
|
|
315
|
+
sage: G._get_minus_one()
|
|
316
|
+
[14]
|
|
317
|
+
sage: g = G.generators()[13]
|
|
318
|
+
sage: (-g.matrix()).is_one()
|
|
319
|
+
True
|
|
320
|
+
sage: G = Gamma(1).farey_symbol()
|
|
321
|
+
sage: G._get_minus_one()
|
|
322
|
+
[1, 1]
|
|
323
|
+
sage: g = G.generators()[0]**2
|
|
324
|
+
sage: (-g.matrix()).is_one()
|
|
325
|
+
True
|
|
326
|
+
sage: G = Gamma0(3).farey_symbol()
|
|
327
|
+
sage: G._get_minus_one()
|
|
328
|
+
[2, 2, 2]
|
|
329
|
+
sage: g = G.generators()[1]**3
|
|
330
|
+
sage: (-g.matrix()).is_one()
|
|
331
|
+
True
|
|
332
|
+
"""
|
|
333
|
+
for i, g in enumerate(self.generators()):
|
|
334
|
+
m = g.matrix()
|
|
335
|
+
if (-m).is_one():
|
|
336
|
+
return [i + 1]
|
|
337
|
+
t = m.trace()
|
|
338
|
+
if t == 0: # order = 4
|
|
339
|
+
return 2 * [i + 1]
|
|
340
|
+
elif t == 1: # order = 6
|
|
341
|
+
return 3 * [i + 1]
|
|
342
|
+
return []
|
|
343
|
+
|
|
344
|
+
def word_problem(self, M, output='standard', check=True):
|
|
345
|
+
r"""
|
|
346
|
+
Solve the word problem (up to sign) using this Farey symbol.
|
|
347
|
+
|
|
348
|
+
INPUT:
|
|
349
|
+
|
|
350
|
+
- ``M`` -- an element `M` of `\SL_2(\ZZ)`
|
|
351
|
+
|
|
352
|
+
- ``output`` -- (default: ``'standard'``) should be one of
|
|
353
|
+
``'standard'``, ``'syllables'``, ``'gens'``.
|
|
354
|
+
|
|
355
|
+
- ``check`` -- boolean (default: ``True``); whether to check for
|
|
356
|
+
correct input and output
|
|
357
|
+
|
|
358
|
+
OUTPUT:
|
|
359
|
+
|
|
360
|
+
A solution to the word problem for the matrix `M`.
|
|
361
|
+
The format depends on the ``output`` parameter, as follows.
|
|
362
|
+
|
|
363
|
+
- ``'standard'`` returns the so called Tietze representation,
|
|
364
|
+
which consists of a tuple of nonzero integers. A positive
|
|
365
|
+
integer `i` indicates the `i`-th generator (that is,
|
|
366
|
+
``self.generators()[i-1]``), while a negative integer `i`
|
|
367
|
+
indicates the inverse of the `i`-th generator.
|
|
368
|
+
- ``'syllables'`` returns a tuple of tuples of the form
|
|
369
|
+
`(i, n)`, where `(i, n)` represents ``self.generators()[i] ^ n``,
|
|
370
|
+
whose product equals `M` up to sign.
|
|
371
|
+
- ``'gens'`` returns a tuple of pairs `(g, n)`, where `g` is a
|
|
372
|
+
matrix and `n` an integer, such that the product of the
|
|
373
|
+
matrices `g^n` equals `M` up to sign.
|
|
374
|
+
|
|
375
|
+
EXAMPLES::
|
|
376
|
+
|
|
377
|
+
sage: F = Gamma0(30).farey_symbol()
|
|
378
|
+
sage: gens = F.generators()
|
|
379
|
+
sage: g = gens[3] * gens[10] * gens[8]^-1 * gens[5]
|
|
380
|
+
sage: g
|
|
381
|
+
[-628597 73008]
|
|
382
|
+
[-692130 80387]
|
|
383
|
+
sage: F.word_problem(g)
|
|
384
|
+
(4, 11, -9, 6)
|
|
385
|
+
sage: g = gens[3] * gens[10]^2 * gens[8]^-1 * gens[5]
|
|
386
|
+
sage: g
|
|
387
|
+
[-5048053 586303]
|
|
388
|
+
[-5558280 645563]
|
|
389
|
+
sage: F.word_problem(g, output='gens')
|
|
390
|
+
((
|
|
391
|
+
[109 -10]
|
|
392
|
+
[120 -11], 1
|
|
393
|
+
),
|
|
394
|
+
(
|
|
395
|
+
[ 19 -7]
|
|
396
|
+
[ 30 -11], 2
|
|
397
|
+
),
|
|
398
|
+
(
|
|
399
|
+
[ 49 -9]
|
|
400
|
+
[ 60 -11], -1
|
|
401
|
+
),
|
|
402
|
+
(
|
|
403
|
+
[17 -2]
|
|
404
|
+
[60 -7], 1
|
|
405
|
+
))
|
|
406
|
+
sage: F.word_problem(g, output='syllables')
|
|
407
|
+
((3, 1), (10, 2), (8, -1), (5, 1))
|
|
408
|
+
|
|
409
|
+
TESTS:
|
|
410
|
+
|
|
411
|
+
Check that problem with forgotten generator is fixed::
|
|
412
|
+
|
|
413
|
+
sage: from sage.misc.misc_c import prod
|
|
414
|
+
sage: G = Gamma0(10)
|
|
415
|
+
sage: F = G.farey_symbol()
|
|
416
|
+
sage: g = G([-701,-137,4600,899])
|
|
417
|
+
sage: g1 = prod(F.generators()[i]**a for i, a in F.word_problem(g, output='syllables'))
|
|
418
|
+
sage: g == g1
|
|
419
|
+
True
|
|
420
|
+
|
|
421
|
+
Check that it works for GammaH as well (:issue:`19660`)::
|
|
422
|
+
|
|
423
|
+
sage: G = GammaH(147, [8])
|
|
424
|
+
sage: G.farey_symbol().word_problem(G([1,1,0,1]))
|
|
425
|
+
(1,)
|
|
426
|
+
|
|
427
|
+
Check that :issue:`20347` is solved::
|
|
428
|
+
|
|
429
|
+
sage: # needs sage.groups
|
|
430
|
+
sage: from sage.misc.misc_c import prod
|
|
431
|
+
sage: G = ArithmeticSubgroup_Permutation(S2="(1,2)(3,4)", S3="(1,2,3)")
|
|
432
|
+
sage: S = G.farey_symbol()
|
|
433
|
+
sage: g1, g2 = S.generators()
|
|
434
|
+
sage: g = g1^3 * g2^-2 * g1 * g2
|
|
435
|
+
sage: S.word_problem(g)
|
|
436
|
+
(2, 2, 2, 1, 1, 1, 2, 1, 2)
|
|
437
|
+
sage: h = prod(S.generators()[i]**a for i, a in S.word_problem(g, output='syllables'))
|
|
438
|
+
sage: g == h
|
|
439
|
+
True
|
|
440
|
+
|
|
441
|
+
"""
|
|
442
|
+
if output not in ['standard', 'syllables', 'gens']:
|
|
443
|
+
raise ValueError('Unrecognized output format')
|
|
444
|
+
if check:
|
|
445
|
+
if M not in self.group:
|
|
446
|
+
raise ValueError("Matrix ( %s ) is not in group ( %s )" % (M, self.group))
|
|
447
|
+
cdef Integer a = M.d()
|
|
448
|
+
cdef Integer b = -M.b()
|
|
449
|
+
cdef Integer c = -M.c()
|
|
450
|
+
cdef Integer d = M.a()
|
|
451
|
+
cdef cpp_SL2Z *cpp_beta = new cpp_SL2Z(1, 0, 0, 1)
|
|
452
|
+
sig_on()
|
|
453
|
+
result = self.this_ptr.word_problem(a.value, b.value, c.value, d.value, cpp_beta)
|
|
454
|
+
sig_off()
|
|
455
|
+
beta = convert_to_SL2Z(cpp_beta[0])**-1
|
|
456
|
+
mbeta = SL2Z([-beta.a(), -beta.b(), -beta.c(), -beta.d()])
|
|
457
|
+
V = self.pairing_matrices_to_tietze_index()
|
|
458
|
+
sgn = 1
|
|
459
|
+
tietze = []
|
|
460
|
+
for o in result:
|
|
461
|
+
if o > 0:
|
|
462
|
+
tietze.append(V[o-1][0])
|
|
463
|
+
sgn *= V[o-1][1]
|
|
464
|
+
else:
|
|
465
|
+
tietze.append(-V[-o-1][0])
|
|
466
|
+
sgn *= V[-o-1][1]
|
|
467
|
+
if sgn == -1:
|
|
468
|
+
beta, mbeta = mbeta, beta
|
|
469
|
+
|
|
470
|
+
gens_dict = {g: i+1 for i, g in enumerate(self.generators())}
|
|
471
|
+
extra_tietze = []
|
|
472
|
+
if beta.is_one():
|
|
473
|
+
found = True
|
|
474
|
+
elif mbeta.is_one():
|
|
475
|
+
found = True
|
|
476
|
+
extra_tietze = self._get_minus_one()
|
|
477
|
+
else:
|
|
478
|
+
found = False
|
|
479
|
+
if not found:
|
|
480
|
+
newval = gens_dict.get(beta)
|
|
481
|
+
if newval is not None:
|
|
482
|
+
found = True
|
|
483
|
+
extra_tietze = [newval]
|
|
484
|
+
if not found:
|
|
485
|
+
newval = gens_dict.get(beta**-1)
|
|
486
|
+
if newval is not None:
|
|
487
|
+
found = True
|
|
488
|
+
extra_tietze = [-newval]
|
|
489
|
+
if not found:
|
|
490
|
+
newval = gens_dict.get(mbeta)
|
|
491
|
+
if newval is not None:
|
|
492
|
+
found = True
|
|
493
|
+
extra_tietze = [newval] + self._get_minus_one()
|
|
494
|
+
if not found:
|
|
495
|
+
newval = gens_dict.get(mbeta**-1)
|
|
496
|
+
if newval is not None:
|
|
497
|
+
found = True
|
|
498
|
+
extra_tietze = [-newval] + self._get_minus_one()
|
|
499
|
+
tietze.extend(extra_tietze)
|
|
500
|
+
tietze.reverse()
|
|
501
|
+
gens = self.generators()
|
|
502
|
+
if check:
|
|
503
|
+
tmp = SL2Z([1, 0, 0, 1])
|
|
504
|
+
for i in range(len(tietze)):
|
|
505
|
+
t = tietze[i]
|
|
506
|
+
tmp = tmp * gens[t-1] if t > 0 else tmp * gens[-t-1]**-1
|
|
507
|
+
assert tmp.matrix() == M.matrix(), '%s %s %s' % (tietze, tmp.matrix(), M.matrix())
|
|
508
|
+
if output == 'standard':
|
|
509
|
+
return tuple(tietze)
|
|
510
|
+
if output == 'syllables':
|
|
511
|
+
return tuple((a-1, len(list(g))) if a > 0 else (-a-1, -len(list(g))) for a, g in groupby(tietze))
|
|
512
|
+
else: # output == 'gens'
|
|
513
|
+
return tuple((gens[a-1], len(list(g))) if a > 0 else (gens[-a-1], -len(list(g))) for a, g in groupby(tietze))
|
|
514
|
+
|
|
515
|
+
def __contains__(self, M) -> bool:
|
|
516
|
+
r"""
|
|
517
|
+
Test if element is in the arithmetic group of the Farey symbol
|
|
518
|
+
via LLT algorithm.
|
|
519
|
+
|
|
520
|
+
EXAMPLES::
|
|
521
|
+
|
|
522
|
+
sage: SL2Z([0, -1, 1, 0]) in FareySymbol(Gamma0(6))
|
|
523
|
+
False
|
|
524
|
+
|
|
525
|
+
sage: SL2Z([1, 1, 0, 1]) in FareySymbol(Gamma0(6))
|
|
526
|
+
True
|
|
527
|
+
"""
|
|
528
|
+
cdef Integer a = M.a()
|
|
529
|
+
cdef Integer b = M.b()
|
|
530
|
+
cdef Integer c = M.c()
|
|
531
|
+
cdef Integer d = M.d()
|
|
532
|
+
sig_on()
|
|
533
|
+
result = self.this_ptr.is_element(a.value, b.value, c.value, d.value)
|
|
534
|
+
sig_off()
|
|
535
|
+
return result
|
|
536
|
+
|
|
537
|
+
def __richcmp__(self, other, op) -> bool:
|
|
538
|
+
r"""
|
|
539
|
+
Compare ``self`` to ``other``.
|
|
540
|
+
|
|
541
|
+
EXAMPLES::
|
|
542
|
+
|
|
543
|
+
sage: FareySymbol(Gamma(2)) == FareySymbol(Gamma0(7))
|
|
544
|
+
False
|
|
545
|
+
|
|
546
|
+
sage: FareySymbol(Gamma0(23)) == loads(dumps(FareySymbol(Gamma0(23))))
|
|
547
|
+
True
|
|
548
|
+
"""
|
|
549
|
+
if not isinstance(other, Farey):
|
|
550
|
+
return NotImplemented
|
|
551
|
+
|
|
552
|
+
cosetA = self.coset_reps()
|
|
553
|
+
cosetB = other.coset_reps()
|
|
554
|
+
if cosetA != cosetB:
|
|
555
|
+
return richcmp_not_equal(cosetA, cosetB, op)
|
|
556
|
+
|
|
557
|
+
cuspA = self.cusps()
|
|
558
|
+
cuspB = other.cusps()
|
|
559
|
+
if cuspA != cuspB:
|
|
560
|
+
return richcmp_not_equal(cuspA, cuspB, op)
|
|
561
|
+
|
|
562
|
+
return PyObject_RichCompare(self.fractions(), other.fractions(), op)
|
|
563
|
+
|
|
564
|
+
def __reduce__(self):
|
|
565
|
+
r"""
|
|
566
|
+
Serialization for pickling::
|
|
567
|
+
|
|
568
|
+
sage: FareySymbol(Gamma0(4)).__reduce__()
|
|
569
|
+
(<class 'sage.modular.arithgroup.farey_symbol.Farey'>, ...))
|
|
570
|
+
"""
|
|
571
|
+
return Farey, (self.group, self.this_ptr.dumps())
|
|
572
|
+
|
|
573
|
+
def __repr__(self) -> str:
|
|
574
|
+
r"""
|
|
575
|
+
Return the string representation of ``self``.
|
|
576
|
+
|
|
577
|
+
EXAMPLES::
|
|
578
|
+
|
|
579
|
+
sage: FareySymbol(Gamma0(23)).__repr__()
|
|
580
|
+
'FareySymbol(Congruence Subgroup Gamma0(23))'
|
|
581
|
+
"""
|
|
582
|
+
if hasattr(self.group, "_repr_"):
|
|
583
|
+
return "FareySymbol(%s)" % self.group._repr_()
|
|
584
|
+
elif hasattr(self.group, "__repr__"):
|
|
585
|
+
return "FareySymbol(%r)" % self.group
|
|
586
|
+
else:
|
|
587
|
+
return "FareySymbol(?)"
|
|
588
|
+
|
|
589
|
+
def _latex_(self, forced_format=None):
|
|
590
|
+
r"""
|
|
591
|
+
Return the LaTeX representation of ``self``.
|
|
592
|
+
|
|
593
|
+
INPUT:
|
|
594
|
+
|
|
595
|
+
- ``forced_format`` -- a format string ('plain' or 'xymatrix')
|
|
596
|
+
or ``None``
|
|
597
|
+
|
|
598
|
+
EXAMPLES::
|
|
599
|
+
|
|
600
|
+
sage: FareySymbol(Gamma0(11))._latex_(forced_format='plain')
|
|
601
|
+
'\\left( -\\infty\\underbrace{\\quad}_{1} 0\\underbrace{\\quad}_{2} \\frac{1}{3}\\underbrace{\\quad}_{3} \\frac{1}{2}\\underbrace{\\quad}_{2} \\frac{2}{3}\\underbrace{\\quad}_{3} 1\\underbrace{\\quad}_{1} \\infty\\right)'
|
|
602
|
+
sage: FareySymbol(Gamma0(11))._latex_(forced_format='xymatrix')
|
|
603
|
+
'\\begin{xy}\\xymatrix{& -\\infty \\ar@{-}@/_1pc/[r]_{1}& 0 \\ar@{-}@/_1pc/[r]_{2}& \\frac{1}{3} \\ar@{-}@/_1pc/[r]_{3}& \\frac{1}{2} \\ar@{-}@/_1pc/[r]_{2}& \\frac{2}{3} \\ar@{-}@/_1pc/[r]_{3}& 1 \\ar@{-}@/_1pc/[r]_{1}& \\infty }\\end{xy}'
|
|
604
|
+
|
|
605
|
+
sage: 'xymatrix' in FareySymbol(Gamma0(11))._latex_()
|
|
606
|
+
True
|
|
607
|
+
"""
|
|
608
|
+
if forced_format == 'plain':
|
|
609
|
+
# output not using xymatrix
|
|
610
|
+
s = r'\left( -\infty'
|
|
611
|
+
a = [x._latex_() for x in self.fractions()] + [r'\infty']
|
|
612
|
+
b = self.pairings()
|
|
613
|
+
for i in range(len(a)):
|
|
614
|
+
u = b[i]
|
|
615
|
+
if u == -3:
|
|
616
|
+
u = r'\bullet'
|
|
617
|
+
elif u == -2:
|
|
618
|
+
u = r'\circ'
|
|
619
|
+
s += r'\underbrace{\quad}_{%s} %s' % (u, a[i])
|
|
620
|
+
return s + r'\right)'
|
|
621
|
+
else:
|
|
622
|
+
# output using xymatrix
|
|
623
|
+
s = r'\begin{xy}\xymatrix{& -\infty '
|
|
624
|
+
f = [x._latex_() for x in self.fractions()] + [r'\infty']
|
|
625
|
+
f.reverse()
|
|
626
|
+
for p in self.pairings():
|
|
627
|
+
if p >= 0:
|
|
628
|
+
s += r'\ar@{-}@/_1pc/[r]_{%s}' % p
|
|
629
|
+
elif p == -2:
|
|
630
|
+
s += r'\ar@{-}@/_1pc/[r]_{\circ}'
|
|
631
|
+
elif p == -3:
|
|
632
|
+
s += r'\ar@{-}@/_1pc/[r]_{\bullet}'
|
|
633
|
+
s += r'& %s ' % f.pop()
|
|
634
|
+
s += r'}\end{xy}'
|
|
635
|
+
return s
|
|
636
|
+
|
|
637
|
+
def index(self):
|
|
638
|
+
r"""
|
|
639
|
+
Return the index of the arithmetic group of the FareySymbol
|
|
640
|
+
in `\PSL_2(\ZZ)`.
|
|
641
|
+
|
|
642
|
+
EXAMPLES::
|
|
643
|
+
|
|
644
|
+
sage: [FareySymbol(Gamma0(n)).index() for n in range(1, 16)]
|
|
645
|
+
[1, 3, 4, 6, 6, 12, 8, 12, 12, 18, 12, 24, 14, 24, 24]
|
|
646
|
+
"""
|
|
647
|
+
return self.this_ptr.index()
|
|
648
|
+
|
|
649
|
+
def genus(self):
|
|
650
|
+
r"""
|
|
651
|
+
Return the genus of the arithmetic group of the FareySymbol.
|
|
652
|
+
|
|
653
|
+
EXAMPLES::
|
|
654
|
+
|
|
655
|
+
sage: [FareySymbol(Gamma0(n)).genus() for n in range(16, 32)]
|
|
656
|
+
[0, 1, 0, 1, 1, 1, 2, 2, 1, 0, 2, 1, 2, 2, 3, 2]
|
|
657
|
+
"""
|
|
658
|
+
return self.this_ptr.genus()
|
|
659
|
+
|
|
660
|
+
def level(self):
|
|
661
|
+
r"""
|
|
662
|
+
Return the level of the arithmetic group of the FareySymbol.
|
|
663
|
+
|
|
664
|
+
EXAMPLES::
|
|
665
|
+
|
|
666
|
+
sage: [FareySymbol(Gamma0(n)).level() for n in range(1, 16)]
|
|
667
|
+
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
|
668
|
+
"""
|
|
669
|
+
return self.this_ptr.level()
|
|
670
|
+
|
|
671
|
+
def nu2(self):
|
|
672
|
+
r"""
|
|
673
|
+
Return the number of elliptic points of order two.
|
|
674
|
+
|
|
675
|
+
EXAMPLES::
|
|
676
|
+
|
|
677
|
+
sage: [FareySymbol(Gamma0(n)).nu2() for n in range(1, 16)]
|
|
678
|
+
[1, 1, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0]
|
|
679
|
+
"""
|
|
680
|
+
return self.this_ptr.nu2()
|
|
681
|
+
|
|
682
|
+
def nu3(self):
|
|
683
|
+
r"""
|
|
684
|
+
Return the number of elliptic points of order three.
|
|
685
|
+
|
|
686
|
+
EXAMPLES::
|
|
687
|
+
|
|
688
|
+
sage: [FareySymbol(Gamma0(n)).nu3() for n in range(1, 16)]
|
|
689
|
+
[1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0]
|
|
690
|
+
"""
|
|
691
|
+
return self.this_ptr.nu3()
|
|
692
|
+
|
|
693
|
+
def coset_reps(self):
|
|
694
|
+
r"""
|
|
695
|
+
Left coset of the arithmetic group of the FareySymbol.
|
|
696
|
+
|
|
697
|
+
EXAMPLES:
|
|
698
|
+
|
|
699
|
+
Calculate the left coset of `\Gamma_0(6)`::
|
|
700
|
+
|
|
701
|
+
sage: FareySymbol(Gamma0(6)).coset_reps()
|
|
702
|
+
[
|
|
703
|
+
[1 0] [ 3 -1] [ 2 -1] [ 1 -1] [ 2 -1] [ 3 -2] [ 1 -1] [-1 0]
|
|
704
|
+
[0 1], [ 1 0], [ 1 0], [ 1 0], [ 3 -1], [ 2 -1], [ 2 -1], [ 2 -1],
|
|
705
|
+
[ 1 -1] [ 0 -1] [-1 0] [-2 1]
|
|
706
|
+
[ 3 -2], [ 1 -1], [ 1 -1], [ 1 -1]
|
|
707
|
+
]
|
|
708
|
+
"""
|
|
709
|
+
return self.this_ptr.get_coset()
|
|
710
|
+
|
|
711
|
+
def generators(self):
|
|
712
|
+
r"""
|
|
713
|
+
Minimal set of generators of the group of the FareySymbol.
|
|
714
|
+
|
|
715
|
+
EXAMPLES:
|
|
716
|
+
|
|
717
|
+
Calculate the generators of `\Gamma_0(6)`::
|
|
718
|
+
|
|
719
|
+
sage: FareySymbol(Gamma0(6)).generators()
|
|
720
|
+
[
|
|
721
|
+
[1 1] [ 5 -1] [ 7 -3] [-1 0]
|
|
722
|
+
[0 1], [ 6 -1], [12 -5], [ 0 -1]
|
|
723
|
+
]
|
|
724
|
+
|
|
725
|
+
Calculate the generators of `\SL_2(\ZZ)`::
|
|
726
|
+
|
|
727
|
+
sage: FareySymbol(SL2Z).generators()
|
|
728
|
+
[
|
|
729
|
+
[ 0 -1] [ 0 -1]
|
|
730
|
+
[ 1 0], [ 1 -1]
|
|
731
|
+
]
|
|
732
|
+
|
|
733
|
+
The unique index 2 even subgroup and index 4 odd subgroup each get handled correctly::
|
|
734
|
+
|
|
735
|
+
sage: # needs sage.groups
|
|
736
|
+
sage: FareySymbol(ArithmeticSubgroup_Permutation(S2="(1,2)", S3="()")).generators()
|
|
737
|
+
[
|
|
738
|
+
[ 0 1] [-1 1]
|
|
739
|
+
[-1 -1], [-1 0]
|
|
740
|
+
]
|
|
741
|
+
sage: FareySymbol(ArithmeticSubgroup_Permutation(S2="(1,2, 3, 4)", S3="(1,3)(2,4)")).generators()
|
|
742
|
+
[
|
|
743
|
+
[ 0 1] [-1 1]
|
|
744
|
+
[-1 -1], [-1 0]
|
|
745
|
+
]
|
|
746
|
+
"""
|
|
747
|
+
return self.this_ptr.get_generators()
|
|
748
|
+
|
|
749
|
+
def fractions(self):
|
|
750
|
+
r"""
|
|
751
|
+
Fractions of the FareySymbol.
|
|
752
|
+
|
|
753
|
+
EXAMPLES::
|
|
754
|
+
|
|
755
|
+
sage: FareySymbol(Gamma(4)).fractions()
|
|
756
|
+
[0, 1/2, 1, 3/2, 2, 5/2, 3, 7/2, 4]
|
|
757
|
+
"""
|
|
758
|
+
return self.this_ptr.get_fractions()
|
|
759
|
+
|
|
760
|
+
def pairings(self):
|
|
761
|
+
r"""
|
|
762
|
+
Pairings of the sides of the fundamental domain of the Farey symbol
|
|
763
|
+
of the arithmetic group.
|
|
764
|
+
|
|
765
|
+
The sides of the hyperbolic polygon are
|
|
766
|
+
numbered 0, 1, ... from left to right. Conventions: even pairings are
|
|
767
|
+
denoted by -2, odd pairings by -3 while free pairings are denoted by
|
|
768
|
+
an integer number greater than zero.
|
|
769
|
+
|
|
770
|
+
EXAMPLES:
|
|
771
|
+
|
|
772
|
+
Odd pairings::
|
|
773
|
+
|
|
774
|
+
sage: FareySymbol(Gamma0(7)).pairings()
|
|
775
|
+
[1, -3, -3, 1]
|
|
776
|
+
|
|
777
|
+
Even and odd pairings::
|
|
778
|
+
|
|
779
|
+
FareySymbol(Gamma0(13)).pairings()
|
|
780
|
+
[1, -3, -2, -2, -3, 1]
|
|
781
|
+
|
|
782
|
+
Only free pairings::
|
|
783
|
+
|
|
784
|
+
sage: FareySymbol(Gamma0(23)).pairings()
|
|
785
|
+
[1, 2, 3, 5, 3, 4, 2, 4, 5, 1]
|
|
786
|
+
"""
|
|
787
|
+
return self.this_ptr.get_pairings()
|
|
788
|
+
|
|
789
|
+
def paired_sides(self):
|
|
790
|
+
r"""
|
|
791
|
+
Pairs of index of the sides of the fundamental domain of the
|
|
792
|
+
Farey symbol of the arithmetic group. The sides of the
|
|
793
|
+
hyperbolic polygon are numbered 0, 1, ... from left to right.
|
|
794
|
+
|
|
795
|
+
.. image:: ../../../media/pairing.png
|
|
796
|
+
|
|
797
|
+
EXAMPLES::
|
|
798
|
+
|
|
799
|
+
sage: FareySymbol(Gamma0(11)).paired_sides()
|
|
800
|
+
[(0, 5), (1, 3), (2, 4)]
|
|
801
|
+
|
|
802
|
+
indicating that the side 0 is paired with 5, 1 with 3 and 2 with 4.
|
|
803
|
+
"""
|
|
804
|
+
return self.this_ptr.get_paired_sides()
|
|
805
|
+
|
|
806
|
+
def pairing_matrices(self):
|
|
807
|
+
r"""
|
|
808
|
+
Pairing matrices of the sides of the fundamental domain. The sides
|
|
809
|
+
of the hyperbolic polygon are numbered 0, 1, ... from left to right.
|
|
810
|
+
|
|
811
|
+
EXAMPLES::
|
|
812
|
+
|
|
813
|
+
sage: FareySymbol(Gamma0(6)).pairing_matrices()
|
|
814
|
+
[
|
|
815
|
+
[1 1] [ 5 -1] [ 7 -3] [ 5 -3] [ 1 -1] [-1 1]
|
|
816
|
+
[0 1], [ 6 -1], [12 -5], [12 -7], [ 6 -5], [ 0 -1]
|
|
817
|
+
]
|
|
818
|
+
"""
|
|
819
|
+
|
|
820
|
+
return self.this_ptr.get_pairing_matrices()
|
|
821
|
+
|
|
822
|
+
def cusps(self):
|
|
823
|
+
r"""
|
|
824
|
+
Cusps of the FareySymbol.
|
|
825
|
+
|
|
826
|
+
EXAMPLES::
|
|
827
|
+
|
|
828
|
+
sage: FareySymbol(Gamma0(6)).cusps()
|
|
829
|
+
[0, 1/3, 1/2, Infinity]
|
|
830
|
+
"""
|
|
831
|
+
return self.this_ptr.get_cusps()+[Cusp(infinity)]
|
|
832
|
+
|
|
833
|
+
def cusp_widths(self):
|
|
834
|
+
r"""
|
|
835
|
+
Cusps widths of the FareySymbol.
|
|
836
|
+
|
|
837
|
+
EXAMPLES::
|
|
838
|
+
|
|
839
|
+
sage: FareySymbol(Gamma0(6)).cusp_widths()
|
|
840
|
+
[6, 2, 3, 1]
|
|
841
|
+
"""
|
|
842
|
+
return self.this_ptr.get_cusp_widths()
|
|
843
|
+
|
|
844
|
+
def cusp_class(self, c):
|
|
845
|
+
r"""
|
|
846
|
+
Cusp class of a cusp in the FareySymbol.
|
|
847
|
+
|
|
848
|
+
INPUT:
|
|
849
|
+
|
|
850
|
+
- ``c`` -- a cusp
|
|
851
|
+
|
|
852
|
+
EXAMPLES::
|
|
853
|
+
|
|
854
|
+
sage: FareySymbol(Gamma0(12)).cusp_class(Cusp(1, 12))
|
|
855
|
+
5
|
|
856
|
+
"""
|
|
857
|
+
cusp = Cusp(c)
|
|
858
|
+
cdef Integer p = cusp.numerator()
|
|
859
|
+
cdef Integer q = cusp.denominator()
|
|
860
|
+
sig_on()
|
|
861
|
+
result = self.this_ptr.get_cusp_class(p.value, q.value)
|
|
862
|
+
sig_off()
|
|
863
|
+
return result
|
|
864
|
+
|
|
865
|
+
def reduce_to_cusp(self, r):
|
|
866
|
+
r"""
|
|
867
|
+
Transformation of a rational number to cusp representative.
|
|
868
|
+
|
|
869
|
+
INPUT:
|
|
870
|
+
|
|
871
|
+
- ``r`` -- a rational number
|
|
872
|
+
|
|
873
|
+
EXAMPLES::
|
|
874
|
+
|
|
875
|
+
sage: FareySymbol(Gamma0(12)).reduce_to_cusp(5/8)
|
|
876
|
+
[ 5 -3]
|
|
877
|
+
[12 -7]
|
|
878
|
+
|
|
879
|
+
Reduce 11/17 to a cusp of for HsuExample10()::
|
|
880
|
+
|
|
881
|
+
sage: # needs sage.groups
|
|
882
|
+
sage: from sage.modular.arithgroup.arithgroup_perm import HsuExample10
|
|
883
|
+
sage: f = FareySymbol(HsuExample10())
|
|
884
|
+
sage: f.reduce_to_cusp(11/17)
|
|
885
|
+
[14 -9]
|
|
886
|
+
[-3 2]
|
|
887
|
+
sage: _.acton(11/17)
|
|
888
|
+
1
|
|
889
|
+
sage: f.cusps()[f.cusp_class(11/17)]
|
|
890
|
+
1
|
|
891
|
+
"""
|
|
892
|
+
cdef Integer p = r.numerator()
|
|
893
|
+
cdef Integer q = r.denominator()
|
|
894
|
+
sig_on()
|
|
895
|
+
result = self.this_ptr.get_transformation_to_cusp(p.value, q.value)
|
|
896
|
+
sig_off()
|
|
897
|
+
return result
|
|
898
|
+
|
|
899
|
+
@options(alpha=1, fill=True, thickness=1, color='lightgray',
|
|
900
|
+
color_even='white',
|
|
901
|
+
zorder=2, linestyle='solid', show_pairing=True,
|
|
902
|
+
tesselation='Dedekind', ymax=1)
|
|
903
|
+
def fundamental_domain(self, **options):
|
|
904
|
+
r"""
|
|
905
|
+
Plot a fundamental domain of an arithmetic subgroup of
|
|
906
|
+
`\PSL_2(\ZZ)` corresponding to the Farey symbol.
|
|
907
|
+
|
|
908
|
+
OPTIONS:
|
|
909
|
+
|
|
910
|
+
- ``fill`` -- boolean (default: ``True``); fill the fundamental domain
|
|
911
|
+
|
|
912
|
+
- ``linestyle`` -- string (default: ``'solid'``); the style of the line,
|
|
913
|
+
which is one of 'dashed', 'dotted', 'solid', 'dashdot', or '--',
|
|
914
|
+
':', '-', '-.', respectively
|
|
915
|
+
|
|
916
|
+
- ``color`` -- (default: ``'lightgray'``) fill color for odd part of
|
|
917
|
+
Dedekind tesselation
|
|
918
|
+
|
|
919
|
+
- ``show_pairing`` -- boolean (default: ``True``); flag for pairing
|
|
920
|
+
|
|
921
|
+
- ``tesselation`` -- (default: ``'Dedekind'``) the type of
|
|
922
|
+
hyperbolic tesselation which is one of
|
|
923
|
+
``'coset'``, ``'Dedekind'`` or ``None`` respectively
|
|
924
|
+
|
|
925
|
+
- ``color_even`` -- fill color for even parts of Dedekind
|
|
926
|
+
tesselation (default: ``'white'``); ignored for other tesselations
|
|
927
|
+
|
|
928
|
+
- ``thickness`` -- float (default: `1`) the thickness of the line
|
|
929
|
+
|
|
930
|
+
- ``ymax`` -- float (default: `1`) maximal height
|
|
931
|
+
|
|
932
|
+
EXAMPLES:
|
|
933
|
+
|
|
934
|
+
For example, to plot the fundamental domain of `\Gamma_0(11)`
|
|
935
|
+
with pairings use the following command::
|
|
936
|
+
|
|
937
|
+
sage: FareySymbol(Gamma0(11)).fundamental_domain() # needs sage.plot sage.symbolic
|
|
938
|
+
Graphics object consisting of 54 graphics primitives
|
|
939
|
+
|
|
940
|
+
indicating that side 1 is paired with side 3 and side 2 is
|
|
941
|
+
paired with side 4, see also :meth:`.paired_sides`.
|
|
942
|
+
|
|
943
|
+
To plot the fundamental domain of `\Gamma(3)` without pairings
|
|
944
|
+
use the following command::
|
|
945
|
+
|
|
946
|
+
sage: FareySymbol(Gamma(3)).fundamental_domain(show_pairing=False) # needs sage.plot sage.symbolic
|
|
947
|
+
Graphics object consisting of 48 graphics primitives
|
|
948
|
+
|
|
949
|
+
Plot the fundamental domain of `\Gamma_0(23)` showing the left
|
|
950
|
+
coset representatives::
|
|
951
|
+
|
|
952
|
+
sage: FareySymbol(Gamma0(23)).fundamental_domain(tesselation='coset') # needs sage.plot sage.symbolic
|
|
953
|
+
Graphics object consisting of 58 graphics primitives
|
|
954
|
+
|
|
955
|
+
The same as above but with a custom linestyle::
|
|
956
|
+
|
|
957
|
+
sage: FareySymbol(Gamma0(23)).fundamental_domain(tesselation='coset', # needs sage.plot sage.symbolic
|
|
958
|
+
....: linestyle=':',
|
|
959
|
+
....: thickness='2')
|
|
960
|
+
Graphics object consisting of 58 graphics primitives
|
|
961
|
+
"""
|
|
962
|
+
from sage.plot.graphics import Graphics
|
|
963
|
+
from sage.plot.colors import rainbow
|
|
964
|
+
from sage.plot.hyperbolic_arc import hyperbolic_arc
|
|
965
|
+
from sage.plot.hyperbolic_polygon import hyperbolic_triangle
|
|
966
|
+
|
|
967
|
+
I = CC(0, 1)
|
|
968
|
+
w = RR(3).sqrt()
|
|
969
|
+
L = 1000
|
|
970
|
+
g = Graphics()
|
|
971
|
+
# show coset
|
|
972
|
+
for x in self.coset_reps():
|
|
973
|
+
a, b, c, d = x[1, 1], -x[0, 1], -x[1, 0], x[0, 0]
|
|
974
|
+
A, B = CC(0, L), CC(0, L)
|
|
975
|
+
if d != 0:
|
|
976
|
+
A = b / d
|
|
977
|
+
if c != 0:
|
|
978
|
+
B = a / c
|
|
979
|
+
C = (a*c+b*d+(a*d+b*c)/2+I*w/2)/(c*c+c*d+d*d)
|
|
980
|
+
D = (a*c+b*d + CC(0, 1))/(c*c+d*d)
|
|
981
|
+
if options['tesselation'] == 'Dedekind':
|
|
982
|
+
g += hyperbolic_triangle(A, D, C,
|
|
983
|
+
alpha=options['alpha'],
|
|
984
|
+
color=options['color'],
|
|
985
|
+
fill=options['fill'],
|
|
986
|
+
linestyle=options['linestyle'],
|
|
987
|
+
thickness=options['thickness'])
|
|
988
|
+
g += hyperbolic_triangle(D, C, B,
|
|
989
|
+
alpha=options['alpha'],
|
|
990
|
+
color=options['color_even'],
|
|
991
|
+
fill=options['fill'],
|
|
992
|
+
linestyle=options['linestyle'],
|
|
993
|
+
thickness=options['thickness'])
|
|
994
|
+
g += hyperbolic_triangle(A, D, C, color='gray')
|
|
995
|
+
g += hyperbolic_triangle(D, C, B, color='gray')
|
|
996
|
+
elif options['tesselation'] == 'coset':
|
|
997
|
+
g += hyperbolic_triangle(A, B, C,
|
|
998
|
+
alpha=options['alpha'],
|
|
999
|
+
color=options['color'],
|
|
1000
|
+
fill=options['fill'],
|
|
1001
|
+
linestyle=options['linestyle'],
|
|
1002
|
+
thickness=options['thickness'])
|
|
1003
|
+
g += hyperbolic_triangle(A, B, C, color='gray',
|
|
1004
|
+
linestyle=options['linestyle'],
|
|
1005
|
+
thickness=options['thickness'])
|
|
1006
|
+
else:
|
|
1007
|
+
g += hyperbolic_triangle(A, B, C,
|
|
1008
|
+
alpha=options['alpha'],
|
|
1009
|
+
color=options['color'],
|
|
1010
|
+
fill=options['fill'],
|
|
1011
|
+
linestyle=options['linestyle'],
|
|
1012
|
+
thickness=options['thickness'])
|
|
1013
|
+
# show pairings
|
|
1014
|
+
p = self.pairings()
|
|
1015
|
+
x = self.fractions()
|
|
1016
|
+
if options['show_pairing']:
|
|
1017
|
+
rc = rainbow(max(p)-min(p)+1)
|
|
1018
|
+
if p[0] > 0:
|
|
1019
|
+
g += hyperbolic_arc(CC(0, L), x[0], color=rc[p[0]-min(p)],
|
|
1020
|
+
linestyle=options['linestyle'],
|
|
1021
|
+
thickness=options['thickness'])
|
|
1022
|
+
if p[-1] > 0:
|
|
1023
|
+
g += hyperbolic_arc(CC(0, L), x[-1], color=rc[p[-1]-min(p)],
|
|
1024
|
+
linestyle=options['linestyle'],
|
|
1025
|
+
thickness=options['thickness'])
|
|
1026
|
+
for i in range(len(x)-1):
|
|
1027
|
+
if p[i+1] > 0:
|
|
1028
|
+
g += hyperbolic_arc(x[i], x[i+1], color=rc[p[i+1]-min(p)],
|
|
1029
|
+
linestyle=options['linestyle'],
|
|
1030
|
+
thickness=options['thickness'])
|
|
1031
|
+
d = g.get_minmax_data()
|
|
1032
|
+
g.set_axes_range(d['xmin'], d['xmax'], 0, options['ymax'])
|
|
1033
|
+
g.set_aspect_ratio(1)
|
|
1034
|
+
return g
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
# ----- conversions ---------------------------------
|
|
1038
|
+
|
|
1039
|
+
cdef public long convert_to_long(n) noexcept:
|
|
1040
|
+
cdef long m = n
|
|
1041
|
+
return m
|
|
1042
|
+
|
|
1043
|
+
cdef public object convert_to_Integer(mpz_class a):
|
|
1044
|
+
A = Integer()
|
|
1045
|
+
A.set_from_mpz(a.get_mpz_t())
|
|
1046
|
+
return A
|
|
1047
|
+
|
|
1048
|
+
cdef public object convert_to_rational(mpq_class r):
|
|
1049
|
+
a = Integer()
|
|
1050
|
+
a.set_from_mpz(r.get_num_mpz_t())
|
|
1051
|
+
b = Integer()
|
|
1052
|
+
b.set_from_mpz(r.get_den_mpz_t())
|
|
1053
|
+
return a/b
|
|
1054
|
+
|
|
1055
|
+
cdef public object convert_to_cusp(mpq_class r):
|
|
1056
|
+
a = Integer()
|
|
1057
|
+
a.set_from_mpz(r.get_num_mpz_t())
|
|
1058
|
+
b = Integer()
|
|
1059
|
+
b.set_from_mpz(r.get_den_mpz_t())
|
|
1060
|
+
return Cusp(a/b)
|
|
1061
|
+
|
|
1062
|
+
cdef public object convert_to_SL2Z(cpp_SL2Z M):
|
|
1063
|
+
a = convert_to_Integer(M.a())
|
|
1064
|
+
b = convert_to_Integer(M.b())
|
|
1065
|
+
c = convert_to_Integer(M.c())
|
|
1066
|
+
d = convert_to_Integer(M.d())
|
|
1067
|
+
return SL2Z([a, b, c, d])
|