passagemath-schemes 10.6.40__cp314-cp314-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-schemes might be problematic. Click here for more details.
- passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
- passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
- passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
- passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
- passagemath_schemes/__init__.py +3 -0
- passagemath_schemes-10.6.40.dist-info/METADATA +204 -0
- passagemath_schemes-10.6.40.dist-info/METADATA.bak +205 -0
- passagemath_schemes-10.6.40.dist-info/RECORD +314 -0
- passagemath_schemes-10.6.40.dist-info/WHEEL +6 -0
- passagemath_schemes-10.6.40.dist-info/top_level.txt +3 -0
- sage/all__sagemath_schemes.py +23 -0
- sage/databases/all__sagemath_schemes.py +7 -0
- sage/databases/cremona.py +1723 -0
- sage/dynamics/all__sagemath_schemes.py +2 -0
- sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
- sage/dynamics/arithmetic_dynamics/all.py +14 -0
- sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
- sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
- sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
- sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
- sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
- sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
- sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314-darwin.so +0 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
- sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
- sage/lfunctions/all.py +18 -0
- sage/lfunctions/dokchitser.py +745 -0
- sage/lfunctions/pari.py +818 -0
- sage/lfunctions/zero_sums.cpython-314-darwin.so +0 -0
- sage/lfunctions/zero_sums.pyx +1847 -0
- sage/modular/abvar/abvar.py +5135 -0
- sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
- sage/modular/abvar/abvar_newform.py +244 -0
- sage/modular/abvar/all.py +8 -0
- sage/modular/abvar/constructor.py +186 -0
- sage/modular/abvar/cuspidal_subgroup.py +371 -0
- sage/modular/abvar/finite_subgroup.py +896 -0
- sage/modular/abvar/homology.py +720 -0
- sage/modular/abvar/homspace.py +998 -0
- sage/modular/abvar/lseries.py +415 -0
- sage/modular/abvar/morphism.py +935 -0
- sage/modular/abvar/torsion_point.py +274 -0
- sage/modular/abvar/torsion_subgroup.py +740 -0
- sage/modular/all.py +43 -0
- sage/modular/arithgroup/all.py +20 -0
- sage/modular/arithgroup/arithgroup_element.cpython-314-darwin.so +0 -0
- sage/modular/arithgroup/arithgroup_element.pyx +474 -0
- sage/modular/arithgroup/arithgroup_generic.py +1402 -0
- sage/modular/arithgroup/arithgroup_perm.py +2692 -0
- sage/modular/arithgroup/congroup.cpython-314-darwin.so +0 -0
- sage/modular/arithgroup/congroup.pyx +334 -0
- sage/modular/arithgroup/congroup_gamma.py +363 -0
- sage/modular/arithgroup/congroup_gamma0.py +692 -0
- sage/modular/arithgroup/congroup_gamma1.py +653 -0
- sage/modular/arithgroup/congroup_gammaH.py +1469 -0
- sage/modular/arithgroup/congroup_generic.py +628 -0
- sage/modular/arithgroup/congroup_sl2z.py +267 -0
- sage/modular/arithgroup/farey_symbol.cpython-314-darwin.so +0 -0
- sage/modular/arithgroup/farey_symbol.pyx +1066 -0
- sage/modular/arithgroup/tests.py +418 -0
- sage/modular/btquotients/all.py +4 -0
- sage/modular/btquotients/btquotient.py +3753 -0
- sage/modular/btquotients/pautomorphicform.py +2570 -0
- sage/modular/buzzard.py +100 -0
- sage/modular/congroup.py +29 -0
- sage/modular/congroup_element.py +13 -0
- sage/modular/cusps.py +1109 -0
- sage/modular/cusps_nf.py +1270 -0
- sage/modular/dims.py +569 -0
- sage/modular/dirichlet.py +3310 -0
- sage/modular/drinfeld_modform/all.py +2 -0
- sage/modular/drinfeld_modform/element.py +446 -0
- sage/modular/drinfeld_modform/ring.py +773 -0
- sage/modular/drinfeld_modform/tutorial.py +236 -0
- sage/modular/etaproducts.py +1065 -0
- sage/modular/hecke/algebra.py +746 -0
- sage/modular/hecke/all.py +20 -0
- sage/modular/hecke/ambient_module.py +1019 -0
- sage/modular/hecke/degenmap.py +119 -0
- sage/modular/hecke/element.py +325 -0
- sage/modular/hecke/hecke_operator.py +780 -0
- sage/modular/hecke/homspace.py +206 -0
- sage/modular/hecke/module.py +1767 -0
- sage/modular/hecke/morphism.py +174 -0
- sage/modular/hecke/submodule.py +989 -0
- sage/modular/hypergeometric_misc.cpython-314-darwin.so +0 -0
- sage/modular/hypergeometric_misc.pxd +4 -0
- sage/modular/hypergeometric_misc.pyx +166 -0
- sage/modular/hypergeometric_motive.py +2017 -0
- sage/modular/local_comp/all.py +2 -0
- sage/modular/local_comp/liftings.py +292 -0
- sage/modular/local_comp/local_comp.py +1071 -0
- sage/modular/local_comp/smoothchar.py +1825 -0
- sage/modular/local_comp/type_space.py +748 -0
- sage/modular/modform/all.py +30 -0
- sage/modular/modform/ambient.py +815 -0
- sage/modular/modform/ambient_R.py +177 -0
- sage/modular/modform/ambient_eps.py +306 -0
- sage/modular/modform/ambient_g0.py +124 -0
- sage/modular/modform/ambient_g1.py +204 -0
- sage/modular/modform/constructor.py +545 -0
- sage/modular/modform/cuspidal_submodule.py +708 -0
- sage/modular/modform/defaults.py +14 -0
- sage/modular/modform/eis_series.py +505 -0
- sage/modular/modform/eisenstein_submodule.py +663 -0
- sage/modular/modform/element.py +4131 -0
- sage/modular/modform/find_generators.py +59 -0
- sage/modular/modform/half_integral.py +154 -0
- sage/modular/modform/hecke_operator_on_qexp.py +247 -0
- sage/modular/modform/j_invariant.py +47 -0
- sage/modular/modform/l_series_gross_zagier.py +133 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314-darwin.so +0 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
- sage/modular/modform/notes.py +45 -0
- sage/modular/modform/numerical.py +514 -0
- sage/modular/modform/periods.py +14 -0
- sage/modular/modform/ring.py +1257 -0
- sage/modular/modform/space.py +1860 -0
- sage/modular/modform/submodule.py +118 -0
- sage/modular/modform/tests.py +64 -0
- sage/modular/modform/theta.py +110 -0
- sage/modular/modform/vm_basis.py +381 -0
- sage/modular/modform/weight1.py +220 -0
- sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
- sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
- sage/modular/modform_hecketriangle/all.py +30 -0
- sage/modular/modform_hecketriangle/analytic_type.py +590 -0
- sage/modular/modform_hecketriangle/constructor.py +416 -0
- sage/modular/modform_hecketriangle/element.py +351 -0
- sage/modular/modform_hecketriangle/functors.py +752 -0
- sage/modular/modform_hecketriangle/graded_ring.py +541 -0
- sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
- sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
- sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
- sage/modular/modform_hecketriangle/readme.py +1214 -0
- sage/modular/modform_hecketriangle/series_constructor.py +580 -0
- sage/modular/modform_hecketriangle/space.py +1037 -0
- sage/modular/modform_hecketriangle/subspace.py +423 -0
- sage/modular/modsym/all.py +17 -0
- sage/modular/modsym/ambient.py +3846 -0
- sage/modular/modsym/boundary.py +1420 -0
- sage/modular/modsym/element.py +336 -0
- sage/modular/modsym/g1list.py +178 -0
- sage/modular/modsym/ghlist.py +182 -0
- sage/modular/modsym/hecke_operator.py +73 -0
- sage/modular/modsym/manin_symbol.cpython-314-darwin.so +0 -0
- sage/modular/modsym/manin_symbol.pxd +5 -0
- sage/modular/modsym/manin_symbol.pyx +497 -0
- sage/modular/modsym/manin_symbol_list.py +1295 -0
- sage/modular/modsym/modsym.py +400 -0
- sage/modular/modsym/modular_symbols.py +384 -0
- sage/modular/modsym/p1list.cpython-314-darwin.so +0 -0
- sage/modular/modsym/p1list.pxd +29 -0
- sage/modular/modsym/p1list.pyx +1372 -0
- sage/modular/modsym/p1list_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-314-darwin.so +0 -0
- sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
- sage/modular/modsym/space.py +2468 -0
- sage/modular/modsym/subspace.py +455 -0
- sage/modular/modsym/tests.py +375 -0
- sage/modular/multiple_zeta.py +2632 -0
- sage/modular/multiple_zeta_F_algebra.py +786 -0
- sage/modular/overconvergent/all.py +6 -0
- sage/modular/overconvergent/genus0.py +1878 -0
- sage/modular/overconvergent/hecke_series.py +1187 -0
- sage/modular/overconvergent/weightspace.py +778 -0
- sage/modular/pollack_stevens/all.py +4 -0
- sage/modular/pollack_stevens/distributions.py +874 -0
- sage/modular/pollack_stevens/fund_domain.py +1572 -0
- sage/modular/pollack_stevens/manin_map.py +859 -0
- sage/modular/pollack_stevens/modsym.py +1593 -0
- sage/modular/pollack_stevens/padic_lseries.py +417 -0
- sage/modular/pollack_stevens/sigma0.py +534 -0
- sage/modular/pollack_stevens/space.py +1076 -0
- sage/modular/quasimodform/all.py +3 -0
- sage/modular/quasimodform/element.py +845 -0
- sage/modular/quasimodform/ring.py +828 -0
- sage/modular/quatalg/all.py +3 -0
- sage/modular/quatalg/brandt.py +1642 -0
- sage/modular/ssmod/all.py +8 -0
- sage/modular/ssmod/ssmod.py +827 -0
- sage/rings/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/binary_form_reduce.py +585 -0
- sage/schemes/all.py +41 -0
- sage/schemes/berkovich/all.py +6 -0
- sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
- sage/schemes/berkovich/berkovich_space.py +748 -0
- sage/schemes/curves/affine_curve.py +2928 -0
- sage/schemes/curves/all.py +33 -0
- sage/schemes/curves/closed_point.py +434 -0
- sage/schemes/curves/constructor.py +381 -0
- sage/schemes/curves/curve.py +542 -0
- sage/schemes/curves/plane_curve_arrangement.py +1283 -0
- sage/schemes/curves/point.py +463 -0
- sage/schemes/curves/projective_curve.py +3026 -0
- sage/schemes/curves/zariski_vankampen.py +1932 -0
- sage/schemes/cyclic_covers/all.py +2 -0
- sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
- sage/schemes/cyclic_covers/constructor.py +137 -0
- sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
- sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
- sage/schemes/elliptic_curves/BSD.py +1036 -0
- sage/schemes/elliptic_curves/Qcurves.py +592 -0
- sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
- sage/schemes/elliptic_curves/all.py +49 -0
- sage/schemes/elliptic_curves/cardinality.py +609 -0
- sage/schemes/elliptic_curves/cm.py +1102 -0
- sage/schemes/elliptic_curves/constructor.py +1552 -0
- sage/schemes/elliptic_curves/ec_database.py +175 -0
- sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
- sage/schemes/elliptic_curves/ell_egros.py +459 -0
- sage/schemes/elliptic_curves/ell_field.py +2836 -0
- sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
- sage/schemes/elliptic_curves/ell_generic.py +3760 -0
- sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
- sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
- sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
- sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
- sage/schemes/elliptic_curves/ell_point.py +4787 -0
- sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
- sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
- sage/schemes/elliptic_curves/ell_torsion.py +436 -0
- sage/schemes/elliptic_curves/ell_wp.py +352 -0
- sage/schemes/elliptic_curves/formal_group.py +760 -0
- sage/schemes/elliptic_curves/gal_reps.py +1459 -0
- sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
- sage/schemes/elliptic_curves/gp_simon.py +152 -0
- sage/schemes/elliptic_curves/heegner.py +7335 -0
- sage/schemes/elliptic_curves/height.py +2109 -0
- sage/schemes/elliptic_curves/hom.py +1406 -0
- sage/schemes/elliptic_curves/hom_composite.py +934 -0
- sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
- sage/schemes/elliptic_curves/hom_scalar.py +531 -0
- sage/schemes/elliptic_curves/hom_sum.py +682 -0
- sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
- sage/schemes/elliptic_curves/homset.py +271 -0
- sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
- sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
- sage/schemes/elliptic_curves/jacobian.py +237 -0
- sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
- sage/schemes/elliptic_curves/kraus.py +1014 -0
- sage/schemes/elliptic_curves/lseries_ell.py +943 -0
- sage/schemes/elliptic_curves/mod5family.py +105 -0
- sage/schemes/elliptic_curves/mod_poly.py +197 -0
- sage/schemes/elliptic_curves/mod_sym_num.cpython-314-darwin.so +0 -0
- sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
- sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
- sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
- sage/schemes/elliptic_curves/padics.py +1816 -0
- sage/schemes/elliptic_curves/period_lattice.py +2234 -0
- sage/schemes/elliptic_curves/period_lattice_region.cpython-314-darwin.so +0 -0
- sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
- sage/schemes/elliptic_curves/saturation.py +715 -0
- sage/schemes/elliptic_curves/sha_tate.py +1158 -0
- sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
- sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
- sage/schemes/hyperelliptic_curves/all.py +6 -0
- sage/schemes/hyperelliptic_curves/constructor.py +291 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
- sage/schemes/hyperelliptic_curves/invariants.py +410 -0
- sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
- sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
- sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
- sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
- sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
- sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
- sage/schemes/hyperelliptic_curves/mestre.py +302 -0
- sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
- sage/schemes/jacobians/abstract_jacobian.py +277 -0
- sage/schemes/jacobians/all.py +2 -0
- sage/schemes/overview.py +161 -0
- sage/schemes/plane_conics/all.py +22 -0
- sage/schemes/plane_conics/con_field.py +1296 -0
- sage/schemes/plane_conics/con_finite_field.py +158 -0
- sage/schemes/plane_conics/con_number_field.py +456 -0
- sage/schemes/plane_conics/con_rational_field.py +406 -0
- sage/schemes/plane_conics/con_rational_function_field.py +580 -0
- sage/schemes/plane_conics/constructor.py +249 -0
- sage/schemes/plane_quartics/all.py +2 -0
- sage/schemes/plane_quartics/quartic_constructor.py +71 -0
- sage/schemes/plane_quartics/quartic_generic.py +73 -0
- sage/schemes/riemann_surfaces/all.py +1 -0
- sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
- sage_wheels/share/cremona/cremona_mini.db +0 -0
- sage_wheels/share/ellcurves/rank0 +30427 -0
- sage_wheels/share/ellcurves/rank1 +31871 -0
- sage_wheels/share/ellcurves/rank10 +6 -0
- sage_wheels/share/ellcurves/rank11 +6 -0
- sage_wheels/share/ellcurves/rank12 +1 -0
- sage_wheels/share/ellcurves/rank14 +1 -0
- sage_wheels/share/ellcurves/rank15 +1 -0
- sage_wheels/share/ellcurves/rank17 +1 -0
- sage_wheels/share/ellcurves/rank19 +1 -0
- sage_wheels/share/ellcurves/rank2 +2388 -0
- sage_wheels/share/ellcurves/rank20 +1 -0
- sage_wheels/share/ellcurves/rank21 +1 -0
- sage_wheels/share/ellcurves/rank22 +1 -0
- sage_wheels/share/ellcurves/rank23 +1 -0
- sage_wheels/share/ellcurves/rank24 +1 -0
- sage_wheels/share/ellcurves/rank28 +1 -0
- sage_wheels/share/ellcurves/rank3 +836 -0
- sage_wheels/share/ellcurves/rank4 +10 -0
- sage_wheels/share/ellcurves/rank5 +5 -0
- sage_wheels/share/ellcurves/rank6 +5 -0
- sage_wheels/share/ellcurves/rank7 +5 -0
- sage_wheels/share/ellcurves/rank8 +6 -0
- sage_wheels/share/ellcurves/rank9 +7 -0
|
@@ -0,0 +1,2017 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
"""
|
|
3
|
+
Hypergeometric motives
|
|
4
|
+
|
|
5
|
+
This is largely a port of the corresponding package in Magma. One
|
|
6
|
+
important conventional difference: the motivic parameter `t` has been replaced
|
|
7
|
+
with `1/t` to match the classical literature on hypergeometric series.
|
|
8
|
+
(E.g., see [BeukersHeckman]_)
|
|
9
|
+
|
|
10
|
+
The computation of Euler factors is currently only supported for primes `p`
|
|
11
|
+
of good or tame reduction.
|
|
12
|
+
|
|
13
|
+
AUTHORS:
|
|
14
|
+
|
|
15
|
+
- Frédéric Chapoton
|
|
16
|
+
- Kiran S. Kedlaya
|
|
17
|
+
|
|
18
|
+
EXAMPLES::
|
|
19
|
+
|
|
20
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
21
|
+
sage: H = Hyp(cyclotomic=([30], [1,2,3,5]))
|
|
22
|
+
sage: H.alpha_beta()
|
|
23
|
+
([1/30, 7/30, 11/30, 13/30, 17/30, 19/30, 23/30, 29/30],
|
|
24
|
+
[0, 1/5, 1/3, 2/5, 1/2, 3/5, 2/3, 4/5])
|
|
25
|
+
sage: H.M_value() == 30**30 / (15**15 * 10**10 * 6**6)
|
|
26
|
+
True
|
|
27
|
+
sage: H.euler_factor(2, 7)
|
|
28
|
+
T^8 + T^5 + T^3 + 1
|
|
29
|
+
|
|
30
|
+
REFERENCES:
|
|
31
|
+
|
|
32
|
+
- [BeukersHeckman]_
|
|
33
|
+
|
|
34
|
+
- [Benasque2009]_
|
|
35
|
+
|
|
36
|
+
- [Kat1991]_
|
|
37
|
+
|
|
38
|
+
- [MagmaHGM]_
|
|
39
|
+
|
|
40
|
+
- [Fedorov2015]_
|
|
41
|
+
|
|
42
|
+
- [Roberts2017]_
|
|
43
|
+
|
|
44
|
+
- [Roberts2015]_
|
|
45
|
+
|
|
46
|
+
- [RRV2022]_
|
|
47
|
+
|
|
48
|
+
- [BeCoMe]_
|
|
49
|
+
|
|
50
|
+
- [Watkins]_
|
|
51
|
+
"""
|
|
52
|
+
# ****************************************************************************
|
|
53
|
+
# Copyright (C) 2017--2024 Frédéric Chapoton
|
|
54
|
+
# Kiran S. Kedlaya <kskedl@gmail.com>
|
|
55
|
+
#
|
|
56
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
57
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
58
|
+
# the License, or (at your option) any later version.
|
|
59
|
+
#
|
|
60
|
+
# https://www.gnu.org/licenses/
|
|
61
|
+
# ****************************************************************************
|
|
62
|
+
|
|
63
|
+
from collections import defaultdict
|
|
64
|
+
from itertools import combinations
|
|
65
|
+
from sage.arith.misc import divisors, gcd, euler_phi, is_prime, moebius
|
|
66
|
+
from sage.arith.misc import gauss_sum, kronecker_symbol
|
|
67
|
+
from sage.combinat.integer_vector_weighted import WeightedIntegerVectors
|
|
68
|
+
from sage.functions.generalized import sgn
|
|
69
|
+
from sage.functions.log import log
|
|
70
|
+
from sage.functions.other import floor, ceil, frac
|
|
71
|
+
from sage.geometry.lattice_polytope import LatticePolytope
|
|
72
|
+
from sage.matrix.constructor import matrix
|
|
73
|
+
from sage.misc.cachefunc import cached_method
|
|
74
|
+
from sage.misc.functional import cyclotomic_polynomial
|
|
75
|
+
from sage.misc.lazy_import import lazy_import
|
|
76
|
+
from sage.misc.misc_c import prod
|
|
77
|
+
from sage.modular.hypergeometric_misc import hgm_coeffs
|
|
78
|
+
from sage.modules.free_module_element import vector
|
|
79
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
80
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
81
|
+
from sage.rings.fraction_field import FractionField
|
|
82
|
+
from sage.rings.integer_ring import ZZ
|
|
83
|
+
from sage.rings.padics.factory import Zp
|
|
84
|
+
from sage.rings.padics.padic_generic_element import gauss_table
|
|
85
|
+
from sage.rings.polynomial.polynomial_ring import polygen, polygens
|
|
86
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
87
|
+
from sage.rings.power_series_ring import PowerSeriesRing
|
|
88
|
+
from sage.rings.rational_field import QQ
|
|
89
|
+
from sage.schemes.generic.spec import Spec
|
|
90
|
+
|
|
91
|
+
lazy_import('sage.rings.universal_cyclotomic_field', 'UniversalCyclotomicField')
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def characteristic_polynomial_from_traces(traces, d, q, i, sign, deg=None, use_fe=True):
|
|
95
|
+
r"""
|
|
96
|
+
Given a sequence of traces `t_1, \dots, t_k`, return the
|
|
97
|
+
corresponding characteristic polynomial with Weil numbers as roots.
|
|
98
|
+
|
|
99
|
+
The characteristic polynomial is defined by the generating series
|
|
100
|
+
|
|
101
|
+
.. MATH::
|
|
102
|
+
|
|
103
|
+
P(T) = \exp\left(- \sum_{k\geq 1} t_k \frac{T^k}{k}\right)
|
|
104
|
+
|
|
105
|
+
and should have the property that reciprocals of all roots have
|
|
106
|
+
absolute value `q^{i/2}`.
|
|
107
|
+
|
|
108
|
+
INPUT:
|
|
109
|
+
|
|
110
|
+
- ``traces`` -- list of integers `t_1, \dots, t_k`
|
|
111
|
+
|
|
112
|
+
- ``d`` -- the degree of the characteristic polynomial
|
|
113
|
+
|
|
114
|
+
- ``q`` -- power of a prime number
|
|
115
|
+
|
|
116
|
+
- ``i`` -- integer; the weight in the motivic sense
|
|
117
|
+
|
|
118
|
+
- ``sign`` -- integer; the sign
|
|
119
|
+
|
|
120
|
+
- ``deg`` -- integer or ``None``
|
|
121
|
+
|
|
122
|
+
- ``use_fe`` -- boolean (default: ``True``)
|
|
123
|
+
|
|
124
|
+
OUTPUT: a polynomial
|
|
125
|
+
|
|
126
|
+
If ``deg`` is specified, only the coefficients up to this degree (inclusive) are computed.
|
|
127
|
+
|
|
128
|
+
If ``use_fe`` is ``False``, we ignore the local functional equation.
|
|
129
|
+
|
|
130
|
+
EXAMPLES::
|
|
131
|
+
|
|
132
|
+
sage: from sage.modular.hypergeometric_motive import characteristic_polynomial_from_traces
|
|
133
|
+
sage: characteristic_polynomial_from_traces([1, 1], 1, 3, 0, -1)
|
|
134
|
+
-T + 1
|
|
135
|
+
sage: characteristic_polynomial_from_traces([25], 1, 5, 4, -1)
|
|
136
|
+
-25*T + 1
|
|
137
|
+
|
|
138
|
+
sage: characteristic_polynomial_from_traces([3], 2, 5, 1, 1)
|
|
139
|
+
5*T^2 - 3*T + 1
|
|
140
|
+
sage: characteristic_polynomial_from_traces([1], 2, 7, 1, 1)
|
|
141
|
+
7*T^2 - T + 1
|
|
142
|
+
|
|
143
|
+
sage: characteristic_polynomial_from_traces([20], 3, 29, 2, 1)
|
|
144
|
+
24389*T^3 - 580*T^2 - 20*T + 1
|
|
145
|
+
sage: characteristic_polynomial_from_traces([12], 3, 13, 2, -1)
|
|
146
|
+
-2197*T^3 + 156*T^2 - 12*T + 1
|
|
147
|
+
|
|
148
|
+
sage: characteristic_polynomial_from_traces([36, 7620], 4, 17, 3, 1)
|
|
149
|
+
24137569*T^4 - 176868*T^3 - 3162*T^2 - 36*T + 1
|
|
150
|
+
sage: characteristic_polynomial_from_traces([-4, 276], 4, 5, 3, 1)
|
|
151
|
+
15625*T^4 + 500*T^3 - 130*T^2 + 4*T + 1
|
|
152
|
+
sage: characteristic_polynomial_from_traces([4, -276], 4, 5, 3, 1)
|
|
153
|
+
15625*T^4 - 500*T^3 + 146*T^2 - 4*T + 1
|
|
154
|
+
sage: characteristic_polynomial_from_traces([22, 484], 4, 31, 2, -1)
|
|
155
|
+
-923521*T^4 + 21142*T^3 - 22*T + 1
|
|
156
|
+
|
|
157
|
+
sage: characteristic_polynomial_from_traces([22], 4, 31, 2, -1, deg=1)
|
|
158
|
+
-22*T + 1
|
|
159
|
+
sage: characteristic_polynomial_from_traces([22, 484], 4, 31, 2, -1, deg=4)
|
|
160
|
+
-923521*T^4 + 21142*T^3 - 22*T + 1
|
|
161
|
+
|
|
162
|
+
TESTS::
|
|
163
|
+
|
|
164
|
+
sage: characteristic_polynomial_from_traces([-36], 4, 17, 3, 1)
|
|
165
|
+
Traceback (most recent call last):
|
|
166
|
+
...
|
|
167
|
+
ValueError: not enough traces were given
|
|
168
|
+
"""
|
|
169
|
+
if use_fe:
|
|
170
|
+
bound = d // 2 if deg is None else min(d // 2, deg)
|
|
171
|
+
else:
|
|
172
|
+
bound = d if deg is None else min(d, deg)
|
|
173
|
+
if len(traces) < bound:
|
|
174
|
+
raise ValueError('not enough traces were given')
|
|
175
|
+
if i % 2 and d % 2 and use_fe:
|
|
176
|
+
raise ValueError('i and d may not both be odd')
|
|
177
|
+
t = PowerSeriesRing(QQ, 't').gen()
|
|
178
|
+
ring = PolynomialRing(ZZ, 'T')
|
|
179
|
+
|
|
180
|
+
series = sum(- api * t**(i + 1) / (i + 1) for i, api in enumerate(traces))
|
|
181
|
+
series = series.O(bound + 1).exp()
|
|
182
|
+
coeffs = list(series)
|
|
183
|
+
coeffs += [0] * max(0, bound + 1 - len(coeffs))
|
|
184
|
+
|
|
185
|
+
fulldeg = d if deg is None else deg
|
|
186
|
+
data = [0] * (fulldeg + 1)
|
|
187
|
+
for k in range(bound + 1):
|
|
188
|
+
data[k] = coeffs[k]
|
|
189
|
+
for k in range(bound + 1, fulldeg + 1):
|
|
190
|
+
data[k] = sign * coeffs[d - k] * q**(i * (k - d / 2))
|
|
191
|
+
return ring(data)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def enumerate_hypergeometric_data(d, weight=None):
|
|
195
|
+
r"""
|
|
196
|
+
Return an iterator over parameters of hypergeometric motives (up to swapping).
|
|
197
|
+
|
|
198
|
+
INPUT:
|
|
199
|
+
|
|
200
|
+
- ``d`` -- the degree
|
|
201
|
+
|
|
202
|
+
- ``weight`` -- (optional) integer; specifies the motivic weight
|
|
203
|
+
|
|
204
|
+
EXAMPLES::
|
|
205
|
+
|
|
206
|
+
sage: from sage.modular.hypergeometric_motive import enumerate_hypergeometric_data as enum
|
|
207
|
+
sage: l = [H for H in enum(6, weight=2) if H.hodge_numbers()[0] == 1] # needs sage.combinat
|
|
208
|
+
sage: len(l) # needs sage.combinat
|
|
209
|
+
112
|
|
210
|
+
"""
|
|
211
|
+
bound = 2 * d * d # to make sure that phi(n) <= d
|
|
212
|
+
possible = [(i, euler_phi(i)) for i in range(1, bound + 1)
|
|
213
|
+
if euler_phi(i) <= d]
|
|
214
|
+
poids = [z[1] for z in possible]
|
|
215
|
+
N = len(poids)
|
|
216
|
+
vectors = WeightedIntegerVectors(d, poids)
|
|
217
|
+
|
|
218
|
+
def formule(u):
|
|
219
|
+
return [possible[j][0] for j in range(N) for _ in range(u[j])]
|
|
220
|
+
|
|
221
|
+
for a, b in combinations(vectors, 2):
|
|
222
|
+
if not any(a[j] and b[j] for j in range(N)):
|
|
223
|
+
H = HypergeometricData(cyclotomic=(formule(a), formule(b)))
|
|
224
|
+
if weight is None or H.weight() == weight:
|
|
225
|
+
yield H
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def possible_hypergeometric_data(d, weight=None) -> list:
|
|
229
|
+
"""
|
|
230
|
+
Return the list of possible parameters of hypergeometric motives (up to swapping).
|
|
231
|
+
|
|
232
|
+
INPUT:
|
|
233
|
+
|
|
234
|
+
- ``d`` -- the degree
|
|
235
|
+
|
|
236
|
+
- ``weight`` -- (optional) integer; specifies the motivic weight
|
|
237
|
+
|
|
238
|
+
EXAMPLES::
|
|
239
|
+
|
|
240
|
+
sage: from sage.modular.hypergeometric_motive import possible_hypergeometric_data as P
|
|
241
|
+
sage: [len(P(i, weight=2)) for i in range(1, 7)] # needs sage.combinat
|
|
242
|
+
[0, 0, 10, 30, 93, 234]
|
|
243
|
+
"""
|
|
244
|
+
return list(enumerate_hypergeometric_data(d, weight))
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def cyclotomic_to_alpha(cyclo) -> list:
|
|
248
|
+
"""
|
|
249
|
+
Convert a list of indices of cyclotomic polynomials
|
|
250
|
+
to a list of rational numbers.
|
|
251
|
+
|
|
252
|
+
The input represents a product of cyclotomic polynomials.
|
|
253
|
+
|
|
254
|
+
The output is the list of arguments of the roots of the
|
|
255
|
+
given product of cyclotomic polynomials.
|
|
256
|
+
|
|
257
|
+
This is the inverse of :func:`alpha_to_cyclotomic`.
|
|
258
|
+
|
|
259
|
+
EXAMPLES::
|
|
260
|
+
|
|
261
|
+
sage: from sage.modular.hypergeometric_motive import cyclotomic_to_alpha
|
|
262
|
+
sage: cyclotomic_to_alpha([1])
|
|
263
|
+
[0]
|
|
264
|
+
sage: cyclotomic_to_alpha([2])
|
|
265
|
+
[1/2]
|
|
266
|
+
sage: cyclotomic_to_alpha([5])
|
|
267
|
+
[1/5, 2/5, 3/5, 4/5]
|
|
268
|
+
sage: cyclotomic_to_alpha([1, 2, 3, 6])
|
|
269
|
+
[0, 1/6, 1/3, 1/2, 2/3, 5/6]
|
|
270
|
+
sage: cyclotomic_to_alpha([2, 3])
|
|
271
|
+
[1/3, 1/2, 2/3]
|
|
272
|
+
"""
|
|
273
|
+
alpha = [QQ((k, d)) for d in cyclo
|
|
274
|
+
for k in ZZ(d).coprime_integers(d)]
|
|
275
|
+
return sorted(alpha)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def alpha_to_cyclotomic(alpha) -> list:
|
|
279
|
+
"""
|
|
280
|
+
Convert from a list of rationals arguments to a list of integers.
|
|
281
|
+
|
|
282
|
+
The input represents arguments of some roots of unity.
|
|
283
|
+
|
|
284
|
+
The output represent a product of cyclotomic polynomials with exactly
|
|
285
|
+
the given roots. Note that the multiplicity of `r/s` in the list
|
|
286
|
+
must be independent of `r`; otherwise, a :exc:`ValueError` will be raised.
|
|
287
|
+
|
|
288
|
+
This is the inverse of :func:`cyclotomic_to_alpha`.
|
|
289
|
+
|
|
290
|
+
EXAMPLES::
|
|
291
|
+
|
|
292
|
+
sage: from sage.modular.hypergeometric_motive import alpha_to_cyclotomic
|
|
293
|
+
sage: alpha_to_cyclotomic([0])
|
|
294
|
+
[1]
|
|
295
|
+
sage: alpha_to_cyclotomic([1/2])
|
|
296
|
+
[2]
|
|
297
|
+
sage: alpha_to_cyclotomic([1/5, 2/5, 3/5, 4/5])
|
|
298
|
+
[5]
|
|
299
|
+
sage: alpha_to_cyclotomic([0, 1/6, 1/3, 1/2, 2/3, 5/6])
|
|
300
|
+
[1, 2, 3, 6]
|
|
301
|
+
sage: alpha_to_cyclotomic([1/3, 2/3, 1/2])
|
|
302
|
+
[2, 3]
|
|
303
|
+
"""
|
|
304
|
+
cyclo = []
|
|
305
|
+
Alpha = list(alpha)
|
|
306
|
+
while Alpha:
|
|
307
|
+
q = QQ(Alpha.pop())
|
|
308
|
+
n = q.numerator()
|
|
309
|
+
d = q.denominator()
|
|
310
|
+
for k in d.coprime_integers(d):
|
|
311
|
+
if k != n:
|
|
312
|
+
try:
|
|
313
|
+
Alpha.remove(QQ((k, d)))
|
|
314
|
+
except ValueError:
|
|
315
|
+
raise ValueError("multiplicities not balanced")
|
|
316
|
+
cyclo.append(d)
|
|
317
|
+
return sorted(cyclo)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def capital_M(n):
|
|
321
|
+
"""
|
|
322
|
+
Auxiliary function, used to describe the canonical scheme.
|
|
323
|
+
|
|
324
|
+
INPUT:
|
|
325
|
+
|
|
326
|
+
- ``n`` -- integer
|
|
327
|
+
|
|
328
|
+
OUTPUT: a rational
|
|
329
|
+
|
|
330
|
+
EXAMPLES::
|
|
331
|
+
|
|
332
|
+
sage: from sage.modular.hypergeometric_motive import capital_M
|
|
333
|
+
sage: [capital_M(i) for i in range(1, 8)]
|
|
334
|
+
[1, 4, 27, 64, 3125, 432, 823543]
|
|
335
|
+
"""
|
|
336
|
+
n = ZZ(n)
|
|
337
|
+
return QQ.prod(d ** (d * moebius(n // d)) for d in divisors(n))
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def cyclotomic_to_gamma(cyclo_up, cyclo_down) -> dict:
|
|
341
|
+
"""
|
|
342
|
+
Convert a quotient of products of cyclotomic polynomials
|
|
343
|
+
to a quotient of products of polynomials `x^n - 1`.
|
|
344
|
+
|
|
345
|
+
INPUT:
|
|
346
|
+
|
|
347
|
+
- ``cyclo_up`` -- list of indices of cyclotomic polynomials in the numerator
|
|
348
|
+
- ``cyclo_down`` -- list of indices of cyclotomic polynomials in the denominator
|
|
349
|
+
|
|
350
|
+
OUTPUT:
|
|
351
|
+
|
|
352
|
+
a dictionary mapping an integer `n` to the power of `x^n - 1` that
|
|
353
|
+
appears in the given product
|
|
354
|
+
|
|
355
|
+
EXAMPLES::
|
|
356
|
+
|
|
357
|
+
sage: from sage.modular.hypergeometric_motive import cyclotomic_to_gamma
|
|
358
|
+
sage: cyclotomic_to_gamma([6], [1])
|
|
359
|
+
{2: -1, 3: -1, 6: 1}
|
|
360
|
+
"""
|
|
361
|
+
dico: dict[int, int] = defaultdict(int)
|
|
362
|
+
for d in cyclo_up:
|
|
363
|
+
dico[d] += 1
|
|
364
|
+
for d in cyclo_down:
|
|
365
|
+
dico[d] -= 1
|
|
366
|
+
|
|
367
|
+
resu: dict[int, int] = defaultdict(int)
|
|
368
|
+
for n in dico:
|
|
369
|
+
for d in divisors(n):
|
|
370
|
+
resu[d] += moebius(n // d) * dico[n]
|
|
371
|
+
|
|
372
|
+
return {d: resu[d] for d in resu if resu[d]}
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def gamma_list_to_cyclotomic(galist):
|
|
376
|
+
r"""
|
|
377
|
+
Convert a quotient of products of polynomials `x^n - 1`
|
|
378
|
+
to a quotient of products of cyclotomic polynomials.
|
|
379
|
+
|
|
380
|
+
INPUT:
|
|
381
|
+
|
|
382
|
+
- ``galist`` -- list of integers, where an integer `n` represents
|
|
383
|
+
the power `(x^{|n|} - 1)^{\operatorname{sgn}(n)}`
|
|
384
|
+
|
|
385
|
+
OUTPUT:
|
|
386
|
+
|
|
387
|
+
a pair of list of integers, where `k` represents the cyclotomic
|
|
388
|
+
polynomial `\Phi_k`
|
|
389
|
+
|
|
390
|
+
EXAMPLES::
|
|
391
|
+
|
|
392
|
+
sage: from sage.modular.hypergeometric_motive import gamma_list_to_cyclotomic
|
|
393
|
+
sage: gamma_list_to_cyclotomic([-1, -1, 2])
|
|
394
|
+
([2], [1])
|
|
395
|
+
|
|
396
|
+
sage: gamma_list_to_cyclotomic([-1, -1, -1, -3, 6])
|
|
397
|
+
([2, 6], [1, 1, 1])
|
|
398
|
+
|
|
399
|
+
sage: gamma_list_to_cyclotomic([-1, 2, 3, -4])
|
|
400
|
+
([3], [4])
|
|
401
|
+
|
|
402
|
+
sage: gamma_list_to_cyclotomic([8, 2, 2, 2, -6, -4, -3, -1])
|
|
403
|
+
([2, 2, 8], [3, 3, 6])
|
|
404
|
+
"""
|
|
405
|
+
resu: dict[int, int] = defaultdict(int)
|
|
406
|
+
for n in galist:
|
|
407
|
+
eps = sgn(n)
|
|
408
|
+
for d in divisors(abs(n)):
|
|
409
|
+
resu[d] += eps
|
|
410
|
+
|
|
411
|
+
return (sorted(d for d in resu for k in range(resu[d])),
|
|
412
|
+
sorted(d for d in resu for k in range(-resu[d])))
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
class HypergeometricData:
|
|
416
|
+
_gauss_table = {}
|
|
417
|
+
|
|
418
|
+
def __init__(self, cyclotomic=None, alpha_beta=None, gamma_list=None):
|
|
419
|
+
r"""
|
|
420
|
+
Creation of hypergeometric motives.
|
|
421
|
+
|
|
422
|
+
INPUT:
|
|
423
|
+
|
|
424
|
+
Three possibilities are offered, each describing a quotient
|
|
425
|
+
of products of cyclotomic polynomials.
|
|
426
|
+
|
|
427
|
+
- ``cyclotomic`` -- a pair of lists of nonnegative integers,
|
|
428
|
+
each integer `k` represents a cyclotomic polynomial `\Phi_k`
|
|
429
|
+
|
|
430
|
+
- ``alpha_beta`` -- a pair of lists of rationals,
|
|
431
|
+
each rational represents a root of unity
|
|
432
|
+
|
|
433
|
+
- ``gamma_list`` -- a pair of lists of nonnegative integers,
|
|
434
|
+
each integer `n` represents a polynomial `x^n - 1`
|
|
435
|
+
|
|
436
|
+
In the last case, it is also allowed to send just one list of signed
|
|
437
|
+
integers where signs indicate to which part the integer belongs to.
|
|
438
|
+
|
|
439
|
+
EXAMPLES::
|
|
440
|
+
|
|
441
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
442
|
+
sage: Hyp(cyclotomic=([2], [1]))
|
|
443
|
+
Hypergeometric data for [1/2] and [0]
|
|
444
|
+
|
|
445
|
+
sage: Hyp(alpha_beta=([1/2], [0]))
|
|
446
|
+
Hypergeometric data for [1/2] and [0]
|
|
447
|
+
sage: Hyp(alpha_beta=([1/5,2/5,3/5,4/5], [0,0,0,0]))
|
|
448
|
+
Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]
|
|
449
|
+
|
|
450
|
+
sage: Hyp(gamma_list=([5], [1,1,1,1,1]))
|
|
451
|
+
Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]
|
|
452
|
+
sage: Hyp(gamma_list=([5,-1,-1,-1,-1,-1]))
|
|
453
|
+
Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]
|
|
454
|
+
"""
|
|
455
|
+
if gamma_list is not None:
|
|
456
|
+
if isinstance(gamma_list[0], (list, tuple)):
|
|
457
|
+
pos, neg = gamma_list
|
|
458
|
+
gamma_list = pos + [-u for u in neg]
|
|
459
|
+
cyclotomic = gamma_list_to_cyclotomic(gamma_list)
|
|
460
|
+
if cyclotomic is not None:
|
|
461
|
+
cyclo_up, cyclo_down = cyclotomic
|
|
462
|
+
if any(x in cyclo_up for x in cyclo_down):
|
|
463
|
+
raise ValueError('overlapping parameters not allowed')
|
|
464
|
+
deg = sum(euler_phi(x) for x in cyclo_down)
|
|
465
|
+
up_deg = sum(euler_phi(x) for x in cyclo_up)
|
|
466
|
+
if up_deg != deg:
|
|
467
|
+
msg = f'not the same degree: {up_deg} != {deg}'
|
|
468
|
+
raise ValueError(msg)
|
|
469
|
+
cyclo_up.sort()
|
|
470
|
+
cyclo_down.sort()
|
|
471
|
+
alpha = cyclotomic_to_alpha(cyclo_up)
|
|
472
|
+
beta = cyclotomic_to_alpha(cyclo_down)
|
|
473
|
+
elif alpha_beta is not None:
|
|
474
|
+
alpha, beta = alpha_beta
|
|
475
|
+
if len(alpha) != len(beta):
|
|
476
|
+
raise ValueError('alpha and beta not of the same length')
|
|
477
|
+
alpha = sorted(u - floor(u) for u in alpha)
|
|
478
|
+
beta = sorted(u - floor(u) for u in beta)
|
|
479
|
+
cyclo_up = alpha_to_cyclotomic(alpha)
|
|
480
|
+
cyclo_down = alpha_to_cyclotomic(beta)
|
|
481
|
+
deg = sum(euler_phi(x) for x in cyclo_down)
|
|
482
|
+
|
|
483
|
+
self._cyclo_up = tuple(cyclo_up)
|
|
484
|
+
self._cyclo_down = tuple(cyclo_down)
|
|
485
|
+
self._alpha = tuple(alpha)
|
|
486
|
+
self._beta = tuple(beta)
|
|
487
|
+
self._deg = deg
|
|
488
|
+
self._gamma_array = cyclotomic_to_gamma(cyclo_up, cyclo_down)
|
|
489
|
+
self._trace_coeffs = {}
|
|
490
|
+
up = QQ.prod(capital_M(d) for d in cyclo_up)
|
|
491
|
+
down = QQ.prod(capital_M(d) for d in cyclo_down)
|
|
492
|
+
self._M_value = up / down
|
|
493
|
+
if 0 in alpha:
|
|
494
|
+
self._swap = HypergeometricData(alpha_beta=(beta, alpha))
|
|
495
|
+
if self.weight() % 2:
|
|
496
|
+
self._sign_param = 1
|
|
497
|
+
else:
|
|
498
|
+
if (deg % 2) != (0 in alpha):
|
|
499
|
+
self._sign_param = prod(cyclotomic_polynomial(v).disc()
|
|
500
|
+
for v in cyclo_down)
|
|
501
|
+
else:
|
|
502
|
+
self._sign_param = prod(cyclotomic_polynomial(v).disc()
|
|
503
|
+
for v in cyclo_up)
|
|
504
|
+
|
|
505
|
+
# --- Internals ---
|
|
506
|
+
def __repr__(self) -> str:
|
|
507
|
+
"""
|
|
508
|
+
Return the string representation.
|
|
509
|
+
|
|
510
|
+
This displays the rational arguments of the roots of unity.
|
|
511
|
+
|
|
512
|
+
EXAMPLES::
|
|
513
|
+
|
|
514
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
515
|
+
sage: Hyp(alpha_beta=([1/2],[0]))
|
|
516
|
+
Hypergeometric data for [1/2] and [0]
|
|
517
|
+
"""
|
|
518
|
+
txt = "Hypergeometric data for {} and {}"
|
|
519
|
+
return txt.format(list(self._alpha), list(self._beta))
|
|
520
|
+
|
|
521
|
+
def __eq__(self, other) -> bool:
|
|
522
|
+
"""
|
|
523
|
+
Return whether two data are equal.
|
|
524
|
+
|
|
525
|
+
EXAMPLES::
|
|
526
|
+
|
|
527
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
528
|
+
sage: H1 = Hyp(alpha_beta=([1/2], [0]))
|
|
529
|
+
sage: H2 = Hyp(cyclotomic=([6,2], [1,1,1]))
|
|
530
|
+
sage: H1 == H1
|
|
531
|
+
True
|
|
532
|
+
sage: H1 == H2
|
|
533
|
+
False
|
|
534
|
+
"""
|
|
535
|
+
return (self._alpha == other._alpha and
|
|
536
|
+
self._beta == other._beta)
|
|
537
|
+
|
|
538
|
+
def __ne__(self, other) -> bool:
|
|
539
|
+
"""
|
|
540
|
+
Return whether two data are unequal.
|
|
541
|
+
|
|
542
|
+
EXAMPLES::
|
|
543
|
+
|
|
544
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
545
|
+
sage: H1 = Hyp(alpha_beta=([1/2], [0]))
|
|
546
|
+
sage: H2 = Hyp(cyclotomic=([6,2], [1,1,1]))
|
|
547
|
+
sage: H1 != H1
|
|
548
|
+
False
|
|
549
|
+
sage: H1 != H2
|
|
550
|
+
True
|
|
551
|
+
"""
|
|
552
|
+
return not (self == other)
|
|
553
|
+
|
|
554
|
+
def __hash__(self):
|
|
555
|
+
"""
|
|
556
|
+
Return a hash for ``self``.
|
|
557
|
+
|
|
558
|
+
EXAMPLES::
|
|
559
|
+
|
|
560
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
561
|
+
sage: H1 = Hyp(alpha_beta=([1/2], [0]))
|
|
562
|
+
sage: h = hash(H1)
|
|
563
|
+
"""
|
|
564
|
+
return hash((self._alpha, self._beta))
|
|
565
|
+
|
|
566
|
+
# --- Parameters and invariants ---
|
|
567
|
+
def cyclotomic_data(self) -> tuple:
|
|
568
|
+
"""
|
|
569
|
+
Return the pair of tuples of indices of cyclotomic polynomials.
|
|
570
|
+
|
|
571
|
+
EXAMPLES::
|
|
572
|
+
|
|
573
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
574
|
+
sage: Hyp(alpha_beta=([1/2], [0])).cyclotomic_data()
|
|
575
|
+
([2], [1])
|
|
576
|
+
"""
|
|
577
|
+
return (list(self._cyclo_up), list(self._cyclo_down))
|
|
578
|
+
|
|
579
|
+
def alpha_beta(self) -> tuple:
|
|
580
|
+
"""
|
|
581
|
+
Return the pair of lists of rational arguments.
|
|
582
|
+
|
|
583
|
+
EXAMPLES::
|
|
584
|
+
|
|
585
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
586
|
+
sage: Hyp(alpha_beta=([1/2], [0])).alpha_beta()
|
|
587
|
+
([1/2], [0])
|
|
588
|
+
"""
|
|
589
|
+
return (list(self._alpha), list(self._beta))
|
|
590
|
+
|
|
591
|
+
def alpha(self) -> list:
|
|
592
|
+
"""
|
|
593
|
+
Return the first tuple of rational arguments.
|
|
594
|
+
|
|
595
|
+
EXAMPLES::
|
|
596
|
+
|
|
597
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
598
|
+
sage: Hyp(alpha_beta=([1/2], [0])).alpha()
|
|
599
|
+
[1/2]
|
|
600
|
+
"""
|
|
601
|
+
return list(self._alpha)
|
|
602
|
+
|
|
603
|
+
def beta(self) -> list:
|
|
604
|
+
"""
|
|
605
|
+
Return the second tuple of rational arguments.
|
|
606
|
+
|
|
607
|
+
EXAMPLES::
|
|
608
|
+
|
|
609
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
610
|
+
sage: Hyp(alpha_beta=([1/2], [0])).beta()
|
|
611
|
+
[0]
|
|
612
|
+
"""
|
|
613
|
+
return list(self._beta)
|
|
614
|
+
|
|
615
|
+
def defining_polynomials(self) -> tuple:
|
|
616
|
+
"""
|
|
617
|
+
Return the pair of products of cyclotomic polynomials.
|
|
618
|
+
|
|
619
|
+
EXAMPLES::
|
|
620
|
+
|
|
621
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
622
|
+
sage: Hyp(alpha_beta=([1/4,3/4], [0,0])).defining_polynomials()
|
|
623
|
+
(x^2 + 1, x^2 - 2*x + 1)
|
|
624
|
+
"""
|
|
625
|
+
up = prod(cyclotomic_polynomial(d) for d in self._cyclo_up)
|
|
626
|
+
down = prod(cyclotomic_polynomial(d) for d in self._cyclo_down)
|
|
627
|
+
return (up, down)
|
|
628
|
+
|
|
629
|
+
def gamma_array(self) -> dict:
|
|
630
|
+
r"""
|
|
631
|
+
Return the dictionary `\{v: \gamma_v\}` for the expression
|
|
632
|
+
|
|
633
|
+
.. MATH::
|
|
634
|
+
|
|
635
|
+
\prod_v (T^v - 1)^{\gamma_v}
|
|
636
|
+
|
|
637
|
+
EXAMPLES::
|
|
638
|
+
|
|
639
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
640
|
+
sage: Hyp(alpha_beta=([1/2], [0])).gamma_array()
|
|
641
|
+
{1: -2, 2: 1}
|
|
642
|
+
sage: Hyp(cyclotomic=([6,2], [1,1,1])).gamma_array()
|
|
643
|
+
{1: -3, 3: -1, 6: 1}
|
|
644
|
+
"""
|
|
645
|
+
return dict(self._gamma_array)
|
|
646
|
+
|
|
647
|
+
def gamma_list(self) -> list:
|
|
648
|
+
r"""
|
|
649
|
+
Return a list of integers describing the `x^n - 1` factors.
|
|
650
|
+
|
|
651
|
+
Each integer `n` stands for `(x^{|n|} - 1)^{\operatorname{sgn}(n)}`.
|
|
652
|
+
|
|
653
|
+
EXAMPLES::
|
|
654
|
+
|
|
655
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
656
|
+
sage: Hyp(alpha_beta=([1/2], [0])).gamma_list()
|
|
657
|
+
[-1, -1, 2]
|
|
658
|
+
|
|
659
|
+
sage: Hyp(cyclotomic=([6,2], [1,1,1])).gamma_list()
|
|
660
|
+
[-1, -1, -1, -3, 6]
|
|
661
|
+
|
|
662
|
+
sage: Hyp(cyclotomic=([3], [4])).gamma_list()
|
|
663
|
+
[-1, 2, 3, -4]
|
|
664
|
+
"""
|
|
665
|
+
gamma = self.gamma_array()
|
|
666
|
+
resu = []
|
|
667
|
+
for v, n in sorted(gamma.items()):
|
|
668
|
+
resu += [sgn(n) * v] * abs(n)
|
|
669
|
+
return resu
|
|
670
|
+
|
|
671
|
+
def wild_primes(self) -> list:
|
|
672
|
+
r"""
|
|
673
|
+
Return the wild primes.
|
|
674
|
+
|
|
675
|
+
EXAMPLES::
|
|
676
|
+
|
|
677
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
678
|
+
sage: Hyp(cyclotomic=([3], [4])).wild_primes()
|
|
679
|
+
[2, 3]
|
|
680
|
+
sage: Hyp(cyclotomic=([2,2,2,2,3,3,3,6,6], [1,1,4,5,9])).wild_primes()
|
|
681
|
+
[2, 3, 5]
|
|
682
|
+
"""
|
|
683
|
+
gamma = self.gamma_array()
|
|
684
|
+
return sorted({p for n in gamma for p, _ in n.factor()})
|
|
685
|
+
|
|
686
|
+
def zigzag(self, x, flip_beta=False):
|
|
687
|
+
r"""
|
|
688
|
+
Count ``alpha``'s at most ``x`` minus ``beta``'s at most ``x``.
|
|
689
|
+
|
|
690
|
+
This function is used to compute the weight and the Hodge numbers.
|
|
691
|
+
With ``flip_beta`` set to ``True``, replace each `b` in `\beta`
|
|
692
|
+
with `1-b`.
|
|
693
|
+
|
|
694
|
+
.. SEEALSO::
|
|
695
|
+
|
|
696
|
+
:meth:`weight`, :meth:`hodge_numbers`
|
|
697
|
+
|
|
698
|
+
EXAMPLES::
|
|
699
|
+
|
|
700
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
701
|
+
sage: H = Hyp(alpha_beta=([1/6,1/3,2/3,5/6], [1/8,3/8,5/8,7/8]))
|
|
702
|
+
sage: [H.zigzag(x) for x in [0, 1/3, 1/2]]
|
|
703
|
+
[0, 1, 0]
|
|
704
|
+
sage: H = Hyp(cyclotomic=([5], [1,1,1,1]))
|
|
705
|
+
sage: [H.zigzag(x) for x in [0,1/6,1/4,1/2,3/4,5/6]]
|
|
706
|
+
[-4, -4, -3, -2, -1, 0]
|
|
707
|
+
"""
|
|
708
|
+
alpha = self._alpha
|
|
709
|
+
beta = self._beta
|
|
710
|
+
if flip_beta:
|
|
711
|
+
return (sum(1 for a in alpha if a <= x) -
|
|
712
|
+
sum(1 for b in beta if 1 - b <= x))
|
|
713
|
+
return (sum(1 for a in alpha if a <= x) -
|
|
714
|
+
sum(1 for b in beta if b <= x))
|
|
715
|
+
|
|
716
|
+
def weight(self):
|
|
717
|
+
"""
|
|
718
|
+
Return the motivic weight of this motivic data.
|
|
719
|
+
|
|
720
|
+
EXAMPLES:
|
|
721
|
+
|
|
722
|
+
With rational inputs::
|
|
723
|
+
|
|
724
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
725
|
+
sage: Hyp(alpha_beta=([1/2], [0])).weight()
|
|
726
|
+
0
|
|
727
|
+
sage: Hyp(alpha_beta=([1/4,3/4], [0,0])).weight()
|
|
728
|
+
1
|
|
729
|
+
sage: Hyp(alpha_beta=([1/6,1/3,2/3,5/6], [0,0,1/4,3/4])).weight()
|
|
730
|
+
1
|
|
731
|
+
sage: H = Hyp(alpha_beta=([1/6,1/3,2/3,5/6], [1/8,3/8,5/8,7/8]))
|
|
732
|
+
sage: H.weight()
|
|
733
|
+
1
|
|
734
|
+
|
|
735
|
+
With cyclotomic inputs::
|
|
736
|
+
|
|
737
|
+
sage: Hyp(cyclotomic=([6,2], [1,1,1])).weight()
|
|
738
|
+
2
|
|
739
|
+
sage: Hyp(cyclotomic=([6], [1,2])).weight()
|
|
740
|
+
0
|
|
741
|
+
sage: Hyp(cyclotomic=([8], [1,2,3])).weight()
|
|
742
|
+
0
|
|
743
|
+
sage: Hyp(cyclotomic=([5], [1,1,1,1])).weight()
|
|
744
|
+
3
|
|
745
|
+
sage: Hyp(cyclotomic=([5,6], [1,1,2,2,3])).weight()
|
|
746
|
+
1
|
|
747
|
+
sage: Hyp(cyclotomic=([3,8], [1,1,1,2,6])).weight()
|
|
748
|
+
2
|
|
749
|
+
sage: Hyp(cyclotomic=([3,3], [2,2,4])).weight()
|
|
750
|
+
1
|
|
751
|
+
|
|
752
|
+
With gamma list input::
|
|
753
|
+
|
|
754
|
+
sage: Hyp(gamma_list=([8,2,2,2], [6,4,3,1])).weight()
|
|
755
|
+
3
|
|
756
|
+
"""
|
|
757
|
+
alpha = self._alpha
|
|
758
|
+
beta = self._beta
|
|
759
|
+
D = [self.zigzag(x) for x in alpha + beta]
|
|
760
|
+
return ZZ(max(D) - min(D) - 1)
|
|
761
|
+
|
|
762
|
+
def degree(self):
|
|
763
|
+
"""
|
|
764
|
+
Return the degree.
|
|
765
|
+
|
|
766
|
+
This is the sum of the Hodge numbers.
|
|
767
|
+
|
|
768
|
+
.. SEEALSO::
|
|
769
|
+
|
|
770
|
+
:meth:`hodge_numbers`
|
|
771
|
+
|
|
772
|
+
EXAMPLES::
|
|
773
|
+
|
|
774
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
775
|
+
sage: Hyp(alpha_beta=([1/2], [0])).degree()
|
|
776
|
+
1
|
|
777
|
+
sage: Hyp(gamma_list=([2,2,4], [8])).degree()
|
|
778
|
+
4
|
|
779
|
+
sage: Hyp(cyclotomic=([5,6], [1,1,2,2,3])).degree()
|
|
780
|
+
6
|
|
781
|
+
sage: Hyp(cyclotomic=([3,8], [1,1,1,2,6])).degree()
|
|
782
|
+
6
|
|
783
|
+
sage: Hyp(cyclotomic=([3,3], [2,2,4])).degree()
|
|
784
|
+
4
|
|
785
|
+
"""
|
|
786
|
+
return self._deg
|
|
787
|
+
|
|
788
|
+
def hodge_numbers(self) -> list:
|
|
789
|
+
"""
|
|
790
|
+
Return the Hodge numbers.
|
|
791
|
+
|
|
792
|
+
.. SEEALSO::
|
|
793
|
+
|
|
794
|
+
:meth:`degree`, :meth:`hodge_polynomial`, :meth:`hodge_polygon`
|
|
795
|
+
|
|
796
|
+
EXAMPLES::
|
|
797
|
+
|
|
798
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
799
|
+
sage: H = Hyp(cyclotomic=([3], [6]))
|
|
800
|
+
sage: H.hodge_numbers()
|
|
801
|
+
[1, 1]
|
|
802
|
+
|
|
803
|
+
sage: H = Hyp(cyclotomic=([4], [1,2]))
|
|
804
|
+
sage: H.hodge_numbers()
|
|
805
|
+
[2]
|
|
806
|
+
|
|
807
|
+
sage: H = Hyp(gamma_list=([8,2,2,2], [6,4,3,1]))
|
|
808
|
+
sage: H.hodge_numbers()
|
|
809
|
+
[1, 2, 2, 1]
|
|
810
|
+
|
|
811
|
+
sage: H = Hyp(gamma_list=([5], [1,1,1,1,1]))
|
|
812
|
+
sage: H.hodge_numbers()
|
|
813
|
+
[1, 1, 1, 1]
|
|
814
|
+
|
|
815
|
+
sage: H = Hyp(gamma_list=[6,1,-4,-3])
|
|
816
|
+
sage: H.hodge_numbers()
|
|
817
|
+
[1, 1]
|
|
818
|
+
|
|
819
|
+
sage: H = Hyp(gamma_list=[-3]*4 + [1]*12)
|
|
820
|
+
sage: H.hodge_numbers()
|
|
821
|
+
[1, 1, 1, 1, 1, 1, 1, 1]
|
|
822
|
+
|
|
823
|
+
REFERENCES:
|
|
824
|
+
|
|
825
|
+
- [Fedorov2015]_
|
|
826
|
+
"""
|
|
827
|
+
alpha = [(x, 'a') for x in self._alpha]
|
|
828
|
+
beta = [(x, 'b') for x in self._beta]
|
|
829
|
+
height = 0
|
|
830
|
+
hodge: dict[int, int] = defaultdict(int)
|
|
831
|
+
for x, letter in sorted(alpha + beta):
|
|
832
|
+
if letter == 'a':
|
|
833
|
+
hodge[height] += 1
|
|
834
|
+
height += 1
|
|
835
|
+
else:
|
|
836
|
+
height -= 1
|
|
837
|
+
return [hodge[i] for i in sorted(hodge)]
|
|
838
|
+
|
|
839
|
+
def hodge_polynomial(self):
|
|
840
|
+
"""
|
|
841
|
+
Return the Hodge polynomial.
|
|
842
|
+
|
|
843
|
+
.. SEEALSO::
|
|
844
|
+
|
|
845
|
+
:meth:`hodge_numbers`, :meth:`hodge_polygon_vertices`, :meth:`hodge_function`
|
|
846
|
+
|
|
847
|
+
EXAMPLES::
|
|
848
|
+
|
|
849
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
850
|
+
sage: H = Hyp(cyclotomic=([6,10], [3,12]))
|
|
851
|
+
sage: H.hodge_polynomial()
|
|
852
|
+
(T^3 + 2*T^2 + 2*T + 1)/T^2
|
|
853
|
+
sage: H = Hyp(cyclotomic=([2,2,2,2,3,3,3,6,6], [1,1,4,5,9]))
|
|
854
|
+
sage: H.hodge_polynomial()
|
|
855
|
+
(T^5 + 3*T^4 + 3*T^3 + 3*T^2 + 3*T + 1)/T^2
|
|
856
|
+
"""
|
|
857
|
+
alpha = self._alpha
|
|
858
|
+
|
|
859
|
+
def z(x):
|
|
860
|
+
return alpha.count(x)
|
|
861
|
+
|
|
862
|
+
T = polygen(ZZ, 'T')
|
|
863
|
+
return sum(T ** (self.zigzag(a, flip_beta=True) - z(a)) *
|
|
864
|
+
(T**z(a) - 1) // (T - 1)
|
|
865
|
+
for a in set(alpha))
|
|
866
|
+
|
|
867
|
+
def hodge_function(self, x):
|
|
868
|
+
"""
|
|
869
|
+
Evaluate the Hodge polygon as a function.
|
|
870
|
+
|
|
871
|
+
.. SEEALSO::
|
|
872
|
+
|
|
873
|
+
:meth:`hodge_numbers`, :meth:`hodge_polynomial`, :meth:`hodge_polygon_vertices`
|
|
874
|
+
|
|
875
|
+
EXAMPLES::
|
|
876
|
+
|
|
877
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
878
|
+
sage: H = Hyp(cyclotomic=([6,10], [3,12]))
|
|
879
|
+
sage: H.hodge_function(3)
|
|
880
|
+
2
|
|
881
|
+
sage: H.hodge_function(4)
|
|
882
|
+
4
|
|
883
|
+
"""
|
|
884
|
+
d = self.degree()
|
|
885
|
+
hn = self.hodge_numbers()
|
|
886
|
+
if x < 0:
|
|
887
|
+
return 0
|
|
888
|
+
i = 0
|
|
889
|
+
j = 0
|
|
890
|
+
k = 0
|
|
891
|
+
while (i < d and i < x):
|
|
892
|
+
i += hn[k]
|
|
893
|
+
j += k * hn[k]
|
|
894
|
+
k += 1
|
|
895
|
+
if i < x:
|
|
896
|
+
return j
|
|
897
|
+
return j - (i - x) * (k - 1)
|
|
898
|
+
|
|
899
|
+
def hodge_polygon_vertices(self) -> list:
|
|
900
|
+
"""
|
|
901
|
+
Return the vertices of the Hodge polygon.
|
|
902
|
+
|
|
903
|
+
.. SEEALSO::
|
|
904
|
+
|
|
905
|
+
:meth:`hodge_numbers`, :meth:`hodge_polynomial`, :meth:`hodge_function`
|
|
906
|
+
|
|
907
|
+
EXAMPLES::
|
|
908
|
+
|
|
909
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
910
|
+
sage: H = Hyp(cyclotomic=([6,10], [3,12]))
|
|
911
|
+
sage: H.hodge_polygon_vertices()
|
|
912
|
+
[(0, 0), (1, 0), (3, 2), (5, 6), (6, 9)]
|
|
913
|
+
sage: H = Hyp(cyclotomic=([2,2,2,2,3,3,3,6,6], [1,1,4,5,9]))
|
|
914
|
+
sage: H.hodge_polygon_vertices()
|
|
915
|
+
[(0, 0), (1, 0), (4, 3), (7, 9), (10, 18), (13, 30), (14, 35)]
|
|
916
|
+
"""
|
|
917
|
+
lst = [(0, 0)]
|
|
918
|
+
hn = self.hodge_numbers()
|
|
919
|
+
for i in range(len(hn)):
|
|
920
|
+
lst.append((lst[-1][0] + hn[i], lst[-1][1] + i * hn[i]))
|
|
921
|
+
return lst
|
|
922
|
+
|
|
923
|
+
def E_polynomial(self, vars=None):
|
|
924
|
+
"""
|
|
925
|
+
Return the E-polynomial of ``self``.
|
|
926
|
+
|
|
927
|
+
This is a bivariate polynomial.
|
|
928
|
+
|
|
929
|
+
The algorithm is taken from [FRV2019]_.
|
|
930
|
+
|
|
931
|
+
INPUT:
|
|
932
|
+
|
|
933
|
+
- ``vars`` -- (optional) pair of variables (default: `u,v`)
|
|
934
|
+
|
|
935
|
+
REFERENCES:
|
|
936
|
+
|
|
937
|
+
.. [FRV2019] Fernando Rodriguez Villegas, *Mixed Hodge numbers
|
|
938
|
+
and factorial ratios*, :arxiv:`1907.02722`
|
|
939
|
+
|
|
940
|
+
EXAMPLES::
|
|
941
|
+
|
|
942
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData
|
|
943
|
+
sage: H = HypergeometricData(gamma_list=[-30, -1, 6, 10, 15])
|
|
944
|
+
sage: H.E_polynomial()
|
|
945
|
+
8*u*v + 7*u + 7*v + 8
|
|
946
|
+
|
|
947
|
+
sage: p, q = polygens(QQ,'p,q')
|
|
948
|
+
sage: H.E_polynomial((p, q))
|
|
949
|
+
8*p*q + 7*p + 7*q + 8
|
|
950
|
+
|
|
951
|
+
sage: H = HypergeometricData(gamma_list=(-11, -2, 1, 3, 4, 5))
|
|
952
|
+
sage: H.E_polynomial()
|
|
953
|
+
5*u^2*v + 5*u*v^2 + u*v + 1
|
|
954
|
+
|
|
955
|
+
sage: H = HypergeometricData(gamma_list=(-63, -8, -2, 1, 4, 16, 21, 31))
|
|
956
|
+
sage: H.E_polynomial()
|
|
957
|
+
21*u^3*v^2 + 21*u^2*v^3 + u^3*v + 23*u^2*v^2 + u*v^3 + u^2*v + u*v^2 + 2*u*v + 1
|
|
958
|
+
"""
|
|
959
|
+
gamma = self.gamma_list()
|
|
960
|
+
ell = len(gamma)
|
|
961
|
+
|
|
962
|
+
gamma_plus = [g for g in gamma if g > 0]
|
|
963
|
+
gamma_minus = [g for g in gamma if g < 0]
|
|
964
|
+
|
|
965
|
+
domain = {d for g in gamma for d in divisors(g.abs())}
|
|
966
|
+
|
|
967
|
+
m_plus = {d: len([1 for g in gamma_plus if not g % d])
|
|
968
|
+
for d in domain}
|
|
969
|
+
|
|
970
|
+
m_minus = {d: len([1 for g in gamma_minus if not g % d])
|
|
971
|
+
for d in domain}
|
|
972
|
+
|
|
973
|
+
if vars is None:
|
|
974
|
+
u, v = polygens(ZZ, 'u,v')
|
|
975
|
+
else:
|
|
976
|
+
u, v = vars
|
|
977
|
+
uqv = u / v
|
|
978
|
+
uv = u * v
|
|
979
|
+
|
|
980
|
+
A = u.parent()
|
|
981
|
+
delta_sharp_N = {d: A.sum(uqv**sum(frac(j * gi / d) for gi in gamma)
|
|
982
|
+
for j in d.coprime_integers(d))
|
|
983
|
+
for d in domain}
|
|
984
|
+
|
|
985
|
+
loop = [(d, m_plus[d], m_minus[d]) for d in domain]
|
|
986
|
+
|
|
987
|
+
delta_sharp = sum((uqv**m - uqv**p) // (uqv - 1) * v**(ell - 1)
|
|
988
|
+
* delta_sharp_N[d]
|
|
989
|
+
for d, p, m in loop if m > p)
|
|
990
|
+
|
|
991
|
+
delta_zero = sum((uv**min(m, p) - 1) // (uv - 1) * v**(ell - m - p)
|
|
992
|
+
* delta_sharp_N[d]
|
|
993
|
+
for d, p, m in loop)
|
|
994
|
+
|
|
995
|
+
return (delta_sharp + delta_zero - 1).numerator() // (u * v)
|
|
996
|
+
|
|
997
|
+
def M_value(self):
|
|
998
|
+
"""
|
|
999
|
+
Return the `M` coefficient that appears in the trace formula.
|
|
1000
|
+
|
|
1001
|
+
OUTPUT: a rational
|
|
1002
|
+
|
|
1003
|
+
.. SEEALSO:: :meth:`canonical_scheme`
|
|
1004
|
+
|
|
1005
|
+
EXAMPLES::
|
|
1006
|
+
|
|
1007
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1008
|
+
sage: H = Hyp(alpha_beta=([1/6,1/3,2/3,5/6], [1/8,3/8,5/8,7/8]))
|
|
1009
|
+
sage: H.M_value()
|
|
1010
|
+
729/4096
|
|
1011
|
+
sage: Hyp(alpha_beta=(([1/2,1/2,1/2,1/2], [0,0,0,0]))).M_value()
|
|
1012
|
+
256
|
|
1013
|
+
sage: Hyp(cyclotomic=([5], [1,1,1,1])).M_value()
|
|
1014
|
+
3125
|
|
1015
|
+
"""
|
|
1016
|
+
return self._M_value
|
|
1017
|
+
|
|
1018
|
+
def is_primitive(self) -> bool:
|
|
1019
|
+
"""
|
|
1020
|
+
Return whether this data is primitive.
|
|
1021
|
+
|
|
1022
|
+
.. SEEALSO::
|
|
1023
|
+
|
|
1024
|
+
:meth:`primitive_index`, :meth:`primitive_data`
|
|
1025
|
+
|
|
1026
|
+
EXAMPLES::
|
|
1027
|
+
|
|
1028
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1029
|
+
sage: Hyp(cyclotomic=([3], [4])).is_primitive()
|
|
1030
|
+
True
|
|
1031
|
+
sage: Hyp(gamma_list=[-2, 4, 6, -8]).is_primitive()
|
|
1032
|
+
False
|
|
1033
|
+
sage: Hyp(gamma_list=[-3, 6, 9, -12]).is_primitive()
|
|
1034
|
+
False
|
|
1035
|
+
"""
|
|
1036
|
+
return self.primitive_index() == 1
|
|
1037
|
+
|
|
1038
|
+
def primitive_index(self):
|
|
1039
|
+
"""
|
|
1040
|
+
Return the primitive index.
|
|
1041
|
+
|
|
1042
|
+
.. SEEALSO::
|
|
1043
|
+
|
|
1044
|
+
:meth:`is_primitive`, :meth:`primitive_data`
|
|
1045
|
+
|
|
1046
|
+
EXAMPLES::
|
|
1047
|
+
|
|
1048
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1049
|
+
sage: Hyp(cyclotomic=([3], [4])).primitive_index()
|
|
1050
|
+
1
|
|
1051
|
+
sage: Hyp(gamma_list=[-2, 4, 6, -8]).primitive_index()
|
|
1052
|
+
2
|
|
1053
|
+
sage: Hyp(gamma_list=[-3, 6, 9, -12]).primitive_index()
|
|
1054
|
+
3
|
|
1055
|
+
"""
|
|
1056
|
+
return gcd(self.gamma_list())
|
|
1057
|
+
|
|
1058
|
+
def has_symmetry_at_one(self) -> bool:
|
|
1059
|
+
"""
|
|
1060
|
+
If ``True``, the motive H(t=1) is a direct sum of two motives.
|
|
1061
|
+
|
|
1062
|
+
Note that simultaneous exchange of (t,1/t) and (alpha,beta)
|
|
1063
|
+
always gives the same motive.
|
|
1064
|
+
|
|
1065
|
+
EXAMPLES::
|
|
1066
|
+
|
|
1067
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1068
|
+
sage: Hyp(alpha_beta=[[1/2]*16, [0]*16]).has_symmetry_at_one()
|
|
1069
|
+
True
|
|
1070
|
+
|
|
1071
|
+
REFERENCES:
|
|
1072
|
+
|
|
1073
|
+
- [Roberts2017]_
|
|
1074
|
+
"""
|
|
1075
|
+
beta_twist = self.twist()._beta
|
|
1076
|
+
return self.degree() % 2 == 0 and self._alpha == beta_twist
|
|
1077
|
+
|
|
1078
|
+
def lfunction(self, t, prec=53):
|
|
1079
|
+
"""
|
|
1080
|
+
Return the `L`-function of ``self``.
|
|
1081
|
+
|
|
1082
|
+
The result is a wrapper around a PARI `L`-function.
|
|
1083
|
+
|
|
1084
|
+
INPUT:
|
|
1085
|
+
|
|
1086
|
+
- ``prec`` -- precision (default: 53)
|
|
1087
|
+
|
|
1088
|
+
EXAMPLES::
|
|
1089
|
+
|
|
1090
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1091
|
+
sage: H = Hyp(cyclotomic=([3], [4]))
|
|
1092
|
+
sage: L = H.lfunction(1/64); L
|
|
1093
|
+
PARI L-function associated to Hypergeometric data for [1/3, 2/3] and [1/4, 3/4]
|
|
1094
|
+
sage: L(4)
|
|
1095
|
+
0.997734256321692
|
|
1096
|
+
"""
|
|
1097
|
+
from sage.lfunctions.pari import lfun_hgm, LFunction
|
|
1098
|
+
Z = LFunction(lfun_hgm(self, t), prec=prec)
|
|
1099
|
+
Z.rename('PARI L-function associated to %s' % self)
|
|
1100
|
+
return Z
|
|
1101
|
+
|
|
1102
|
+
def canonical_scheme(self, t=None):
|
|
1103
|
+
"""
|
|
1104
|
+
Return the canonical scheme.
|
|
1105
|
+
|
|
1106
|
+
This is a scheme that contains this hypergeometric motive in its cohomology.
|
|
1107
|
+
|
|
1108
|
+
EXAMPLES::
|
|
1109
|
+
|
|
1110
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1111
|
+
sage: H = Hyp(cyclotomic=([3], [4]))
|
|
1112
|
+
sage: H.gamma_list()
|
|
1113
|
+
[-1, 2, 3, -4]
|
|
1114
|
+
sage: H.canonical_scheme()
|
|
1115
|
+
Spectrum of Quotient of Multivariate Polynomial Ring
|
|
1116
|
+
in X0, X1, Y0, Y1 over Fraction Field of Univariate Polynomial Ring
|
|
1117
|
+
in t over Rational Field by the ideal
|
|
1118
|
+
(X0 + X1 - 1, Y0 + Y1 - 1, (-t)*X0^2*X1^3 + 27/64*Y0*Y1^4)
|
|
1119
|
+
|
|
1120
|
+
sage: H = Hyp(gamma_list=[-2, 3, 4, -5])
|
|
1121
|
+
sage: H.canonical_scheme()
|
|
1122
|
+
Spectrum of Quotient of Multivariate Polynomial Ring
|
|
1123
|
+
in X0, X1, Y0, Y1 over Fraction Field of Univariate Polynomial Ring
|
|
1124
|
+
in t over Rational Field by the ideal
|
|
1125
|
+
(X0 + X1 - 1, Y0 + Y1 - 1, (-t)*X0^3*X1^4 + 1728/3125*Y0^2*Y1^5)
|
|
1126
|
+
|
|
1127
|
+
REFERENCES:
|
|
1128
|
+
|
|
1129
|
+
[Kat1991]_, section 5.4
|
|
1130
|
+
"""
|
|
1131
|
+
if t is None:
|
|
1132
|
+
t = FractionField(QQ['t']).gen()
|
|
1133
|
+
basering = t.parent()
|
|
1134
|
+
gamma_pos = [u for u in self.gamma_list() if u > 0]
|
|
1135
|
+
gamma_neg = [u for u in self.gamma_list() if u < 0]
|
|
1136
|
+
N_pos = len(gamma_pos)
|
|
1137
|
+
N_neg = len(gamma_neg)
|
|
1138
|
+
varX = [f'X{i}' for i in range(N_pos)]
|
|
1139
|
+
varY = [f'Y{i}' for i in range(N_neg)]
|
|
1140
|
+
ring = PolynomialRing(basering, varX + varY)
|
|
1141
|
+
gens = ring.gens()
|
|
1142
|
+
X = gens[:N_pos]
|
|
1143
|
+
Y = gens[N_pos:]
|
|
1144
|
+
eq0 = ring.sum(X) - 1
|
|
1145
|
+
eq1 = ring.sum(Y) - 1
|
|
1146
|
+
eq2_pos = ring.prod(X[i] ** gamma_pos[i] for i in range(N_pos))
|
|
1147
|
+
eq2_neg = ring.prod(Y[j] ** -gamma_neg[j] for j in range(N_neg))
|
|
1148
|
+
|
|
1149
|
+
ideal = ring.ideal([eq0, eq1, self.M_value() * eq2_neg - t * eq2_pos])
|
|
1150
|
+
return Spec(ring.quotient(ideal))
|
|
1151
|
+
|
|
1152
|
+
def lattice_polytope(self):
|
|
1153
|
+
"""
|
|
1154
|
+
Return the associated lattice polytope.
|
|
1155
|
+
|
|
1156
|
+
This uses the matrix defined in section 3 of [RRV2022]_ and
|
|
1157
|
+
section 3 of [RV2019]_.
|
|
1158
|
+
|
|
1159
|
+
EXAMPLES::
|
|
1160
|
+
|
|
1161
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1162
|
+
sage: H = Hyp(gamma_list=[-5, -2, 3, 4])
|
|
1163
|
+
sage: P = H.lattice_polytope(); P
|
|
1164
|
+
2-d lattice polytope in 2-d lattice M
|
|
1165
|
+
sage: P.polyhedron().f_vector()
|
|
1166
|
+
(1, 4, 4, 1)
|
|
1167
|
+
sage: len(P.points()) # needs palp
|
|
1168
|
+
7
|
|
1169
|
+
|
|
1170
|
+
The Chebyshev example from [RV2019]_::
|
|
1171
|
+
|
|
1172
|
+
sage: H = Hyp(gamma_list=[-30, -1, 6, 10, 15])
|
|
1173
|
+
sage: P = H.lattice_polytope(); P
|
|
1174
|
+
3-d lattice polytope in 3-d lattice M
|
|
1175
|
+
sage: len(P.points()) # needs palp
|
|
1176
|
+
19
|
|
1177
|
+
sage: P.polyhedron().f_vector()
|
|
1178
|
+
(1, 5, 9, 6, 1)
|
|
1179
|
+
"""
|
|
1180
|
+
l = len(self.gamma_list())
|
|
1181
|
+
m = matrix(ZZ, l, 1, self.gamma_list())
|
|
1182
|
+
ext_ker = m.kernel().basis_matrix().insert_row(0, vector(ZZ, [1] * l))
|
|
1183
|
+
unique_relation = ext_ker.kernel().basis()[0]
|
|
1184
|
+
removed = next(i for i, ci in enumerate(unique_relation)
|
|
1185
|
+
if i and abs(ci) == 1)
|
|
1186
|
+
mat = matrix(ZZ, [v for i, v in enumerate(ext_ker)
|
|
1187
|
+
if i and i != removed])
|
|
1188
|
+
return LatticePolytope(mat.transpose())
|
|
1189
|
+
|
|
1190
|
+
# --- Operations on data ---
|
|
1191
|
+
def twist(self):
|
|
1192
|
+
r"""
|
|
1193
|
+
Return the twist of this data.
|
|
1194
|
+
|
|
1195
|
+
This is defined by adding `1/2` to each rational in `\alpha`
|
|
1196
|
+
and `\beta`.
|
|
1197
|
+
|
|
1198
|
+
This is an involution.
|
|
1199
|
+
|
|
1200
|
+
EXAMPLES::
|
|
1201
|
+
|
|
1202
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1203
|
+
sage: H = Hyp(alpha_beta=([1/2], [0]))
|
|
1204
|
+
sage: H.twist()
|
|
1205
|
+
Hypergeometric data for [0] and [1/2]
|
|
1206
|
+
sage: H.twist().twist() == H
|
|
1207
|
+
True
|
|
1208
|
+
|
|
1209
|
+
sage: Hyp(cyclotomic=([6], [1,2])).twist().cyclotomic_data()
|
|
1210
|
+
([3], [1, 2])
|
|
1211
|
+
"""
|
|
1212
|
+
alpha = [x + QQ((1, 2)) for x in self._alpha]
|
|
1213
|
+
beta = [x + QQ((1, 2)) for x in self._beta]
|
|
1214
|
+
return HypergeometricData(alpha_beta=(alpha, beta))
|
|
1215
|
+
|
|
1216
|
+
def swap_alpha_beta(self):
|
|
1217
|
+
"""
|
|
1218
|
+
Return the hypergeometric data with ``alpha`` and ``beta`` exchanged.
|
|
1219
|
+
|
|
1220
|
+
EXAMPLES::
|
|
1221
|
+
|
|
1222
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1223
|
+
sage: H = Hyp(alpha_beta=([1/2], [0]))
|
|
1224
|
+
sage: H.swap_alpha_beta()
|
|
1225
|
+
Hypergeometric data for [0] and [1/2]
|
|
1226
|
+
"""
|
|
1227
|
+
alpha, beta = self.alpha_beta()
|
|
1228
|
+
return HypergeometricData(alpha_beta=(beta, alpha))
|
|
1229
|
+
|
|
1230
|
+
def primitive_data(self):
|
|
1231
|
+
"""
|
|
1232
|
+
Return a primitive version.
|
|
1233
|
+
|
|
1234
|
+
.. SEEALSO::
|
|
1235
|
+
|
|
1236
|
+
:meth:`is_primitive`, :meth:`primitive_index`
|
|
1237
|
+
|
|
1238
|
+
EXAMPLES::
|
|
1239
|
+
|
|
1240
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1241
|
+
sage: H = Hyp(cyclotomic=([3], [4]))
|
|
1242
|
+
sage: H2 = Hyp(gamma_list=[-2, 4, 6, -8])
|
|
1243
|
+
sage: H2.primitive_data() == H
|
|
1244
|
+
True
|
|
1245
|
+
"""
|
|
1246
|
+
g = self.gamma_list()
|
|
1247
|
+
d = gcd(g)
|
|
1248
|
+
return HypergeometricData(gamma_list=[x / d for x in g])
|
|
1249
|
+
|
|
1250
|
+
# ----- L-functions -----
|
|
1251
|
+
|
|
1252
|
+
def gauss_table(self, p, f, prec):
|
|
1253
|
+
"""
|
|
1254
|
+
Return (and cache) a table of Gauss sums used in the trace formula.
|
|
1255
|
+
|
|
1256
|
+
.. SEEALSO::
|
|
1257
|
+
|
|
1258
|
+
:meth:`gauss_table_full`
|
|
1259
|
+
|
|
1260
|
+
EXAMPLES::
|
|
1261
|
+
|
|
1262
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1263
|
+
sage: H = Hyp(cyclotomic=([3], [4]))
|
|
1264
|
+
sage: H.gauss_table(2, 2, 4)
|
|
1265
|
+
(4, [1 + 2 + 2^2 + 2^3, 1 + 2 + 2^2 + 2^3, 1 + 2 + 2^2 + 2^3])
|
|
1266
|
+
"""
|
|
1267
|
+
try:
|
|
1268
|
+
prec1, gtab = self._gauss_table[p, f]
|
|
1269
|
+
if prec1 < prec:
|
|
1270
|
+
raise KeyError
|
|
1271
|
+
except KeyError:
|
|
1272
|
+
use_longs = (p ** prec < 2 ** 31)
|
|
1273
|
+
gtab = gauss_table(p, f, prec, use_longs)
|
|
1274
|
+
self._gauss_table[p, f] = (prec, gtab)
|
|
1275
|
+
prec1 = prec
|
|
1276
|
+
return prec1, gtab
|
|
1277
|
+
|
|
1278
|
+
def gauss_table_full(self):
|
|
1279
|
+
"""
|
|
1280
|
+
Return a dict of all stored tables of Gauss sums.
|
|
1281
|
+
|
|
1282
|
+
The result is passed by reference, and is an attribute of the class;
|
|
1283
|
+
consequently, modifying the result has global side effects. Use with
|
|
1284
|
+
caution.
|
|
1285
|
+
|
|
1286
|
+
.. SEEALSO::
|
|
1287
|
+
|
|
1288
|
+
:meth:`gauss_table`
|
|
1289
|
+
|
|
1290
|
+
EXAMPLES::
|
|
1291
|
+
|
|
1292
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1293
|
+
sage: H = Hyp(cyclotomic=([3], [4]))
|
|
1294
|
+
sage: H.euler_factor(2, 7, cache_p=True)
|
|
1295
|
+
7*T^2 - 3*T + 1
|
|
1296
|
+
sage: H.gauss_table_full()[(7, 1)]
|
|
1297
|
+
(2, array('l', [-1, -29, -25, -48, -47, -22]))
|
|
1298
|
+
|
|
1299
|
+
Clearing cached values::
|
|
1300
|
+
|
|
1301
|
+
sage: H = Hyp(cyclotomic=([3], [4]))
|
|
1302
|
+
sage: H.euler_factor(2, 7, cache_p=True)
|
|
1303
|
+
7*T^2 - 3*T + 1
|
|
1304
|
+
sage: d = H.gauss_table_full()
|
|
1305
|
+
sage: d.clear() # Delete all entries of this dict
|
|
1306
|
+
sage: H1 = Hyp(cyclotomic=([5], [12]))
|
|
1307
|
+
sage: d1 = H1.gauss_table_full()
|
|
1308
|
+
sage: len(d1.keys()) # No cached values
|
|
1309
|
+
0
|
|
1310
|
+
"""
|
|
1311
|
+
return self._gauss_table
|
|
1312
|
+
|
|
1313
|
+
# --- L-functions ---
|
|
1314
|
+
@cached_method
|
|
1315
|
+
def padic_H_value(self, p, f, t, prec=None, cache_p=False):
|
|
1316
|
+
"""
|
|
1317
|
+
Return the `p`-adic trace of Frobenius, computed using the
|
|
1318
|
+
Gross-Koblitz formula.
|
|
1319
|
+
|
|
1320
|
+
If left unspecified, `prec` is set to the minimum `p`-adic precision
|
|
1321
|
+
needed to recover the Euler factor.
|
|
1322
|
+
|
|
1323
|
+
If ``cache_p`` is ``True``, then the function caches an intermediate
|
|
1324
|
+
result which depends only on `p` and `f`. This leads to a significant
|
|
1325
|
+
speedup when iterating over `t`.
|
|
1326
|
+
|
|
1327
|
+
INPUT:
|
|
1328
|
+
|
|
1329
|
+
- ``p`` -- a prime number
|
|
1330
|
+
|
|
1331
|
+
- ``f`` -- integer such that `q = p^f`
|
|
1332
|
+
|
|
1333
|
+
- ``t`` -- a rational parameter
|
|
1334
|
+
|
|
1335
|
+
- ``prec`` -- precision (optional)
|
|
1336
|
+
|
|
1337
|
+
- ``cache_p`` -- boolean
|
|
1338
|
+
|
|
1339
|
+
OUTPUT: integer
|
|
1340
|
+
|
|
1341
|
+
EXAMPLES:
|
|
1342
|
+
|
|
1343
|
+
From Benasque report [Benasque2009]_, page 8::
|
|
1344
|
+
|
|
1345
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1346
|
+
sage: H = Hyp(alpha_beta=([1/2]*4, [0]*4))
|
|
1347
|
+
sage: [H.padic_H_value(3,i,-1) for i in range(1,3)]
|
|
1348
|
+
[0, -12]
|
|
1349
|
+
sage: [H.padic_H_value(5,i,-1) for i in range(1,3)]
|
|
1350
|
+
[-4, 276]
|
|
1351
|
+
sage: [H.padic_H_value(7,i,-1) for i in range(1,3)]
|
|
1352
|
+
[0, -476]
|
|
1353
|
+
sage: [H.padic_H_value(11,i,-1) for i in range(1,3)]
|
|
1354
|
+
[0, -4972]
|
|
1355
|
+
|
|
1356
|
+
From [Roberts2015]_ (but note conventions regarding `t`)::
|
|
1357
|
+
|
|
1358
|
+
sage: H = Hyp(gamma_list=[-6,-1,4,3])
|
|
1359
|
+
sage: t = 189/125
|
|
1360
|
+
sage: H.padic_H_value(13,1,1/t)
|
|
1361
|
+
0
|
|
1362
|
+
|
|
1363
|
+
TESTS:
|
|
1364
|
+
|
|
1365
|
+
Check issue from :issue:`28404`::
|
|
1366
|
+
|
|
1367
|
+
sage: H1 = Hyp(cyclotomic=([1,1,1], [6,2]))
|
|
1368
|
+
sage: H2 = Hyp(cyclotomic=([6,2], [1,1,1]))
|
|
1369
|
+
sage: [H1.padic_H_value(5,1,i) for i in range(2,5)]
|
|
1370
|
+
[1, -4, -4]
|
|
1371
|
+
sage: [H2.padic_H_value(5,1,i) for i in range(2,5)]
|
|
1372
|
+
[-4, 1, -4]
|
|
1373
|
+
|
|
1374
|
+
Check for potential overflow::
|
|
1375
|
+
|
|
1376
|
+
sage: H = Hyp(cyclotomic=[[10,6], [5,4]])
|
|
1377
|
+
sage: H.padic_H_value(101, 2, 2)
|
|
1378
|
+
-1560629
|
|
1379
|
+
|
|
1380
|
+
Check issue from :issue:`29778`::
|
|
1381
|
+
|
|
1382
|
+
sage: H = Hyp(alpha_beta=([1/5,2/5,3/5,4/5,1/5,2/5,3/5,4/5], [1/4,3/4,1/7,2/7,3/7,4/7,5/7,6/7]))
|
|
1383
|
+
sage: try:
|
|
1384
|
+
....: print(H.padic_H_value(373, 4, 2))
|
|
1385
|
+
....: except ValueError as s:
|
|
1386
|
+
....: print(s)
|
|
1387
|
+
p^f cannot exceed 2^31
|
|
1388
|
+
|
|
1389
|
+
Check error handling for wild and tame primes::
|
|
1390
|
+
|
|
1391
|
+
sage: H = Hyp(alpha_beta=([1/5,2/5,3/5,4/5,1/5,2/5,3/5,4/5], [1/4,3/4,1/7,2/7,3/7,4/7,5/7,6/7]))
|
|
1392
|
+
sage: try:
|
|
1393
|
+
....: print(H.padic_H_value(5, 1, 2))
|
|
1394
|
+
....: except NotImplementedError as s:
|
|
1395
|
+
....: print(s)
|
|
1396
|
+
p is wild
|
|
1397
|
+
sage: try:
|
|
1398
|
+
....: print(H.padic_H_value(3, 1, 3))
|
|
1399
|
+
....: except NotImplementedError as s:
|
|
1400
|
+
....: print(s)
|
|
1401
|
+
p is tame
|
|
1402
|
+
|
|
1403
|
+
Check that :issue:`37910` is resolved::
|
|
1404
|
+
|
|
1405
|
+
sage: H = Hyp(alpha_beta=[[1/2,1/2,1/2,1/2,1/2,1/3,2/3,1/6,5/6], [0,0,0,0,0,0,0,0,0]])
|
|
1406
|
+
sage: H.padic_H_value(151, 2, -512000)
|
|
1407
|
+
50178940126155881
|
|
1408
|
+
|
|
1409
|
+
REFERENCES:
|
|
1410
|
+
|
|
1411
|
+
- [MagmaHGM]_
|
|
1412
|
+
"""
|
|
1413
|
+
alpha = self._alpha
|
|
1414
|
+
beta = self._beta
|
|
1415
|
+
t = QQ(t)
|
|
1416
|
+
if not is_prime(p):
|
|
1417
|
+
raise ValueError('p not prime')
|
|
1418
|
+
if not all(x.denominator() % p for x in self._alpha + self._beta):
|
|
1419
|
+
raise NotImplementedError('p is wild')
|
|
1420
|
+
if t.numerator() % p == 0 or t.denominator() % p == 0:
|
|
1421
|
+
raise NotImplementedError('p is tame')
|
|
1422
|
+
|
|
1423
|
+
if 0 in alpha:
|
|
1424
|
+
return self._swap.padic_H_value(p, f, ~t, prec)
|
|
1425
|
+
q = p ** f
|
|
1426
|
+
if q > 2 ** 31:
|
|
1427
|
+
raise ValueError("p^f cannot exceed 2^31")
|
|
1428
|
+
|
|
1429
|
+
m: dict[int, int] = defaultdict(int)
|
|
1430
|
+
for b in beta:
|
|
1431
|
+
u = b * (q - 1)
|
|
1432
|
+
if u.is_integer():
|
|
1433
|
+
m[u] += 1
|
|
1434
|
+
M = self.M_value()
|
|
1435
|
+
D = -min(self.zigzag(x, flip_beta=True) for x in alpha + beta)
|
|
1436
|
+
# also: D = (self.weight() + 1 - m[0]) // 2
|
|
1437
|
+
|
|
1438
|
+
if prec is None:
|
|
1439
|
+
prec = ceil((self.weight() * f) / 2 + log(2 * self.degree() + 1, p))
|
|
1440
|
+
use_longs = (p ** prec < 2 ** 31)
|
|
1441
|
+
|
|
1442
|
+
gamma = self._gamma_array
|
|
1443
|
+
if cache_p:
|
|
1444
|
+
try:
|
|
1445
|
+
trcoeffs = self._trace_coeffs[p, f]
|
|
1446
|
+
except KeyError:
|
|
1447
|
+
gtab_prec, gtab = self.gauss_table(p, f, prec)
|
|
1448
|
+
trcoeffs = hgm_coeffs(p, f, prec, gamma, m, D, gtab, gtab_prec, use_longs)
|
|
1449
|
+
self._trace_coeffs[p, f] = trcoeffs
|
|
1450
|
+
else:
|
|
1451
|
+
gtab = gauss_table(p, f, prec, use_longs)
|
|
1452
|
+
trcoeffs = hgm_coeffs(p, f, prec, gamma, m, D, gtab, prec, use_longs)
|
|
1453
|
+
sigma = trcoeffs[p - 2]
|
|
1454
|
+
p_ring = sigma.parent()
|
|
1455
|
+
|
|
1456
|
+
teich = p_ring.teichmuller(M / t)
|
|
1457
|
+
for i in range(p - 3, -1, -1):
|
|
1458
|
+
sigma = sigma * teich + trcoeffs[i]
|
|
1459
|
+
resu = ZZ(-1) ** m[0] * sigma / (1 - q)
|
|
1460
|
+
return IntegerModRing(p**prec)(resu).lift_centered()
|
|
1461
|
+
|
|
1462
|
+
trace = padic_H_value
|
|
1463
|
+
|
|
1464
|
+
@cached_method
|
|
1465
|
+
def H_value(self, p, f, t, ring=None):
|
|
1466
|
+
"""
|
|
1467
|
+
Return the trace of the Frobenius, computed in terms of Gauss sums
|
|
1468
|
+
using the hypergeometric trace formula.
|
|
1469
|
+
|
|
1470
|
+
INPUT:
|
|
1471
|
+
|
|
1472
|
+
- ``p`` -- a prime number
|
|
1473
|
+
|
|
1474
|
+
- ``f`` -- integer such that `q = p^f`
|
|
1475
|
+
|
|
1476
|
+
- ``t`` -- a rational parameter
|
|
1477
|
+
|
|
1478
|
+
- ``ring`` -- (default: :class:`UniversalCyclotomicfield`)
|
|
1479
|
+
|
|
1480
|
+
The ring could be also ``ComplexField(n)`` or ``QQbar``.
|
|
1481
|
+
|
|
1482
|
+
OUTPUT: integer
|
|
1483
|
+
|
|
1484
|
+
.. WARNING::
|
|
1485
|
+
|
|
1486
|
+
This is apparently working correctly as can be tested
|
|
1487
|
+
using ``ComplexField(70)`` as the value ring.
|
|
1488
|
+
|
|
1489
|
+
Using instead :class:`UniversalCyclotomicfield`, this is much
|
|
1490
|
+
slower than the `p`-adic version :meth:`padic_H_value`.
|
|
1491
|
+
|
|
1492
|
+
Unlike in :meth:`padic_H_value`, tame and wild primes are not supported.
|
|
1493
|
+
|
|
1494
|
+
EXAMPLES:
|
|
1495
|
+
|
|
1496
|
+
With values in the :class:`UniversalCyclotomicField` (slow)::
|
|
1497
|
+
|
|
1498
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1499
|
+
|
|
1500
|
+
sage: # needs sage.libs.gap sage.rings.number_field
|
|
1501
|
+
sage: H = Hyp(alpha_beta=([1/2]*4, [0]*4))
|
|
1502
|
+
sage: [H.H_value(3,i,-1) for i in range(1,3)]
|
|
1503
|
+
[0, -12]
|
|
1504
|
+
sage: [H.H_value(5,i,-1) for i in range(1,3)]
|
|
1505
|
+
[-4, 276]
|
|
1506
|
+
sage: [H.H_value(7,i,-1) for i in range(1,3)] # not tested
|
|
1507
|
+
[0, -476]
|
|
1508
|
+
sage: [H.H_value(11,i,-1) for i in range(1,3)] # not tested
|
|
1509
|
+
[0, -4972]
|
|
1510
|
+
sage: [H.H_value(13,i,-1) for i in range(1,3)] # not tested
|
|
1511
|
+
[-84, -1420]
|
|
1512
|
+
|
|
1513
|
+
With values in :class:`ComplexField`::
|
|
1514
|
+
|
|
1515
|
+
sage: [H.H_value(5,i,-1, ComplexField(60)) for i in range(1,3)] # needs sage.libs.gap sage.rings.number_field
|
|
1516
|
+
[-4, 276]
|
|
1517
|
+
|
|
1518
|
+
Check issue from :issue:`28404`::
|
|
1519
|
+
|
|
1520
|
+
sage: H1 = Hyp(cyclotomic=([1,1,1], [6,2]))
|
|
1521
|
+
sage: H2 = Hyp(cyclotomic=([6,2], [1,1,1]))
|
|
1522
|
+
sage: [H1.H_value(5,1,i) for i in range(2,5)]
|
|
1523
|
+
[1, -4, -4]
|
|
1524
|
+
sage: [H2.H_value(5,1,QQ(i)) for i in range(2,5)]
|
|
1525
|
+
[-4, 1, -4]
|
|
1526
|
+
|
|
1527
|
+
TESTS:
|
|
1528
|
+
|
|
1529
|
+
Check issue from :issue:`29778`::
|
|
1530
|
+
|
|
1531
|
+
sage: H = Hyp(cyclotomic=[[5,5], [4,7]])
|
|
1532
|
+
sage: try:
|
|
1533
|
+
....: print(H.padic_H_value(373, 4, 2))
|
|
1534
|
+
....: except ValueError as s:
|
|
1535
|
+
....: print(s)
|
|
1536
|
+
p^f cannot exceed 2^31
|
|
1537
|
+
|
|
1538
|
+
Check error handling for wild and tame primes::
|
|
1539
|
+
|
|
1540
|
+
sage: H = Hyp(cyclotomic=[[5,5], [4,7]])
|
|
1541
|
+
sage: try:
|
|
1542
|
+
....: print(H.padic_H_value(5, 1, 2))
|
|
1543
|
+
....: except NotImplementedError as s:
|
|
1544
|
+
....: print(s)
|
|
1545
|
+
p is wild
|
|
1546
|
+
sage: try:
|
|
1547
|
+
....: print(H.padic_H_value(3, 1, 3))
|
|
1548
|
+
....: except NotImplementedError as s:
|
|
1549
|
+
....: print(s)
|
|
1550
|
+
p is tame
|
|
1551
|
+
|
|
1552
|
+
REFERENCES:
|
|
1553
|
+
|
|
1554
|
+
- [BeCoMe]_ (Theorem 1.3)
|
|
1555
|
+
- [Benasque2009]_
|
|
1556
|
+
"""
|
|
1557
|
+
alpha = self._alpha
|
|
1558
|
+
beta = self._beta
|
|
1559
|
+
t = QQ(t)
|
|
1560
|
+
if not is_prime(p):
|
|
1561
|
+
raise ValueError('p not prime')
|
|
1562
|
+
if not all(x.denominator() % p for x in self._alpha + self._beta):
|
|
1563
|
+
raise NotImplementedError('p is wild')
|
|
1564
|
+
if (t.numerator() * t.denominator() % p == 0 or (t - 1) % p == 0):
|
|
1565
|
+
raise NotImplementedError('p is tame')
|
|
1566
|
+
|
|
1567
|
+
if 0 in alpha:
|
|
1568
|
+
return self._swap.H_value(p, f, ~t, ring)
|
|
1569
|
+
if ring is None:
|
|
1570
|
+
ring = UniversalCyclotomicField()
|
|
1571
|
+
gamma = self.gamma_array()
|
|
1572
|
+
q = p**f
|
|
1573
|
+
|
|
1574
|
+
m = {r: beta.count(QQ((r, q - 1))) for r in range(q - 1)}
|
|
1575
|
+
D = -min(self.zigzag(x, flip_beta=True) for x in alpha + beta)
|
|
1576
|
+
# also: D = (self.weight() + 1 - m[0]) // 2
|
|
1577
|
+
M = self.M_value()
|
|
1578
|
+
|
|
1579
|
+
Fq = GF((p, f))
|
|
1580
|
+
gen = Fq.multiplicative_generator()
|
|
1581
|
+
zeta_q = ring.zeta(q - 1)
|
|
1582
|
+
|
|
1583
|
+
tM = Fq(M / t)
|
|
1584
|
+
for k in range(q - 1):
|
|
1585
|
+
if gen ** k == tM:
|
|
1586
|
+
teich = zeta_q ** k
|
|
1587
|
+
break
|
|
1588
|
+
|
|
1589
|
+
gauss_table = [gauss_sum(zeta_q ** r, Fq) for r in range(q - 1)]
|
|
1590
|
+
|
|
1591
|
+
sigma = sum(q**(D + m[0] - m[r]) *
|
|
1592
|
+
prod(gauss_table[(-v * r) % (q - 1)]**gv
|
|
1593
|
+
for v, gv in gamma.items()) *
|
|
1594
|
+
teich ** r
|
|
1595
|
+
for r in range(q - 1))
|
|
1596
|
+
resu = ZZ(-1) ** m[0] / (1 - q) * sigma
|
|
1597
|
+
if not ring.is_exact():
|
|
1598
|
+
resu = resu.real_part().round()
|
|
1599
|
+
return resu
|
|
1600
|
+
|
|
1601
|
+
def sign(self, t, p):
|
|
1602
|
+
"""
|
|
1603
|
+
Return the sign of the functional equation for the Euler factor of the motive `H_t` at the prime `p`.
|
|
1604
|
+
|
|
1605
|
+
For odd weight, the sign of the functional equation is +1. For even
|
|
1606
|
+
weight, the sign is computed by a recipe found in Section 11.1 of [Watkins]_
|
|
1607
|
+
(when 0 is not in alpha).
|
|
1608
|
+
|
|
1609
|
+
EXAMPLES::
|
|
1610
|
+
|
|
1611
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1612
|
+
sage: H = Hyp(cyclotomic=([6,2], [1,1,1]))
|
|
1613
|
+
sage: H.weight(), H.degree()
|
|
1614
|
+
(2, 3)
|
|
1615
|
+
sage: [H.sign(1/4,p) for p in [5,7,11,13,17,19]]
|
|
1616
|
+
[1, 1, -1, -1, 1, 1]
|
|
1617
|
+
|
|
1618
|
+
sage: H = Hyp(alpha_beta=([1/12,5/12,7/12,11/12], [0,1/2,1/2,1/2]))
|
|
1619
|
+
sage: H.weight(), H.degree()
|
|
1620
|
+
(2, 4)
|
|
1621
|
+
sage: t = -5
|
|
1622
|
+
sage: [H.sign(1/t,p) for p in [11,13,17,19,23,29]]
|
|
1623
|
+
[-1, -1, -1, 1, 1, 1]
|
|
1624
|
+
|
|
1625
|
+
We check that :issue:`28404` is fixed::
|
|
1626
|
+
|
|
1627
|
+
sage: H = Hyp(cyclotomic=([1,1,1], [6,2]))
|
|
1628
|
+
sage: [H.sign(4,p) for p in [5,7,11,13,17,19]]
|
|
1629
|
+
[1, 1, -1, -1, 1, 1]
|
|
1630
|
+
"""
|
|
1631
|
+
t = QQ(t)
|
|
1632
|
+
if 0 in self._alpha:
|
|
1633
|
+
return self._swap.sign(~t, p)
|
|
1634
|
+
d = self.degree()
|
|
1635
|
+
w = self.weight()
|
|
1636
|
+
|
|
1637
|
+
if w % 2: # sign is always +1 for odd weight
|
|
1638
|
+
sign = 1
|
|
1639
|
+
elif d % 2:
|
|
1640
|
+
sign = -kronecker_symbol((1 - t) * self._sign_param, p)
|
|
1641
|
+
else:
|
|
1642
|
+
sign = kronecker_symbol(t * (t - 1) * self._sign_param, p)
|
|
1643
|
+
return sign
|
|
1644
|
+
|
|
1645
|
+
def euler_factor_tame_contribution(self, t, p, mo, deg=None):
|
|
1646
|
+
"""
|
|
1647
|
+
Return a contribution to the Euler factor of the motive `H_t` at a tame prime.
|
|
1648
|
+
|
|
1649
|
+
The output is only nontrivial when `t` has nonzero `p`-adic valuation.
|
|
1650
|
+
The algorithm is described in Section 11.4.1 of [Watkins]_.
|
|
1651
|
+
|
|
1652
|
+
INPUT:
|
|
1653
|
+
|
|
1654
|
+
- ``t`` -- rational number, not 0 or 1
|
|
1655
|
+
|
|
1656
|
+
- ``p`` -- prime number of good reduction
|
|
1657
|
+
|
|
1658
|
+
- ``mo`` -- integer
|
|
1659
|
+
|
|
1660
|
+
- ``deg`` -- integer (optional)
|
|
1661
|
+
|
|
1662
|
+
OUTPUT: a polynomial
|
|
1663
|
+
|
|
1664
|
+
If ``deg`` is specified, the output is truncated to that degree (inclusive).
|
|
1665
|
+
|
|
1666
|
+
EXAMPLES::
|
|
1667
|
+
|
|
1668
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1669
|
+
sage: H = Hyp(cyclotomic=[[3,7], [4,5,6]])
|
|
1670
|
+
sage: H.euler_factor_tame_contribution(11^2, 11, 4)
|
|
1671
|
+
1
|
|
1672
|
+
sage: H.euler_factor_tame_contribution(11^20, 11, 4)
|
|
1673
|
+
1331*T^2 + 1
|
|
1674
|
+
sage: H.euler_factor_tame_contribution(11^20, 11, 4, deg=1)
|
|
1675
|
+
1
|
|
1676
|
+
sage: H.euler_factor_tame_contribution(11^20, 11, 5)
|
|
1677
|
+
1771561*T^4 + 161051*T^3 + 6171*T^2 + 121*T + 1
|
|
1678
|
+
sage: H.euler_factor_tame_contribution(11^20, 11, 5, deg=3)
|
|
1679
|
+
161051*T^3 + 6171*T^2 + 121*T + 1
|
|
1680
|
+
sage: H.euler_factor_tame_contribution(11^20, 11, 6)
|
|
1681
|
+
1
|
|
1682
|
+
"""
|
|
1683
|
+
t = QQ(t)
|
|
1684
|
+
if t in [0, 1]:
|
|
1685
|
+
raise ValueError('invalid t')
|
|
1686
|
+
if not is_prime(p):
|
|
1687
|
+
raise ValueError('p not prime')
|
|
1688
|
+
if not all(x.denominator() % p for x in self._alpha + self._beta):
|
|
1689
|
+
raise NotImplementedError('p is wild')
|
|
1690
|
+
|
|
1691
|
+
e = t.valuation(p)
|
|
1692
|
+
t0 = t / p**e
|
|
1693
|
+
if e > 0:
|
|
1694
|
+
mul = self.cyclotomic_data()[1].count(mo)
|
|
1695
|
+
elif e < 0:
|
|
1696
|
+
mul = self.cyclotomic_data()[0].count(mo)
|
|
1697
|
+
else:
|
|
1698
|
+
mul = None
|
|
1699
|
+
if e % mo or not mul:
|
|
1700
|
+
return ZZ.one()
|
|
1701
|
+
d = euler_phi(mo)
|
|
1702
|
+
f = IntegerModRing(mo)(p).multiplicative_order()
|
|
1703
|
+
if deg is None:
|
|
1704
|
+
deg = d
|
|
1705
|
+
if deg < f:
|
|
1706
|
+
return ZZ.one()
|
|
1707
|
+
q = p ** f
|
|
1708
|
+
prec = ceil(deg*(self.weight()+1-mul)/2 + log(2*d + 1, p))
|
|
1709
|
+
k = (q-1) // mo
|
|
1710
|
+
flip = (f == 1 and prec == 1)
|
|
1711
|
+
gtab_prec, gtab = self.gauss_table(p, f, prec)
|
|
1712
|
+
try:
|
|
1713
|
+
p_ring = gtab[0].parent()
|
|
1714
|
+
except AttributeError:
|
|
1715
|
+
p_ring = Zp(p, prec, 'fixed-mod')
|
|
1716
|
+
M = self.M_value()
|
|
1717
|
+
teich = p_ring.teichmuller(M / t0)
|
|
1718
|
+
m = {r: self._beta.count(QQ((r, q - 1))) for r in range(q - 1)}
|
|
1719
|
+
D = -min(self.zigzag(x, flip_beta=True) for x in self._alpha + self._beta)
|
|
1720
|
+
gamma = self.gamma_array()
|
|
1721
|
+
l = []
|
|
1722
|
+
for j in range(mo):
|
|
1723
|
+
if gcd(j, mo) == 1:
|
|
1724
|
+
r = j * k
|
|
1725
|
+
term = teich**r * ZZ(-1)**m[0]
|
|
1726
|
+
ct = 0
|
|
1727
|
+
for v, gv in gamma.items():
|
|
1728
|
+
r1 = v * r % (q-1)
|
|
1729
|
+
ct += gv * sum(r1.digits(p))
|
|
1730
|
+
term *= p_ring(gtab[r1]) ** (-gv if flip else gv)
|
|
1731
|
+
ct //= p - 1
|
|
1732
|
+
term *= ZZ(-1) ** ct
|
|
1733
|
+
ct += f * (D + m[0] - m[r])
|
|
1734
|
+
l.append(term * p**ct)
|
|
1735
|
+
traces = [0 if j % f else sum(i ** (j//f) for i in l) for j in range(1,d+1)]
|
|
1736
|
+
R = IntegerModRing(p**prec)
|
|
1737
|
+
traces = [R(i).lift_centered() for i in traces]
|
|
1738
|
+
return characteristic_polynomial_from_traces(traces, d, p, 0, 1, deg, use_fe=False)
|
|
1739
|
+
|
|
1740
|
+
@cached_method
|
|
1741
|
+
def euler_factor(self, t, p, deg=None, cache_p=False):
|
|
1742
|
+
"""
|
|
1743
|
+
Return the Euler factor of the motive `H_t` at prime `p`.
|
|
1744
|
+
|
|
1745
|
+
INPUT:
|
|
1746
|
+
|
|
1747
|
+
- ``t`` -- rational number, not 0
|
|
1748
|
+
|
|
1749
|
+
- ``p`` -- prime number of good reduction
|
|
1750
|
+
|
|
1751
|
+
- ``deg`` -- integer or ``None``
|
|
1752
|
+
|
|
1753
|
+
OUTPUT: a polynomial
|
|
1754
|
+
|
|
1755
|
+
See [Benasque2009]_ for explicit examples of Euler factors.
|
|
1756
|
+
|
|
1757
|
+
For odd weight, the sign of the functional equation is +1. For even
|
|
1758
|
+
weight, the sign is computed by a recipe found in Section 11.1 of [Watkins]_.
|
|
1759
|
+
|
|
1760
|
+
If ``deg`` is specified, then the polynomial is only computed up to degree
|
|
1761
|
+
``deg`` (inclusive).
|
|
1762
|
+
|
|
1763
|
+
The prime `p` may be tame, but not wild. When `v_p(t-1)` is nonzero and even,
|
|
1764
|
+
the Euler factor includes a linear term described in Section 11.2 of [Watkins]_.
|
|
1765
|
+
|
|
1766
|
+
EXAMPLES::
|
|
1767
|
+
|
|
1768
|
+
sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
|
|
1769
|
+
sage: H = Hyp(alpha_beta=([1/2]*4, [0]*4))
|
|
1770
|
+
sage: H.euler_factor(-1, 5)
|
|
1771
|
+
15625*T^4 + 500*T^3 - 130*T^2 + 4*T + 1
|
|
1772
|
+
|
|
1773
|
+
sage: H = Hyp(gamma_list=[-6,-1,4,3])
|
|
1774
|
+
sage: H.weight(), H.degree()
|
|
1775
|
+
(1, 2)
|
|
1776
|
+
sage: t = 189/125
|
|
1777
|
+
sage: [H.euler_factor(1/t,p) for p in [11,13,17,19,23,29]]
|
|
1778
|
+
[11*T^2 + 4*T + 1,
|
|
1779
|
+
13*T^2 + 1,
|
|
1780
|
+
17*T^2 + 1,
|
|
1781
|
+
19*T^2 + 1,
|
|
1782
|
+
23*T^2 + 8*T + 1,
|
|
1783
|
+
29*T^2 + 2*T + 1]
|
|
1784
|
+
|
|
1785
|
+
sage: H = Hyp(cyclotomic=([6,2], [1,1,1]))
|
|
1786
|
+
sage: H.weight(), H.degree()
|
|
1787
|
+
(2, 3)
|
|
1788
|
+
sage: [H.euler_factor(1/4,p) for p in [5,7,11,13,17,19]]
|
|
1789
|
+
[125*T^3 + 20*T^2 + 4*T + 1,
|
|
1790
|
+
343*T^3 - 42*T^2 - 6*T + 1,
|
|
1791
|
+
-1331*T^3 - 22*T^2 + 2*T + 1,
|
|
1792
|
+
-2197*T^3 - 156*T^2 + 12*T + 1,
|
|
1793
|
+
4913*T^3 + 323*T^2 + 19*T + 1,
|
|
1794
|
+
6859*T^3 - 57*T^2 - 3*T + 1]
|
|
1795
|
+
|
|
1796
|
+
sage: H = Hyp(alpha_beta=([1/12,5/12,7/12,11/12], [0,1/2,1/2,1/2]))
|
|
1797
|
+
sage: H.weight(), H.degree()
|
|
1798
|
+
(2, 4)
|
|
1799
|
+
sage: t = -5
|
|
1800
|
+
sage: [H.euler_factor(1/t,p) for p in [11,13,17,19,23,29]]
|
|
1801
|
+
[-14641*T^4 - 1210*T^3 + 10*T + 1,
|
|
1802
|
+
-28561*T^4 - 2704*T^3 + 16*T + 1,
|
|
1803
|
+
-83521*T^4 - 4046*T^3 + 14*T + 1,
|
|
1804
|
+
130321*T^4 + 14440*T^3 + 969*T^2 + 40*T + 1,
|
|
1805
|
+
279841*T^4 - 25392*T^3 + 1242*T^2 - 48*T + 1,
|
|
1806
|
+
707281*T^4 - 7569*T^3 + 696*T^2 - 9*T + 1]
|
|
1807
|
+
|
|
1808
|
+
This is an example of higher degree::
|
|
1809
|
+
|
|
1810
|
+
sage: H = Hyp(cyclotomic=([11], [7, 12]))
|
|
1811
|
+
sage: H.euler_factor(2, 13)
|
|
1812
|
+
371293*T^10 - 85683*T^9 + 26364*T^8 + 1352*T^7 - 65*T^6 + 394*T^5 - 5*T^4 + 8*T^3 + 12*T^2 - 3*T + 1
|
|
1813
|
+
sage: H.euler_factor(2, 13, deg=4)
|
|
1814
|
+
-5*T^4 + 8*T^3 + 12*T^2 - 3*T + 1
|
|
1815
|
+
sage: H.euler_factor(2, 19) # long time
|
|
1816
|
+
2476099*T^10 - 651605*T^9 + 233206*T^8 - 77254*T^7 + 20349*T^6 - 4611*T^5 + 1071*T^4 - 214*T^3 + 34*T^2 - 5*T + 1
|
|
1817
|
+
|
|
1818
|
+
This is an example of tame primes::
|
|
1819
|
+
|
|
1820
|
+
sage: H = Hyp(cyclotomic=[[4,2,2], [3,1,1]])
|
|
1821
|
+
sage: H.euler_factor(8, 7)
|
|
1822
|
+
-7*T^3 + 7*T^2 - T + 1
|
|
1823
|
+
sage: H.euler_factor(50, 7)
|
|
1824
|
+
-7*T^3 + 7*T^2 - T + 1
|
|
1825
|
+
sage: H.euler_factor(7, 7)
|
|
1826
|
+
-T + 1
|
|
1827
|
+
sage: H.euler_factor(1/7^2, 7)
|
|
1828
|
+
T + 1
|
|
1829
|
+
sage: H.euler_factor(1/7^4, 7)
|
|
1830
|
+
7*T^3 + 7*T^2 + T + 1
|
|
1831
|
+
|
|
1832
|
+
This is an example with `t = 1`::
|
|
1833
|
+
|
|
1834
|
+
sage: H = Hyp(cyclotomic=[[4,2], [3,1]])
|
|
1835
|
+
sage: H.euler_factor(1, 7)
|
|
1836
|
+
-T^2 + 1
|
|
1837
|
+
sage: H = Hyp(cyclotomic=[[5], [1,1,1,1]])
|
|
1838
|
+
sage: H.euler_factor(1, 7)
|
|
1839
|
+
343*T^2 - 6*T + 1
|
|
1840
|
+
|
|
1841
|
+
TESTS::
|
|
1842
|
+
|
|
1843
|
+
sage: H1 = Hyp(alpha_beta=([1,1,1], [1/2,1/2,1/2]))
|
|
1844
|
+
sage: H2 = H1.swap_alpha_beta()
|
|
1845
|
+
sage: H1.euler_factor(-1, 3)
|
|
1846
|
+
27*T^3 + 3*T^2 + T + 1
|
|
1847
|
+
sage: H2.euler_factor(-1, 3)
|
|
1848
|
+
27*T^3 + 3*T^2 + T + 1
|
|
1849
|
+
sage: H = Hyp(alpha_beta=([0,0,0,1/3,2/3], [1/2,1/5,2/5,3/5,4/5]))
|
|
1850
|
+
sage: H.euler_factor(5,7)
|
|
1851
|
+
16807*T^5 - 686*T^4 - 105*T^3 - 15*T^2 - 2*T + 1
|
|
1852
|
+
|
|
1853
|
+
Check for precision downsampling::
|
|
1854
|
+
|
|
1855
|
+
sage: H = Hyp(cyclotomic=[[3], [4]])
|
|
1856
|
+
sage: H.euler_factor(2, 11, cache_p=True)
|
|
1857
|
+
11*T^2 - 3*T + 1
|
|
1858
|
+
sage: H = Hyp(cyclotomic=[[12], [1,2,6]])
|
|
1859
|
+
sage: H.euler_factor(2, 11, cache_p=True)
|
|
1860
|
+
-T^4 + T^3 - T + 1
|
|
1861
|
+
|
|
1862
|
+
Check issue from :issue:`29778`::
|
|
1863
|
+
|
|
1864
|
+
sage: H = Hyp(cyclotomic=[[5,5], [4,7]])
|
|
1865
|
+
sage: try:
|
|
1866
|
+
....: print(H.euler_factor(2, 373))
|
|
1867
|
+
....: except ValueError as s:
|
|
1868
|
+
....: print(s)
|
|
1869
|
+
p^f cannot exceed 2^31
|
|
1870
|
+
|
|
1871
|
+
Check handling of some tame cases::
|
|
1872
|
+
|
|
1873
|
+
sage: H = Hyp(cyclotomic=[[4,2,2,2], [3,1,1,1]])
|
|
1874
|
+
sage: H.euler_factor(8, 7)
|
|
1875
|
+
2401*T^4 - 392*T^3 + 46*T^2 - 8*T + 1
|
|
1876
|
+
sage: H.euler_factor(50, 7)
|
|
1877
|
+
16807*T^5 - 343*T^4 - 70*T^3 - 10*T^2 - T + 1
|
|
1878
|
+
sage: H = Hyp(cyclotomic=[[3,7], [4,5,6]])
|
|
1879
|
+
sage: H.euler_factor(11, 11)
|
|
1880
|
+
1
|
|
1881
|
+
sage: H.euler_factor(11**4, 11)
|
|
1882
|
+
1331*T^2 + 1
|
|
1883
|
+
sage: H.euler_factor(11**5, 11)
|
|
1884
|
+
1771561*T^4 + 161051*T^3 + 6171*T^2 + 121*T + 1
|
|
1885
|
+
sage: H.euler_factor(11**5, 11, deg=3)
|
|
1886
|
+
161051*T^3 + 6171*T^2 + 121*T + 1
|
|
1887
|
+
sage: H.euler_factor(11**-3, 11)
|
|
1888
|
+
1331*T^2 + 1
|
|
1889
|
+
sage: H.euler_factor(11**-7, 11)
|
|
1890
|
+
2357947691*T^6 - 58564*T^3 + 1
|
|
1891
|
+
sage: H = Hyp(cyclotomic=[[7], [5,1,1]])
|
|
1892
|
+
sage: H.euler_factor(2, 2)
|
|
1893
|
+
-T + 1
|
|
1894
|
+
sage: H.euler_factor(2^-7, 2)
|
|
1895
|
+
8*T^6 - 2*T^3 + 1
|
|
1896
|
+
sage: H.euler_factor(3, 2)
|
|
1897
|
+
4*T^5 + 4*T^4 + 2*T^3 + 2*T^2 + T + 1
|
|
1898
|
+
|
|
1899
|
+
More examples of tame primes from [Watkins]_::
|
|
1900
|
+
|
|
1901
|
+
sage: H = Hyp(cyclotomic=[[3,12], [6,6,1,1]])
|
|
1902
|
+
sage: H.euler_factor(1/8, 7).factor()
|
|
1903
|
+
(-1) * (7*T - 1) * (117649*T^4 + 2744*T^3 + 105*T^2 + 8*T + 1)
|
|
1904
|
+
sage: H.euler_factor(1/12, 11).factor()
|
|
1905
|
+
(11*T + 1) * (1771561*T^4 - 18634*T^3 + 22*T^2 - 14*T + 1)
|
|
1906
|
+
sage: H = Hyp(cyclotomic=[[4,4,4],[6,2,1,1,1]])
|
|
1907
|
+
sage: H.euler_factor(1/8, 7).factor()
|
|
1908
|
+
(49*T + 1) * (5764801*T^4 - 86436*T^3 + 2758*T^2 - 36*T + 1)
|
|
1909
|
+
sage: H.euler_factor(1/12, 11).factor()
|
|
1910
|
+
(-1) * (121*T - 1) * (214358881*T^4 - 527076*T^3 + 12694*T^2 - 36*T + 1)
|
|
1911
|
+
sage: H = Hyp(cyclotomic=[[10,4,2], [18,1]])
|
|
1912
|
+
sage: H.euler_factor(1/14, 13)
|
|
1913
|
+
-4826809*T^6 + 114244*T^5 + 2197*T^4 - 13*T^2 - 4*T + 1
|
|
1914
|
+
|
|
1915
|
+
Check error handling for wild primes::
|
|
1916
|
+
|
|
1917
|
+
sage: H = Hyp(cyclotomic=[[5,5], [4,7]])
|
|
1918
|
+
sage: try:
|
|
1919
|
+
....: print(H.euler_factor(2, 5))
|
|
1920
|
+
....: except NotImplementedError as s:
|
|
1921
|
+
....: print(s)
|
|
1922
|
+
p is wild
|
|
1923
|
+
|
|
1924
|
+
REFERENCES:
|
|
1925
|
+
|
|
1926
|
+
- [Roberts2015]_
|
|
1927
|
+
- [Watkins]_
|
|
1928
|
+
"""
|
|
1929
|
+
t = QQ(t)
|
|
1930
|
+
if t == 0:
|
|
1931
|
+
raise ValueError('invalid t')
|
|
1932
|
+
if not is_prime(p):
|
|
1933
|
+
raise ValueError('p not prime')
|
|
1934
|
+
if not all(x.denominator() % p for x in self._alpha + self._beta):
|
|
1935
|
+
raise NotImplementedError('p is wild')
|
|
1936
|
+
if 0 in self._alpha:
|
|
1937
|
+
return self._swap.euler_factor(~t, p)
|
|
1938
|
+
P = PolynomialRing(ZZ, 'T')
|
|
1939
|
+
if t.numerator() % p == 0 or t.denominator() % p == 0:
|
|
1940
|
+
ans = P.one()
|
|
1941
|
+
for m in {j for i in self.cyclotomic_data() for j in i}:
|
|
1942
|
+
ans *= self.euler_factor_tame_contribution(t, p, m, deg)
|
|
1943
|
+
if deg is not None:
|
|
1944
|
+
ans = ans.truncate(deg + 1)
|
|
1945
|
+
return ans
|
|
1946
|
+
# now p is good, or p is tame and t is a p-adic unit
|
|
1947
|
+
elif (t - 1) % p == 0:
|
|
1948
|
+
typ = "mult"
|
|
1949
|
+
d = self.degree() - 1
|
|
1950
|
+
if d % 2:
|
|
1951
|
+
d -= 1
|
|
1952
|
+
else:
|
|
1953
|
+
typ = "good"
|
|
1954
|
+
d = self.degree()
|
|
1955
|
+
bound = d // 2
|
|
1956
|
+
if deg is not None:
|
|
1957
|
+
bound = min(deg, bound)
|
|
1958
|
+
|
|
1959
|
+
if p ** bound > 2 ** 31:
|
|
1960
|
+
raise ValueError("p^f cannot exceed 2^31")
|
|
1961
|
+
|
|
1962
|
+
traces = [self.padic_H_value(p, i + 1, t, cache_p=cache_p)
|
|
1963
|
+
for i in range(bound)]
|
|
1964
|
+
|
|
1965
|
+
w = self.weight()
|
|
1966
|
+
m1 = self.cyclotomic_data()[1].count(1)
|
|
1967
|
+
|
|
1968
|
+
# In the multiplicative case, we sometimes need to pull out a linear factor
|
|
1969
|
+
# in order to apply the functional equation.
|
|
1970
|
+
if typ == "mult":
|
|
1971
|
+
if self.degree() % 2 == 0:
|
|
1972
|
+
sign = 1
|
|
1973
|
+
if w % 2:
|
|
1974
|
+
assert m1 % 2 == 0
|
|
1975
|
+
u = (-1) ** (m1//2)
|
|
1976
|
+
u *= prod(v ** gv for v, gv in self.gamma_array().items())
|
|
1977
|
+
c = kronecker_symbol(u, p) * p**((w-1)//2)
|
|
1978
|
+
else:
|
|
1979
|
+
u = (-1) ** (1 + self.degree()//2 + (m1-1)//2)
|
|
1980
|
+
num, den = self.defining_polynomials()
|
|
1981
|
+
x = num.parent().gen()
|
|
1982
|
+
num = num(-x)
|
|
1983
|
+
num /= (x-1) ** num.valuation(x-1)
|
|
1984
|
+
den /= (x-1) ** den.valuation(x-1)
|
|
1985
|
+
u *= 2 * num(1) / den(1)
|
|
1986
|
+
c = kronecker_symbol(u, p) * p**(w//2)
|
|
1987
|
+
cpow = c
|
|
1988
|
+
for j in range(len(traces)):
|
|
1989
|
+
traces[j] -= cpow
|
|
1990
|
+
cpow *= c
|
|
1991
|
+
tmp = 1 - c*P.gen()
|
|
1992
|
+
else:
|
|
1993
|
+
u = (-1) ** (1+(self.degree()-1)//2)
|
|
1994
|
+
num, den = self.defining_polynomials()
|
|
1995
|
+
x = num.parent().gen()
|
|
1996
|
+
den = den(-x)
|
|
1997
|
+
num /= (x-1) ** num.valuation(x-1)
|
|
1998
|
+
den /= (x-1) ** den.valuation(x-1)
|
|
1999
|
+
u *= num(1) / den(1)
|
|
2000
|
+
sign = kronecker_symbol(u, p)
|
|
2001
|
+
else:
|
|
2002
|
+
sign = self.sign(t, p)
|
|
2003
|
+
|
|
2004
|
+
ans = characteristic_polynomial_from_traces(traces, d, p, w, sign, deg=deg)
|
|
2005
|
+
|
|
2006
|
+
# In the multiplicative case, we sometimes need to add extra factors.
|
|
2007
|
+
if typ == "mult" and t != 1:
|
|
2008
|
+
if self.degree() % 2 == 0:
|
|
2009
|
+
ans *= tmp
|
|
2010
|
+
if w % 2 == 0 and (t-1).valuation(p) % 2 == 0:
|
|
2011
|
+
K = (-1) ** ((m1-1)//2)*2*prod(abs(x) for x in self.gamma_list())
|
|
2012
|
+
t0 = (~t-1) / p**((t-1).valuation(p))
|
|
2013
|
+
c = kronecker_symbol(K*t0, p) * p**(w//2)
|
|
2014
|
+
ans *= 1 - c*P.gen()
|
|
2015
|
+
if deg is not None:
|
|
2016
|
+
ans = ans.truncate(deg + 1)
|
|
2017
|
+
return ans
|