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,1426 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# sage.doctest: needs sage.libs.gap
|
|
3
|
+
r"""
|
|
4
|
+
Hecke triangle groups
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
- Jonas Jermann (2013): initial version
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# ****************************************************************************
|
|
12
|
+
# Copyright (C) 2013-2014 Jonas Jermann <jjermann2@gmail.com>
|
|
13
|
+
#
|
|
14
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
15
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
16
|
+
# the License, or (at your option) any later version.
|
|
17
|
+
# https://www.gnu.org/licenses/
|
|
18
|
+
# ****************************************************************************
|
|
19
|
+
|
|
20
|
+
from sage.arith.misc import divisors
|
|
21
|
+
from sage.groups.matrix_gps.finitely_generated import FinitelyGeneratedMatrixGroup_generic
|
|
22
|
+
from sage.matrix.constructor import matrix
|
|
23
|
+
from sage.misc.cachefunc import cached_method
|
|
24
|
+
from sage.misc.latex import latex
|
|
25
|
+
from sage.misc.lazy_import import lazy_import
|
|
26
|
+
from sage.misc.misc_c import prod
|
|
27
|
+
from sage.rings.infinity import infinity
|
|
28
|
+
from sage.rings.integer_ring import ZZ
|
|
29
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
30
|
+
from sage.rings.rational_field import QQ
|
|
31
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
32
|
+
|
|
33
|
+
lazy_import("sage.functions.log", "exp")
|
|
34
|
+
lazy_import("sage.functions.gamma", "psi1")
|
|
35
|
+
lazy_import("sage.functions.trig", "sec")
|
|
36
|
+
lazy_import("sage.rings.number_field.number_field", "NumberField")
|
|
37
|
+
lazy_import("sage.rings.qqbar", ["AA", "AlgebraicField"])
|
|
38
|
+
lazy_import("sage.rings.universal_cyclotomic_field", "E")
|
|
39
|
+
lazy_import("sage.symbolic.constants", "pi")
|
|
40
|
+
|
|
41
|
+
from .hecke_triangle_group_element import HeckeTriangleGroupElement, cyclic_representative, coerce_AA
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class HeckeTriangleGroup(FinitelyGeneratedMatrixGroup_generic,
|
|
45
|
+
UniqueRepresentation):
|
|
46
|
+
r"""
|
|
47
|
+
Hecke triangle group `(2, n, \infty)`.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
Element = HeckeTriangleGroupElement
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def __classcall__(cls, n=3):
|
|
54
|
+
r"""
|
|
55
|
+
Return a (cached) instance with canonical parameters.
|
|
56
|
+
|
|
57
|
+
EXAMPLES::
|
|
58
|
+
|
|
59
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
60
|
+
sage: HeckeTriangleGroup(QQ(3)) == HeckeTriangleGroup(int(3))
|
|
61
|
+
True
|
|
62
|
+
"""
|
|
63
|
+
if n == infinity:
|
|
64
|
+
n = infinity
|
|
65
|
+
else:
|
|
66
|
+
n = ZZ(n)
|
|
67
|
+
if n < 3:
|
|
68
|
+
raise AttributeError("n has to be infinity or an Integer >= 3.")
|
|
69
|
+
|
|
70
|
+
return super().__classcall__(cls, n)
|
|
71
|
+
|
|
72
|
+
def __init__(self, n):
|
|
73
|
+
r"""
|
|
74
|
+
Hecke triangle group (2, n, infinity).
|
|
75
|
+
|
|
76
|
+
Namely the von Dyck group corresponding to the triangle group
|
|
77
|
+
with angles (pi/2, pi/n, 0).
|
|
78
|
+
|
|
79
|
+
INPUT:
|
|
80
|
+
|
|
81
|
+
- ``n`` -- ``infinity`` or an integer greater or equal to `3`
|
|
82
|
+
|
|
83
|
+
OUTPUT: the Hecke triangle group for the given parameter `n`
|
|
84
|
+
|
|
85
|
+
EXAMPLES::
|
|
86
|
+
|
|
87
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
88
|
+
sage: G = HeckeTriangleGroup(12)
|
|
89
|
+
sage: G
|
|
90
|
+
Hecke triangle group for n = 12
|
|
91
|
+
sage: G.category()
|
|
92
|
+
Category of groups
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
self._n = n
|
|
96
|
+
self.element_repr_method("default")
|
|
97
|
+
|
|
98
|
+
if n in [3, infinity]:
|
|
99
|
+
self._base_ring = ZZ
|
|
100
|
+
self._lam = ZZ.one() if n == 3 else ZZ(2)
|
|
101
|
+
else:
|
|
102
|
+
lam_symbolic = coerce_AA(E(2 * n) + ~E(2 * n))
|
|
103
|
+
K = NumberField(self.lam_minpoly(), 'lam',
|
|
104
|
+
embedding=lam_symbolic)
|
|
105
|
+
# self._base_ring = K.order(K.gens())
|
|
106
|
+
self._base_ring = K.maximal_order()
|
|
107
|
+
self._lam = self._base_ring.gen(1)
|
|
108
|
+
|
|
109
|
+
T = matrix(self._base_ring, [[1, self._lam], [0, 1]])
|
|
110
|
+
S = matrix(self._base_ring, [[0, -1], [1, 0]])
|
|
111
|
+
|
|
112
|
+
FinitelyGeneratedMatrixGroup_generic.__init__(self, ZZ(2), self._base_ring, [S, T])
|
|
113
|
+
|
|
114
|
+
def _repr_(self):
|
|
115
|
+
r"""
|
|
116
|
+
Return the string representation of ``self``.
|
|
117
|
+
|
|
118
|
+
EXAMPLES::
|
|
119
|
+
|
|
120
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
121
|
+
sage: HeckeTriangleGroup(10)
|
|
122
|
+
Hecke triangle group for n = 10
|
|
123
|
+
"""
|
|
124
|
+
return f"Hecke triangle group for n = {self._n}"
|
|
125
|
+
|
|
126
|
+
def _latex_(self):
|
|
127
|
+
r"""
|
|
128
|
+
Return the LaTeX representation of ``self``.
|
|
129
|
+
|
|
130
|
+
EXAMPLES::
|
|
131
|
+
|
|
132
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
133
|
+
sage: a = HeckeTriangleGroup(5)
|
|
134
|
+
sage: latex(a)
|
|
135
|
+
\Gamma^{(5)}
|
|
136
|
+
"""
|
|
137
|
+
return '\\Gamma^{(%s)}' % latex(self._n)
|
|
138
|
+
|
|
139
|
+
def element_repr_method(self, method=None):
|
|
140
|
+
r"""
|
|
141
|
+
Either return or set the representation method for elements of ``self``.
|
|
142
|
+
|
|
143
|
+
INPUT:
|
|
144
|
+
|
|
145
|
+
- ``method`` -- if ``method=None`` (default) the current default
|
|
146
|
+
representation method is returned. Otherwise the default method is
|
|
147
|
+
set to ``method``. If ``method`` is not available a
|
|
148
|
+
:exc:`ValueError` is raised. Possible methods are:
|
|
149
|
+
|
|
150
|
+
- ``default``: use the usual representation method for matrix group
|
|
151
|
+
elements
|
|
152
|
+
|
|
153
|
+
- ``basic``: the representation is given as a word in ``S`` and
|
|
154
|
+
powers of ``T``
|
|
155
|
+
|
|
156
|
+
- ``conj``: the conjugacy representative of the element is
|
|
157
|
+
represented as a word in powers of the basic blocks, together with
|
|
158
|
+
an unspecified conjugation matrix
|
|
159
|
+
|
|
160
|
+
- ``block``: same as ``conj`` but the conjugation matrix is
|
|
161
|
+
specified as well
|
|
162
|
+
|
|
163
|
+
EXAMPLES::
|
|
164
|
+
|
|
165
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
166
|
+
sage: G = HeckeTriangleGroup(5)
|
|
167
|
+
sage: G.element_repr_method()
|
|
168
|
+
'default'
|
|
169
|
+
sage: G.element_repr_method("basic")
|
|
170
|
+
sage: G.element_repr_method()
|
|
171
|
+
'basic'
|
|
172
|
+
"""
|
|
173
|
+
if method is None:
|
|
174
|
+
return self._element_repr_method
|
|
175
|
+
elif method in ["default", "basic", "block", "conj"]:
|
|
176
|
+
self._element_repr_method = method
|
|
177
|
+
else:
|
|
178
|
+
raise ValueError(f"the specified method {method} is not supported")
|
|
179
|
+
|
|
180
|
+
def one(self):
|
|
181
|
+
r"""
|
|
182
|
+
Return the identity element/matrix for ``self``.
|
|
183
|
+
|
|
184
|
+
EXAMPLES::
|
|
185
|
+
|
|
186
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
187
|
+
sage: G = HeckeTriangleGroup(10)
|
|
188
|
+
sage: G(1) == G.one()
|
|
189
|
+
True
|
|
190
|
+
sage: G(1)
|
|
191
|
+
[1 0]
|
|
192
|
+
[0 1]
|
|
193
|
+
|
|
194
|
+
sage: G(1).parent()
|
|
195
|
+
Hecke triangle group for n = 10
|
|
196
|
+
"""
|
|
197
|
+
return self.I()
|
|
198
|
+
|
|
199
|
+
def lam_minpoly(self):
|
|
200
|
+
r"""
|
|
201
|
+
Return the minimal polynomial of the corresponding lambda parameter of ``self``.
|
|
202
|
+
|
|
203
|
+
EXAMPLES::
|
|
204
|
+
|
|
205
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
206
|
+
sage: HeckeTriangleGroup(10).lam_minpoly()
|
|
207
|
+
x^4 - 5*x^2 + 5
|
|
208
|
+
sage: HeckeTriangleGroup(17).lam_minpoly()
|
|
209
|
+
x^8 - x^7 - 7*x^6 + 6*x^5 + 15*x^4 - 10*x^3 - 10*x^2 + 4*x + 1
|
|
210
|
+
sage: HeckeTriangleGroup(infinity).lam_minpoly()
|
|
211
|
+
x - 2
|
|
212
|
+
"""
|
|
213
|
+
# TODO: Write an explicit (faster) implementation
|
|
214
|
+
n = self._n
|
|
215
|
+
if n == infinity:
|
|
216
|
+
lam_symbolic = QQ(2)
|
|
217
|
+
else:
|
|
218
|
+
lam_symbolic = E(2 * n) + ~E(2 * n)
|
|
219
|
+
return lam_symbolic.minpoly()
|
|
220
|
+
|
|
221
|
+
def base_ring(self):
|
|
222
|
+
r"""
|
|
223
|
+
Return the base ring of ``self``.
|
|
224
|
+
|
|
225
|
+
EXAMPLES::
|
|
226
|
+
|
|
227
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
228
|
+
sage: HeckeTriangleGroup(n=infinity).base_ring()
|
|
229
|
+
Integer Ring
|
|
230
|
+
sage: HeckeTriangleGroup(n=7).base_ring()
|
|
231
|
+
Maximal Order generated by lam in Number Field in lam with defining polynomial x^3 - x^2 - 2*x + 1 with lam = 1.801937735804839?
|
|
232
|
+
"""
|
|
233
|
+
return self._base_ring
|
|
234
|
+
|
|
235
|
+
def base_field(self):
|
|
236
|
+
r"""
|
|
237
|
+
Return the base field of ``self``.
|
|
238
|
+
|
|
239
|
+
EXAMPLES::
|
|
240
|
+
|
|
241
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
242
|
+
sage: HeckeTriangleGroup(n=infinity).base_field()
|
|
243
|
+
Rational Field
|
|
244
|
+
sage: HeckeTriangleGroup(n=7).base_field()
|
|
245
|
+
Number Field in lam with defining polynomial x^3 - x^2 - 2*x + 1 with lam = 1.801937735804839?
|
|
246
|
+
"""
|
|
247
|
+
if self._n in [3, infinity]:
|
|
248
|
+
return QQ
|
|
249
|
+
else:
|
|
250
|
+
return self._base_ring.number_field()
|
|
251
|
+
|
|
252
|
+
def n(self):
|
|
253
|
+
r"""
|
|
254
|
+
Return the parameter ``n`` of ``self``, where
|
|
255
|
+
``pi/n`` is the angle at ``rho`` of the corresponding
|
|
256
|
+
basic hyperbolic triangle with vertices ``i``, ``rho``
|
|
257
|
+
and ``infinity``.
|
|
258
|
+
|
|
259
|
+
EXAMPLES::
|
|
260
|
+
|
|
261
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
262
|
+
sage: HeckeTriangleGroup(10).n()
|
|
263
|
+
10
|
|
264
|
+
sage: HeckeTriangleGroup(infinity).n()
|
|
265
|
+
+Infinity
|
|
266
|
+
"""
|
|
267
|
+
return self._n
|
|
268
|
+
|
|
269
|
+
def lam(self):
|
|
270
|
+
r"""
|
|
271
|
+
Return the parameter ``lambda`` of ``self``,
|
|
272
|
+
where ``lambda`` is twice the real part of ``rho``,
|
|
273
|
+
lying between ``1`` (when ``n=3``) and ``2`` (when ``n=infinity``).
|
|
274
|
+
|
|
275
|
+
EXAMPLES::
|
|
276
|
+
|
|
277
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
278
|
+
sage: HeckeTriangleGroup(3).lam()
|
|
279
|
+
1
|
|
280
|
+
sage: HeckeTriangleGroup(4).lam()
|
|
281
|
+
lam
|
|
282
|
+
sage: HeckeTriangleGroup(4).lam()^2
|
|
283
|
+
2
|
|
284
|
+
sage: HeckeTriangleGroup(6).lam()^2
|
|
285
|
+
3
|
|
286
|
+
sage: AA(HeckeTriangleGroup(10).lam())
|
|
287
|
+
1.9021130325903...?
|
|
288
|
+
sage: HeckeTriangleGroup(infinity).lam()
|
|
289
|
+
2
|
|
290
|
+
"""
|
|
291
|
+
return self._lam
|
|
292
|
+
|
|
293
|
+
def rho(self):
|
|
294
|
+
r"""
|
|
295
|
+
Return the vertex ``rho`` of the basic hyperbolic
|
|
296
|
+
triangle which describes ``self``. ``rho`` has
|
|
297
|
+
absolute value 1 and angle ``pi/n``.
|
|
298
|
+
|
|
299
|
+
EXAMPLES::
|
|
300
|
+
|
|
301
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
302
|
+
sage: HeckeTriangleGroup(3).rho() == QQbar(1/2 + sqrt(3)/2*i)
|
|
303
|
+
True
|
|
304
|
+
sage: HeckeTriangleGroup(4).rho() == QQbar(sqrt(2)/2*(1 + i))
|
|
305
|
+
True
|
|
306
|
+
sage: HeckeTriangleGroup(6).rho() == QQbar(sqrt(3)/2 + 1/2*i)
|
|
307
|
+
True
|
|
308
|
+
sage: HeckeTriangleGroup(10).rho()
|
|
309
|
+
0.95105651629515...? + 0.30901699437494...?*I
|
|
310
|
+
sage: HeckeTriangleGroup(infinity).rho()
|
|
311
|
+
1
|
|
312
|
+
"""
|
|
313
|
+
# TODO: maybe rho should be replaced by -rhobar
|
|
314
|
+
# Also we could use NumberFields...
|
|
315
|
+
if self._n == infinity:
|
|
316
|
+
return AA.one()
|
|
317
|
+
else:
|
|
318
|
+
rho = AlgebraicField()(E(2 * self._n))
|
|
319
|
+
rho.simplify()
|
|
320
|
+
return rho
|
|
321
|
+
|
|
322
|
+
def alpha(self):
|
|
323
|
+
r"""
|
|
324
|
+
Return the parameter ``alpha`` of ``self``.
|
|
325
|
+
|
|
326
|
+
This is the first parameter of the hypergeometric series used
|
|
327
|
+
in the calculation of the Hauptmodul of ``self``.
|
|
328
|
+
|
|
329
|
+
EXAMPLES::
|
|
330
|
+
|
|
331
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
332
|
+
sage: HeckeTriangleGroup(3).alpha()
|
|
333
|
+
1/12
|
|
334
|
+
sage: HeckeTriangleGroup(4).alpha()
|
|
335
|
+
1/8
|
|
336
|
+
sage: HeckeTriangleGroup(5).alpha()
|
|
337
|
+
3/20
|
|
338
|
+
sage: HeckeTriangleGroup(6).alpha()
|
|
339
|
+
1/6
|
|
340
|
+
sage: HeckeTriangleGroup(10).alpha()
|
|
341
|
+
1/5
|
|
342
|
+
sage: HeckeTriangleGroup(infinity).alpha()
|
|
343
|
+
1/4
|
|
344
|
+
"""
|
|
345
|
+
return QQ((1, 2)) * (QQ((1, 2)) - ZZ.one() / self._n)
|
|
346
|
+
|
|
347
|
+
def beta(self):
|
|
348
|
+
r"""
|
|
349
|
+
Return the parameter ``beta`` of ``self``.
|
|
350
|
+
|
|
351
|
+
This is the second parameter of the hypergeometric series used
|
|
352
|
+
in the calculation of the Hauptmodul of ``self``.
|
|
353
|
+
|
|
354
|
+
EXAMPLES::
|
|
355
|
+
|
|
356
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
357
|
+
sage: HeckeTriangleGroup(3).beta()
|
|
358
|
+
5/12
|
|
359
|
+
sage: HeckeTriangleGroup(4).beta()
|
|
360
|
+
3/8
|
|
361
|
+
sage: HeckeTriangleGroup(5).beta()
|
|
362
|
+
7/20
|
|
363
|
+
sage: HeckeTriangleGroup(6).beta()
|
|
364
|
+
1/3
|
|
365
|
+
sage: HeckeTriangleGroup(10).beta()
|
|
366
|
+
3/10
|
|
367
|
+
sage: HeckeTriangleGroup(infinity).beta()
|
|
368
|
+
1/4
|
|
369
|
+
"""
|
|
370
|
+
return QQ((1, 2)) * (QQ((1, 2)) + ZZ.one() / self._n)
|
|
371
|
+
|
|
372
|
+
# We use cached method here to create unique instances of basic matrices
|
|
373
|
+
# (major performance gain)
|
|
374
|
+
@cached_method
|
|
375
|
+
def I(self):
|
|
376
|
+
r"""
|
|
377
|
+
Return the identity element/matrix for ``self``.
|
|
378
|
+
|
|
379
|
+
EXAMPLES::
|
|
380
|
+
|
|
381
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
382
|
+
sage: HeckeTriangleGroup(10).I()
|
|
383
|
+
[1 0]
|
|
384
|
+
[0 1]
|
|
385
|
+
|
|
386
|
+
sage: HeckeTriangleGroup(10).I().parent()
|
|
387
|
+
Hecke triangle group for n = 10
|
|
388
|
+
"""
|
|
389
|
+
return self(matrix(self._base_ring, [[1, 0], [0, 1]]), check=False)
|
|
390
|
+
|
|
391
|
+
# We use cached method here to create unique instances of basic matrices
|
|
392
|
+
# (major performance gain)
|
|
393
|
+
@cached_method
|
|
394
|
+
def T(self, m=1):
|
|
395
|
+
r"""
|
|
396
|
+
Return the element in ``self`` corresponding to the translation by
|
|
397
|
+
``m*self.lam()``.
|
|
398
|
+
|
|
399
|
+
INPUT:
|
|
400
|
+
|
|
401
|
+
- ``m`` -- integer (default: 1); namely the second generator of
|
|
402
|
+
``self``
|
|
403
|
+
|
|
404
|
+
EXAMPLES::
|
|
405
|
+
|
|
406
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
407
|
+
sage: HeckeTriangleGroup(3).T()
|
|
408
|
+
[1 1]
|
|
409
|
+
[0 1]
|
|
410
|
+
sage: HeckeTriangleGroup(10).T(-4)
|
|
411
|
+
[ 1 -4*lam]
|
|
412
|
+
[ 0 1]
|
|
413
|
+
sage: HeckeTriangleGroup(10).T().parent()
|
|
414
|
+
Hecke triangle group for n = 10
|
|
415
|
+
"""
|
|
416
|
+
return self(matrix(self._base_ring, [[1, self._lam * m], [0, 1]]),
|
|
417
|
+
check=False)
|
|
418
|
+
|
|
419
|
+
# We use cached method here to create unique instances of basic matrices
|
|
420
|
+
# (major performance gain)
|
|
421
|
+
@cached_method
|
|
422
|
+
def S(self):
|
|
423
|
+
r"""
|
|
424
|
+
Return the generator of ``self`` corresponding to the
|
|
425
|
+
conformal circle inversion.
|
|
426
|
+
|
|
427
|
+
EXAMPLES::
|
|
428
|
+
|
|
429
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
430
|
+
sage: HeckeTriangleGroup(3).S()
|
|
431
|
+
[ 0 -1]
|
|
432
|
+
[ 1 0]
|
|
433
|
+
sage: HeckeTriangleGroup(10).S()
|
|
434
|
+
[ 0 -1]
|
|
435
|
+
[ 1 0]
|
|
436
|
+
sage: HeckeTriangleGroup(10).S()^2 == -HeckeTriangleGroup(10).I()
|
|
437
|
+
True
|
|
438
|
+
sage: HeckeTriangleGroup(10).S()^4 == HeckeTriangleGroup(10).I()
|
|
439
|
+
True
|
|
440
|
+
|
|
441
|
+
sage: HeckeTriangleGroup(10).S().parent()
|
|
442
|
+
Hecke triangle group for n = 10
|
|
443
|
+
"""
|
|
444
|
+
return self.gen(0)
|
|
445
|
+
|
|
446
|
+
# We use cached method here to create unique instances of basic matrices
|
|
447
|
+
# (major performance gain)
|
|
448
|
+
@cached_method
|
|
449
|
+
def U(self):
|
|
450
|
+
r"""
|
|
451
|
+
Return an alternative generator of ``self`` instead of ``T``.
|
|
452
|
+
``U`` stabilizes ``rho`` and has order ``2*self.n()``.
|
|
453
|
+
|
|
454
|
+
If ``n=infinity`` then ``U`` is parabolic and has infinite order,
|
|
455
|
+
it then fixes the cusp ``[-1]``.
|
|
456
|
+
|
|
457
|
+
EXAMPLES::
|
|
458
|
+
|
|
459
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
460
|
+
sage: HeckeTriangleGroup(3).U()
|
|
461
|
+
[ 1 -1]
|
|
462
|
+
[ 1 0]
|
|
463
|
+
sage: HeckeTriangleGroup(3).U()^3 == -HeckeTriangleGroup(3).I()
|
|
464
|
+
True
|
|
465
|
+
sage: HeckeTriangleGroup(3).U()^6 == HeckeTriangleGroup(3).I()
|
|
466
|
+
True
|
|
467
|
+
sage: HeckeTriangleGroup(10).U()
|
|
468
|
+
[lam -1]
|
|
469
|
+
[ 1 0]
|
|
470
|
+
sage: HeckeTriangleGroup(10).U()^10 == -HeckeTriangleGroup(10).I()
|
|
471
|
+
True
|
|
472
|
+
sage: HeckeTriangleGroup(10).U()^20 == HeckeTriangleGroup(10).I()
|
|
473
|
+
True
|
|
474
|
+
|
|
475
|
+
sage: HeckeTriangleGroup(10).U().parent()
|
|
476
|
+
Hecke triangle group for n = 10
|
|
477
|
+
"""
|
|
478
|
+
return self.T() * self.S()
|
|
479
|
+
|
|
480
|
+
def V(self, j):
|
|
481
|
+
r"""
|
|
482
|
+
Return the j'th generator for the usual representatives of
|
|
483
|
+
conjugacy classes of ``self``. It is given by ``V=U^(j-1)*T``.
|
|
484
|
+
|
|
485
|
+
INPUT:
|
|
486
|
+
|
|
487
|
+
- ``j`` --integer; to get the usual representatives
|
|
488
|
+
``j`` should range from ``1`` to ``self.n()-1``
|
|
489
|
+
|
|
490
|
+
OUTPUT: the corresponding matrix/element
|
|
491
|
+
|
|
492
|
+
The matrix is parabolic if ``j`` is congruent to `\pm 1` modulo ``self.n()``.
|
|
493
|
+
It is elliptic if ``j`` is congruent to 0 modulo ``self.n()``.
|
|
494
|
+
It is hyperbolic otherwise.
|
|
495
|
+
|
|
496
|
+
EXAMPLES::
|
|
497
|
+
|
|
498
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
499
|
+
sage: G = HeckeTriangleGroup(3)
|
|
500
|
+
sage: G.V(0) == -G.S()
|
|
501
|
+
True
|
|
502
|
+
sage: G.V(1) == G.T()
|
|
503
|
+
True
|
|
504
|
+
sage: G.V(2)
|
|
505
|
+
[1 0]
|
|
506
|
+
[1 1]
|
|
507
|
+
sage: G.V(3) == G.S()
|
|
508
|
+
True
|
|
509
|
+
|
|
510
|
+
sage: G = HeckeTriangleGroup(5)
|
|
511
|
+
sage: G.element_repr_method("default")
|
|
512
|
+
sage: G.V(1)
|
|
513
|
+
[ 1 lam]
|
|
514
|
+
[ 0 1]
|
|
515
|
+
sage: G.V(2)
|
|
516
|
+
[lam lam]
|
|
517
|
+
[ 1 lam]
|
|
518
|
+
sage: G.V(3)
|
|
519
|
+
[lam 1]
|
|
520
|
+
[lam lam]
|
|
521
|
+
sage: G.V(4)
|
|
522
|
+
[ 1 0]
|
|
523
|
+
[lam 1]
|
|
524
|
+
sage: G.V(5) == G.S()
|
|
525
|
+
True
|
|
526
|
+
"""
|
|
527
|
+
return self.U()**(j-1) * self.T()
|
|
528
|
+
|
|
529
|
+
def dvalue(self):
|
|
530
|
+
r"""
|
|
531
|
+
Return a symbolic expression (or an exact value in case n=3, 4, 6)
|
|
532
|
+
for the transfinite diameter (or capacity) of ``self``.
|
|
533
|
+
|
|
534
|
+
This is the first nontrivial Fourier coefficient of the Hauptmodul
|
|
535
|
+
for the Hecke triangle group in case it is normalized to ``J_inv(i)=1``.
|
|
536
|
+
|
|
537
|
+
EXAMPLES::
|
|
538
|
+
|
|
539
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
540
|
+
sage: HeckeTriangleGroup(3).dvalue()
|
|
541
|
+
1/1728
|
|
542
|
+
sage: HeckeTriangleGroup(4).dvalue()
|
|
543
|
+
1/256
|
|
544
|
+
sage: HeckeTriangleGroup(5).dvalue()
|
|
545
|
+
e^(2*euler_gamma - 4*pi/(sqrt(5) + 1) + psi(17/20) + psi(13/20))
|
|
546
|
+
sage: HeckeTriangleGroup(6).dvalue()
|
|
547
|
+
1/108
|
|
548
|
+
sage: HeckeTriangleGroup(10).dvalue()
|
|
549
|
+
e^(2*euler_gamma - 4*pi/sqrt(2*sqrt(5) + 10) + psi(4/5) + psi(7/10))
|
|
550
|
+
sage: HeckeTriangleGroup(infinity).dvalue()
|
|
551
|
+
1/64
|
|
552
|
+
"""
|
|
553
|
+
n = self._n
|
|
554
|
+
if n == 3:
|
|
555
|
+
return 1 / ZZ(2**6*3**3)
|
|
556
|
+
if n == 4:
|
|
557
|
+
return 1 / ZZ(2**8)
|
|
558
|
+
if n == 6:
|
|
559
|
+
return 1 / ZZ(2**2*3**3)
|
|
560
|
+
if n == infinity:
|
|
561
|
+
return 1 / ZZ(2**6)
|
|
562
|
+
# reference for this formula ?
|
|
563
|
+
return exp(-ZZ(2)*psi1(ZZ.one()) + psi1(ZZ.one()-self.alpha())
|
|
564
|
+
+ psi1(ZZ.one()-self.beta()) - pi*sec(pi/self._n))
|
|
565
|
+
|
|
566
|
+
def is_arithmetic(self) -> bool:
|
|
567
|
+
r"""
|
|
568
|
+
Return ``True`` if ``self`` is an arithmetic subgroup.
|
|
569
|
+
|
|
570
|
+
EXAMPLES::
|
|
571
|
+
|
|
572
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
573
|
+
sage: HeckeTriangleGroup(3).is_arithmetic()
|
|
574
|
+
True
|
|
575
|
+
sage: HeckeTriangleGroup(4).is_arithmetic()
|
|
576
|
+
True
|
|
577
|
+
sage: HeckeTriangleGroup(5).is_arithmetic()
|
|
578
|
+
False
|
|
579
|
+
sage: HeckeTriangleGroup(6).is_arithmetic()
|
|
580
|
+
True
|
|
581
|
+
sage: HeckeTriangleGroup(10).is_arithmetic()
|
|
582
|
+
False
|
|
583
|
+
sage: HeckeTriangleGroup(infinity).is_arithmetic()
|
|
584
|
+
True
|
|
585
|
+
"""
|
|
586
|
+
return self._n in [ZZ(3), ZZ(4), ZZ(6), infinity]
|
|
587
|
+
|
|
588
|
+
def get_FD(self, z):
|
|
589
|
+
r"""
|
|
590
|
+
Return a tuple (A,w) which determines how to map ``z``
|
|
591
|
+
to the usual (strict) fundamental domain of ``self``.
|
|
592
|
+
|
|
593
|
+
INPUT:
|
|
594
|
+
|
|
595
|
+
- ``z`` -- a complex number or an element of AlgebraicField()
|
|
596
|
+
|
|
597
|
+
OUTPUT:
|
|
598
|
+
|
|
599
|
+
A tuple ``(A, w)``.
|
|
600
|
+
|
|
601
|
+
- ``A`` -- a matrix in ``self`` such that ``A.acton(w)==z``
|
|
602
|
+
(if ``z`` is exact at least)
|
|
603
|
+
|
|
604
|
+
- ``w`` -- a complex number or an element of AlgebraicField()
|
|
605
|
+
(depending on the type ``z``) which lies inside the (strict)
|
|
606
|
+
fundamental domain of ``self`` (``self.in_FD(w)==True``) and
|
|
607
|
+
which is equivalent to ``z`` (by the above property)
|
|
608
|
+
|
|
609
|
+
EXAMPLES::
|
|
610
|
+
|
|
611
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
612
|
+
sage: G = HeckeTriangleGroup(8)
|
|
613
|
+
sage: z = AlgebraicField()(1+i/2)
|
|
614
|
+
sage: A, w = G.get_FD(z)
|
|
615
|
+
sage: A
|
|
616
|
+
[-lam 1]
|
|
617
|
+
[ -1 0]
|
|
618
|
+
sage: A.acton(w) == z
|
|
619
|
+
True
|
|
620
|
+
|
|
621
|
+
sage: from sage.modular.modform_hecketriangle.space import ModularForms
|
|
622
|
+
sage: z = (134.12 + 0.22*i).n()
|
|
623
|
+
sage: A, w = G.get_FD(z)
|
|
624
|
+
sage: A
|
|
625
|
+
[-73*lam^3 + 74*lam 73*lam^2 - 1]
|
|
626
|
+
[ -lam^2 + 1 lam]
|
|
627
|
+
sage: w
|
|
628
|
+
0.769070776942... + 0.779859114103...*I
|
|
629
|
+
sage: z
|
|
630
|
+
134.120000000... + 0.220000000000...*I
|
|
631
|
+
sage: A.acton(w)
|
|
632
|
+
134.1200000... + 0.2200000000...*I
|
|
633
|
+
"""
|
|
634
|
+
ID = self.I()
|
|
635
|
+
T = self.T()
|
|
636
|
+
S = self.S()
|
|
637
|
+
TI = self.T(-1)
|
|
638
|
+
|
|
639
|
+
A = ID
|
|
640
|
+
w = z
|
|
641
|
+
while abs(w) < ZZ.one() or abs(w.real()) > self.lam() / ZZ(2):
|
|
642
|
+
if abs(w) < ZZ.one():
|
|
643
|
+
w = self.S().acton(w)
|
|
644
|
+
A = S*A
|
|
645
|
+
while w.real() >= self.lam() / ZZ(2):
|
|
646
|
+
w = TI.acton(w)
|
|
647
|
+
A = TI*A
|
|
648
|
+
while w.real() < -self.lam() / ZZ(2):
|
|
649
|
+
w = T.acton(w)
|
|
650
|
+
A = T*A
|
|
651
|
+
if w.real() == self.lam() / ZZ(2):
|
|
652
|
+
w = TI.acton(w)
|
|
653
|
+
A = TI*A
|
|
654
|
+
if abs(w) == ZZ.one() and w.real() > ZZ.zero():
|
|
655
|
+
w = S.acton(w)
|
|
656
|
+
A = S*A
|
|
657
|
+
|
|
658
|
+
AI = A.inverse()
|
|
659
|
+
|
|
660
|
+
return (AI, A.acton(z))
|
|
661
|
+
|
|
662
|
+
def in_FD(self, z) -> bool:
|
|
663
|
+
r"""
|
|
664
|
+
Return ``True`` if ``z`` lies in the (strict) fundamental
|
|
665
|
+
domain of ``self``.
|
|
666
|
+
|
|
667
|
+
EXAMPLES::
|
|
668
|
+
|
|
669
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
670
|
+
sage: HeckeTriangleGroup(5).in_FD(CC(1.5/2 + 0.9*i))
|
|
671
|
+
True
|
|
672
|
+
sage: HeckeTriangleGroup(4).in_FD(CC(1.5/2 + 0.9*i))
|
|
673
|
+
False
|
|
674
|
+
"""
|
|
675
|
+
return self.get_FD(z)[0] == self.I()
|
|
676
|
+
|
|
677
|
+
def root_extension_field(self, D):
|
|
678
|
+
r"""
|
|
679
|
+
Return the quadratic extension field of the base field by
|
|
680
|
+
the square root of the given discriminant ``D``.
|
|
681
|
+
|
|
682
|
+
INPUT:
|
|
683
|
+
|
|
684
|
+
- ``D`` -- an element of the base ring of ``self``
|
|
685
|
+
corresponding to a discriminant
|
|
686
|
+
|
|
687
|
+
OUTPUT:
|
|
688
|
+
|
|
689
|
+
A relative (at most quadratic) extension to the base field
|
|
690
|
+
of ``self`` in the variable ``e`` which corresponds to ``sqrt(D)``.
|
|
691
|
+
If the extension degree is ``1`` then the base field is returned.
|
|
692
|
+
|
|
693
|
+
The correct embedding is the positive resp. positive imaginary one.
|
|
694
|
+
Unfortunately no default embedding can be specified for relative
|
|
695
|
+
number fields yet.
|
|
696
|
+
|
|
697
|
+
EXAMPLES::
|
|
698
|
+
|
|
699
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
700
|
+
sage: G = HeckeTriangleGroup(n=infinity)
|
|
701
|
+
sage: G.root_extension_field(32)
|
|
702
|
+
Number Field in e with defining polynomial x^2 - 32
|
|
703
|
+
sage: G.root_extension_field(-4)
|
|
704
|
+
Number Field in e with defining polynomial x^2 + 4
|
|
705
|
+
sage: G.root_extension_field(4) == G.base_field()
|
|
706
|
+
True
|
|
707
|
+
|
|
708
|
+
sage: G = HeckeTriangleGroup(n=7)
|
|
709
|
+
sage: lam = G.lam()
|
|
710
|
+
sage: D = 4*lam^2 + 4*lam - 4
|
|
711
|
+
sage: G.root_extension_field(D)
|
|
712
|
+
Number Field in e with defining polynomial x^2 - 4*lam^2 - 4*lam + 4 over its base field
|
|
713
|
+
sage: G.root_extension_field(4) == G.base_field()
|
|
714
|
+
True
|
|
715
|
+
sage: D = lam^2 - 4
|
|
716
|
+
sage: G.root_extension_field(D)
|
|
717
|
+
Number Field in e with defining polynomial x^2 - lam^2 + 4 over its base field
|
|
718
|
+
"""
|
|
719
|
+
K = self.base_field()
|
|
720
|
+
x = PolynomialRing(K, 'x').gen()
|
|
721
|
+
D = self.base_ring()(D)
|
|
722
|
+
|
|
723
|
+
if D.is_square():
|
|
724
|
+
return K
|
|
725
|
+
else:
|
|
726
|
+
# unfortunately we can't set embeddings for relative extensions :-(
|
|
727
|
+
# return K.extension(x**2 - D, 'e', embedding=AA(D).sqrt())
|
|
728
|
+
|
|
729
|
+
L = K.extension(x**2 - D, 'e')
|
|
730
|
+
|
|
731
|
+
# e = AA(D).sqrt()
|
|
732
|
+
# emb = L.hom([e])
|
|
733
|
+
# L._unset_embedding()
|
|
734
|
+
# L.register_embedding(emb)
|
|
735
|
+
|
|
736
|
+
# return NumberField(L.absolute_polynomial(), 'e', structure=AbsoluteFromRelative(L), embedding=(???))
|
|
737
|
+
return L
|
|
738
|
+
|
|
739
|
+
# We cache this method for performance reasons (it is repeatedly reused)
|
|
740
|
+
@cached_method
|
|
741
|
+
def root_extension_embedding(self, D, K=None):
|
|
742
|
+
r"""
|
|
743
|
+
Return the correct embedding from the root extension field
|
|
744
|
+
of the given discriminant ``D`` to the field ``K``.
|
|
745
|
+
|
|
746
|
+
Also see the method ``root_extension_embedding(K)`` of
|
|
747
|
+
``HeckeTriangleGroupElement`` for more examples.
|
|
748
|
+
|
|
749
|
+
INPUT:
|
|
750
|
+
|
|
751
|
+
- ``D`` -- an element of the base ring of ``self``
|
|
752
|
+
corresponding to a discriminant
|
|
753
|
+
|
|
754
|
+
- ``K`` -- a field to which we want the (correct) embedding;
|
|
755
|
+
if ``K=None`` (default) then ``AlgebraicField()`` is
|
|
756
|
+
used for positive ``D`` and ``AlgebraicRealField()``
|
|
757
|
+
otherwise
|
|
758
|
+
|
|
759
|
+
OUTPUT:
|
|
760
|
+
|
|
761
|
+
The corresponding embedding if it was found.
|
|
762
|
+
Otherwise a :exc:`ValueError` is raised.
|
|
763
|
+
|
|
764
|
+
EXAMPLES::
|
|
765
|
+
|
|
766
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
767
|
+
sage: G = HeckeTriangleGroup(n=infinity)
|
|
768
|
+
sage: G.root_extension_embedding(32)
|
|
769
|
+
Ring morphism:
|
|
770
|
+
From: Number Field in e with defining polynomial x^2 - 32
|
|
771
|
+
To: Algebraic Real Field
|
|
772
|
+
Defn: e |--> 5.656854249492...?
|
|
773
|
+
sage: G.root_extension_embedding(-4)
|
|
774
|
+
Ring morphism:
|
|
775
|
+
From: Number Field in e with defining polynomial x^2 + 4
|
|
776
|
+
To: Algebraic Field
|
|
777
|
+
Defn: e |--> 2*I
|
|
778
|
+
sage: G.root_extension_embedding(4)
|
|
779
|
+
Coercion map:
|
|
780
|
+
From: Rational Field
|
|
781
|
+
To: Algebraic Real Field
|
|
782
|
+
|
|
783
|
+
sage: G = HeckeTriangleGroup(n=7)
|
|
784
|
+
sage: lam = G.lam()
|
|
785
|
+
sage: D = 4*lam^2 + 4*lam - 4
|
|
786
|
+
sage: G.root_extension_embedding(D, CC)
|
|
787
|
+
Relative number field morphism:
|
|
788
|
+
From: Number Field in e with defining polynomial x^2 - 4*lam^2 - 4*lam + 4 over its base field
|
|
789
|
+
To: Complex Field with 53 bits of precision
|
|
790
|
+
Defn: e |--> 4.02438434522...
|
|
791
|
+
lam |--> 1.80193773580...
|
|
792
|
+
sage: D = lam^2 - 4
|
|
793
|
+
sage: G.root_extension_embedding(D)
|
|
794
|
+
Relative number field morphism:
|
|
795
|
+
From: Number Field in e with defining polynomial x^2 - lam^2 + 4 over its base field
|
|
796
|
+
To: Algebraic Field
|
|
797
|
+
Defn: e |--> 0.?... + 0.867767478235...?*I
|
|
798
|
+
lam |--> 1.801937735804...?
|
|
799
|
+
"""
|
|
800
|
+
D = self.base_ring()(D)
|
|
801
|
+
F = self.root_extension_field(D)
|
|
802
|
+
if K is None:
|
|
803
|
+
if coerce_AA(D) > 0:
|
|
804
|
+
K = AA
|
|
805
|
+
else:
|
|
806
|
+
K = AlgebraicField()
|
|
807
|
+
|
|
808
|
+
L = list(F.embeddings(K))
|
|
809
|
+
|
|
810
|
+
# Three possibilities up to numerical artefacts:
|
|
811
|
+
# (1) emb = e, purely imaginary
|
|
812
|
+
# (2) emb = e or lam (can't distinguish), purely real
|
|
813
|
+
# (3) emb = (e,lam), e purely imaginary, lam purely real
|
|
814
|
+
# (4) emb = (e,lam), e purely real, lam purely real
|
|
815
|
+
# There always exists one emb with "e" positive resp. positive imaginary
|
|
816
|
+
# and if there is a lam there exists a positive one...
|
|
817
|
+
#
|
|
818
|
+
# Criteria to pick the correct "maximum":
|
|
819
|
+
# 1. First figure out if e resp. lam is purely real or imaginary
|
|
820
|
+
# (using "abs(e.imag()) > abs(e.real())")
|
|
821
|
+
# 2. In the purely imaginary case we don't want anything negative imaginary
|
|
822
|
+
# and we know the positive case is unique after sorting lam
|
|
823
|
+
# 3. For the remaining cases we want the biggest real part
|
|
824
|
+
# (and lam should get comparison priority)
|
|
825
|
+
def emb_key(emb):
|
|
826
|
+
L = []
|
|
827
|
+
gens_len = len(emb.im_gens())
|
|
828
|
+
for k in range(gens_len):
|
|
829
|
+
a = emb.im_gens()[k]
|
|
830
|
+
try:
|
|
831
|
+
a.simplify()
|
|
832
|
+
a.exactify()
|
|
833
|
+
except AttributeError:
|
|
834
|
+
pass
|
|
835
|
+
# If a is purely imaginary:
|
|
836
|
+
if abs(a.imag()) > abs(a.real()):
|
|
837
|
+
if a.imag() < 0:
|
|
838
|
+
a = -infinity
|
|
839
|
+
else:
|
|
840
|
+
a = ZZ(0)
|
|
841
|
+
else:
|
|
842
|
+
a = a.real()
|
|
843
|
+
|
|
844
|
+
L.append(a)
|
|
845
|
+
|
|
846
|
+
L.reverse()
|
|
847
|
+
return L
|
|
848
|
+
|
|
849
|
+
if len(L) > 1:
|
|
850
|
+
L.sort(key=emb_key)
|
|
851
|
+
return L[-1]
|
|
852
|
+
|
|
853
|
+
def _elliptic_conj_reps(self):
|
|
854
|
+
r"""
|
|
855
|
+
Store all elliptic conjugacy representatives in the
|
|
856
|
+
internal dictionary. This is a helper function
|
|
857
|
+
used by :meth:`_conjugacy_representatives`.
|
|
858
|
+
|
|
859
|
+
EXAMPLES::
|
|
860
|
+
|
|
861
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
862
|
+
sage: G = HeckeTriangleGroup(n=5)
|
|
863
|
+
sage: G.element_repr_method("conj")
|
|
864
|
+
sage: G._elliptic_conj_reps()
|
|
865
|
+
sage: sorted(G._conj_prim.items())
|
|
866
|
+
[(-4, [[S], [S]]), (lam - 3, [[U], [U]]), (0, [[V(4)]])]
|
|
867
|
+
sage: sorted(G._conj_nonprim.items())
|
|
868
|
+
[(-lam - 2, [[U^(-2)], [U^2], [U^(-2)], [U^2]]), (lam - 3, [[U^(-1)], [U^(-1)]])]
|
|
869
|
+
"""
|
|
870
|
+
if not hasattr(self, "_max_block_length"):
|
|
871
|
+
self._conjugacy_representatives()
|
|
872
|
+
elif ZZ(-4) in self._conj_prim:
|
|
873
|
+
return
|
|
874
|
+
|
|
875
|
+
D = self.U().discriminant()
|
|
876
|
+
if D not in self._conj_prim:
|
|
877
|
+
self._conj_prim[D] = []
|
|
878
|
+
self._conj_prim[D].append(self.U())
|
|
879
|
+
|
|
880
|
+
D = self.S().discriminant()
|
|
881
|
+
if D not in self._conj_prim:
|
|
882
|
+
self._conj_prim[D] = []
|
|
883
|
+
self._conj_prim[D].append(self.S())
|
|
884
|
+
|
|
885
|
+
other_reps = [self.U()**k
|
|
886
|
+
for k in range(-((self.n() - 1) / 2).floor(),
|
|
887
|
+
self.n() // 2 + 1)
|
|
888
|
+
if k not in [0, 1]]
|
|
889
|
+
|
|
890
|
+
for v in other_reps:
|
|
891
|
+
D = v.discriminant()
|
|
892
|
+
if D not in self._conj_nonprim:
|
|
893
|
+
self._conj_nonprim[D] = []
|
|
894
|
+
self._conj_nonprim[D].append(v)
|
|
895
|
+
|
|
896
|
+
def _conjugacy_representatives(self, max_block_length=0, D=None):
|
|
897
|
+
r"""
|
|
898
|
+
Store conjugacy representatives up to block length
|
|
899
|
+
``max_block_length`` (a nonnegative integer, default: 0)
|
|
900
|
+
in the internal dictionary. Previously calculated data is reused.
|
|
901
|
+
This is a helper function for e.g. :meth:`class_number`.
|
|
902
|
+
|
|
903
|
+
The set of all (hyperbolic) conjugacy types of block length
|
|
904
|
+
``t`` is stored in ``self._conj_block[t]``.
|
|
905
|
+
The set of all primitive representatives (so far) with
|
|
906
|
+
discriminant ``D`` is stored in ``self._conj_prim[D]``.
|
|
907
|
+
The set of all non-primitive representatives (so far) with
|
|
908
|
+
discriminant ``D`` is stored in ``self._conj_nonprim[D]``.
|
|
909
|
+
|
|
910
|
+
The case of nonpositive discriminants is done manually.
|
|
911
|
+
|
|
912
|
+
INPUT:
|
|
913
|
+
|
|
914
|
+
- ``max_block_length`` -- nonnegative integer (default: `0`); the
|
|
915
|
+
maximal block length
|
|
916
|
+
|
|
917
|
+
- ``D`` -- an element/discriminant of the base ring or more generally
|
|
918
|
+
an upper bound for the involved discriminants. If ``D != None`` then
|
|
919
|
+
an upper bound for ``max_block_length`` is deduced from ``D``
|
|
920
|
+
(default: ``None``).
|
|
921
|
+
|
|
922
|
+
EXAMPLES::
|
|
923
|
+
|
|
924
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
925
|
+
sage: G = HeckeTriangleGroup(n=5)
|
|
926
|
+
sage: G.element_repr_method("conj")
|
|
927
|
+
sage: G._conjugacy_representatives(2)
|
|
928
|
+
|
|
929
|
+
sage: sorted(G._conj_block[2])
|
|
930
|
+
[((2, 1), (1, 1)),
|
|
931
|
+
((2, 2),),
|
|
932
|
+
((3, 1), (1, 1)),
|
|
933
|
+
((3, 1), (2, 1)),
|
|
934
|
+
((3, 2),),
|
|
935
|
+
((4, 1), (1, 1)),
|
|
936
|
+
((4, 1), (2, 1)),
|
|
937
|
+
((4, 1), (3, 1))]
|
|
938
|
+
|
|
939
|
+
sage: [key for key in sorted(G._conj_prim)]
|
|
940
|
+
[-4, lam - 3, 0, 4*lam, 7*lam + 6, 9*lam + 5, 15*lam + 6, 33*lam + 21]
|
|
941
|
+
sage: for key in sorted(G._conj_prim):
|
|
942
|
+
....: print(sorted(G._conj_prim[key]))
|
|
943
|
+
[[S], [S]]
|
|
944
|
+
[[U], [U]]
|
|
945
|
+
[[V(4)]]
|
|
946
|
+
[[V(3)], [V(2)]]
|
|
947
|
+
[[V(1)*V(4)]]
|
|
948
|
+
[[V(3)*V(4)], [V(1)*V(2)]]
|
|
949
|
+
[[V(2)*V(4)], [V(1)*V(3)]]
|
|
950
|
+
[[V(2)*V(3)]]
|
|
951
|
+
sage: [key for key in sorted(G._conj_nonprim)]
|
|
952
|
+
[-lam - 2, lam - 3, 32*lam + 16]
|
|
953
|
+
|
|
954
|
+
sage: for key in sorted(G._conj_nonprim):
|
|
955
|
+
....: print(sorted(G._conj_nonprim[key]))
|
|
956
|
+
[[U^(-2)], [U^(-2)], [U^2], [U^2]]
|
|
957
|
+
[[U^(-1)], [U^(-1)]]
|
|
958
|
+
[[V(3)^2], [V(2)^2]]
|
|
959
|
+
|
|
960
|
+
sage: G.element_repr_method("default")
|
|
961
|
+
"""
|
|
962
|
+
from sage.combinat.partition import OrderedPartitions
|
|
963
|
+
from sage.combinat.combinat import tuples
|
|
964
|
+
|
|
965
|
+
if D is not None:
|
|
966
|
+
max_block_length = max(AA.zero(),
|
|
967
|
+
coerce_AA((D + 4)/(self.lam()**2))).sqrt().floor()
|
|
968
|
+
else:
|
|
969
|
+
try:
|
|
970
|
+
max_block_length = ZZ(max_block_length)
|
|
971
|
+
if max_block_length < 0:
|
|
972
|
+
raise TypeError
|
|
973
|
+
except TypeError:
|
|
974
|
+
raise ValueError("max_block_length must be a nonnegative integer!")
|
|
975
|
+
|
|
976
|
+
if not hasattr(self, "_max_block_length"):
|
|
977
|
+
self._max_block_length = ZZ.zero()
|
|
978
|
+
self._conj_block = {}
|
|
979
|
+
self._conj_nonprim = {}
|
|
980
|
+
self._conj_prim = {}
|
|
981
|
+
|
|
982
|
+
# It is not clear how to define the class number for D=0:
|
|
983
|
+
# Conjugacy classes are V(n-1)^(+-k) for arbitrary k
|
|
984
|
+
# and the trivial class (what about self_conj_block[0]?).
|
|
985
|
+
#
|
|
986
|
+
# One way is to define it using the fixed points and in
|
|
987
|
+
# that case V(n-1) would be a good representative.
|
|
988
|
+
# The non-primitive case is unclear however...
|
|
989
|
+
#
|
|
990
|
+
# We set it here to ensure that 0 is enlisted as a discriminant...
|
|
991
|
+
#
|
|
992
|
+
self._conj_prim[ZZ.zero()] = []
|
|
993
|
+
self._conj_prim[ZZ.zero()].append(self.V(self.n()-1))
|
|
994
|
+
|
|
995
|
+
self._elliptic_conj_reps()
|
|
996
|
+
|
|
997
|
+
if max_block_length <= self._max_block_length:
|
|
998
|
+
return
|
|
999
|
+
|
|
1000
|
+
def is_cycle(seq) -> bool:
|
|
1001
|
+
length = len(seq)
|
|
1002
|
+
for n in divisors(length):
|
|
1003
|
+
if n < length and is_cycle_of_length(seq, n):
|
|
1004
|
+
return True
|
|
1005
|
+
return False
|
|
1006
|
+
|
|
1007
|
+
def is_cycle_of_length(seq, n) -> bool:
|
|
1008
|
+
return all(seq[j] == seq[j % n] for j in range(n, len(seq)))
|
|
1009
|
+
|
|
1010
|
+
j_list = range(1, self.n())
|
|
1011
|
+
|
|
1012
|
+
for t in range(self._max_block_length + 1, max_block_length + 1):
|
|
1013
|
+
t_ZZ = ZZ(t)
|
|
1014
|
+
if t_ZZ not in self._conj_block:
|
|
1015
|
+
self._conj_block[t_ZZ] = set()
|
|
1016
|
+
|
|
1017
|
+
partitions = OrderedPartitions(t).list()
|
|
1018
|
+
for par in partitions:
|
|
1019
|
+
len_par = len(par)
|
|
1020
|
+
exp_list = tuples(j_list, len_par)
|
|
1021
|
+
for ex in exp_list:
|
|
1022
|
+
keep = True
|
|
1023
|
+
if len_par > 1:
|
|
1024
|
+
for k in range(-1, len_par - 1):
|
|
1025
|
+
if ex[k] == ex[k + 1]:
|
|
1026
|
+
keep = False
|
|
1027
|
+
break
|
|
1028
|
+
# We don't want powers of V(1)
|
|
1029
|
+
elif ex[0] == 1:
|
|
1030
|
+
keep = False
|
|
1031
|
+
# But: Do we maybe want powers of V(n-1)??
|
|
1032
|
+
# For now we exclude the parabolic cases...
|
|
1033
|
+
elif ex[0] == self.n() - 1:
|
|
1034
|
+
keep = False
|
|
1035
|
+
|
|
1036
|
+
if keep:
|
|
1037
|
+
conj_type = cyclic_representative(tuple((ZZ(ex[k]), ZZ(par[k])) for k in range(len_par)))
|
|
1038
|
+
self._conj_block[t_ZZ].add(conj_type)
|
|
1039
|
+
|
|
1040
|
+
for el in self._conj_block[t_ZZ]:
|
|
1041
|
+
group_el = prod([self.V(el[k][0])**el[k][1] for k in range(len(el))])
|
|
1042
|
+
|
|
1043
|
+
D = group_el.discriminant()
|
|
1044
|
+
assert coerce_AA(D) > 0
|
|
1045
|
+
|
|
1046
|
+
# The primitive cases
|
|
1047
|
+
# if group_el.is_primitive():
|
|
1048
|
+
if not ((len(el) == 1 and el[0][1] > 1) or is_cycle(el)):
|
|
1049
|
+
if D not in self._conj_prim:
|
|
1050
|
+
self._conj_prim[D] = []
|
|
1051
|
+
self._conj_prim[D].append(group_el)
|
|
1052
|
+
# The remaining cases
|
|
1053
|
+
else:
|
|
1054
|
+
if D not in self._conj_nonprim:
|
|
1055
|
+
self._conj_nonprim[D] = []
|
|
1056
|
+
self._conj_nonprim[D].append(group_el)
|
|
1057
|
+
|
|
1058
|
+
self._max_block_length = max_block_length
|
|
1059
|
+
|
|
1060
|
+
def class_representatives(self, D, primitive=True):
|
|
1061
|
+
r"""
|
|
1062
|
+
Return a representative for each conjugacy class for the
|
|
1063
|
+
discriminant ``D`` (ignoring the sign).
|
|
1064
|
+
|
|
1065
|
+
If ``primitive=True`` only one representative for each
|
|
1066
|
+
fixed point is returned (ignoring sign).
|
|
1067
|
+
|
|
1068
|
+
INPUT:
|
|
1069
|
+
|
|
1070
|
+
- ``D`` -- an element of the base ring corresponding
|
|
1071
|
+
to a valid discriminant
|
|
1072
|
+
|
|
1073
|
+
- ``primitive`` -- if ``True`` (default) then only primitive
|
|
1074
|
+
representatives are considered
|
|
1075
|
+
|
|
1076
|
+
EXAMPLES::
|
|
1077
|
+
|
|
1078
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
1079
|
+
sage: G = HeckeTriangleGroup(n=4)
|
|
1080
|
+
sage: G.element_repr_method("conj")
|
|
1081
|
+
|
|
1082
|
+
sage: R = G.class_representatives(4)
|
|
1083
|
+
sage: R
|
|
1084
|
+
[[V(2)]]
|
|
1085
|
+
sage: [v.continued_fraction()[1] for v in R]
|
|
1086
|
+
[(2,)]
|
|
1087
|
+
|
|
1088
|
+
sage: R = G.class_representatives(0)
|
|
1089
|
+
sage: R
|
|
1090
|
+
[[V(3)]]
|
|
1091
|
+
sage: [v.continued_fraction()[1] for v in R]
|
|
1092
|
+
[(1, 2)]
|
|
1093
|
+
|
|
1094
|
+
sage: R = G.class_representatives(-4)
|
|
1095
|
+
sage: R
|
|
1096
|
+
[[S]]
|
|
1097
|
+
sage: R = G.class_representatives(-4, primitive=False)
|
|
1098
|
+
sage: R
|
|
1099
|
+
[[S], [U^2]]
|
|
1100
|
+
|
|
1101
|
+
sage: R = G.class_representatives(G.lam()^2 - 4)
|
|
1102
|
+
sage: R
|
|
1103
|
+
[[U]]
|
|
1104
|
+
sage: R = G.class_representatives(G.lam()^2 - 4, primitive=False)
|
|
1105
|
+
sage: R
|
|
1106
|
+
[[U], [U^(-1)]]
|
|
1107
|
+
|
|
1108
|
+
sage: R = G.class_representatives(14)
|
|
1109
|
+
sage: sorted(R)
|
|
1110
|
+
[[V(2)*V(3)], [V(1)*V(2)]]
|
|
1111
|
+
sage: sorted(v.continued_fraction()[1] for v in R)
|
|
1112
|
+
[(1, 2, 2), (3,)]
|
|
1113
|
+
|
|
1114
|
+
sage: R = G.class_representatives(32)
|
|
1115
|
+
sage: sorted(R)
|
|
1116
|
+
[[V(3)^2*V(1)], [V(1)^2*V(3)]]
|
|
1117
|
+
sage: [v.continued_fraction()[1] for v in sorted(R)]
|
|
1118
|
+
[(1, 2, 1, 3), (1, 4)]
|
|
1119
|
+
|
|
1120
|
+
sage: R = G.class_representatives(32, primitive=False)
|
|
1121
|
+
sage: sorted(R)
|
|
1122
|
+
[[V(3)^2*V(1)], [V(1)^2*V(3)], [V(2)^2]]
|
|
1123
|
+
|
|
1124
|
+
sage: G.element_repr_method("default")
|
|
1125
|
+
"""
|
|
1126
|
+
if coerce_AA(D) == 0 and not primitive:
|
|
1127
|
+
raise ValueError("There are infinitely many non-primitive conjugacy classes of discriminant 0.")
|
|
1128
|
+
|
|
1129
|
+
self._conjugacy_representatives(D=D)
|
|
1130
|
+
|
|
1131
|
+
L = []
|
|
1132
|
+
if D in self._conj_prim:
|
|
1133
|
+
L += self._conj_prim[D]
|
|
1134
|
+
if not primitive and D in self._conj_nonprim:
|
|
1135
|
+
L += self._conj_nonprim[D]
|
|
1136
|
+
|
|
1137
|
+
if not L:
|
|
1138
|
+
raise ValueError("D = {} is not a{} discriminant for {}".format(D, " primitive" if primitive else "", self))
|
|
1139
|
+
else:
|
|
1140
|
+
return L
|
|
1141
|
+
|
|
1142
|
+
def class_number(self, D, primitive=True):
|
|
1143
|
+
r"""
|
|
1144
|
+
Return the class number of ``self`` for the discriminant ``D``.
|
|
1145
|
+
|
|
1146
|
+
This is the number of conjugacy classes of (primitive) elements
|
|
1147
|
+
of discriminant ``D``.
|
|
1148
|
+
|
|
1149
|
+
Note: Due to the 1-1 correspondence with hyperbolic fixed
|
|
1150
|
+
points resp. hyperbolic binary quadratic forms
|
|
1151
|
+
this also gives the class number in those cases.
|
|
1152
|
+
|
|
1153
|
+
INPUT:
|
|
1154
|
+
|
|
1155
|
+
- ``D`` -- an element of the base ring corresponding
|
|
1156
|
+
to a valid discriminant
|
|
1157
|
+
|
|
1158
|
+
- ``primitive`` -- if ``True`` (default) then only primitive
|
|
1159
|
+
elements are considered
|
|
1160
|
+
|
|
1161
|
+
EXAMPLES::
|
|
1162
|
+
|
|
1163
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
1164
|
+
sage: G = HeckeTriangleGroup(n=4)
|
|
1165
|
+
|
|
1166
|
+
sage: G.class_number(4)
|
|
1167
|
+
1
|
|
1168
|
+
sage: G.class_number(4, primitive=False)
|
|
1169
|
+
1
|
|
1170
|
+
sage: G.class_number(14)
|
|
1171
|
+
2
|
|
1172
|
+
sage: G.class_number(32)
|
|
1173
|
+
2
|
|
1174
|
+
sage: G.class_number(32, primitive=False)
|
|
1175
|
+
3
|
|
1176
|
+
sage: G.class_number(68)
|
|
1177
|
+
4
|
|
1178
|
+
"""
|
|
1179
|
+
|
|
1180
|
+
if coerce_AA(D) <= 0:
|
|
1181
|
+
raise NotImplementedError
|
|
1182
|
+
|
|
1183
|
+
self._conjugacy_representatives(D=D)
|
|
1184
|
+
|
|
1185
|
+
num = ZZ(0)
|
|
1186
|
+
if D in self._conj_prim:
|
|
1187
|
+
num = len(self._conj_prim[D])
|
|
1188
|
+
if not primitive and D in self._conj_nonprim:
|
|
1189
|
+
num += len(self._conj_nonprim[D])
|
|
1190
|
+
|
|
1191
|
+
if num == 0:
|
|
1192
|
+
raise ValueError("D = {} is not a{} discriminant for {}".format(D, " primitive" if primitive else "", self))
|
|
1193
|
+
else:
|
|
1194
|
+
return num
|
|
1195
|
+
|
|
1196
|
+
def is_discriminant(self, D, primitive=True) -> bool:
|
|
1197
|
+
r"""
|
|
1198
|
+
Return whether ``D`` is a discriminant of an element of ``self``.
|
|
1199
|
+
|
|
1200
|
+
Note: Checking that something isn't a discriminant takes much
|
|
1201
|
+
longer than checking for valid discriminants.
|
|
1202
|
+
|
|
1203
|
+
INPUT:
|
|
1204
|
+
|
|
1205
|
+
- ``D`` -- an element of the base ring
|
|
1206
|
+
|
|
1207
|
+
- ``primitive`` -- if ``True`` (default) then only primitive
|
|
1208
|
+
elements are considered
|
|
1209
|
+
|
|
1210
|
+
OUTPUT:
|
|
1211
|
+
|
|
1212
|
+
``True`` if ``D`` is a primitive discriminant (a discriminant of
|
|
1213
|
+
a primitive element) and ``False`` otherwise.
|
|
1214
|
+
If ``primitive=False`` then also non-primitive elements are considered.
|
|
1215
|
+
|
|
1216
|
+
EXAMPLES::
|
|
1217
|
+
|
|
1218
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
1219
|
+
sage: G = HeckeTriangleGroup(n=4)
|
|
1220
|
+
|
|
1221
|
+
sage: G.is_discriminant(68)
|
|
1222
|
+
True
|
|
1223
|
+
sage: G.is_discriminant(196, primitive=False) # long time
|
|
1224
|
+
True
|
|
1225
|
+
sage: G.is_discriminant(2)
|
|
1226
|
+
False
|
|
1227
|
+
"""
|
|
1228
|
+
self._conjugacy_representatives(0)
|
|
1229
|
+
t_bound = max(AA.zero(),
|
|
1230
|
+
coerce_AA((D + 4) / (self.lam()**2))).sqrt().floor()
|
|
1231
|
+
for t in range(self._max_block_length + 1, t_bound + 1):
|
|
1232
|
+
self._conjugacy_representatives(t)
|
|
1233
|
+
|
|
1234
|
+
if D in self._conj_prim:
|
|
1235
|
+
return True
|
|
1236
|
+
if not primitive and D in self._conj_nonprim:
|
|
1237
|
+
return True
|
|
1238
|
+
|
|
1239
|
+
if D in self._conj_prim:
|
|
1240
|
+
return True
|
|
1241
|
+
return not primitive and D in self._conj_nonprim
|
|
1242
|
+
|
|
1243
|
+
def list_discriminants(self, D, primitive=True, hyperbolic=True, incomplete=False):
|
|
1244
|
+
r"""
|
|
1245
|
+
Return a list of all discriminants up to some upper bound ``D``.
|
|
1246
|
+
|
|
1247
|
+
INPUT:
|
|
1248
|
+
|
|
1249
|
+
- ``D`` -- an element/discriminant of the base ring or
|
|
1250
|
+
more generally an upper bound for the discriminant
|
|
1251
|
+
|
|
1252
|
+
- ``primitive`` -- if ``True`` (default) then only primitive
|
|
1253
|
+
discriminants are listed
|
|
1254
|
+
|
|
1255
|
+
- ``hyperbolic`` -- if ``True`` (default) then only positive
|
|
1256
|
+
discriminants are listed
|
|
1257
|
+
|
|
1258
|
+
- ``incomplete`` -- if ``True`` (default: ``False``) then all
|
|
1259
|
+
(also higher) discriminants which were gathered so far are listed
|
|
1260
|
+
(however there might be missing discriminants in between).
|
|
1261
|
+
|
|
1262
|
+
OUTPUT: list of discriminants less than or equal to ``D``
|
|
1263
|
+
|
|
1264
|
+
EXAMPLES::
|
|
1265
|
+
|
|
1266
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
1267
|
+
sage: G = HeckeTriangleGroup(n=4)
|
|
1268
|
+
sage: G.list_discriminants(D=68)
|
|
1269
|
+
[4, 12, 14, 28, 32, 46, 60, 68]
|
|
1270
|
+
sage: G.list_discriminants(D=0, hyperbolic=False, primitive=False)
|
|
1271
|
+
[-4, -2, 0]
|
|
1272
|
+
|
|
1273
|
+
sage: G = HeckeTriangleGroup(n=5)
|
|
1274
|
+
sage: G.list_discriminants(D=20)
|
|
1275
|
+
[4*lam, 7*lam + 6, 9*lam + 5]
|
|
1276
|
+
sage: G.list_discriminants(D=0, hyperbolic=False, primitive=False)
|
|
1277
|
+
[-4, -lam - 2, lam - 3, 0]
|
|
1278
|
+
"""
|
|
1279
|
+
|
|
1280
|
+
self._conjugacy_representatives(D=D)
|
|
1281
|
+
|
|
1282
|
+
if incomplete:
|
|
1283
|
+
max_D = infinity
|
|
1284
|
+
else:
|
|
1285
|
+
max_D = coerce_AA(D)
|
|
1286
|
+
|
|
1287
|
+
if hyperbolic:
|
|
1288
|
+
L = [key for key in self._conj_prim if 0 < coerce_AA(key) <= max_D]
|
|
1289
|
+
else:
|
|
1290
|
+
L = [key for key in self._conj_prim if coerce_AA(key) <= max_D]
|
|
1291
|
+
|
|
1292
|
+
if not primitive:
|
|
1293
|
+
if hyperbolic:
|
|
1294
|
+
L += [key for key in self._conj_nonprim
|
|
1295
|
+
if 0 < coerce_AA(key) <= max_D and key not in L]
|
|
1296
|
+
else:
|
|
1297
|
+
L += [key for key in self._conj_nonprim
|
|
1298
|
+
if coerce_AA(key) <= max_D and key not in L]
|
|
1299
|
+
|
|
1300
|
+
return sorted(L, key=coerce_AA)
|
|
1301
|
+
|
|
1302
|
+
# TODO: non-primitive ones?
|
|
1303
|
+
def reduced_elements(self, D):
|
|
1304
|
+
r"""
|
|
1305
|
+
Return all reduced (primitive) elements of discriminant ``D``.
|
|
1306
|
+
|
|
1307
|
+
Also see the element method :meth:`is_reduced` for more information.
|
|
1308
|
+
|
|
1309
|
+
- ``D`` -- an element of the base ring corresponding
|
|
1310
|
+
to a valid discriminant
|
|
1311
|
+
|
|
1312
|
+
EXAMPLES::
|
|
1313
|
+
|
|
1314
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
1315
|
+
sage: G = HeckeTriangleGroup(n=4)
|
|
1316
|
+
sage: R = G.reduced_elements(D=12)
|
|
1317
|
+
sage: R
|
|
1318
|
+
[
|
|
1319
|
+
[ 5 -lam] [ 5 -3*lam]
|
|
1320
|
+
[3*lam -1], [ lam -1]
|
|
1321
|
+
]
|
|
1322
|
+
sage: [v.continued_fraction() for v in R]
|
|
1323
|
+
[((), (1, 3)), ((), (3, 1))]
|
|
1324
|
+
sage: R = G.reduced_elements(D=14)
|
|
1325
|
+
sage: sorted(R)
|
|
1326
|
+
[
|
|
1327
|
+
[3*lam -1] [4*lam -3] [ 5*lam -7] [ 5*lam -3]
|
|
1328
|
+
[ 1 0], [ 3 -lam], [ 3 -2*lam], [ 7 -2*lam]
|
|
1329
|
+
]
|
|
1330
|
+
sage: sorted(v.continued_fraction() for v in R)
|
|
1331
|
+
[((), (1, 2, 2)), ((), (2, 1, 2)), ((), (2, 2, 1)), ((), (3,))]
|
|
1332
|
+
"""
|
|
1333
|
+
L = self.class_representatives(D=D, primitive=True)
|
|
1334
|
+
R = []
|
|
1335
|
+
for v in L:
|
|
1336
|
+
R += v.reduced_elements()
|
|
1337
|
+
|
|
1338
|
+
return R
|
|
1339
|
+
|
|
1340
|
+
def simple_elements(self, D):
|
|
1341
|
+
r"""
|
|
1342
|
+
Return all simple elements of discriminant ``D``.
|
|
1343
|
+
|
|
1344
|
+
Also see the element method ``is_simple()`` for more information.
|
|
1345
|
+
|
|
1346
|
+
- ``D`` -- an element of the base ring corresponding to a valid
|
|
1347
|
+
discriminant
|
|
1348
|
+
|
|
1349
|
+
EXAMPLES::
|
|
1350
|
+
|
|
1351
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
1352
|
+
sage: G = HeckeTriangleGroup(n=4)
|
|
1353
|
+
sage: sorted(G.simple_elements(D=12))
|
|
1354
|
+
[
|
|
1355
|
+
[ 1 lam] [ 3 lam]
|
|
1356
|
+
[lam 3], [lam 1]
|
|
1357
|
+
]
|
|
1358
|
+
sage: sorted(G.simple_elements(D=14))
|
|
1359
|
+
[
|
|
1360
|
+
[ lam 1] [ lam 3] [2*lam 1] [2*lam 3]
|
|
1361
|
+
[ 3 2*lam], [ 1 2*lam], [ 3 lam], [ 1 lam]
|
|
1362
|
+
]
|
|
1363
|
+
"""
|
|
1364
|
+
L = self.class_representatives(D=D, primitive=True)
|
|
1365
|
+
R = []
|
|
1366
|
+
for v in L:
|
|
1367
|
+
R += v.simple_elements()
|
|
1368
|
+
|
|
1369
|
+
return R
|
|
1370
|
+
|
|
1371
|
+
def rational_period_functions(self, k, D):
|
|
1372
|
+
r"""
|
|
1373
|
+
Return a list of basic rational period functions of weight ``k`` for
|
|
1374
|
+
discriminant ``D``.
|
|
1375
|
+
|
|
1376
|
+
The list is expected to be a generating set for all rational
|
|
1377
|
+
period functions of the given weight and discriminant (unknown).
|
|
1378
|
+
|
|
1379
|
+
The method assumes that ``D > 0``.
|
|
1380
|
+
|
|
1381
|
+
Also see the element method ``rational_period_function`` for more information.
|
|
1382
|
+
|
|
1383
|
+
- ``k`` -- even integer, the desired weight of the rational period
|
|
1384
|
+
functions
|
|
1385
|
+
|
|
1386
|
+
- ``D`` -- an element of the base ring corresponding to a valid
|
|
1387
|
+
discriminant
|
|
1388
|
+
|
|
1389
|
+
EXAMPLES::
|
|
1390
|
+
|
|
1391
|
+
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup
|
|
1392
|
+
sage: G = HeckeTriangleGroup(n=4)
|
|
1393
|
+
sage: sorted(G.rational_period_functions(k=4, D=12))
|
|
1394
|
+
[(z^4 - 1)/z^4]
|
|
1395
|
+
sage: sorted(G.rational_period_functions(k=-2, D=12))
|
|
1396
|
+
[-z^2 + 1, 4*lam*z^2 - 4*lam]
|
|
1397
|
+
sage: sorted(G.rational_period_functions(k=2, D=14))
|
|
1398
|
+
[(24*z^6 - 120*z^4 + 120*z^2 - 24)/(9*z^8 - 80*z^6 + 146*z^4 - 80*z^2 + 9),
|
|
1399
|
+
(24*z^6 - 120*z^4 + 120*z^2 - 24)/(9*z^8 - 80*z^6 + 146*z^4 - 80*z^2 + 9),
|
|
1400
|
+
1/z,
|
|
1401
|
+
(z^2 - 1)/z^2]
|
|
1402
|
+
sage: sorted(G.rational_period_functions(k=-4, D=14))
|
|
1403
|
+
[-16*z^4 + 16, -z^4 + 1, 16*z^4 - 16]
|
|
1404
|
+
"""
|
|
1405
|
+
try:
|
|
1406
|
+
k = ZZ(k)
|
|
1407
|
+
if not ZZ(2).divides(k):
|
|
1408
|
+
raise TypeError
|
|
1409
|
+
except TypeError:
|
|
1410
|
+
raise ValueError(f"k={k} has to be an even integer!")
|
|
1411
|
+
|
|
1412
|
+
z = PolynomialRing(self.base_ring(), 'z').gen()
|
|
1413
|
+
|
|
1414
|
+
R = []
|
|
1415
|
+
if k != 0:
|
|
1416
|
+
R.append(ZZ(1) - z**(-k))
|
|
1417
|
+
if k == 2:
|
|
1418
|
+
R.append(z**(-1))
|
|
1419
|
+
|
|
1420
|
+
L = self.class_representatives(D=D, primitive=True)
|
|
1421
|
+
for v in L:
|
|
1422
|
+
rat = v.rational_period_function(k)
|
|
1423
|
+
if rat != 0:
|
|
1424
|
+
R.append(rat)
|
|
1425
|
+
|
|
1426
|
+
return R
|