passagemath-schemes 10.6.47__cp312-cp312-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
- passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
- passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
- passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
- passagemath_schemes/__init__.py +3 -0
- passagemath_schemes-10.6.47.dist-info/METADATA +204 -0
- passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
- passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
- passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
- passagemath_schemes-10.6.47.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-312-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-312-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-312-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-312-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-312-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-312-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-312-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-312-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_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-312-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-312-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-312-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,1816 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# sage.doctest: needs sage.rings.padics
|
|
3
|
+
#
|
|
4
|
+
# All these methods are imported in EllipticCurve_rational_field,
|
|
5
|
+
# so there is no reason to add this module to the documentation.
|
|
6
|
+
r"""
|
|
7
|
+
Miscellaneous `p`-adic methods
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
######################################################################
|
|
11
|
+
# Copyright (C) 2007 William Stein <wstein@gmail.com>
|
|
12
|
+
#
|
|
13
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
14
|
+
#
|
|
15
|
+
# This code is distributed in the hope that it will be useful,
|
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
18
|
+
# General Public License for more details.
|
|
19
|
+
#
|
|
20
|
+
# The full text of the GPL is available at:
|
|
21
|
+
#
|
|
22
|
+
# https://www.gnu.org/licenses/
|
|
23
|
+
######################################################################
|
|
24
|
+
|
|
25
|
+
import math
|
|
26
|
+
|
|
27
|
+
from sage.arith.functions import lcm as LCM
|
|
28
|
+
from sage.arith.misc import valuation
|
|
29
|
+
from sage.matrix.constructor import Matrix as matrix
|
|
30
|
+
from sage.misc.cachefunc import cached_method
|
|
31
|
+
from sage.misc.lazy_import import lazy_import
|
|
32
|
+
from sage.rings.big_oh import O
|
|
33
|
+
from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
|
|
34
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing as Integers
|
|
35
|
+
from sage.rings.integer import Integer
|
|
36
|
+
from sage.rings.laurent_series_ring import LaurentSeriesRing
|
|
37
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
38
|
+
from sage.rings.power_series_ring import PowerSeriesRing
|
|
39
|
+
from sage.rings.rational_field import RationalField
|
|
40
|
+
|
|
41
|
+
lazy_import('sage.rings.padics.factory', ['Qp', 'Zp'])
|
|
42
|
+
lazy_import('sage.schemes.hyperelliptic_curves.hypellfrob', 'hypellfrob')
|
|
43
|
+
lazy_import('sage.schemes.hyperelliptic_curves.monsky_washnitzer',
|
|
44
|
+
['adjusted_prec', 'matrix_of_frobenius'],
|
|
45
|
+
as_=['mw_adjusted_prec', 'mw_matrix_of_frobenius'])
|
|
46
|
+
|
|
47
|
+
from . import padic_lseries as plseries
|
|
48
|
+
|
|
49
|
+
sqrt = math.sqrt
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def __check_padic_hypotheses(self, p):
|
|
53
|
+
r"""
|
|
54
|
+
Helper function that determines if `p`
|
|
55
|
+
is an odd prime of good ordinary reduction.
|
|
56
|
+
|
|
57
|
+
EXAMPLES::
|
|
58
|
+
|
|
59
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
60
|
+
sage: E = EllipticCurve('11a1')
|
|
61
|
+
sage: from sage.schemes.elliptic_curves.padics import __check_padic_hypotheses
|
|
62
|
+
sage: __check_padic_hypotheses(E,5)
|
|
63
|
+
5
|
|
64
|
+
sage: __check_padic_hypotheses(E,29)
|
|
65
|
+
Traceback (most recent call last):
|
|
66
|
+
...
|
|
67
|
+
ArithmeticError: p must be a good ordinary prime
|
|
68
|
+
"""
|
|
69
|
+
p = Integer(p)
|
|
70
|
+
if not p.is_prime():
|
|
71
|
+
raise ValueError("p = (%s) must be prime" % p)
|
|
72
|
+
if p == 2:
|
|
73
|
+
raise ValueError("p must be odd")
|
|
74
|
+
if self.conductor() % p == 0 or self.ap(p) % p == 0:
|
|
75
|
+
raise ArithmeticError("p must be a good ordinary prime")
|
|
76
|
+
return p
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _normalize_padic_lseries(self, p, normalize, implementation, precision):
|
|
80
|
+
r"""
|
|
81
|
+
Normalize parameters for :meth:`padic_lseries`.
|
|
82
|
+
|
|
83
|
+
TESTS::
|
|
84
|
+
|
|
85
|
+
sage: from sage.schemes.elliptic_curves.padics import _normalize_padic_lseries
|
|
86
|
+
sage: u = _normalize_padic_lseries(None, 5, None, 'sage', 10)
|
|
87
|
+
sage: v = _normalize_padic_lseries(None, 5, "L_ratio", 'sage', 10)
|
|
88
|
+
sage: u == v
|
|
89
|
+
True
|
|
90
|
+
"""
|
|
91
|
+
if implementation == 'eclib':
|
|
92
|
+
if normalize is None:
|
|
93
|
+
normalize = "L_ratio"
|
|
94
|
+
elif implementation == 'sage':
|
|
95
|
+
if normalize is None:
|
|
96
|
+
normalize = "L_ratio"
|
|
97
|
+
elif implementation == 'pollackstevens':
|
|
98
|
+
if precision is None:
|
|
99
|
+
raise ValueError("Must specify precision when using 'pollackstevens'")
|
|
100
|
+
if normalize is not None:
|
|
101
|
+
raise ValueError("The 'normalize' parameter is not used for Pollack-Stevens' overconvergent modular symbols")
|
|
102
|
+
elif implementation == "num":
|
|
103
|
+
if normalize is not None:
|
|
104
|
+
raise ValueError("The 'normalize' parameter is not used for numerical modular symbols")
|
|
105
|
+
else:
|
|
106
|
+
raise ValueError("Implementation should be one of 'sage', 'eclib', 'num' or 'pollackstevens'")
|
|
107
|
+
return (p, normalize, implementation, precision)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@cached_method(key=_normalize_padic_lseries)
|
|
111
|
+
def padic_lseries(self, p, normalize=None, implementation='eclib',
|
|
112
|
+
precision=None):
|
|
113
|
+
r"""
|
|
114
|
+
Return the `p`-adic `L`-series of ``self`` at
|
|
115
|
+
`p`, which is an object whose approx method computes
|
|
116
|
+
approximation to the true `p`-adic `L`-series to
|
|
117
|
+
any desired precision.
|
|
118
|
+
|
|
119
|
+
INPUT:
|
|
120
|
+
|
|
121
|
+
- ``p`` -- prime
|
|
122
|
+
|
|
123
|
+
- ``normalize`` -- 'L_ratio' (default), 'period' or 'none';
|
|
124
|
+
this is describes the way the modular symbols
|
|
125
|
+
are normalized. See modular_symbol for
|
|
126
|
+
more details.
|
|
127
|
+
|
|
128
|
+
- ``implementation`` -- 'eclib' (default), 'sage', 'num' or 'pollackstevens';
|
|
129
|
+
Whether to use John Cremona's eclib, the Sage implementation,
|
|
130
|
+
numerical modular symbols
|
|
131
|
+
or Pollack-Stevens' implementation of overconvergent
|
|
132
|
+
modular symbols.
|
|
133
|
+
|
|
134
|
+
EXAMPLES::
|
|
135
|
+
|
|
136
|
+
sage: # needs database_cremona_mini_ellcurve eclib
|
|
137
|
+
sage: E = EllipticCurve('37a')
|
|
138
|
+
sage: L = E.padic_lseries(5); L
|
|
139
|
+
5-adic L-series of Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
|
|
140
|
+
sage: type(L)
|
|
141
|
+
<class 'sage.schemes.elliptic_curves.padic_lseries.pAdicLseriesOrdinary'>
|
|
142
|
+
|
|
143
|
+
We compute the `3`-adic `L`-series of two curves of
|
|
144
|
+
rank `0` and in each case verify the interpolation property
|
|
145
|
+
for their leading coefficient (i.e., value at 0)::
|
|
146
|
+
|
|
147
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
148
|
+
sage: e = EllipticCurve('11a')
|
|
149
|
+
sage: ms = e.modular_symbol()
|
|
150
|
+
sage: [ms(1/11), ms(1/3), ms(0), ms(oo)]
|
|
151
|
+
[0, -3/10, 1/5, 0]
|
|
152
|
+
sage: ms(0)
|
|
153
|
+
1/5
|
|
154
|
+
sage: L = e.padic_lseries(3)
|
|
155
|
+
sage: P = L.series(5)
|
|
156
|
+
sage: P(0)
|
|
157
|
+
2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7)
|
|
158
|
+
sage: alpha = L.alpha(9); alpha
|
|
159
|
+
2 + 3^2 + 2*3^3 + 2*3^4 + 2*3^6 + 3^8 + O(3^9)
|
|
160
|
+
sage: R.<x> = QQ[]
|
|
161
|
+
sage: f = x^2 - e.ap(3)*x + 3
|
|
162
|
+
sage: f(alpha)
|
|
163
|
+
O(3^9)
|
|
164
|
+
sage: r = e.lseries().L_ratio(); r # needs sage.graphs
|
|
165
|
+
1/5
|
|
166
|
+
sage: (1 - alpha^(-1))^2 * r # needs sage.graphs
|
|
167
|
+
2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + 3^7 + O(3^9)
|
|
168
|
+
sage: P(0)
|
|
169
|
+
2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7)
|
|
170
|
+
|
|
171
|
+
Next consider the curve 37b::
|
|
172
|
+
|
|
173
|
+
sage: # needs database_cremona_mini_ellcurve sage.graphs
|
|
174
|
+
sage: e = EllipticCurve('37b')
|
|
175
|
+
sage: L = e.padic_lseries(3)
|
|
176
|
+
sage: P = L.series(5)
|
|
177
|
+
sage: alpha = L.alpha(9); alpha
|
|
178
|
+
1 + 2*3 + 3^2 + 2*3^5 + 2*3^7 + 3^8 + O(3^9)
|
|
179
|
+
sage: r = e.lseries().L_ratio(); r
|
|
180
|
+
1/3
|
|
181
|
+
sage: (1 - alpha^(-1))^2 * r
|
|
182
|
+
3 + 3^2 + 2*3^4 + 2*3^5 + 2*3^6 + 3^7 + O(3^9)
|
|
183
|
+
sage: P(0)
|
|
184
|
+
3 + 3^2 + 2*3^4 + 2*3^5 + O(3^6)
|
|
185
|
+
|
|
186
|
+
We can use Sage modular symbols instead to compute the `L`-series::
|
|
187
|
+
|
|
188
|
+
sage: # needs database_cremona_mini_ellcurve sage.graphs
|
|
189
|
+
sage: e = EllipticCurve('11a')
|
|
190
|
+
sage: L = e.padic_lseries(3, implementation='sage')
|
|
191
|
+
sage: L.series(5, prec=10)
|
|
192
|
+
2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7) + (1 + 3 + 2*3^2 + 3^3 + O(3^4))*T
|
|
193
|
+
+ (1 + 2*3 + O(3^4))*T^2 + (3 + 2*3^2 + O(3^3))*T^3 + (2*3 + 3^2 + O(3^3))*T^4
|
|
194
|
+
+ (2 + 2*3 + 2*3^2 + O(3^3))*T^5 + (1 + 3^2 + O(3^3))*T^6 + (2 + 3^2 + O(3^3))*T^7
|
|
195
|
+
+ (2 + 2*3 + 2*3^2 + O(3^3))*T^8 + (2 + O(3^2))*T^9 + O(T^10)
|
|
196
|
+
|
|
197
|
+
Also the numerical modular symbols can be used.
|
|
198
|
+
This may allow for much larger conductor in some instances::
|
|
199
|
+
|
|
200
|
+
sage: E = EllipticCurve([101,103])
|
|
201
|
+
sage: L = E.padic_lseries(5, implementation='num')
|
|
202
|
+
sage: L.series(2) # needs sage.graphs
|
|
203
|
+
O(5^4) + (3 + O(5))*T + (1 + O(5))*T^2 + (3 + O(5))*T^3 + O(5)*T^4 + O(T^5)
|
|
204
|
+
|
|
205
|
+
Finally, we can use the overconvergent method of Pollack-Stevens.::
|
|
206
|
+
|
|
207
|
+
sage: # needs database_cremona_mini_ellcurve sage.graphs
|
|
208
|
+
sage: e = EllipticCurve('11a')
|
|
209
|
+
sage: L = e.padic_lseries(3, implementation='pollackstevens', precision=6)
|
|
210
|
+
sage: L.series(5)
|
|
211
|
+
2 + 3 + 3^2 + 2*3^3 + 2*3^5 + O(3^6) + (1 + 3 + 2*3^2 + 3^3 + O(3^4))*T + (1 + 2*3 + O(3^2))*T^2 + (3 + O(3^2))*T^3 + O(3^0)*T^4 + O(T^5)
|
|
212
|
+
sage: L[3]
|
|
213
|
+
3 + O(3^2)
|
|
214
|
+
|
|
215
|
+
Another example with a semistable prime.::
|
|
216
|
+
|
|
217
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
218
|
+
sage: E = EllipticCurve("11a1")
|
|
219
|
+
sage: L = E.padic_lseries(11, implementation='pollackstevens', precision=3)
|
|
220
|
+
sage: L[1]
|
|
221
|
+
10 + 3*11 + O(11^2)
|
|
222
|
+
sage: L[3]
|
|
223
|
+
O(11^0)
|
|
224
|
+
"""
|
|
225
|
+
p, normalize, implementation, precision = self._normalize_padic_lseries(p,
|
|
226
|
+
normalize, implementation, precision)
|
|
227
|
+
|
|
228
|
+
if implementation in ['sage', 'eclib', 'num']:
|
|
229
|
+
if self.ap(p) % p != 0:
|
|
230
|
+
Lp = plseries.pAdicLseriesOrdinary(self, p,
|
|
231
|
+
normalize=normalize, implementation=implementation)
|
|
232
|
+
else:
|
|
233
|
+
Lp = plseries.pAdicLseriesSupersingular(self, p,
|
|
234
|
+
normalize=normalize, implementation=implementation)
|
|
235
|
+
else:
|
|
236
|
+
phi = self.pollack_stevens_modular_symbol(sign=0)
|
|
237
|
+
if phi.parent().level() % p == 0:
|
|
238
|
+
Phi = phi.lift(p, precision, eigensymbol=True)
|
|
239
|
+
else:
|
|
240
|
+
Phi = phi.p_stabilize_and_lift(p, precision, eigensymbol=True)
|
|
241
|
+
Lp = Phi.padic_lseries() #mm TODO should this pass precision on too ?
|
|
242
|
+
Lp._cinf = self.real_components()
|
|
243
|
+
return Lp
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def padic_regulator(self, p, prec=20, height=None, check_hypotheses=True):
|
|
247
|
+
r"""
|
|
248
|
+
Compute the cyclotomic `p`-adic regulator of this curve.
|
|
249
|
+
The model of the curve needs to be integral and minimal at `p`.
|
|
250
|
+
Moreover the reduction at `p` should not be additive.
|
|
251
|
+
|
|
252
|
+
INPUT:
|
|
253
|
+
|
|
254
|
+
- ``p`` -- prime >= 5
|
|
255
|
+
|
|
256
|
+
- ``prec`` -- answer will be returned modulo `p^{\mathrm{prec}}`
|
|
257
|
+
|
|
258
|
+
- ``height`` -- precomputed height function; if not supplied, this function
|
|
259
|
+
will call ``padic_height`` to compute it
|
|
260
|
+
|
|
261
|
+
- ``check_hypotheses`` -- boolean; whether to check
|
|
262
|
+
that this is a curve for which the `p`-adic height makes sense
|
|
263
|
+
|
|
264
|
+
OUTPUT: the `p`-adic cyclotomic regulator of this curve, to the
|
|
265
|
+
requested precision
|
|
266
|
+
|
|
267
|
+
If the rank is 0, we output 1.
|
|
268
|
+
|
|
269
|
+
AUTHORS:
|
|
270
|
+
|
|
271
|
+
- Liang Xiao: original implementation at the 2006 MSRI
|
|
272
|
+
graduate workshop on modular forms
|
|
273
|
+
|
|
274
|
+
- David Harvey (2006-09-13): cleaned up and integrated into Sage,
|
|
275
|
+
removed some redundant height computations
|
|
276
|
+
|
|
277
|
+
- Chris Wuthrich (2007-05-22): added multiplicative and
|
|
278
|
+
supersingular cases
|
|
279
|
+
|
|
280
|
+
- David Harvey (2007-09-20): fixed some precision loss that was
|
|
281
|
+
occurring
|
|
282
|
+
|
|
283
|
+
EXAMPLES::
|
|
284
|
+
|
|
285
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
286
|
+
sage: E = EllipticCurve("37a")
|
|
287
|
+
sage: E.padic_regulator(5, 10)
|
|
288
|
+
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)
|
|
289
|
+
|
|
290
|
+
An anomalous case::
|
|
291
|
+
|
|
292
|
+
sage: E.padic_regulator(53, 10) # needs database_cremona_mini_ellcurve sage.symbolic
|
|
293
|
+
26*53^-1 + 30 + 20*53 + 47*53^2 + 10*53^3 + 32*53^4 + 9*53^5 + 22*53^6 + 35*53^7 + 30*53^8 + O(53^9)
|
|
294
|
+
|
|
295
|
+
An anomalous case where the precision drops some::
|
|
296
|
+
|
|
297
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
298
|
+
sage: E = EllipticCurve("5077a")
|
|
299
|
+
sage: E.padic_regulator(5, 10)
|
|
300
|
+
5 + 5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + 4*5^7 + 2*5^8 + 5^9 + O(5^10)
|
|
301
|
+
|
|
302
|
+
Check that answers agree over a range of precisions::
|
|
303
|
+
|
|
304
|
+
sage: # long time, needs database_cremona_mini_ellcurve sage.symbolic
|
|
305
|
+
sage: max_prec = 30 # make sure we get past p^2
|
|
306
|
+
sage: full = E.padic_regulator(5, max_prec)
|
|
307
|
+
sage: for prec in range(1, max_prec):
|
|
308
|
+
....: assert E.padic_regulator(5, prec) == full
|
|
309
|
+
|
|
310
|
+
A case where the generator belongs to the formal group already
|
|
311
|
+
(:issue:`3632`)::
|
|
312
|
+
|
|
313
|
+
sage: E = EllipticCurve([37,0])
|
|
314
|
+
sage: E.padic_regulator(5,10) # needs sage.symbolic
|
|
315
|
+
2*5^2 + 2*5^3 + 5^4 + 5^5 + 4*5^6 + 3*5^8 + 4*5^9 + O(5^10)
|
|
316
|
+
|
|
317
|
+
The result is not dependent on the model for the curve::
|
|
318
|
+
|
|
319
|
+
sage: E = EllipticCurve([0,0,0,0,2^12*17])
|
|
320
|
+
sage: Em = E.minimal_model()
|
|
321
|
+
sage: E.padic_regulator(7) == Em.padic_regulator(7) # needs sage.symbolic
|
|
322
|
+
True
|
|
323
|
+
|
|
324
|
+
Allow a python int as input::
|
|
325
|
+
|
|
326
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
327
|
+
sage: E = EllipticCurve('37a')
|
|
328
|
+
sage: E.padic_regulator(int(5))
|
|
329
|
+
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + 5^10 + 3*5^11 + 3*5^12 + 5^13 + 4*5^14 + 5^15 + 2*5^16 + 5^17 + 2*5^18 + 4*5^19 + O(5^20)
|
|
330
|
+
"""
|
|
331
|
+
p = Integer(p) # this is assumed in code below
|
|
332
|
+
if check_hypotheses:
|
|
333
|
+
if not p.is_prime():
|
|
334
|
+
raise ValueError("p = (%s) must be prime" % p)
|
|
335
|
+
if p == 2:
|
|
336
|
+
raise ValueError("p must be odd") # todo
|
|
337
|
+
if self.conductor() % (p**2) == 0:
|
|
338
|
+
raise ArithmeticError("p must be a semi-stable prime")
|
|
339
|
+
|
|
340
|
+
if self.conductor() % p == 0:
|
|
341
|
+
Eq = self.tate_curve(p)
|
|
342
|
+
reg = Eq.padic_regulator(prec=prec)
|
|
343
|
+
return reg
|
|
344
|
+
elif self.ap(p) % p == 0:
|
|
345
|
+
lp = self.padic_lseries(p)
|
|
346
|
+
reg = lp.Dp_valued_regulator(prec=prec)
|
|
347
|
+
return reg
|
|
348
|
+
else:
|
|
349
|
+
if self.rank() == 0:
|
|
350
|
+
return Qp(p,prec)(1)
|
|
351
|
+
if height is None:
|
|
352
|
+
height = self.padic_height(p, prec, check_hypotheses=False)
|
|
353
|
+
d = self.padic_height_pairing_matrix(p=p, prec=prec, height=height, check_hypotheses=False)
|
|
354
|
+
return d.determinant()
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def padic_height_pairing_matrix(self, p, prec=20, height=None, check_hypotheses=True):
|
|
358
|
+
r"""
|
|
359
|
+
Compute the cyclotomic `p`-adic height pairing matrix of
|
|
360
|
+
this curve with respect to the basis ``self.gens()`` for the
|
|
361
|
+
Mordell-Weil group for a given odd prime `p` of good ordinary
|
|
362
|
+
reduction.
|
|
363
|
+
The model needs to be integral and minimal at `p`.
|
|
364
|
+
|
|
365
|
+
INPUT:
|
|
366
|
+
|
|
367
|
+
- ``p`` -- prime >= 5
|
|
368
|
+
|
|
369
|
+
- ``prec`` -- answer will be returned modulo `p^{\mathrm{prec}}`
|
|
370
|
+
|
|
371
|
+
- ``height`` -- precomputed height function; if not supplied, this function
|
|
372
|
+
will call ``padic_height`` to compute it
|
|
373
|
+
|
|
374
|
+
- ``check_hypotheses`` -- boolean; whether to check that this is a curve
|
|
375
|
+
for which the `p`-adic height makes sense
|
|
376
|
+
|
|
377
|
+
OUTPUT: the `p`-adic cyclotomic height pairing matrix of this curve
|
|
378
|
+
to the given precision
|
|
379
|
+
|
|
380
|
+
AUTHORS:
|
|
381
|
+
|
|
382
|
+
- David Harvey, Liang Xiao, Robert Bradshaw, Jennifer
|
|
383
|
+
Balakrishnan: original implementation at the 2006 MSRI graduate
|
|
384
|
+
workshop on modular forms
|
|
385
|
+
|
|
386
|
+
- David Harvey (2006-09-13): cleaned up and integrated into Sage,
|
|
387
|
+
removed some redundant height computations
|
|
388
|
+
|
|
389
|
+
EXAMPLES::
|
|
390
|
+
|
|
391
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
392
|
+
sage: E = EllipticCurve("37a")
|
|
393
|
+
sage: E.padic_height_pairing_matrix(5, 10)
|
|
394
|
+
[5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)]
|
|
395
|
+
|
|
396
|
+
A rank two example::
|
|
397
|
+
|
|
398
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
399
|
+
sage: e = EllipticCurve('389a')
|
|
400
|
+
sage: e._set_gens([e(-1, 1), e(1,0)]) # avoid platform dependent gens
|
|
401
|
+
sage: e.padic_height_pairing_matrix(5,10)
|
|
402
|
+
[ 3*5 + 2*5^2 + 5^4 + 5^5 + 5^7 + 4*5^9 + O(5^10) 5 + 4*5^2 + 5^3 + 2*5^4 + 3*5^5 + 4*5^6 + 5^7 + 5^8 + 2*5^9 + O(5^10)]
|
|
403
|
+
[5 + 4*5^2 + 5^3 + 2*5^4 + 3*5^5 + 4*5^6 + 5^7 + 5^8 + 2*5^9 + O(5^10) 4*5 + 2*5^4 + 3*5^6 + 4*5^7 + 4*5^8 + O(5^10)]
|
|
404
|
+
|
|
405
|
+
An anomalous rank 3 example::
|
|
406
|
+
|
|
407
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
408
|
+
sage: e = EllipticCurve("5077a")
|
|
409
|
+
sage: e._set_gens([e(-1,3), e(2,0), e(4,6)])
|
|
410
|
+
sage: e.padic_height_pairing_matrix(5,4)
|
|
411
|
+
[4 + 3*5 + 4*5^2 + 4*5^3 + O(5^4) 4 + 4*5^2 + 2*5^3 + O(5^4) 3*5 + 4*5^2 + 5^3 + O(5^4)]
|
|
412
|
+
[ 4 + 4*5^2 + 2*5^3 + O(5^4) 3 + 4*5 + 3*5^2 + 5^3 + O(5^4) 2 + 4*5 + O(5^4)]
|
|
413
|
+
[ 3*5 + 4*5^2 + 5^3 + O(5^4) 2 + 4*5 + O(5^4) 1 + 3*5 + 5^2 + 5^3 + O(5^4)]
|
|
414
|
+
"""
|
|
415
|
+
if check_hypotheses:
|
|
416
|
+
p = __check_padic_hypotheses(self, p)
|
|
417
|
+
|
|
418
|
+
K = Qp(p, prec=prec)
|
|
419
|
+
|
|
420
|
+
rank = self.rank()
|
|
421
|
+
M = matrix(K, rank, rank, 0)
|
|
422
|
+
if rank == 0:
|
|
423
|
+
return M
|
|
424
|
+
|
|
425
|
+
basis = self.gens()
|
|
426
|
+
|
|
427
|
+
if height is None:
|
|
428
|
+
height = self.padic_height(p, prec, check_hypotheses=False)
|
|
429
|
+
|
|
430
|
+
# Use <P, Q> =1/2*( h(P + Q) - h(P) - h(Q) )
|
|
431
|
+
|
|
432
|
+
for i in range(rank):
|
|
433
|
+
M[i,i] = height(basis[i])
|
|
434
|
+
for i in range(rank):
|
|
435
|
+
for j in range(i+1, rank):
|
|
436
|
+
M[i, j] = ( height(basis[i] + basis[j]) - M[i,i] - M[j,j] ) / 2
|
|
437
|
+
M[j, i] = M[i, j]
|
|
438
|
+
|
|
439
|
+
return M
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def _multiply_point(E, R, P, m):
|
|
443
|
+
r"""
|
|
444
|
+
Compute coordinates of a multiple of `P` with entries in a ring.
|
|
445
|
+
|
|
446
|
+
INPUT:
|
|
447
|
+
|
|
448
|
+
- ``E`` -- elliptic curve over `\QQ` with integer
|
|
449
|
+
coefficients
|
|
450
|
+
|
|
451
|
+
- ``P`` -- a rational point on `P` that reduces to a
|
|
452
|
+
non-singular point at all primes
|
|
453
|
+
|
|
454
|
+
- ``R`` -- a ring in which 2 is invertible (typically
|
|
455
|
+
`\ZZ/L\ZZ` for some positive odd integer `L`)
|
|
456
|
+
|
|
457
|
+
- ``m`` -- integer (default: 1)
|
|
458
|
+
|
|
459
|
+
OUTPUT:
|
|
460
|
+
|
|
461
|
+
A triple `(a', b', d')` such that if the point
|
|
462
|
+
`mP` has coordinates `(a/d^2, b/d^3)`, then we have
|
|
463
|
+
`a' \equiv a`, `b' \equiv \pm b`,
|
|
464
|
+
`d' \equiv \pm d` all in `R` (i.e. modulo
|
|
465
|
+
`L`).
|
|
466
|
+
|
|
467
|
+
Note the ambiguity of signs for `b'` and `d'`.
|
|
468
|
+
There's not much one can do about this, but at least one can say
|
|
469
|
+
that the sign for `b'` will match the sign for
|
|
470
|
+
`d'`.
|
|
471
|
+
|
|
472
|
+
ALGORITHM: Proposition 9 in [Har2009]_.
|
|
473
|
+
|
|
474
|
+
Complexity is soft-`O(\log L \log m + \log^2 m)`.
|
|
475
|
+
|
|
476
|
+
AUTHORS:
|
|
477
|
+
|
|
478
|
+
- David Harvey (2008-01): replaced _DivPolyContext with
|
|
479
|
+
_multiply_point
|
|
480
|
+
|
|
481
|
+
EXAMPLES:
|
|
482
|
+
|
|
483
|
+
37a has trivial Tamagawa numbers so all points have nonsingular
|
|
484
|
+
reduction at all primes::
|
|
485
|
+
|
|
486
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
487
|
+
sage: E = EllipticCurve("37a")
|
|
488
|
+
sage: P = E([0, -1]); P
|
|
489
|
+
(0 : -1 : 1)
|
|
490
|
+
sage: 19*P
|
|
491
|
+
(-59997896/67387681 : 88075171080/553185473329 : 1)
|
|
492
|
+
sage: R = Integers(625)
|
|
493
|
+
sage: from sage.schemes.elliptic_curves.padics import _multiply_point
|
|
494
|
+
sage: _multiply_point(E, R, P, 19)
|
|
495
|
+
(229, 170, 541)
|
|
496
|
+
sage: -59997896 % 625
|
|
497
|
+
229
|
|
498
|
+
sage: -88075171080 % 625 # note sign is flipped
|
|
499
|
+
170
|
|
500
|
+
sage: -67387681.sqrt() % 625 # sign is flipped here too
|
|
501
|
+
541
|
|
502
|
+
|
|
503
|
+
Trivial cases (:issue:`3632`)::
|
|
504
|
+
|
|
505
|
+
sage: # needs database_cremona_mini_ellcurve
|
|
506
|
+
sage: _multiply_point(E, R, P, 1)
|
|
507
|
+
(0, 624, 1)
|
|
508
|
+
sage: _multiply_point(E, R, 19*P, 1)
|
|
509
|
+
(229, 455, 84)
|
|
510
|
+
sage: (170 + 455) % 625 # note the sign did not flip here
|
|
511
|
+
0
|
|
512
|
+
sage: (541 + 84) % 625
|
|
513
|
+
0
|
|
514
|
+
|
|
515
|
+
Test over a range of `n` for a single curve with fairly
|
|
516
|
+
random coefficients::
|
|
517
|
+
|
|
518
|
+
sage: R = Integers(625)
|
|
519
|
+
sage: E = EllipticCurve([4, -11, 17, -8, -10])
|
|
520
|
+
sage: P = E.gens()[0] * LCM(E.tamagawa_numbers())
|
|
521
|
+
sage: from sage.schemes.elliptic_curves.padics import _multiply_point
|
|
522
|
+
sage: Q = P
|
|
523
|
+
sage: for n in range(1, 25):
|
|
524
|
+
....: naive = R(Q[0].numerator()), \
|
|
525
|
+
....: R(Q[1].numerator()), \
|
|
526
|
+
....: R(Q[0].denominator().sqrt())
|
|
527
|
+
....: triple = _multiply_point(E, R, P, n)
|
|
528
|
+
....: assert (triple[0] == naive[0]) and ( \
|
|
529
|
+
....: (triple[1] == naive[1] and triple[2] == naive[2]) or \
|
|
530
|
+
....: (triple[1] == -naive[1] and triple[2] == -naive[2])), \
|
|
531
|
+
....: "_multiply_point() gave an incorrect answer"
|
|
532
|
+
....: Q = Q + P
|
|
533
|
+
"""
|
|
534
|
+
assert m >= 1
|
|
535
|
+
|
|
536
|
+
alpha = R(P[0].numerator())
|
|
537
|
+
beta = R(P[1].numerator())
|
|
538
|
+
d = R(P[0].denominator().sqrt())
|
|
539
|
+
if m == 1:
|
|
540
|
+
return alpha, beta, d
|
|
541
|
+
|
|
542
|
+
a1 = R(E.a1()) * d
|
|
543
|
+
a3 = R(E.a3()) * d**3
|
|
544
|
+
|
|
545
|
+
b2 = R(E.b2()) * d**2
|
|
546
|
+
b4 = R(E.b4()) * d**4
|
|
547
|
+
b6 = R(E.b6()) * d**6
|
|
548
|
+
b8 = R(E.b8()) * d**8
|
|
549
|
+
|
|
550
|
+
B4 = 6*alpha**2 + b2*alpha + b4
|
|
551
|
+
B6 = 4*alpha**3 + b2*alpha**2 + 2*b4*alpha + b6
|
|
552
|
+
B6_sqr = B6*B6
|
|
553
|
+
B8 = 3*alpha**4 + b2*alpha**3 + 3*b4*alpha**2 + 3*b6*alpha + b8
|
|
554
|
+
|
|
555
|
+
T = 2*beta + a1*alpha + a3
|
|
556
|
+
|
|
557
|
+
# make a list of disjoint intervals [a[i], b[i]) such that we need to
|
|
558
|
+
# compute g(k) for all a[i] <= k <= b[i] for each i
|
|
559
|
+
intervals = []
|
|
560
|
+
interval = (m - 2, m + 3)
|
|
561
|
+
while interval[0] < interval[1]:
|
|
562
|
+
intervals.append(interval)
|
|
563
|
+
interval = max((interval[0] - 3) >> 1, 0), \
|
|
564
|
+
min((interval[1] + 5) >> 1, interval[0])
|
|
565
|
+
|
|
566
|
+
# now walk through list and compute g(k)
|
|
567
|
+
g = {0 : R(0), 1 : R(1), 2 : R(-1), 3 : B8, 4 : B6**2 - B4*B8}
|
|
568
|
+
for i in reversed(intervals):
|
|
569
|
+
k = i[0]
|
|
570
|
+
while k < i[1]:
|
|
571
|
+
if k > 4:
|
|
572
|
+
j = k >> 1
|
|
573
|
+
if k & 1:
|
|
574
|
+
t1 = g[j]
|
|
575
|
+
t2 = g[j+1]
|
|
576
|
+
prod1 = g[j+2] * t1*t1*t1
|
|
577
|
+
prod2 = g[j-1] * t2*t2*t2
|
|
578
|
+
g[k] = prod1 - B6_sqr * prod2 if j & 1 else B6_sqr * prod1 - prod2
|
|
579
|
+
else:
|
|
580
|
+
t1 = g[j-1]
|
|
581
|
+
t2 = g[j+1]
|
|
582
|
+
g[k] = g[j] * (g[j-2] * t2*t2 - g[j+2] * t1*t1)
|
|
583
|
+
k = k + 1
|
|
584
|
+
|
|
585
|
+
if m & 1:
|
|
586
|
+
psi_m = g[m]
|
|
587
|
+
psi_m_m1 = g[m-1] * T
|
|
588
|
+
psi_m_p1 = g[m+1] * T
|
|
589
|
+
else:
|
|
590
|
+
psi_m = g[m] * T
|
|
591
|
+
psi_m_m1 = g[m-1]
|
|
592
|
+
psi_m_p1 = g[m+1]
|
|
593
|
+
|
|
594
|
+
theta = alpha * psi_m * psi_m - psi_m_m1 * psi_m_p1
|
|
595
|
+
t1 = g[m-2] * g[m+1] * g[m+1] - g[m+2] * g[m-1] * g[m-1]
|
|
596
|
+
if m & 1:
|
|
597
|
+
t1 = t1 * T
|
|
598
|
+
omega = (t1 + (a1 * theta + a3 * psi_m * psi_m) * psi_m) / -2
|
|
599
|
+
|
|
600
|
+
return theta, omega, psi_m * d
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def _multiple_to_make_good_reduction(E):
|
|
604
|
+
r"""
|
|
605
|
+
Return the integer `n_2` such that for all points `P` in `E(\QQ)`
|
|
606
|
+
`n_2*P` has good reduction at all primes.
|
|
607
|
+
If the model is globally minimal the lcm of the
|
|
608
|
+
Tamagawa numbers will do, otherwise we have to take into
|
|
609
|
+
account the change of the model.
|
|
610
|
+
|
|
611
|
+
INPUT:
|
|
612
|
+
|
|
613
|
+
- ``E`` -- an elliptic curve over `\QQ`
|
|
614
|
+
|
|
615
|
+
OUTPUT: a positive integer ``n2``
|
|
616
|
+
|
|
617
|
+
EXAMPLE (:issue:`34790`)::
|
|
618
|
+
|
|
619
|
+
sage: from sage.schemes.elliptic_curves.padics import _multiple_to_make_good_reduction
|
|
620
|
+
sage: E = EllipticCurve([-1728,-100656])
|
|
621
|
+
sage: _multiple_to_make_good_reduction(E)
|
|
622
|
+
30
|
|
623
|
+
|
|
624
|
+
The number ``n_2`` is not always optimal but it is in this example.
|
|
625
|
+
The first multiple of the generator `P` with good reduction in this
|
|
626
|
+
non-minimal model is `30 P`.
|
|
627
|
+
|
|
628
|
+
TESTS::
|
|
629
|
+
|
|
630
|
+
sage: from sage.schemes.elliptic_curves.padics import _multiple_to_make_good_reduction
|
|
631
|
+
sage: E = EllipticCurve([1/2,1/3])
|
|
632
|
+
sage: _multiple_to_make_good_reduction(E)
|
|
633
|
+
Traceback (most recent call last):
|
|
634
|
+
...
|
|
635
|
+
NotImplementedError: This only implemented for integral models. Please change the model first.
|
|
636
|
+
sage: E = EllipticCurve([0,3])
|
|
637
|
+
sage: _multiple_to_make_good_reduction(E)
|
|
638
|
+
1
|
|
639
|
+
sage: E = EllipticCurve([0,5^7]) # min eq is additive
|
|
640
|
+
sage: _multiple_to_make_good_reduction(E)
|
|
641
|
+
5
|
|
642
|
+
sage: E = EllipticCurve([7,0,0,0,7^7]) # min eq is split mult
|
|
643
|
+
sage: _multiple_to_make_good_reduction(E)
|
|
644
|
+
6
|
|
645
|
+
sage: E = EllipticCurve([0,-3^2,0,0,3^7]) # min eq is non-split mult
|
|
646
|
+
sage: _multiple_to_make_good_reduction(E)
|
|
647
|
+
4
|
|
648
|
+
"""
|
|
649
|
+
if not E.is_integral():
|
|
650
|
+
st = ("This only implemented for integral models. "
|
|
651
|
+
"Please change the model first.")
|
|
652
|
+
raise NotImplementedError(st)
|
|
653
|
+
if E.is_minimal():
|
|
654
|
+
n2 = LCM(E.tamagawa_numbers())
|
|
655
|
+
else:
|
|
656
|
+
# generalising to number fields one can get the u from local_data
|
|
657
|
+
Emin = E.global_minimal_model()
|
|
658
|
+
iota = E.isomorphism_to(Emin)
|
|
659
|
+
u = Integer(iota.u)
|
|
660
|
+
ps = u.prime_divisors()
|
|
661
|
+
li = []
|
|
662
|
+
for p in ps:
|
|
663
|
+
np = u.valuation(p)
|
|
664
|
+
if Emin.discriminant() % p != 0:
|
|
665
|
+
li.append(Emin.Np(p) * p**(np-1))
|
|
666
|
+
elif Emin.has_additive_reduction(p):
|
|
667
|
+
li.append(E.tamagawa_number(p) * p**np)
|
|
668
|
+
elif E.has_split_multiplicative_reduction(p):
|
|
669
|
+
li.append(E.tamagawa_number(p) * (p-1) * p**(np-1))
|
|
670
|
+
else: # non split
|
|
671
|
+
li.append(E.tamagawa_number(p) * (p+1) * p**(np-1))
|
|
672
|
+
otherbad = Integer(Emin.discriminant()).prime_divisors()
|
|
673
|
+
otherbad = [p for p in otherbad if u % p != 0 ]
|
|
674
|
+
li += [E.tamagawa_number(p) for p in otherbad]
|
|
675
|
+
n2 = LCM(li)
|
|
676
|
+
return n2
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
def padic_height(self, p, prec=20, sigma=None, check_hypotheses=True):
|
|
680
|
+
r"""
|
|
681
|
+
Compute the cyclotomic `p`-adic height.
|
|
682
|
+
|
|
683
|
+
The equation of the curve must be integral and minimal at `p`.
|
|
684
|
+
|
|
685
|
+
INPUT:
|
|
686
|
+
|
|
687
|
+
- ``p`` -- prime >= 5 for which the curve has semi-stable reduction
|
|
688
|
+
|
|
689
|
+
- ``prec`` -- integer >= 1 (default: 20); desired precision of result
|
|
690
|
+
|
|
691
|
+
- ``sigma`` -- precomputed value of sigma; if not supplied, this function
|
|
692
|
+
will call ``padic_sigma`` to compute it
|
|
693
|
+
|
|
694
|
+
- ``check_hypotheses`` -- boolean; whether to check that this is a curve
|
|
695
|
+
for which the `p`-adic height makes sense
|
|
696
|
+
|
|
697
|
+
OUTPUT:
|
|
698
|
+
|
|
699
|
+
A function that accepts two parameters:
|
|
700
|
+
|
|
701
|
+
- a `\QQ`-rational point on the curve whose height should be computed
|
|
702
|
+
|
|
703
|
+
- optional boolean flag 'check': if ``False``, it skips some input
|
|
704
|
+
checking, and returns the `p`-adic height of that point to the
|
|
705
|
+
desired precision.
|
|
706
|
+
|
|
707
|
+
- The normalization (sign and a factor 1/2 with respect to some other
|
|
708
|
+
normalizations that appear in the literature) is chosen in such a way
|
|
709
|
+
as to make the `p`-adic Birch Swinnerton-Dyer conjecture hold as stated
|
|
710
|
+
in [MTT1986]_.
|
|
711
|
+
|
|
712
|
+
AUTHORS:
|
|
713
|
+
|
|
714
|
+
- Jennifer Balakrishnan: original code developed at the 2006 MSRI
|
|
715
|
+
graduate workshop on modular forms
|
|
716
|
+
|
|
717
|
+
- David Harvey (2006-09-13): integrated into Sage, optimised to
|
|
718
|
+
speed up repeated evaluations of the returned height function,
|
|
719
|
+
addressed some thorny precision questions
|
|
720
|
+
|
|
721
|
+
- David Harvey (2006-09-30): rewrote to use division polynomials
|
|
722
|
+
for computing denominator of `nP`.
|
|
723
|
+
|
|
724
|
+
- David Harvey (2007-02): cleaned up according to algorithms in
|
|
725
|
+
"Efficient Computation of p-adic Heights"
|
|
726
|
+
|
|
727
|
+
- Chris Wuthrich (2007-05): added supersingular and multiplicative heights
|
|
728
|
+
|
|
729
|
+
EXAMPLES::
|
|
730
|
+
|
|
731
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
732
|
+
sage: E = EllipticCurve("37a")
|
|
733
|
+
sage: P = E.gens()[0]
|
|
734
|
+
sage: h = E.padic_height(5, 10)
|
|
735
|
+
sage: h(P)
|
|
736
|
+
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)
|
|
737
|
+
|
|
738
|
+
An anomalous case::
|
|
739
|
+
|
|
740
|
+
sage: h = E.padic_height(53, 10) # needs database_cremona_mini_ellcurve sage.symbolic
|
|
741
|
+
sage: h(P) # needs database_cremona_mini_ellcurve sage.symbolic
|
|
742
|
+
26*53^-1 + 30 + 20*53 + 47*53^2 + 10*53^3 + 32*53^4 + 9*53^5 + 22*53^6 + 35*53^7 + 30*53^8 + 17*53^9 + O(53^10)
|
|
743
|
+
|
|
744
|
+
Boundary case::
|
|
745
|
+
|
|
746
|
+
sage: E.padic_height(5, 3)(P) # needs database_cremona_mini_ellcurve sage.symbolic
|
|
747
|
+
5 + 5^2 + O(5^3)
|
|
748
|
+
|
|
749
|
+
A case that works the division polynomial code a little harder::
|
|
750
|
+
|
|
751
|
+
sage: E.padic_height(5, 10)(5*P) # needs database_cremona_mini_ellcurve sage.symbolic
|
|
752
|
+
5^3 + 5^4 + 5^5 + 3*5^8 + 4*5^9 + O(5^10)
|
|
753
|
+
|
|
754
|
+
Check that answers agree over a range of precisions::
|
|
755
|
+
|
|
756
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
757
|
+
sage: max_prec = 30 # make sure we get past p^2 # long time
|
|
758
|
+
sage: full = E.padic_height(5, max_prec)(P) # long time
|
|
759
|
+
sage: for prec in range(1, max_prec): # long time
|
|
760
|
+
....: assert E.padic_height(5, prec)(P) == full
|
|
761
|
+
|
|
762
|
+
A supersingular prime for a curve::
|
|
763
|
+
|
|
764
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
765
|
+
sage: E = EllipticCurve('37a')
|
|
766
|
+
sage: E.is_supersingular(3)
|
|
767
|
+
True
|
|
768
|
+
sage: h = E.padic_height(3, 5)
|
|
769
|
+
sage: h(E.gens()[0])
|
|
770
|
+
(3 + 3^3 + O(3^6), 2*3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + O(3^7))
|
|
771
|
+
sage: E.padic_regulator(5)
|
|
772
|
+
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + 5^10 + 3*5^11 + 3*5^12 + 5^13 + 4*5^14 + 5^15 + 2*5^16 + 5^17 + 2*5^18 + 4*5^19 + O(5^20)
|
|
773
|
+
sage: E.padic_regulator(3, 5)
|
|
774
|
+
(3 + 2*3^2 + 3^3 + O(3^4), 3^2 + 2*3^3 + 3^4 + O(3^5))
|
|
775
|
+
|
|
776
|
+
A torsion point in both the good and supersingular cases::
|
|
777
|
+
|
|
778
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
779
|
+
sage: E = EllipticCurve('11a')
|
|
780
|
+
sage: P = E.torsion_subgroup().gen(0).element(); P
|
|
781
|
+
(5 : 5 : 1)
|
|
782
|
+
sage: h = E.padic_height(19, 5)
|
|
783
|
+
sage: h(P)
|
|
784
|
+
0
|
|
785
|
+
sage: h = E.padic_height(5, 5)
|
|
786
|
+
sage: h(P)
|
|
787
|
+
0
|
|
788
|
+
|
|
789
|
+
The result is not dependent on the model for the curve::
|
|
790
|
+
|
|
791
|
+
sage: # needs sage.symbolic
|
|
792
|
+
sage: E = EllipticCurve([0,0,0,0,2^12*17])
|
|
793
|
+
sage: Em = E.minimal_model()
|
|
794
|
+
sage: P = E.gens()[0]
|
|
795
|
+
sage: Pm = Em.gens()[0]
|
|
796
|
+
sage: h = E.padic_height(7)
|
|
797
|
+
sage: hm = Em.padic_height(7)
|
|
798
|
+
sage: h(P) == hm(Pm)
|
|
799
|
+
True
|
|
800
|
+
|
|
801
|
+
TESTS:
|
|
802
|
+
|
|
803
|
+
Check that issue :issue:`20798` is solved::
|
|
804
|
+
|
|
805
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
806
|
+
sage: E = EllipticCurve("91b")
|
|
807
|
+
sage: h = E.padic_height(7,10)
|
|
808
|
+
sage: P = E.gen(0)
|
|
809
|
+
sage: h(P)
|
|
810
|
+
2*7 + 7^2 + 5*7^3 + 6*7^4 + 2*7^5 + 3*7^6 + 7^7 + 4*7^9 + 5*7^10 + O(7^11)
|
|
811
|
+
sage: h(P+P)
|
|
812
|
+
7 + 5*7^2 + 6*7^3 + 5*7^4 + 4*7^5 + 6*7^6 + 5*7^7 + 2*7^9 + 7^10 + O(7^11)
|
|
813
|
+
"""
|
|
814
|
+
if check_hypotheses:
|
|
815
|
+
if not p.is_prime():
|
|
816
|
+
raise ValueError("p = (%s) must be prime" % p)
|
|
817
|
+
if p == 2:
|
|
818
|
+
raise ValueError("p must be odd") # todo
|
|
819
|
+
if self.conductor() % (p**2) == 0:
|
|
820
|
+
raise ArithmeticError("p must be a semi-stable prime")
|
|
821
|
+
|
|
822
|
+
prec = int(prec)
|
|
823
|
+
if prec < 1:
|
|
824
|
+
raise ValueError("prec (=%s) must be at least 1" % prec)
|
|
825
|
+
|
|
826
|
+
if self.conductor() % p == 0:
|
|
827
|
+
Eq = self.tate_curve(p)
|
|
828
|
+
return Eq.padic_height(prec=prec)
|
|
829
|
+
elif self.ap(p) % p == 0:
|
|
830
|
+
lp = self.padic_lseries(p)
|
|
831
|
+
return lp.Dp_valued_height(prec=prec)
|
|
832
|
+
|
|
833
|
+
# else good ordinary case
|
|
834
|
+
|
|
835
|
+
# For notation and definitions, see [Har2009]_.
|
|
836
|
+
|
|
837
|
+
n1 = self.change_ring(GF(p)).cardinality()
|
|
838
|
+
n2 = _multiple_to_make_good_reduction(self)
|
|
839
|
+
n = LCM(n1, n2)
|
|
840
|
+
m = int(n / n2)
|
|
841
|
+
|
|
842
|
+
adjusted_prec = prec + 2 * valuation(n, p) # this is M'
|
|
843
|
+
R = Integers(p ** adjusted_prec)
|
|
844
|
+
|
|
845
|
+
if sigma is None:
|
|
846
|
+
sigma = self.padic_sigma(p, adjusted_prec, check_hypotheses=False)
|
|
847
|
+
|
|
848
|
+
# K is the field for the final result
|
|
849
|
+
K = Qp(p, prec=adjusted_prec-1)
|
|
850
|
+
E = self
|
|
851
|
+
|
|
852
|
+
def height(P, check=True):
|
|
853
|
+
if P.is_finite_order():
|
|
854
|
+
return K(0)
|
|
855
|
+
|
|
856
|
+
if check:
|
|
857
|
+
assert P.curve() == E, "the point P must lie on the curve " \
|
|
858
|
+
"from which the height function was created"
|
|
859
|
+
|
|
860
|
+
Q = n2 * P
|
|
861
|
+
alpha, beta, d = _multiply_point(E, R, Q, m)
|
|
862
|
+
|
|
863
|
+
assert beta.lift() % p != 0, "beta should be a unit!"
|
|
864
|
+
assert d.lift() % p == 0, "d should not be a unit!"
|
|
865
|
+
|
|
866
|
+
t = -d * alpha / beta
|
|
867
|
+
|
|
868
|
+
total = R(1)
|
|
869
|
+
t_power = t
|
|
870
|
+
for k in range(2, adjusted_prec + 1):
|
|
871
|
+
total = total + t_power * sigma[k].lift()
|
|
872
|
+
t_power = t_power * t
|
|
873
|
+
total = (-alpha / beta) * total
|
|
874
|
+
|
|
875
|
+
L = Qp(p, prec=adjusted_prec)
|
|
876
|
+
total = L(total.lift(), adjusted_prec) # yuck... get rid of this lift!
|
|
877
|
+
|
|
878
|
+
# changed sign to make it correct for p-adic bsd
|
|
879
|
+
answer = -total.log() * 2 / n**2
|
|
880
|
+
|
|
881
|
+
if check:
|
|
882
|
+
assert answer.precision_absolute() >= prec, "we should have got an " \
|
|
883
|
+
"answer with precision at least prec, but we didn't."
|
|
884
|
+
return K(answer)
|
|
885
|
+
|
|
886
|
+
# (man... I love python's local function definitions...)
|
|
887
|
+
return height
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
def padic_height_via_multiply(self, p, prec=20, E2=None, check_hypotheses=True):
|
|
891
|
+
r"""
|
|
892
|
+
Compute the cyclotomic `p`-adic height.
|
|
893
|
+
|
|
894
|
+
The equation of the curve must be minimal at `p`.
|
|
895
|
+
|
|
896
|
+
INPUT:
|
|
897
|
+
|
|
898
|
+
- ``p`` -- prime >= 5 for which the curve has good ordinary reduction
|
|
899
|
+
|
|
900
|
+
- ``prec`` -- integer >= 2 (default: 20); desired precision of result
|
|
901
|
+
|
|
902
|
+
- ``E2`` -- precomputed value of E2. If not supplied,
|
|
903
|
+
this function will call padic_E2 to compute it. The value supplied
|
|
904
|
+
must be correct mod `p^{prec-2}` (or slightly higher in the
|
|
905
|
+
anomalous case; see the code for details).
|
|
906
|
+
|
|
907
|
+
- ``check_hypotheses`` -- boolean; whether to check
|
|
908
|
+
that this is a curve for which the `p`-adic height makes sense
|
|
909
|
+
|
|
910
|
+
OUTPUT:
|
|
911
|
+
|
|
912
|
+
A function that accepts two parameters:
|
|
913
|
+
|
|
914
|
+
- a `\QQ`-rational point on the curve whose height should be computed
|
|
915
|
+
|
|
916
|
+
- optional boolean flag 'check': if ``False``, it skips some input
|
|
917
|
+
checking, and returns the `p`-adic height of that point to the
|
|
918
|
+
desired precision.
|
|
919
|
+
|
|
920
|
+
- The normalization (sign and a factor 1/2 with respect to some other
|
|
921
|
+
normalizations that appear in the literature) is chosen in such a way
|
|
922
|
+
as to make the `p`-adic Birch Swinnerton-Dyer conjecture hold as stated
|
|
923
|
+
in [MTT1986]_.
|
|
924
|
+
|
|
925
|
+
AUTHORS:
|
|
926
|
+
|
|
927
|
+
- David Harvey (2008-01): based on the padic_height() function,
|
|
928
|
+
using the algorithm of [Har2009]_.
|
|
929
|
+
|
|
930
|
+
EXAMPLES::
|
|
931
|
+
|
|
932
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
933
|
+
sage: E = EllipticCurve("37a")
|
|
934
|
+
sage: P = E.gens()[0]
|
|
935
|
+
sage: h = E.padic_height_via_multiply(5, 10)
|
|
936
|
+
sage: h(P)
|
|
937
|
+
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)
|
|
938
|
+
|
|
939
|
+
An anomalous case::
|
|
940
|
+
|
|
941
|
+
sage: h = E.padic_height_via_multiply(53, 10) # needs database_cremona_mini_ellcurve sage.symbolic
|
|
942
|
+
sage: h(P) # needs database_cremona_mini_ellcurve sage.symbolic
|
|
943
|
+
26*53^-1 + 30 + 20*53 + 47*53^2 + 10*53^3 + 32*53^4 + 9*53^5 + 22*53^6 + 35*53^7 + 30*53^8 + 17*53^9 + O(53^10)
|
|
944
|
+
|
|
945
|
+
Supply the value of E2 manually::
|
|
946
|
+
|
|
947
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
948
|
+
sage: E2 = E.padic_E2(5, 8)
|
|
949
|
+
sage: E2
|
|
950
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + O(5^8)
|
|
951
|
+
sage: h = E.padic_height_via_multiply(5, 10, E2=E2)
|
|
952
|
+
sage: h(P)
|
|
953
|
+
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)
|
|
954
|
+
|
|
955
|
+
Boundary case::
|
|
956
|
+
|
|
957
|
+
sage: E.padic_height_via_multiply(5, 3)(P) # needs database_cremona_mini_ellcurve sage.symbolic
|
|
958
|
+
5 + 5^2 + O(5^3)
|
|
959
|
+
|
|
960
|
+
Check that answers agree over a range of precisions::
|
|
961
|
+
|
|
962
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
963
|
+
sage: max_prec = 30 # make sure we get past p^2 # long time
|
|
964
|
+
sage: full = E.padic_height(5, max_prec)(P) # long time
|
|
965
|
+
sage: for prec in range(2, max_prec): # long time
|
|
966
|
+
....: assert E.padic_height_via_multiply(5, prec)(P) == full
|
|
967
|
+
"""
|
|
968
|
+
if check_hypotheses:
|
|
969
|
+
if not p.is_prime():
|
|
970
|
+
raise ValueError("p = (%s) must be prime" % p)
|
|
971
|
+
if p == 2:
|
|
972
|
+
raise ValueError("p must be odd") # todo
|
|
973
|
+
if self.conductor() % p == 0:
|
|
974
|
+
raise ArithmeticError("must have good reduction at p")
|
|
975
|
+
if self.ap(p) % p == 0:
|
|
976
|
+
raise ArithmeticError("must be ordinary at p")
|
|
977
|
+
|
|
978
|
+
prec = int(prec)
|
|
979
|
+
if prec < 1:
|
|
980
|
+
raise ValueError("prec (=%s) must be at least 1" % prec)
|
|
981
|
+
|
|
982
|
+
# For notation and definitions, [Har2009]_
|
|
983
|
+
|
|
984
|
+
n1 = self.change_ring(GF(p)).cardinality()
|
|
985
|
+
n2 = _multiple_to_make_good_reduction(self)
|
|
986
|
+
n = LCM(n1, n2)
|
|
987
|
+
m = int(n / n2)
|
|
988
|
+
|
|
989
|
+
lamb = int(math.floor(math.sqrt(prec)))
|
|
990
|
+
|
|
991
|
+
adjusted_prec = prec + 2 * valuation(n, p) # this is M'
|
|
992
|
+
R = Integers(p ** (adjusted_prec + 2*lamb))
|
|
993
|
+
|
|
994
|
+
sigma = self.padic_sigma_truncated(p, N=adjusted_prec, E2=E2, lamb=lamb)
|
|
995
|
+
|
|
996
|
+
# K is the field for the final result
|
|
997
|
+
K = Qp(p, prec=adjusted_prec-1)
|
|
998
|
+
E = self
|
|
999
|
+
|
|
1000
|
+
def height(P, check=True):
|
|
1001
|
+
if P.is_finite_order():
|
|
1002
|
+
return K(0)
|
|
1003
|
+
|
|
1004
|
+
if check:
|
|
1005
|
+
assert P.curve() == E, "the point P must lie on the curve " \
|
|
1006
|
+
"from which the height function was created"
|
|
1007
|
+
|
|
1008
|
+
Q = n2 * P
|
|
1009
|
+
alpha, beta, d = _multiply_point(E, R, Q, m * p**lamb)
|
|
1010
|
+
|
|
1011
|
+
assert beta.lift() % p != 0, "beta should be a unit!"
|
|
1012
|
+
assert d.lift() % p == 0, "d should not be a unit!"
|
|
1013
|
+
|
|
1014
|
+
t = -d * alpha / beta
|
|
1015
|
+
|
|
1016
|
+
total = R(1)
|
|
1017
|
+
t_power = t
|
|
1018
|
+
for k in range(2, sigma.prec()):
|
|
1019
|
+
total = total + t_power * sigma[k].lift()
|
|
1020
|
+
t_power = t_power * t
|
|
1021
|
+
total = (-alpha / beta) * total
|
|
1022
|
+
|
|
1023
|
+
L = Qp(p, prec=adjusted_prec + 2*lamb)
|
|
1024
|
+
total = L(total.lift(), adjusted_prec + 2*lamb)
|
|
1025
|
+
|
|
1026
|
+
# changed sign to make it correct for p-adic bsd
|
|
1027
|
+
answer = -total.log() * 2 / (n * p**lamb)**2
|
|
1028
|
+
|
|
1029
|
+
if check:
|
|
1030
|
+
assert answer.precision_absolute() >= prec, "we should have got an " \
|
|
1031
|
+
"answer with precision at least prec, but we didn't."
|
|
1032
|
+
return K(answer)
|
|
1033
|
+
|
|
1034
|
+
# (man... I love python's local function definitions...)
|
|
1035
|
+
return height
|
|
1036
|
+
|
|
1037
|
+
|
|
1038
|
+
def padic_sigma(self, p, N=20, E2=None, check=False, check_hypotheses=True):
|
|
1039
|
+
r"""
|
|
1040
|
+
Compute the `p`-adic sigma function with respect to the standard
|
|
1041
|
+
invariant differential `dx/(2y + a_1 x + a_3)`, as
|
|
1042
|
+
defined by Mazur and Tate in [MT1991]_, as a power series in the usual
|
|
1043
|
+
uniformiser `t` at the origin.
|
|
1044
|
+
|
|
1045
|
+
The equation of the curve must be minimal at `p`.
|
|
1046
|
+
|
|
1047
|
+
INPUT:
|
|
1048
|
+
|
|
1049
|
+
- ``p`` -- prime >= 5 for which the curve has good ordinary reduction
|
|
1050
|
+
|
|
1051
|
+
- ``N`` -- integer >= 1 (default: 20); precision of result,
|
|
1052
|
+
see OUTPUT section for description
|
|
1053
|
+
|
|
1054
|
+
- ``E2`` -- precomputed value of E2. If not supplied,
|
|
1055
|
+
this function will call padic_E2 to compute it. The value supplied
|
|
1056
|
+
must be correct mod `p^{N-2}`.
|
|
1057
|
+
|
|
1058
|
+
- ``check`` -- boolean; whether to perform a
|
|
1059
|
+
consistency check (i.e. verify that the computed sigma satisfies
|
|
1060
|
+
the defining
|
|
1061
|
+
|
|
1062
|
+
- ``differential equation`` -- note that this does NOT guarantee
|
|
1063
|
+
correctness of all the returned digits, but it comes pretty close
|
|
1064
|
+
|
|
1065
|
+
- ``check_hypotheses`` -- boolean; whether to check that this is a curve
|
|
1066
|
+
for which the `p`-adic sigma function makes sense
|
|
1067
|
+
|
|
1068
|
+
OUTPUT: a power series `t + \cdots` with coefficients in `\ZZ_p`
|
|
1069
|
+
|
|
1070
|
+
The output series will be truncated at `O(t^{N+1})`, and
|
|
1071
|
+
the coefficient of `t^n` for `n \geq 1` will be
|
|
1072
|
+
correct to precision `O(p^{N-n+1})`.
|
|
1073
|
+
|
|
1074
|
+
In practice this means the following. If `t_0 = p^k u`,
|
|
1075
|
+
where `u` is a `p`-adic unit with at least
|
|
1076
|
+
`N` digits of precision, and `k \geq 1`, then the
|
|
1077
|
+
returned series may be used to compute `\sigma(t_0)`
|
|
1078
|
+
correctly modulo `p^{N+k}` (i.e. with `N` correct
|
|
1079
|
+
`p`-adic digits).
|
|
1080
|
+
|
|
1081
|
+
ALGORITHM: Described in "Efficient Computation of p-adic Heights"
|
|
1082
|
+
(David Harvey) [Har2009]_ which is basically an optimised version of the
|
|
1083
|
+
algorithm from "p-adic Heights and Log Convergence" (Mazur, Stein,
|
|
1084
|
+
Tate) [MST2006]_.
|
|
1085
|
+
|
|
1086
|
+
Running time is soft-`O(N^2 \log p)`, plus whatever time is
|
|
1087
|
+
necessary to compute `E_2`.
|
|
1088
|
+
|
|
1089
|
+
AUTHORS:
|
|
1090
|
+
|
|
1091
|
+
- David Harvey (2006-09-12)
|
|
1092
|
+
|
|
1093
|
+
- David Harvey (2007-02): rewrote
|
|
1094
|
+
|
|
1095
|
+
EXAMPLES::
|
|
1096
|
+
|
|
1097
|
+
sage: EllipticCurve([-1, 1/4]).padic_sigma(5, 10) # needs sage.symbolic
|
|
1098
|
+
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (3 + 2*5^2 + 3*5^3 + 3*5^6 + 4*5^7 + O(5^8))*t^3 + O(5^7)*t^4 + (2 + 4*5^2 + 4*5^3 + 5^4 + 5^5 + O(5^6))*t^5 + O(5^5)*t^6 + (2 + 2*5 + 5^2 + 4*5^3 + O(5^4))*t^7 + O(5^3)*t^8 + (1 + 2*5 + O(5^2))*t^9 + O(5)*t^10 + O(t^11)
|
|
1099
|
+
|
|
1100
|
+
Run it with a consistency check::
|
|
1101
|
+
|
|
1102
|
+
sage: EllipticCurve("37a").padic_sigma(5, 10, check=True) # needs sage.symbolic
|
|
1103
|
+
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (3 + 2*5^2 + 3*5^3 + 3*5^6 + 4*5^7 + O(5^8))*t^3 + (3 + 2*5 + 2*5^2 + 2*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + O(5^7))*t^4 + (2 + 4*5^2 + 4*5^3 + 5^4 + 5^5 + O(5^6))*t^5 + (2 + 3*5 + 5^4 + O(5^5))*t^6 + (4 + 3*5 + 2*5^2 + O(5^4))*t^7 + (2 + 3*5 + 2*5^2 + O(5^3))*t^8 + (4*5 + O(5^2))*t^9 + (1 + O(5))*t^10 + O(t^11)
|
|
1104
|
+
|
|
1105
|
+
Boundary cases::
|
|
1106
|
+
|
|
1107
|
+
sage: EllipticCurve([1, 1, 1, 1, 1]).padic_sigma(5, 1) # needs sage.symbolic
|
|
1108
|
+
(1 + O(5))*t + O(t^2)
|
|
1109
|
+
sage: EllipticCurve([1, 1, 1, 1, 1]).padic_sigma(5, 2) # needs sage.symbolic
|
|
1110
|
+
(1 + O(5^2))*t + (3 + O(5))*t^2 + O(t^3)
|
|
1111
|
+
|
|
1112
|
+
Supply your very own value of E2::
|
|
1113
|
+
|
|
1114
|
+
sage: # needs sage.symbolic
|
|
1115
|
+
sage: X = EllipticCurve("37a")
|
|
1116
|
+
sage: my_E2 = X.padic_E2(5, 8)
|
|
1117
|
+
sage: my_E2 = my_E2 + 5**5 # oops!!!
|
|
1118
|
+
sage: X.padic_sigma(5, 10, E2=my_E2)
|
|
1119
|
+
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (3 + 2*5^2 + 3*5^3 + 4*5^5 + 2*5^6 + 3*5^7 + O(5^8))*t^3 + (3 + 2*5 + 2*5^2 + 2*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + O(5^7))*t^4 + (2 + 4*5^2 + 4*5^3 + 5^4 + 3*5^5 + O(5^6))*t^5 + (2 + 3*5 + 5^4 + O(5^5))*t^6 + (4 + 3*5 + 2*5^2 + O(5^4))*t^7 + (2 + 3*5 + 2*5^2 + O(5^3))*t^8 + (4*5 + O(5^2))*t^9 + (1 + O(5))*t^10 + O(t^11)
|
|
1120
|
+
|
|
1121
|
+
Check that sigma is "weight 1".
|
|
1122
|
+
|
|
1123
|
+
::
|
|
1124
|
+
|
|
1125
|
+
sage: # needs sage.symbolic
|
|
1126
|
+
sage: f = EllipticCurve([-1, 3]).padic_sigma(5, 10)
|
|
1127
|
+
sage: g = EllipticCurve([-1*(2**4), 3*(2**6)]).padic_sigma(5, 10)
|
|
1128
|
+
sage: t = f.parent().gen()
|
|
1129
|
+
sage: f(2*t)/2
|
|
1130
|
+
(1 + O(5^10))*t + (4 + 3*5 + 3*5^2 + 3*5^3 + 4*5^4 + 4*5^5 + 3*5^6 + 5^7 + O(5^8))*t^3 + (3 + 3*5^2 + 5^4 + 2*5^5 + O(5^6))*t^5 + (4 + 5 + 3*5^3 + O(5^4))*t^7 + (4 + 2*5 + O(5^2))*t^9 + O(5)*t^10 + O(t^11)
|
|
1131
|
+
sage: g
|
|
1132
|
+
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (4 + 3*5 + 3*5^2 + 3*5^3 + 4*5^4 + 4*5^5 + 3*5^6 + 5^7 + O(5^8))*t^3 + O(5^7)*t^4 + (3 + 3*5^2 + 5^4 + 2*5^5 + O(5^6))*t^5 + O(5^5)*t^6 + (4 + 5 + 3*5^3 + O(5^4))*t^7 + O(5^3)*t^8 + (4 + 2*5 + O(5^2))*t^9 + O(5)*t^10 + O(t^11)
|
|
1133
|
+
sage: f(2*t)/2 -g
|
|
1134
|
+
O(t^11)
|
|
1135
|
+
|
|
1136
|
+
Test that it returns consistent results over a range of precision::
|
|
1137
|
+
|
|
1138
|
+
sage: # long time, needs sage.symbolic
|
|
1139
|
+
sage: max_N = 30 # get up to at least p^2
|
|
1140
|
+
sage: E = EllipticCurve([1, 1, 1, 1, 1])
|
|
1141
|
+
sage: p = 5
|
|
1142
|
+
sage: E2 = E.padic_E2(5, max_N)
|
|
1143
|
+
sage: max_sigma = E.padic_sigma(p, max_N, E2=E2)
|
|
1144
|
+
sage: for N in range(3, max_N):
|
|
1145
|
+
....: sigma = E.padic_sigma(p, N, E2=E2)
|
|
1146
|
+
....: assert sigma == max_sigma
|
|
1147
|
+
"""
|
|
1148
|
+
if check_hypotheses:
|
|
1149
|
+
p = __check_padic_hypotheses(self, p)
|
|
1150
|
+
|
|
1151
|
+
# todo: implement the p == 3 case
|
|
1152
|
+
# NOTE: If we ever implement p == 3, it's necessary to check over
|
|
1153
|
+
# the precision loss estimates (below) very carefully; I think it
|
|
1154
|
+
# may become necessary to compute E2 to an even higher precision.
|
|
1155
|
+
if p < 5:
|
|
1156
|
+
raise NotImplementedError("p (=%s) must be at least 5" % p)
|
|
1157
|
+
|
|
1158
|
+
N = int(N)
|
|
1159
|
+
|
|
1160
|
+
# a few special cases for small N
|
|
1161
|
+
if N < 1:
|
|
1162
|
+
raise ValueError("N (=%s) must be at least 1" % N)
|
|
1163
|
+
|
|
1164
|
+
if N == 1:
|
|
1165
|
+
# return simply t + O(t^2)
|
|
1166
|
+
K = Qp(p, 2)
|
|
1167
|
+
return PowerSeriesRing(K, "t")([K(0), K(1, 1)], prec=2)
|
|
1168
|
+
|
|
1169
|
+
if N == 2:
|
|
1170
|
+
# return t + a_1/2 t^2 + O(t^3)
|
|
1171
|
+
K = Qp(p, 3)
|
|
1172
|
+
return PowerSeriesRing(K, "t")([K(0), K(1, 2),
|
|
1173
|
+
K(self.a1()/2, 1)], prec=3)
|
|
1174
|
+
|
|
1175
|
+
if self.discriminant().valuation(p) != 0:
|
|
1176
|
+
raise NotImplementedError("equation of curve must be minimal at p")
|
|
1177
|
+
|
|
1178
|
+
if E2 is None:
|
|
1179
|
+
E2 = self.padic_E2(p, N-2, check_hypotheses=False)
|
|
1180
|
+
elif E2.precision_absolute() < N-2:
|
|
1181
|
+
raise ValueError("supplied E2 has insufficient precision")
|
|
1182
|
+
|
|
1183
|
+
QQt = LaurentSeriesRing(RationalField(), "x")
|
|
1184
|
+
|
|
1185
|
+
R = Integers(p**(N-2))
|
|
1186
|
+
X = self.change_ring(R)
|
|
1187
|
+
c = (X.a1()**2 + 4*X.a2() - R(E2)) / 12
|
|
1188
|
+
|
|
1189
|
+
f = X.formal_group().differential(N+2) # f = 1 + ... + O(t^{N+2})
|
|
1190
|
+
x = X.formal_group().x(N) # x = t^{-2} + ... + O(t^N)
|
|
1191
|
+
|
|
1192
|
+
Rt = x.parent()
|
|
1193
|
+
|
|
1194
|
+
A = (x + c) * f
|
|
1195
|
+
# do integral over QQ, to avoid divisions by p
|
|
1196
|
+
A = Rt(QQt(A).integral())
|
|
1197
|
+
A = (-X.a1()/2 - A) * f
|
|
1198
|
+
|
|
1199
|
+
# Convert to a power series and remove the -1/x term.
|
|
1200
|
+
# Also we artificially bump up the accuracy from N-2 to N-1 digits;
|
|
1201
|
+
# the constant term needs to be known to N-1 digits, so we compute
|
|
1202
|
+
# it directly
|
|
1203
|
+
assert A.valuation() == -1 and A[-1] == 1
|
|
1204
|
+
A = A - A.parent().gen() ** (-1)
|
|
1205
|
+
A = A.power_series().list()
|
|
1206
|
+
R = Integers(p**(N-1))
|
|
1207
|
+
A = [R(u) for u in A]
|
|
1208
|
+
A[0] = self.change_ring(R).a1()/2 # fix constant term
|
|
1209
|
+
A = PowerSeriesRing(R, "x")(A, len(A))
|
|
1210
|
+
|
|
1211
|
+
theta = _brent(A, p, N)
|
|
1212
|
+
sigma = theta * theta.parent().gen()
|
|
1213
|
+
|
|
1214
|
+
# Convert the answer to power series over p-adics; drop the precision
|
|
1215
|
+
# of the t^k coefficient to p^(N-k+1).
|
|
1216
|
+
# [Note: there are actually more digits available, but it's a bit
|
|
1217
|
+
# tricky to figure out exactly how many, and we only need p^(N-k+1)
|
|
1218
|
+
# for p-adic height purposes anyway]
|
|
1219
|
+
K = Qp(p, N + 1)
|
|
1220
|
+
|
|
1221
|
+
sigma = sigma.padded_list(N+1)
|
|
1222
|
+
|
|
1223
|
+
sigma[0] = K(0, N + 1)
|
|
1224
|
+
sigma[1] = K(1, N)
|
|
1225
|
+
for n in range(2, N+1):
|
|
1226
|
+
sigma[n] = K(sigma[n].lift(), N - n + 1)
|
|
1227
|
+
|
|
1228
|
+
S = PowerSeriesRing(K, "t", N+1)
|
|
1229
|
+
sigma = S(sigma, N+1)
|
|
1230
|
+
|
|
1231
|
+
# if requested, check that sigma satisfies the appropriate
|
|
1232
|
+
# differential equation
|
|
1233
|
+
if check:
|
|
1234
|
+
R = Integers(p**N)
|
|
1235
|
+
X = self.change_ring(R)
|
|
1236
|
+
x = X.formal_group().x(N+5) # few extra terms for safety
|
|
1237
|
+
f = X.formal_group().differential(N+5)
|
|
1238
|
+
c = (X.a1()**2 + 4*X.a2() - R(E2)) / 12
|
|
1239
|
+
|
|
1240
|
+
# convert sigma to be over Z/p^N
|
|
1241
|
+
s = f.parent()(sigma)
|
|
1242
|
+
sinv = s**(-1)
|
|
1243
|
+
finv = f**(-1)
|
|
1244
|
+
|
|
1245
|
+
# apply differential equation
|
|
1246
|
+
temp = (s.derivative() * sinv * finv).derivative() * finv + c + x
|
|
1247
|
+
|
|
1248
|
+
# coefficient of t^k in the result should be zero mod p^(N-k-2)
|
|
1249
|
+
for k in range(N-2):
|
|
1250
|
+
assert temp[k].lift().valuation(p) >= N - k - 2, \
|
|
1251
|
+
"sigma correctness check failed!"
|
|
1252
|
+
|
|
1253
|
+
return sigma
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
def padic_sigma_truncated(self, p, N=20, lamb=0, E2=None, check_hypotheses=True):
|
|
1257
|
+
r"""
|
|
1258
|
+
Compute the `p`-adic sigma function with respect to the standard
|
|
1259
|
+
invariant differential `dx/(2y + a_1 x + a_3)`, as
|
|
1260
|
+
defined by Mazur and Tate in [MT1991]_, as a power series in the usual
|
|
1261
|
+
uniformiser `t` at the origin.
|
|
1262
|
+
|
|
1263
|
+
The equation of the curve must be minimal at `p`.
|
|
1264
|
+
|
|
1265
|
+
This function differs from :func:`padic_sigma` in the precision profile
|
|
1266
|
+
of the returned power series; see OUTPUT below.
|
|
1267
|
+
|
|
1268
|
+
INPUT:
|
|
1269
|
+
|
|
1270
|
+
- ``p`` -- prime >= 5 for which the curve has good ordinary reduction
|
|
1271
|
+
|
|
1272
|
+
- ``N`` -- integer >= 2 (default: 20); precision of result,
|
|
1273
|
+
see OUTPUT section for description
|
|
1274
|
+
|
|
1275
|
+
- ``lamb`` -- integer >= 0; see OUTPUT section for description
|
|
1276
|
+
|
|
1277
|
+
- ``E2`` -- precomputed value of E2. If not supplied,
|
|
1278
|
+
this function will call padic_E2 to compute it. The value supplied
|
|
1279
|
+
must be correct mod `p^{N-2}`.
|
|
1280
|
+
|
|
1281
|
+
- ``check_hypotheses`` -- boolean; whether to check that this is a curve
|
|
1282
|
+
for which the `p`-adic sigma function makes sense
|
|
1283
|
+
|
|
1284
|
+
OUTPUT: a power series `t + \cdots` with coefficients in `\ZZ_p`
|
|
1285
|
+
|
|
1286
|
+
The coefficient of `t^j` for `j \geq 1` will be
|
|
1287
|
+
correct to precision `O(p^{N - 2 + (3 - j)(lamb + 1)})`.
|
|
1288
|
+
|
|
1289
|
+
ALGORITHM: Described in "Efficient Computation of p-adic Heights"
|
|
1290
|
+
[Har2009]_, which is basically an
|
|
1291
|
+
optimised version of the algorithm from "p-adic Heights and Log
|
|
1292
|
+
Convergence" (Mazur, Stein, Tate) [MST2006]_.
|
|
1293
|
+
|
|
1294
|
+
Running time is soft-`O(N^2 \lambda^{-1} \log p)`, plus
|
|
1295
|
+
whatever time is necessary to compute `E_2`.
|
|
1296
|
+
|
|
1297
|
+
AUTHORS:
|
|
1298
|
+
|
|
1299
|
+
- David Harvey (2008-01): wrote based on previous
|
|
1300
|
+
:func:`padic_sigma` function
|
|
1301
|
+
|
|
1302
|
+
EXAMPLES::
|
|
1303
|
+
|
|
1304
|
+
sage: E = EllipticCurve([-1, 1/4])
|
|
1305
|
+
sage: E.padic_sigma_truncated(5, 10) # needs sage.symbolic
|
|
1306
|
+
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (3 + 2*5^2 + 3*5^3 + 3*5^6 + 4*5^7 + O(5^8))*t^3 + O(5^7)*t^4 + (2 + 4*5^2 + 4*5^3 + 5^4 + 5^5 + O(5^6))*t^5 + O(5^5)*t^6 + (2 + 2*5 + 5^2 + 4*5^3 + O(5^4))*t^7 + O(5^3)*t^8 + (1 + 2*5 + O(5^2))*t^9 + O(5)*t^10 + O(t^11)
|
|
1307
|
+
|
|
1308
|
+
Note the precision of the `t^3` coefficient depends only on
|
|
1309
|
+
`N`, not on lamb::
|
|
1310
|
+
|
|
1311
|
+
sage: E.padic_sigma_truncated(5, 10, lamb=2) # needs sage.symbolic
|
|
1312
|
+
O(5^17) + (1 + O(5^14))*t + O(5^11)*t^2 + (3 + 2*5^2 + 3*5^3 + 3*5^6 + 4*5^7 + O(5^8))*t^3 + O(5^5)*t^4 + (2 + O(5^2))*t^5 + O(t^6)
|
|
1313
|
+
|
|
1314
|
+
Compare against plain padic_sigma() function over a dense range of
|
|
1315
|
+
N and lamb
|
|
1316
|
+
|
|
1317
|
+
::
|
|
1318
|
+
|
|
1319
|
+
sage: # long time, needs sage.symbolic
|
|
1320
|
+
sage: E = EllipticCurve([1, 2, 3, 4, 7])
|
|
1321
|
+
sage: E2 = E.padic_E2(5, 50)
|
|
1322
|
+
sage: for N in range(2, 10):
|
|
1323
|
+
....: for lamb in range(10):
|
|
1324
|
+
....: correct = E.padic_sigma(5, N + 3*lamb, E2=E2)
|
|
1325
|
+
....: compare = E.padic_sigma_truncated(5, N=N, lamb=lamb, E2=E2)
|
|
1326
|
+
....: assert compare == correct
|
|
1327
|
+
"""
|
|
1328
|
+
if check_hypotheses:
|
|
1329
|
+
p = __check_padic_hypotheses(self, p)
|
|
1330
|
+
|
|
1331
|
+
# todo: implement the p == 3 case
|
|
1332
|
+
# NOTE: If we ever implement p == 3, it's necessary to check over
|
|
1333
|
+
# the precision loss estimates (below) very carefully; I think it
|
|
1334
|
+
# may become necessary to compute E2 to an even higher precision.
|
|
1335
|
+
if p < 5:
|
|
1336
|
+
raise NotImplementedError("p (=%s) must be at least 5" % p)
|
|
1337
|
+
|
|
1338
|
+
N = int(N)
|
|
1339
|
+
lamb = int(lamb)
|
|
1340
|
+
|
|
1341
|
+
if lamb < 0:
|
|
1342
|
+
raise ValueError("lamb (=%s) must be at least 0" % lamb)
|
|
1343
|
+
|
|
1344
|
+
# a few special cases for small N
|
|
1345
|
+
if N <= 1:
|
|
1346
|
+
raise ValueError("N (=%s) must be at least 2" % N)
|
|
1347
|
+
|
|
1348
|
+
if N == 2:
|
|
1349
|
+
# return t + a_1/2 t^2 + O(t^3)
|
|
1350
|
+
K = Qp(p, 3*(lamb+1))
|
|
1351
|
+
return PowerSeriesRing(K, "t")([K(0), K(1, 2*(lamb+1)),
|
|
1352
|
+
K(self.a1()/2, lamb+1)], prec=3)
|
|
1353
|
+
|
|
1354
|
+
if self.discriminant().valuation(p) != 0:
|
|
1355
|
+
raise NotImplementedError("equation of curve must be minimal at p")
|
|
1356
|
+
|
|
1357
|
+
if E2 is None:
|
|
1358
|
+
E2 = self.padic_E2(p, N-2, check_hypotheses=False)
|
|
1359
|
+
elif E2.precision_absolute() < N-2:
|
|
1360
|
+
raise ValueError("supplied E2 has insufficient precision")
|
|
1361
|
+
|
|
1362
|
+
# The main part of the algorithm is exactly the same as
|
|
1363
|
+
# for padic_sigma(), but we truncate all the series earlier.
|
|
1364
|
+
# Want the answer O(t^(trunc+1)) instead of O(t^(N+1)) like in padic_sigma().
|
|
1365
|
+
trunc = (Integer(N-2) / (lamb + 1)).ceil() + 2
|
|
1366
|
+
|
|
1367
|
+
QQt = LaurentSeriesRing(RationalField(), "x")
|
|
1368
|
+
|
|
1369
|
+
R = Integers(p**(N-2))
|
|
1370
|
+
X = self.change_ring(R)
|
|
1371
|
+
c = (X.a1()**2 + 4*X.a2() - R(E2)) / 12
|
|
1372
|
+
|
|
1373
|
+
f = X.formal_group().differential(trunc+2) # f = 1 + ... + O(t^{trunc+2})
|
|
1374
|
+
x = X.formal_group().x(trunc) # x = t^{-2} + ... + O(t^trunc)
|
|
1375
|
+
|
|
1376
|
+
Rt = x.parent()
|
|
1377
|
+
|
|
1378
|
+
A = (x + c) * f
|
|
1379
|
+
# do integral over QQ, to avoid divisions by p
|
|
1380
|
+
A = Rt(QQt(A).integral())
|
|
1381
|
+
A = (-X.a1()/2 - A) * f
|
|
1382
|
+
|
|
1383
|
+
# Convert to a power series and remove the -1/x term.
|
|
1384
|
+
# Also we artificially bump up the accuracy from N-2 to N-1+lamb digits;
|
|
1385
|
+
# the constant term needs to be known to N-1+lamb digits, so we compute
|
|
1386
|
+
# it directly
|
|
1387
|
+
assert A.valuation() == -1 and A[-1] == 1
|
|
1388
|
+
A = A - A.parent().gen() ** (-1)
|
|
1389
|
+
A = A.power_series().list()
|
|
1390
|
+
R = Integers(p**(N-1+lamb))
|
|
1391
|
+
A = [R(u) for u in A]
|
|
1392
|
+
A[0] = self.change_ring(R).a1()/2 # fix constant term
|
|
1393
|
+
A = PowerSeriesRing(R, "x")(A, len(A))
|
|
1394
|
+
|
|
1395
|
+
theta = _brent(A, p, trunc)
|
|
1396
|
+
sigma = theta * theta.parent().gen()
|
|
1397
|
+
|
|
1398
|
+
# Convert the answer to power series over p-adics; drop the precision
|
|
1399
|
+
# of the t^j coefficient to p^{N - 2 + (3 - j)(lamb + 1)}).
|
|
1400
|
+
K = Qp(p, N - 2 + 3*(lamb+1))
|
|
1401
|
+
|
|
1402
|
+
sigma = sigma.padded_list(trunc+1)
|
|
1403
|
+
|
|
1404
|
+
sigma[0] = K(0, N - 2 + 3*(lamb+1))
|
|
1405
|
+
sigma[1] = K(1, N - 2 + 2*(lamb+1))
|
|
1406
|
+
for j in range(2, trunc+1):
|
|
1407
|
+
sigma[j] = K(sigma[j].lift(), N - 2 + (3 - j)*(lamb+1))
|
|
1408
|
+
|
|
1409
|
+
S = PowerSeriesRing(K, "t", trunc + 1)
|
|
1410
|
+
sigma = S(sigma, trunc+1)
|
|
1411
|
+
|
|
1412
|
+
return sigma
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
def padic_E2(self, p, prec=20, check=False, check_hypotheses=True, algorithm='auto'):
|
|
1416
|
+
r"""
|
|
1417
|
+
Return the value of the `p`-adic modular form `E2`
|
|
1418
|
+
for `(E, \omega)` where `\omega` is the usual
|
|
1419
|
+
invariant differential `dx/(2y + a_1 x + a_3)`.
|
|
1420
|
+
|
|
1421
|
+
INPUT:
|
|
1422
|
+
|
|
1423
|
+
- ``p`` -- prime (= 5) for which `E` is good and ordinary
|
|
1424
|
+
|
|
1425
|
+
- ``prec`` -- (relative) `p`-adic precision (= 1) for result
|
|
1426
|
+
|
|
1427
|
+
- ``check`` -- boolean; whether to perform a consistency check. This will
|
|
1428
|
+
slow down the computation by a constant factor 2. (The consistency check
|
|
1429
|
+
is to compute the whole matrix of frobenius on Monsky-Washnitzer
|
|
1430
|
+
cohomology, and verify that its trace is correct to the specified
|
|
1431
|
+
precision. Otherwise, the trace is used to compute one column from the
|
|
1432
|
+
other one (possibly after a change of basis).)
|
|
1433
|
+
|
|
1434
|
+
- ``check_hypotheses`` -- boolean; whether to check that this is a curve
|
|
1435
|
+
for which the `p`-adic sigma function makes sense
|
|
1436
|
+
|
|
1437
|
+
- ``algorithm`` -- one of ``'standard'``, ``'sqrtp'``, or
|
|
1438
|
+
``'auto'``. This selects which version of Kedlaya's algorithm is used.
|
|
1439
|
+
The ``'standard'`` one is the one described in Kedlaya's paper. The
|
|
1440
|
+
``'sqrtp'`` one has better performance for large `p`, but only
|
|
1441
|
+
works when `p > 6N` (`N=` ``prec``). The ``'auto'`` option
|
|
1442
|
+
selects ``'sqrtp'`` whenever possible.
|
|
1443
|
+
|
|
1444
|
+
Note that if the ``'sqrtp'`` algorithm is used, a consistency check
|
|
1445
|
+
will automatically be applied, regardless of the setting of the
|
|
1446
|
+
``check`` flag.
|
|
1447
|
+
|
|
1448
|
+
OUTPUT: `p`-adic number to precision ``prec``
|
|
1449
|
+
|
|
1450
|
+
.. NOTE::
|
|
1451
|
+
|
|
1452
|
+
If the discriminant of the curve has nonzero valuation at p,
|
|
1453
|
+
then the result will not be returned mod `p^\text{prec}`,
|
|
1454
|
+
but it still *will* have ``prec`` *digits* of precision.
|
|
1455
|
+
|
|
1456
|
+
.. TODO::
|
|
1457
|
+
|
|
1458
|
+
Once we have a better implementation of the "standard"
|
|
1459
|
+
algorithm, the algorithm selection strategy for "auto" needs to be
|
|
1460
|
+
revisited.
|
|
1461
|
+
|
|
1462
|
+
AUTHORS:
|
|
1463
|
+
|
|
1464
|
+
- David Harvey (2006-09-01): partly based on code written
|
|
1465
|
+
by Robert Bradshaw at the MSRI 2006 modular forms workshop
|
|
1466
|
+
|
|
1467
|
+
ACKNOWLEDGMENT: - discussion with Eyal Goren that led to the trace
|
|
1468
|
+
trick.
|
|
1469
|
+
|
|
1470
|
+
EXAMPLES: Here is the example discussed in the paper "Computation
|
|
1471
|
+
of p-adic Heights and Log Convergence" (Mazur, Stein, Tate) [MST2006]_::
|
|
1472
|
+
|
|
1473
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(5) # needs sage.symbolic
|
|
1474
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + 4*5^10 + 2*5^11 + 2*5^12 + 2*5^14 + 3*5^15 + 3*5^16 + 3*5^17 + 4*5^18 + 2*5^19 + O(5^20)
|
|
1475
|
+
|
|
1476
|
+
Let's try to higher precision (this is the same answer the MAGMA
|
|
1477
|
+
implementation gives)::
|
|
1478
|
+
|
|
1479
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 100) # needs sage.symbolic
|
|
1480
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + 4*5^10 + 2*5^11 + 2*5^12 + 2*5^14 + 3*5^15 + 3*5^16 + 3*5^17 + 4*5^18 + 2*5^19 + 4*5^20 + 5^21 + 4*5^22 + 2*5^23 + 3*5^24 + 3*5^26 + 2*5^27 + 3*5^28 + 2*5^30 + 5^31 + 4*5^33 + 3*5^34 + 4*5^35 + 5^36 + 4*5^37 + 4*5^38 + 3*5^39 + 4*5^41 + 2*5^42 + 3*5^43 + 2*5^44 + 2*5^48 + 3*5^49 + 4*5^50 + 2*5^51 + 5^52 + 4*5^53 + 4*5^54 + 3*5^55 + 2*5^56 + 3*5^57 + 4*5^58 + 4*5^59 + 5^60 + 3*5^61 + 5^62 + 4*5^63 + 5^65 + 3*5^66 + 2*5^67 + 5^69 + 2*5^70 + 3*5^71 + 3*5^72 + 5^74 + 5^75 + 5^76 + 3*5^77 + 4*5^78 + 4*5^79 + 2*5^80 + 3*5^81 + 5^82 + 5^83 + 4*5^84 + 3*5^85 + 2*5^86 + 3*5^87 + 5^88 + 2*5^89 + 4*5^90 + 4*5^92 + 3*5^93 + 4*5^94 + 3*5^95 + 2*5^96 + 4*5^97 + 4*5^98 + 2*5^99 + O(5^100)
|
|
1481
|
+
|
|
1482
|
+
Check it works at low precision too::
|
|
1483
|
+
|
|
1484
|
+
sage: # needs sage.symbolic
|
|
1485
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 1)
|
|
1486
|
+
2 + O(5)
|
|
1487
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 2)
|
|
1488
|
+
2 + 4*5 + O(5^2)
|
|
1489
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 3)
|
|
1490
|
+
2 + 4*5 + O(5^3)
|
|
1491
|
+
|
|
1492
|
+
TODO: With the old(-er), i.e., = sage-2.4 `p`-adics we got
|
|
1493
|
+
`5 + O(5^2)` as output, i.e., relative precision 1, but
|
|
1494
|
+
with the newer `p`-adics we get relative precision 0 and absolute
|
|
1495
|
+
precision 1.
|
|
1496
|
+
|
|
1497
|
+
::
|
|
1498
|
+
|
|
1499
|
+
sage: EllipticCurve([1, 1, 1, 1, 1]).padic_E2(5, 1) # needs sage.symbolic
|
|
1500
|
+
O(5)
|
|
1501
|
+
|
|
1502
|
+
Check it works for different models of the same curve (37a), even
|
|
1503
|
+
when the discriminant changes by a power of p (note that E2 depends
|
|
1504
|
+
on the differential too, which is why it gets scaled in some of the
|
|
1505
|
+
examples below)::
|
|
1506
|
+
|
|
1507
|
+
sage: X1 = EllipticCurve([-1, 1/4])
|
|
1508
|
+
sage: X1.j_invariant(), X1.discriminant()
|
|
1509
|
+
(110592/37, 37)
|
|
1510
|
+
sage: X1.padic_E2(5, 10) # needs sage.symbolic
|
|
1511
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
|
|
1512
|
+
|
|
1513
|
+
::
|
|
1514
|
+
|
|
1515
|
+
sage: X2 = EllipticCurve([0, 0, 1, -1, 0])
|
|
1516
|
+
sage: X2.j_invariant(), X2.discriminant()
|
|
1517
|
+
(110592/37, 37)
|
|
1518
|
+
sage: X2.padic_E2(5, 10) # needs sage.symbolic
|
|
1519
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
|
|
1520
|
+
|
|
1521
|
+
::
|
|
1522
|
+
|
|
1523
|
+
sage: X3 = EllipticCurve([-1*(2**4), 1/4*(2**6)])
|
|
1524
|
+
sage: X3.j_invariant(), X3.discriminant() / 2**12
|
|
1525
|
+
(110592/37, 37)
|
|
1526
|
+
sage: 2**(-2) * X3.padic_E2(5, 10) # needs sage.symbolic
|
|
1527
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
|
|
1528
|
+
|
|
1529
|
+
::
|
|
1530
|
+
|
|
1531
|
+
sage: X4 = EllipticCurve([-1*(7**4), 1/4*(7**6)])
|
|
1532
|
+
sage: X4.j_invariant(), X4.discriminant() / 7**12
|
|
1533
|
+
(110592/37, 37)
|
|
1534
|
+
sage: 7**(-2) * X4.padic_E2(5, 10) # needs sage.symbolic
|
|
1535
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
|
|
1536
|
+
|
|
1537
|
+
::
|
|
1538
|
+
|
|
1539
|
+
sage: X5 = EllipticCurve([-1*(5**4), 1/4*(5**6)])
|
|
1540
|
+
sage: X5.j_invariant(), X5.discriminant() / 5**12
|
|
1541
|
+
(110592/37, 37)
|
|
1542
|
+
sage: 5**(-2) * X5.padic_E2(5, 10) # needs sage.symbolic
|
|
1543
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
|
|
1544
|
+
|
|
1545
|
+
::
|
|
1546
|
+
|
|
1547
|
+
sage: X6 = EllipticCurve([-1/(5**4), 1/4/(5**6)])
|
|
1548
|
+
sage: X6.j_invariant(), X6.discriminant() * 5**12
|
|
1549
|
+
(110592/37, 37)
|
|
1550
|
+
sage: 5**2 * X6.padic_E2(5, 10) # needs sage.symbolic
|
|
1551
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
|
|
1552
|
+
|
|
1553
|
+
Test check=True vs check=False::
|
|
1554
|
+
|
|
1555
|
+
sage: # needs sage.symbolic
|
|
1556
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 1, check=False)
|
|
1557
|
+
2 + O(5)
|
|
1558
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 1, check=True)
|
|
1559
|
+
2 + O(5)
|
|
1560
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 30, check=False)
|
|
1561
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + 4*5^10 + 2*5^11 + 2*5^12 + 2*5^14 + 3*5^15 + 3*5^16 + 3*5^17 + 4*5^18 + 2*5^19 + 4*5^20 + 5^21 + 4*5^22 + 2*5^23 + 3*5^24 + 3*5^26 + 2*5^27 + 3*5^28 + O(5^30)
|
|
1562
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 30, check=True)
|
|
1563
|
+
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + 4*5^10 + 2*5^11 + 2*5^12 + 2*5^14 + 3*5^15 + 3*5^16 + 3*5^17 + 4*5^18 + 2*5^19 + 4*5^20 + 5^21 + 4*5^22 + 2*5^23 + 3*5^24 + 3*5^26 + 2*5^27 + 3*5^28 + O(5^30)
|
|
1564
|
+
|
|
1565
|
+
Here's one using the `p^{1/2}` algorithm::
|
|
1566
|
+
|
|
1567
|
+
sage: EllipticCurve([-1, 1/4]).padic_E2(3001, 3, algorithm='sqrtp') # needs sage.symbolic
|
|
1568
|
+
1907 + 2819*3001 + 1124*3001^2 + O(3001^3)
|
|
1569
|
+
"""
|
|
1570
|
+
if self.conductor() % p == 0:
|
|
1571
|
+
if not self.conductor() % (p**2) == 0:
|
|
1572
|
+
eq = self.tate_curve(p)
|
|
1573
|
+
return eq.E2(prec=prec)
|
|
1574
|
+
|
|
1575
|
+
X = self.minimal_model().short_weierstrass_model()
|
|
1576
|
+
frob_p = X.matrix_of_frobenius(p, prec, check, check_hypotheses, algorithm).change_ring(Integers(p**prec))
|
|
1577
|
+
|
|
1578
|
+
frob_p_n = frob_p**prec
|
|
1579
|
+
|
|
1580
|
+
# todo: think about the sign of this. Is it correct?
|
|
1581
|
+
output_ring = Qp(p, prec)
|
|
1582
|
+
|
|
1583
|
+
E2_of_X = output_ring( (-12 * frob_p_n[0,1] / frob_p_n[1,1]).lift() ) \
|
|
1584
|
+
+ O(p**prec)
|
|
1585
|
+
|
|
1586
|
+
# Take into account the coordinate change.
|
|
1587
|
+
fudge_factor = (X.discriminant() / self.discriminant()).nth_root(6)
|
|
1588
|
+
# todo: here I should be able to write:
|
|
1589
|
+
# return E2_of_X / fudge_factor
|
|
1590
|
+
# However, there is a bug in Sage (#51 on trac) which makes this
|
|
1591
|
+
# crash sometimes when prec == 1. For example,
|
|
1592
|
+
# EllipticCurve([1, 1, 1, 1, 1]).padic_E2(5, 1)
|
|
1593
|
+
# makes it crash. I haven't figured out exactly what the bug
|
|
1594
|
+
# is yet, but for now I use the following workaround:
|
|
1595
|
+
fudge_factor_inverse = Qp(p, prec=(E2_of_X.precision_absolute() + 1))(1 / fudge_factor)
|
|
1596
|
+
return output_ring(E2_of_X * fudge_factor_inverse)
|
|
1597
|
+
|
|
1598
|
+
|
|
1599
|
+
def matrix_of_frobenius(self, p, prec=20, check=False, check_hypotheses=True, algorithm='auto'):
|
|
1600
|
+
r"""
|
|
1601
|
+
Return the matrix of Frobenius on the Monsky Washnitzer cohomology of
|
|
1602
|
+
the short Weierstrass model of the minimal model of the elliptic curve.
|
|
1603
|
+
|
|
1604
|
+
INPUT:
|
|
1605
|
+
|
|
1606
|
+
- ``p`` -- prime (>= 3) for which `E` is good and ordinary
|
|
1607
|
+
|
|
1608
|
+
- ``prec`` -- (relative) `p`-adic precision for result (default: 20)
|
|
1609
|
+
|
|
1610
|
+
- ``check`` -- boolean (default: ``False``); whether to perform a
|
|
1611
|
+
consistency check. This will slow down the computation by a
|
|
1612
|
+
constant factor 2. (The consistency check is to verify
|
|
1613
|
+
that its trace is correct to the specified precision. Otherwise,
|
|
1614
|
+
the trace is used to compute one column from the other one
|
|
1615
|
+
(possibly after a change of basis).)
|
|
1616
|
+
|
|
1617
|
+
- ``check_hypotheses`` -- boolean; whether to check that this is a curve
|
|
1618
|
+
for which the `p`-adic sigma function makes sense
|
|
1619
|
+
|
|
1620
|
+
- ``algorithm`` -- one of ``'standard'``, ``'sqrtp'``, or
|
|
1621
|
+
``'auto'``. This selects which version of Kedlaya's algorithm is used.
|
|
1622
|
+
The ``'standard'`` one is the one described in Kedlaya's paper. The
|
|
1623
|
+
``'sqrtp'`` one has better performance for large `p`, but only
|
|
1624
|
+
works when `p > 6N` (`N=` prec). The ``'auto'`` option
|
|
1625
|
+
selects ``'sqrtp'`` whenever possible.
|
|
1626
|
+
|
|
1627
|
+
Note that if the ``'sqrtp'`` algorithm is used, a consistency check
|
|
1628
|
+
will automatically be applied, regardless of the setting of the
|
|
1629
|
+
``check`` flag.
|
|
1630
|
+
|
|
1631
|
+
OUTPUT: a matrix of `p`-adic number to precision ``prec``
|
|
1632
|
+
|
|
1633
|
+
See also the documentation of padic_E2.
|
|
1634
|
+
|
|
1635
|
+
EXAMPLES::
|
|
1636
|
+
|
|
1637
|
+
sage: # needs database_cremona_mini_ellcurve sage.symbolic
|
|
1638
|
+
sage: E = EllipticCurve('37a1')
|
|
1639
|
+
sage: E.matrix_of_frobenius(7)
|
|
1640
|
+
[ 2*7 + 4*7^2 + 5*7^4 + 6*7^5 + 6*7^6 + 7^8 + 4*7^9 + 3*7^10 + 2*7^11 + 5*7^12 + 4*7^14 + 7^16 + 2*7^17 + 3*7^18 + 4*7^19 + 3*7^20 + O(7^21) 2 + 3*7 + 6*7^2 + 7^3 + 3*7^4 + 5*7^5 + 3*7^7 + 7^8 + 3*7^9 + 6*7^13 + 7^14 + 7^16 + 5*7^17 + 4*7^18 + 7^19 + O(7^20)]
|
|
1641
|
+
[ 2*7 + 3*7^2 + 7^3 + 3*7^4 + 6*7^5 + 2*7^6 + 3*7^7 + 5*7^8 + 3*7^9 + 2*7^11 + 6*7^12 + 5*7^13 + 4*7^16 + 4*7^17 + 6*7^18 + 6*7^19 + 4*7^20 + O(7^21) 6 + 4*7 + 2*7^2 + 6*7^3 + 7^4 + 6*7^7 + 5*7^8 + 2*7^9 + 3*7^10 + 4*7^11 + 7^12 + 6*7^13 + 2*7^14 + 6*7^15 + 5*7^16 + 4*7^17 + 3*7^18 + 2*7^19 + O(7^20)]
|
|
1642
|
+
sage: M = E.matrix_of_frobenius(11,prec=3); M
|
|
1643
|
+
[ 9*11 + 9*11^3 + O(11^4) 10 + 11 + O(11^3)]
|
|
1644
|
+
[ 2*11 + 11^2 + O(11^4) 6 + 11 + 10*11^2 + O(11^3)]
|
|
1645
|
+
sage: M.det()
|
|
1646
|
+
11 + O(11^4)
|
|
1647
|
+
sage: M.trace()
|
|
1648
|
+
6 + 10*11 + 10*11^2 + O(11^3)
|
|
1649
|
+
sage: E.ap(11)
|
|
1650
|
+
-5
|
|
1651
|
+
sage: E = EllipticCurve('83a1')
|
|
1652
|
+
sage: E.matrix_of_frobenius(3,6)
|
|
1653
|
+
[ 2*3 + 3^5 + O(3^6) 2*3 + 2*3^2 + 2*3^3 + O(3^6)]
|
|
1654
|
+
[ 2*3 + 3^2 + 2*3^5 + O(3^6) 2 + 2*3^2 + 2*3^3 + 2*3^4 + 3^5 + O(3^6)]
|
|
1655
|
+
"""
|
|
1656
|
+
p = Integer(p)
|
|
1657
|
+
prec = int(prec)
|
|
1658
|
+
|
|
1659
|
+
if p < 3:
|
|
1660
|
+
raise NotImplementedError("p (=%s) must be at least 3" % p)
|
|
1661
|
+
if prec < 1:
|
|
1662
|
+
raise ValueError("prec (=%s) must be at least 1" % prec)
|
|
1663
|
+
|
|
1664
|
+
if check_hypotheses:
|
|
1665
|
+
p = __check_padic_hypotheses(self, p)
|
|
1666
|
+
|
|
1667
|
+
if algorithm == "auto":
|
|
1668
|
+
algorithm = "standard" if p < 6*prec else "sqrtp"
|
|
1669
|
+
elif algorithm == "sqrtp" and p < 6*prec:
|
|
1670
|
+
raise ValueError("sqrtp algorithm is only available when p > 6*prec")
|
|
1671
|
+
|
|
1672
|
+
if algorithm not in ["standard", "sqrtp"]:
|
|
1673
|
+
raise ValueError("unknown algorithm '%s'" % algorithm)
|
|
1674
|
+
|
|
1675
|
+
# for p = 3, we create the corresponding hyperelliptic curve
|
|
1676
|
+
# and call matrix of frobenius on it
|
|
1677
|
+
if p == 3:
|
|
1678
|
+
from sage.schemes.hyperelliptic_curves.constructor import HyperellipticCurve
|
|
1679
|
+
f,g = self.hyperelliptic_polynomials()
|
|
1680
|
+
return HyperellipticCurve(f + (g/2)**2).matrix_of_frobenius(p,prec)
|
|
1681
|
+
|
|
1682
|
+
# To run matrix_of_frobenius(), we need to have the equation in the
|
|
1683
|
+
# form y^2 = x^3 + ax + b, whose discriminant is invertible mod p.
|
|
1684
|
+
# When we change coordinates like this, we might scale the invariant
|
|
1685
|
+
# differential, so we need to account for this. We do this by
|
|
1686
|
+
# comparing discriminants: if the discriminants differ by u^12,
|
|
1687
|
+
# then the differentials differ by u. There's a sign ambiguity here,
|
|
1688
|
+
# but it doesn't matter because E2 changes by u^2 :-)
|
|
1689
|
+
|
|
1690
|
+
# todo: In fact, there should be available a function that returns
|
|
1691
|
+
# exactly *which* coordinate change was used. If I had that I could
|
|
1692
|
+
# avoid the discriminant circus at the end.
|
|
1693
|
+
|
|
1694
|
+
# todo: The following strategy won't work at all for p = 2, 3.
|
|
1695
|
+
|
|
1696
|
+
# TODO change the basis back to the original equation.
|
|
1697
|
+
X = self.minimal_model().short_weierstrass_model()
|
|
1698
|
+
|
|
1699
|
+
assert X.discriminant().valuation(p) == 0, "Something's gone wrong. " \
|
|
1700
|
+
"The discriminant of the Weierstrass model should be a unit " \
|
|
1701
|
+
" at p."
|
|
1702
|
+
|
|
1703
|
+
if algorithm == "standard":
|
|
1704
|
+
# Need to increase precision a little to compensate for precision
|
|
1705
|
+
# losses during the computation. (See monsky_washnitzer.py
|
|
1706
|
+
# for more details.)
|
|
1707
|
+
adjusted_prec = mw_adjusted_prec(p, prec)
|
|
1708
|
+
|
|
1709
|
+
if check:
|
|
1710
|
+
trace = None
|
|
1711
|
+
else:
|
|
1712
|
+
trace = self.ap(p)
|
|
1713
|
+
|
|
1714
|
+
base_ring = Integers(p**adjusted_prec)
|
|
1715
|
+
|
|
1716
|
+
R, x = PolynomialRing(base_ring, 'x').objgen()
|
|
1717
|
+
Q = x**3 + base_ring(X.a4()) * x + base_ring(X.a6())
|
|
1718
|
+
frob_p = mw_matrix_of_frobenius(Q, p, adjusted_prec, trace)
|
|
1719
|
+
|
|
1720
|
+
else: # algorithm == "sqrtp"
|
|
1721
|
+
p_to_prec = p**prec
|
|
1722
|
+
R = PolynomialRing(Integers(), "x")
|
|
1723
|
+
Q = R([X.a6() % p_to_prec, X.a4() % p_to_prec, 0, 1])
|
|
1724
|
+
frob_p = hypellfrob(p, prec, Q)
|
|
1725
|
+
|
|
1726
|
+
# let's force a trace-check since this algorithm is fairly new
|
|
1727
|
+
# and we don't want to get caught with our pants down...
|
|
1728
|
+
trace = self.ap(p)
|
|
1729
|
+
check = True
|
|
1730
|
+
|
|
1731
|
+
if check:
|
|
1732
|
+
trace_of_frobenius = frob_p.trace().lift() % p**prec
|
|
1733
|
+
correct_trace = self.ap(p) % p**prec
|
|
1734
|
+
assert trace_of_frobenius == correct_trace, \
|
|
1735
|
+
"Consistency check failed! (correct = %s, actual = %s)" % \
|
|
1736
|
+
(correct_trace, trace_of_frobenius)
|
|
1737
|
+
|
|
1738
|
+
return frob_p.change_ring(Zp(p, prec))
|
|
1739
|
+
|
|
1740
|
+
|
|
1741
|
+
def _brent(F, p, N):
|
|
1742
|
+
r"""
|
|
1743
|
+
This is an internal function; it is used by padic_sigma().
|
|
1744
|
+
|
|
1745
|
+
`F` is a assumed to be a power series over `R = \ZZ/p^{N-1}\ZZ`.
|
|
1746
|
+
|
|
1747
|
+
It solves the differential equation `G'(t)/G(t) = F(t)`
|
|
1748
|
+
using Brent's algorithm, with initial condition `G(0) = 1`.
|
|
1749
|
+
It is assumed that the solution `G` has `p`-integral coefficients.
|
|
1750
|
+
|
|
1751
|
+
More precisely, suppose that `f(t)` is a power series with
|
|
1752
|
+
genuine `p`-adic coefficients, and suppose that
|
|
1753
|
+
`g(t)` is an exact solution to `g'(t)/g(t) = f(t)`.
|
|
1754
|
+
Let `I` be the ideal
|
|
1755
|
+
`(p^N, p^{N-1} t, \ldots, p t^{N-1}, t^N)`. The input
|
|
1756
|
+
`F(t)` should be a finite-precision approximation to
|
|
1757
|
+
`f(t)`, in the sense that `\int (F - f) dt` should
|
|
1758
|
+
lie in `I`. Then the function returns a series
|
|
1759
|
+
`G(t)` such that `(G - g)(t)` lies in `I`.
|
|
1760
|
+
|
|
1761
|
+
Complexity should be about `O(N^2 \log^2 N \log p)`, plus
|
|
1762
|
+
some log-log factors.
|
|
1763
|
+
|
|
1764
|
+
For more information, and a proof of the precision guarantees, see
|
|
1765
|
+
Lemma 4 in [Har2009]_.
|
|
1766
|
+
|
|
1767
|
+
AUTHORS:
|
|
1768
|
+
|
|
1769
|
+
- David Harvey (2007-02)
|
|
1770
|
+
|
|
1771
|
+
EXAMPLES: Carefully test the precision guarantees::
|
|
1772
|
+
|
|
1773
|
+
sage: brent = sage.schemes.elliptic_curves.padics._brent
|
|
1774
|
+
sage: for p in [2, 3, 5]:
|
|
1775
|
+
....: for N in [2, 3, 10, 50]:
|
|
1776
|
+
....: R = Integers(p**(N-1))
|
|
1777
|
+
....: Rx.<x> = PowerSeriesRing(R, "x")
|
|
1778
|
+
....: for _ in range(5):
|
|
1779
|
+
....: g = [R.random_element() for i in range(N)]
|
|
1780
|
+
....: g[0] = R(1)
|
|
1781
|
+
....: g = Rx(g, len(g))
|
|
1782
|
+
....: f = g.derivative() / g
|
|
1783
|
+
....: # perturb f by something whose integral is in I
|
|
1784
|
+
....: err = [R.random_element() * p**(N-i) for i in range(N+1)]
|
|
1785
|
+
....: err = Rx(err, len(err))
|
|
1786
|
+
....: err = err.derivative()
|
|
1787
|
+
....: F = f + err
|
|
1788
|
+
....: # run brent() and compare output modulo I
|
|
1789
|
+
....: G = brent(F, p, N)
|
|
1790
|
+
....: assert G.prec() >= N, "not enough output terms"
|
|
1791
|
+
....: err = (G - g).list()
|
|
1792
|
+
....: for i in range(len(err)):
|
|
1793
|
+
....: assert err[i].lift().valuation(p) >= (N - i), \
|
|
1794
|
+
....: "incorrect precision output"
|
|
1795
|
+
"""
|
|
1796
|
+
Rx = F.parent() # Rx = power series ring over Z/p^{N-1} Z
|
|
1797
|
+
Qx = PowerSeriesRing(RationalField(), "x")
|
|
1798
|
+
|
|
1799
|
+
# initial approximation:
|
|
1800
|
+
G = Rx.one()
|
|
1801
|
+
|
|
1802
|
+
from sage.misc.misc import newton_method_sizes
|
|
1803
|
+
|
|
1804
|
+
# loop over an appropriate increasing sequence of lengths s
|
|
1805
|
+
for s in newton_method_sizes(N):
|
|
1806
|
+
# zero-extend to s terms
|
|
1807
|
+
# todo: there has to be a better way in Sage to do this...
|
|
1808
|
+
G = Rx(G.list(), s)
|
|
1809
|
+
|
|
1810
|
+
# extend current approximation to be correct to s terms
|
|
1811
|
+
H = G.derivative() / G - F
|
|
1812
|
+
# Do the integral of H over QQ[x] to avoid division by p problems
|
|
1813
|
+
H = Rx(Qx(H).integral())
|
|
1814
|
+
G = G * (1 - H)
|
|
1815
|
+
|
|
1816
|
+
return G
|