Path: blob/master/sage/schemes/elliptic_curves/padics.py
4128 views
# -*- coding: utf-8 -*-1"""2Miscellaneous p-adic functions34p-adic functions from ell_rational_field.py, moved here to reduce5crowding in that file.6"""78######################################################################9# Copyright (C) 2007 William Stein <[email protected]>10#11# Distributed under the terms of the GNU General Public License (GPL)12#13# This code is distributed in the hope that it will be useful,14# but WITHOUT ANY WARRANTY; without even the implied warranty of15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU16# General Public License for more details.17#18# The full text of the GPL is available at:19#20# http://www.gnu.org/licenses/21######################################################################222324import sage.rings.all as rings25import padic_lseries as plseries26import sage.rings.arith as arith27from sage.rings.all import (28Qp, Zp,29Integers,30Integer,31O,32PowerSeriesRing,33LaurentSeriesRing,34RationalField)35import math36import sage.misc.misc as misc37import sage.matrix.all as matrix38sqrt = math.sqrt39import monsky_washnitzer40import sage.schemes.hyperelliptic_curves.hypellfrob4142def __check_padic_hypotheses(self, p):43r"""44Helper function that determines if `p`45is an odd prime of good ordinary reduction.4647EXAMPLES::48sage: E = EllipticCurve('11a1')49sage: from sage.schemes.elliptic_curves.padics import __check_padic_hypotheses50sage: __check_padic_hypotheses(E,5)51552sage: __check_padic_hypotheses(E,29)53Traceback (most recent call last):54...55ArithmeticError: p must be a good ordinary prime5657"""58p = rings.Integer(p)59if not p.is_prime():60raise ValueError, "p = (%s) must be prime"%p61if p == 2:62raise ValueError, "p must be odd"63if self.conductor() % p == 0 or self.ap(p) % p == 0:64raise ArithmeticError, "p must be a good ordinary prime"65return p666768def padic_lseries(self, p, normalize='L_ratio', use_eclib=False):69r"""70Return the `p`-adic `L`-series of self at71`p`, which is an object whose approx method computes72approximation to the true `p`-adic `L`-series to73any desired precision.7475INPUT:767778- ``p`` - prime7980- ``use_eclib`` - bool (default:False); whether or not to use81John Cremona's eclib for the computation of modular82symbols8384- ``normalize`` - 'L_ratio' (default), 'period' or 'none';85this is describes the way the modular symbols86are normalized. See modular_symbol for87more details.888990EXAMPLES::9192sage: E = EllipticCurve('37a')93sage: L = E.padic_lseries(5); L945-adic L-series of Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field95sage: type(L)96<class 'sage.schemes.elliptic_curves.padic_lseries.pAdicLseriesOrdinary'>9798We compute the `3`-adic `L`-series of two curves of99rank `0` and in each case verify the interpolation property100for their leading coefficient (i.e., value at 0)::101102sage: e = EllipticCurve('11a')103sage: ms = e.modular_symbol()104sage: [ms(1/11), ms(1/3), ms(0), ms(oo)]105[0, -3/10, 1/5, 0]106sage: ms(0)1071/5108sage: L = e.padic_lseries(3)109sage: P = L.series(5)110sage: P(0)1112 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7)112sage: alpha = L.alpha(9); alpha1132 + 3^2 + 2*3^3 + 2*3^4 + 2*3^6 + 3^8 + O(3^9)114sage: R.<x> = QQ[]115sage: f = x^2 - e.ap(3)*x + 3116sage: f(alpha)117O(3^9)118sage: r = e.lseries().L_ratio(); r1191/5120sage: (1 - alpha^(-1))^2 * r1212 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + 3^7 + O(3^9)122sage: P(0)1232 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7)124125Next consider the curve 37b::126127sage: e = EllipticCurve('37b')128sage: L = e.padic_lseries(3)129sage: P = L.series(5)130sage: alpha = L.alpha(9); alpha1311 + 2*3 + 3^2 + 2*3^5 + 2*3^7 + 3^8 + O(3^9)132sage: r = e.lseries().L_ratio(); r1331/3134sage: (1 - alpha^(-1))^2 * r1353 + 3^2 + 2*3^4 + 2*3^5 + 2*3^6 + 3^7 + O(3^9)136sage: P(0)1373 + 3^2 + 2*3^4 + 2*3^5 + O(3^6)138139We can use eclib to compute the `L`-series::140141sage: e = EllipticCurve('11a')142sage: L = e.padic_lseries(3,use_eclib=True)143sage: L.series(5,prec=10) # NOTE: Output below prints slightly incorrectly -- see trac 10280!1442 + 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 + (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 + (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 + (2 + 2*3 + 2*3^2 + O(3^3))*T^8 + (2 + O(3^2))*T^9 + O(T^10)145146"""147key = (p, normalize)148try:149return self._padic_lseries[key]150except AttributeError:151self._padic_lseries = {}152except KeyError:153pass154155if self.ap(p) % p != 0:156Lp = plseries.pAdicLseriesOrdinary(self, p,157normalize = normalize, use_eclib=use_eclib)158else:159Lp = plseries.pAdicLseriesSupersingular(self, p,160normalize = normalize, use_eclib=use_eclib)161self._padic_lseries[key] = Lp162return Lp163164165def padic_regulator(self, p, prec=20, height=None, check_hypotheses=True):166r"""167Computes the cyclotomic p-adic regulator of this curve.168169170INPUT:171172173- ``p`` - prime = 5174175- ``prec`` - answer will be returned modulo176`p^{\mathrm{prec}}`177178- ``height`` - precomputed height function. If not179supplied, this function will call padic_height to compute it.180181- ``check_hypotheses`` - boolean, whether to check182that this is a curve for which the p-adic height makes sense183184185OUTPUT: The p-adic cyclotomic regulator of this curve, to the186requested precision.187188If the rank is 0, we output 1.189190TODO: - remove restriction that curve must be in minimal191Weierstrass form. This is currently required for E.gens().192193AUTHORS:194195- Liang Xiao: original implementation at the 2006 MSRI196graduate workshop on modular forms197198- David Harvey (2006-09-13): cleaned up and integrated into Sage,199removed some redundant height computations200201- Chris Wuthrich (2007-05-22): added multiplicative and202supersingular cases203204- David Harvey (2007-09-20): fixed some precision loss that was205occurring206207EXAMPLES::208209sage: E = EllipticCurve("37a")210sage: E.padic_regulator(5, 10)2115 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)212213An anomalous case::214215sage: E.padic_regulator(53, 10)21626*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)217218An anomalous case where the precision drops some::219220sage: E = EllipticCurve("5077a")221sage: E.padic_regulator(5, 10)2225 + 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)223224Check that answers agree over a range of precisions::225226sage: max_prec = 30 # make sure we get past p^2 # long time227sage: full = E.padic_regulator(5, max_prec) # long time228sage: for prec in range(1, max_prec): # long time229... assert E.padic_regulator(5, prec) == full # long time230231A case where the generator belongs to the formal group already232(trac #3632)::233234sage: E = EllipticCurve([37,0])235sage: E.padic_regulator(5,10)2362*5^2 + 2*5^3 + 5^4 + 5^5 + 4*5^6 + 3*5^8 + 4*5^9 + O(5^10)237238The result is not dependent on the model for the curve::239240sage: E = EllipticCurve([0,0,0,0,2^12*17])241sage: Em = E.minimal_model()242sage: E.padic_regulator(7) == Em.padic_regulator(7)243True244245Allow a Python int as input::246247sage: E = EllipticCurve('37a')248sage: E.padic_regulator(int(5))2495 + 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)250"""251p = Integer(p) # this is assumed in code below252if check_hypotheses:253if not p.is_prime():254raise ValueError, "p = (%s) must be prime"%p255if p == 2:256raise ValueError, "p must be odd" # todo257if self.conductor() % (p**2) == 0:258raise ArithmeticError, "p must be a semi-stable prime"259260if self.conductor() % p == 0:261Eq = self.tate_curve(p)262reg = Eq.padic_regulator(prec=prec)263return reg264elif self.ap(p) % p == 0:265lp = self.padic_lseries(p)266reg = lp.Dp_valued_regulator(prec=prec)267return reg268else:269if self.rank() == 0:270return Qp(p,prec)(1)271if height is None:272height = self.padic_height(p, prec, check_hypotheses=False)273d = self.padic_height_pairing_matrix(p=p, prec=prec, height=height, check_hypotheses=False)274return d.determinant()275276277def padic_height_pairing_matrix(self, p, prec=20, height=None, check_hypotheses=True):278r"""279Computes the cyclotomic `p`-adic height pairing matrix of280this curve with respect to the basis self.gens() for the281Mordell-Weil group for a given odd prime p of good ordinary282reduction.283284INPUT:285286287- ``p`` - prime = 5288289- ``prec`` - answer will be returned modulo290`p^{\mathrm{prec}}`291292- ``height`` - precomputed height function. If not293supplied, this function will call padic_height to compute it.294295- ``check_hypotheses`` - boolean, whether to check296that this is a curve for which the p-adic height makes sense297298299OUTPUT: The p-adic cyclotomic height pairing matrix of this curve300to the given precision.301302TODO: - remove restriction that curve must be in minimal303Weierstrass form. This is currently required for E.gens().304305AUTHORS:306307- David Harvey, Liang Xiao, Robert Bradshaw, Jennifer308Balakrishnan: original implementation at the 2006 MSRI graduate309workshop on modular forms310311- David Harvey (2006-09-13): cleaned up and integrated into Sage,312removed some redundant height computations313314EXAMPLES::315316sage: E = EllipticCurve("37a")317sage: E.padic_height_pairing_matrix(5, 10)318[5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)]319320A rank two example::321322sage: e =EllipticCurve('389a')323sage: e._set_gens([e(-1, 1), e(1,0)]) # avoid platform dependent gens324sage: e.padic_height_pairing_matrix(5,10)325[ 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)]326[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)]327328An anomalous rank 3 example::329330sage: e = EllipticCurve("5077a")331sage: e._set_gens([e(-1,3), e(2,0), e(4,6)])332sage: e.padic_height_pairing_matrix(5,4)333[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)]334[ 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)]335[ 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)]336337"""338if check_hypotheses:339p = __check_padic_hypotheses(self, p)340341K = Qp(p, prec=prec)342343rank = self.rank()344M = matrix.matrix(K, rank, rank, 0)345if rank == 0:346return M347348basis = self.gens()349350if height is None:351height = self.padic_height(p, prec, check_hypotheses=False)352353# Use <P, Q> =1/2*( h(P + Q) - h(P) - h(Q) )354355for i in range(rank):356M[i,i] = height(basis[i])357for i in range(rank):358for j in range(i+1, rank):359M[i, j] = ( height(basis[i] + basis[j]) - M[i,i] - M[j,j] ) / 2360M[j, i] = M[i, j]361362return M363364def _multiply_point(E, R, P, m):365r"""366Computes coordinates of a multiple of P with entries in a ring.367368INPUT:369370371- ``E`` - elliptic curve over Q with integer372coefficients373374- ``P`` - a rational point on P that reduces to a375non-singular point at all primes376377- ``R`` - a ring in which 2 is invertible (typically378`\ZZ/L\ZZ` for some positive odd integer379`L`).380381- ``m`` - an integer, = 1382383384OUTPUT: A triple `(a', b', d')` such that if the point385`mP` has coordinates `(a/d^2, b/d^3)`, then we have386`a' \equiv a`, `b' \equiv \pm b`,387`d' \equiv \pm d` all in `R` (i.e. modulo388`L`).389390Note the ambiguity of signs for `b'` and `d'`.391There's not much one can do about this, but at least one can say392that the sign for `b'` will match the sign for393`d'`.394395ALGORITHM: Proposition 9 of "Efficient Computation of p-adic396Heights" (David Harvey, to appear in LMS JCM).397398Complexity is soft-`O(\log L \log m + \log^2 m)`.399400AUTHORS:401402- David Harvey (2008-01): replaced _DivPolyContext with403_multiply_point404405EXAMPLES:40640737a has trivial Tamagawa numbers so all points have nonsingular408reduction at all primes::409410sage: E = EllipticCurve("37a")411sage: P = E([0, -1]); P412(0 : -1 : 1)413sage: 19*P414(-59997896/67387681 : 88075171080/553185473329 : 1)415sage: R = Integers(625)416sage: from sage.schemes.elliptic_curves.padics import _multiply_point417sage: _multiply_point(E, R, P, 19)418(229, 170, 541)419sage: -59997896 % 625420229421sage: -88075171080 % 625 # note sign is flipped422170423sage: -67387681.sqrt() % 625 # sign is flipped here too424541425426Trivial cases (trac 3632)::427428sage: _multiply_point(E, R, P, 1)429(0, 624, 1)430sage: _multiply_point(E, R, 19*P, 1)431(229, 455, 84)432sage: (170 + 455) % 625 # note the sign did not flip here4330434sage: (541 + 84) % 6254350436437Test over a range of `n` for a single curve with fairly438random coefficients::439440sage: R = Integers(625)441sage: E = EllipticCurve([4, -11, 17, -8, -10])442sage: P = E.gens()[0] * LCM(E.tamagawa_numbers())443sage: from sage.schemes.elliptic_curves.padics import _multiply_point444sage: Q = P445sage: for n in range(1, 25):446... naive = R(Q[0].numerator()), \447... R(Q[1].numerator()), \448... R(Q[0].denominator().sqrt())449... triple = _multiply_point(E, R, P, n)450... assert (triple[0] == naive[0]) and ( \451... (triple[1] == naive[1] and triple[2] == naive[2]) or \452... (triple[1] == -naive[1] and triple[2] == -naive[2])), \453... "_multiply_point() gave an incorrect answer"454... Q = Q + P455"""456assert m >= 1457458alpha = R(P[0].numerator())459beta = R(P[1].numerator())460d = R(P[0].denominator().sqrt())461if m == 1:462return alpha, beta, d463464a1 = R(E.a1()) * d465a3 = R(E.a3()) * d**3466467b2 = R(E.b2()) * d**2468b4 = R(E.b4()) * d**4469b6 = R(E.b6()) * d**6470b8 = R(E.b8()) * d**8471472B4 = 6*alpha**2 + b2*alpha + b4473B6 = 4*alpha**3 + b2*alpha**2 + 2*b4*alpha + b6474B6_sqr = B6*B6475B8 = 3*alpha**4 + b2*alpha**3 + 3*b4*alpha**2 + 3*b6*alpha + b8476477T = 2*beta + a1*alpha + a3478479# make a list of disjoint intervals [a[i], b[i]) such that we need to480# compute g(k) for all a[i] <= k <= b[i] for each i481intervals = []482interval = (m - 2, m + 3)483while interval[0] < interval[1]:484intervals.append(interval)485interval = max((interval[0] - 3) >> 1, 0), \486min((interval[1] + 5) >> 1, interval[0])487488# now walk through list and compute g(k)489g = {0 : R(0), 1 : R(1), 2 : R(-1), 3 : B8, 4 : B6**2 - B4*B8}490last = [0, 1, 2, 3, 4] # last few k491for i in reversed(intervals):492k = i[0]493while k < i[1]:494if k > 4:495j = k >> 1496if k & 1:497t1 = g[j]498t2 = g[j+1]499prod1 = g[j+2] * t1*t1*t1500prod2 = g[j-1] * t2*t2*t2501g[k] = prod1 - B6_sqr * prod2 if j & 1 else B6_sqr * prod1 - prod2502else:503t1 = g[j-1]504t2 = g[j+1]505g[k] = g[j] * (g[j-2] * t2*t2 - g[j+2] * t1*t1)506k = k + 1507508if m & 1:509psi_m = g[m]510psi_m_m1 = g[m-1] * T511psi_m_p1 = g[m+1] * T512else:513psi_m = g[m] * T514psi_m_m1 = g[m-1]515psi_m_p1 = g[m+1]516517theta = alpha * psi_m * psi_m - psi_m_m1 * psi_m_p1518t1 = g[m-2] * g[m+1] * g[m+1] - g[m+2] * g[m-1] * g[m-1]519if m & 1:520t1 = t1 * T521omega = (t1 + (a1 * theta + a3 * psi_m * psi_m) * psi_m) / -2522523return theta, omega, psi_m * d524525526527def padic_height(self, p, prec=20, sigma=None, check_hypotheses=True):528r"""529Computes the cyclotomic p-adic height.530531The equation of the curve must be minimal at `p`.532533INPUT:534535536- ``p`` - prime = 5 for which the curve has537semi-stable reduction538539- ``prec`` - integer = 1, desired precision of result540541- ``sigma`` - precomputed value of sigma. If not542supplied, this function will call padic_sigma to compute it.543544- ``check_hypotheses`` - boolean, whether to check545that this is a curve for which the p-adic height makes sense546547548OUTPUT: A function that accepts two parameters:549550- a Q-rational point on the curve whose height should be computed551552- optional boolean flag 'check': if False, it skips some input553checking, and returns the p-adic height of that point to the554desired precision.555556- The normalization (sign and a factor 1/2 with respect to some other557normalizations that appear in the literature) is chosen in such a way558as to make the p-adic Birch Swinnerton-Dyer conjecture hold as stated559in [Mazur-Tate-Teitelbaum].560561AUTHORS:562563- Jennifer Balakrishnan: original code developed at the 2006 MSRI564graduate workshop on modular forms565566- David Harvey (2006-09-13): integrated into Sage, optimised to567speed up repeated evaluations of the returned height function,568addressed some thorny precision questions569570- David Harvey (2006-09-30): rewrote to use division polynomials571for computing denominator of `nP`.572573- David Harvey (2007-02): cleaned up according to algorithms in574"Efficient Computation of p-adic Heights"575576- Chris Wuthrich (2007-05): added supersingular and multiplicative heights577578EXAMPLES::579580sage: E = EllipticCurve("37a")581sage: P = E.gens()[0]582sage: h = E.padic_height(5, 10)583sage: h(P)5845 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)585586An anomalous case::587588sage: h = E.padic_height(53, 10)589sage: h(P)59026*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)591592Boundary case::593594sage: E.padic_height(5, 3)(P)5955 + 5^2 + O(5^3)596597A case that works the division polynomial code a little harder::598599sage: E.padic_height(5, 10)(5*P)6005^3 + 5^4 + 5^5 + 3*5^8 + 4*5^9 + O(5^10)601602Check that answers agree over a range of precisions::603604sage: max_prec = 30 # make sure we get past p^2 # long time605sage: full = E.padic_height(5, max_prec)(P) # long time606sage: for prec in range(1, max_prec): # long time607... assert E.padic_height(5, prec)(P) == full # long time608609A supersingular prime for a curve::610611sage: E = EllipticCurve('37a')612sage: E.is_supersingular(3)613True614sage: h = E.padic_height(3, 5)615sage: h(E.gens()[0])616(3 + 3^3 + O(3^6), 2*3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + O(3^7))617sage: E.padic_regulator(5)6185 + 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)619sage: E.padic_regulator(3, 5)620(3 + 2*3^2 + 3^3 + O(3^4), 3^2 + 2*3^3 + 3^4 + O(3^5))621622A torsion point in both the good and supersingular cases::623624sage: E = EllipticCurve('11a')625sage: P = E.torsion_subgroup().gen(0).element(); P626(5 : 5 : 1)627sage: h = E.padic_height(19, 5)628sage: h(P)6290630sage: h = E.padic_height(5, 5)631sage: h(P)6320633634The result is not dependent on the model for the curve::635636sage: E = EllipticCurve([0,0,0,0,2^12*17])637sage: Em = E.minimal_model()638sage: P = E.gens()[0]639sage: Pm = Em.gens()[0]640sage: h = E.padic_height(7)641sage: hm = Em.padic_height(7)642sage: h(P) == hm(Pm)643True644"""645if check_hypotheses:646if not p.is_prime():647raise ValueError, "p = (%s) must be prime"%p648if p == 2:649raise ValueError, "p must be odd" # todo650if self.conductor() % (p**2) == 0:651raise ArithmeticError, "p must be a semi-stable prime"652653prec = int(prec)654if prec < 1:655raise ValueError, "prec (=%s) must be at least 1" % prec656657if self.conductor() % p == 0:658Eq = self.tate_curve(p,prec=prec)659return Eq.height(prec=prec)660elif self.ap(p) % p == 0:661lp = self.padic_lseries(p)662return lp.Dp_valued_height(prec=prec)663664# else good ordinary case665666# For notation and definitions, see "Efficient Computation of667# p-adic Heights", David Harvey (unpublished)668669n1 = self.change_ring(rings.GF(p)).cardinality()670n2 = arith.LCM(self.tamagawa_numbers())671n = arith.LCM(n1, n2)672m = int(n / n2)673674adjusted_prec = prec + 2 * arith.valuation(n, p) # this is M'675R = rings.Integers(p ** adjusted_prec)676677if sigma is None:678sigma = self.padic_sigma(p, adjusted_prec, check_hypotheses=False)679680# K is the field for the final result681K = Qp(p, prec=adjusted_prec-1)682E = self683684def height(P, check=True):685if P.is_finite_order():686return K(0)687688if check:689assert P.curve() == E, "the point P must lie on the curve " \690"from which the height function was created"691692Q = n2 * P693alpha, beta, d = _multiply_point(E, R, Q, m)694695assert beta.lift() % p != 0, "beta should be a unit!"696assert d.lift() % p == 0, "d should not be a unit!"697698t = -d * alpha / beta699700total = R(1)701t_power = t702for k in range(2, adjusted_prec + 1):703total = total + t_power * sigma[k].lift()704t_power = t_power * t705total = (-alpha / beta) * total706707L = Qp(p, prec=adjusted_prec)708total = L(total.lift(), adjusted_prec) # yuck... get rid of this lift!709710# changed sign to make it correct for p-adic bsd711answer = -total.log() * 2 / n**2712713if check:714assert answer.precision_absolute() >= prec, "we should have got an " \715"answer with precision at least prec, but we didn't."716return K(answer)717718719# (man... I love python's local function definitions...)720return height721722723724def padic_height_via_multiply(self, p, prec=20, E2=None, check_hypotheses=True):725r"""726Computes the cyclotomic p-adic height.727728The equation of the curve must be minimal at `p`.729730INPUT:731732733- ``p`` - prime = 5 for which the curve has good734ordinary reduction735736- ``prec`` - integer = 2, desired precision of result737738- ``E2`` - precomputed value of E2. If not supplied,739this function will call padic_E2 to compute it. The value supplied740must be correct mod `p^(prec-2)` (or slightly higher in the741anomalous case; see the code for details).742743- ``check_hypotheses`` - boolean, whether to check744that this is a curve for which the p-adic height makes sense745746747OUTPUT: A function that accepts two parameters:748749- a Q-rational point on the curve whose height should be computed750751- optional boolean flag 'check': if False, it skips some input752checking, and returns the p-adic height of that point to the753desired precision.754755- The normalization (sign and a factor 1/2 with respect to some other756normalizations that appear in the literature) is chosen in such a way757as to make the p-adic Birch Swinnerton-Dyer conjecture hold as stated758in [Mazur-Tate-Teitelbaum].759760AUTHORS:761762- David Harvey (2008-01): based on the padic_height() function,763using the algorithm of"Computing p-adic heights via764point multiplication"765766EXAMPLES::767768sage: E = EllipticCurve("37a")769sage: P = E.gens()[0]770sage: h = E.padic_height_via_multiply(5, 10)771sage: h(P)7725 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)773774An anomalous case::775776sage: h = E.padic_height_via_multiply(53, 10)777sage: h(P)77826*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)779780Supply the value of E2 manually::781782sage: E2 = E.padic_E2(5, 8)783sage: E27842 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + O(5^8)785sage: h = E.padic_height_via_multiply(5, 10, E2=E2)786sage: h(P)7875 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)788789Boundary case::790791sage: E.padic_height_via_multiply(5, 3)(P)7925 + 5^2 + O(5^3)793794Check that answers agree over a range of precisions::795796sage: max_prec = 30 # make sure we get past p^2 # long time797sage: full = E.padic_height(5, max_prec)(P) # long time798sage: for prec in range(2, max_prec): # long time799... assert E.padic_height_via_multiply(5, prec)(P) == full # long time800"""801if check_hypotheses:802if not p.is_prime():803raise ValueError, "p = (%s) must be prime"%p804if p == 2:805raise ValueError, "p must be odd" # todo806if self.conductor() % p == 0:807raise ArithmeticError, "must have good reduction at p"808if self.ap(p) % p == 0:809raise ArithmeticError, "must be ordinary at p"810811prec = int(prec)812if prec < 1:813raise ValueError, "prec (=%s) must be at least 1" % prec814815# For notation and definitions, see ``Computing p-adic heights via point816# multiplication'' (David Harvey, still in draft form)817818n1 = self.change_ring(rings.GF(p)).cardinality()819n2 = arith.LCM(self.tamagawa_numbers())820n = arith.LCM(n1, n2)821m = int(n / n2)822823lamb = int(math.floor(math.sqrt(prec)))824825adjusted_prec = prec + 2 * arith.valuation(n, p) # this is M'826R = rings.Integers(p ** (adjusted_prec + 2*lamb))827828sigma = self.padic_sigma_truncated(p, N=adjusted_prec, E2=E2, lamb=lamb)829830# K is the field for the final result831K = Qp(p, prec=adjusted_prec-1)832E = self833834def height(P, check=True):835if P.is_finite_order():836return K(0)837838if check:839assert P.curve() == E, "the point P must lie on the curve " \840"from which the height function was created"841842Q = n2 * P843alpha, beta, d = _multiply_point(E, R, Q, m * p**lamb)844845assert beta.lift() % p != 0, "beta should be a unit!"846assert d.lift() % p == 0, "d should not be a unit!"847848t = -d * alpha / beta849850total = R(1)851t_power = t852for k in range(2, sigma.prec()):853total = total + t_power * sigma[k].lift()854t_power = t_power * t855total = (-alpha / beta) * total856857L = Qp(p, prec=adjusted_prec + 2*lamb)858total = L(total.lift(), adjusted_prec + 2*lamb)859860# changed sign to make it correct for p-adic bsd861answer = -total.log() * 2 / (n * p**lamb)**2862863if check:864assert answer.precision_absolute() >= prec, "we should have got an " \865"answer with precision at least prec, but we didn't."866return K(answer)867868869# (man... I love python's local function definitions...)870return height871872873def padic_sigma(self, p, N=20, E2=None, check=False, check_hypotheses=True):874r"""875Computes the p-adic sigma function with respect to the standard876invariant differential `dx/(2y + a_1 x + a_3)`, as877defined by Mazur and Tate, as a power series in the usual878uniformiser `t` at the origin.879880The equation of the curve must be minimal at `p`.881882INPUT:883884885- ``p`` - prime = 5 for which the curve has good886ordinary reduction887888- ``N`` - integer = 1, indicates precision of result;889see OUTPUT section for description890891- ``E2`` - precomputed value of E2. If not supplied,892this function will call padic_E2 to compute it. The value supplied893must be correct mod `p^{N-2}`.894895- ``check`` - boolean, whether to perform a896consistency check (i.e. verify that the computed sigma satisfies897the defining898899- ``differential equation`` - note that this does NOT900guarantee correctness of all the returned digits, but it comes901pretty close :-))902903- ``check_hypotheses`` - boolean, whether to check904that this is a curve for which the p-adic sigma function makes905sense906907908OUTPUT: A power series `t + \cdots` with coefficients in909`\ZZ_p`.910911The output series will be truncated at `O(t^{N+1})`, and912the coefficient of `t^n` for `n \geq 1` will be913correct to precision `O(p^{N-n+1})`.914915In practice this means the following. If `t_0 = p^k u`,916where `u` is a `p`-adic unit with at least917`N` digits of precision, and `k \geq 1`, then the918returned series may be used to compute `\sigma(t_0)`919correctly modulo `p^{N+k}` (i.e. with `N` correct920`p`-adic digits).921922ALGORITHM: Described in "Efficient Computation of p-adic Heights"923(David Harvey), which is basically an optimised version of the924algorithm from "p-adic Heights and Log Convergence" (Mazur, Stein,925Tate).926927Running time is soft-`O(N^2 \log p)`, plus whatever time is928necessary to compute `E_2`.929930AUTHORS:931932- David Harvey (2006-09-12)933934- David Harvey (2007-02): rewrote935936EXAMPLES::937938sage: EllipticCurve([-1, 1/4]).padic_sigma(5, 10)939O(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)940941Run it with a consistency check::942943sage: EllipticCurve("37a").padic_sigma(5, 10, check=True)944O(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)945946Boundary cases::947948sage: EllipticCurve([1, 1, 1, 1, 1]).padic_sigma(5, 1)949(1 + O(5))*t + O(t^2)950sage: EllipticCurve([1, 1, 1, 1, 1]).padic_sigma(5, 2)951(1 + O(5^2))*t + (3 + O(5))*t^2 + O(t^3)952953Supply your very own value of E2::954955sage: X = EllipticCurve("37a")956sage: my_E2 = X.padic_E2(5, 8)957sage: my_E2 = my_E2 + 5**5 # oops!!!958sage: X.padic_sigma(5, 10, E2=my_E2)959O(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)960961Check that sigma is "weight 1".962963::964965sage: f = EllipticCurve([-1, 3]).padic_sigma(5, 10)966sage: g = EllipticCurve([-1*(2**4), 3*(2**6)]).padic_sigma(5, 10)967sage: t = f.parent().gen()968sage: f(2*t)/2969(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)970sage: g971O(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)972sage: f(2*t)/2 -g973O(t^11)974975Test that it returns consistent results over a range of precision::976977sage: max_N = 30 # get up to at least p^2 # long time978sage: E = EllipticCurve([1, 1, 1, 1, 1]) # long time979sage: p = 5 # long time980sage: E2 = E.padic_E2(5, max_N) # long time981sage: max_sigma = E.padic_sigma(p, max_N, E2=E2) # long time982sage: for N in range(3, max_N): # long time983... sigma = E.padic_sigma(p, N, E2=E2) # long time984... assert sigma == max_sigma985"""986if check_hypotheses:987p = __check_padic_hypotheses(self, p)988989# todo: implement the p == 3 case990# NOTE: If we ever implement p == 3, it's necessary to check over991# the precision loss estimates (below) very carefully; I think it992# may become necessary to compute E2 to an even higher precision.993if p < 5:994raise NotImplementedError, "p (=%s) must be at least 5" % p995996N = int(N)997if N <= 2:998# a few special cases for small N999if N < 1:1000raise ValueError, "N (=%s) must be at least 1" % prec10011002if N == 1:1003# return simply t + O(t^2)1004K = Qp(p, 2)1005return PowerSeriesRing(K, "t")([K(0), K(1, 1)], prec=2)100610071008if N == 2:1009# return t + a_1/2 t^2 + O(t^3)1010K = Qp(p, 3)1011return PowerSeriesRing(K, "t")([K(0), K(1, 2),1012K(self.a1()/2, 1)], prec=3)10131014if self.discriminant().valuation(p) != 0:1015raise NotImplementedError, "equation of curve must be minimal at p"10161017if E2 is None:1018E2 = self.padic_E2(p, N-2, check_hypotheses=False)1019elif E2.precision_absolute() < N-2:1020raise ValueError, "supplied E2 has insufficient precision"10211022QQt = LaurentSeriesRing(RationalField(), "x")10231024R = rings.Integers(p**(N-2))1025X = self.change_ring(R)1026c = (X.a1()**2 + 4*X.a2() - R(E2)) / 1210271028f = X.formal_group().differential(N+2) # f = 1 + ... + O(t^{N+2})1029x = X.formal_group().x(N) # x = t^{-2} + ... + O(t^N)10301031Rt = x.parent()10321033A = (x + c) * f1034# do integral over QQ, to avoid divisions by p1035A = Rt(QQt(A).integral())1036A = (-X.a1()/2 - A) * f10371038# Convert to a power series and remove the -1/x term.1039# Also we artificially bump up the accuracy from N-2 to to N-1 digits;1040# the constant term needs to be known to N-1 digits, so we compute1041# it directly1042assert A.valuation() == -1 and A[-1] == 11043A = A - A.parent().gen() ** (-1)1044A = A.power_series().list()1045R = rings.Integers(p**(N-1))1046A = [R(u) for u in A]1047A[0] = self.change_ring(R).a1()/2 # fix constant term1048A = PowerSeriesRing(R, "x")(A, len(A))10491050theta = _brent(A, p, N)1051sigma = theta * theta.parent().gen()10521053# Convert the answer to power series over p-adics; drop the precision1054# of the $t^k$ coefficient to $p^(N-k+1)$.1055# [Note: there are actually more digits available, but it's a bit1056# tricky to figure out exactly how many, and we only need $p^(N-k+1)$1057# for p-adic height purposes anyway]1058K = rings.pAdicField(p, N + 1)10591060sigma = sigma.padded_list(N+1)10611062sigma[0] = K(0, N +1)1063sigma[1] = K(1, N)1064for n in range(2, N+1):1065sigma[n] = K(sigma[n].lift(), N - n + 1)10661067S = rings.PowerSeriesRing(K, "t", N+1)1068sigma = S(sigma, N+1)10691070# if requested, check that sigma satisfies the appropriate1071# differential equation1072if check:1073R = rings.Integers(p**N)1074X = self.change_ring(R)1075x = X.formal_group().x(N+5) # few extra terms for safety1076f = X.formal_group().differential(N+5)1077c = (X.a1()**2 + 4*X.a2() - R(E2)) / 1210781079# convert sigma to be over Z/p^N1080s = f.parent()(sigma)1081sinv = s**(-1)1082finv = f**(-1)10831084# apply differential equation1085temp = (s.derivative() * sinv * finv).derivative() * finv + c + x10861087# coefficient of t^k in the result should be zero mod p^(N-k-2)1088for k in range(N-2):1089assert temp[k].lift().valuation(p) >= N - k - 2, \1090"sigma correctness check failed!"10911092return sigma10931094109510961097def padic_sigma_truncated(self, p, N=20, lamb=0, E2=None, check_hypotheses=True):1098r"""1099Computes the p-adic sigma function with respect to the standard1100invariant differential `dx/(2y + a_1 x + a_3)`, as1101defined by Mazur and Tate, as a power series in the usual1102uniformiser `t` at the origin.11031104The equation of the curve must be minimal at `p`.11051106This function differs from padic_sigma() in the precision profile1107of the returned power series; see OUTPUT below.11081109INPUT:111011111112- ``p`` - prime = 5 for which the curve has good1113ordinary reduction11141115- ``N`` - integer = 2, indicates precision of result;1116see OUTPUT section for description11171118- ``lamb`` - integer = 0, see OUTPUT section for1119description11201121- ``E2`` - precomputed value of E2. If not supplied,1122this function will call padic_E2 to compute it. The value supplied1123must be correct mod `p^{N-2}`.11241125- ``check_hypotheses`` - boolean, whether to check1126that this is a curve for which the p-adic sigma function makes1127sense112811291130OUTPUT: A power series `t + \cdots` with coefficients in1131`\ZZ_p`.11321133The coefficient of `t^j` for `j \geq 1` will be1134correct to precision `O(p^{N - 2 + (3 - j)(lamb + 1)})`.11351136ALGORITHM: Described in "Efficient Computation of p-adic Heights"1137(David Harvey, to appear in LMS JCM), which is basically an1138optimised version of the algorithm from "p-adic Heights and Log1139Convergence" (Mazur, Stein, Tate), and "Computing p-adic heights1140via point multiplication" (David Harvey, still draft form).11411142Running time is soft-`O(N^2 \lambda^{-1} \log p)`, plus1143whatever time is necessary to compute `E_2`.11441145AUTHOR:11461147- David Harvey (2008-01): wrote based on previous1148padic_sigma function11491150EXAMPLES::11511152sage: E = EllipticCurve([-1, 1/4])1153sage: E.padic_sigma_truncated(5, 10)1154O(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)11551156Note the precision of the `t^3` coefficient depends only on1157`N`, not on lamb::11581159sage: E.padic_sigma_truncated(5, 10, lamb=2)1160O(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)11611162Compare against plain padic_sigma() function over a dense range of1163N and lamb11641165::11661167sage: E = EllipticCurve([1, 2, 3, 4, 7]) # long time1168sage: E2 = E.padic_E2(5, 50) # long time1169sage: for N in range(2, 10): # long time1170... for lamb in range(10): # long time1171... correct = E.padic_sigma(5, N + 3*lamb, E2=E2) # long time1172... compare = E.padic_sigma_truncated(5, N=N, lamb=lamb, E2=E2) # long time1173... assert compare == correct # long time1174"""1175if check_hypotheses:1176p = __check_padic_hypotheses(self, p)11771178# todo: implement the p == 3 case1179# NOTE: If we ever implement p == 3, it's necessary to check over1180# the precision loss estimates (below) very carefully; I think it1181# may become necessary to compute E2 to an even higher precision.1182if p < 5:1183raise NotImplementedError, "p (=%s) must be at least 5" % p11841185N = int(N)1186lamb = int(lamb)11871188if lamb < 0:1189raise ValueError, "lamb (=%s) must be at least 0" % lamb11901191# a few special cases for small N1192if N <= 1:1193raise ValueError, "N (=%s) must be at least 2" % N11941195if N == 2:1196# return t + a_1/2 t^2 + O(t^3)1197K = Qp(p, 3*(lamb+1))1198return PowerSeriesRing(K, "t")([K(0), K(1, 2*(lamb+1)),1199K(self.a1()/2, lamb+1)], prec=3)12001201if self.discriminant().valuation(p) != 0:1202raise NotImplementedError, "equation of curve must be minimal at p"12031204if E2 is None:1205E2 = self.padic_E2(p, N-2, check_hypotheses=False)1206elif E2.precision_absolute() < N-2:1207raise ValueError, "supplied E2 has insufficient precision"12081209# The main part of the algorithm is exactly the same as1210# for padic_sigma(), but we truncate all the series earlier.1211# Want the answer O(t^(trunc+1)) instead of O(t^(N+1)) like in padic_sigma().1212trunc = (Integer(N-2) / (lamb + 1)).ceil() + 212131214QQt = LaurentSeriesRing(RationalField(), "x")12151216R = rings.Integers(p**(N-2))1217X = self.change_ring(R)1218c = (X.a1()**2 + 4*X.a2() - R(E2)) / 1212191220f = X.formal_group().differential(trunc+2) # f = 1 + ... + O(t^{trunc+2})1221x = X.formal_group().x(trunc) # x = t^{-2} + ... + O(t^trunc)12221223Rt = x.parent()12241225A = (x + c) * f1226# do integral over QQ, to avoid divisions by p1227A = Rt(QQt(A).integral())1228A = (-X.a1()/2 - A) * f12291230# Convert to a power series and remove the -1/x term.1231# Also we artificially bump up the accuracy from N-2 to N-1+lamb digits;1232# the constant term needs to be known to N-1+lamb digits, so we compute1233# it directly1234assert A.valuation() == -1 and A[-1] == 11235A = A - A.parent().gen() ** (-1)1236A = A.power_series().list()1237R = rings.Integers(p**(N-1+lamb))1238A = [R(u) for u in A]1239A[0] = self.change_ring(R).a1()/2 # fix constant term1240A = PowerSeriesRing(R, "x")(A, len(A))12411242theta = _brent(A, p, trunc)1243sigma = theta * theta.parent().gen()12441245# Convert the answer to power series over p-adics; drop the precision1246# of the $t^j$ coefficient to $p^{N - 2 + (3 - j)(lamb + 1)})$.1247K = rings.pAdicField(p, N - 2 + 3*(lamb+1))12481249sigma = sigma.padded_list(trunc+1)12501251sigma[0] = K(0, N - 2 + 3*(lamb+1))1252sigma[1] = K(1, N - 2 + 2*(lamb+1))1253for j in range(2, trunc+1):1254sigma[j] = K(sigma[j].lift(), N - 2 + (3 - j)*(lamb+1))12551256S = rings.PowerSeriesRing(K, "t", trunc + 1)1257sigma = S(sigma, trunc+1)12581259return sigma126012611262def padic_E2(self, p, prec=20, check=False, check_hypotheses=True, algorithm="auto"):1263r"""1264Returns the value of the `p`-adic modular form `E2`1265for `(E, \omega)` where `\omega` is the usual1266invariant differential `dx/(2y + a_1 x + a_3)`.12671268INPUT:126912701271- ``p`` - prime (= 5) for which `E` is good1272and ordinary12731274- ``prec`` - (relative) p-adic precision (= 1) for1275result12761277- ``check`` - boolean, whether to perform a1278consistency check. This will slow down the computation by a1279constant factor 2. (The consistency check is to compute the whole1280matrix of frobenius on Monsky-Washnitzer cohomology, and verify1281that its trace is correct to the specified precision. Otherwise,1282the trace is used to compute one column from the other one1283(possibly after a change of basis).)12841285- ``check_hypotheses`` - boolean, whether to check1286that this is a curve for which the p-adic sigma function makes1287sense12881289- ``algorithm`` - one of "standard", "sqrtp", or1290"auto". This selects which version of Kedlaya's algorithm is used.1291The "standard" one is the one described in Kedlaya's paper. The1292"sqrtp" one has better performance for large `p`, but only1293works when `p > 6N` (`N=` prec). The "auto" option1294selects "sqrtp" whenever possible.12951296Note that if the "sqrtp" algorithm is used, a consistency check1297will automatically be applied, regardless of the setting of the1298"check" flag.129913001301OUTPUT: p-adic number to precision prec13021303.. note::13041305If the discriminant of the curve has nonzero valuation at p,1306then the result will not be returned mod `p^\text{prec}`,1307but it still *will* have prec *digits* of precision.13081309TODO: - Once we have a better implementation of the "standard"1310algorithm, the algorithm selection strategy for "auto" needs to be1311revisited.13121313AUTHORS:13141315- David Harvey (2006-09-01): partly based on code written1316by Robert Bradshaw at the MSRI 2006 modular forms workshop13171318ACKNOWLEDGMENT: - discussion with Eyal Goren that led to the trace1319trick.13201321EXAMPLES: Here is the example discussed in the paper "Computation1322of p-adic Heights and Log Convergence" (Mazur, Stein, Tate)::13231324sage: EllipticCurve([-1, 1/4]).padic_E2(5)13252 + 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)13261327Let's try to higher precision (this is the same answer the MAGMA1328implementation gives)::13291330sage: EllipticCurve([-1, 1/4]).padic_E2(5, 100)13312 + 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)13321333Check it works at low precision too::13341335sage: EllipticCurve([-1, 1/4]).padic_E2(5, 1)13362 + O(5)1337sage: EllipticCurve([-1, 1/4]).padic_E2(5, 2)13382 + 4*5 + O(5^2)1339sage: EllipticCurve([-1, 1/4]).padic_E2(5, 3)13402 + 4*5 + O(5^3)13411342TODO: With the old(-er), i.e., = sage-2.4 p-adics we got1343`5 + O(5^2)` as output, i.e., relative precision 1, but1344with the newer p-adics we get relative precision 0 and absolute1345precision 1.13461347::13481349sage: EllipticCurve([1, 1, 1, 1, 1]).padic_E2(5, 1)1350O(5)13511352Check it works for different models of the same curve (37a), even1353when the discriminant changes by a power of p (note that E2 depends1354on the differential too, which is why it gets scaled in some of the1355examples below)::13561357sage: X1 = EllipticCurve([-1, 1/4])1358sage: X1.j_invariant(), X1.discriminant()1359(110592/37, 37)1360sage: X1.padic_E2(5, 10)13612 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)13621363::13641365sage: X2 = EllipticCurve([0, 0, 1, -1, 0])1366sage: X2.j_invariant(), X2.discriminant()1367(110592/37, 37)1368sage: X2.padic_E2(5, 10)13692 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)13701371::13721373sage: X3 = EllipticCurve([-1*(2**4), 1/4*(2**6)])1374sage: X3.j_invariant(), X3.discriminant() / 2**121375(110592/37, 37)1376sage: 2**(-2) * X3.padic_E2(5, 10)13772 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)13781379::13801381sage: X4 = EllipticCurve([-1*(7**4), 1/4*(7**6)])1382sage: X4.j_invariant(), X4.discriminant() / 7**121383(110592/37, 37)1384sage: 7**(-2) * X4.padic_E2(5, 10)13852 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)13861387::13881389sage: X5 = EllipticCurve([-1*(5**4), 1/4*(5**6)])1390sage: X5.j_invariant(), X5.discriminant() / 5**121391(110592/37, 37)1392sage: 5**(-2) * X5.padic_E2(5, 10)13932 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)13941395::13961397sage: X6 = EllipticCurve([-1/(5**4), 1/4/(5**6)])1398sage: X6.j_invariant(), X6.discriminant() * 5**121399(110592/37, 37)1400sage: 5**2 * X6.padic_E2(5, 10)14012 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)14021403Test check=True vs check=False::14041405sage: EllipticCurve([-1, 1/4]).padic_E2(5, 1, check=False)14062 + O(5)1407sage: EllipticCurve([-1, 1/4]).padic_E2(5, 1, check=True)14082 + O(5)1409sage: EllipticCurve([-1, 1/4]).padic_E2(5, 30, check=False)14102 + 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)1411sage: EllipticCurve([-1, 1/4]).padic_E2(5, 30, check=True)14122 + 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)14131414Here's one using the `p^{1/2}` algorithm::14151416sage: EllipticCurve([-1, 1/4]).padic_E2(3001, 3, algorithm="sqrtp")14171907 + 2819*3001 + 1124*3001^2 + O(3001^3)1418"""1419if self.conductor() % p == 0:1420if not self.conductor() % (p**2) == 0:1421eq = self.tate_curve(p,prec=prec)1422return eq.E2(prec=prec)14231424frob_p = self.matrix_of_frobenius(p, prec, check, check_hypotheses, algorithm).change_ring(Integers(p**prec))14251426frob_p_n = frob_p**prec14271428# todo: think about the sign of this. Is it correct?1429output_ring = rings.pAdicField(p, prec)14301431E2_of_X = output_ring( (-12 * frob_p_n[0,1] / frob_p_n[1,1]).lift() ) \1432+ O(p**prec)14331434# Take into account the coordinate change.1435X = self.minimal_model().short_weierstrass_model()1436fudge_factor = (X.discriminant() / self.discriminant()).nth_root(6)1437# todo: here I should be able to write:1438# return E2_of_X / fudge_factor1439# However, there is a bug in Sage (#51 on trac) which makes this1440# crash sometimes when prec == 1. For example,1441# EllipticCurve([1, 1, 1, 1, 1]).padic_E2(5, 1)1442# makes it crash. I haven't figured out exactly what the bug1443# is yet, but for now I use the following workaround:1444fudge_factor_inverse = Qp(p, prec=(E2_of_X.precision_absolute() + 1))(1 / fudge_factor)1445return output_ring(E2_of_X * fudge_factor_inverse)14461447def matrix_of_frobenius(self, p, prec=20, check=False, check_hypotheses=True, algorithm="auto"):1448r"""1449Returns the matrix of Frobenius on the Monsky Washnitzer cohomology of the elliptic curve.14501451INPUT:14521453- ``p`` - prime (= 5) for which `E` is good1454and ordinary14551456- ``prec`` - (relative) `p`-adic precision for1457result (default 20)14581459- ``check`` - boolean (default: False), whether to perform a1460consistency check. This will slow down the computation by a1461constant factor 2. (The consistency check is to verify1462that its trace is correct to the specified precision. Otherwise,1463the trace is used to compute one column from the other one1464(possibly after a change of basis).)14651466- ``check_hypotheses`` - boolean, whether to check1467that this is a curve for which the `p`-adic sigma function makes1468sense14691470- ``algorithm`` - one of "standard", "sqrtp", or1471"auto". This selects which version of Kedlaya's algorithm is used.1472The "standard" one is the one described in Kedlaya's paper. The1473"sqrtp" one has better performance for large `p`, but only1474works when `p > 6N` (`N=` prec). The "auto" option1475selects "sqrtp" whenever possible.14761477Note that if the "sqrtp" algorithm is used, a consistency check1478will automatically be applied, regardless of the setting of the1479"check" flag.14801481OUTPUT: a matrix of `p`-adic number to precision ``prec``14821483See also the documentation of padic_E2.14841485EXAMPLES::14861487sage: E = EllipticCurve('37a1')1488sage: E.matrix_of_frobenius(7)1489[ 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)]1490[ 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)]1491sage: M = E.matrix_of_frobenius(11,prec=3); M1492[ 9*11 + 9*11^3 + O(11^4) 10 + 11 + O(11^3)]1493[ 2*11 + 11^2 + O(11^4) 6 + 11 + 10*11^2 + O(11^3)]1494sage: M.det()149511 + O(11^4)1496sage: M.trace()14976 + 10*11 + 10*11^2 + O(11^3)1498sage: E.ap(11)1499-515001501"""1502# TODO change the basis back to the original equation.1503# TODO, add lots of comments like the above1504if check_hypotheses:1505p = __check_padic_hypotheses(self, p)15061507if algorithm == "auto":1508algorithm = "standard" if p < 6*prec else "sqrtp"1509elif algorithm == "sqrtp" and p < 6*prec:1510raise ValueError, "sqrtp algorithm is only available when p > 6*prec"15111512if algorithm not in ["standard", "sqrtp"]:1513raise ValueError, "unknown algorithm '%s'" % algorithm15141515# todo: maybe it would be good if default prec was None, and then1516# it selects an appropriate precision based on how large the prime1517# is15181519# todo: implement the p == 3 case1520if p < 5:1521raise NotImplementedError, "p (=%s) must be at least 5" % p15221523prec = int(prec)1524if prec < 1:1525raise ValueError, "prec (=%s) must be at least 1" % prec15261527# To run matrix_of_frobenius(), we need to have the equation in the1528# form y^2 = x^3 + ax + b, whose discriminant is invertible mod p.1529# When we change coordinates like this, we might scale the invariant1530# differential, so we need to account for this. We do this by1531# comparing discriminants: if the discriminants differ by u^12,1532# then the differentials differ by u. There's a sign ambiguity here,1533# but it doesn't matter because E2 changes by u^2 :-)15341535# todo: In fact, there should be available a function that returns1536# exactly *which* coordinate change was used. If I had that I could1537# avoid the discriminant circus at the end.15381539# todo: The following strategy won't work at all for p = 2, 3.15401541X=self.minimal_model().short_weierstrass_model()15421543assert X.discriminant().valuation(p) == 0, "Something's gone wrong. " \1544"The discriminant of the Weierstrass model should be a unit " \1545" at p."15461547if algorithm == "standard":1548# Need to increase precision a little to compensate for precision1549# losses during the computation. (See monsky_washnitzer.py1550# for more details.)1551adjusted_prec = monsky_washnitzer.adjusted_prec(p, prec)15521553if check:1554trace = None1555else:1556trace = self.ap(p)15571558base_ring = rings.Integers(p**adjusted_prec)1559output_ring = rings.pAdicField(p, prec)15601561R, x = rings.PolynomialRing(base_ring, 'x').objgen()1562Q = x**3 + base_ring(X.a4()) * x + base_ring(X.a6())1563frob_p = monsky_washnitzer.matrix_of_frobenius(1564Q, p, adjusted_prec, trace)156515661567else: # algorithm == "sqrtp"1568p_to_prec = p**prec1569R = rings.PolynomialRing(Integers(), "x")1570Q = R([X.a6() % p_to_prec, X.a4() % p_to_prec, 0, 1])1571frob_p = sage.schemes.hyperelliptic_curves.hypellfrob.hypellfrob(p, prec, Q)15721573# let's force a trace-check since this algorithm is fairly new1574# and we don't want to get caught with our pants down...1575trace = self.ap(p)1576check = True157715781579# return frob_p ## why was this here ?15801581if check:1582trace_of_frobenius = frob_p.trace().lift() % p**prec1583correct_trace = self.ap(p) % p**prec1584assert trace_of_frobenius == correct_trace, \1585"Consistency check failed! (correct = %s, actual = %s)" % \1586(correct_trace, trace_of_frobenius)15871588return frob_p.change_ring(Zp(p, prec))15891590def _brent(F, p, N):1591r"""1592This is an internal function; it is used by padic_sigma().15931594`F` is a assumed to be a power series over1595`R = \ZZ/p^{N-1}\ZZ`.15961597It solves the differential equation `G'(t)/G(t) = F(t)`1598using Brent's algorithm, with initial condition `G(0) = 1`.1599It is assumed that the solution `G` has1600`p`-integral coefficients.16011602More precisely, suppose that `f(t)` is a power series with1603genuine `p`-adic coefficients, and suppose that1604`g(t)` is an exact solution to `g'(t)/g(t) = f(t)`.1605Let `I` be the ideal1606`(p^N, p^{N-1} t, \ldots,1607p t^{N-1}, t^N)`. The input1608`F(t)` should be a finite-precision approximation to1609`f(t)`, in the sense that `\int (F - f) dt` should1610lie in `I`. Then the function returns a series1611`G(t)` such that `(G - g)(t)` lies in `I`.16121613Complexity should be about `O(N^2 \log^2 N \log p)`, plus1614some log-log factors.16151616For more information, and a proof of the precision guarantees, see1617Lemma 4 in "Efficient Computation of p-adic Heights" (David1618Harvey).16191620AUTHORS:16211622- David Harvey (2007-02)16231624EXAMPLES: Carefully test the precision guarantees::16251626sage: brent = sage.schemes.elliptic_curves.padics._brent1627sage: for p in [2, 3, 5]:1628... for N in [2, 3, 10, 50]:1629... R = Integers(p**(N-1))1630... Rx, x = PowerSeriesRing(R, "x").objgen()1631... for _ in range(5):1632... g = [R.random_element() for i in range(N)]1633... g[0] = R(1)1634... g = Rx(g, len(g))1635... f = g.derivative() / g1636... # perturb f by something whose integral is in I1637... err = [R.random_element() * p**(N-i) for i in range(N+1)]1638... err = Rx(err, len(err))1639... err = err.derivative()1640... F = f + err1641... # run brent() and compare output modulo I1642... G = brent(F, p, N)1643... assert G.prec() >= N, "not enough output terms"1644... err = (G - g).list()1645... for i in range(len(err)):1646... assert err[i].lift().valuation(p) >= (N - i), \1647... "incorrect precision output"1648"""1649Rx = F.parent() # Rx = power series ring over Z/p^{N-1} Z1650R = Rx.base_ring() # R = Z/p^{N-1} Z1651Qx = PowerSeriesRing(RationalField(), "x")16521653# initial approximation:1654G = Rx(1)16551656# loop over an appropriate increasing sequence of lengths s1657for s in misc.newton_method_sizes(N):1658# zero-extend to s terms1659# todo: there has to be a better way in Sage to do this...1660G = Rx(G.list(), s)16611662# extend current approximation to be correct to s terms1663H = G.derivative() / G - F1664# Do the integral of H over QQ[x] to avoid division by p problems1665H = Rx(Qx(H).integral())1666G = G * (1 - H)16671668return G166916701671