Elliptic curves over a general ring#

Sage defines an elliptic curve over a ring \(R\) as a Weierstrass Model with five coefficients \([a_1,a_2,a_3,a_4,a_6]\) in \(R\) given by

\[y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.\]

Note 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 note that in Magma, “Weierstrass Model” refers to a model with \(a_1=a_2=a_3=0\), which is called Short Weierstrass Model in Sage; these do not always exist in characteristics 2 and 3.

EXAMPLES:

We construct an elliptic curve over an elaborate base ring:

sage: p, a, b = 97, 1, 3
sage: R.<u> = GF(p)[]
sage: S.<v> = R[]
sage: T = S.fraction_field()
sage: E = EllipticCurve(T, [a, b]); E
Elliptic 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 97
sage: latex(E)
y^2  = x^{3} + x + 3

AUTHORS:

  • William Stein (2005): Initial version

  • Robert Bradshaw et al….

  • John Cremona (2008-01): isomorphisms, automorphisms and twists in all characteristics

  • Julian Rueth (2014-04-11): improved caching

  • Lorenz Panny (2022-04-14): added .montgomery_model()

class sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic(K, ainvs, category=None)#

Bases: WithEqualityById, ProjectivePlaneCurve

Elliptic curve over a generic base ring.

EXAMPLES:

sage: E = EllipticCurve([1,2,3/4,7,19]); E
Elliptic Curve defined by y^2 + x*y + 3/4*y = x^3 + 2*x^2 + 7*x + 19 over Rational Field
sage: loads(E.dumps()) == E
True
sage: E = EllipticCurve([1,3])
sage: P = E([-1,1,1])
sage: -5*P
(179051/80089 : -91814227/22665187 : 1)
a1()#

Return the \(a_1\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a1()
1
a2()#

Return the \(a_2\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a2()
2
a3()#

Return the \(a_3\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a3()
3
a4()#

Return the \(a_4\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a4()
4
a6()#

Return the \(a_6\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a6()
6
a_invariants()#

The \(a\)-invariants of this elliptic curve, as a tuple.

OUTPUT:

(tuple) - a 5-tuple of the \(a\)-invariants of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.a_invariants()
(1, 2, 3, 4, 5)

sage: E = EllipticCurve([0,1]); E
Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
sage: E.a_invariants()
(0, 0, 0, 0, 1)

sage: E = EllipticCurve([GF(7)(3),5])
sage: E.a_invariants()
(0, 0, 0, 3, 5)
ainvs()#

The \(a\)-invariants of this elliptic curve, as a tuple.

OUTPUT:

(tuple) - a 5-tuple of the \(a\)-invariants of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.a_invariants()
(1, 2, 3, 4, 5)

sage: E = EllipticCurve([0,1]); E
Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
sage: E.a_invariants()
(0, 0, 0, 0, 1)

sage: E = EllipticCurve([GF(7)(3),5])
sage: E.a_invariants()
(0, 0, 0, 3, 5)
automorphisms(field=None)#

Return the set of isomorphisms from self to itself (as a list).

The identity and negation morphisms are guaranteed to appear as the first and second entry of the returned list.

INPUT:

  • field (default None) – a field into which the coefficients of the curve may be coerced (by default, uses the base field of the curve).

OUTPUT:

(list) A list of WeierstrassIsomorphism objects consisting of all the isomorphisms from the curve self to itself defined over field.

EXAMPLES:

sage: E = EllipticCurve_from_j(QQ(0))  # a curve with j=0 over QQ
sage: E.automorphisms()
[Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Rational Field
   Via:  (u,r,s,t) = (1, 0, 0, 0),
 Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Rational Field
   Via:  (u,r,s,t) = (-1, 0, 0, -1)]

We can also find automorphisms defined over extension fields:

sage: x = polygen(ZZ, 'x')
sage: K.<a> = NumberField(x^2 + 3)  # adjoin roots of unity                 # needs sage.rings.number_field
sage: E.automorphisms(K)                                                    # needs sage.rings.number_field
[Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Number Field in a with defining polynomial x^2 + 3
   Via:  (u,r,s,t) = (1, 0, 0, 0),
 Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Number Field in a with defining polynomial x^2 + 3
   Via:  (u,r,s,t) = (-1, 0, 0, -1),
 Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Number Field in a with defining polynomial x^2 + 3
   Via:  (u,r,s,t) = (-1/2*a - 1/2, 0, 0, 0),
 Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Number Field in a with defining polynomial x^2 + 3
   Via:  (u,r,s,t) = (1/2*a + 1/2, 0, 0, -1),
 Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Number Field in a with defining polynomial x^2 + 3
   Via:  (u,r,s,t) = (1/2*a - 1/2, 0, 0, 0),
 Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Number Field in a with defining polynomial x^2 + 3
   Via:  (u,r,s,t) = (-1/2*a + 1/2, 0, 0, -1)]
sage: [len(EllipticCurve_from_j(GF(q,'a')(0)).automorphisms())              # needs sage.rings.finite_rings
....:  for q in [2,4,3,9,5,25,7,49]]
[2, 24, 2, 12, 2, 6, 6, 6]
b2()#

Return the \(b_2\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.b2()
9
b4()#

Return the \(b_4\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.b4()
11
b6()#

Return the \(b_6\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.b6()
29
b8()#

Return the \(b_8\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.b8()
35
b_invariants()#

Return the \(b\)-invariants of this elliptic curve, as a tuple.

OUTPUT:

(tuple) - a 4-tuple of the \(b\)-invariants of this elliptic curve.

This method is cached.

EXAMPLES:

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.b_invariants()
(-4, -20, -79, -21)

sage: E = EllipticCurve([-4,0])
sage: E.b_invariants()
(0, -8, 0, -16)

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.b_invariants()
(9, 11, 29, 35)
sage: E.b2()
9
sage: E.b4()
11
sage: E.b6()
29
sage: E.b8()
35

ALGORITHM:

These are simple functions of the \(a\)-invariants.

AUTHORS:

  • William Stein (2005-04-25)

base_extend(R)#

Return the base extension of self to \(R\).

INPUT:

  • R – either a ring into which the \(a\)-invariants of self may be converted, or a morphism which may be applied to them.

OUTPUT:

An elliptic curve over the new ring whose \(a\)-invariants are the images of the \(a\)-invariants of self.

EXAMPLES:

sage: E = EllipticCurve(GF(5), [1,1]); E
Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
sage: E1 = E.base_extend(GF(125,'a')); E1                                   # needs sage.rings.finite_rings
Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 5^3
base_ring()#

Return the base ring of the elliptic curve.

EXAMPLES:

sage: E = EllipticCurve(GF(49, 'a'), [3,5])                                 # needs sage.rings.finite_rings
sage: E.base_ring()                                                         # needs sage.rings.finite_rings
Finite Field in a of size 7^2
sage: E = EllipticCurve([1,1])
sage: E.base_ring()
Rational Field
sage: E = EllipticCurve(ZZ, [3,5])
sage: E.base_ring()
Integer Ring
c4()#

Return the \(c_4\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.c4()
496
c6()#

Return the \(c_6\) invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.c6()
20008
c_invariants()#

Return the \(c\)-invariants of this elliptic curve, as a tuple.

This method is cached.

OUTPUT:

(tuple) - a 2-tuple of the \(c\)-invariants of the elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.c_invariants()
(496, 20008)

sage: E = EllipticCurve([-4,0])
sage: E.c_invariants()
(192, 0)

ALGORITHM:

These are simple functions of the \(a\)-invariants.

AUTHORS:

  • William Stein (2005-04-25)

change_ring(R)#

Return the base change of self to \(R\).

This has the same effect as self.base_extend(R).

EXAMPLES:

sage: # needs sage.rings.finite_rings
sage: F2 = GF(5^2,'a'); a = F2.gen()
sage: F4 = GF(5^4,'b'); b = F4.gen()
sage: roots = a.charpoly().roots(ring=F4, multiplicities=False)
sage: h = F2.hom([roots[0]], F4)
sage: E = EllipticCurve(F2, [1,a]); E
Elliptic Curve defined by y^2 = x^3 + x + a
over Finite Field in a of size 5^2
sage: E.change_ring(h)
Elliptic 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^4
change_weierstrass_model(*urst)#

Return a new Weierstrass model of self under the standard transformation \((u,r,s,t)\)

\[(x,y) \mapsto (x',y') = (u^2x + r , u^3y + su^2x + t).\]

EXAMPLES:

sage: E = EllipticCurve('15a')
sage: F1 = E.change_weierstrass_model([1/2,0,0,0]); F1
Elliptic Curve defined by y^2 + 2*x*y + 8*y = x^3 + 4*x^2 - 160*x - 640
over Rational Field
sage: F2 = E.change_weierstrass_model([7,2,1/3,5]); F2
Elliptic 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 Field
sage: F1.is_isomorphic(F2)
True
discriminant()#

Return the discriminant of this elliptic curve.

This method is cached.

EXAMPLES:

sage: E = EllipticCurve([0,0,1,-1,0])
sage: E.discriminant()
37

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.discriminant()
-161051

sage: E = EllipticCurve([GF(7)(2),1])
sage: E.discriminant()
1
division_polynomial(m, x=None, two_torsion_multiplicity=2, force_evaluate=None)#

Return the \(m^{th}\) division polynomial of this elliptic curve evaluated at \(x\).

The division polynomial is cached if \(x\) is None.

INPUT:

  • m – positive integer.

  • x – optional ring element to use as the \(x\) variable. If \(x\) is None (omitted), then a new polynomial ring will be constructed over the base ring of the elliptic curve, and its generator will be used as \(x\). Note that \(x\) does not need to be a generator of a polynomial ring; any ring element works. This permits fast calculation of the torsion polynomial evaluated on any element of a ring.

  • two_torsion_multiplicity – 0, 1, or 2

    If 0: For even \(m\) when \(x\) is None, a univariate polynomial over the base ring of the curve is returned, which omits factors whose roots are the \(x\)-coordinates of the \(2\)-torsion points. When \(x\) is not None, the evaluation of such a polynomial at \(x\) is returned.

    If 2: For even \(m\) when \(x\) is None, a univariate polynomial over the base ring of the curve is returned, which includes a factor of degree 3 whose roots are the \(x\)-coordinates of the \(2\)-torsion points. Similarly, when \(x\) is not None, the evaluation of such a polynomial at \(x\) is returned.

    If 1: For even \(m\) when \(x\) is None, a bivariate polynomial over the base ring of the curve is returned, which includes a factor \(2y+a_1x+a_3\) having simple zeros at the \(2\)-torsion points. When \(x\) is not None, it should be a tuple of length 2, and the evaluation of such a polynomial at \(x\) is returned.

  • force_evaluate (optional) – 0, 1, or 2

    By default, this method makes use of previously cached generic division polynomials to compute the value of the polynomial at a given element \(x\) whenever it appears beneficial to do so. Explicitly setting this flag overrides the default behavior.

    Note that the complexity of evaluating a generic division polynomial scales much worse than that of computing the value at a point directly (using the recursive formulas), hence setting this flag can be detrimental to performance.

    If 0: Do not use cached generic division polynomials.

    If 1: If the generic division polynomial for this \(m\) has been cached before, evaluate it at \(x\) to compute the result.

    If 2: Compute the value at \(x\) by evaluating the generic division polynomial. If the generic \(m\)-division polynomial has not yet been cached, compute and cache it first.

EXAMPLES:

sage: E = EllipticCurve([0,0,1,-1,0])
sage: E.division_polynomial(1)
1
sage: E.division_polynomial(2, two_torsion_multiplicity=0)
1
sage: E.division_polynomial(2, two_torsion_multiplicity=1)
2*y + 1
sage: E.division_polynomial(2, two_torsion_multiplicity=2)
4*x^3 - 4*x + 1
sage: E.division_polynomial(2)
4*x^3 - 4*x + 1
sage: [E.division_polynomial(3, two_torsion_multiplicity=i) for i in range(3)]
[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]
sage: [type(E.division_polynomial(3, two_torsion_multiplicity=i)) for i in range(3)]
[<... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>,
 <... 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>,
 <... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>]
sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: R.<z> = PolynomialRing(QQ)
sage: E.division_polynomial(4, z, 0)
2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821
sage: E.division_polynomial(4, z)
8*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 + 459859

This does not work, since when two_torsion_multiplicity is 1, we compute a bivariate polynomial, and must evaluate at a tuple of length 2:

sage: E.division_polynomial(4,z,1)
Traceback (most recent call last):
...
ValueError: x should be a tuple of length 2 (or None)
when two_torsion_multiplicity is 1
sage: R.<z,w> = PolynomialRing(QQ, 2)
sage: E.division_polynomial(4, (z,w), 1).factor()
(2*w + 1) * (2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821)

We can also evaluate this bivariate polynomial at a point:

sage: P = E(5,5)
sage: E.division_polynomial(4,P,two_torsion_multiplicity=1)
-1771561
division_polynomial_0(n, x=None)#

Return the \(n^{th}\) torsion (division) polynomial, without the 2-torsion factor if \(n\) is even, as a polynomial in \(x\).

These are the polynomials \(g_n\) defined in [MT1991], but with the sign flipped for even \(n\), so that the leading coefficient is always positive.

Note

This function is intended for internal use; users should use division_polynomial().

See also

INPUT:

  • n – positive integer, or the special values -1 and -2 which mean \(B_6 = (2y + a_1 x + a_3)^2\) and \(B_6^2\) respectively (in the notation of [MT1991]); or a list of integers.

  • x – a ring element to use as the “x” variable or None (default: None). If None, then a new polynomial ring will be constructed over the base ring of the elliptic curve, and its generator will be used as x. Note that x does not need to be a generator of a polynomial ring; any ring element is ok. This permits fast calculation of the torsion polynomial evaluated on any element of a ring.

ALGORITHM:

Recursion described in [MT1991]. The recursive formulae are evaluated \(O(\log^2 n)\) times.

AUTHORS:

  • David Harvey (2006-09-24): initial version

  • John Cremona (2008-08-26): unified division polynomial code

EXAMPLES:

sage: E = EllipticCurve("37a")
sage: E.division_polynomial_0(1)
1
sage: E.division_polynomial_0(2)
1
sage: E.division_polynomial_0(3)
3*x^4 - 6*x^2 + 3*x - 1
sage: E.division_polynomial_0(4)
2*x^6 - 10*x^4 + 10*x^3 - 10*x^2 + 2*x + 1
sage: E.division_polynomial_0(5)
5*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 + 2
sage: E.division_polynomial_0(6)
3*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 - 1
sage: E.division_polynomial_0(7)
7*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 - 3
sage: E.division_polynomial_0(8)
4*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 - 5
sage: E.division_polynomial_0(18) % E.division_polynomial_0(6) == 0
True

An example to illustrate the relationship with torsion points:

sage: F = GF(11)
sage: E = EllipticCurve(F, [0, 2]); E
Elliptic Curve defined by y^2  = x^3 + 2 over Finite Field of size 11
sage: f = E.division_polynomial_0(5); f
5*x^12 + x^9 + 8*x^6 + 4*x^3 + 7
sage: f.factor()
(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)

This indicates that the \(x\)-coordinates of all the 5-torsion points of \(E\) are in \(\GF{11^2}\), and therefore the \(y\)-coordinates are in \(\GF{11^4}\):

sage: # needs sage.rings.finite_rings
sage: K = GF(11^4, 'a')
sage: X = E.change_ring(K)
sage: f = X.division_polynomial_0(5)
sage: x_coords = f.roots(multiplicities=False); x_coords
[10*a^3 + 4*a^2 + 5*a + 6,
 9*a^3 + 8*a^2 + 10*a + 8,
 8*a^3 + a^2 + 4*a + 10,
 8*a^3 + a^2 + 4*a + 8,
 8*a^3 + a^2 + 4*a + 4,
 6*a^3 + 9*a^2 + 3*a + 4,
 5*a^3 + 2*a^2 + 8*a + 7,
 3*a^3 + 10*a^2 + 7*a + 8,
 3*a^3 + 10*a^2 + 7*a + 3,
 3*a^3 + 10*a^2 + 7*a + 1,
 2*a^3 + 3*a^2 + a + 7,
 a^3 + 7*a^2 + 6*a]

Now we check that these are exactly the \(x\)-coordinates of the 5-torsion points of \(E\):

sage: for x in x_coords:                                                    # needs sage.rings.finite_rings
....:     assert X.lift_x(x).order() == 5

The roots of the polynomial are the \(x\)-coordinates of the points \(P\) such that \(mP=0\) but \(2P\not=0\):

sage: E = EllipticCurve('14a1')
sage: T = E.torsion_subgroup()
sage: [n*T.0 for n in range(6)]
[(0 : 1 : 0),
(9 : 23 : 1),
(2 : 2 : 1),
(1 : -1 : 1),
(2 : -5 : 1),
(9 : -33 : 1)]
sage: pol = E.division_polynomial_0(6)
sage: xlist = pol.roots(multiplicities=False); xlist
[9, 2, -1/3, -5]
sage: [E.lift_x(x, all=True) for x in xlist]
[[(9 : -33 : 1), (9 : 23 : 1)], [(2 : -5 : 1), (2 : 2 : 1)], [], []]

Note

The point of order 2 and the identity do not appear. The points with \(x=-1/3\) and \(x=-5\) are not rational.

formal()#

Return the formal group associated to this elliptic curve.

This method is cached.

EXAMPLES:

sage: E = EllipticCurve("37a")
sage: E.formal_group()
Formal Group associated to the Elliptic Curve
defined by y^2 + y = x^3 - x over Rational Field
formal_group()#

Return the formal group associated to this elliptic curve.

This method is cached.

EXAMPLES:

sage: E = EllipticCurve("37a")
sage: E.formal_group()
Formal Group associated to the Elliptic Curve
defined by y^2 + y = x^3 - x over Rational Field
frobenius_isogeny(n=1)#

Return the \(n\)-power Frobenius isogeny from this curve to its Galois conjugate.

The Frobenius endomorphism is the special case where \(n\) is divisible by the degree of the base ring of the curve.

EXAMPLES:

sage: # needs sage.rings.finite_rings
sage: z3, = GF(13^3).gens()
sage: E = EllipticCurve([z3, z3^2])
sage: E.frobenius_isogeny()
Frobenius isogeny of degree 13:
  From: Elliptic Curve defined by y^2 = x^3 + z3*x + z3^2
         over Finite Field in z3 of size 13^3
  To:   Elliptic Curve defined by y^2 = x^3 + (5*z3^2+7*z3+11)*x + (5*z3^2+12*z3+1)
         over Finite Field in z3 of size 13^3
sage: E.frobenius_isogeny(3)
Frobenius endomorphism of degree 2197 = 13^3:
  From: Elliptic Curve defined by y^2 = x^3 + z3*x + z3^2
         over Finite Field in z3 of size 13^3
  To:   Elliptic Curve defined by y^2 = x^3 + z3*x + z3^2
         over Finite Field in z3 of size 13^3
gen(i)#

Function returning the i’th generator of this elliptic curve.

Note

Relies on gens() being implemented.

EXAMPLES:

sage: R.<a1,a2,a3,a4,a6> = QQ[]
sage: E = EllipticCurve([a1,a2,a3,a4,a6])
sage: E.gen(0)
Traceback (most recent call last):
...
NotImplementedError: not implemented.
gens()#

Placeholder function to return generators of an elliptic curve.

Note

This functionality is implemented in certain derived classes, such as EllipticCurve_rational_field.

EXAMPLES:

sage: R.<a1,a2,a3,a4,a6> = QQ[]
sage: E = EllipticCurve([a1,a2,a3,a4,a6])
sage: E.gens()
Traceback (most recent call last):
...
NotImplementedError: not implemented.
sage: E = EllipticCurve(QQ, [1,1])
sage: E.gens()
[(0 : 1 : 1)]
hyperelliptic_polynomials()#

Return a pair of polynomials \(g(x)\), \(h(x)\) such that this elliptic curve can be defined by the standard hyperelliptic equation

\[y^2 + h(x)y = g(x).\]

EXAMPLES:

sage: R.<a1,a2,a3,a4,a6>=QQ[]
sage: E = EllipticCurve([a1,a2,a3,a4,a6])
sage: E.hyperelliptic_polynomials()
(x^3 + a2*x^2 + a4*x + a6, a1*x + a3)
identity_morphism()#

Return the identity endomorphism of this elliptic curve as an EllipticCurveHom object.

EXAMPLES:

sage: E = EllipticCurve(j=42)
sage: E.identity_morphism()
Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + 5901*x + 1105454 over Rational Field
  Via:  (u,r,s,t) = (1, 0, 0, 0)
sage: E.identity_morphism() == E.scalar_multiplication(1)
True
is_isomorphic(other, field=None)#

Return whether or not self is isomorphic to other.

INPUT:

  • other – another elliptic curve.

  • field (default None) – a field into which the coefficients of the curves may be coerced (by default, uses the base field of the curves).

OUTPUT:

(bool) True if there is an isomorphism from curve self to curve other defined over field.

EXAMPLES:

sage: E = EllipticCurve('389a')
sage: F = E.change_weierstrass_model([2,3,4,5]); F
Elliptic Curve defined by y^2 + 4*x*y + 11/8*y = x^3 - 3/2*x^2 - 13/16*x
over Rational Field
sage: E.is_isomorphic(F)
True
sage: E.is_isomorphic(F.change_ring(CC))
False
is_on_curve(x, y)#

Return True if \((x,y)\) is an affine point on this curve.

INPUT:

  • x, y – elements of the base ring of the curve.

EXAMPLES:

sage: E = EllipticCurve(QQ,[1,1])
sage: E.is_on_curve(0,1)
True
sage: E.is_on_curve(1,1)
False
is_x_coord(x)#

Return True if x is the \(x\)-coordinate of a point on this curve.

Note

See also lift_x() to find the point(s) with a given \(x\)-coordinate. This function may be useful in cases where testing an element of the base field for being a square is faster than finding its square root.

EXAMPLES:

sage: E = EllipticCurve('37a'); E
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
sage: E.is_x_coord(1)
True
sage: E.is_x_coord(2)
True

There are no rational points with x-coordinate 3:

sage: E.is_x_coord(3)
False

However, there are such points in \(E(\RR)\):

sage: E.change_ring(RR).is_x_coord(3)
True

And of course it always works in \(E(\CC)\):

sage: E.change_ring(RR).is_x_coord(-3)
False
sage: E.change_ring(CC).is_x_coord(-3)
True

AUTHORS:

  • John Cremona (2008-08-07): adapted from lift_x()

isomorphism(u, r, s=0, t=0, is_codomain=0)#

Given four values \(u,r,s,t\) in the base ring of this curve, return the WeierstrassIsomorphism defined by \(u,r,s,t\) with this curve as its codomain. (The value \(u\) must be a unit; the values \(r,s,t\) default to zero.)

Optionally, if the keyword argument is_codomain is set to True, return the isomorphism defined by \(u,r,s,t\) with this curve as its codomain.

EXAMPLES:

sage: E = EllipticCurve([1, 2, 3, 4, 5])
sage: iso = E.isomorphism(6); iso
Elliptic-curve morphism:
  From: Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
  To:   Elliptic Curve defined by y^2 + 1/6*x*y + 1/72*y = x^3 + 1/18*x^2 + 1/324*x + 5/46656 over Rational Field
  Via:  (u,r,s,t) = (6, 0, 0, 0)
sage: iso.domain() == E
True
sage: iso.codomain() == E.scale_curve(1 / 6)
True

sage: iso = E.isomorphism(1, 7, 8, 9); iso
Elliptic-curve morphism:
  From: Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
  To:   Elliptic Curve defined by y^2 + 17*x*y + 28*y = x^3 - 49*x^2 - 54*x + 303 over Rational Field
  Via:  (u,r,s,t) = (1, 7, 8, 9)
sage: iso.domain() == E
True
sage: iso.codomain() == E.rst_transform(7, 8, 9)
True

sage: iso = E.isomorphism(6, 7, 8, 9); iso
Elliptic-curve morphism:
  From: Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
  To:   Elliptic Curve defined by y^2 + 17/6*x*y + 7/54*y = x^3 - 49/36*x^2 - 1/24*x + 101/15552 over Rational Field
  Via:  (u,r,s,t) = (6, 7, 8, 9)
sage: iso.domain() == E
True
sage: iso.codomain() == E.rst_transform(7, 8, 9).scale_curve(1 / 6)
True

The is_codomain argument reverses the role of domain and codomain:

sage: E = EllipticCurve([1, 2, 3, 4, 5])
sage: iso = E.isomorphism(6, is_codomain=True); iso
Elliptic-curve morphism:
  From: Elliptic Curve defined by y^2 + 6*x*y + 648*y = x^3 + 72*x^2 + 5184*x + 233280 over Rational Field
  To:   Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
  Via:  (u,r,s,t) = (6, 0, 0, 0)
sage: iso.domain() == E.scale_curve(6)
True
sage: iso.codomain() == E
True

sage: iso = E.isomorphism(1, 7, 8, 9, is_codomain=True); iso
Elliptic-curve morphism:
  From: Elliptic Curve defined by y^2 - 15*x*y + 90*y = x^3 - 75*x^2 + 796*x - 2289 over Rational Field
  To:   Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
  Via:  (u,r,s,t) = (1, 7, 8, 9)
sage: iso.domain().rst_transform(7, 8, 9) == E
True
sage: iso.codomain() == E
True

sage: iso = E.isomorphism(6, 7, 8, 9, is_codomain=True); iso
Elliptic-curve morphism:
  From: Elliptic Curve defined by y^2 - 10*x*y + 700*y = x^3 + 35*x^2 + 9641*x + 169486 over Rational Field
  To:   Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
  Via:  (u,r,s,t) = (6, 7, 8, 9)
sage: iso.domain().rst_transform(7, 8, 9) == E.scale_curve(6)
True
sage: iso.codomain() == E
True
isomorphism_to(other)#

Given another weierstrass model other of self, return an isomorphism from self to other.

INPUT:

  • other – an elliptic curve isomorphic to self.

OUTPUT:

(Weierstrassmorphism) An isomorphism from self to other.

Note

If the curves in question are not isomorphic, a ValueError is raised.

EXAMPLES:

sage: E = EllipticCurve('37a')
sage: F = E.short_weierstrass_model()
sage: w = E.isomorphism_to(F); w
Elliptic-curve morphism:
  From: Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
  To:   Elliptic Curve defined by y^2  = x^3 - 16*x + 16 over Rational Field
  Via:  (u,r,s,t) = (1/2, 0, 0, -1/2)
sage: P = E(0,-1,1)
sage: w(P)
(0 : -4 : 1)
sage: w(5*P)
(1 : 1 : 1)
sage: 5*w(P)
(1 : 1 : 1)
sage: 120*w(P) == w(120*P)
True

We can also handle injections to different base rings:

sage: x = polygen(ZZ, 'x')
sage: K.<a> = NumberField(x^3 - 7)                                          # needs sage.rings.number_field
sage: E.isomorphism_to(E.change_ring(K))                                    # needs sage.rings.number_field
Elliptic-curve morphism:
  From: Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
  To:   Elliptic Curve defined by y^2 + y = x^3 + (-1)*x
         over Number Field in a with defining polynomial x^3 - 7
  Via:  (u,r,s,t) = (1, 0, 0, 0)
isomorphisms(other, field=None)#

Return the set of isomorphisms from self to other (as a list).

INPUT:

  • other – another elliptic curve.

  • field (default None) – a field into which the coefficients of the curves may be coerced (by default, uses the base field of the curves).

OUTPUT:

(list) A list of WeierstrassIsomorphism objects consisting of all the isomorphisms from the curve self to the curve other defined over field.

EXAMPLES:

sage: E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ
sage: F = EllipticCurve('27a3') # should be the same one
sage: E.isomorphisms(F)
[Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Rational Field
   Via:  (u,r,s,t) = (1, 0, 0, 0),
 Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
  over Rational Field
   Via:  (u,r,s,t) = (-1, 0, 0, -1)]

We can also find isomorphisms defined over extension fields:

sage: # needs sage.rings.finite_rings
sage: E = EllipticCurve(GF(7), [0,0,0,1,1])
sage: F = EllipticCurve(GF(7), [0,0,0,1,-1])
sage: E.isomorphisms(F)
[]
sage: E.isomorphisms(F, GF(49,'a'))
[Elliptic-curve morphism:
   From: Elliptic Curve defined by y^2 = x^3 + x + 1
         over Finite Field in a of size 7^2
   To:   Elliptic Curve defined by y^2 = x^3 + x + 6
         over Finite Field in a of size 7^2
   Via:  (u,r,s,t) = (a + 3, 0, 0, 0),
 Elliptic-curve morphism:
   From: Elliptic Curve defined by y^2 = x^3 + x + 1
         over Finite Field in a of size 7^2
   To:   Elliptic Curve defined by y^2 = x^3 + x + 6
         over Finite Field in a of size 7^2
   Via:  (u,r,s,t) = (6*a + 4, 0, 0, 0)]
j_invariant()#

Return the \(j\)-invariant of this elliptic curve.

This method is cached.

EXAMPLES:

sage: E = EllipticCurve([0,0,1,-1,0])
sage: E.j_invariant()
110592/37

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.j_invariant()
-122023936/161051

sage: E = EllipticCurve([-4,0])
sage: E.j_invariant()
1728

sage: E = EllipticCurve([GF(7)(2),1])
sage: E.j_invariant()
1
lift_x(x, all=False, extend=False)#

Return one or all points with given \(x\)-coordinate.

This method is deterministic: It returns the same data each time when called again with the same \(x\).

INPUT:

  • x – an element of the base ring of the curve, or of an extension.

  • all (bool, default False) – if True, return a (possibly empty) list of all points; if False, return just one point, or raise a ValueError if there are none.

  • extend (bool, default False) –

    • if False, extend the base if necessary and possible to include \(x\), and only return point(s) defined over this ring, or raise an error when there are none with this \(x\)-coordinate;

    • If True, the base ring will be extended if necessary to contain the \(y\)-coordinates of the point(s) with this \(x\)-coordinate, in addition to a possible base change to include \(x\).

OUTPUT:

A point or list of up to 2 points on this curve, or a base-change of this curve to a larger ring.

See also

is_x_coord()

EXAMPLES:

sage: E = EllipticCurve('37a'); E
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
sage: E.lift_x(1)
(1 : -1 : 1)
sage: E.lift_x(2)
(2 : -3 : 1)
sage: E.lift_x(1/4, all=True)
[(1/4 : -5/8 : 1), (1/4 : -3/8 : 1)]

There are no rational points with \(x\)-coordinate 3:

sage: E.lift_x(3)
Traceback (most recent call last):
...
ValueError: No point with x-coordinate 3
on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field

We can use the extend parameter to make the necessary quadratic extension. Note that in such cases the returned point is a point on a new curve object, the result of changing the base ring to the parent of \(x\):

sage: P = E.lift_x(3, extend=True); P                                       # needs sage.rings.number_field
(3 : -y - 1 : 1)
sage: P.curve()                                                             # needs sage.rings.number_field
Elliptic Curve defined by y^2 + y = x^3 + (-1)*x
over Number Field in y with defining polynomial y^2 + y - 24

Or we can extend scalars. There are two such points in \(E(\RR)\):

sage: E.change_ring(RR).lift_x(3, all=True)
[(3.00000000000000 : -5.42442890089805 : 1.00000000000000),
 (3.00000000000000 : 4.42442890089805 : 1.00000000000000)]

And of course it always works in \(E(\CC)\):

sage: E.change_ring(RR).lift_x(.5, all=True)
[]
sage: E.change_ring(CC).lift_x(.5)
(0.500000000000000 : -0.500000000000000 - 0.353553390593274*I : 1.00000000000000)

In this example we start with a curve defined over \(\QQ\) which has no rational points with \(x=0\), but using extend = True we can construct such a point over a quadratic field:

sage: E = EllipticCurve([0,0,0,0,2]); E
Elliptic Curve defined by y^2 = x^3 + 2 over Rational Field
sage: P = E.lift_x(0, extend=True); P                                       # needs sage.rings.number_field
(0 : -y : 1)
sage: P.curve()                                                             # needs sage.rings.number_field
Elliptic Curve defined by y^2 = x^3 + 2
over Number Field in y with defining polynomial y^2 - 2

We can perform these operations over finite fields too:

sage: E = EllipticCurve('37a').change_ring(GF(17)); E
Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17
sage: E.lift_x(7)
(7 : 5 : 1)
sage: E.lift_x(3)
Traceback (most recent call last):
...
ValueError: No point with x-coordinate 3 on
Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17

Note that there is only one lift with \(x\)-coordinate 10 in \(E(\GF{17})\):

sage: E.lift_x(10, all=True)
[(10 : 8 : 1)]

We can lift over more exotic rings too. If the supplied x value is in an extension of the base, note that the point returned is on the base-extended curve:

sage: E = EllipticCurve('37a')
sage: P = E.lift_x(pAdicField(17, 5)(6)); P                                 # needs sage.rings.padics
(6 + O(17^5) : 14 + O(17^5) : 1 + O(17^5))
sage: P.curve()                                                             # needs sage.rings.padics
Elliptic Curve defined by
y^2 + (1+O(17^5))*y = x^3 + (16+16*17+16*17^2+16*17^3+16*17^4+O(17^5))*x
over 17-adic Field with capped relative precision 5
sage: K.<t> = PowerSeriesRing(QQ, 't', 5)
sage: P = E.lift_x(1 + t); P
(1 + t : -1 - 2*t + t^2 - 5*t^3 + 21*t^4 + O(t^5) : 1)
sage: K.<a> = GF(16)                                                        # needs sage.rings.finite_rings
sage: P = E.change_ring(K).lift_x(a^3); P                                   # needs sage.rings.finite_rings
(a^3 : a^3 + a : 1)
sage: P.curve()                                                             # needs sage.rings.finite_rings
Elliptic Curve defined by y^2 + y = x^3 + x over Finite Field in a of size 2^4

We can extend the base field to include the associated \(y\) value(s):

sage: E = EllipticCurve([0,0,0,0,2]); E
Elliptic Curve defined by y^2 = x^3 + 2 over Rational Field
sage: x = polygen(QQ)
sage: P = E.lift_x(x, extend=True); P
(x : -y : 1)

This point is a generic point on E:

sage: P.curve()
Elliptic Curve defined by y^2 = x^3 + 2
over Univariate Quotient Polynomial Ring in y
over Fraction Field of Univariate Polynomial Ring in x over Rational Field
with modulus y^2 - x^3 - 2
sage: -P
(x : y : 1)
sage: 2*P
((1/4*x^4 - 4*x)/(x^3 + 2) : ((-1/8*x^6 - 5*x^3 + 4)/(x^6 + 4*x^3 + 4))*y : 1)

Check that github issue #30297 is fixed:

sage: K = Qp(5)                                                             # needs sage.rings.padics
sage: E = EllipticCurve([K(0), K(1)])                                       # needs sage.rings.padics
sage: E.lift_x(1, extend=True)                                              # needs sage.rings.padics
(1 + O(5^20) : y + O(5^20) : 1 + O(5^20))

AUTHORS:

  • Robert Bradshaw (2007-04-24)

  • John Cremona (2017-11-10)

montgomery_model(twisted=False, morphism=False)#

Return a (twisted or untwisted) Montgomery model for this elliptic curve, if possible.

A Montgomery curve is a smooth projective curve of the form

\[BY^2 = X^3 + AX^2 + X.\]

The Montgomery curve is called untwisted if \(B=1\).

INPUT:

  • twisted – boolean (default: False); allow \(B \neq 1\)

  • morphism – boolean (default: False); also return an isomorphism from this curve to the computed Montgomery model

OUTPUT:

If twisted is False (the default), an EllipticCurve_generic object encapsulating an untwisted Montgomery curve. Otherwise, a ProjectivePlaneCurve object encapsulating a (potentially twisted) Montgomery curve.

If morphism is True, this method returns a tuple consisting of such a curve together with an isomorphism of suitable type (either WeierstrassIsomorphism or WeierstrassTransformationWithInverse) from this curve to the Montgomery model.

EXAMPLES:

sage: E = EllipticCurve(QQbar, '11a1')                                      # needs sage.rings.number_field
sage: E.montgomery_model()                                                  # needs sage.rings.number_field
Elliptic Curve defined by y^2 = x^3 + (-1.953522420987248?)*x^2 + x
over Algebraic Field
sage: E = EllipticCurve(GF(431^2), [7,7])                                   # needs sage.rings.finite_rings
sage: E.montgomery_model()                                                  # needs sage.rings.finite_rings
Elliptic Curve defined by y^2 = x^3 + (51*z2+190)*x^2 + x
over Finite Field in z2 of size 431^2

An isomorphism between the Montgomery and Weierstrass form can be obtained using the morphism parameter:

sage: E.montgomery_model(morphism=True)                                     # needs sage.rings.finite_rings
(Elliptic Curve defined by y^2 = x^3 + (51*z2+190)*x^2 + x
  over Finite Field in z2 of size 431^2,
 Elliptic-curve morphism:
   From: Elliptic Curve defined by y^2 = x^3 + 7*x + 7
         over Finite Field in z2 of size 431^2
   To:   Elliptic Curve defined by y^2 = x^3 + (51*z2+190)*x^2 + x
         over Finite Field in z2 of size 431^2
   Via:  (u,r,s,t) = (64*z2 + 407, 159, 0, 0))

Not all elliptic curves have a Montgomery model over their field of definition:

sage: E = EllipticCurve(GF(257), [1,1])
sage: E.montgomery_model()
Traceback (most recent call last):
...
ValueError: Elliptic Curve defined by y^2 = x^3 + x + 1
over Finite Field of size 257 has no Montgomery model
sage: E = EllipticCurve(GF(257), [10,10])
sage: E.montgomery_model()
Traceback (most recent call last):
...
ValueError: Elliptic Curve defined by y^2 = x^3 + 10*x + 10
over Finite Field of size 257 has no untwisted Montgomery model

However, as hinted by the error message, the latter curve does admit a twisted Montgomery model, which can be computed by passing twisted=True:

sage: E.montgomery_model(twisted=True)
Projective Plane Curve over Finite Field of size 257
defined by -x^3 + 8*x^2*z - 127*y^2*z - x*z^2

Since Sage internally represents elliptic curves as (long) Weierstrass curves, which do not feature the Montgomery \(B\) coefficient, the returned curve in this case is merely a ProjectivePlaneCurve rather than the usual EllipticCurve_generic.

Arithmetic on curves of this type is not implemented natively, but can easily be emulated by mapping back and forth to the corresponding Weierstrass curve:

sage: C, f = E.montgomery_model(twisted=True, morphism=True)
sage: f
Scheme morphism:
  From: Elliptic Curve defined by y^2 = x^3 + 10*x + 10
        over Finite Field of size 257
  To:   Projective Plane Curve over Finite Field of size 257
        defined by -x^3 + 8*x^2*z - 127*y^2*z - x*z^2
  Defn: Defined on coordinates by sending (x : y : z) to
        (x + 116*z : -y : -85*z)
sage: g = f.inverse(); g
Scheme morphism:
  From: Projective Plane Curve over Finite Field of size 257
        defined by -x^3 + 8*x^2*z - 127*y^2*z - x*z^2
  To:   Elliptic Curve defined by y^2 = x^3 + 10*x + 10
        over Finite Field of size 257
  Defn: Defined on coordinates by sending (x : y : z) to
        (-85*x - 116*z : 85*y : z)
sage: P = C(70, 8)
sage: Q = C(17, 17)
sage: P + Q             # this doesn't work...
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for +: ...
sage: f(g(P) + g(Q))    # ...but this does
(107 : 168 : 1)

Using the fact that the Weil pairing satisfies \(e(\psi(P),\psi(Q)) = e(P,Q)^{\deg\psi}\), even pairings can be emulated in this way (note that isomorphisms have degree \(1\)):

sage: # needs sage.rings.finite_rings
sage: F.<z2> = GF(257^2)
sage: C_ = C.change_ring(F)
sage: g_ = g.change_ring(F)
sage: g_(P).order()
12
sage: T = C_(-7 * z2 - 57, 31 * z2 - 52, 1)
sage: g_(T).order()
12
sage: g_(P).weil_pairing(g_(T), 12)
15*z2 + 204

Another alternative is to simply extend the base field enough for the curve to have an untwisted Montgomery model:

sage: C_ = E.change_ring(F).montgomery_model(); C_                          # needs sage.rings.finite_rings
Elliptic Curve defined by y^2 = x^3 + 249*x^2 + x
over Finite Field in z2 of size 257^2
sage: h = C.defining_polynomial().change_ring(F); h                         # needs sage.rings.finite_rings
-x^3 + 8*x^2*z - 127*y^2*z - x*z^2
sage: C_.is_isomorphic(EllipticCurve_from_cubic(h).codomain())              # needs sage.rings.finite_rings
True

See also

The inverse conversion — computing a Weierstrass model for a given Montgomery curve — can be performed using EllipticCurve_from_cubic().

ALGORITHM: [CS2018], §2.4

REFERENCES:

multiplication_by_m(m, x_only=False)#

Return the multiplication-by-\(m\) map from self to self

The result is a pair of rational functions in two variables \(x\), \(y\) (or a rational function in one variable \(x\) if x_only is True).

INPUT:

  • m – a nonzero integer

  • x_only – boolean (default: False) if True, return only the \(x\)-coordinate of the map (as a rational function in one variable).

OUTPUT:

  • a pair \((f(x), g(x,y))\), where \(f\) and \(g\) are rational functions with the degree of \(y\) in \(g(x,y)\) exactly 1,

  • or just \(f(x)\) if x_only is True

Note

  • The result is not cached.

  • m is allowed to be negative (but not 0).

EXAMPLES:

sage: E = EllipticCurve([-1,3])

We verify that multiplication by 1 is just the identity:

sage: E.multiplication_by_m(1)
(x, y)

Multiplication by 2 is more complicated:

sage: f = E.multiplication_by_m(2)
sage: f
((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))

Grab only the x-coordinate (less work):

sage: mx = E.multiplication_by_m(2, x_only=True); mx
(1/4*x^4 + 1/2*x^2 - 6*x + 1/4)/(x^3 - x + 3)
sage: mx.parent()
Fraction Field of Univariate Polynomial Ring in x over Rational Field

We check that it works on a point:

sage: P = E([2,3])
sage: eval = lambda f,P: [fi(P[0],P[1]) for fi in f]
sage: assert E(eval(f,P)) == 2*P

We do the same but with multiplication by 3:

sage: f = E.multiplication_by_m(3)
sage: assert E(eval(f,P)) == 3*P

And the same with multiplication by 4:

sage: f = E.multiplication_by_m(4)
sage: assert E(eval(f,P)) == 4*P

And the same with multiplication by -1,-2,-3,-4:

sage: for m in [-1,-2,-3,-4]:
....:     f = E.multiplication_by_m(m)
....:     assert E(eval(f,P)) == m*P
multiplication_by_m_isogeny(m)#

Return the EllipticCurveIsogeny object associated to the multiplication-by-\(m\) map on this elliptic curve.

The resulting isogeny will have the associated rational maps (i.e., those returned by multiplication_by_m()) already computed.

NOTE: This function is currently much slower than the result of self.multiplication_by_m(), because constructing an isogeny precomputes a significant amount of information. See github issue #7368 and github issue #8014 for the status of improving this situation.

INPUT:

  • m – a nonzero integer

OUTPUT:

  • An EllipticCurveIsogeny object associated to the multiplication-by-\(m\) map on this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve('11a1')
sage: E.multiplication_by_m_isogeny(7)
doctest:warning ... DeprecationWarning: ...
Isogeny 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 Field
pari_curve()#

Return the PARI curve corresponding to this elliptic curve.

The result is cached.

EXAMPLES:

sage: # needs sage.libs.pari
sage: E = EllipticCurve([RR(0), RR(0), RR(1), RR(-1), RR(0)])
sage: e = E.pari_curve()
sage: type(e)
<... 'cypari2.gen.Gen'>
sage: e.type()
't_VEC'
sage: e.disc()
37.0000000000000

Over a finite field:

sage: EllipticCurve(GF(41), [2,5]).pari_curve()                             # needs sage.libs.pari
[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),
 Vecsmall([3]),
 [41, [9, 31, [6, 0, 0, 0]]], [0, 0, 0, 0]]

Over a \(p\)-adic field:

sage: # needs sage.libs.pari sage.rings.padics
sage: Qp = pAdicField(5, prec=3)
sage: E = EllipticCurve(Qp, [3, 4])
sage: E.pari_curve()
[0, 0, 0, 3, 4, 0, 6, 16, -9, -144, -3456, -8640, 1728/5,
 Vecsmall([2]), [O(5^3)], [0, 0]]
sage: E.j_invariant()
3*5^-1 + O(5)

Over a number field:

sage: K.<a> = QuadraticField(2)                                             # needs sage.libs.pari sage.rings.number_field
sage: E = EllipticCurve([1,a])                                              # needs sage.libs.pari sage.rings.number_field
sage: E.pari_curve()                                                        # needs sage.libs.pari sage.rings.number_field
[0, 0, 0, Mod(1, y^2 - 2),
 Mod(y, y^2 - 2), 0, Mod(2, y^2 - 2), Mod(4*y, y^2 - 2),
 Mod(-1, y^2 - 2), Mod(-48, y^2 - 2), Mod(-864*y, y^2 - 2),
 Mod(-928, y^2 - 2), Mod(3456/29, y^2 - 2),
 Vecsmall([5]),
 [[y^2 - 2, [2, 0], 8, 1, [[1, -1.41421356237310; 1, 1.41421356237310],
 [1, -1.41421356237310; 1, 1.41421356237310],
 [16, -23; 16, 23], [2, 0; 0, 4], [4, 0; 0, 2], [2, 0; 0, 1],
 [2, [0, 2; 1, 0]], [2]], [-1.41421356237310, 1.41421356237310],
 [1, y], [1, 0; 0, 1], [1, 0, 0, 2; 0, 1, 1, 0]]], [0, 0, 0, 0, 0]]

PARI no longer requires that the \(j\)-invariant has negative \(p\)-adic valuation:

sage: E = EllipticCurve(Qp,[1, 1])                                          # needs sage.libs.pari sage.rings.padics
sage: E.j_invariant()  # the j-invariant is a p-adic integer                # needs sage.libs.pari sage.rings.padics
2 + 4*5^2 + O(5^3)
sage: E.pari_curve()                                                        # needs sage.libs.pari sage.rings.padics
[0, 0, 0, 1, 1, 0, 2, 4, -1, -48, -864, -496, 6912/31,
 Vecsmall([2]), [O(5^3)], [0, 0]]
plot(xmin=None, xmax=None, components='both', **args)#

Draw a graph of this elliptic curve.

The plot method is only implemented when there is a natural coercion from the base ring of self to RR. In this case, self is plotted as if it was defined over RR.

INPUT:

  • xmin, xmax – (optional) points will be computed at least within this range, but possibly farther.

  • components – a string, one of the following:

    • both – (default), scale so that both bounded and unbounded components appear

    • bounded – scale the plot to show the bounded component. Raises an error if there is only one real component.

    • unbounded – scale the plot to show the unbounded component, including the two flex points.

  • plot_points – passed to sage.plot.generate_plot_points()

  • adaptive_tolerance – passed to sage.plot.generate_plot_points()

  • adaptive_recursion – passed to sage.plot.generate_plot_points()

  • randomize – passed to sage.plot.generate_plot_points()

  • **args – all other options are passed to sage.plot.line.Line

EXAMPLES:

sage: E = EllipticCurve([0, -1])
sage: plot(E, rgbcolor=hue(0.7))                                            # needs sage.plot
Graphics object consisting of 1 graphics primitive
sage: E = EllipticCurve('37a')
sage: plot(E)                                                               # needs sage.plot
Graphics object consisting of 2 graphics primitives
sage: plot(E, xmin=25, xmax=26)                                             # needs sage.plot
Graphics object consisting of 2 graphics primitives

With github issue #12766 we added the components keyword:

sage: E.real_components()
2
sage: E.plot(components='bounded')                                          # needs sage.plot
Graphics object consisting of 1 graphics primitive
sage: E.plot(components='unbounded')                                        # needs sage.plot
Graphics object consisting of 1 graphics primitive

If there is only one component then specifying components=’bounded’ raises a ValueError:

sage: E = EllipticCurve('9990be2')
sage: E.plot(components='bounded')                                          # needs sage.plot
Traceback (most recent call last):
...
ValueError: no bounded component for this curve

An elliptic curve defined over the Complex Field can not be plotted:

sage: E = EllipticCurve(CC, [0,0,1,-1,0])
sage: E.plot()                                                              # needs sage.plot
Traceback (most recent call last):
...
NotImplementedError: plotting of curves over Complex Field
with 53 bits of precision is not implemented yet
rst_transform(r, s, t)#

Return the transform of the curve by \((r,s,t)\) (with \(u=1\)).

INPUT:

  • r, s, t – three elements of the base ring.

OUTPUT:

The elliptic curve obtained from self by the standard Weierstrass transformation \((u,r,s,t)\) with \(u=1\).

Note

This is just a special case of change_weierstrass_model(), with \(u=1\).

EXAMPLES:

sage: R.<r,s,t> = QQ[]
sage: E = EllipticCurve([1,2,3,4,5])
sage: E.rst_transform(r, s, t)
Elliptic 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 Field
scalar_multiplication(m)#

Return the scalar-multiplication map \([m]\) on this elliptic curve as a sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar object.

EXAMPLES:

sage: E = EllipticCurve('77a1')
sage: m = E.scalar_multiplication(-7); m
Scalar-multiplication endomorphism [-7]
of Elliptic Curve defined by y^2 + y = x^3 + 2*x over Rational Field
sage: m.degree()
49
sage: P = E(2,3)
sage: m(P)
(-26/225 : -2132/3375 : 1)
sage: m.rational_maps() == E.multiplication_by_m(-7)
True
scale_curve(u)#

Return the transform of the curve by scale factor \(u\).

INPUT:

  • u – an invertible element of the base ring.

OUTPUT:

The elliptic curve obtained from self by the standard Weierstrass transformation \((u,r,s,t)\) with \(r=s=t=0\).

Note

This is just a special case of change_weierstrass_model(), with \(r=s=t=0\).

EXAMPLES:

sage: K = Frac(PolynomialRing(QQ, 'u'))
sage: u = K.gen()
sage: E = EllipticCurve([1,2,3,4,5])
sage: E.scale_curve(u)
Elliptic 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 Field
short_weierstrass_model(complete_cube=True)#

Return a short Weierstrass model for self.

INPUT:

  • complete_cube – boolean (default: True); for meaning, see below.

OUTPUT:

An elliptic curve.

If complete_cube=True: Return a model of the form \(y^2 = x^3 + a*x + b\) for this curve. The characteristic must not be 2; in characteristic 3, it is only possible if \(b_2=0\).

If complete_cube=False: Return a model of the form \(y^2 = x^3 + ax^2 + bx + c\) for this curve. The characteristic must not be 2.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
sage: F = E.short_weierstrass_model()
sage: F
Elliptic Curve defined by y^2  = x^3 + 4941*x + 185166 over Rational Field
sage: E.is_isomorphic(F)
True
sage: F = E.short_weierstrass_model(complete_cube=False)
sage: F
Elliptic Curve defined by y^2  = x^3 + 9*x^2 + 88*x + 464 over Rational Field
sage: E.is_isomorphic(F)
True
sage: E = EllipticCurve(GF(3), [1,2,3,4,5])
sage: E.short_weierstrass_model(complete_cube=False)
Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 3

This used to be different see github issue #3973:

sage: E.short_weierstrass_model()
Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 3

More tests in characteristic 3:

sage: E = EllipticCurve(GF(3), [0,2,1,2,1])
sage: E.short_weierstrass_model()
Traceback (most recent call last):
...
ValueError: 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)
sage: E.short_weierstrass_model(complete_cube=False)
Elliptic Curve defined by y^2 = x^3 + 2*x^2 + 2*x + 2
over Finite Field of size 3
sage: E.short_weierstrass_model(complete_cube=False).is_isomorphic(E)
True
torsion_polynomial(m, x=None, two_torsion_multiplicity=2, force_evaluate=None)#

Return the \(m^{th}\) division polynomial of this elliptic curve evaluated at \(x\).

The division polynomial is cached if \(x\) is None.

INPUT:

  • m – positive integer.

  • x – optional ring element to use as the \(x\) variable. If \(x\) is None (omitted), then a new polynomial ring will be constructed over the base ring of the elliptic curve, and its generator will be used as \(x\). Note that \(x\) does not need to be a generator of a polynomial ring; any ring element works. This permits fast calculation of the torsion polynomial evaluated on any element of a ring.

  • two_torsion_multiplicity – 0, 1, or 2

    If 0: For even \(m\) when \(x\) is None, a univariate polynomial over the base ring of the curve is returned, which omits factors whose roots are the \(x\)-coordinates of the \(2\)-torsion points. When \(x\) is not None, the evaluation of such a polynomial at \(x\) is returned.

    If 2: For even \(m\) when \(x\) is None, a univariate polynomial over the base ring of the curve is returned, which includes a factor of degree 3 whose roots are the \(x\)-coordinates of the \(2\)-torsion points. Similarly, when \(x\) is not None, the evaluation of such a polynomial at \(x\) is returned.

    If 1: For even \(m\) when \(x\) is None, a bivariate polynomial over the base ring of the curve is returned, which includes a factor \(2y+a_1x+a_3\) having simple zeros at the \(2\)-torsion points. When \(x\) is not None, it should be a tuple of length 2, and the evaluation of such a polynomial at \(x\) is returned.

  • force_evaluate (optional) – 0, 1, or 2

    By default, this method makes use of previously cached generic division polynomials to compute the value of the polynomial at a given element \(x\) whenever it appears beneficial to do so. Explicitly setting this flag overrides the default behavior.

    Note that the complexity of evaluating a generic division polynomial scales much worse than that of computing the value at a point directly (using the recursive formulas), hence setting this flag can be detrimental to performance.

    If 0: Do not use cached generic division polynomials.

    If 1: If the generic division polynomial for this \(m\) has been cached before, evaluate it at \(x\) to compute the result.

    If 2: Compute the value at \(x\) by evaluating the generic division polynomial. If the generic \(m\)-division polynomial has not yet been cached, compute and cache it first.

EXAMPLES:

sage: E = EllipticCurve([0,0,1,-1,0])
sage: E.division_polynomial(1)
1
sage: E.division_polynomial(2, two_torsion_multiplicity=0)
1
sage: E.division_polynomial(2, two_torsion_multiplicity=1)
2*y + 1
sage: E.division_polynomial(2, two_torsion_multiplicity=2)
4*x^3 - 4*x + 1
sage: E.division_polynomial(2)
4*x^3 - 4*x + 1
sage: [E.division_polynomial(3, two_torsion_multiplicity=i) for i in range(3)]
[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]
sage: [type(E.division_polynomial(3, two_torsion_multiplicity=i)) for i in range(3)]
[<... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>,
 <... 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>,
 <... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>]
sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: R.<z> = PolynomialRing(QQ)
sage: E.division_polynomial(4, z, 0)
2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821
sage: E.division_polynomial(4, z)
8*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 + 459859

This does not work, since when two_torsion_multiplicity is 1, we compute a bivariate polynomial, and must evaluate at a tuple of length 2:

sage: E.division_polynomial(4,z,1)
Traceback (most recent call last):
...
ValueError: x should be a tuple of length 2 (or None)
when two_torsion_multiplicity is 1
sage: R.<z,w> = PolynomialRing(QQ, 2)
sage: E.division_polynomial(4, (z,w), 1).factor()
(2*w + 1) * (2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821)

We can also evaluate this bivariate polynomial at a point:

sage: P = E(5,5)
sage: E.division_polynomial(4,P,two_torsion_multiplicity=1)
-1771561
two_division_polynomial(x=None)#

Return the 2-division polynomial of this elliptic curve evaluated at x.

INPUT:

  • x – optional ring element to use as the \(x\) variable. If x is None, then a new polynomial ring will be constructed over the base ring of the elliptic curve, and its generator will be used as x. Note that x does not need to be a generator of a polynomial ring; any ring element is acceptable. This permits fast calculation of the torsion polynomial evaluated on any element of a ring.

EXAMPLES:

sage: E = EllipticCurve('5077a1')
sage: E.two_division_polynomial()
4*x^3 - 28*x + 25
sage: E = EllipticCurve(GF(3^2,'a'), [1,1,1,1,1])                           # needs sage.rings.finite_rings
sage: E.two_division_polynomial()                                           # needs sage.rings.finite_rings
x^3 + 2*x^2 + 2
sage: E.two_division_polynomial().roots()                                   # needs sage.rings.finite_rings
[(2, 1), (2*a, 1), (a + 2, 1)]
sage.schemes.elliptic_curves.ell_generic.is_EllipticCurve(x)#

Utility function to test if x is an instance of an Elliptic Curve class.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_generic import is_EllipticCurve
sage: E = EllipticCurve([1,2,3/4,7,19])
sage: is_EllipticCurve(E)
True
sage: is_EllipticCurve(0)
False