Path: blob/master/sage/schemes/elliptic_curves/ell_wp.py
4127 views
r"""1Weierstrass `\wp` function for elliptic curves23The Weierstrass `\wp` function associated to an elliptic curve over a field `k` is a Laurent series4of the form56.. math::78\wp(z) = \frac{1}{z^2} + c_2 \cdot z^2 + c_4 \cdot z^4 + \cdots.910If the field is contained in `\mathbb{C}`, then11this is the series expansion of the map from `\mathbb{C}` to `E(\mathbb{C})` whose kernel is the period lattice of `E`.1213Over other fields, like finite fields, this still makes sense as a formal power series with coefficients in `k` - at least its first `p-2` coefficients where `p` is the characteristic of `k`. It can be defined via the formal group as `x+c` in the variable `z=\log_E(t)` for a constant `c` such that the constant term `c_0` in `\wp(z)` is zero.1415EXAMPLE::1617sage: E = EllipticCurve([0,1])18sage: E.weierstrass_p()19z^-2 - 1/7*z^4 + 1/637*z^10 - 1/84721*z^16 + O(z^20)2021REFERENCES:2223- [BMSS] Boston, Morain, Salvy, Schost, "Fast Algorithms for Isogenies."2425AUTHORS:2627- Dan Shumov 04/09 - original implementation28- Chris Wuthrich 11/09 - major restructuring2930"""3132#*****************************************************************************33# Copyright (C) 2009 William Stein <[email protected]>34#35# Distributed under the terms of the GNU General Public License (GPL)36#37# http://www.gnu.org/licenses/38#*****************************************************************************3940#from sage.structure.sage_object import SageObject41#from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing42from sage.rings.laurent_series_ring import LaurentSeriesRing43from sage.rings.power_series_ring import PowerSeriesRing4445#from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism4647def weierstrass_p(E, prec=20, algorithm=None):48r"""49Computes the Weierstrass `\wp`-function on an elliptic curve.5051INPUT:5253- ``E`` - an elliptic curve54- ``prec`` - precision55- ``algorithm`` - string (default:``None``) an algorithm identifier indicating using the ``pari``, ``fast`` or ``quadratic`` algorithm. If the algorithm is ``None``, then this function determines the best algorithm to use.5657OUTPUT:5859a Laurent series in one variable `z` with coefficients in the base field `k` of `E`.6061EXAMPLES::6263sage: E = EllipticCurve('11a1')64sage: E.weierstrass_p(prec=10)65z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8 + O(z^10)66sage: E.weierstrass_p(prec=8)67z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)68sage: Esh = E.short_weierstrass_model()69sage: Esh.weierstrass_p(prec=8)70z^-2 + 13392/5*z^2 + 1080432/7*z^4 + 59781888/25*z^6 + O(z^8)7172sage: E.weierstrass_p(prec=8, algorithm='pari')73z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)74sage: E.weierstrass_p(prec=8, algorithm='quadratic')75z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)7677sage: k = GF(11)78sage: E = EllipticCurve(k, [1,1])79sage: E.weierstrass_p(prec=6, algorithm='fast')80z^-2 + 2*z^2 + 3*z^4 + O(z^6)81sage: E.weierstrass_p(prec=7, algorithm='fast')82Traceback (most recent call last):83...84ValueError: For computing the Weierstrass p-function via the fast algorithm, the characteristic (11) of the underlying field must be greater than prec + 4 = 11.85sage: E.weierstrass_p(prec=8 ,algorithm='pari')86z^-2 + 2*z^2 + 3*z^4 + 5*z^6 + O(z^8)87sage: E.weierstrass_p(prec=9, algorithm='pari')88Traceback (most recent call last):89...90ValueError: For computing the Weierstrass p-function via pari, the characteristic (11) of the underlying field must be greater than prec + 2 = 11.9192"""93Esh = E.short_weierstrass_model()94u = E.isomorphism_to(Esh).u9596k = E.base_ring()97p = k.characteristic()9899# if the algorithm is not set, try to determine algorithm from input100if (None == algorithm):101if (0 == p) or (p > prec+4):102algorithm = "fast"103elif p > prec + 2:104algorithm = "pari"105else:106raise NotImplementedError, "Currently no algorithms for computing the Weierstrass p-function for that characteristic / precision pair is implemented. Lower the precision below char(k)-2"107108A = Esh.a4()109B = Esh.a6()110111112if ("quadratic"==algorithm):113114if (0 < p) and (p < 2*prec + 3):115raise ValueError, "For computing the Weierstrass p-function via the quadratic algorithm, the characteristic (%s) of the underlying field must be greater than 2*prec + 3 = %s."%(p,2*prec+4)116117wp = compute_wp_quadratic(k, A, B, prec)118R = wp.parent()119z = R.gen()120wp = wp(z*u) * u**2121wp = wp.add_bigoh(prec)122123elif ("fast"==algorithm):124125if (0 < p) and (p < prec + 5):126raise ValueError, "For computing the Weierstrass p-function via the fast algorithm, the characteristic (%s) of the underlying field must be greater than prec + 4 = %s."%(p,prec+4)127128wp = compute_wp_fast(k, A, B, prec)129R = wp.parent()130z = R.gen()131wp = wp(z*u) * u**2132wp = wp.add_bigoh(prec)133134135elif ("pari"==algorithm):136137if (0 < p) and (p < prec + 3):138raise ValueError, "For computing the Weierstrass p-function via pari, the characteristic (%s) of the underlying field must be greater than prec + 2 = %s."%(p,prec+2)139140wp = compute_wp_pari(E, prec)141142else:143raise ValueError, "Unknown algorithm for computing the Weierstrass p-function."144145return wp146147def compute_wp_pari(E,prec):148r"""149Computes the Weierstrass `\wp`-function via calling the corresponding function in pari.150151EXAMPLES::152153sage: E = EllipticCurve([0,1])154sage: E.weierstrass_p(algorithm='pari')155z^-2 - 1/7*z^4 + 1/637*z^10 - 1/84721*z^16 + O(z^20)156157sage: E = EllipticCurve(GF(101),[5,4])158sage: E.weierstrass_p(prec=30, algorithm='pari')159z^-2 + 100*z^2 + 86*z^4 + 34*z^6 + 50*z^8 + 82*z^10 + 45*z^12 + 70*z^14 + 33*z^16 + 87*z^18 + 33*z^20 + 36*z^22 + 45*z^24 + 40*z^26 + 12*z^28 + O(z^30)160161sage: from sage.schemes.elliptic_curves.ell_wp import compute_wp_pari162sage: compute_wp_pari(E, prec= 20)163z^-2 + 100*z^2 + 86*z^4 + 34*z^6 + 50*z^8 + 82*z^10 + 45*z^12 + 70*z^14 + 33*z^16 + 87*z^18 + O(z^20)164165"""166ep = E._pari_()167wpp = ep.ellwp(n=prec)168k = E.base_ring()169R = LaurentSeriesRing(k,'z')170z = R.gen()171wp = z**(-2)172for i in xrange(prec):173wp += k(wpp[i]) * z**i174wp = wp.add_bigoh(prec)175return wp176177178def compute_wp_quadratic(k, A, B, prec):179r"""180Computes the truncated Weierstrass function of an elliptic curve defined by short Weierstrass model: `y^2 = x^3 + Ax + B`. Uses an algorithm that is of complexity `O(prec^2)`.181182Let p be the characteristic of the underlying field: Then we must have either p=0, or p > ``prec`` + 3.183184INPUT:185186- ``k`` - the field of definition of the curve187- ``A`` - and188- ``B`` - the coefficients of the elliptic curve189- ``prec`` - the precision to which we compute the series.190191OUTPUT:192A Laurent series aproximating the Weierstrass `\wp`-function to precision ``prec``.193194ALGORITHM:195This function uses the algorithm described in section 3.2 of [BMSS].196197REFERENCES:198[BMSS] Boston, Morain, Salvy, Schost, "Fast Algorithms for Isogenies."199200EXAMPLES::201202sage: E = EllipticCurve([7,0])203sage: E.weierstrass_p(prec=10, algorithm='quadratic')204z^-2 - 7/5*z^2 + 49/75*z^6 + O(z^10)205206sage: E = EllipticCurve(GF(103),[1,2])207sage: E.weierstrass_p(algorithm='quadratic')208z^-2 + 41*z^2 + 88*z^4 + 11*z^6 + 57*z^8 + 55*z^10 + 73*z^12 + 11*z^14 + 17*z^16 + 50*z^18 + O(z^20)209210sage: from sage.schemes.elliptic_curves.ell_wp import compute_wp_quadratic211sage: compute_wp_quadratic(E.base_ring(), E.a4(), E.a6(), prec=10)212z^-2 + 41*z^2 + 88*z^4 + 11*z^6 + 57*z^8 + O(z^10)213214"""215m = prec//2 +1216c = [0 for j in xrange(m)]217c[0] = -A/5218c[1] = -B/7219220# first Z represent z^2221R = LaurentSeriesRing(k,'z') #,default_prec = prec+5)222Z = R.gen()223pe = Z**-1 + c[0]*Z + c[1]*Z**2224225for i in xrange(3, m):226t = 0227for j in xrange(1,i-1):228t += c[j-1]*c[i-2-j]229ci = (3*t)/((i-2)*(2*i+3))230pe += ci * Z**i231c[i-1] = ci232233return pe(Z**2).add_bigoh(prec)234235def compute_wp_fast(k, A, B, m):236r"""237Computes the Weierstrass function of an elliptic curve defined by short Weierstrass model: `y^2 = x^3 + Ax + B`. It does this with as fast as polynomial of degree `m` can be multiplied together in the base ring, i.e. `O(M(n))` in the notation of [BMSS].238239Let `p` be the characteristic of the underlying field: Then we must have either `p=0`, or `p > m + 3`.240241INPUT:242243- ``k`` - the base field of the curve244- ``A`` - and245- ``B`` - as the coeffients of the short Weierstrass model `y^2 = x^3 +Ax +B`, and246- ``m`` - the precision to which the function is computed to.247248OUTPUT:249250the Weierstrass `\wp` function as a Laurent series to precision `m`.251252ALGORITHM:253254This function uses the algorithm described in section 3.3 of255[BMSS].256257EXAMPLES::258259sage: from sage.schemes.elliptic_curves.ell_wp import compute_wp_fast260sage: compute_wp_fast(QQ, 1, 8, 7)261z^-2 - 1/5*z^2 - 8/7*z^4 + 1/75*z^6 + O(z^7)262263sage: k = GF(37)264sage: compute_wp_fast(k, k(1), k(8), 5)265z^-2 + 22*z^2 + 20*z^4 + O(z^5)266267"""268R = PowerSeriesRing(k,'z',default_prec=m+5)269z = R.gen()270s = 2271f1 = z.add_bigoh(m+3)272n = 2*m + 4273274# solve the nonlinear differential equation275while (s < n):276f1pr = f1.derivative()277next_s = 2*s - 1278279a = 2*f1pr280b = -(6*B*(f1**5) + 4*A*(f1**3))281c = B*(f1**6) + A*f1**4 + 1 - (f1pr**2)282283# we should really be computing only mod z^next_s here.284# but we loose only a factor 2285f2 = solve_linear_differential_system(a, b, c, 0)286# sometimes we get to 0 quicker than s reaches n287if f2 == 0:288break289f1 = f1 + f2290s = next_s291292R = f1293Q = R**2294pe = 1/Q295296return pe297298299def solve_linear_differential_system(a, b, c, alpha):300r"""301Solves a system of linear differential equations: `af' + bf = c` and `f'(0) = \alpha`302where `a`, `b`, and `c` are power series in one variable and `\alpha` is a constant in the coefficient ring.303304ALGORITHM:305306due to Brent and Kung '78.307308EXAMPLES::309310sage: from sage.schemes.elliptic_curves.ell_wp import solve_linear_differential_system311sage: k = GF(17)312sage: R.<x> = PowerSeriesRing(k)313sage: a = 1+x+O(x^7); b = x+O(x^7); c = 1+x^3+O(x^7); alpha = k(3)314sage: f = solve_linear_differential_system(a,b,c,alpha)315sage: f3163 + x + 15*x^2 + x^3 + 10*x^5 + 3*x^6 + 13*x^7 + O(x^8)317sage: a*f.derivative()+b*f - c318O(x^7)319sage: f(0) == alpha320True321322"""323a_recip = 1/a324B = b * a_recip325C = c * a_recip326int_B = B.integral()327J = int_B.exp()328J_recip = 1/J329CJ = C * J330int_CJ = CJ.integral()331f = J_recip * (alpha + int_CJ)332333return f334335336