passagemath-schemes 10.6.38__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.
Potentially problematic release.
This version of passagemath-schemes might be problematic. Click here for more details.
- passagemath_schemes/.dylibs/libflint.21.0.dylib +0 -0
- passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
- passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
- passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
- passagemath_schemes/__init__.py +3 -0
- passagemath_schemes-10.6.38.dist-info/METADATA +204 -0
- passagemath_schemes-10.6.38.dist-info/METADATA.bak +205 -0
- passagemath_schemes-10.6.38.dist-info/RECORD +314 -0
- passagemath_schemes-10.6.38.dist-info/WHEEL +6 -0
- passagemath_schemes-10.6.38.dist-info/top_level.txt +3 -0
- sage/all__sagemath_schemes.py +23 -0
- sage/databases/all__sagemath_schemes.py +7 -0
- sage/databases/cremona.py +1723 -0
- sage/dynamics/all__sagemath_schemes.py +2 -0
- sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
- sage/dynamics/arithmetic_dynamics/all.py +14 -0
- sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
- sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
- sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
- sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
- sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
- sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
- sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
- sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
- sage/lfunctions/all.py +18 -0
- sage/lfunctions/dokchitser.py +745 -0
- sage/lfunctions/pari.py +818 -0
- sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
- sage/lfunctions/zero_sums.pyx +1847 -0
- sage/modular/abvar/abvar.py +5135 -0
- sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
- sage/modular/abvar/abvar_newform.py +244 -0
- sage/modular/abvar/all.py +8 -0
- sage/modular/abvar/constructor.py +186 -0
- sage/modular/abvar/cuspidal_subgroup.py +371 -0
- sage/modular/abvar/finite_subgroup.py +896 -0
- sage/modular/abvar/homology.py +720 -0
- sage/modular/abvar/homspace.py +998 -0
- sage/modular/abvar/lseries.py +415 -0
- sage/modular/abvar/morphism.py +935 -0
- sage/modular/abvar/torsion_point.py +274 -0
- sage/modular/abvar/torsion_subgroup.py +740 -0
- sage/modular/all.py +43 -0
- sage/modular/arithgroup/all.py +20 -0
- sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
- sage/modular/arithgroup/arithgroup_element.pyx +474 -0
- sage/modular/arithgroup/arithgroup_generic.py +1402 -0
- sage/modular/arithgroup/arithgroup_perm.py +2692 -0
- sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
- sage/modular/arithgroup/congroup.pyx +334 -0
- sage/modular/arithgroup/congroup_gamma.py +363 -0
- sage/modular/arithgroup/congroup_gamma0.py +692 -0
- sage/modular/arithgroup/congroup_gamma1.py +653 -0
- sage/modular/arithgroup/congroup_gammaH.py +1469 -0
- sage/modular/arithgroup/congroup_generic.py +628 -0
- sage/modular/arithgroup/congroup_sl2z.py +267 -0
- sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
- sage/modular/arithgroup/farey_symbol.pyx +1066 -0
- sage/modular/arithgroup/tests.py +418 -0
- sage/modular/btquotients/all.py +4 -0
- sage/modular/btquotients/btquotient.py +3753 -0
- sage/modular/btquotients/pautomorphicform.py +2570 -0
- sage/modular/buzzard.py +100 -0
- sage/modular/congroup.py +29 -0
- sage/modular/congroup_element.py +13 -0
- sage/modular/cusps.py +1109 -0
- sage/modular/cusps_nf.py +1270 -0
- sage/modular/dims.py +569 -0
- sage/modular/dirichlet.py +3310 -0
- sage/modular/drinfeld_modform/all.py +2 -0
- sage/modular/drinfeld_modform/element.py +446 -0
- sage/modular/drinfeld_modform/ring.py +773 -0
- sage/modular/drinfeld_modform/tutorial.py +236 -0
- sage/modular/etaproducts.py +1065 -0
- sage/modular/hecke/algebra.py +746 -0
- sage/modular/hecke/all.py +20 -0
- sage/modular/hecke/ambient_module.py +1019 -0
- sage/modular/hecke/degenmap.py +119 -0
- sage/modular/hecke/element.py +325 -0
- sage/modular/hecke/hecke_operator.py +780 -0
- sage/modular/hecke/homspace.py +206 -0
- sage/modular/hecke/module.py +1767 -0
- sage/modular/hecke/morphism.py +174 -0
- sage/modular/hecke/submodule.py +989 -0
- sage/modular/hypergeometric_misc.cpython-314t-darwin.so +0 -0
- sage/modular/hypergeometric_misc.pxd +4 -0
- sage/modular/hypergeometric_misc.pyx +166 -0
- sage/modular/hypergeometric_motive.py +2017 -0
- sage/modular/local_comp/all.py +2 -0
- sage/modular/local_comp/liftings.py +292 -0
- sage/modular/local_comp/local_comp.py +1071 -0
- sage/modular/local_comp/smoothchar.py +1825 -0
- sage/modular/local_comp/type_space.py +748 -0
- sage/modular/modform/all.py +30 -0
- sage/modular/modform/ambient.py +815 -0
- sage/modular/modform/ambient_R.py +177 -0
- sage/modular/modform/ambient_eps.py +306 -0
- sage/modular/modform/ambient_g0.py +124 -0
- sage/modular/modform/ambient_g1.py +204 -0
- sage/modular/modform/constructor.py +545 -0
- sage/modular/modform/cuspidal_submodule.py +708 -0
- sage/modular/modform/defaults.py +14 -0
- sage/modular/modform/eis_series.py +505 -0
- sage/modular/modform/eisenstein_submodule.py +663 -0
- sage/modular/modform/element.py +4131 -0
- sage/modular/modform/find_generators.py +59 -0
- sage/modular/modform/half_integral.py +154 -0
- sage/modular/modform/hecke_operator_on_qexp.py +247 -0
- sage/modular/modform/j_invariant.py +47 -0
- sage/modular/modform/l_series_gross_zagier.py +133 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.cpython-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 +1860 -0
- sage/modular/modform/submodule.py +118 -0
- sage/modular/modform/tests.py +64 -0
- sage/modular/modform/theta.py +110 -0
- sage/modular/modform/vm_basis.py +381 -0
- sage/modular/modform/weight1.py +220 -0
- sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
- sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
- sage/modular/modform_hecketriangle/all.py +30 -0
- sage/modular/modform_hecketriangle/analytic_type.py +590 -0
- sage/modular/modform_hecketriangle/constructor.py +416 -0
- sage/modular/modform_hecketriangle/element.py +351 -0
- sage/modular/modform_hecketriangle/functors.py +752 -0
- sage/modular/modform_hecketriangle/graded_ring.py +541 -0
- sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
- sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
- sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
- sage/modular/modform_hecketriangle/readme.py +1214 -0
- sage/modular/modform_hecketriangle/series_constructor.py +580 -0
- sage/modular/modform_hecketriangle/space.py +1037 -0
- sage/modular/modform_hecketriangle/subspace.py +423 -0
- sage/modular/modsym/all.py +17 -0
- sage/modular/modsym/ambient.py +3846 -0
- sage/modular/modsym/boundary.py +1420 -0
- sage/modular/modsym/element.py +336 -0
- sage/modular/modsym/g1list.py +178 -0
- sage/modular/modsym/ghlist.py +182 -0
- sage/modular/modsym/hecke_operator.py +73 -0
- sage/modular/modsym/manin_symbol.cpython-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 +1295 -0
- sage/modular/modsym/modsym.py +400 -0
- sage/modular/modsym/modular_symbols.py +384 -0
- sage/modular/modsym/p1list.cpython-314t-darwin.so +0 -0
- sage/modular/modsym/p1list.pxd +29 -0
- sage/modular/modsym/p1list.pyx +1372 -0
- sage/modular/modsym/p1list_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-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 +375 -0
- sage/modular/multiple_zeta.py +2632 -0
- sage/modular/multiple_zeta_F_algebra.py +786 -0
- sage/modular/overconvergent/all.py +6 -0
- sage/modular/overconvergent/genus0.py +1878 -0
- sage/modular/overconvergent/hecke_series.py +1187 -0
- sage/modular/overconvergent/weightspace.py +778 -0
- sage/modular/pollack_stevens/all.py +4 -0
- sage/modular/pollack_stevens/distributions.py +874 -0
- sage/modular/pollack_stevens/fund_domain.py +1572 -0
- sage/modular/pollack_stevens/manin_map.py +859 -0
- sage/modular/pollack_stevens/modsym.py +1593 -0
- sage/modular/pollack_stevens/padic_lseries.py +417 -0
- sage/modular/pollack_stevens/sigma0.py +534 -0
- sage/modular/pollack_stevens/space.py +1076 -0
- sage/modular/quasimodform/all.py +3 -0
- sage/modular/quasimodform/element.py +845 -0
- sage/modular/quasimodform/ring.py +828 -0
- sage/modular/quatalg/all.py +3 -0
- sage/modular/quatalg/brandt.py +1642 -0
- sage/modular/ssmod/all.py +8 -0
- sage/modular/ssmod/ssmod.py +827 -0
- sage/rings/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/binary_form_reduce.py +585 -0
- sage/schemes/all.py +41 -0
- sage/schemes/berkovich/all.py +6 -0
- sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
- sage/schemes/berkovich/berkovich_space.py +748 -0
- sage/schemes/curves/affine_curve.py +2928 -0
- sage/schemes/curves/all.py +33 -0
- sage/schemes/curves/closed_point.py +434 -0
- sage/schemes/curves/constructor.py +381 -0
- sage/schemes/curves/curve.py +542 -0
- sage/schemes/curves/plane_curve_arrangement.py +1283 -0
- sage/schemes/curves/point.py +463 -0
- sage/schemes/curves/projective_curve.py +3026 -0
- sage/schemes/curves/zariski_vankampen.py +1932 -0
- sage/schemes/cyclic_covers/all.py +2 -0
- sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
- sage/schemes/cyclic_covers/constructor.py +137 -0
- sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
- sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
- sage/schemes/elliptic_curves/BSD.py +1036 -0
- sage/schemes/elliptic_curves/Qcurves.py +592 -0
- sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
- sage/schemes/elliptic_curves/all.py +49 -0
- sage/schemes/elliptic_curves/cardinality.py +609 -0
- sage/schemes/elliptic_curves/cm.py +1102 -0
- sage/schemes/elliptic_curves/constructor.py +1552 -0
- sage/schemes/elliptic_curves/ec_database.py +175 -0
- sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
- sage/schemes/elliptic_curves/ell_egros.py +459 -0
- sage/schemes/elliptic_curves/ell_field.py +2836 -0
- sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
- sage/schemes/elliptic_curves/ell_generic.py +3760 -0
- sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
- sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
- sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
- sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
- sage/schemes/elliptic_curves/ell_point.py +4787 -0
- sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
- sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
- sage/schemes/elliptic_curves/ell_torsion.py +436 -0
- sage/schemes/elliptic_curves/ell_wp.py +352 -0
- sage/schemes/elliptic_curves/formal_group.py +760 -0
- sage/schemes/elliptic_curves/gal_reps.py +1459 -0
- sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
- sage/schemes/elliptic_curves/gp_simon.py +152 -0
- sage/schemes/elliptic_curves/heegner.py +7335 -0
- sage/schemes/elliptic_curves/height.py +2109 -0
- sage/schemes/elliptic_curves/hom.py +1406 -0
- sage/schemes/elliptic_curves/hom_composite.py +934 -0
- sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
- sage/schemes/elliptic_curves/hom_scalar.py +531 -0
- sage/schemes/elliptic_curves/hom_sum.py +682 -0
- sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
- sage/schemes/elliptic_curves/homset.py +271 -0
- sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
- sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
- sage/schemes/elliptic_curves/jacobian.py +237 -0
- sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
- sage/schemes/elliptic_curves/kraus.py +1014 -0
- sage/schemes/elliptic_curves/lseries_ell.py +943 -0
- sage/schemes/elliptic_curves/mod5family.py +105 -0
- sage/schemes/elliptic_curves/mod_poly.py +197 -0
- sage/schemes/elliptic_curves/mod_sym_num.cpython-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 +715 -0
- sage/schemes/elliptic_curves/sha_tate.py +1158 -0
- sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
- sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
- sage/schemes/hyperelliptic_curves/all.py +6 -0
- sage/schemes/hyperelliptic_curves/constructor.py +291 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
- sage/schemes/hyperelliptic_curves/invariants.py +410 -0
- sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
- sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
- sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
- sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
- sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
- sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
- sage/schemes/hyperelliptic_curves/mestre.py +302 -0
- sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
- sage/schemes/jacobians/abstract_jacobian.py +277 -0
- sage/schemes/jacobians/all.py +2 -0
- sage/schemes/overview.py +161 -0
- sage/schemes/plane_conics/all.py +22 -0
- sage/schemes/plane_conics/con_field.py +1296 -0
- sage/schemes/plane_conics/con_finite_field.py +158 -0
- sage/schemes/plane_conics/con_number_field.py +456 -0
- sage/schemes/plane_conics/con_rational_field.py +406 -0
- sage/schemes/plane_conics/con_rational_function_field.py +580 -0
- sage/schemes/plane_conics/constructor.py +249 -0
- sage/schemes/plane_quartics/all.py +2 -0
- sage/schemes/plane_quartics/quartic_constructor.py +71 -0
- sage/schemes/plane_quartics/quartic_generic.py +73 -0
- sage/schemes/riemann_surfaces/all.py +1 -0
- sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
- sage_wheels/share/cremona/cremona_mini.db +0 -0
- sage_wheels/share/ellcurves/rank0 +30427 -0
- sage_wheels/share/ellcurves/rank1 +31871 -0
- sage_wheels/share/ellcurves/rank10 +6 -0
- sage_wheels/share/ellcurves/rank11 +6 -0
- sage_wheels/share/ellcurves/rank12 +1 -0
- sage_wheels/share/ellcurves/rank14 +1 -0
- sage_wheels/share/ellcurves/rank15 +1 -0
- sage_wheels/share/ellcurves/rank17 +1 -0
- sage_wheels/share/ellcurves/rank19 +1 -0
- sage_wheels/share/ellcurves/rank2 +2388 -0
- sage_wheels/share/ellcurves/rank20 +1 -0
- sage_wheels/share/ellcurves/rank21 +1 -0
- sage_wheels/share/ellcurves/rank22 +1 -0
- sage_wheels/share/ellcurves/rank23 +1 -0
- sage_wheels/share/ellcurves/rank24 +1 -0
- sage_wheels/share/ellcurves/rank28 +1 -0
- sage_wheels/share/ellcurves/rank3 +836 -0
- sage_wheels/share/ellcurves/rank4 +10 -0
- sage_wheels/share/ellcurves/rank5 +5 -0
- sage_wheels/share/ellcurves/rank6 +5 -0
- sage_wheels/share/ellcurves/rank7 +5 -0
- sage_wheels/share/ellcurves/rank8 +6 -0
- sage_wheels/share/ellcurves/rank9 +7 -0
sage/modular/cusps_nf.py
ADDED
|
@@ -0,0 +1,1270 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# sage.doctest: needs sage.rings.number_field
|
|
3
|
+
r"""
|
|
4
|
+
The set `\mathbb{P}^1(K)` of cusps of a number field `K`
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
- Maite Aranes (2009): Initial version
|
|
9
|
+
|
|
10
|
+
EXAMPLES:
|
|
11
|
+
|
|
12
|
+
The space of cusps over a number field k::
|
|
13
|
+
|
|
14
|
+
sage: x = polygen(ZZ, 'x')
|
|
15
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
16
|
+
sage: kCusps = NFCusps(k); kCusps
|
|
17
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 5
|
|
18
|
+
sage: kCusps is NFCusps(k)
|
|
19
|
+
True
|
|
20
|
+
|
|
21
|
+
Define a cusp over a number field::
|
|
22
|
+
|
|
23
|
+
sage: NFCusp(k, a, 2/(a+1))
|
|
24
|
+
Cusp [a - 5: 2] of Number Field in a with defining polynomial x^2 + 5
|
|
25
|
+
sage: kCusps((a,2))
|
|
26
|
+
Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 5
|
|
27
|
+
sage: NFCusp(k,oo)
|
|
28
|
+
Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
|
|
29
|
+
|
|
30
|
+
Different operations with cusps over a number field::
|
|
31
|
+
|
|
32
|
+
sage: alpha = NFCusp(k, 3, 1/a + 2); alpha
|
|
33
|
+
Cusp [a + 10: 7] of Number Field in a with defining polynomial x^2 + 5
|
|
34
|
+
sage: alpha.numerator()
|
|
35
|
+
a + 10
|
|
36
|
+
sage: alpha.denominator()
|
|
37
|
+
7
|
|
38
|
+
sage: alpha.ideal()
|
|
39
|
+
Fractional ideal (7, a + 3)
|
|
40
|
+
sage: M = alpha.ABmatrix(); M # random
|
|
41
|
+
[a + 10, 2*a + 6, 7, a + 5]
|
|
42
|
+
sage: NFCusp(k, oo).apply(M)
|
|
43
|
+
Cusp [a + 10: 7] of Number Field in a with defining polynomial x^2 + 5
|
|
44
|
+
|
|
45
|
+
Check Gamma0(N)-equivalence of cusps::
|
|
46
|
+
|
|
47
|
+
sage: N = k.ideal(3)
|
|
48
|
+
sage: alpha = NFCusp(k, 3, a + 1)
|
|
49
|
+
sage: beta = kCusps((2, a - 3))
|
|
50
|
+
sage: alpha.is_Gamma0_equivalent(beta, N)
|
|
51
|
+
True
|
|
52
|
+
|
|
53
|
+
Obtain transformation matrix for equivalent cusps::
|
|
54
|
+
|
|
55
|
+
sage: t, M = alpha.is_Gamma0_equivalent(beta, N, Transformation=True)
|
|
56
|
+
sage: M[2] in N
|
|
57
|
+
True
|
|
58
|
+
sage: M[0]*M[3] - M[1]*M[2] == 1
|
|
59
|
+
True
|
|
60
|
+
sage: alpha.apply(M) == beta
|
|
61
|
+
True
|
|
62
|
+
|
|
63
|
+
List representatives for Gamma_0(N) - equivalence classes of cusps::
|
|
64
|
+
|
|
65
|
+
sage: Gamma0_NFCusps(N)
|
|
66
|
+
[Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5,
|
|
67
|
+
Cusp [1: 3] of Number Field in a with defining polynomial x^2 + 5,
|
|
68
|
+
...]
|
|
69
|
+
"""
|
|
70
|
+
# ****************************************************************************
|
|
71
|
+
# Copyright (C) 2009, Maite Aranes <M.T.Aranes@warwick.ac.uk>
|
|
72
|
+
#
|
|
73
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
74
|
+
# https://www.gnu.org/licenses/
|
|
75
|
+
# ****************************************************************************
|
|
76
|
+
from typing import Any
|
|
77
|
+
|
|
78
|
+
from sage.misc.cachefunc import cached_method, cached_function
|
|
79
|
+
from sage.structure.parent import Parent
|
|
80
|
+
from sage.structure.element import Element, InfinityElement
|
|
81
|
+
from sage.structure.richcmp import richcmp, rich_to_bool
|
|
82
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@cached_function
|
|
86
|
+
def list_of_representatives(N):
|
|
87
|
+
"""
|
|
88
|
+
Return a list of ideals, coprime to the ideal ``N``, representatives of
|
|
89
|
+
the ideal classes of the corresponding number field.
|
|
90
|
+
|
|
91
|
+
.. NOTE::
|
|
92
|
+
|
|
93
|
+
This list, used every time we check `\\Gamma_0(N)` - equivalence of
|
|
94
|
+
cusps, is cached.
|
|
95
|
+
|
|
96
|
+
INPUT:
|
|
97
|
+
|
|
98
|
+
- ``N`` -- an ideal of a number field
|
|
99
|
+
|
|
100
|
+
OUTPUT:
|
|
101
|
+
|
|
102
|
+
A list of ideals coprime to the ideal ``N``, such that they are
|
|
103
|
+
representatives of all the ideal classes of the number field.
|
|
104
|
+
|
|
105
|
+
EXAMPLES::
|
|
106
|
+
|
|
107
|
+
sage: from sage.modular.cusps_nf import list_of_representatives
|
|
108
|
+
sage: x = polygen(ZZ, 'x')
|
|
109
|
+
sage: k.<a> = NumberField(x^4 + 13*x^3 - 11)
|
|
110
|
+
sage: N = k.ideal(713, a + 208)
|
|
111
|
+
sage: L = list_of_representatives(N); L
|
|
112
|
+
(Fractional ideal (1),
|
|
113
|
+
Fractional ideal (47, a - 9),
|
|
114
|
+
Fractional ideal (53, a - 16))
|
|
115
|
+
"""
|
|
116
|
+
return NFCusps_ideal_reps_for_levelN(N)[0]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@cached_function
|
|
120
|
+
def NFCusps(number_field):
|
|
121
|
+
r"""
|
|
122
|
+
The set of cusps of a number field `K`, i.e. `\mathbb{P}^1(K)`.
|
|
123
|
+
|
|
124
|
+
INPUT:
|
|
125
|
+
|
|
126
|
+
- ``number_field`` -- a number field
|
|
127
|
+
|
|
128
|
+
OUTPUT: the set of cusps over the given number field
|
|
129
|
+
|
|
130
|
+
EXAMPLES::
|
|
131
|
+
|
|
132
|
+
sage: x = polygen(ZZ, 'x')
|
|
133
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
134
|
+
sage: kCusps = NFCusps(k); kCusps
|
|
135
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 5
|
|
136
|
+
sage: kCusps is NFCusps(k)
|
|
137
|
+
True
|
|
138
|
+
|
|
139
|
+
Saving and loading works::
|
|
140
|
+
|
|
141
|
+
sage: loads(kCusps.dumps()) == kCusps
|
|
142
|
+
True
|
|
143
|
+
"""
|
|
144
|
+
return NFCuspsSpace(number_field)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# *************************************************************************
|
|
148
|
+
# NFCuspsSpace class *
|
|
149
|
+
# *************************************************************************
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class NFCuspsSpace(UniqueRepresentation, Parent):
|
|
153
|
+
"""
|
|
154
|
+
The set of cusps of a number field. See ``NFCusps`` for full documentation.
|
|
155
|
+
|
|
156
|
+
EXAMPLES::
|
|
157
|
+
|
|
158
|
+
sage: x = polygen(ZZ, 'x')
|
|
159
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
160
|
+
sage: kCusps = NFCusps(k); kCusps
|
|
161
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 5
|
|
162
|
+
"""
|
|
163
|
+
def __init__(self, number_field):
|
|
164
|
+
"""
|
|
165
|
+
See ``NFCusps`` for full documentation.
|
|
166
|
+
|
|
167
|
+
EXAMPLES::
|
|
168
|
+
|
|
169
|
+
sage: x = polygen(ZZ, 'x')
|
|
170
|
+
sage: k.<a> = NumberField(x^3 + x^2 + 13)
|
|
171
|
+
sage: kCusps = NFCusps(k); kCusps
|
|
172
|
+
Set of all cusps of Number Field in a with defining polynomial x^3 + x^2 + 13
|
|
173
|
+
"""
|
|
174
|
+
self.__number_field = number_field
|
|
175
|
+
Parent.__init__(self, self)
|
|
176
|
+
|
|
177
|
+
def __eq__(self, right):
|
|
178
|
+
"""
|
|
179
|
+
Return equality only if right is the set of cusps for the same field.
|
|
180
|
+
|
|
181
|
+
EXAMPLES::
|
|
182
|
+
|
|
183
|
+
sage: x = polygen(ZZ, 'x')
|
|
184
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
185
|
+
sage: L.<a> = NumberField(x^2 + 23)
|
|
186
|
+
sage: kCusps = NFCusps(k); kCusps
|
|
187
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 5
|
|
188
|
+
sage: LCusps = NFCusps(L); LCusps
|
|
189
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 23
|
|
190
|
+
sage: kCusps == NFCusps(k)
|
|
191
|
+
True
|
|
192
|
+
sage: LCusps == NFCusps(L)
|
|
193
|
+
True
|
|
194
|
+
sage: LCusps == kCusps
|
|
195
|
+
False
|
|
196
|
+
"""
|
|
197
|
+
if not isinstance(right, NFCuspsSpace):
|
|
198
|
+
return False
|
|
199
|
+
return self.number_field() == right.number_field()
|
|
200
|
+
|
|
201
|
+
def __ne__(self, right):
|
|
202
|
+
"""
|
|
203
|
+
Check that ``self`` is not equal to ``right``.
|
|
204
|
+
|
|
205
|
+
EXAMPLES::
|
|
206
|
+
|
|
207
|
+
sage: x = polygen(ZZ, 'x')
|
|
208
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
209
|
+
sage: L.<a> = NumberField(x^2 + 23)
|
|
210
|
+
sage: kCusps = NFCusps(k); kCusps
|
|
211
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 5
|
|
212
|
+
sage: LCusps = NFCusps(L); LCusps
|
|
213
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 23
|
|
214
|
+
sage: kCusps != NFCusps(k)
|
|
215
|
+
False
|
|
216
|
+
sage: LCusps != NFCusps(L)
|
|
217
|
+
False
|
|
218
|
+
sage: LCusps != kCusps
|
|
219
|
+
True
|
|
220
|
+
"""
|
|
221
|
+
return not (self == right)
|
|
222
|
+
|
|
223
|
+
def _repr_(self):
|
|
224
|
+
"""
|
|
225
|
+
String representation of the set of cusps of a number field.
|
|
226
|
+
|
|
227
|
+
EXAMPLES::
|
|
228
|
+
|
|
229
|
+
sage: x = polygen(ZZ, 'x')
|
|
230
|
+
sage: k.<a> = NumberField(x^2 + 2)
|
|
231
|
+
sage: kCusps = NFCusps(k)
|
|
232
|
+
sage: kCusps
|
|
233
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 2
|
|
234
|
+
sage: kCusps._repr_()
|
|
235
|
+
'Set of all cusps of Number Field in a with defining polynomial x^2 + 2'
|
|
236
|
+
sage: kCusps.rename('Number Field Cusps'); kCusps
|
|
237
|
+
Number Field Cusps
|
|
238
|
+
sage: kCusps.rename(); kCusps
|
|
239
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 2
|
|
240
|
+
"""
|
|
241
|
+
return "Set of all cusps of %s" % self.number_field()
|
|
242
|
+
|
|
243
|
+
def _latex_(self):
|
|
244
|
+
r"""
|
|
245
|
+
Return latex representation of ``self``.
|
|
246
|
+
|
|
247
|
+
EXAMPLES::
|
|
248
|
+
|
|
249
|
+
sage: x = polygen(ZZ, 'x')
|
|
250
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
251
|
+
sage: kCusps = NFCusps(k)
|
|
252
|
+
sage: latex(kCusps) # indirect doctest
|
|
253
|
+
\mathbf{P}^1(\Bold{Q}[a]/(a^{2} + 5))
|
|
254
|
+
"""
|
|
255
|
+
return r"\mathbf{P}^1(%s)" % self.number_field()._latex_()
|
|
256
|
+
|
|
257
|
+
def __call__(self, x):
|
|
258
|
+
"""
|
|
259
|
+
Convert x into the set of cusps of a number field.
|
|
260
|
+
|
|
261
|
+
EXAMPLES::
|
|
262
|
+
|
|
263
|
+
sage: x = polygen(ZZ, 'x')
|
|
264
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
265
|
+
sage: kCusps = NFCusps(k)
|
|
266
|
+
sage: c = kCusps(a,2)
|
|
267
|
+
Traceback (most recent call last):
|
|
268
|
+
...
|
|
269
|
+
TypeError: ...__call__() takes 2 positional arguments but 3 were given
|
|
270
|
+
|
|
271
|
+
::
|
|
272
|
+
|
|
273
|
+
sage: c = kCusps((a,2)); c
|
|
274
|
+
Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 5
|
|
275
|
+
sage: kCusps(2/a)
|
|
276
|
+
Cusp [-2*a: 5] of Number Field in a with defining polynomial x^2 + 5
|
|
277
|
+
sage: kCusps(oo)
|
|
278
|
+
Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
|
|
279
|
+
"""
|
|
280
|
+
return NFCusp(self.number_field(), x, parent=self)
|
|
281
|
+
|
|
282
|
+
@cached_method
|
|
283
|
+
def zero(self):
|
|
284
|
+
"""
|
|
285
|
+
Return the zero cusp.
|
|
286
|
+
|
|
287
|
+
.. NOTE::
|
|
288
|
+
|
|
289
|
+
This method just exists to make some general algorithms work.
|
|
290
|
+
It is not intended that the returned cusp is an additive
|
|
291
|
+
neutral element.
|
|
292
|
+
|
|
293
|
+
EXAMPLES::
|
|
294
|
+
|
|
295
|
+
sage: x = polygen(ZZ, 'x')
|
|
296
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
297
|
+
sage: kCusps = NFCusps(k)
|
|
298
|
+
sage: kCusps.zero()
|
|
299
|
+
Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5
|
|
300
|
+
"""
|
|
301
|
+
return self(0)
|
|
302
|
+
|
|
303
|
+
def number_field(self):
|
|
304
|
+
"""
|
|
305
|
+
Return the number field that this set of cusps is attached to.
|
|
306
|
+
|
|
307
|
+
EXAMPLES::
|
|
308
|
+
|
|
309
|
+
sage: x = polygen(ZZ, 'x')
|
|
310
|
+
sage: k.<a> = NumberField(x^2 + 1)
|
|
311
|
+
sage: kCusps = NFCusps(k)
|
|
312
|
+
sage: kCusps.number_field()
|
|
313
|
+
Number Field in a with defining polynomial x^2 + 1
|
|
314
|
+
"""
|
|
315
|
+
return self.__number_field
|
|
316
|
+
|
|
317
|
+
# *************************************************************************
|
|
318
|
+
# NFCusp class *
|
|
319
|
+
# *************************************************************************
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
class NFCusp(Element):
|
|
323
|
+
r"""
|
|
324
|
+
Create a number field cusp, i.e., an element of `\mathbb{P}^1(k)`.
|
|
325
|
+
|
|
326
|
+
A cusp on a number field is either an element of the field or infinity,
|
|
327
|
+
i.e., an element of the projective line over the number field. It is
|
|
328
|
+
stored as a pair (a,b), where a, b are integral elements of the number
|
|
329
|
+
field.
|
|
330
|
+
|
|
331
|
+
INPUT:
|
|
332
|
+
|
|
333
|
+
- ``number_field`` -- the number field over which the cusp is defined
|
|
334
|
+
|
|
335
|
+
- ``a`` -- it can be a number field element (integral or not), or
|
|
336
|
+
a number field cusp
|
|
337
|
+
|
|
338
|
+
- ``b`` -- (optional) when present, it must be either Infinity or
|
|
339
|
+
coercible to an element of the number field
|
|
340
|
+
|
|
341
|
+
- ``lreps`` -- (optional) a list of chosen representatives for all the
|
|
342
|
+
ideal classes of the field. When given, the representative of the cusp
|
|
343
|
+
will be changed so its associated ideal is one of the ideals in the list.
|
|
344
|
+
|
|
345
|
+
OUTPUT:
|
|
346
|
+
|
|
347
|
+
``[a: b]`` -- a number field cusp.
|
|
348
|
+
|
|
349
|
+
EXAMPLES::
|
|
350
|
+
|
|
351
|
+
sage: x = polygen(ZZ, 'x')
|
|
352
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
353
|
+
sage: NFCusp(k, a, 2)
|
|
354
|
+
Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 5
|
|
355
|
+
sage: NFCusp(k, (a,2))
|
|
356
|
+
Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 5
|
|
357
|
+
sage: NFCusp(k, a, 2/(a+1))
|
|
358
|
+
Cusp [a - 5: 2] of Number Field in a with defining polynomial x^2 + 5
|
|
359
|
+
|
|
360
|
+
Cusp Infinity:
|
|
361
|
+
|
|
362
|
+
::
|
|
363
|
+
|
|
364
|
+
sage: NFCusp(k, 0)
|
|
365
|
+
Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5
|
|
366
|
+
sage: NFCusp(k, oo)
|
|
367
|
+
Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
|
|
368
|
+
sage: NFCusp(k, 3*a, oo)
|
|
369
|
+
Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5
|
|
370
|
+
sage: NFCusp(k, a + 5, 0)
|
|
371
|
+
Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
|
|
372
|
+
|
|
373
|
+
Saving and loading works:
|
|
374
|
+
|
|
375
|
+
::
|
|
376
|
+
|
|
377
|
+
sage: alpha = NFCusp(k, a, 2/(a+1))
|
|
378
|
+
sage: loads(dumps(alpha))==alpha
|
|
379
|
+
True
|
|
380
|
+
|
|
381
|
+
Some tests:
|
|
382
|
+
|
|
383
|
+
::
|
|
384
|
+
|
|
385
|
+
sage: I*I
|
|
386
|
+
-1
|
|
387
|
+
sage: NFCusp(k, I)
|
|
388
|
+
Traceback (most recent call last):
|
|
389
|
+
...
|
|
390
|
+
TypeError: unable to convert I to a cusp of the number field
|
|
391
|
+
|
|
392
|
+
::
|
|
393
|
+
|
|
394
|
+
sage: NFCusp(k, oo, oo)
|
|
395
|
+
Traceback (most recent call last):
|
|
396
|
+
...
|
|
397
|
+
TypeError: unable to convert (+Infinity, +Infinity) to a cusp of the number field
|
|
398
|
+
|
|
399
|
+
::
|
|
400
|
+
|
|
401
|
+
sage: NFCusp(k, 0, 0)
|
|
402
|
+
Traceback (most recent call last):
|
|
403
|
+
...
|
|
404
|
+
TypeError: unable to convert (0, 0) to a cusp of the number field
|
|
405
|
+
|
|
406
|
+
::
|
|
407
|
+
|
|
408
|
+
sage: NFCusp(k, "a + 2", a)
|
|
409
|
+
Cusp [-2*a + 5: 5] of Number Field in a with defining polynomial x^2 + 5
|
|
410
|
+
|
|
411
|
+
::
|
|
412
|
+
|
|
413
|
+
sage: NFCusp(k, NFCusp(k, oo))
|
|
414
|
+
Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
|
|
415
|
+
sage: c = NFCusp(k, 3, 2*a)
|
|
416
|
+
sage: NFCusp(k, c, a + 1)
|
|
417
|
+
Cusp [-a - 5: 20] of Number Field in a with defining polynomial x^2 + 5
|
|
418
|
+
sage: L.<b> = NumberField(x^2 + 2)
|
|
419
|
+
sage: NFCusp(L, c)
|
|
420
|
+
Traceback (most recent call last):
|
|
421
|
+
...
|
|
422
|
+
ValueError: Cannot coerce cusps from one field to another
|
|
423
|
+
"""
|
|
424
|
+
def __init__(self, number_field, a, b=None, parent=None, lreps=None):
|
|
425
|
+
"""
|
|
426
|
+
Constructor of number field cusps. See ``NFCusp`` for full
|
|
427
|
+
documentation.
|
|
428
|
+
|
|
429
|
+
EXAMPLES::
|
|
430
|
+
|
|
431
|
+
sage: x = polygen(ZZ, 'x')
|
|
432
|
+
sage: k.<a> = NumberField(x^2 + 1)
|
|
433
|
+
sage: c = NFCusp(k, 3, a+1); c
|
|
434
|
+
Cusp [3: a + 1] of Number Field in a with defining polynomial x^2 + 1
|
|
435
|
+
sage: c.parent()
|
|
436
|
+
Set of all cusps of Number Field in a with defining polynomial x^2 + 1
|
|
437
|
+
sage: kCusps = NFCusps(k)
|
|
438
|
+
sage: c.parent() is kCusps
|
|
439
|
+
True
|
|
440
|
+
"""
|
|
441
|
+
if parent is None:
|
|
442
|
+
parent = NFCusps(number_field)
|
|
443
|
+
Element.__init__(self, parent)
|
|
444
|
+
R = number_field.maximal_order()
|
|
445
|
+
if b is None:
|
|
446
|
+
if not a: # that is cusp "0"
|
|
447
|
+
self.__a = R.zero()
|
|
448
|
+
self.__b = R.one()
|
|
449
|
+
return
|
|
450
|
+
if isinstance(a, NFCusp):
|
|
451
|
+
if a.parent() == parent:
|
|
452
|
+
self.__a = R(a.__a)
|
|
453
|
+
self.__b = R(a.__b)
|
|
454
|
+
else:
|
|
455
|
+
raise ValueError("Cannot coerce cusps from one field to another")
|
|
456
|
+
elif a in R:
|
|
457
|
+
self.__a = R(a)
|
|
458
|
+
self.__b = R.one()
|
|
459
|
+
elif a in number_field:
|
|
460
|
+
self.__b = R(a.denominator())
|
|
461
|
+
self.__a = R(a * self.__b)
|
|
462
|
+
elif isinstance(a, InfinityElement):
|
|
463
|
+
self.__a = R.one()
|
|
464
|
+
self.__b = R.zero()
|
|
465
|
+
elif isinstance(a, int):
|
|
466
|
+
self.__a = R(a)
|
|
467
|
+
self.__b = R.one()
|
|
468
|
+
elif isinstance(a, (tuple, list)):
|
|
469
|
+
if len(a) != 2:
|
|
470
|
+
raise TypeError("unable to convert %r to a cusp \
|
|
471
|
+
of the number field" % a)
|
|
472
|
+
if a[1].is_zero():
|
|
473
|
+
self.__a = R.one()
|
|
474
|
+
self.__b = R.zero()
|
|
475
|
+
elif a[0] in R and a[1] in R:
|
|
476
|
+
self.__a = R(a[0])
|
|
477
|
+
self.__b = R(a[1])
|
|
478
|
+
elif isinstance(a[0], NFCusp): # we know that a[1] is not zero
|
|
479
|
+
if a[1] == 1:
|
|
480
|
+
self.__a = a[0].__a
|
|
481
|
+
self.__b = a[0].__b
|
|
482
|
+
else:
|
|
483
|
+
r = a[0].__a / (a[0].__b * a[1])
|
|
484
|
+
self.__b = R(r.denominator())
|
|
485
|
+
self.__a = R(r * self.__b)
|
|
486
|
+
else:
|
|
487
|
+
try:
|
|
488
|
+
r = number_field(a[0] / a[1])
|
|
489
|
+
self.__b = R(r.denominator())
|
|
490
|
+
self.__a = R(r * self.__b)
|
|
491
|
+
except (ValueError, TypeError):
|
|
492
|
+
raise TypeError(f"unable to convert {a} to a cusp "
|
|
493
|
+
"of the number field")
|
|
494
|
+
else:
|
|
495
|
+
try:
|
|
496
|
+
r = number_field(a)
|
|
497
|
+
self.__b = R(r.denominator())
|
|
498
|
+
self.__a = R(r * self.__b)
|
|
499
|
+
except (ValueError, TypeError):
|
|
500
|
+
raise TypeError("unable to convert %r to a cusp "
|
|
501
|
+
"of the number field" % a)
|
|
502
|
+
else: # 'b' is given
|
|
503
|
+
if isinstance(b, InfinityElement):
|
|
504
|
+
if isinstance(a, InfinityElement) or (isinstance(a, NFCusp) and a.is_infinity()):
|
|
505
|
+
raise TypeError("unable to convert (%r, %r) "
|
|
506
|
+
"to a cusp of the number field" % (a, b))
|
|
507
|
+
self.__a = R.zero()
|
|
508
|
+
self.__b = R.one()
|
|
509
|
+
return
|
|
510
|
+
elif not b:
|
|
511
|
+
if not a:
|
|
512
|
+
raise TypeError("unable to convert (%r, %r) "
|
|
513
|
+
"to a cusp of the number field" % (a, b))
|
|
514
|
+
self.__a = R.one()
|
|
515
|
+
self.__b = R.zero()
|
|
516
|
+
return
|
|
517
|
+
if not a:
|
|
518
|
+
self.__a = R.zero()
|
|
519
|
+
self.__b = R.one()
|
|
520
|
+
return
|
|
521
|
+
if (b in R or isinstance(b, int)) and (a in R or isinstance(a, int)):
|
|
522
|
+
self.__a = R(a)
|
|
523
|
+
self.__b = R(b)
|
|
524
|
+
else:
|
|
525
|
+
if a in R or a in number_field:
|
|
526
|
+
r = a / b
|
|
527
|
+
elif isinstance(a, InfinityElement):
|
|
528
|
+
self.__a = R.one()
|
|
529
|
+
self.__b = R.zero()
|
|
530
|
+
return
|
|
531
|
+
elif isinstance(a, NFCusp):
|
|
532
|
+
if a.is_infinity():
|
|
533
|
+
self.__a = R.one()
|
|
534
|
+
self.__b = R.zero()
|
|
535
|
+
return
|
|
536
|
+
r = a.__a / (a.__b * b)
|
|
537
|
+
elif isinstance(a, int):
|
|
538
|
+
r = R(a) / b
|
|
539
|
+
elif isinstance(a, (tuple, list)):
|
|
540
|
+
if len(a) != 2:
|
|
541
|
+
raise TypeError("unable to convert (%r, %r) \
|
|
542
|
+
to a cusp of the number field" % (a, b))
|
|
543
|
+
r = R(a[0]) / (R(a[1]) * b)
|
|
544
|
+
else:
|
|
545
|
+
try:
|
|
546
|
+
r = number_field(a) / b
|
|
547
|
+
except (ValueError, TypeError):
|
|
548
|
+
raise TypeError("unable to convert (%r, %r) \
|
|
549
|
+
to a cusp of the number field" % (a, b))
|
|
550
|
+
self.__b = R(r.denominator())
|
|
551
|
+
self.__a = R(r * self.__b)
|
|
552
|
+
if lreps is not None:
|
|
553
|
+
# Changes the representative of the cusp so the ideal associated
|
|
554
|
+
# to the cusp is one of the ideals of the given list lreps.
|
|
555
|
+
# Note: the trivial class is always represented by (1).
|
|
556
|
+
I = self.ideal()
|
|
557
|
+
for J in lreps:
|
|
558
|
+
if (J / I).is_principal():
|
|
559
|
+
newI = J
|
|
560
|
+
l = (newI / I).gens_reduced()[0]
|
|
561
|
+
self.__a = R(l * self.__a)
|
|
562
|
+
self.__b = R(l * self.__b)
|
|
563
|
+
|
|
564
|
+
def _repr_(self):
|
|
565
|
+
"""
|
|
566
|
+
String representation of this cusp.
|
|
567
|
+
|
|
568
|
+
EXAMPLES::
|
|
569
|
+
|
|
570
|
+
sage: x = polygen(ZZ, 'x')
|
|
571
|
+
sage: k.<a> = NumberField(x^2 + 1)
|
|
572
|
+
sage: c = NFCusp(k, a, 2); c
|
|
573
|
+
Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 1
|
|
574
|
+
sage: c._repr_()
|
|
575
|
+
'Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 1'
|
|
576
|
+
sage: c.rename('[a:2](cusp of a number field)');c
|
|
577
|
+
[a:2](cusp of a number field)
|
|
578
|
+
sage: c.rename();c
|
|
579
|
+
Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 1
|
|
580
|
+
"""
|
|
581
|
+
if self.__b.is_zero():
|
|
582
|
+
return "Cusp Infinity of %s" % self.parent().number_field()
|
|
583
|
+
else:
|
|
584
|
+
return "Cusp [%s: %s] of %s" % (self.__a, self.__b,
|
|
585
|
+
self.parent().number_field())
|
|
586
|
+
|
|
587
|
+
def number_field(self):
|
|
588
|
+
"""
|
|
589
|
+
Return the number field of definition of the cusp ``self``.
|
|
590
|
+
|
|
591
|
+
EXAMPLES::
|
|
592
|
+
|
|
593
|
+
sage: x = polygen(ZZ, 'x')
|
|
594
|
+
sage: k.<a> = NumberField(x^2 + 2)
|
|
595
|
+
sage: alpha = NFCusp(k, 1, a + 1)
|
|
596
|
+
sage: alpha.number_field()
|
|
597
|
+
Number Field in a with defining polynomial x^2 + 2
|
|
598
|
+
"""
|
|
599
|
+
return self.parent().number_field()
|
|
600
|
+
|
|
601
|
+
def is_infinity(self) -> bool:
|
|
602
|
+
"""
|
|
603
|
+
Return ``True`` if this is the cusp infinity.
|
|
604
|
+
|
|
605
|
+
EXAMPLES::
|
|
606
|
+
|
|
607
|
+
sage: x = polygen(ZZ, 'x')
|
|
608
|
+
sage: k.<a> = NumberField(x^2 + 1)
|
|
609
|
+
sage: NFCusp(k, a, 2).is_infinity()
|
|
610
|
+
False
|
|
611
|
+
sage: NFCusp(k, 2, 0).is_infinity()
|
|
612
|
+
True
|
|
613
|
+
sage: NFCusp(k, oo).is_infinity()
|
|
614
|
+
True
|
|
615
|
+
"""
|
|
616
|
+
return self.__b == 0
|
|
617
|
+
|
|
618
|
+
def numerator(self):
|
|
619
|
+
"""
|
|
620
|
+
Return the numerator of the cusp ``self``.
|
|
621
|
+
|
|
622
|
+
EXAMPLES::
|
|
623
|
+
|
|
624
|
+
sage: x = polygen(ZZ, 'x')
|
|
625
|
+
sage: k.<a> = NumberField(x^2 + 1)
|
|
626
|
+
sage: c = NFCusp(k, a, 2)
|
|
627
|
+
sage: c.numerator()
|
|
628
|
+
a
|
|
629
|
+
sage: d = NFCusp(k, 1, a)
|
|
630
|
+
sage: d.numerator()
|
|
631
|
+
1
|
|
632
|
+
sage: NFCusp(k, oo).numerator()
|
|
633
|
+
1
|
|
634
|
+
"""
|
|
635
|
+
return self.__a
|
|
636
|
+
|
|
637
|
+
def denominator(self):
|
|
638
|
+
"""
|
|
639
|
+
Return the denominator of the cusp ``self``.
|
|
640
|
+
|
|
641
|
+
EXAMPLES::
|
|
642
|
+
|
|
643
|
+
sage: x = polygen(ZZ, 'x')
|
|
644
|
+
sage: k.<a> = NumberField(x^2 + 1)
|
|
645
|
+
sage: c = NFCusp(k, a, 2)
|
|
646
|
+
sage: c.denominator()
|
|
647
|
+
2
|
|
648
|
+
sage: d = NFCusp(k, 1, a + 1);d
|
|
649
|
+
Cusp [1: a + 1] of Number Field in a with defining polynomial x^2 + 1
|
|
650
|
+
sage: d.denominator()
|
|
651
|
+
a + 1
|
|
652
|
+
sage: NFCusp(k, oo).denominator()
|
|
653
|
+
0
|
|
654
|
+
"""
|
|
655
|
+
return self.__b
|
|
656
|
+
|
|
657
|
+
def _number_field_element_(self):
|
|
658
|
+
"""
|
|
659
|
+
Coerce to an element of the number field.
|
|
660
|
+
|
|
661
|
+
EXAMPLES::
|
|
662
|
+
|
|
663
|
+
sage: x = polygen(ZZ, 'x')
|
|
664
|
+
sage: k.<a> = NumberField(x^2 + 2)
|
|
665
|
+
sage: NFCusp(k, a, 2)._number_field_element_()
|
|
666
|
+
1/2*a
|
|
667
|
+
sage: NFCusp(k, 1, a + 1)._number_field_element_()
|
|
668
|
+
-1/3*a + 1/3
|
|
669
|
+
"""
|
|
670
|
+
if self.__b.is_zero():
|
|
671
|
+
raise TypeError("%s is not an element of %s" % (self,
|
|
672
|
+
self.number_field()))
|
|
673
|
+
k = self.number_field()
|
|
674
|
+
return k(self.__a / self.__b)
|
|
675
|
+
|
|
676
|
+
def _ring_of_integers_element_(self):
|
|
677
|
+
"""
|
|
678
|
+
Coerce to an element of the ring of integers of the number field.
|
|
679
|
+
|
|
680
|
+
EXAMPLES::
|
|
681
|
+
|
|
682
|
+
sage: x = polygen(ZZ, 'x')
|
|
683
|
+
sage: k.<a> = NumberField(x^2 + 2)
|
|
684
|
+
sage: NFCusp(k, a+1)._ring_of_integers_element_()
|
|
685
|
+
a + 1
|
|
686
|
+
sage: NFCusp(k, 1, a + 1)._ring_of_integers_element_()
|
|
687
|
+
Traceback (most recent call last):
|
|
688
|
+
...
|
|
689
|
+
TypeError: Cusp [1: a + 1] of Number Field in a with defining polynomial x^2 + 2 is not an integral element
|
|
690
|
+
"""
|
|
691
|
+
if self.__b.is_one():
|
|
692
|
+
return self.__a
|
|
693
|
+
R = self.number_field().ring_of_integers()
|
|
694
|
+
if self.__b.is_zero():
|
|
695
|
+
raise TypeError("%s is not an element of %s" % (self, R))
|
|
696
|
+
try:
|
|
697
|
+
return R(self.__a / self.__b)
|
|
698
|
+
except (ValueError, TypeError):
|
|
699
|
+
raise TypeError("%s is not an integral element" % self)
|
|
700
|
+
|
|
701
|
+
def _latex_(self):
|
|
702
|
+
r"""
|
|
703
|
+
Latex representation of this cusp.
|
|
704
|
+
|
|
705
|
+
EXAMPLES::
|
|
706
|
+
|
|
707
|
+
sage: x = polygen(ZZ, 'x')
|
|
708
|
+
sage: k.<a> = NumberField(x^2 + 11)
|
|
709
|
+
sage: latex(NFCusp(k, 3*a, a + 1)) # indirect doctest
|
|
710
|
+
\[3 a: a + 1\]
|
|
711
|
+
sage: latex(NFCusp(k, 3*a, a + 1)) == NFCusp(k, 3*a, a + 1)._latex_()
|
|
712
|
+
True
|
|
713
|
+
sage: latex(NFCusp(k, oo))
|
|
714
|
+
\infty
|
|
715
|
+
"""
|
|
716
|
+
if self.__b.is_zero():
|
|
717
|
+
return "\\infty"
|
|
718
|
+
else:
|
|
719
|
+
return "\\[%s: %s\\]" % (self.__a._latex_(),
|
|
720
|
+
self.__b._latex_())
|
|
721
|
+
|
|
722
|
+
def _richcmp_(self, right, op):
|
|
723
|
+
"""
|
|
724
|
+
Compare the cusps ``self`` and ``right``.
|
|
725
|
+
|
|
726
|
+
Comparison is as for elements in the number field, except with
|
|
727
|
+
the cusp oo which is greater than everything but itself.
|
|
728
|
+
|
|
729
|
+
The ordering in comparison is only really meaningful for infinity.
|
|
730
|
+
|
|
731
|
+
EXAMPLES::
|
|
732
|
+
|
|
733
|
+
sage: x = polygen(ZZ, 'x')
|
|
734
|
+
sage: k.<a> = NumberField(x^3 + x + 1)
|
|
735
|
+
sage: kCusps = NFCusps(k)
|
|
736
|
+
|
|
737
|
+
Comparing with infinity::
|
|
738
|
+
|
|
739
|
+
sage: c = kCusps((a,2))
|
|
740
|
+
sage: d = kCusps(oo)
|
|
741
|
+
sage: c < d
|
|
742
|
+
True
|
|
743
|
+
sage: kCusps(oo) < d
|
|
744
|
+
False
|
|
745
|
+
|
|
746
|
+
Comparison as elements of the number field::
|
|
747
|
+
|
|
748
|
+
sage: kCusps(2/3) < kCusps(5/2)
|
|
749
|
+
False
|
|
750
|
+
sage: k(2/3) < k(5/2)
|
|
751
|
+
False
|
|
752
|
+
"""
|
|
753
|
+
if self.__b.is_zero():
|
|
754
|
+
if right.__b.is_zero():
|
|
755
|
+
return rich_to_bool(op, 0)
|
|
756
|
+
else:
|
|
757
|
+
return rich_to_bool(op, 1)
|
|
758
|
+
else:
|
|
759
|
+
if right.__b.is_zero():
|
|
760
|
+
return rich_to_bool(op, -1)
|
|
761
|
+
else:
|
|
762
|
+
return richcmp(self._number_field_element_(),
|
|
763
|
+
right._number_field_element_(), op)
|
|
764
|
+
|
|
765
|
+
def __neg__(self):
|
|
766
|
+
"""
|
|
767
|
+
The negative of this cusp.
|
|
768
|
+
|
|
769
|
+
EXAMPLES::
|
|
770
|
+
|
|
771
|
+
sage: x = polygen(ZZ, 'x')
|
|
772
|
+
sage: k.<a> = NumberField(x^2 + 23)
|
|
773
|
+
sage: c = NFCusp(k, a, a+1); c
|
|
774
|
+
Cusp [a: a + 1] of Number Field in a with defining polynomial x^2 + 23
|
|
775
|
+
sage: -c
|
|
776
|
+
Cusp [-a: a + 1] of Number Field in a with defining polynomial x^2 + 23
|
|
777
|
+
"""
|
|
778
|
+
return NFCusp(self.parent().number_field(), -self.__a, self.__b)
|
|
779
|
+
|
|
780
|
+
def apply(self, g):
|
|
781
|
+
"""
|
|
782
|
+
Return g(``self``), where ``g`` is a 2x2 matrix, which we view as a
|
|
783
|
+
linear fractional transformation.
|
|
784
|
+
|
|
785
|
+
INPUT:
|
|
786
|
+
|
|
787
|
+
- ``g`` -- list of integral elements [a, b, c, d] that are the
|
|
788
|
+
entries of a 2x2 matrix
|
|
789
|
+
|
|
790
|
+
OUTPUT:
|
|
791
|
+
|
|
792
|
+
A number field cusp, obtained by the action of ``g`` on the cusp
|
|
793
|
+
``self``.
|
|
794
|
+
|
|
795
|
+
EXAMPLES::
|
|
796
|
+
|
|
797
|
+
sage: x = polygen(ZZ, 'x')
|
|
798
|
+
sage: k.<a> = NumberField(x^2 + 23)
|
|
799
|
+
sage: beta = NFCusp(k, 0, 1)
|
|
800
|
+
sage: beta.apply([0, -1, 1, 0])
|
|
801
|
+
Cusp Infinity of Number Field in a with defining polynomial x^2 + 23
|
|
802
|
+
sage: beta.apply([1, a, 0, 1])
|
|
803
|
+
Cusp [a: 1] of Number Field in a with defining polynomial x^2 + 23
|
|
804
|
+
"""
|
|
805
|
+
k = self.number_field()
|
|
806
|
+
return NFCusp(k, g[0] * self.__a + g[1] * self.__b,
|
|
807
|
+
g[2] * self.__a + g[3] * self.__b)
|
|
808
|
+
|
|
809
|
+
def ideal(self):
|
|
810
|
+
"""
|
|
811
|
+
Return the ideal associated to the cusp ``self``.
|
|
812
|
+
|
|
813
|
+
EXAMPLES::
|
|
814
|
+
|
|
815
|
+
sage: x = polygen(ZZ, 'x')
|
|
816
|
+
sage: k.<a> = NumberField(x^2 + 23)
|
|
817
|
+
sage: alpha = NFCusp(k, 3, a-1)
|
|
818
|
+
sage: alpha.ideal()
|
|
819
|
+
Fractional ideal (3, 1/2*a - 1/2)
|
|
820
|
+
sage: NFCusp(k, oo).ideal()
|
|
821
|
+
Fractional ideal (1)
|
|
822
|
+
"""
|
|
823
|
+
k = self.number_field()
|
|
824
|
+
return k.ideal(self.__a, self.__b)
|
|
825
|
+
|
|
826
|
+
def ABmatrix(self) -> list:
|
|
827
|
+
"""
|
|
828
|
+
Return AB-matrix associated to the cusp ``self``.
|
|
829
|
+
|
|
830
|
+
Given R a Dedekind domain and A, B ideals of R in inverse classes, an
|
|
831
|
+
AB-matrix is a matrix realizing the isomorphism between R+R and A+B.
|
|
832
|
+
An AB-matrix associated to a cusp [a1: a2] is an AB-matrix with A the
|
|
833
|
+
ideal associated to the cusp (A=<a1, a2>) and first column given by
|
|
834
|
+
the coefficients of the cusp.
|
|
835
|
+
|
|
836
|
+
EXAMPLES:
|
|
837
|
+
|
|
838
|
+
::
|
|
839
|
+
|
|
840
|
+
sage: x = polygen(ZZ, 'x')
|
|
841
|
+
sage: k.<a> = NumberField(x^3 + 11)
|
|
842
|
+
sage: alpha = NFCusp(k, oo)
|
|
843
|
+
sage: alpha.ABmatrix()
|
|
844
|
+
[1, 0, 0, 1]
|
|
845
|
+
|
|
846
|
+
::
|
|
847
|
+
|
|
848
|
+
sage: alpha = NFCusp(k, 0)
|
|
849
|
+
sage: alpha.ABmatrix()
|
|
850
|
+
[0, -1, 1, 0]
|
|
851
|
+
|
|
852
|
+
Note that the AB-matrix associated to a cusp is not unique, and the
|
|
853
|
+
output of the ``ABmatrix`` function may change.
|
|
854
|
+
|
|
855
|
+
::
|
|
856
|
+
|
|
857
|
+
sage: alpha = NFCusp(k, 3/2, a-1)
|
|
858
|
+
sage: M = alpha.ABmatrix()
|
|
859
|
+
sage: M # random
|
|
860
|
+
[-a^2 - a - 1, -3*a - 7, 8, -2*a^2 - 3*a + 4]
|
|
861
|
+
sage: M[0] == alpha.numerator() and M[2] == alpha.denominator()
|
|
862
|
+
True
|
|
863
|
+
|
|
864
|
+
An AB-matrix associated to a cusp alpha will send Infinity to alpha:
|
|
865
|
+
|
|
866
|
+
::
|
|
867
|
+
|
|
868
|
+
sage: alpha = NFCusp(k, 3, a-1)
|
|
869
|
+
sage: M = alpha.ABmatrix()
|
|
870
|
+
sage: (k.ideal(M[1], M[3])*alpha.ideal()).is_principal()
|
|
871
|
+
True
|
|
872
|
+
sage: M[0] == alpha.numerator() and M[2] == alpha.denominator()
|
|
873
|
+
True
|
|
874
|
+
sage: NFCusp(k, oo).apply(M) == alpha
|
|
875
|
+
True
|
|
876
|
+
"""
|
|
877
|
+
k = self.number_field()
|
|
878
|
+
A = self.ideal()
|
|
879
|
+
|
|
880
|
+
if self.is_infinity():
|
|
881
|
+
return [1, 0, 0, 1]
|
|
882
|
+
if not self:
|
|
883
|
+
return [0, -1, 1, 0]
|
|
884
|
+
|
|
885
|
+
if A.is_principal():
|
|
886
|
+
B = k.ideal(1)
|
|
887
|
+
else:
|
|
888
|
+
B = k.ideal(A.gens_reduced()[1]) / A
|
|
889
|
+
assert (A * B).is_principal()
|
|
890
|
+
|
|
891
|
+
a1 = self.__a
|
|
892
|
+
a2 = self.__b
|
|
893
|
+
|
|
894
|
+
g = (A * B).gens_reduced()[0]
|
|
895
|
+
Ainv = A**(-1)
|
|
896
|
+
A1 = a1 * Ainv
|
|
897
|
+
A2 = a2 * Ainv
|
|
898
|
+
r = A1.element_1_mod(A2)
|
|
899
|
+
b1 = -(1 - r) / a2 * g
|
|
900
|
+
b2 = (r / a1) * g
|
|
901
|
+
return [a1, b1, a2, b2]
|
|
902
|
+
|
|
903
|
+
def is_Gamma0_equivalent(self, other, N,
|
|
904
|
+
Transformation=False) -> bool | tuple[bool, Any]:
|
|
905
|
+
r"""
|
|
906
|
+
Check if cusps ``self`` and ``other`` are `\Gamma_0(N)`- equivalent.
|
|
907
|
+
|
|
908
|
+
INPUT:
|
|
909
|
+
|
|
910
|
+
- ``other`` -- a number field cusp or a list of two number field
|
|
911
|
+
elements which define a cusp
|
|
912
|
+
|
|
913
|
+
- ``N`` -- an ideal of the number field (level)
|
|
914
|
+
|
|
915
|
+
OUTPUT: boolean; ``True`` if the cusps are equivalent
|
|
916
|
+
|
|
917
|
+
- a transformation matrix -- (if ``Transformation=True``) a list of
|
|
918
|
+
integral elements [a, b, c, d] which are the entries of a 2x2 matrix
|
|
919
|
+
M in `\Gamma_0(N)` such that M * ``self`` = ``other`` if ``other``
|
|
920
|
+
and ``self`` are `\Gamma_0(N)`- equivalent. If ``self`` and ``other``
|
|
921
|
+
are not equivalent it returns zero.
|
|
922
|
+
|
|
923
|
+
EXAMPLES:
|
|
924
|
+
|
|
925
|
+
::
|
|
926
|
+
|
|
927
|
+
sage: x = polygen(ZZ, 'x')
|
|
928
|
+
sage: K.<a> = NumberField(x^3 - 10)
|
|
929
|
+
sage: N = K.ideal(a - 1)
|
|
930
|
+
sage: alpha = NFCusp(K, 0)
|
|
931
|
+
sage: beta = NFCusp(K, oo)
|
|
932
|
+
sage: alpha.is_Gamma0_equivalent(beta, N)
|
|
933
|
+
False
|
|
934
|
+
sage: alpha.is_Gamma0_equivalent(beta, K.ideal(1))
|
|
935
|
+
True
|
|
936
|
+
sage: b, M = alpha.is_Gamma0_equivalent(beta, K.ideal(1),Transformation=True)
|
|
937
|
+
sage: alpha.apply(M)
|
|
938
|
+
Cusp Infinity of Number Field in a with defining polynomial x^3 - 10
|
|
939
|
+
|
|
940
|
+
::
|
|
941
|
+
|
|
942
|
+
sage: k.<a> = NumberField(x^2 + 23)
|
|
943
|
+
sage: N = k.ideal(3)
|
|
944
|
+
sage: alpha1 = NFCusp(k, a+1, 4)
|
|
945
|
+
sage: alpha2 = NFCusp(k, a-8, 29)
|
|
946
|
+
sage: alpha1.is_Gamma0_equivalent(alpha2, N)
|
|
947
|
+
True
|
|
948
|
+
sage: b, M = alpha1.is_Gamma0_equivalent(alpha2, N, Transformation=True)
|
|
949
|
+
sage: alpha1.apply(M) == alpha2
|
|
950
|
+
True
|
|
951
|
+
sage: M[2] in N
|
|
952
|
+
True
|
|
953
|
+
"""
|
|
954
|
+
k = self.number_field()
|
|
955
|
+
other = NFCusp(k, other)
|
|
956
|
+
if not (self.ideal() / other.ideal()).is_principal():
|
|
957
|
+
if not Transformation:
|
|
958
|
+
return False
|
|
959
|
+
else:
|
|
960
|
+
return False, 0
|
|
961
|
+
|
|
962
|
+
reps = list_of_representatives(N)
|
|
963
|
+
alpha1 = NFCusp(k, self, lreps=reps)
|
|
964
|
+
alpha2 = NFCusp(k, other, lreps=reps)
|
|
965
|
+
|
|
966
|
+
delta = k.ideal(alpha1.__b) + N
|
|
967
|
+
if (k.ideal(alpha2.__b) + N) != delta:
|
|
968
|
+
if not Transformation:
|
|
969
|
+
return False
|
|
970
|
+
else:
|
|
971
|
+
return False, 0
|
|
972
|
+
|
|
973
|
+
M1 = alpha1.ABmatrix()
|
|
974
|
+
M2 = alpha2.ABmatrix()
|
|
975
|
+
|
|
976
|
+
A = alpha1.ideal()
|
|
977
|
+
B = k.ideal(M1[1], M1[3])
|
|
978
|
+
|
|
979
|
+
ABdelta = A * B * delta * delta
|
|
980
|
+
|
|
981
|
+
units = units_mod_ideal(ABdelta)
|
|
982
|
+
for u in units:
|
|
983
|
+
if (M2[2] * M1[3] - u * M1[2] * M2[3]) in ABdelta:
|
|
984
|
+
if not Transformation:
|
|
985
|
+
return True
|
|
986
|
+
else:
|
|
987
|
+
AuxCoeff = [1, 0, 0, 1]
|
|
988
|
+
Aux = M2[2] * M1[3] - u * M1[2] * M2[3]
|
|
989
|
+
if Aux in A * B * N:
|
|
990
|
+
if u != 1:
|
|
991
|
+
AuxCoeff[3] = u
|
|
992
|
+
else:
|
|
993
|
+
A1 = (A * B * N) / ABdelta
|
|
994
|
+
A2 = B * k.ideal(M1[2] * M2[2]) / (A * ABdelta)
|
|
995
|
+
f = A1.element_1_mod(A2)
|
|
996
|
+
w = ((1 - f) * Aux) / (M1[2] * M2[2])
|
|
997
|
+
AuxCoeff[3] = u
|
|
998
|
+
AuxCoeff[1] = w
|
|
999
|
+
from sage.matrix.constructor import Matrix
|
|
1000
|
+
Maux = Matrix(k, 2, AuxCoeff)
|
|
1001
|
+
M1inv = Matrix(k, 2, M1).inverse()
|
|
1002
|
+
Mtrans = Matrix(k, 2, M2) * Maux * M1inv
|
|
1003
|
+
assert Mtrans[1][0] in N
|
|
1004
|
+
return True, Mtrans.list()
|
|
1005
|
+
if not Transformation:
|
|
1006
|
+
return False
|
|
1007
|
+
else:
|
|
1008
|
+
return False, 0
|
|
1009
|
+
|
|
1010
|
+
# *************************************************************************
|
|
1011
|
+
# Global functions:
|
|
1012
|
+
# - Gamma0_NFCusps --compute list of inequivalent cusps
|
|
1013
|
+
# Internal use only:
|
|
1014
|
+
# - number_of_Gamma0_NFCusps -- useful to test Gamma0_NFCusps
|
|
1015
|
+
# - NFCusps_ideal_reps_for_levelN -- lists of reps for ideal classes
|
|
1016
|
+
# - units_mod_ideal -- needed to check Gamma0(N)-equiv of cusps
|
|
1017
|
+
# *************************************************************************
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
def Gamma0_NFCusps(N):
|
|
1021
|
+
r"""
|
|
1022
|
+
Return a list of inequivalent cusps for `\Gamma_0(N)`, i.e., a set of
|
|
1023
|
+
representatives for the orbits of ``self`` on `\mathbb{P}^1(k)`.
|
|
1024
|
+
|
|
1025
|
+
INPUT:
|
|
1026
|
+
|
|
1027
|
+
- ``N`` -- an integral ideal of the number field k (the level)
|
|
1028
|
+
|
|
1029
|
+
OUTPUT: list of inequivalent number field cusps
|
|
1030
|
+
|
|
1031
|
+
EXAMPLES::
|
|
1032
|
+
|
|
1033
|
+
sage: x = polygen(ZZ, 'x')
|
|
1034
|
+
sage: k.<a> = NumberField(x^2 + 5)
|
|
1035
|
+
sage: N = k.ideal(3)
|
|
1036
|
+
sage: L = Gamma0_NFCusps(N)
|
|
1037
|
+
|
|
1038
|
+
The cusps in the list are inequivalent::
|
|
1039
|
+
|
|
1040
|
+
sage: any(L[i].is_Gamma0_equivalent(L[j], N)
|
|
1041
|
+
....: for i in range(len(L)) for j in range(len(L)) if i < j)
|
|
1042
|
+
False
|
|
1043
|
+
|
|
1044
|
+
We test that we obtain the right number of orbits::
|
|
1045
|
+
|
|
1046
|
+
sage: from sage.modular.cusps_nf import number_of_Gamma0_NFCusps
|
|
1047
|
+
sage: len(L) == number_of_Gamma0_NFCusps(N)
|
|
1048
|
+
True
|
|
1049
|
+
|
|
1050
|
+
Another example::
|
|
1051
|
+
|
|
1052
|
+
sage: x = polygen(ZZ, 'x')
|
|
1053
|
+
sage: k.<a> = NumberField(x^4 - x^3 -21*x^2 + 17*x + 133)
|
|
1054
|
+
sage: N = k.ideal(5)
|
|
1055
|
+
sage: from sage.modular.cusps_nf import number_of_Gamma0_NFCusps
|
|
1056
|
+
sage: len(Gamma0_NFCusps(N)) == number_of_Gamma0_NFCusps(N) # long time (over 1 sec)
|
|
1057
|
+
True
|
|
1058
|
+
"""
|
|
1059
|
+
# We create L a list of three lists, which are different and each a list of
|
|
1060
|
+
# prime ideals, coprime to N, representing the ideal classes of k
|
|
1061
|
+
L = NFCusps_ideal_reps_for_levelN(N, nlists=3)
|
|
1062
|
+
Laux = L[1] + L[2]
|
|
1063
|
+
Lreps = list_of_representatives(N)
|
|
1064
|
+
Lcusps = []
|
|
1065
|
+
|
|
1066
|
+
k = N.number_field()
|
|
1067
|
+
|
|
1068
|
+
for A in L[0]:
|
|
1069
|
+
# find B in inverse class:
|
|
1070
|
+
if A.is_trivial():
|
|
1071
|
+
B = k.ideal(1)
|
|
1072
|
+
# B = k.unit_ideal() produces an error because we need fract ideal
|
|
1073
|
+
g = 1
|
|
1074
|
+
else:
|
|
1075
|
+
Lbs = [P for P in Laux if (P * A).is_principal()]
|
|
1076
|
+
B = Lbs[0]
|
|
1077
|
+
g = (A * B).gens_reduced()[0]
|
|
1078
|
+
|
|
1079
|
+
# for every divisor of N we have to find cusps
|
|
1080
|
+
from sage.arith.misc import divisors
|
|
1081
|
+
for d in divisors(N):
|
|
1082
|
+
# find delta prime coprime to B in inverse class of d*A
|
|
1083
|
+
# by searching in our list of auxiliary prime ideals
|
|
1084
|
+
Lds = [P for P in Laux
|
|
1085
|
+
if (P * d * A).is_principal() and P.is_coprime(B)]
|
|
1086
|
+
deltap = Lds[0]
|
|
1087
|
+
a = (deltap * d * A).gens_reduced()[0]
|
|
1088
|
+
I = d + N / d
|
|
1089
|
+
# special case: A=B=d=<1>:
|
|
1090
|
+
if a.is_one() and I.is_trivial():
|
|
1091
|
+
Lcusps.append(NFCusp(k, 0, 1, lreps=Lreps))
|
|
1092
|
+
else:
|
|
1093
|
+
u = k.unit_group().gens()
|
|
1094
|
+
for b in I.invertible_residues_mod(u):
|
|
1095
|
+
# Note: if I trivial, invertible_residues_mod returns [1]
|
|
1096
|
+
# lift b to (R/a)star
|
|
1097
|
+
# we need the part of d which is coprime to I, call it M
|
|
1098
|
+
M = d.prime_to_idealM_part(I)
|
|
1099
|
+
deltAM = deltap * A * M
|
|
1100
|
+
u = (B * deltAM).element_1_mod(I)
|
|
1101
|
+
v = (I * B).element_1_mod(deltAM)
|
|
1102
|
+
newb = u * b + v
|
|
1103
|
+
# build AB-matrix:
|
|
1104
|
+
# ----> extended gcd for k.ideal(a), k.ideal(newb)
|
|
1105
|
+
Y = k.ideal(newb).element_1_mod(k.ideal(a))
|
|
1106
|
+
# if xa + yb = 1, cusp = y*g /a
|
|
1107
|
+
Lcusps.append(NFCusp(k, Y * g, a, lreps=Lreps))
|
|
1108
|
+
return Lcusps
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
def number_of_Gamma0_NFCusps(N):
|
|
1112
|
+
"""
|
|
1113
|
+
Return the total number of orbits of cusps under the action of the
|
|
1114
|
+
congruence subgroup `\\Gamma_0(N)`.
|
|
1115
|
+
|
|
1116
|
+
INPUT:
|
|
1117
|
+
|
|
1118
|
+
- ``N`` -- a number field ideal
|
|
1119
|
+
|
|
1120
|
+
OUTPUT: integer; the number of orbits of cusps under Gamma0(N)-action
|
|
1121
|
+
|
|
1122
|
+
EXAMPLES::
|
|
1123
|
+
|
|
1124
|
+
sage: x = polygen(ZZ, 'x')
|
|
1125
|
+
sage: k.<a> = NumberField(x^3 + 11)
|
|
1126
|
+
sage: N = k.ideal(2, a+1)
|
|
1127
|
+
sage: from sage.modular.cusps_nf import number_of_Gamma0_NFCusps
|
|
1128
|
+
sage: number_of_Gamma0_NFCusps(N)
|
|
1129
|
+
4
|
|
1130
|
+
sage: L = Gamma0_NFCusps(N)
|
|
1131
|
+
sage: len(L) == number_of_Gamma0_NFCusps(N)
|
|
1132
|
+
True
|
|
1133
|
+
sage: k.<a> = NumberField(x^2 + 7)
|
|
1134
|
+
sage: N = k.ideal(9)
|
|
1135
|
+
sage: number_of_Gamma0_NFCusps(N)
|
|
1136
|
+
6
|
|
1137
|
+
sage: N = k.ideal(a*9 + 7)
|
|
1138
|
+
sage: number_of_Gamma0_NFCusps(N)
|
|
1139
|
+
24
|
|
1140
|
+
"""
|
|
1141
|
+
k = N.number_field()
|
|
1142
|
+
# The number of Gamma0(N)-sub-orbits for each Gamma-orbit:
|
|
1143
|
+
from sage.arith.misc import divisors
|
|
1144
|
+
Ugens = [k(u) for u in k.unit_group().gens()]
|
|
1145
|
+
s = sum([len((d + N / d).invertible_residues_mod(Ugens))
|
|
1146
|
+
for d in divisors(N)])
|
|
1147
|
+
# There are h Gamma-orbits, with h class number of underlying number field.
|
|
1148
|
+
return s * k.class_number()
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
def NFCusps_ideal_reps_for_levelN(N, nlists=1):
|
|
1152
|
+
"""
|
|
1153
|
+
Return a list of lists (``nlists`` different lists) of prime ideals,
|
|
1154
|
+
coprime to ``N``, representing every ideal class of the number field.
|
|
1155
|
+
|
|
1156
|
+
INPUT:
|
|
1157
|
+
|
|
1158
|
+
- ``N`` -- number field ideal
|
|
1159
|
+
|
|
1160
|
+
- ``nlists`` -- (default: 1) the number of lists of prime ideals
|
|
1161
|
+
we want
|
|
1162
|
+
|
|
1163
|
+
OUTPUT:
|
|
1164
|
+
|
|
1165
|
+
A list of lists of ideals representatives of the ideal classes, all coprime
|
|
1166
|
+
to ``N``, representing every ideal.
|
|
1167
|
+
|
|
1168
|
+
EXAMPLES::
|
|
1169
|
+
|
|
1170
|
+
sage: x = polygen(ZZ, 'x')
|
|
1171
|
+
sage: k.<a> = NumberField(x^3 + 11)
|
|
1172
|
+
sage: N = k.ideal(5, a + 1)
|
|
1173
|
+
sage: from sage.modular.cusps_nf import NFCusps_ideal_reps_for_levelN
|
|
1174
|
+
sage: NFCusps_ideal_reps_for_levelN(N)
|
|
1175
|
+
[(Fractional ideal (1), Fractional ideal (2, a + 1))]
|
|
1176
|
+
sage: L = NFCusps_ideal_reps_for_levelN(N, 3)
|
|
1177
|
+
sage: all(len(L[i]) == k.class_number() for i in range(len(L)))
|
|
1178
|
+
True
|
|
1179
|
+
|
|
1180
|
+
::
|
|
1181
|
+
|
|
1182
|
+
sage: k.<a> = NumberField(x^4 - x^3 - 21*x^2 + 17*x + 133)
|
|
1183
|
+
sage: N = k.ideal(6)
|
|
1184
|
+
sage: from sage.modular.cusps_nf import NFCusps_ideal_reps_for_levelN
|
|
1185
|
+
sage: NFCusps_ideal_reps_for_levelN(N)
|
|
1186
|
+
[(Fractional ideal (1),
|
|
1187
|
+
Fractional ideal (67, -4/7*a^3 + 13/7*a^2 + 39/7*a - 43),
|
|
1188
|
+
Fractional ideal (127, -4/7*a^3 + 13/7*a^2 + 39/7*a - 42),
|
|
1189
|
+
Fractional ideal (157, -4/7*a^3 + 13/7*a^2 + 39/7*a + 48))]
|
|
1190
|
+
sage: L = NFCusps_ideal_reps_for_levelN(N, 5)
|
|
1191
|
+
sage: all(len(L[i]) == k.class_number() for i in range(len(L)))
|
|
1192
|
+
True
|
|
1193
|
+
"""
|
|
1194
|
+
k = N.number_field()
|
|
1195
|
+
G = k.class_group()
|
|
1196
|
+
L = [[k.ideal(1)] for _ in range(nlists)]
|
|
1197
|
+
it = k.primes_of_degree_one_iter()
|
|
1198
|
+
for I in G.list():
|
|
1199
|
+
check = 0
|
|
1200
|
+
if not I.is_principal():
|
|
1201
|
+
Iinv = I.ideal()**(-1)
|
|
1202
|
+
while check < nlists:
|
|
1203
|
+
J = next(it)
|
|
1204
|
+
if (J * Iinv).is_principal() and J.is_coprime(N):
|
|
1205
|
+
L[check].append(J)
|
|
1206
|
+
check += 1
|
|
1207
|
+
return [tuple(l) for l in L]
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
def units_mod_ideal(I):
|
|
1211
|
+
"""
|
|
1212
|
+
Return integral elements of the number field representing the images of
|
|
1213
|
+
the global units modulo the ideal ``I``.
|
|
1214
|
+
|
|
1215
|
+
INPUT:
|
|
1216
|
+
|
|
1217
|
+
- ``I`` -- number field ideal
|
|
1218
|
+
|
|
1219
|
+
OUTPUT:
|
|
1220
|
+
|
|
1221
|
+
A list of integral elements of the number field representing the images of
|
|
1222
|
+
the global units modulo the ideal ``I``. Elements of the list might be
|
|
1223
|
+
equivalent to each other mod ``I``.
|
|
1224
|
+
|
|
1225
|
+
EXAMPLES::
|
|
1226
|
+
|
|
1227
|
+
sage: from sage.modular.cusps_nf import units_mod_ideal
|
|
1228
|
+
sage: x = polygen(ZZ, 'x')
|
|
1229
|
+
sage: k.<a> = NumberField(x^2 + 1)
|
|
1230
|
+
sage: I = k.ideal(a + 1)
|
|
1231
|
+
sage: units_mod_ideal(I)
|
|
1232
|
+
[1]
|
|
1233
|
+
sage: I = k.ideal(3)
|
|
1234
|
+
sage: units_mod_ideal(I)
|
|
1235
|
+
[1, a, -1, -a]
|
|
1236
|
+
|
|
1237
|
+
::
|
|
1238
|
+
|
|
1239
|
+
sage: from sage.modular.cusps_nf import units_mod_ideal
|
|
1240
|
+
sage: k.<a> = NumberField(x^3 + 11)
|
|
1241
|
+
sage: k.unit_group()
|
|
1242
|
+
Unit group with structure C2 x Z of
|
|
1243
|
+
Number Field in a with defining polynomial x^3 + 11
|
|
1244
|
+
sage: I = k.ideal(5, a + 1)
|
|
1245
|
+
sage: units_mod_ideal(I)
|
|
1246
|
+
[1,
|
|
1247
|
+
2*a^2 + 4*a - 1,
|
|
1248
|
+
...]
|
|
1249
|
+
|
|
1250
|
+
::
|
|
1251
|
+
|
|
1252
|
+
sage: from sage.modular.cusps_nf import units_mod_ideal
|
|
1253
|
+
sage: k.<a> = NumberField(x^4 - x^3 -21*x^2 + 17*x + 133)
|
|
1254
|
+
sage: k.unit_group()
|
|
1255
|
+
Unit group with structure C6 x Z of
|
|
1256
|
+
Number Field in a with defining polynomial x^4 - x^3 - 21*x^2 + 17*x + 133
|
|
1257
|
+
sage: I = k.ideal(3)
|
|
1258
|
+
sage: U = units_mod_ideal(I)
|
|
1259
|
+
sage: all(U[j].is_unit() and (U[j] not in I) for j in range(len(U)))
|
|
1260
|
+
True
|
|
1261
|
+
"""
|
|
1262
|
+
k = I.number_field()
|
|
1263
|
+
Uk = k.unit_group()
|
|
1264
|
+
Istar = I.idealstar(2)
|
|
1265
|
+
ulist = Uk.gens_values()
|
|
1266
|
+
elist = [Istar(I.ideallog(u)).order() for u in ulist]
|
|
1267
|
+
|
|
1268
|
+
from sage.misc.mrange import xmrange
|
|
1269
|
+
|
|
1270
|
+
return [k.prod(u**e for u, e in zip(ulist, ei)) for ei in xmrange(elist)]
|