Path: blob/master/sage/schemes/elliptic_curves/ell_generic.py
4128 views
r"""1Elliptic curves over a general ring23Sage defines an elliptic curve over a ring `R` as a 'Weierstrass Model' with4five coefficients `[a_1,a_2,a_3,a_4,a_6]` in `R` given by56`y^2 + a_1 xy + a_3 y = x^3 +a_2 x^2 +a_4 x +a_6`.78Note that the (usual) scheme-theoretic definition of an elliptic curve over `R` would require the discriminant to be a unit in `R`, Sage only imposes that the discriminant is non-zero. Also, in Magma, 'Weierstrass Model' means a model with `a1=a2=a3=0`, which is called 'Short Weierstrass Model' in Sage; these do not always exist in characteristics 2 and 3.910EXAMPLES:1112We construct an elliptic curve over an elaborate base ring::1314sage: p = 97; a=1; b=315sage: R, u = PolynomialRing(GF(p), 'u').objgen()16sage: S, v = PolynomialRing(R, 'v').objgen()17sage: T = S.fraction_field()18sage: E = EllipticCurve(T, [a, b]); E19Elliptic Curve defined by y^2 = x^3 + x + 3 over Fraction Field of Univariate Polynomial Ring in v over Univariate Polynomial Ring in u over Finite Field of size 9720sage: latex(E)21y^2 = x^3 + x + 32223AUTHORS:2425- William Stein (2005): Initial version2627- Robert Bradshaw et al....2829- John Cremona (2008-01): isomorphisms, automorphisms and twists in all characteristics30"""3132#*****************************************************************************33# Copyright (C) 2005 William Stein <[email protected]>34#35# Distributed under the terms of the GNU General Public License (GPL)36#37# This code is distributed in the hope that it will be useful,38# but WITHOUT ANY WARRANTY; without even the implied warranty of39# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU40# General Public License for more details.41#42# The full text of the GPL is available at:43#44# http://www.gnu.org/licenses/45#*****************************************************************************4647import math4849from sage.rings.all import PolynomialRing50import sage.groups.additive_abelian.additive_abelian_group as groups51import sage.groups.generic as generic52import sage.plot.all as plot53from sage.plot.plot import generate_plot_points5455import sage.rings.arith as arith56import sage.rings.all as rings57from sage.rings.number_field.all import is_NumberField58import sage.misc.misc as misc596061# Schemes62import sage.schemes.generic.projective_space as projective_space63import sage.schemes.generic.homset as homset6465import ell_point66import ell_torsion67import constructor68import formal_group69import weierstrass_morphism as wm707172factor = arith.factor73sqrt = math.sqrt74exp = math.exp75mul = misc.mul76next_prime = arith.next_prime7778oo = rings.infinity # infinity79O = rings.O # big oh8081import sage.schemes.plane_curves.projective_curve as plane_curve8283def is_EllipticCurve(x):84r"""85Utility function to test if ``x`` is an instance of an Elliptic Curve class.8687EXAMPLES::8889sage: from sage.schemes.elliptic_curves.ell_generic import is_EllipticCurve90sage: E = EllipticCurve([1,2,3/4,7,19])91sage: is_EllipticCurve(E)92True93sage: is_EllipticCurve(0)94False95"""96return isinstance(x, EllipticCurve_generic)9798class EllipticCurve_generic(plane_curve.ProjectiveCurve_generic):99r"""100Elliptic curve over a generic base ring.101102EXAMPLES::103104sage: E = EllipticCurve([1,2,3/4,7,19]); E105Elliptic Curve defined by y^2 + x*y + 3/4*y = x^3 + 2*x^2 + 7*x + 19 over Rational Field106sage: loads(E.dumps()) == E107True108sage: E = EllipticCurve([1,3])109sage: P = E([-1,1,1])110sage: -5*P111(179051/80089 : -91814227/22665187 : 1)112"""113def __init__(self, ainvs, extra=None):114r"""115Constructor from `a`-invariants (long or short Weierstrass coefficients).116117INPUT:118119- ``ainvs`` (list) -- either `[a_1,a_2,a_3,a_4,a_6]` or120`[a_4,a_6]` (with `a_1=a_2=a_3=0` in the second case).121122.. note::123124See constructor.py for more variants.125126EXAMPLES::127128sage: E = EllipticCurve([1,2,3,4,5]); E129Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field130sage: E = EllipticCurve(GF(7),[1,2,3,4,5]); E131Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 7132133Constructor from `[a_4,a_6]` sets `a_1=a_2=a_3=0`::134135sage: EllipticCurve([4,5]).ainvs()136(0, 0, 0, 4, 5)137138The base ring need not be a field::139140sage: EllipticCurve(IntegerModRing(91),[1,2,3,4,5])141Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Ring of integers modulo 91142"""143if extra != None: # possibility of two arguments144K, ainvs = ainvs, extra145else:146K = ainvs[0].parent()147assert len(ainvs) == 2 or len(ainvs) == 5148self.__base_ring = K149ainvs = [K(x) for x in ainvs]150if len(ainvs) == 2:151ainvs = [K(0),K(0),K(0)] + ainvs152self.__ainvs = tuple(ainvs)153if self.discriminant() == 0:154raise ArithmeticError, \155"Invariants %s define a singular curve."%ainvs156PP = projective_space.ProjectiveSpace(2, K, names='xyz');157x, y, z = PP.coordinate_ring().gens()158a1, a2, a3, a4, a6 = ainvs159f = y**2*z + (a1*x + a3*z)*y*z \160- (x**3 + a2*x**2*z + a4*x*z**2 + a6*z**3)161plane_curve.ProjectiveCurve_generic.__init__(self, PP, f)162# TODO: cleanup, are these two point classes redundant?163164# See #1975: we deliberately set the class to165# EllipticCurvePoint_finite_field for finite rings, so that we166# can do some arithmetic on points over Z/NZ, for teaching167# purposes.168from sage.rings.all import is_FiniteField, is_IntegerModRing169if is_FiniteField(K) or is_IntegerModRing(K):170self._morphism = self._point = ell_point.EllipticCurvePoint_finite_field171elif K.is_field():172if is_NumberField(K):173self._morphism = self._point = ell_point.EllipticCurvePoint_number_field174else:175self._morphism = self._point = ell_point.EllipticCurvePoint_field176else:177self._morphism = self._point = ell_point.EllipticCurvePoint178179def _defining_params_(self):180r"""181Internal function. Returns a tuple of the base ring of this182elliptic curve and its `a`-invariants, from which it can be183reconstructed.184185EXAMPLES::186187sage: E=EllipticCurve(QQ,[1,1])188sage: E._defining_params_()189(Rational Field, [0, 0, 0, 1, 1])190sage: EllipticCurve(*E._defining_params_()) == E191True192"""193return (self.__base_ring, list(self.__ainvs))194195def __hash__(self):196"""197TESTS::198199sage: E = EllipticCurve('37a')200sage: hash(E)201-1437250549 # 32-bit202-2189969105152029685 # 64-bit203sage: hash(E) != hash(E.change_ring(GF(7)))204True205"""206return hash((self.__base_ring, self.__ainvs))207208def _repr_(self):209"""210String representation of elliptic curve.211212EXAMPLES::213214sage: E=EllipticCurve([1,2,3,4,5]); E._repr_()215'Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field'216217::218219sage: R.<x> = QQ['x']220sage: K.<a> = NumberField(x^3-17)221sage: EllipticCurve([a^2-3, -2/3*a + 3])222Elliptic Curve defined by y^2 = x^3 + (a^2-3)*x + (-2/3*a+3) over Number Field in a223with defining polynomial x^3 - 17224"""225#return "Elliptic Curve with a-invariants %s over %s"%(self.ainvs(), self.base_ring())226b = self.ainvs()227#return "y^2 + %s*x*y + %s*y = x^3 + %s*x^2 + %s*x + %s"%\228# (a[0], a[2], a[1], a[3], a[4])229a = [z._coeff_repr() for z in b]230s = "Elliptic Curve defined by "231s += "y^2 "232if a[0] == "-1":233s += "- x*y "234elif a[0] == '1':235s += "+ x*y "236elif b[0]:237s += "+ %s*x*y "%a[0]238if a[2] == "-1":239s += "- y "240elif a[2] == '1':241s += "+ y "242elif b[2]:243s += "+ %s*y "%a[2]244s += "= x^3 "245if a[1] == "-1":246s += "- x^2 "247elif a[1] == '1':248s += "+ x^2 "249elif b[1]:250s += "+ %s*x^2 "%a[1]251if a[3] == "-1":252s += "- x "253elif a[3] == '1':254s += "+ x "255elif b[3]:256s += "+ %s*x "%a[3]257if a[4] == '-1':258s += "- 1 "259elif a[4] == '1':260s += "+ 1 "261elif b[4]:262s += "+ %s "%a[4]263s = s.replace("+ -","- ")264s += "over %s"%self.base_ring()265return s266267def _latex_(self):268"""269Internal function. Returns a latex string for this elliptic curve.270Users will normally use latex() instead.271272EXAMPLES::273274sage: E=EllipticCurve(QQ,[1,1])275sage: E._latex_()276'y^2 = x^3 + x + 1 '277sage: latex(E)278y^2 = x^3 + x + 1279"""280b = self.ainvs()281a = [z._latex_coeff_repr() for z in b]282s = "y^2 "283if a[0] == '-1':284s += "- xy "285elif a[0] == '1':286s += "+ xy "287elif b[0]:288s += "+ %sxy "%a[0]289if a[2] == '-1':290s += "- y "291elif a[2] == '1':292s += "+ y "293elif b[2]:294s += "+ %sy "%a[2]295s += "= x^3 "296if a[1] == '-1':297s += "- x^2 "298elif a[1] == '1':299s += "+ x^2 "300elif b[1]:301s += "+ %sx^2 "%a[1]302if a[3] == '-1':303s += "- x "304elif a[3] == '1':305s += "+ x "306elif b[3]:307s += "+ %sx "%a[3]308if a[4] == '-1':309s += "- 1 "310elif a[4] == '1':311s += "+ 1 "312elif b[4]:313s += "+ %s "%a[4]314s = s.replace("+ -","- ")315return s316317def _pari_init_(self):318"""319Internal function. Returns a string to initialize this elliptic320curve in the PARI system.321322EXAMPLES::323324sage: E=EllipticCurve(QQ,[1,1])325sage: E._pari_init_()326'ellinit([0/1,0/1,0/1,1/1,1/1])'327"""328return 'ellinit([%s])'%(','.join([x._pari_init_() for x in self.ainvs()]))329330def _magma_init_(self, magma):331"""332Internal function. Returns a string to initialize this elliptic333curve in the Magma subsystem.334335EXAMPLES::336337sage: E = EllipticCurve(QQ,[1,1])338sage: E._magma_init_(magma) # optional - magma339'EllipticCurve([_sage_ref...|0/1,0/1,0/1,1/1,1/1])'340sage: E = EllipticCurve(GF(41),[2,5]) # optional - magma341sage: E._magma_init_(magma) # optional - magma342'EllipticCurve([_sage_ref...|GF(41)!0,GF(41)!0,GF(41)!0,GF(41)!2,GF(41)!5])'343sage: E = EllipticCurve(GF(25,'a'), [0,0,1,4,0])344sage: magma(E) # optional - magma345Elliptic Curve defined by y^2 + y = x^3 + 4*x over GF(5^2)346sage: magma(EllipticCurve([1/2,2/3,-4/5,6/7,8/9])) # optional - magma347Elliptic Curve defined by y^2 + 1/2*x*y - 4/5*y = x^3 + 2/3*x^2 + 6/7*x + 8/9 over Rational Field348sage: R.<x> = Frac(QQ['x'])349sage: magma(EllipticCurve([x,1+x])) # optional - magma350Elliptic Curve defined by y^2 = x^3 + x*x + (x + 1) over Univariate rational function field over Rational Field351"""352kmn = magma(self.base_ring())._ref()353return 'EllipticCurve([%s|%s])'%(kmn,','.join([x._magma_init_(magma) for x in self.ainvs()]))354355356def _symbolic_(self, SR):357r"""358Many elliptic curves can be converted into a symbolic expression359using the ``symbolic_expression`` command.360361EXAMPLES: We find a torsion point on 11a.362363::364365sage: E = EllipticCurve('11a')366sage: E._symbolic_(SR)367y^2 + y == x^3 - x^2 - 10*x - 20368sage: E.torsion_subgroup().gens()369((5 : 5 : 1),)370371We find the corresponding symbolic equality::372373sage: eqn = symbolic_expression(E); eqn374y^2 + y == x^3 - x^2 - 10*x - 20375376We verify that the given point is on the curve::377378sage: eqn(x=5,y=5)37930 == 30380sage: bool(eqn(x=5,y=5))381True382383We create a single expression::384385sage: F = eqn.lhs() - eqn.rhs(); F386-x^3 + x^2 + y^2 + 10*x + y + 20387sage: y = var('y')388sage: F.solve(y)389[y == -1/2*sqrt(4*x^3 - 4*x^2 - 40*x - 79) - 1/2,390y == 1/2*sqrt(4*x^3 - 4*x^2 - 40*x - 79) - 1/2]391392You can also solve for x in terms of y, but the result is393horrendous. Continuing with the above example, we can explicitly394find points over random fields by substituting in values for x::395396sage: v = F.solve(y)[0].rhs(); v397-1/2*sqrt(4*x^3 - 4*x^2 - 40*x - 79) - 1/2398sage: v = v.function(x)399sage: v(3)400-1/2*sqrt(-127) - 1/2401sage: v(7)402-1/2*sqrt(817) - 1/2403sage: v(-7)404-1/2*sqrt(-1367) - 1/2405sage: v(sqrt(2))406-1/2*sqrt(-32*sqrt(2) - 87) - 1/2407408We can even do arithmetic with them, as follows::409410sage: E2 = E.change_ring(SR); E2411Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20) over Symbolic Ring412sage: P = E2.point((3, v(3), 1), check=False) # the check=False option doesn't verify that y^2 = f(x)413sage: P414(3 : -1/2*sqrt(-127) - 1/2 : 1)415sage: P + P416(-756/127 : 41143/32258*sqrt(-127) - 1/2 : 1)417418We can even throw in a transcendental::419420sage: w = E2.point((pi,v(pi),1), check=False); w421(pi : -1/2*sqrt(-40*pi + 4*pi^3 - 4*pi^2 - 79) - 1/2 : 1)422sage: x, y, z = w; ((y^2 + y) - (x^3 - x^2 - 10*x - 20)).expand()4230424425sage: 2*w426(-2*pi + (2*pi - 3*pi^2 + 10)^2/(-40*pi + 4*pi^3 - 4*pi^2 - 79) + 1 : (2*pi - 3*pi^2 + 10)*(3*pi - (2*pi - 3*pi^2 + 10)^2/(-40*pi + 4*pi^3 - 4*pi^2 - 79) - 1)/sqrt(-40*pi + 4*pi^3 - 4*pi^2 - 79) + 1/2*sqrt(-40*pi + 4*pi^3 - 4*pi^2 - 79) - 1/2 : 1)427428sage: x, y, z = 2*w; temp = ((y^2 + y) - (x^3 - x^2 - 10*x - 20))429430This is a point on the curve::431432sage: bool(temp == 0)433True434"""435a = [SR(x) for x in self.a_invariants()]436x, y = SR.var('x, y')437return y**2 + a[0]*x*y + a[2]*y == x**3 + a[1]*x**2 + a[3]*x + a[4]438439def __cmp__(self, other):440"""441Standard comparison function for elliptic curves, to allow sorting442and equality testing.443444EXAMPLES::445446sage: E=EllipticCurve(QQ,[1,1])447sage: F=EllipticCurve(QQ,[0,0,0,1,1])448sage: E==F449True450"""451if not isinstance(other, EllipticCurve_generic):452return -1453t = cmp(self.base_ring(), other.base_ring())454if t:455return t456return cmp(self.ainvs(), other.ainvs())457458def __contains__(self, P):459"""460Returns True if and only if P is a point on the elliptic curve. P461just has to be something that can be coerced to a point.462463EXAMPLES::464465sage: E = EllipticCurve([0, 0, 1, -1, 0])466sage: (0,0) in E467True468sage: (1,3) in E469False470sage: E = EllipticCurve([GF(7)(0), 1])471sage: [0,0] in E472False473sage: [0,8] in E474True475sage: P = E(0,8)476sage: P477(0 : 1 : 1)478sage: P in E479True480"""481if not isinstance(P, ell_point.EllipticCurvePoint):482try:483P = self(P)484except TypeError:485return False486if P.curve() == self:487return True488x, y, a = P[0], P[1], self.ainvs()489return y**2 + a[0]*x*y + a[2]*y == x**3 + a[1]*x**2 + a[3]*x + a[4]490491def __call__(self, *args, **kwds):492r"""493EXAMPLES::494495sage: E = EllipticCurve([0, 0, 1, -1, 0])496497The point at infinity, which is the 0 element of the group::498499sage: E(0)500(0 : 1 : 0)501502The origin is a point on our curve::503504sage: P = E([0,0])505sage: P506(0 : 0 : 1)507508The curve associated to a point::509510sage: P.curve()511Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field512513Points can be specified by given a 2-tuple or 3-tuple::514515sage: E([0,0])516(0 : 0 : 1)517sage: E([0,1,0])518(0 : 1 : 0)519520Over a field, points are normalized so the 3rd entry (if non-zero)521is 1::522523sage: E(105, -69, 125)524(21/25 : -69/125 : 1)525526We create points on an elliptic curve over a prime finite field::527528sage: E = EllipticCurve([GF(7)(0), 1])529sage: E([2,3])530(2 : 3 : 1)531sage: E([0,0])532Traceback (most recent call last):533...534TypeError: Coordinates [0, 0, 1] do not define a point on Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7535536We create a point on an elliptic curve over a number field::537538sage: x = polygen(RationalField())539sage: K = NumberField(x**3 + x + 1, 'a'); a = K.gen()540sage: E = EllipticCurve([a,a])541sage: E542Elliptic Curve defined by y^2 = x^3 + a*x + a over Number Field in a with defining polynomial x^3 + x + 1543sage: E = EllipticCurve([K(1),1])544sage: E545Elliptic Curve defined by y^2 = x^3 + x + 1 over Number Field in a with defining polynomial x^3 + x + 1546sage: P = E([a,0,1])547sage: P548(a : 0 : 1)549sage: P+P550(0 : 1 : 0)551552Another example involving p-adics::553554sage: E = EllipticCurve('37a1')555sage: P = E([0,0]); P556(0 : 0 : 1)557sage: R = pAdicField(3,20)558sage: Ep = E.base_extend(R); Ep559Elliptic Curve defined by y^2 + (1+O(3^20))*y = x^3 + (2+2*3+2*3^2+2*3^3+2*3^4+2*3^5+2*3^6+2*3^7+2*3^8+2*3^9+2*3^10+2*3^11+2*3^12+2*3^13+2*3^14+2*3^15+2*3^16+2*3^17+2*3^18+2*3^19+O(3^20))*x over 3-adic Field with capped relative precision 20560sage: Ep(P)561(0 : 0 : 1 + O(3^20))562563Constructing points from the torsion subgroup (which is an abstract564abelian group)::565566sage: E = EllipticCurve('14a1')567sage: T = E.torsion_subgroup()568sage: [E(t) for t in T]569[(0 : 1 : 0),570(9 : 23 : 1),571(2 : 2 : 1),572(1 : -1 : 1),573(2 : -5 : 1),574(9 : -33 : 1)]575576::577578sage: E = EllipticCurve([0,0,0,-49,0])579sage: T = E.torsion_subgroup()580sage: [E(t) for t in T]581[(0 : 1 : 0), (7 : 0 : 1), (0 : 0 : 1), (-7 : 0 : 1)]582583::584585sage: E = EllipticCurve('37a1')586sage: T = E.torsion_subgroup()587sage: [E(t) for t in T]588[(0 : 1 : 0)]589"""590if len(args) == 1 and args[0] == 0:591R = self.base_ring()592return self.point([R(0),R(1),R(0)], check=False)593P = args[0]594if isinstance(P, groups.AdditiveAbelianGroupElement) and isinstance(P.parent(),ell_torsion.EllipticCurveTorsionSubgroup):595return self(P.element())596if isinstance(args[0],597(ell_point.EllipticCurvePoint_field, \598ell_point.EllipticCurvePoint_number_field, \599ell_point.EllipticCurvePoint)):600# check if denominator of the point contains a factor of the601# characteristic of the base ring. if so, coerce the point to602# infinity.603characteristic = self.base_ring().characteristic()604if characteristic != 0 and isinstance(args[0][0], rings.Rational) and isinstance(args[0][1], rings.Rational):605if rings.mod(args[0][0].denominator(),characteristic) == 0 or rings.mod(args[0][1].denominator(),characteristic) == 0:606return self._reduce_point(args[0], characteristic)607args = tuple(args[0])608609return plane_curve.ProjectiveCurve_generic.__call__(self, *args, **kwds)610611def _reduce_point(self, R, p):612r"""613Reduces a point R on an ellipitc curve to the corresponding point on614the elliptic curve reduced modulo p. Used to coerce points between615curves when p is a factor of the denominator of one of the616coordinates.617618This functionality is used internally in the \code{call} method for619elliptic curves.620621INPUT:622R -- a point on an elliptic curve623p -- a prime624625OUTPUT:626S -- the corresponding point of the elliptic curve containing R, but627reduced modulo p628629EXAMPLES:630Suppose we have a point with large height on a rational elliptic curve631whose denominator contains a factor of 11::632633sage: E = EllipticCurve([1,-1,0,94,9])634sage: R = E([0,3]) + 5*E([8,31])635sage: factor(R.xy()[0].denominator())6362^2 * 11^2 * 1457253032371^2637638Since 11 is a factor of the denominator, this point corresponds to the639point at infinity on the same curve but reduced modulo 11. The reduce640function tells us this::641642sage: E11 = E.change_ring(GF(11))643sage: S = E11._reduce_point(R, 11)644sage: E11(S)645(0 : 1 : 0)646647The 0 point reduces as expected::648649sage: E11._reduce_point(E(0), 11)650(0 : 1 : 0)651652Note that one need not explicitly call653\code{EllipticCurve._reduce_point}654"""655if R.is_zero():656return R.curve().change_ring(rings.GF(p))(0)657x, y = R.xy()658d = arith.LCM(x.denominator(), y.denominator())659return R.curve().change_ring(rings.GF(p))([x*d, y*d, d])660661def is_x_coord(self, x):662r"""663Returns True if ``x`` is the `x`-coordinate of a point on this curve.664665.. note::666667See also ``lift_x()`` to find the point(s) with a given668`x`-coordinate. This function may be useful in cases where669testing an element of the base field for being a square is670faster than finding its square root.671672EXAMPLES::673674sage: E = EllipticCurve('37a'); E675Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field676sage: E.is_x_coord(1)677True678sage: E.is_x_coord(2)679True680681There are no rational points with x-coordinate 3::682683sage: E.is_x_coord(3)684False685686However, there are such points in `E(\RR)`::687688sage: E.change_ring(RR).is_x_coord(3)689True690691And of course it always works in `E(\CC)`::692693sage: E.change_ring(RR).is_x_coord(-3)694False695sage: E.change_ring(CC).is_x_coord(-3)696True697698AUTHORS:699700- John Cremona (2008-08-07): adapted from lift_x()701702TEST::703704sage: E=EllipticCurve('5077a1')705sage: [x for x in srange(-10,10) if E.is_x_coord (x)]706[-3, -2, -1, 0, 1, 2, 3, 4, 8]707708::709710sage: F=GF(32,'a')711sage: E=EllipticCurve(F,[1,0,0,0,1])712sage: set([P[0] for P in E.points() if P!=E(0)]) == set([x for x in F if E.is_x_coord(x)])713True714"""715K = self.base_ring()716try:717x = K(x)718except TypeError:719raise TypeError, 'x must be coercible into the base ring of the curve'720a1, a2, a3, a4, a6 = self.ainvs()721fx = ((x + a2) * x + a4) * x + a6722if a1.is_zero() and a3.is_zero():723return fx.is_square()724b = (a1*x + a3)725if K.characteristic() == 2:726R = PolynomialRing(K, 'y')727F = R([-fx,b,1])728return len(F.roots())>0729D = b*b + 4*fx730return D.is_square()731732def lift_x(self, x, all=False):733r"""734Returns one or all points with given `x`-coordinate.735736INPUT:737738- ``x`` -- an element of the base ring of the curve.739740- ``all`` (bool, default False) -- if True, return a (possibly741empty) list of all points; if False, return just one point,742or raise a ValueError if there are none.743744.. note::745746See also ``is_x_coord()``.747748EXAMPLES::749750sage: E = EllipticCurve('37a'); E751Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field752sage: E.lift_x(1)753(1 : 0 : 1)754sage: E.lift_x(2)755(2 : 2 : 1)756sage: E.lift_x(1/4, all=True)757[(1/4 : -3/8 : 1), (1/4 : -5/8 : 1)]758759There are no rational points with `x`-coordinate 3::760761sage: E.lift_x(3)762Traceback (most recent call last):763...764ValueError: No point with x-coordinate 3 on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field765766However, there are two such points in `E(\RR)`::767768sage: E.change_ring(RR).lift_x(3, all=True)769[(3.00000000000000 : 4.42442890089805 : 1.00000000000000), (3.00000000000000 : -5.42442890089805 : 1.00000000000000)]770771And of course it always works in `E(\CC)`::772773sage: E.change_ring(RR).lift_x(.5, all=True)774[]775sage: E.change_ring(CC).lift_x(.5)776(0.500000000000000 : -0.500000000000000 + 0.353553390593274*I : 1.00000000000000)777778We can perform these operations over finite fields too::779780sage: E = E.change_ring(GF(17)); E781Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17782sage: E.lift_x(7)783(7 : 11 : 1)784sage: E.lift_x(3)785Traceback (most recent call last):786...787ValueError: No point with x-coordinate 3 on Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17788789Note that there is only one lift with `x`-coordinate 10 in790`E(\GF{17})`::791792sage: E.lift_x(10, all=True)793[(10 : 8 : 1)]794795We can lift over more exotic rings too::796797sage: E = EllipticCurve('37a');798sage: E.lift_x(pAdicField(17, 5)(6))799(6 + O(17^5) : 2 + 16*17 + 16*17^2 + 16*17^3 + 16*17^4 + O(17^5) : 1 + O(17^5))800sage: K.<t> = PowerSeriesRing(QQ, 't', 5)801sage: E.lift_x(1+t)802(1 + t : 2*t - t^2 + 5*t^3 - 21*t^4 + O(t^5) : 1)803sage: K.<a> = GF(16)804sage: E = E.change_ring(K)805sage: E.lift_x(a^3)806(a^3 : a^3 + a : 1)807808AUTHOR:809810- Robert Bradshaw (2007-04-24)811812TEST::813814sage: E = EllipticCurve('37a').short_weierstrass_model().change_ring(GF(17))815sage: E.lift_x(3, all=True)816[]817sage: E.lift_x(7, all=True)818[(7 : 3 : 1), (7 : 14 : 1)]819"""820a1, a2, a3, a4, a6 = self.ainvs()821f = ((x + a2) * x + a4) * x + a6822K = self.base_ring()823x += K(0)824one = x.parent()(1)825if a1.is_zero() and a3.is_zero():826if f.is_square():827if all:828ys = f.sqrt(all=True)829return [self.point([x, y, one], check=False) for y in ys]830else:831return self.point([x, f.sqrt(), one], check=False)832else:833b = (a1*x + a3)834D = b*b + 4*f835if K.characteristic() == 2:836R = PolynomialRing(K, 'y')837F = R([-f,b,1])838ys = F.roots(multiplicities=False)839if all:840return [self.point([x, y, one], check=False) for y in ys]841elif len(ys) > 0:842return self.point([x, ys[0], one], check=False)843elif D.is_square():844if all:845return [self.point([x, (-b+d)/2, one], check=False) for d in D.sqrt(all=True)]846else:847return self.point([x, (-b+D.sqrt())/2, one], check=False)848if all:849return []850else:851raise ValueError, "No point with x-coordinate %s on %s"%(x, self)852853def _point_homset(self, *args, **kwds):854r"""855Internal function. Returns the (abstract) group of points on this856elliptic curve over a ring.857858EXAMPLES::859860sage: E=EllipticCurve(GF(5),[1,1])861sage: E._point_homset(Spec(GF(5^10,'a'),GF(5)), E)862Abelian group of points on Elliptic Curve defined863by y^2 = x^3 + x + 1 over Finite Field in a of size 5^10864"""865return homset.SchemeHomset_points_abelian_variety_field(*args, **kwds)866867def __getitem__(self, n):868r"""869Placeholder for standard indexing function.870871EXAMPLES::872873sage: E=EllipticCurve(QQ,[1,1])874sage: E[2]875Traceback (most recent call last):876...877NotImplementedError: not implemented.878"""879raise NotImplementedError, "not implemented."880881def __is_over_RationalField(self):882r"""883Internal function. Returns true iff the base ring of this elliptic884curve is the field of rational numbers.885886EXAMPLES::887888sage: E=EllipticCurve(QQ,[1,1])889sage: E._EllipticCurve_generic__is_over_RationalField()890True891sage: E=EllipticCurve(GF(5),[1,1])892sage: E._EllipticCurve_generic__is_over_RationalField()893False894"""895return isinstance(self.base_ring(), rings.RationalField)896897def is_on_curve(self, x, y):898r"""899Returns True if `(x,y)` is an affine point on this curve.900901INPUT:902903- ``x``, ``y`` - elements of the base ring of the curve.904905EXAMPLES::906907sage: E=EllipticCurve(QQ,[1,1])908sage: E.is_on_curve(0,1)909True910sage: E.is_on_curve(1,1)911False912"""913a = self.ainvs()914return y**2 +a[0]*x*y + a[2]*y == x**3 + a[1]*x**2 + a[3]*x + a[4]915916def a_invariants(self):917r"""918The `a`-invariants of this elliptic curve, as a tuple.919920OUTPUT:921922(tuple) - a 5-tuple of the `a`-invariants of this elliptic curve.923924EXAMPLES::925926sage: E = EllipticCurve([1,2,3,4,5])927sage: E.a_invariants()928(1, 2, 3, 4, 5)929sage: E = EllipticCurve([0,1])930sage: E931Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field932sage: E.a_invariants()933(0, 0, 0, 0, 1)934sage: E = EllipticCurve([GF(7)(3),5])935sage: E.a_invariants()936(0, 0, 0, 3, 5)937938::939940sage: E = EllipticCurve([1,0,0,0,1])941sage: E.a_invariants()[0] = 100000000942Traceback (most recent call last):943...944TypeError: 'tuple' object does not support item assignment945946"""947return self.__ainvs948949ainvs = a_invariants950951def a1(self):952r"""953Returns the `a_1` invariant of this elliptic curve.954955EXAMPLES::956957sage: E = EllipticCurve([1,2,3,4,6])958sage: E.a1()9591960"""961return self.__ainvs[0]962963def a2(self):964r"""965Returns the `a_2` invariant of this elliptic curve.966967EXAMPLES::968969sage: E = EllipticCurve([1,2,3,4,6])970sage: E.a2()9712972"""973return self.__ainvs[1]974975def a3(self):976r"""977Returns the `a_3` invariant of this elliptic curve.978979EXAMPLES::980981sage: E = EllipticCurve([1,2,3,4,6])982sage: E.a3()9833984"""985return self.__ainvs[2]986987def a4(self):988r"""989Returns the `a_4` invariant of this elliptic curve.990991EXAMPLES::992993sage: E = EllipticCurve([1,2,3,4,6])994sage: E.a4()9954996"""997return self.__ainvs[3]998999def a6(self):1000r"""1001Returns the `a_6` invariant of this elliptic curve.10021003EXAMPLES::10041005sage: E = EllipticCurve([1,2,3,4,6])1006sage: E.a6()100761008"""1009return self.__ainvs[4]10101011def b_invariants(self):1012r"""1013Returns the `b`-invariants of this elliptic curve, as a tuple.10141015OUTPUT:10161017(tuple) - a 4-tuple of the `b`-invariants of this elliptic curve.10181019EXAMPLES::10201021sage: E = EllipticCurve([0, -1, 1, -10, -20])1022sage: E.b_invariants()1023(-4, -20, -79, -21)1024sage: E = EllipticCurve([-4,0])1025sage: E.b_invariants()1026(0, -8, 0, -16)10271028::10291030sage: E = EllipticCurve([1,2,3,4,5])1031sage: E.b_invariants()1032(9, 11, 29, 35)1033sage: E.b2()103491035sage: E.b4()1036111037sage: E.b6()1038291039sage: E.b8()10403510411042ALGORITHM:10431044These are simple functions of the `a`-invariants.10451046AUTHORS:10471048- William Stein (2005-04-25)1049"""1050try:1051return self.__b_invariants1052except AttributeError:1053a1,a2,a3,a4,a6 = self.ainvs()1054self.__b_invariants = a1*a1 + 4*a2, \1055a1*a3 + 2*a4, \1056a3**2 + 4*a6, \1057a1**2 * a6 + 4*a2*a6 - a1*a3*a4 + a2*a3**2 - a4**21058return self.__b_invariants10591060def b2(self):1061r"""1062Returns the `b_2` invariant of this elliptic curve.10631064EXAMPLES::10651066sage: E = EllipticCurve([1,2,3,4,5])1067sage: E.b2()106891069"""1070try:1071return self.__b_invariants[0]1072except AttributeError:1073return self.b_invariants()[0]10741075def b4(self):1076r"""1077Returns the `b_4` invariant of this elliptic curve.10781079EXAMPLES::10801081sage: E = EllipticCurve([1,2,3,4,5])1082sage: E.b4()1083111084"""1085try:1086return self.__b_invariants[1]1087except AttributeError:1088return self.b_invariants()[1]10891090def b6(self):1091r"""1092Returns the `b_6` invariant of this elliptic curve.10931094EXAMPLES::10951096sage: E = EllipticCurve([1,2,3,4,5])1097sage: E.b6()1098291099"""1100try:1101return self.__b_invariants[2]1102except AttributeError:1103return self.b_invariants()[2]11041105def b8(self):1106r"""1107Returns the `b_8` invariant of this elliptic curve.11081109EXAMPLES::11101111sage: E = EllipticCurve([1,2,3,4,5])1112sage: E.b8()1113351114"""1115try:1116return self.__b_invariants[3]1117except AttributeError:1118return self.b_invariants()[3]11191120def c_invariants(self):1121r"""1122Returns the `c`-invariants of this elliptic curve, as a tuple.11231124OUTPUT:11251126(tuple) - a 2-tuple of the `c`-invariants of the elliptic curve.11271128EXAMPLES::11291130sage: E = EllipticCurve([0, -1, 1, -10, -20])1131sage: E.c_invariants()1132(496, 20008)1133sage: E = EllipticCurve([-4,0])1134sage: E.c_invariants()1135(192, 0)11361137ALGORITHM:11381139These are simple functions of the `a`-invariants.11401141AUTHORS:11421143- William Stein (2005-04-25)1144"""1145try:1146return self.__c_invariants1147except AttributeError:1148b2,b4,b6,b8 = self.b_invariants()1149self.__c_invariants = b2**2 - 24*b4,\1150-b2**3 + 36*b2*b4 - 216*b6 # note: c6 is wrong in Silverman, but right in Cremona1151return self.__c_invariants11521153def c4(self):1154r"""1155Returns the `c_4` invariant of this elliptic curve.11561157EXAMPLES::11581159sage: E = EllipticCurve([0, -1, 1, -10, -20])1160sage: E.c4()11614961162"""1163try:1164return self.__c_invariants[0]1165except AttributeError:1166pass1167return self.c_invariants()[0]11681169def c6(self):1170r"""1171Returns the `c_6` invariant of this elliptic curve.11721173EXAMPLES::11741175sage: E = EllipticCurve([0, -1, 1, -10, -20])1176sage: E.c6()1177200081178"""1179try:1180return self.__c_invariants[1]1181except AttributeError:1182pass1183return self.c_invariants()[1]11841185def discriminant(self):1186r"""1187Returns the discriminant of this elliptic curve.11881189EXAMPLES::11901191sage: E = EllipticCurve([0,0,1,-1,0])1192sage: E.discriminant()1193371194sage: E = EllipticCurve([0, -1, 1, -10, -20])1195sage: E.discriminant()1196-16105111971198::11991200sage: E = EllipticCurve([GF(7)(2),1])1201sage: E.discriminant()120211203"""1204try:1205return self.__discriminant1206except AttributeError:1207b2, b4, b6, b8 = self.b_invariants()1208self.__discriminant = -b2**2*b8 - 8*b4**3 - 27*b6**2 + 9*b2*b4*b61209return self.__discriminant12101211def j_invariant(self):1212r"""1213Returns the `j`-invariant of this elliptic curve.12141215EXAMPLES::12161217sage: E = EllipticCurve([0,0,1,-1,0])1218sage: E.j_invariant()1219110592/371220sage: E = EllipticCurve([0, -1, 1, -10, -20])1221sage: E.j_invariant()1222-122023936/1610511223sage: E = EllipticCurve([-4,0])1224sage: E.j_invariant()1225172812261227::12281229sage: E = EllipticCurve([GF(7)(2),1])1230sage: E.j_invariant()123111232"""1233try:1234return self.__j_invariant1235except AttributeError:1236c4, _ = self.c_invariants()1237self.__j_invariant = c4**3 / self.discriminant()1238return self.__j_invariant123912401241def base_extend(self, R):1242r"""1243Returns a new curve with the same `a`-invariants but defined over a new ring.12441245INPUT:12461247- ``R`` -- either a ring into which the curve's `a`-invariants1248may be coerced, or a morphism which may be applied to them.12491250OUTPUT:12511252A new elliptic curve with the same `a`-invariants, defined over the new ring.12531254EXAMPLES::12551256sage: E=EllipticCurve(GF(5),[1,1]); E1257Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 51258sage: E1=E.base_extend(GF(125,'a')); E11259Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 5^31260sage: F2=GF(5^2,'a'); a=F2.gen()1261sage: F4=GF(5^4,'b'); b=F4.gen()1262sage: h=F2.hom([a.charpoly().roots(ring=F4,multiplicities=False)[0]],F4)1263sage: E=EllipticCurve(F2,[1,a]); E1264Elliptic Curve defined by y^2 = x^3 + x + a over Finite Field in a of size 5^21265sage: E.base_extend(h)1266Elliptic Curve defined by y^2 = x^3 + x + (4*b^3+4*b^2+4*b+3) over Finite Field in b of size 5^41267"""1268return constructor.EllipticCurve([R(a) for a in self.a_invariants()])12691270change_ring = base_extend12711272def base_ring(self):1273r"""1274Returns the base ring of the elliptic curve.12751276EXAMPLES::12771278sage: E = EllipticCurve(GF(49, 'a'), [3,5])1279sage: E.base_ring()1280Finite Field in a of size 7^212811282::12831284sage: E = EllipticCurve([1,1])1285sage: E.base_ring()1286Rational Field12871288::12891290sage: E = EllipticCurve(ZZ, [3,5])1291sage: E.base_ring()1292Integer Ring1293"""1294return self.__base_ring12951296def gens(self):1297r"""1298Placeholder function to return generators of an elliptic curve.12991300.. note::13011302This functionality is implemented in certain derived1303classes, such as EllipticCurve_rational_field.13041305EXAMPLES::13061307sage: R.<a1,a2,a3,a4,a6>=QQ[]1308sage: E=EllipticCurve([a1,a2,a3,a4,a6])1309sage: E.gens()1310Traceback (most recent call last):1311...1312NotImplementedError: not implemented.1313sage: E=EllipticCurve(QQ,[1,1])1314sage: E.gens()1315[(0 : 1 : 1)]1316"""1317raise NotImplementedError, "not implemented."13181319def gen(self, i):1320r"""1321Function returning the i'th generator of this elliptic curve.13221323.. note::13241325Relies on gens() being implemented.13261327EXAMPLES::13281329sage: R.<a1,a2,a3,a4,a6>=QQ[]1330sage: E=EllipticCurve([a1,a2,a3,a4,a6])1331sage: E.gen(0)1332Traceback (most recent call last):1333...1334NotImplementedError: not implemented.1335"""1336return self.gens()[i]13371338def rst_transform(self, r, s, t):1339r"""1340Returns the transform of the curve by `(r,s,t)` (with `u=1`).13411342INPUT:13431344- ``r``, ``s``, ``t`` -- three elements of the base ring.13451346OUTPUT:13471348The elliptic curve obtained from self by the standard1349Weierstrass transformation `(u,r,s,t)` with `u=1`.13501351.. note::13521353This is just a special case of ``change_weierstrass_model()``, with `u=1`.13541355EXAMPLES::13561357sage: R.<r,s,t>=QQ[]1358sage: E=EllipticCurve([1,2,3,4,5])1359sage: E.rst_transform(r,s,t)1360Elliptic Curve defined by y^2 + (2*s+1)*x*y + (r+2*t+3)*y = x^3 + (-s^2+3*r-s+2)*x^2 + (3*r^2-r*s-2*s*t+4*r-3*s-t+4)*x + (r^3+2*r^2-r*t-t^2+4*r-3*t+5) over Multivariate Polynomial Ring in r, s, t over Rational Field1361"""1362return self.change_weierstrass_model(1,r,s,t)13631364def scale_curve(self, u):1365r"""1366Returns the transform of the curve by scale factor `u`.13671368INPUT:13691370- ``u`` -- an invertible element of the base ring.13711372OUTPUT:13731374The elliptic curve obtained from self by the standard1375Weierstrass transformation `(u,r,s,t)` with `r=s=t=0`.13761377.. note::13781379This is just a special case of ``change_weierstrass_model()``, with `r=s=t=0`.13801381EXAMPLES::13821383sage: K=Frac(PolynomialRing(QQ,'u'))1384sage: u=K.gen()1385sage: E=EllipticCurve([1,2,3,4,5])1386sage: E.scale_curve(u)1387Elliptic Curve defined by y^2 + u*x*y + 3*u^3*y = x^3 + 2*u^2*x^2 + 4*u^4*x + 5*u^6 over Fraction Field of Univariate Polynomial Ring in u over Rational Field1388"""1389if isinstance(u, (int,long)):1390u=self.base_ring()(u) # because otherwise 1/u would round!1391return self.change_weierstrass_model(1/u,0,0,0)13921393def discriminant(self):1394r"""1395Returns the discriminant of this elliptic curve.13961397EXAMPLES::13981399sage: E = EllipticCurve([0,0,1,-1,0])1400sage: E.discriminant()1401371402sage: E = EllipticCurve([0, -1, 1, -10, -20])1403sage: E.discriminant()1404-16105114051406::14071408sage: E = EllipticCurve([GF(7)(2),1])1409sage: E.discriminant()141011411"""1412try:1413return self.__discriminant1414except AttributeError:1415b2, b4, b6, b8 = self.b_invariants()1416self.__discriminant = -b2**2*b8 - 8*b4**3 - 27*b6**2 + 9*b2*b4*b61417return self.__discriminant14181419def j_invariant(self):1420r"""1421Returns the j-invariant of this elliptic curve.14221423EXAMPLES::14241425sage: E = EllipticCurve([0,0,1,-1,0])1426sage: E.j_invariant()1427110592/371428sage: E = EllipticCurve([0, -1, 1, -10, -20])1429sage: E.j_invariant()1430-122023936/1610511431sage: E = EllipticCurve([-4,0])1432sage: E.j_invariant()1433172814341435::14361437sage: E = EllipticCurve([GF(7)(2),1])1438sage: E.j_invariant()143911440"""1441try:1442return self.__j_invariant1443except AttributeError:1444c4, _ = self.c_invariants()1445self.__j_invariant = c4**3 / self.discriminant()1446return self.__j_invariant14471448#############################################################1449#1450# Explanation of the division (also known as torsion) polynomial1451# functions in Sage.1452#1453# The main user function division_polynomial() (also aliased as1454# torsion_polynomial()) is used to compute polynomials whose roots1455# determine the $m$-torsion points on the curve. Three options are1456# available, which effect the result when $m$ is even and also the1457# parent ring of the returned value. The function can return either a1458# polynomial or the evaluation of that polynomial at a point,1459# depending on the input. Values are cached.1460#1461# The options are controlled by the value of the parameter1462# two_torsion_multiplicity, which may be 0, 1 or 2. If it is 0 or 2,1463# then a univariate polynomial will be returned (or evaluated at the1464# parameter x if x is not None). This is the polynomial whose roots1465# are the values of $x(P)$ at the nonzero points $P$ where $m*P=0$1466# (when two_torsion_multiplicity==2), or the points where $m*P=0$ but1467# $2*P\not=0$ (when two_torsion_multiplicity==0).1468#1469# If two_torsion_multiplicity==1, then a bivariate polynomial is1470# returned, which (as a function on the curve) has a simple zero at1471# each nonzero point $P$ such that $m*P=0$. When $m$ is odd this is a1472# polynomial in $x$ alone, but is still returned as an element of a1473# polynomial ring in two variables; when $m$ is even it has a factor1474# $2y+a_1x+a_3$. In this case if the parameter x is not None then it1475# should be a tuple of length 2, or a point P on the curve, and the1476# returned value is the value of the bivariate polynomial at this1477# point.1478#1479# Comparison with Magma: Magma's function DivisionPolynomial(E,m)1480# returns a triple of univariate polynomials $f,g,h$ where $f$ is1481# \code{E.division_polynomial(m,two_torsion_multiplicity=2)}, $g$ is1482# \code{E.division_polynomial(m,two_torsion_multiplicity=0)} and $h$1483# is the quotient, so that $h=1$ when $m$ is odd.14841485#############################################################14861487def division_polynomial_0(self, n, x=None, cache=None):1488r"""1489Returns the `n^{th}` torsion (division) polynomial, without1490the 2-torsion factor if `n` is even, as a polynomial in `x`.14911492These are the polynomials `g_n` defined in Mazur/Tate1493("The p-adic sigma function"), but with the sign flipped for even1494`n`, so that the leading coefficient is always positive.14951496.. note::14971498This function is intended for internal use; users should use1499:meth:`.division_polynomial`.15001501.. seealso::15021503:meth:`multiple_x_numerator`1504:meth:`multiple_x_denominator`1505:meth:`division_polynomial`15061507INPUT:150815091510- ``n`` - positive integer, or the special values `-1`1511and `-2` which mean `B_6 = (2y + a_1 x + a_3)^2` and1512`B_6^2` respectively (in the notation of Mazur/Tate).15131514- ``x`` - optional ring element to use as the "x"1515variable. If x is None, then a new polynomial ring will be1516constructed over the base ring of the elliptic curve, and its1517generator will be used as x. Note that x does not need to be a1518generator of a polynomial ring; any ring element is ok. This1519permits fast calculation of the torsion polynomial *evaluated* on1520any element of a ring.15211522- ``cache`` - optional dictionary, with integer keys.1523If the key m is in cache, then cache[m] is assumed to be the value1524of division_polynomial_0(m) for the supplied x. New entries will1525be added to the cache as they are computed.152615271528ALGORITHM:15291530Recursion described in Mazur/Tate. The recursive1531formulae are evaluated `O((log n)^2)` times.15321533AUTHORS:15341535- David Harvey (2006-09-24): initial version15361537- John Cremona (2008-08-26): unified division polynomial code15381539EXAMPLES::15401541sage: E = EllipticCurve("37a")1542sage: E.division_polynomial_0(1)154311544sage: E.division_polynomial_0(2)154511546sage: E.division_polynomial_0(3)15473*x^4 - 6*x^2 + 3*x - 11548sage: E.division_polynomial_0(4)15492*x^6 - 10*x^4 + 10*x^3 - 10*x^2 + 2*x + 11550sage: E.division_polynomial_0(5)15515*x^12 - 62*x^10 + 95*x^9 - 105*x^8 - 60*x^7 + 285*x^6 - 174*x^5 - 5*x^4 - 5*x^3 + 35*x^2 - 15*x + 21552sage: E.division_polynomial_0(6)15533*x^16 - 72*x^14 + 168*x^13 - 364*x^12 + 1120*x^10 - 1144*x^9 + 300*x^8 - 540*x^7 + 1120*x^6 - 588*x^5 - 133*x^4 + 252*x^3 - 114*x^2 + 22*x - 11554sage: E.division_polynomial_0(7)15557*x^24 - 308*x^22 + 986*x^21 - 2954*x^20 + 28*x^19 + 17171*x^18 - 23142*x^17 + 511*x^16 - 5012*x^15 + 43804*x^14 - 7140*x^13 - 96950*x^12 + 111356*x^11 - 19516*x^10 - 49707*x^9 + 40054*x^8 - 124*x^7 - 18382*x^6 + 13342*x^5 - 4816*x^4 + 1099*x^3 - 210*x^2 + 35*x - 31556sage: E.division_polynomial_0(8)15574*x^30 - 292*x^28 + 1252*x^27 - 5436*x^26 + 2340*x^25 + 39834*x^24 - 79560*x^23 + 51432*x^22 - 142896*x^21 + 451596*x^20 - 212040*x^19 - 1005316*x^18 + 1726416*x^17 - 671160*x^16 - 954924*x^15 + 1119552*x^14 + 313308*x^13 - 1502818*x^12 + 1189908*x^11 - 160152*x^10 - 399176*x^9 + 386142*x^8 - 220128*x^7 + 99558*x^6 - 33528*x^5 + 6042*x^4 + 310*x^3 - 406*x^2 + 78*x - 515581559::15601561sage: E.division_polynomial_0(18) % E.division_polynomial_0(6) == 01562True15631564An example to illustrate the relationship with torsion points::15651566sage: F = GF(11)1567sage: E = EllipticCurve(F, [0, 2]); E1568Elliptic Curve defined by y^2 = x^3 + 2 over Finite Field of size 111569sage: f = E.division_polynomial_0(5); f15705*x^12 + x^9 + 8*x^6 + 4*x^3 + 71571sage: f.factor()1572(5) * (x^2 + 5) * (x^2 + 2*x + 5) * (x^2 + 5*x + 7) * (x^2 + 7*x + 7) * (x^2 + 9*x + 5) * (x^2 + 10*x + 7)15731574This indicates that the x-coordinates of all the 5-torsion points1575of `E` are in `GF(11^2)`, and therefore the1576`y`-coordinates are in `\GF(11^4)`::15771578sage: K = GF(11^4, 'a')1579sage: X = E.change_ring(K)1580sage: f = X.division_polynomial_0(5)1581sage: x_coords = f.roots(multiplicities=False); x_coords1582[10*a^3 + 4*a^2 + 5*a + 6,15839*a^3 + 8*a^2 + 10*a + 8,15848*a^3 + a^2 + 4*a + 10,15858*a^3 + a^2 + 4*a + 8,15868*a^3 + a^2 + 4*a + 4,15876*a^3 + 9*a^2 + 3*a + 4,15885*a^3 + 2*a^2 + 8*a + 7,15893*a^3 + 10*a^2 + 7*a + 8,15903*a^3 + 10*a^2 + 7*a + 3,15913*a^3 + 10*a^2 + 7*a + 1,15922*a^3 + 3*a^2 + a + 7,1593a^3 + 7*a^2 + 6*a]15941595Now we check that these are exactly the `x`-coordinates of the15965-torsion points of `E`::15971598sage: for x in x_coords:1599... assert X.lift_x(x).order() == 516001601The roots of the polynomial are the `x`-coordinates of the points `P`1602such that `mP=0` but `2P\not=0`::16031604sage: E=EllipticCurve('14a1')1605sage: T=E.torsion_subgroup()1606sage: [n*T.0 for n in range(6)]1607[(0 : 1 : 0),1608(9 : 23 : 1),1609(2 : 2 : 1),1610(1 : -1 : 1),1611(2 : -5 : 1),1612(9 : -33 : 1)]1613sage: pol=E.division_polynomial_0(6)1614sage: xlist=pol.roots(multiplicities=False); xlist1615[9, 2, -1/3, -5]1616sage: [E.lift_x(x, all=True) for x in xlist]1617[[(9 : 23 : 1), (9 : -33 : 1)], [(2 : 2 : 1), (2 : -5 : 1)], [], []]16181619.. note::16201621The point of order 2 and the identity do not appear.1622The points with `x=-1/3` and `x=-5` are not rational.1623"""1624if cache is None:1625cache = {}1626else:1627try:1628return cache[n]1629except KeyError:1630pass16311632if x is None:1633x = rings.PolynomialRing(self.base_ring(), 'x').gen()16341635b2, b4, b6, b8 = self.b_invariants()16361637n = int(n)1638if n <= 4:1639if n == -1:1640answer = 4*x**3 + b2*x**2 + 2*b4*x + b61641elif n == -2:1642answer = self.division_polynomial_0(-1, x, cache) ** 21643elif n == 1 or n == 2:1644answer = x.parent()(1)1645elif n == 3:1646answer = 3*x**4 + b2*x**3 + 3*b4*x**2 + 3*b6*x + b81647elif n == 4:1648answer = -self.division_polynomial_0(-2, x, cache) + \1649(6*x**2 + b2*x + b4) * \1650self.division_polynomial_0(3, x, cache)1651else:1652raise ValueError, "n must be a positive integer (or -1 or -2)"1653else:1654if n % 2 == 0:1655m = (n-2) // 21656g_mplus3 = self.division_polynomial_0(m+3, x, cache)1657g_mplus2 = self.division_polynomial_0(m+2, x, cache)1658g_mplus1 = self.division_polynomial_0(m+1, x, cache)1659g_m = self.division_polynomial_0(m, x, cache)1660g_mless1 = self.division_polynomial_0(m-1, x, cache)1661answer = g_mplus1 * \1662(g_mplus3 * g_m**2 - g_mless1 * g_mplus2**2)1663else:1664m = (n-1) // 21665g_mplus2 = self.division_polynomial_0(m+2, x, cache)1666g_mplus1 = self.division_polynomial_0(m+1, x, cache)1667g_m = self.division_polynomial_0(m, x, cache)1668g_mless1 = self.division_polynomial_0(m-1, x, cache)1669B6_sqr = self.division_polynomial_0(-2, x, cache)1670if m % 2 == 0:1671answer = B6_sqr * g_mplus2 * g_m**3 - \1672g_mless1 * g_mplus1**31673else:1674answer = g_mplus2 * g_m**3 - \1675B6_sqr * g_mless1 * g_mplus1**316761677cache[n] = answer1678return answer16791680def two_division_polynomial(self, x = None):1681r"""1682Returns the 2-division polynomial of this elliptic curve evaluated1683at ``x``.16841685INPUT:16861687- ``x`` - optional ring element to use as the `x` variable. If1688``x`` is ``None``, then a new polynomial ring will be1689constructed over the base ring of the elliptic curve, and1690its generator will be used as ``x``. Note that ``x`` does1691not need to be a generator of a polynomial ring; any ring1692element is ok. This permits fast calculation of the torsion1693polynomial *evaluated* on any element of a ring.169416951696EXAMPLES::16971698sage: E=EllipticCurve('5077a1')1699sage: E.two_division_polynomial()17004*x^3 - 28*x + 251701sage: E=EllipticCurve(GF(3^2,'a'),[1,1,1,1,1])1702sage: E.two_division_polynomial()1703x^3 + 2*x^2 + 21704sage: E.two_division_polynomial().roots()1705[(2, 1), (2*a, 1), (a + 2, 1)]1706"""1707return self.division_polynomial_0(-1,x)17081709def division_polynomial(self, m, x=None, two_torsion_multiplicity=2):1710r"""1711Returns the `m^{th}` division polynomial of this elliptic1712curve evaluated at ``x``.17131714INPUT:171517161717- ``m`` - positive integer.17181719- ``x`` - optional ring element to use as the "x"1720variable. If x is None, then a new polynomial ring will be1721constructed over the base ring of the elliptic curve, and its1722generator will be used as x. Note that x does not need to be a1723generator of a polynomial ring; any ring element is ok. This1724permits fast calculation of the torsion polynomial *evaluated* on1725any element of a ring.17261727- ``two_torsion_multiplicity`` - 0,1 or 217281729If 0: for even `m` when x is None, a univariate polynomial1730over the base ring of the curve is returned, which omits1731factors whose roots are the `x`-coordinates of the1732`2`-torsion points. Similarly when `x` is not none, the1733evaluation of such a polynomial at `x` is returned.17341735If 2: for even `m` when x is None, a univariate polynomial1736over the base ring of the curve is returned, which includes a1737factor of degree 3 whose roots are the `x`-coordinates of1738the `2`-torsion points. Similarly when `x` is not1739none, the evaluation of such a polynomial at `x` is1740returned.17411742If 1: when x is None, a bivariate polynomial over the base1743ring of the curve is returned, which includes a factor1744`2*y+a1*x+a3` which has simple zeros at the `2`-torsion1745points. When `x` is not none, it should be a tuple of1746length 2, and the evaluation of such a polynomial at `x`1747is returned.17481749EXAMPLES::17501751sage: E = EllipticCurve([0,0,1,-1,0])1752sage: E.division_polynomial(1)175311754sage: E.division_polynomial(2, two_torsion_multiplicity=0)175511756sage: E.division_polynomial(2, two_torsion_multiplicity=1)17572*y + 11758sage: E.division_polynomial(2, two_torsion_multiplicity=2)17594*x^3 - 4*x + 11760sage: E.division_polynomial(2)17614*x^3 - 4*x + 11762sage: [E.division_polynomial(3, two_torsion_multiplicity=i) for i in range(3)]1763[3*x^4 - 6*x^2 + 3*x - 1, 3*x^4 - 6*x^2 + 3*x - 1, 3*x^4 - 6*x^2 + 3*x - 1]1764sage: [type(E.division_polynomial(3, two_torsion_multiplicity=i)) for i in range(3)]1765[<type 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>,1766<type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>,1767<type 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>]17681769::17701771sage: E = EllipticCurve([0, -1, 1, -10, -20])1772sage: R.<z>=PolynomialRing(QQ)1773sage: E.division_polynomial(4,z,0)17742*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 58211775sage: E.division_polynomial(4,z)17768*z^9 - 24*z^8 - 464*z^7 - 2758*z^6 + 6636*z^5 + 34356*z^4 + 53510*z^3 + 99714*z^2 + 351024*z + 45985917771778This does not work, since when two_torsion_multiplicity is 1, we1779compute a bivariate polynomial, and must evaluate at a tuple of1780length 2::17811782sage: E.division_polynomial(4,z,1)1783Traceback (most recent call last):1784...1785ValueError: x should be a tuple of length 2 (or None) when two_torsion_multiplicity is 11786sage: R.<z,w>=PolynomialRing(QQ,2)1787sage: E.division_polynomial(4,(z,w),1).factor()1788(2*w + 1) * (2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821)17891790We can also evaluate this bivariate polynomial at a point::17911792sage: P = E(5,5)1793sage: E.division_polynomial(4,P,two_torsion_multiplicity=1)1794-17715611795"""17961797if not two_torsion_multiplicity in [0,1,2]:1798raise ValueError, "two_torsion_multiplicity must be 0,1 or 2"17991800# Coerce the input m to be an integer1801m = rings.Integer(m)18021803if two_torsion_multiplicity == 0:1804try:1805return self.__divpoly0[(m,x)]1806except AttributeError:1807self.__divpoly0 = {}1808except KeyError:1809pass1810f = self.division_polynomial_0(m,x)1811self.__divpoly0[(m,x)] = f1812return f18131814if two_torsion_multiplicity == 1:1815try:1816return self.__divpoly1[(m,x)]1817except AttributeError:1818self.__divpoly1 = {}1819except KeyError:1820pass1821xy = x1822R, (x,y) = PolynomialRing(self.base_ring(), 2, 'x,y').objgens()1823a1,a2,a3,a4,a6 = self.a_invariants()1824f = self.division_polynomial_0(m,x)1825if m % 2 == 0:1826f *= (2*y+a1*x+a3)1827if xy is None:1828self.__divpoly1[(m,(x,y))] = f1829return f1830else:1831if isinstance(xy,tuple) and len(xy)==2 or isinstance(xy, ell_point.EllipticCurvePoint_field):1832fxy = f(xy[0],xy[1])1833self.__divpoly1[(m,xy)] = fxy1834return fxy1835else:1836raise ValueError, "x should be a tuple of length 2 (or None) when two_torsion_multiplicity is 1"18371838if two_torsion_multiplicity == 2:1839try:1840return self.__divpoly2[(m,x)]1841except AttributeError:1842self.__divpoly2 = {}1843except KeyError:1844pass1845f = self.division_polynomial_0(m,x)1846if m%2 == 0:1847f *= self.division_polynomial_0(-1,x)1848self.__divpoly2[(m,x)] = f1849return f18501851torsion_polynomial = division_polynomial18521853def _multiple_x_numerator(self, n, x=None, cache=None):1854r"""1855Returns the numerator of the `x`-coordinate of the `n\th` multiple of a1856point, using torsion polynomials (division polynomials).18571858INPUT:18591860- ``n``, ``x``, ``cache`` -- as described in ``division_polynomial_0()``.18611862The result is cached. This is so that on calling1863``P.division_points(n)`` for the same `n` and different1864points `P` (on the same curve), we do not have to recompute1865the polynomials.18661867.. warning::18681869There may of course be cancellation between the numerator1870and the denominator (_multiple_x_denominator()). Be1871careful. E.g. if a point on an elliptic curve with1872coefficients in ZZ reduces to a singular point modulo a1873prime, then there will be cancellation, otherwise not, see1874Chris Wuthrich' p-adic heights in families of elliptic1875curves'.18761877.. seealso::18781879:meth:`_multiple_x_denominator`18801881AUTHORS:18821883- David Harvey (2006-09-24)18841885EXAMPLES::18861887sage: E = EllipticCurve("37a")1888sage: P = E.gens()[0]1889sage: x = P[0]18901891::18921893sage: (35*P)[0]1894-804287518035141565236193151/10631982599010279006006657961895sage: E._multiple_x_numerator(35, x)1896-8042875180351415652361931511897sage: E._multiple_x_denominator(35, x)1898106319825990102790060066579618991900::19011902sage: (36*P)[0]190354202648602164057575419038802/154025439973241468921987904011904sage: E._multiple_x_numerator(36, x)1905542026486021640575754190388021906sage: E._multiple_x_denominator(36, x)19071540254399732414689219879040119081909An example where cancellation occurs::19101911sage: E = EllipticCurve("88a1")1912sage: P = E([2,2]) # fixed choice of generator1913sage: n = E._multiple_x_numerator(11, P[0]); n19144424467847388475631280686505293434922786514534401915sage: d = E._multiple_x_denominator(11, P[0]); d191614272476927059598810582859694494951363827466241917sage: n/d19183101919sage: 11*P1920(310 : -5458 : 1)1921"""1922try:1923return self._mul_x_num_cache[n]1924except AttributeError:1925self._mul_x_num_cache = {}1926except KeyError:1927pass19281929if cache is None:1930cache = {}19311932if x is None:1933x = rings.PolynomialRing(self.base_ring(), 'x').gen()19341935n = int(n)1936if n < 2:1937print "n must be at least 2"19381939self.division_polynomial_0( -2, x, cache)1940self.division_polynomial_0(n-1, x, cache)1941self.division_polynomial_0(n , x, cache)1942self.division_polynomial_0(n+1, x, cache)19431944if n % 2 == 0:1945self._mul_x_num_cache[n] = x * cache[-1] * cache[n]**2 - cache[n-1] * cache[n+1]1946else:1947self._mul_x_num_cache[n] = x * cache[n]**2 - cache[-1] * cache[n-1] * cache[n+1]1948return self._mul_x_num_cache[n]194919501951def _multiple_x_denominator(self, n, x=None, cache=None):1952r"""1953Returns the denominator of the x-coordinate of the nth multiple of1954a point, using torsion polynomials (division polynomials).19551956INPUT:19571958- ``n``, ``x``, ``cache`` -- as described in ``division_polynomial_0()``.19591960The result is cached. This is so that calling1961P.division_points(n) for the same n and different points P1962(on the same curve) does not have to recompute the1963polynomials.19641965.. seealso::19661967:meth:`multiple_x_numerator`19681969TODO: the numerator and denominator versions share a calculation,1970namely squaring `\psi_n`. Maybe would be good to offer a1971combined version to make this more efficient.19721973EXAMPLES::19741975sage: E = EllipticCurve("43a")1976sage: P = E.gens()[0]1977sage: x = P[0]1978sage: (31*P)[0]1979-33058398375463796474831580/1546936377542239700569753211980sage: E._multiple_x_numerator(31, x)1981-330583983754637964748315801982sage: E._multiple_x_denominator(31, x)198315469363775422397005697532119841985AUTHORS:19861987- David Harvey (2006-09-24)1988"""1989try:1990return self._mul_x_den_cache[n]1991except AttributeError:1992self._mul_x_den_cache = {}1993except KeyError:1994pass19951996if cache is None:1997cache = {}19981999if x is None:2000x = rings.PolynomialRing(self.base_ring(), 'x').gen()20012002n = int(n)2003if n < 2:2004print "n must be at least 2"20052006self.division_polynomial_0(-2, x, cache)2007self.division_polynomial_0(n , x, cache)20082009if n % 2 == 0:2010self._mul_x_den_cache[n] = cache[-1] * cache[n]**22011else:2012self._mul_x_den_cache[n] = cache[n]**22013return self._mul_x_den_cache[n]201420152016def multiplication_by_m(self, m, x_only=False):2017r"""2018Return the multiplication-by-`m` map from self to self as a pair of2019rational functions in two variables `x`,`y`.20202021INPUT:20222023- ``m`` - a nonzero integer20242025- ``x_only`` - bool (default: False) if True, return2026only the `x`-coordinate of the map.202720282029OUTPUT:20302031(2-tuple) `(f(x), g(x,y))`, where `f` and `g` are rational2032functions with the degree of `y` in `g(x,y)` exactly 1.203320342035.. note:20362037The result is not cached.20382039``m`` is allowed to be negative (but not 0).20402041EXAMPLES::20422043sage: E = EllipticCurve([-1,3])20442045We verify that multiplication by 1 is just the identity::20462047sage: E.multiplication_by_m(1)2048(x, y)20492050Multiplication by 2 is more complicated::20512052sage: f = E.multiplication_by_m(2)2053sage: f2054((x^4 + 2*x^2 - 24*x + 1)/(4*x^3 - 4*x + 12), (8*x^6*y - 40*x^4*y + 480*x^3*y - 40*x^2*y + 96*x*y - 568*y)/(64*x^6 - 128*x^4 + 384*x^3 + 64*x^2 - 384*x + 576))20552056Grab only the x-coordinate (less work)::20572058sage: E.multiplication_by_m(2, x_only=True)2059(x^4 + 2*x^2 - 24*x + 1)/(4*x^3 - 4*x + 12)20602061We check that it works on a point::20622063sage: P = E([2,3])2064sage: eval = lambda f,P: [fi(P[0],P[1]) for fi in f]2065sage: assert E(eval(f,P)) == 2*P20662067We do the same but with multiplication by 3::20682069sage: f = E.multiplication_by_m(3)2070sage: assert E(eval(f,P)) == 3*P20712072And the same with multiplication by 4::20732074sage: f = E.multiplication_by_m(4)2075sage: assert E(eval(f,P)) == 4*P20762077And the same with multiplication by -1,-2,-3,-4::20782079sage: for m in [-1,-2,-3,-4]:2080... f = E.multiplication_by_m(m)2081... assert E(eval(f,P)) == m*P20822083TESTS:20842085Verify for this fairly random looking curve and point that2086multiplication by m returns the right result for the first 102087integers::20882089sage: E = EllipticCurve([23,-105])2090sage: P = E([129/4, 1479/8])2091sage: for n in [1..10]:2092... f = E.multiplication_by_m(n)2093... Q = n*P2094... assert Q == E(eval(f,P))2095... f = E.multiplication_by_m(-n)2096... Q = -n*P2097... assert Q == E(eval(f,P))20982099The following test shows that \#4364 is indeed fixed::21002101sage: p = next_prime(2^30-41)2102sage: a = GF(p)(1)2103sage: b = GF(p)(1)2104sage: E = EllipticCurve([a, b])2105sage: P = E.random_point()2106sage: my_eval = lambda f,P: [fi(P[0],P[1]) for fi in f]2107sage: f = E.multiplication_by_m(2)2108sage: assert(E(eval(f,P)) == 2*P)2109"""2110# Coerce the input m to be an integer2111m = rings.Integer(m)21122113if m==0:2114raise ValueError, "m must be a non-zero integer"21152116R = PolynomialRing(self.base_ring(), 2, 'x,y')21172118# Kxy is the function field, containing the full division polynomial.2119Kxy = R.fraction_field()2120x,y = Kxy.gens()21212122# Special case of multiplication by 1 is easy.2123if m == 1:2124return (x, y)21252126# Grab curve invariants2127a1,a2,a3,a4,a6 = self.a_invariants()21282129if m == -1:2130return (x, -y-a1*x-a3)21312132# the x-coordinate does not depend on the sign of m. The work2133# here is done by functions defined earlier:21342135mx = self._multiple_x_numerator(m.abs(),x) / self._multiple_x_denominator(m.abs(),x)21362137if x_only:2138# Return it if the optional parameter x_only is set.2139return mx21402141# Consideration of the invariant differential2142# w=dx/(2*y+a1*x+a3) shows that m*w = d(mx)/(2*my+a1*mx+a3)2143# and hence 2*my+a1*mx+a3 = (1/m)*(2*y+a1*x+a3)*d(mx)/dx21442145my = ((2*y+a1*x+a3)*mx.derivative(x)/m - a1*mx-a3)/221462147return mx, my21482149def multiplication_by_m_isogeny(self, m):2150r"""2151Return the ``EllipticCurveIsogeny`` object associated to the2152multiplication-by-`m` map on self. The resulting isogeny will2153have the associated rational maps (i.e. those returned by2154`self.multiplication_by_m()`) already computed.21552156NOTE: This function is currently *much* slower than the2157result of ``self.multiplication_by_m()``, because2158constructing an isogeny precomputes a significant amount2159of information. See trac tickets #7368 and #8014 for the2160status of improving this situation.21612162INPUT:21632164- ``m`` - a nonzero integer21652166OUTPUT:21672168- An ``EllipticCurveIsogeny`` object associated to the2169multiplication-by-`m` map on self.21702171EXAMPLES::21722173sage: E = EllipticCurve('11a1')2174sage: E.multiplication_by_m_isogeny(7)2175Isogeny of degree 49 from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field21762177"""2178mx, my = self.multiplication_by_m(m)21792180torsion_poly = self.torsion_polynomial(m).monic()2181phi = self.isogeny(torsion_poly, codomain=self)2182phi._EllipticCurveIsogeny__initialize_rational_maps(precomputed_maps=(mx, my))21832184return phi21852186def isomorphism_to(self, other):2187"""2188Given another weierstrass model ``other`` of self, return an2189isomorphism from self to ``other``.21902191INPUT:21922193- ``other`` -- an elliptic curve isomorphic to ``self``.21942195OUTPUT:21962197(Weierstrassmorphism) An isomorphism from self to other.21982199.. note::22002201If the curves in question are not isomorphic, a ValueError is raised.22022203EXAMPLES::22042205sage: E = EllipticCurve('37a')2206sage: F = E.short_weierstrass_model()2207sage: w = E.isomorphism_to(F); w2208Generic morphism:2209From: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field2210To: Abelian group of points on Elliptic Curve defined by y^2 = x^3 - 16*x + 16 over Rational Field2211Via: (u,r,s,t) = (1/2, 0, 0, -1/2)2212sage: P = E(0,-1,1)2213sage: w(P)2214(0 : -4 : 1)2215sage: w(5*P)2216(1 : 1 : 1)2217sage: 5*w(P)2218(1 : 1 : 1)2219sage: 120*w(P) == w(120*P)2220True22212222We can also handle injections to different base rings::22232224sage: K.<a> = NumberField(x^3-7)2225sage: E.isomorphism_to(E.change_ring(K))2226Generic morphism:2227From: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field2228To: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 + (-1)*x over Number Field in a with defining polynomial x^3 - 72229Via: (u,r,s,t) = (1, 0, 0, 0)2230"""2231return wm.WeierstrassIsomorphism(self, None, other)22322233def automorphisms(self, field=None):2234"""2235Return the set of isomorphisms from self to itself (as a list).22362237INPUT:22382239- ``field`` (default None) -- a field into which the2240coefficients of the curve may be coerced (by default, uses2241the base field of the curve).22422243OUTPUT:22442245(list) A list of ``WeierstrassIsomorphism`` objects2246consisting of all the isomorphisms from the curve ``self`` to2247itself defined over ``field``.22482249EXAMPLES::22502251sage: E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ2252sage: E.automorphisms();2253[Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Rational Field2254Via: (u,r,s,t) = (-1, 0, 0, -1), Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Rational Field2255Via: (u,r,s,t) = (1, 0, 0, 0)]22562257We can also find automorphisms defined over extension fields::22582259sage: K.<a> = NumberField(x^2+3) # adjoin roots of unity2260sage: E.automorphisms(K)2261[Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 32262Via: (u,r,s,t) = (1, 0, 0, 0),2263...2264Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 32265Via: (u,r,s,t) = (-1/2*a - 1/2, 0, 0, 0)]22662267::22682269sage: [ len(EllipticCurve_from_j(GF(q,'a')(0)).automorphisms()) for q in [2,4,3,9,5,25,7,49]]2270[2, 24, 2, 12, 2, 6, 6, 6]2271"""2272if field==None:2273return [wm.WeierstrassIsomorphism(self, urst, self)2274for urst in wm.isomorphisms(self,self)]2275E=self.change_ring(field)2276return [wm.WeierstrassIsomorphism(E, urst, E)2277for urst in wm.isomorphisms(E,E)]22782279def isomorphisms(self, other, field=None):2280"""2281Return the set of isomorphisms from self to other (as a list).22822283INPUT:22842285- ``other`` -- another elliptic curve.22862287- ``field`` (default None) -- a field into which the2288coefficients of the curves may be coerced (by default, uses2289the base field of the curves).22902291OUTPUT:22922293(list) A list of ``WeierstrassIsomorphism`` objects consisting of all2294the isomorphisms from the curve ``self`` to the curve2295``other`` defined over ``field``.22962297EXAMPLES::22982299sage: E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ2300sage: F = EllipticCurve('27a3') # should be the same one2301sage: E.isomorphisms(F);2302[Generic morphism:2303From: Abelian group of points on Elliptic Curve defined2304by y^2 + y = x^3 over Rational Field2305To: Abelian group of points on Elliptic Curve defined2306by y^2 + y = x^3 over Rational Field2307Via: (u,r,s,t) = (-1, 0, 0, -1), Generic morphism:2308From: Abelian group of points on Elliptic Curve defined2309by y^2 + y = x^3 over Rational Field2310To: Abelian group of points on Elliptic Curve defined2311by y^2 + y = x^3 over Rational Field2312Via: (u,r,s,t) = (1, 0, 0, 0)]231323142315We can also find isomorphisms defined over extension fields::23162317sage: E=EllipticCurve(GF(7),[0,0,0,1,1])2318sage: F=EllipticCurve(GF(7),[0,0,0,1,-1])2319sage: E.isomorphisms(F)2320[]2321sage: E.isomorphisms(F,GF(49,'a'))2322[Generic morphism:2323From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 7^22324To: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 6 over Finite Field in a of size 7^22325Via: (u,r,s,t) = (a + 3, 0, 0, 0), Generic morphism:2326From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 7^22327To: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 6 over Finite Field in a of size 7^22328Via: (u,r,s,t) = (6*a + 4, 0, 0, 0)]2329"""2330if field==None:2331return [wm.WeierstrassIsomorphism(self, urst, other)2332for urst in wm.isomorphisms(self,other)]2333E=self.change_ring(field)2334F=other.change_ring(field)2335return [wm.WeierstrassIsomorphism(E, urst, F)2336for urst in wm.isomorphisms(E,F)]23372338def is_isomorphic(self, other, field=None):2339"""2340Returns whether or not self is isomorphic to other.23412342INPUT:23432344- ``other`` -- another elliptic curve.23452346- ``field`` (default None) -- a field into which the2347coefficients of the curves may be coerced (by default, uses2348the base field of the curves).23492350OUTPUT:23512352(bool) True if there is an isomorphism from curve ``self`` to2353curve ``other`` defined over ``field``.23542355EXAMPLES::23562357sage: E = EllipticCurve('389a')2358sage: F = E.change_weierstrass_model([2,3,4,5]); F2359Elliptic Curve defined by y^2 + 4*x*y + 11/8*y = x^3 - 3/2*x^2 - 13/16*x over Rational Field2360sage: E.is_isomorphic(F)2361True2362sage: E.is_isomorphic(F.change_ring(CC))2363False2364"""2365if not is_EllipticCurve(other):2366return False2367if field==None:2368if self.base_ring() != other.base_ring():2369return False2370elif self.j_invariant() != other.j_invariant(): # easy check2371return False2372else:2373return wm.isomorphisms(self,other,True) != None2374else:2375E=self.base_extend(field)2376F=other.base_extend(field)2377if E.j_invariant() != F.j_invariant(): # easy check2378return False2379else:2380return wm.isomorphisms(E,other,F) != None23812382def change_weierstrass_model(self, *urst):2383r"""2384Return a new Weierstrass model of self under the standard transformation `(u,r,s,t)`23852386.. math::23872388(x,y) \mapsto (x',y') = (u^2x + r , u^3y + su^2x + t).238923902391EXAMPLES::23922393sage: E = EllipticCurve('15a')2394sage: F1 = E.change_weierstrass_model([1/2,0,0,0]); F12395Elliptic Curve defined by y^2 + 2*x*y + 8*y = x^3 + 4*x^2 - 160*x - 640 over Rational Field2396sage: F2 = E.change_weierstrass_model([7,2,1/3,5]); F22397Elliptic Curve defined by y^2 + 5/21*x*y + 13/343*y = x^3 + 59/441*x^2 - 10/7203*x - 58/117649 over Rational Field2398sage: F1.is_isomorphic(F2)2399True2400"""2401if isinstance(urst[0], (tuple, list)):2402urst = urst[0]2403return constructor.EllipticCurve((wm.baseWI(*urst))(self.ainvs()))24042405def short_weierstrass_model(self, complete_cube=True):2406"""2407Returns a short Weierstrass model for self.24082409INPUT:24102411- ``complete_cube`` - bool (default: True); for2412meaning, see below.24132414OUTPUT:24152416An elliptic curve.24172418If ``complete_cube=True``: Return a model of the form2419`y^2 = x^3 + a*x + b` for this curve. The characteristic2420must not be 2; in characteristic 3, it is only possible if `b_2=0`.24212422If ``complete_cube=False``: Return a model of the form2423`y^2 = x^3 + ax^2 + bx + c` for this curve. The2424characteristic must not be 2.24252426EXAMPLES::24272428sage: E = EllipticCurve([1,2,3,4,5])2429sage: print E2430Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field2431sage: F = E.short_weierstrass_model()2432sage: print F2433Elliptic Curve defined by y^2 = x^3 + 4941*x + 185166 over Rational Field2434sage: E.is_isomorphic(F)2435True2436sage: F = E.short_weierstrass_model(complete_cube=False)2437sage: print F2438Elliptic Curve defined by y^2 = x^3 + 9*x^2 + 88*x + 464 over Rational Field2439sage: print E.is_isomorphic(F)2440True24412442::24432444sage: E = EllipticCurve(GF(3),[1,2,3,4,5])2445sage: E.short_weierstrass_model(complete_cube=False)2446Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 324472448This used to be different see trac #3973::24492450sage: E.short_weierstrass_model()2451Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 324522453More tests in characteristic 3::24542455sage: E = EllipticCurve(GF(3),[0,2,1,2,1])2456sage: E.short_weierstrass_model()2457Traceback (most recent call last):2458...2459ValueError: short_weierstrass_model(): no short model for Elliptic Curve defined by y^2 + y = x^3 + 2*x^2 + 2*x + 1 over Finite Field of size 3 (characteristic is 3)2460sage: E.short_weierstrass_model(complete_cube=False)2461Elliptic Curve defined by y^2 = x^3 + 2*x^2 + 2*x + 2 over Finite Field of size 32462sage: E.short_weierstrass_model(complete_cube=False).is_isomorphic(E)2463True2464"""2465import constructor2466K = self.base_ring()24672468# any curve of the form y^2 = x^3 +.. is singular in characteristic 22469if K.characteristic() == 2:2470raise ValueError, "short_weierstrass_model(): no short model for %s (characteristic is %s)"%(self,K.characteristic())24712472# in characteristic 3 we can complete the square but we can only complete the cube if b2 is 02473if K.characteristic() == 3:2474b2,b4,b6,_ = self.b_invariants()2475if complete_cube and b2 != 0:2476raise ValueError, "short_weierstrass_model(): no short model for %s (characteristic is %s)"%(self,K.characteristic())2477else:2478return constructor.EllipticCurve([0,b2,0,8*b4,16*b6])24792480a1,a2,a3,_,_ = self.a_invariants()2481if complete_cube:2482if a1==0 and a2==0 and a3==0:2483return self2484else:2485b2,b4,b6,_ = self.b_invariants()2486if b2==0:2487return constructor.EllipticCurve([0,0,0,8*b4,16*b6])2488else:2489c4, c6 = self.c_invariants()2490return constructor.EllipticCurve([0,0,0,-27*c4, -54*c6])2491else:2492if a1==0 and a3==0:2493return self2494else:2495b2,b4,b6,_ = self.b_invariants()2496return constructor.EllipticCurve([0,b2,0,8*b4,16*b6])2497249824992500# Plotting250125022503def plot(self, xmin=None, xmax=None, components='both', **args):2504"""2505Draw a graph of this elliptic curve.25062507INPUT:25082509- ``xmin, xmax`` - (optional) points will be computed at2510least within this range, but possibly farther.25112512- ``components`` - a string, one of the following:25132514- ``both`` -- (default), scale so that both bounded and2515unbounded components appear25162517- ``bounded`` -- scale the plot to show the bounded2518component. Raises an error if there is only one real2519component.25202521- ``unbounded`` -- scale the plot to show the unbounded2522component, including the two flex points.25232524- ``plot_points`` -- passed to2525:func:`sage.plot.generate_plot_points`25262527- ``adaptive_tolerance`` -- passed to2528:func:`sage.plot.generate_plot_points`25292530- ``adaptive_recursion`` -- passed to2531:func:`sage.plot.generate_plot_points`25322533- ``randomize`` -- passed to2534:func:`sage.plot.generate_plot_points`25352536- ``**args`` - all other options are passed to2537:class:`sage.plot.line.Line`25382539EXAMPLES::25402541sage: E = EllipticCurve([0,-1])2542sage: plot(E, rgbcolor=hue(0.7))2543sage: E = EllipticCurve('37a')2544sage: plot(E)2545sage: plot(E, xmin=25,xmax=26)25462547With #12766 we added the components keyword::25482549sage: E.real_components()255022551sage: E.plot(components='bounded')2552sage: E.plot(components='unbounded')25532554If there is only one component then specifying2555components='bounded' raises a ValueError::25562557sage: E = EllipticCurve('9990be2')2558sage: E.plot(components='bounded')2559Traceback (most recent call last):2560...2561ValueError: no bounded component for this curve2562"""2563RR = rings.RealField()2564K = self.base_ring()2565try:2566RR._coerce_(K(1))2567except TypeError:2568raise NotImplementedError, "Plotting of curves over %s not implemented yet"%K2569if components not in ['both', 'bounded', 'unbounded']:2570raise ValueError("component must be one of 'both', 'bounded' or 'unbounded'")25712572a1, a2, a3, a4, a6 = self.ainvs()2573d = self.division_polynomial(2)2574# Internal function for plotting first branch of the curve2575f1 = lambda z: (-(a1*z + a3) + sqrt(abs(d(z))))/22576# Internal function for plotting second branch of the curve2577f2 = lambda z: (-(a1*z + a3) - sqrt(abs(d(z))))/22578r = d.roots(RR, multiplicities=False)2579r.sort()2580if components == 'bounded' and len(r) == 1:2581raise ValueError("no bounded component for this curve")2582if isinstance(xmin, (tuple, list)):2583if xmax is not None:2584raise ValueError("xmax must be None if xmin is a tuple")2585if len(xmin) != 2:2586raise ValueError("if xmin is a tuple it must have length 2")2587xmin, xmax = xmin2588if xmin is None or xmax is None:2589xmins = []2590xmaxs = []2591if components in ['both','bounded'] and len(r) > 1:2592xmins.append(r[0])2593xmaxs.append(r[1])25942595# The following 3 is an aesthetic choice. It's possible2596# that we should compute both of the following when2597# components=='both' and len(r) > 1 and take the maximum2598# generated xmax.2599if components == 'unbounded' or components == 'both' and (len(r) == 1 or r[2] - r[1] > 3*(r[1] - r[0])):2600flex = self.division_polynomial(3).roots(RR, multiplicities=False)2601flex.sort()2602flex = flex[-1]2603xmins.append(r[-1])2604# The doubling here is an aesthetic choice2605xmaxs.append(flex + 2*(flex - r[-1]))2606elif components == 'both':2607# First the easy part.2608xmins.append(r[-1])2609# There are two components and the unbounded component2610# is not too far from the bounded one. We scale so2611# that the unbounded component is twice as tall as the2612# bounded component. The y values corresponding to2613# horizontal tangent lines are determined as follows.2614# We implicitly differentiate the equation for this2615# curve and get2616# 2 yy' + a1 y + a1 xy' + a3 y' = 3 x^2 + 2a2 x + a426172618R = RR['x']2619x = R.gen()2620if a1 == 0:2621# a horizontal tangent line can only occur at a root of2622Ederiv = 3*x**2 + 2*a2*x + a42623else:2624# y' = 0 ==> y = (3*x^2 + 2*a2*x + a4) / a12625y = (3*x**2 + 2*a2*x + a4) / a12626Ederiv = y**2 + a1*x*y + a3*y - (x**3 + a2*x**2 + a4*x + a6)2627critx = [a for a in Ederiv.roots(RR, multiplicities=False) if r[0] < a < r[1]]2628if len(critx) == 0:2629raise RuntimeError("No horizontal tangent lines on bounded component")2630# The 2.5 here is an aesthetic choice2631ymax = 2.5 * max([f1(a) for a in critx])2632ymin = 2.5 * min([f2(a) for a in critx])2633top_branch = ymax**2 + a1*x*ymax + a3*ymax - (x**3 + a2*x**2 + a4*x + a6)2634bottom_branch = ymin**2 + a1*x*ymin + a3*ymin - (x**3 + a2*x**2 + a4*x + a6)2635xmaxs.append(max(top_branch.roots(RR,multiplicities=False) + bottom_branch.roots(RR,multiplicities=False)))2636xmins = min(xmins)2637xmaxs = max(xmaxs)2638span = xmaxs - xmins2639if xmin is None:2640xmin = xmins - .02*span2641if xmax is None:2642xmax = xmaxs + .02*span2643elif xmin >= xmax:2644raise ValueError("xmin must be less than xmax")26452646I = []2647if components in ['unbounded', 'both'] and xmax > r[-1]:2648# one real root; 1 component2649if xmin <= r[-1]:2650I.append((r[-1],xmax,'<'))2651else:2652I.append((xmin, xmax,'='))2653if components in ['bounded','both'] and len(r) > 1 and (xmin < r[1] or xmax > r[0]):2654if xmin <= r[0]:2655if xmax >= r[1]:2656I.append((r[0],r[1],'o'))2657else:2658I.append((r[0],xmax,'<'))2659elif xmax >= r[1]:2660I.append((xmin, r[1], '>'))2661else:2662I.append((xmin, xmax, '='))26632664g = plot.Graphics()2665plot_points = int(args.pop('plot_points',200))2666adaptive_tolerance = args.pop('adaptive_tolerance',0.01)2667adaptive_recursion = args.pop('adaptive_recursion',5)2668randomize = args.pop('randomize',True)2669for j in range(len(I)):2670a,b,shape = I[j]2671v = generate_plot_points(f1, (a, b), plot_points, adaptive_tolerance, adaptive_recursion, randomize)2672w = generate_plot_points(f2, (a, b), plot_points, adaptive_tolerance, adaptive_recursion, randomize)2673if shape == 'o':2674g += plot.line(v + list(reversed(w)) + [v[0]], **args)2675elif shape == '<':2676g += plot.line(list(reversed(v)) + w, **args)2677elif shape == '>':2678g += plot.line(v + list(reversed(w)), **args)2679else:2680g += plot.line(v, **args)2681g += plot.line(w, **args)2682return g26832684def formal_group(self):2685r"""2686The formal group associated to this elliptic curve.26872688EXAMPLES::26892690sage: E = EllipticCurve("37a")2691sage: E.formal_group()2692Formal Group associated to the Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field2693"""2694try:2695return self.__formal_group2696except AttributeError:2697self.__formal_group = formal_group.EllipticCurveFormalGroup(self)2698return self.__formal_group26992700formal = formal_group27012702def _p_primary_torsion_basis(self,p,m=None):2703r"""2704Find a basis for the `p`-primary part of the torsion2705subgroup of this elliptic curve.27062707INPUT:27082709- ``p`` (integer) -- a prime number.27102711- ``m`` (integer or None) -- if not None, the $p$-primary torsion will be assumed to have order at most $p^m$.27122713OUTPUT:27142715A list of 0, 1 or 2 pairs `[T,k]` where `T` is a generator of2716order `p^k`. That is, either `[]` or `[[T_1,k_1]]` or2717`[[T_1,k_1],[T_2,k_2]]` with `[]`, `[T_1]`, or `[T_1,T_2]` a2718basis and `p^{k_1} \ge p^{k_2} \ge 1` their orders.27192720.. warning::272127221. Do not call this on a curve whose group is2723`p`-divisible (i.e., whose `p`-primary part2724is infinite)!272527262. The code uses division polynomials and will be slow for2727large `p`.27282729EXAMPLES::27302731sage: E = EllipticCurve('11a1')2732sage: E._p_primary_torsion_basis(5)2733[[(5 : -6 : 1), 1]]2734sage: K.<t> = NumberField(x^4 + x^3 + 11*x^2 + 41*x + 101)2735sage: EK = E.base_extend(K)2736sage: EK._p_primary_torsion_basis(5) # long time (2s on sage.math, 2011)2737[[(16 : 60 : 1), 1], [(t : 1/11*t^3 + 6/11*t^2 + 19/11*t + 48/11 : 1), 1]]2738sage: EF = E.change_ring(GF(101))2739sage: EF._p_primary_torsion_basis(5)2740[[(0 : 13 : 1), 1], [(5 : 5 : 1), 1]]27412742sage: F.<z> = CyclotomicField(21)2743sage: E = EllipticCurve([2,-z^7,-z^7,0,0])2744sage: E._p_primary_torsion_basis(7,2) # long time (8s on sage.math, 2011)2745[[(0 : z^7 : 1), 1],2746[(z^7 - z^6 + z^4 - z^3 + z^2 - 1 : z^8 - 2*z^7 + z^6 + 2*z^5 - 3*z^4 + 2*z^3 - 2*z + 2 : 1), 1]]27472748TESTS:27492750This shows that the bug at trac #4937 is fixed::27512752sage: a=8045159777348605664942397709822820638954804843023637154948732753sage: b=5847722216036328666656823228992971417931882520006742566620712754sage: E = EllipticCurve(GF(10^60+3201),[0,a,0,b,0])2755sage: [t[1] for t in E._p_primary_torsion_basis(2)] # long time (3s on sage.math, 2011)2756[16, 1]2757"""2758p = rings.Integer(p)2759if not p.is_prime():2760raise ValueError, "p (=%s) should be prime"%p27612762if m is None:2763from sage.rings.infinity import Infinity2764m = Infinity27652766if m == 0:2767return []27682769# First find the p-torsion:2770Ep = self(0).division_points(p)2771p_rank = rings.Integer(len(Ep)).exact_log(p)2772assert p_rank in [0,1,2]27732774if p_rank == 0:2775return []27762777assert p_rank in [1,2]27782779if p_rank == 1:2780P = Ep[0]2781if P.is_zero(): P=Ep[1]2782k = 12783if m==1:2784return [[P,k]]2785pts = P.division_points(p) # length 0 or p2786while len(pts)>0:2787k += 12788P = pts[0]2789if m<=k:2790return [[P,k]]2791pts = P.division_points(p)2792# now P generates the p-power-torsion and has order p^k2793return [[P,k]]27942795assert p_rank == 227962797Epi = iter(Ep) # used to iterate through Ep2798# Find P1,P2 which generate the p-torsion:2799P1 = Epi.next()2800while P1.is_zero(): P1 = Epi.next()2801P2 = Epi.next()2802while generic.linear_relation(P1,P2,'+')[0] != 0: P2 = Epi.next()28032804k = 12805log_order = 22806if m<=log_order:2807return [[P1,1],[P2,1]]28082809pts1 = P1.division_points(p)2810pts2 = P2.division_points(p)2811while len(pts1)>0 and len(pts2)>0:2812k += 12813P1 = pts1[0]2814P2 = pts2[0]2815log_order += 22816if m<=log_order:2817return [[P1,k],[P2,k]]2818pts1 = P1.division_points(p)2819pts2 = P2.division_points(p)28202821# Now P1,P2 are a basis for the p^k torsion, which is2822# isomorphic to (Z/p^k)^2, and k is the maximal integer for2823# which this is the case.28242825# We now determine whether a combination (P2 or P1+a*P2 for2826# some a) can be further divided for some a mod p; if so,2827# replace P1 by that combination, set pts to be the list of2828# solutions Q to p*Q=P1. If no combination can be divided,2829# then the structure is (p^k,p^k) and we can stop.28302831if len(pts1) > 0:2832pts = pts12833elif len(pts2) > 0:2834P1, P2 = P2, P12835pts = pts22836else:2837for Q in generic.multiples(P2,p-1,P1+P2,operation='+'):2838# Q runs through P1+a*P2 for a=1,2,...,p-12839pts = Q.division_points(p)2840if len(pts) > 0:2841P1 = Q2842break28432844if len(pts)==0:2845return [[P1,k],[P2,k]]28462847# Now the structure is (p^n,p^k) for some n>k. We need to2848# replace P1 by an element of maximal order p^n. So far we2849# have pts = list of Q satisfying p*Q=P1, and all such Q have2850# order p^{k+1}.28512852# We keep trying to divide P1 by p. At each step, if we2853# succeed, replace P1 by any of the results and increment n.2854# If we fails try again with P1+a*P2 for a in [1..p-1]. If any2855# succeed, replace P1 by one of the resulting divided points.2856# If all fail, the structure is (p^n,p^k) and P1,P2 are2857# generators.28582859n=k2860while True:2861P1=pts[0]2862n += 12863log_order += 12864if m<=log_order:2865return [[P1,n],[P2,k]]2866pts = P1.division_points(p)2867if len(pts)==0:2868for Q in generic.multiples(P2,p-1,P1+P2,operation='+'):2869# Q runs through P1+a*P2 for a=1,2,...,p-12870pts = Q.division_points(p)2871if len(pts)>0:2872break2873if len(pts)==0:2874return [[P1,n],[P2,k]]287528762877def hyperelliptic_polynomials(self):2878r"""2879Returns a pair of polynomials `g(x)`, `h(x)` such that this elliptic2880curve can be defined by the standard hyperelliptic equation28812882.. math::28832884y^2 + h(x)y = g(x).28852886EXAMPLES::28872888sage: R.<a1,a2,a3,a4,a6>=QQ[]2889sage: E=EllipticCurve([a1,a2,a3,a4,a6])2890sage: E.hyperelliptic_polynomials()2891(x^3 + a2*x^2 + a4*x + a6, a1*x + a3)2892"""2893K = self.base_ring()2894R = PolynomialRing(K, 'x')2895x = R.gen(0)2896a1, a2, a3, a4, a6 = self.ainvs()2897return R([a6, a4, a2, 1]), R([a3, a1])28982899def pari_curve(self):2900"""2901Return the PARI curve corresponding to this elliptic curve.29022903The result is cached.29042905EXAMPLES::29062907sage: E = EllipticCurve([RR(0), RR(0), RR(1), RR(-1), RR(0)])2908sage: e = E.pari_curve()2909sage: type(e)2910<type 'sage.libs.pari.gen.gen'>2911sage: e.type()2912't_VEC'2913sage: e.disc()291437.000000000000029152916Over a finite field::29172918sage: EllipticCurve(GF(41),[2,5]).pari_curve()2919[Mod(0, 41), Mod(0, 41), Mod(0, 41), Mod(2, 41), Mod(5, 41), Mod(0, 41), Mod(4, 41), Mod(20, 41), Mod(37, 41), Mod(27, 41), Mod(26, 41), Mod(4, 41), Mod(11, 41), 0, 0, 0, 0, 0, 0]29202921Over a `p`-adic field::29222923sage: Qp = pAdicField(5, prec=3)2924sage: E = EllipticCurve(Qp,[3, 4])2925sage: E.pari_curve()2926[O(5^3), O(5^3), O(5^3), 3 + O(5^3), 4 + O(5^3), O(5^3), 1 + 5 + O(5^3), 1 + 3*5 + O(5^3), 1 + 3*5 + 4*5^2 + O(5^3), 1 + 5 + 4*5^2 + O(5^3), 4 + 3*5 + 5^2 + O(5^3), 2*5 + 4*5^2 + O(5^3), 3*5^-1 + O(5), [4 + 4*5 + 4*5^2 + O(5^3)], 1 + 2*5 + 4*5^2 + O(5^3), 1 + 5 + 4*5^2 + O(5^3), 2*5 + 4*5^2 + O(5^3), 3 + 3*5 + 3*5^2 + O(5^3), 0]2927sage: E.j_invariant()29283*5^-1 + O(5)29292930The `j`-invariant must have negative `p`-adic valuation::29312932sage: E = EllipticCurve(Qp,[1, 1])2933sage: E.j_invariant() # the j-invariant is a p-adic integer29342 + 4*5^2 + O(5^3)2935sage: E.pari_curve()2936Traceback (most recent call last):2937...2938PariError: (5)2939"""2940try:2941return self._pari_curve2942except AttributeError:2943pass29442945from sage.libs.pari.all import pari2946self._pari_curve = pari(list(self.a_invariants())).ellinit()2947return self._pari_curve29482949# This method is defined so that pari(E) returns exactly the same2950# as E.pari_curve(). This works even for classes that inherit from2951# EllipticCurve_generic, such as EllipticCurve_rational_field.2952def _pari_(self):2953"""2954Return the PARI curve corresponding to this elliptic curve2955with the default precision of 64 bits.29562957EXAMPLES::29582959sage: E = EllipticCurve('11a1')2960sage: pari(E)2961[0, -1, 1, -10, -20, -4, -20, -79, -21, 496, 20008, -161051, -122023936/161051, [4.34630815820539, -1.67315407910270 + 1.32084892226908*I, -1.67315407910270 - 1.32084892226908*I]~, ...]2962sage: E.pari_curve(prec=64)2963[0, -1, 1, -10, -20, -4, -20, -79, -21, 496, 20008, -161051, -122023936/161051, [4.34630815820539, -1.67315407910270 + 1.32084892226908*I, -1.67315407910270 - 1.32084892226908*I]~, ...]29642965Over a finite field::29662967sage: EllipticCurve(GF(2), [0,0,1,1,1])._pari_()2968[Mod(0, 2), Mod(0, 2), Mod(1, 2), Mod(1, 2), Mod(1, 2), Mod(0, 2), Mod(0, 2), Mod(1, 2), Mod(1, 2), Mod(0, 2), Mod(0, 2), Mod(1, 2), Mod(0, 2), 0, 0, 0, 0, 0, 0]2969"""2970return self.pari_curve()297129722973