Elliptic curves over a general ring#

Sage defines an elliptic curve over a ring R as a Weierstrass Model with five coefficients [a1,a2,a3,a4,a6] in R given by

y2+a1xy+a3y=x3+a2x2+a4x+a6.

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 a1=a2=a3=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
p, a, b = 97, 1, 3
R.<u> = GF(p)[]
S.<v> = R[]
T = S.fraction_field()
E = EllipticCurve(T, [a, b]); E
latex(E)
>>> from sage.all import *
>>> p, a, b = Integer(97), Integer(1), Integer(3)
>>> R = GF(p)['u']; (u,) = R._first_ngens(1)
>>> S = R['v']; (v,) = S._first_ngens(1)
>>> T = S.fraction_field()
>>> 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
>>> 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)[source]#

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)
E = EllipticCurve([1,2,3/4,7,19]); E
loads(E.dumps()) == E
E = EllipticCurve([1,3])
P = E([-1,1,1])
-5*P
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3)/Integer(4),Integer(7),Integer(19)]); E
Elliptic Curve defined by y^2 + x*y + 3/4*y = x^3 + 2*x^2 + 7*x + 19 over Rational Field
>>> loads(E.dumps()) == E
True
>>> E = EllipticCurve([Integer(1),Integer(3)])
>>> P = E([-Integer(1),Integer(1),Integer(1)])
>>> -Integer(5)*P
(179051/80089 : -91814227/22665187 : 1)
a1()[source]#

Return the a1 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a1()
1
E = EllipticCurve([1,2,3,4,6])
E.a1()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(6)])
>>> E.a1()
1
a2()[source]#

Return the a2 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a2()
2
E = EllipticCurve([1,2,3,4,6])
E.a2()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(6)])
>>> E.a2()
2
a3()[source]#

Return the a3 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a3()
3
E = EllipticCurve([1,2,3,4,6])
E.a3()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(6)])
>>> E.a3()
3
a4()[source]#

Return the a4 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a4()
4
E = EllipticCurve([1,2,3,4,6])
E.a4()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(6)])
>>> E.a4()
4
a6()[source]#

Return the a6 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,6])
sage: E.a6()
6
E = EllipticCurve([1,2,3,4,6])
E.a6()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(6)])
>>> E.a6()
6
a_invariants()[source]#

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)
E = EllipticCurve([1,2,3,4,5])
E.a_invariants()
E = EllipticCurve([0,1]); E
E.a_invariants()
E = EllipticCurve([GF(7)(3),5])
E.a_invariants()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> E.a_invariants()
(1, 2, 3, 4, 5)

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

>>> E = EllipticCurve([GF(Integer(7))(Integer(3)),Integer(5)])
>>> E.a_invariants()
(0, 0, 0, 3, 5)
ainvs()[source]#

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)
E = EllipticCurve([1,2,3,4,5])
E.a_invariants()
E = EllipticCurve([0,1]); E
E.a_invariants()
E = EllipticCurve([GF(7)(3),5])
E.a_invariants()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> E.a_invariants()
(1, 2, 3, 4, 5)

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

>>> E = EllipticCurve([GF(Integer(7))(Integer(3)),Integer(5)])
>>> E.a_invariants()
(0, 0, 0, 3, 5)
automorphisms(field=None)[source]#

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)]
E = EllipticCurve_from_j(QQ(0))  # a curve with j=0 over QQ
E.automorphisms()
>>> from sage.all import *
>>> E = EllipticCurve_from_j(QQ(Integer(0)))  # a curve with j=0 over QQ
>>> 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)]
x = polygen(ZZ, 'x')
K.<a> = NumberField(x^2 + 3)  # adjoin roots of unity                 # needs sage.rings.number_field
E.automorphisms(K)                                                    # needs sage.rings.number_field
>>> from sage.all import *
>>> x = polygen(ZZ, 'x')
>>> K = NumberField(x**Integer(2) + Integer(3), names=('a',)); (a,) = K._first_ngens(1)# adjoin roots of unity                 # needs sage.rings.number_field
>>> 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]
[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]]
>>> from sage.all import *
>>> [len(EllipticCurve_from_j(GF(q,'a')(Integer(0))).automorphisms())              # needs sage.rings.finite_rings
...  for q in [Integer(2),Integer(4),Integer(3),Integer(9),Integer(5),Integer(25),Integer(7),Integer(49)]]
[2, 24, 2, 12, 2, 6, 6, 6]
b2()[source]#

Return the b2 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.b2()
9
E = EllipticCurve([1,2,3,4,5])
E.b2()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> E.b2()
9
b4()[source]#

Return the b4 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.b4()
11
E = EllipticCurve([1,2,3,4,5])
E.b4()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> E.b4()
11
b6()[source]#

Return the b6 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.b6()
29
E = EllipticCurve([1,2,3,4,5])
E.b6()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> E.b6()
29
b8()[source]#

Return the b8 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.b8()
35
E = EllipticCurve([1,2,3,4,5])
E.b8()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> E.b8()
35
b_invariants()[source]#

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
E = EllipticCurve([0, -1, 1, -10, -20])
E.b_invariants()
E = EllipticCurve([-4,0])
E.b_invariants()
E = EllipticCurve([1,2,3,4,5])
E.b_invariants()
E.b2()
E.b4()
E.b6()
E.b8()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0), -Integer(1), Integer(1), -Integer(10), -Integer(20)])
>>> E.b_invariants()
(-4, -20, -79, -21)

>>> E = EllipticCurve([-Integer(4),Integer(0)])
>>> E.b_invariants()
(0, -8, 0, -16)

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

ALGORITHM:

These are simple functions of the a-invariants.

AUTHORS:

  • William Stein (2005-04-25)

base_extend(R)[source]#

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
E = EllipticCurve(GF(5), [1,1]); E
E1 = E.base_extend(GF(125,'a')); E1                                   # needs sage.rings.finite_rings
>>> from sage.all import *
>>> E = EllipticCurve(GF(Integer(5)), [Integer(1),Integer(1)]); E
Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
>>> E1 = E.base_extend(GF(Integer(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()[source]#

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
E = EllipticCurve(GF(49, 'a'), [3,5])                                 # needs sage.rings.finite_rings
E.base_ring()                                                         # needs sage.rings.finite_rings
>>> from sage.all import *
>>> E = EllipticCurve(GF(Integer(49), 'a'), [Integer(3),Integer(5)])                                 # needs sage.rings.finite_rings
>>> 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
E = EllipticCurve([1,1])
E.base_ring()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(1)])
>>> E.base_ring()
Rational Field
sage: E = EllipticCurve(ZZ, [3,5])
sage: E.base_ring()
Integer Ring
E = EllipticCurve(ZZ, [3,5])
E.base_ring()
>>> from sage.all import *
>>> E = EllipticCurve(ZZ, [Integer(3),Integer(5)])
>>> E.base_ring()
Integer Ring
c4()[source]#

Return the c4 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.c4()
496
E = EllipticCurve([0, -1, 1, -10, -20])
E.c4()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0), -Integer(1), Integer(1), -Integer(10), -Integer(20)])
>>> E.c4()
496
c6()[source]#

Return the c6 invariant of this elliptic curve.

EXAMPLES:

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.c6()
20008
E = EllipticCurve([0, -1, 1, -10, -20])
E.c6()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0), -Integer(1), Integer(1), -Integer(10), -Integer(20)])
>>> E.c6()
20008
c_invariants()[source]#

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)
E = EllipticCurve([0, -1, 1, -10, -20])
E.c_invariants()
E = EllipticCurve([-4,0])
E.c_invariants()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0), -Integer(1), Integer(1), -Integer(10), -Integer(20)])
>>> E.c_invariants()
(496, 20008)

>>> E = EllipticCurve([-Integer(4),Integer(0)])
>>> E.c_invariants()
(192, 0)

ALGORITHM:

These are simple functions of the a-invariants.

AUTHORS:

  • William Stein (2005-04-25)

change_ring(R)[source]#

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

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

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

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
E = EllipticCurve([0,0,1,-1,0])
E.discriminant()
E = EllipticCurve([0, -1, 1, -10, -20])
E.discriminant()
E = EllipticCurve([GF(7)(2),1])
E.discriminant()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0),Integer(0),Integer(1),-Integer(1),Integer(0)])
>>> E.discriminant()
37

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

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

Return the mth 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+a1x+a3 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'>]
E = EllipticCurve([0,0,1,-1,0])
E.division_polynomial(1)
E.division_polynomial(2, two_torsion_multiplicity=0)
E.division_polynomial(2, two_torsion_multiplicity=1)
E.division_polynomial(2, two_torsion_multiplicity=2)
E.division_polynomial(2)
[E.division_polynomial(3, two_torsion_multiplicity=i) for i in range(3)]
[type(E.division_polynomial(3, two_torsion_multiplicity=i)) for i in range(3)]
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0),Integer(0),Integer(1),-Integer(1),Integer(0)])
>>> E.division_polynomial(Integer(1))
1
>>> E.division_polynomial(Integer(2), two_torsion_multiplicity=Integer(0))
1
>>> E.division_polynomial(Integer(2), two_torsion_multiplicity=Integer(1))
2*y + 1
>>> E.division_polynomial(Integer(2), two_torsion_multiplicity=Integer(2))
4*x^3 - 4*x + 1
>>> E.division_polynomial(Integer(2))
4*x^3 - 4*x + 1
>>> [E.division_polynomial(Integer(3), two_torsion_multiplicity=i) for i in range(Integer(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]
>>> [type(E.division_polynomial(Integer(3), two_torsion_multiplicity=i)) for i in range(Integer(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
E = EllipticCurve([0, -1, 1, -10, -20])
R.<z> = PolynomialRing(QQ)
E.division_polynomial(4, z, 0)
E.division_polynomial(4, z)
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0), -Integer(1), Integer(1), -Integer(10), -Integer(20)])
>>> R = PolynomialRing(QQ, names=('z',)); (z,) = R._first_ngens(1)
>>> E.division_polynomial(Integer(4), z, Integer(0))
2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821
>>> E.division_polynomial(Integer(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)
E.division_polynomial(4,z,1)
R.<z,w> = PolynomialRing(QQ, 2)
E.division_polynomial(4, (z,w), 1).factor()
>>> from sage.all import *
>>> E.division_polynomial(Integer(4),z,Integer(1))
Traceback (most recent call last):
...
ValueError: x should be a tuple of length 2 (or None)
when two_torsion_multiplicity is 1
>>> R = PolynomialRing(QQ, Integer(2), names=('z', 'w',)); (z, w,) = R._first_ngens(2)
>>> E.division_polynomial(Integer(4), (z,w), Integer(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
P = E(5,5)
E.division_polynomial(4,P,two_torsion_multiplicity=1)
>>> from sage.all import *
>>> P = E(Integer(5),Integer(5))
>>> E.division_polynomial(Integer(4),P,two_torsion_multiplicity=Integer(1))
-1771561
division_polynomial_0(n, x=None)[source]#

Return the nth torsion (division) polynomial, without the 2-torsion factor if n is even, as a polynomial in x.

These are the polynomials gn 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 B6=(2y+a1x+a3)2 and B62 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(log2n) 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
E = EllipticCurve("37a")
E.division_polynomial_0(1)
E.division_polynomial_0(2)
E.division_polynomial_0(3)
E.division_polynomial_0(4)
E.division_polynomial_0(5)
E.division_polynomial_0(6)
E.division_polynomial_0(7)
E.division_polynomial_0(8)
>>> from sage.all import *
>>> E = EllipticCurve("37a")
>>> E.division_polynomial_0(Integer(1))
1
>>> E.division_polynomial_0(Integer(2))
1
>>> E.division_polynomial_0(Integer(3))
3*x^4 - 6*x^2 + 3*x - 1
>>> E.division_polynomial_0(Integer(4))
2*x^6 - 10*x^4 + 10*x^3 - 10*x^2 + 2*x + 1
>>> E.division_polynomial_0(Integer(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
>>> E.division_polynomial_0(Integer(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
>>> E.division_polynomial_0(Integer(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
>>> E.division_polynomial_0(Integer(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
E.division_polynomial_0(18) % E.division_polynomial_0(6) == 0
>>> from sage.all import *
>>> E.division_polynomial_0(Integer(18)) % E.division_polynomial_0(Integer(6)) == Integer(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)
F = GF(11)
E = EllipticCurve(F, [0, 2]); E
f = E.division_polynomial_0(5); f
f.factor()
>>> from sage.all import *
>>> F = GF(Integer(11))
>>> E = EllipticCurve(F, [Integer(0), Integer(2)]); E
Elliptic Curve defined by y^2  = x^3 + 2 over Finite Field of size 11
>>> f = E.division_polynomial_0(Integer(5)); f
5*x^12 + x^9 + 8*x^6 + 4*x^3 + 7
>>> 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 F112, and therefore the y-coordinates are in F114:

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]
# needs sage.rings.finite_rings
K = GF(11^4, 'a')
X = E.change_ring(K)
f = X.division_polynomial_0(5)
x_coords = f.roots(multiplicities=False); x_coords
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> K = GF(Integer(11)**Integer(4), 'a')
>>> X = E.change_ring(K)
>>> f = X.division_polynomial_0(Integer(5))
>>> 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
for x in x_coords:                                                    # needs sage.rings.finite_rings
    assert X.lift_x(x).order() == 5
>>> from sage.all import *
>>> for x in x_coords:                                                    # needs sage.rings.finite_rings
...     assert X.lift_x(x).order() == Integer(5)

The roots of the polynomial are the x-coordinates of the points P such that mP=0 but 2P0:

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)], [], []]
E = EllipticCurve('14a1')
T = E.torsion_subgroup()
[n*T.0 for n in range(6)]
pol = E.division_polynomial_0(6)
xlist = pol.roots(multiplicities=False); xlist
[E.lift_x(x, all=True) for x in xlist]
>>> from sage.all import *
>>> E = EllipticCurve('14a1')
>>> T = E.torsion_subgroup()
>>> [n*T.gen(0) for n in range(Integer(6))]
[(0 : 1 : 0),
(9 : 23 : 1),
(2 : 2 : 1),
(1 : -1 : 1),
(2 : -5 : 1),
(9 : -33 : 1)]
>>> pol = E.division_polynomial_0(Integer(6))
>>> xlist = pol.roots(multiplicities=False); xlist
[9, 2, -1/3, -5]
>>> [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()[source]#

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
E = EllipticCurve("37a")
E.formal_group()
>>> from sage.all import *
>>> E = EllipticCurve("37a")
>>> E.formal_group()
Formal Group associated to the Elliptic Curve
defined by y^2 + y = x^3 - x over Rational Field
formal_group()[source]#

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
E = EllipticCurve("37a")
E.formal_group()
>>> from sage.all import *
>>> E = EllipticCurve("37a")
>>> 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)[source]#

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
# needs sage.rings.finite_rings
z3, = GF(13^3).gens()
E = EllipticCurve([z3, z3^2])
E.frobenius_isogeny()
E.frobenius_isogeny(3)
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> z3, = GF(Integer(13)**Integer(3)).gens()
>>> E = EllipticCurve([z3, z3**Integer(2)])
>>> 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
>>> E.frobenius_isogeny(Integer(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)[source]#

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.
R.<a1,a2,a3,a4,a6> = QQ[]
E = EllipticCurve([a1,a2,a3,a4,a6])
E.gen(0)
>>> from sage.all import *
>>> R = QQ['a1, a2, a3, a4, a6']; (a1, a2, a3, a4, a6,) = R._first_ngens(5)
>>> E = EllipticCurve([a1,a2,a3,a4,a6])
>>> E.gen(Integer(0))
Traceback (most recent call last):
...
NotImplementedError: not implemented.
gens()[source]#

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)]
R.<a1,a2,a3,a4,a6> = QQ[]
E = EllipticCurve([a1,a2,a3,a4,a6])
E.gens()
E = EllipticCurve(QQ, [1,1])
E.gens()
>>> from sage.all import *
>>> R = QQ['a1, a2, a3, a4, a6']; (a1, a2, a3, a4, a6,) = R._first_ngens(5)
>>> E = EllipticCurve([a1,a2,a3,a4,a6])
>>> E.gens()
Traceback (most recent call last):
...
NotImplementedError: not implemented.
>>> E = EllipticCurve(QQ, [Integer(1),Integer(1)])
>>> E.gens()
[(0 : 1 : 1)]
hyperelliptic_polynomials()[source]#

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

y2+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)
R.<a1,a2,a3,a4,a6>=QQ[]
E = EllipticCurve([a1,a2,a3,a4,a6])
E.hyperelliptic_polynomials()
>>> from sage.all import *
>>> R = QQ['a1, a2, a3, a4, a6']; (a1, a2, a3, a4, a6,) = R._first_ngens(5)
>>> E = EllipticCurve([a1,a2,a3,a4,a6])
>>> E.hyperelliptic_polynomials()
(x^3 + a2*x^2 + a4*x + a6, a1*x + a3)
identity_morphism()[source]#

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
E = EllipticCurve(j=42)
E.identity_morphism()
E.identity_morphism() == E.scalar_multiplication(1)
>>> from sage.all import *
>>> E = EllipticCurve(j=Integer(42))
>>> 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)
>>> E.identity_morphism() == E.scalar_multiplication(Integer(1))
True
is_isomorphic(other, field=None)[source]#

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
E = EllipticCurve('389a')
F = E.change_weierstrass_model([2,3,4,5]); F
E.is_isomorphic(F)
E.is_isomorphic(F.change_ring(CC))
>>> from sage.all import *
>>> E = EllipticCurve('389a')
>>> F = E.change_weierstrass_model([Integer(2),Integer(3),Integer(4),Integer(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
>>> E.is_isomorphic(F)
True
>>> E.is_isomorphic(F.change_ring(CC))
False
is_on_curve(x, y)[source]#

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
E = EllipticCurve(QQ,[1,1])
E.is_on_curve(0,1)
E.is_on_curve(1,1)
>>> from sage.all import *
>>> E = EllipticCurve(QQ,[Integer(1),Integer(1)])
>>> E.is_on_curve(Integer(0),Integer(1))
True
>>> E.is_on_curve(Integer(1),Integer(1))
False
is_x_coord(x)[source]#

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
E = EllipticCurve('37a'); E
E.is_x_coord(1)
E.is_x_coord(2)
>>> from sage.all import *
>>> E = EllipticCurve('37a'); E
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
>>> E.is_x_coord(Integer(1))
True
>>> E.is_x_coord(Integer(2))
True

There are no rational points with x-coordinate 3:

sage: E.is_x_coord(3)
False
E.is_x_coord(3)
>>> from sage.all import *
>>> E.is_x_coord(Integer(3))
False

However, there are such points in E(R):

sage: E.change_ring(RR).is_x_coord(3)
True
E.change_ring(RR).is_x_coord(3)
>>> from sage.all import *
>>> E.change_ring(RR).is_x_coord(Integer(3))
True

And of course it always works in E(C):

sage: E.change_ring(RR).is_x_coord(-3)
False
sage: E.change_ring(CC).is_x_coord(-3)
True
E.change_ring(RR).is_x_coord(-3)
E.change_ring(CC).is_x_coord(-3)
>>> from sage.all import *
>>> E.change_ring(RR).is_x_coord(-Integer(3))
False
>>> E.change_ring(CC).is_x_coord(-Integer(3))
True

AUTHORS:

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

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

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
E = EllipticCurve([1, 2, 3, 4, 5])
iso = E.isomorphism(6); iso
iso.domain() == E
iso.codomain() == E.scale_curve(1 / 6)
iso = E.isomorphism(1, 7, 8, 9); iso
iso.domain() == E
iso.codomain() == E.rst_transform(7, 8, 9)
iso = E.isomorphism(6, 7, 8, 9); iso
iso.domain() == E
iso.codomain() == E.rst_transform(7, 8, 9).scale_curve(1 / 6)
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1), Integer(2), Integer(3), Integer(4), Integer(5)])
>>> iso = E.isomorphism(Integer(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)
>>> iso.domain() == E
True
>>> iso.codomain() == E.scale_curve(Integer(1) / Integer(6))
True

>>> iso = E.isomorphism(Integer(1), Integer(7), Integer(8), Integer(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)
>>> iso.domain() == E
True
>>> iso.codomain() == E.rst_transform(Integer(7), Integer(8), Integer(9))
True

>>> iso = E.isomorphism(Integer(6), Integer(7), Integer(8), Integer(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)
>>> iso.domain() == E
True
>>> iso.codomain() == E.rst_transform(Integer(7), Integer(8), Integer(9)).scale_curve(Integer(1) / Integer(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
E = EllipticCurve([1, 2, 3, 4, 5])
iso = E.isomorphism(6, is_codomain=True); iso
iso.domain() == E.scale_curve(6)
iso.codomain() == E
iso = E.isomorphism(1, 7, 8, 9, is_codomain=True); iso
iso.domain().rst_transform(7, 8, 9) == E
iso.codomain() == E
iso = E.isomorphism(6, 7, 8, 9, is_codomain=True); iso
iso.domain().rst_transform(7, 8, 9) == E.scale_curve(6)
iso.codomain() == E
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1), Integer(2), Integer(3), Integer(4), Integer(5)])
>>> iso = E.isomorphism(Integer(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)
>>> iso.domain() == E.scale_curve(Integer(6))
True
>>> iso.codomain() == E
True

>>> iso = E.isomorphism(Integer(1), Integer(7), Integer(8), Integer(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)
>>> iso.domain().rst_transform(Integer(7), Integer(8), Integer(9)) == E
True
>>> iso.codomain() == E
True

>>> iso = E.isomorphism(Integer(6), Integer(7), Integer(8), Integer(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)
>>> iso.domain().rst_transform(Integer(7), Integer(8), Integer(9)) == E.scale_curve(Integer(6))
True
>>> iso.codomain() == E
True
isomorphism_to(other)[source]#

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
E = EllipticCurve('37a')
F = E.short_weierstrass_model()
w = E.isomorphism_to(F); w
P = E(0,-1,1)
w(P)
w(5*P)
5*w(P)
120*w(P) == w(120*P)
>>> from sage.all import *
>>> E = EllipticCurve('37a')
>>> F = E.short_weierstrass_model()
>>> 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)
>>> P = E(Integer(0),-Integer(1),Integer(1))
>>> w(P)
(0 : -4 : 1)
>>> w(Integer(5)*P)
(1 : 1 : 1)
>>> Integer(5)*w(P)
(1 : 1 : 1)
>>> Integer(120)*w(P) == w(Integer(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)
x = polygen(ZZ, 'x')
K.<a> = NumberField(x^3 - 7)                                          # needs sage.rings.number_field
E.isomorphism_to(E.change_ring(K))                                    # needs sage.rings.number_field
>>> from sage.all import *
>>> x = polygen(ZZ, 'x')
>>> K = NumberField(x**Integer(3) - Integer(7), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field
>>> 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)[source]#

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)]
E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ
F = EllipticCurve('27a3') # should be the same one
E.isomorphisms(F)
>>> from sage.all import *
>>> E = EllipticCurve_from_j(QQ(Integer(0))) # a curve with j=0 over QQ
>>> F = EllipticCurve('27a3') # should be the same one
>>> 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)]
# needs sage.rings.finite_rings
E = EllipticCurve(GF(7), [0,0,0,1,1])
F = EllipticCurve(GF(7), [0,0,0,1,-1])
E.isomorphisms(F)
E.isomorphisms(F, GF(49,'a'))
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> E = EllipticCurve(GF(Integer(7)), [Integer(0),Integer(0),Integer(0),Integer(1),Integer(1)])
>>> F = EllipticCurve(GF(Integer(7)), [Integer(0),Integer(0),Integer(0),Integer(1),-Integer(1)])
>>> E.isomorphisms(F)
[]
>>> E.isomorphisms(F, GF(Integer(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()[source]#

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
E = EllipticCurve([0,0,1,-1,0])
E.j_invariant()
E = EllipticCurve([0, -1, 1, -10, -20])
E.j_invariant()
E = EllipticCurve([-4,0])
E.j_invariant()
E = EllipticCurve([GF(7)(2),1])
E.j_invariant()
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0),Integer(0),Integer(1),-Integer(1),Integer(0)])
>>> E.j_invariant()
110592/37

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

>>> E = EllipticCurve([-Integer(4),Integer(0)])
>>> E.j_invariant()
1728

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

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)]
E = EllipticCurve('37a'); E
E.lift_x(1)
E.lift_x(2)
E.lift_x(1/4, all=True)
>>> from sage.all import *
>>> E = EllipticCurve('37a'); E
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
>>> E.lift_x(Integer(1))
(1 : -1 : 1)
>>> E.lift_x(Integer(2))
(2 : -3 : 1)
>>> E.lift_x(Integer(1)/Integer(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
E.lift_x(3)
>>> from sage.all import *
>>> E.lift_x(Integer(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
P = E.lift_x(3, extend=True); P                                       # needs sage.rings.number_field
P.curve()                                                             # needs sage.rings.number_field
>>> from sage.all import *
>>> P = E.lift_x(Integer(3), extend=True); P                                       # needs sage.rings.number_field
(3 : -y - 1 : 1)
>>> 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(R):

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

And of course it always works in E(C):

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)
E.change_ring(RR).lift_x(.5, all=True)
E.change_ring(CC).lift_x(.5)
>>> from sage.all import *
>>> E.change_ring(RR).lift_x(RealNumber('.5'), all=True)
[]
>>> E.change_ring(CC).lift_x(RealNumber('.5'))
(0.500000000000000 : -0.500000000000000 - 0.353553390593274*I : 1.00000000000000)

In this example we start with a curve defined over Q 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
E = EllipticCurve([0,0,0,0,2]); E
P = E.lift_x(0, extend=True); P                                       # needs sage.rings.number_field
P.curve()                                                             # needs sage.rings.number_field
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0),Integer(0),Integer(0),Integer(0),Integer(2)]); E
Elliptic Curve defined by y^2 = x^3 + 2 over Rational Field
>>> P = E.lift_x(Integer(0), extend=True); P                                       # needs sage.rings.number_field
(0 : -y : 1)
>>> 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
E = EllipticCurve('37a').change_ring(GF(17)); E
E.lift_x(7)
E.lift_x(3)
>>> from sage.all import *
>>> E = EllipticCurve('37a').change_ring(GF(Integer(17))); E
Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17
>>> E.lift_x(Integer(7))
(7 : 5 : 1)
>>> E.lift_x(Integer(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(F17):

sage: E.lift_x(10, all=True)
[(10 : 8 : 1)]
E.lift_x(10, all=True)
>>> from sage.all import *
>>> E.lift_x(Integer(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
E = EllipticCurve('37a')
P = E.lift_x(pAdicField(17, 5)(6)); P                                 # needs sage.rings.padics
P.curve()                                                             # needs sage.rings.padics
K.<t> = PowerSeriesRing(QQ, 't', 5)
P = E.lift_x(1 + t); P
K.<a> = GF(16)                                                        # needs sage.rings.finite_rings
P = E.change_ring(K).lift_x(a^3); P                                   # needs sage.rings.finite_rings
P.curve()                                                             # needs sage.rings.finite_rings
>>> from sage.all import *
>>> E = EllipticCurve('37a')
>>> P = E.lift_x(pAdicField(Integer(17), Integer(5))(Integer(6))); P                                 # needs sage.rings.padics
(6 + O(17^5) : 14 + O(17^5) : 1 + O(17^5))
>>> 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
>>> K = PowerSeriesRing(QQ, 't', Integer(5), names=('t',)); (t,) = K._first_ngens(1)
>>> P = E.lift_x(Integer(1) + t); P
(1 + t : -1 - 2*t + t^2 - 5*t^3 + 21*t^4 + O(t^5) : 1)
>>> K = GF(Integer(16), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.finite_rings
>>> P = E.change_ring(K).lift_x(a**Integer(3)); P                                   # needs sage.rings.finite_rings
(a^3 : a^3 + a : 1)
>>> 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)
E = EllipticCurve([0,0,0,0,2]); E
x = polygen(QQ)
P = E.lift_x(x, extend=True); P
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0),Integer(0),Integer(0),Integer(0),Integer(2)]); E
Elliptic Curve defined by y^2 = x^3 + 2 over Rational Field
>>> x = polygen(QQ)
>>> 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)
P.curve()
-P
2*P
>>> from sage.all import *
>>> 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
>>> -P
(x : y : 1)
>>> Integer(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 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))
K = Qp(5)                                                             # needs sage.rings.padics
E = EllipticCurve([K(0), K(1)])                                       # needs sage.rings.padics
E.lift_x(1, extend=True)                                              # needs sage.rings.padics
>>> from sage.all import *
>>> K = Qp(Integer(5))                                                             # needs sage.rings.padics
>>> E = EllipticCurve([K(Integer(0)), K(Integer(1))])                                       # needs sage.rings.padics
>>> E.lift_x(Integer(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)[source]#

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

A Montgomery curve is a smooth projective curve of the form

BY2=X3+AX2+X.

The Montgomery curve is called untwisted if B=1.

INPUT:

  • twisted – boolean (default: False); allow B1

  • 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
E = EllipticCurve(QQbar, '11a1')                                      # needs sage.rings.number_field
E.montgomery_model()                                                  # needs sage.rings.number_field
>>> from sage.all import *
>>> E = EllipticCurve(QQbar, '11a1')                                      # needs sage.rings.number_field
>>> 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
E = EllipticCurve(GF(431^2), [7,7])                                   # needs sage.rings.finite_rings
E.montgomery_model()                                                  # needs sage.rings.finite_rings
>>> from sage.all import *
>>> E = EllipticCurve(GF(Integer(431)**Integer(2)), [Integer(7),Integer(7)])                                   # needs sage.rings.finite_rings
>>> 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))
E.montgomery_model(morphism=True)                                     # needs sage.rings.finite_rings
>>> from sage.all import *
>>> 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
E = EllipticCurve(GF(257), [1,1])
E.montgomery_model()
>>> from sage.all import *
>>> E = EllipticCurve(GF(Integer(257)), [Integer(1),Integer(1)])
>>> 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
E = EllipticCurve(GF(257), [10,10])
E.montgomery_model()
>>> from sage.all import *
>>> E = EllipticCurve(GF(Integer(257)), [Integer(10),Integer(10)])
>>> 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
E.montgomery_model(twisted=True)
>>> from sage.all import *
>>> 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)
C, f = E.montgomery_model(twisted=True, morphism=True)
f
g = f.inverse(); g
P = C(70, 8)
Q = C(17, 17)
P + Q             # this doesn't work...
f(g(P) + g(Q))    # ...but this does
>>> from sage.all import *
>>> C, f = E.montgomery_model(twisted=True, morphism=True)
>>> 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)
>>> 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)
>>> P = C(Integer(70), Integer(8))
>>> Q = C(Integer(17), Integer(17))
>>> P + Q             # this doesn't work...
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for +: ...
>>> f(g(P) + g(Q))    # ...but this does
(107 : 168 : 1)

Using the fact that the Weil pairing satisfies e(ψ(P),ψ(Q))=e(P,Q)degψ, 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
# needs sage.rings.finite_rings
F.<z2> = GF(257^2)
C_ = C.change_ring(F)
g_ = g.change_ring(F)
g_(P).order()
T = C_(-7 * z2 - 57, 31 * z2 - 52, 1)
g_(T).order()
g_(P).weil_pairing(g_(T), 12)
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> F = GF(Integer(257)**Integer(2), names=('z2',)); (z2,) = F._first_ngens(1)
>>> C_ = C.change_ring(F)
>>> g_ = g.change_ring(F)
>>> g_(P).order()
12
>>> T = C_(-Integer(7) * z2 - Integer(57), Integer(31) * z2 - Integer(52), Integer(1))
>>> g_(T).order()
12
>>> g_(P).weil_pairing(g_(T), Integer(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
C_ = E.change_ring(F).montgomery_model(); C_                          # needs sage.rings.finite_rings
h = C.defining_polynomial().change_ring(F); h                         # needs sage.rings.finite_rings
C_.is_isomorphic(EllipticCurve_from_cubic(h).codomain())              # needs sage.rings.finite_rings
>>> from sage.all import *
>>> 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
>>> 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
>>> 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)[source]#

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])
E = EllipticCurve([-1,3])
>>> from sage.all import *
>>> E = EllipticCurve([-Integer(1),Integer(3)])

We verify that multiplication by 1 is just the identity:

sage: E.multiplication_by_m(1)
(x, y)
E.multiplication_by_m(1)
>>> from sage.all import *
>>> E.multiplication_by_m(Integer(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))
f = E.multiplication_by_m(2)
f
>>> from sage.all import *
>>> f = E.multiplication_by_m(Integer(2))
>>> 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
mx = E.multiplication_by_m(2, x_only=True); mx
mx.parent()
>>> from sage.all import *
>>> mx = E.multiplication_by_m(Integer(2), x_only=True); mx
(1/4*x^4 + 1/2*x^2 - 6*x + 1/4)/(x^3 - x + 3)
>>> 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
P = E([2,3])
eval = lambda f,P: [fi(P[0],P[1]) for fi in f]
assert E(eval(f,P)) == 2*P
>>> from sage.all import *
>>> P = E([Integer(2),Integer(3)])
>>> eval = lambda f,P: [fi(P[Integer(0)],P[Integer(1)]) for fi in f]
>>> assert E(eval(f,P)) == Integer(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
f = E.multiplication_by_m(3)
assert E(eval(f,P)) == 3*P
>>> from sage.all import *
>>> f = E.multiplication_by_m(Integer(3))
>>> assert E(eval(f,P)) == Integer(3)*P

And the same with multiplication by 4:

sage: f = E.multiplication_by_m(4)
sage: assert E(eval(f,P)) == 4*P
f = E.multiplication_by_m(4)
assert E(eval(f,P)) == 4*P
>>> from sage.all import *
>>> f = E.multiplication_by_m(Integer(4))
>>> assert E(eval(f,P)) == Integer(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
for m in [-1,-2,-3,-4]:
    f = E.multiplication_by_m(m)
    assert E(eval(f,P)) == m*P
>>> from sage.all import *
>>> for m in [-Integer(1),-Integer(2),-Integer(3),-Integer(4)]:
...     f = E.multiplication_by_m(m)
...     assert E(eval(f,P)) == m*P
multiplication_by_m_isogeny(m)[source]#

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 Issue #7368 and 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
E = EllipticCurve('11a1')
E.multiplication_by_m_isogeny(7)
>>> from sage.all import *
>>> E = EllipticCurve('11a1')
>>> E.multiplication_by_m_isogeny(Integer(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()[source]#

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
# needs sage.libs.pari
E = EllipticCurve([RR(0), RR(0), RR(1), RR(-1), RR(0)])
e = E.pari_curve()
type(e)
e.type()
e.disc()
>>> from sage.all import *
>>> # needs sage.libs.pari
>>> E = EllipticCurve([RR(Integer(0)), RR(Integer(0)), RR(Integer(1)), RR(-Integer(1)), RR(Integer(0))])
>>> e = E.pari_curve()
>>> type(e)
<... 'cypari2.gen.Gen'>
>>> e.type()
't_VEC'
>>> 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]]
EllipticCurve(GF(41), [2,5]).pari_curve()                             # needs sage.libs.pari
>>> from sage.all import *
>>> EllipticCurve(GF(Integer(41)), [Integer(2),Integer(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)
# needs sage.libs.pari sage.rings.padics
Qp = pAdicField(5, prec=3)
E = EllipticCurve(Qp, [3, 4])
E.pari_curve()
E.j_invariant()
>>> from sage.all import *
>>> # needs sage.libs.pari sage.rings.padics
>>> Qp = pAdicField(Integer(5), prec=Integer(3))
>>> E = EllipticCurve(Qp, [Integer(3), Integer(4)])
>>> E.pari_curve()
[0, 0, 0, 3, 4, 0, 6, 16, -9, -144, -3456, -8640, 1728/5,
 Vecsmall([2]), [O(5^3)], [0, 0]]
>>> 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]]
K.<a> = QuadraticField(2)                                             # needs sage.libs.pari sage.rings.number_field
E = EllipticCurve([1,a])                                              # needs sage.libs.pari sage.rings.number_field
E.pari_curve()                                                        # needs sage.libs.pari sage.rings.number_field
>>> from sage.all import *
>>> K = QuadraticField(Integer(2), names=('a',)); (a,) = K._first_ngens(1)# needs sage.libs.pari sage.rings.number_field
>>> E = EllipticCurve([Integer(1),a])                                              # needs sage.libs.pari sage.rings.number_field
>>> 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]]
E = EllipticCurve(Qp,[1, 1])                                          # needs sage.libs.pari sage.rings.padics
E.j_invariant()  # the j-invariant is a p-adic integer                # needs sage.libs.pari sage.rings.padics
E.pari_curve()                                                        # needs sage.libs.pari sage.rings.padics
>>> from sage.all import *
>>> E = EllipticCurve(Qp,[Integer(1), Integer(1)])                                          # needs sage.libs.pari sage.rings.padics
>>> 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)
>>> 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)[source]#

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
E = EllipticCurve([0, -1])
plot(E, rgbcolor=hue(0.7))                                            # needs sage.plot
E = EllipticCurve('37a')
plot(E)                                                               # needs sage.plot
plot(E, xmin=25, xmax=26)                                             # needs sage.plot
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0), -Integer(1)])
>>> plot(E, rgbcolor=hue(RealNumber('0.7')))                                            # needs sage.plot
Graphics object consisting of 1 graphics primitive
>>> E = EllipticCurve('37a')
>>> plot(E)                                                               # needs sage.plot
Graphics object consisting of 2 graphics primitives
>>> plot(E, xmin=Integer(25), xmax=Integer(26))                                             # needs sage.plot
Graphics object consisting of 2 graphics primitives

With 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
E.real_components()
E.plot(components='bounded')                                          # needs sage.plot
E.plot(components='unbounded')                                        # needs sage.plot
>>> from sage.all import *
>>> E.real_components()
2
>>> E.plot(components='bounded')                                          # needs sage.plot
Graphics object consisting of 1 graphics primitive
>>> 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
E = EllipticCurve('9990be2')
E.plot(components='bounded')                                          # needs sage.plot
>>> from sage.all import *
>>> E = EllipticCurve('9990be2')
>>> 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
E = EllipticCurve(CC, [0,0,1,-1,0])
E.plot()                                                              # needs sage.plot
>>> from sage.all import *
>>> E = EllipticCurve(CC, [Integer(0),Integer(0),Integer(1),-Integer(1),Integer(0)])
>>> 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)[source]#

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
R.<r,s,t> = QQ[]
E = EllipticCurve([1,2,3,4,5])
E.rst_transform(r, s, t)
>>> from sage.all import *
>>> R = QQ['r, s, t']; (r, s, t,) = R._first_ngens(3)
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> 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)[source]#

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

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
K = Frac(PolynomialRing(QQ, 'u'))
u = K.gen()
E = EllipticCurve([1,2,3,4,5])
E.scale_curve(u)
>>> from sage.all import *
>>> K = Frac(PolynomialRing(QQ, 'u'))
>>> u = K.gen()
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> 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)[source]#

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 y2=x3+ax+b for this curve. The characteristic must not be 2; in characteristic 3, it is only possible if b2=0.

If complete_cube=False: Return a model of the form y2=x3+ax2+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
E = EllipticCurve([1,2,3,4,5])
E
F = E.short_weierstrass_model()
F
E.is_isomorphic(F)
F = E.short_weierstrass_model(complete_cube=False)
F
E.is_isomorphic(F)
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
>>> F = E.short_weierstrass_model()
>>> F
Elliptic Curve defined by y^2  = x^3 + 4941*x + 185166 over Rational Field
>>> E.is_isomorphic(F)
True
>>> F = E.short_weierstrass_model(complete_cube=False)
>>> F
Elliptic Curve defined by y^2  = x^3 + 9*x^2 + 88*x + 464 over Rational Field
>>> 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
E = EllipticCurve(GF(3), [1,2,3,4,5])
E.short_weierstrass_model(complete_cube=False)
>>> from sage.all import *
>>> E = EllipticCurve(GF(Integer(3)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> 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 Issue #3973:

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

Return the mth 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+a1x+a3 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'>]
E = EllipticCurve([0,0,1,-1,0])
E.division_polynomial(1)
E.division_polynomial(2, two_torsion_multiplicity=0)
E.division_polynomial(2, two_torsion_multiplicity=1)
E.division_polynomial(2, two_torsion_multiplicity=2)
E.division_polynomial(2)
[E.division_polynomial(3, two_torsion_multiplicity=i) for i in range(3)]
[type(E.division_polynomial(3, two_torsion_multiplicity=i)) for i in range(3)]
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0),Integer(0),Integer(1),-Integer(1),Integer(0)])
>>> E.division_polynomial(Integer(1))
1
>>> E.division_polynomial(Integer(2), two_torsion_multiplicity=Integer(0))
1
>>> E.division_polynomial(Integer(2), two_torsion_multiplicity=Integer(1))
2*y + 1
>>> E.division_polynomial(Integer(2), two_torsion_multiplicity=Integer(2))
4*x^3 - 4*x + 1
>>> E.division_polynomial(Integer(2))
4*x^3 - 4*x + 1
>>> [E.division_polynomial(Integer(3), two_torsion_multiplicity=i) for i in range(Integer(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]
>>> [type(E.division_polynomial(Integer(3), two_torsion_multiplicity=i)) for i in range(Integer(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
E = EllipticCurve([0, -1, 1, -10, -20])
R.<z> = PolynomialRing(QQ)
E.division_polynomial(4, z, 0)
E.division_polynomial(4, z)
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0), -Integer(1), Integer(1), -Integer(10), -Integer(20)])
>>> R = PolynomialRing(QQ, names=('z',)); (z,) = R._first_ngens(1)
>>> E.division_polynomial(Integer(4), z, Integer(0))
2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821
>>> E.division_polynomial(Integer(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)
E.division_polynomial(4,z,1)
R.<z,w> = PolynomialRing(QQ, 2)
E.division_polynomial(4, (z,w), 1).factor()
>>> from sage.all import *
>>> E.division_polynomial(Integer(4),z,Integer(1))
Traceback (most recent call last):
...
ValueError: x should be a tuple of length 2 (or None)
when two_torsion_multiplicity is 1
>>> R = PolynomialRing(QQ, Integer(2), names=('z', 'w',)); (z, w,) = R._first_ngens(2)
>>> E.division_polynomial(Integer(4), (z,w), Integer(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
P = E(5,5)
E.division_polynomial(4,P,two_torsion_multiplicity=1)
>>> from sage.all import *
>>> P = E(Integer(5),Integer(5))
>>> E.division_polynomial(Integer(4),P,two_torsion_multiplicity=Integer(1))
-1771561
two_division_polynomial(x=None)[source]#

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)]
E = EllipticCurve('5077a1')
E.two_division_polynomial()
E = EllipticCurve(GF(3^2,'a'), [1,1,1,1,1])                           # needs sage.rings.finite_rings
E.two_division_polynomial()                                           # needs sage.rings.finite_rings
E.two_division_polynomial().roots()                                   # needs sage.rings.finite_rings
>>> from sage.all import *
>>> E = EllipticCurve('5077a1')
>>> E.two_division_polynomial()
4*x^3 - 28*x + 25
>>> E = EllipticCurve(GF(Integer(3)**Integer(2),'a'), [Integer(1),Integer(1),Integer(1),Integer(1),Integer(1)])                           # needs sage.rings.finite_rings
>>> E.two_division_polynomial()                                           # needs sage.rings.finite_rings
x^3 + 2*x^2 + 2
>>> 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)[source]#

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)
doctest:warning...
DeprecationWarning: The function is_EllipticCurve is deprecated; use 'isinstance(..., EllipticCurve_generic)' instead.
See https://github.com/sagemath/sage/issues/38022 for details.
True
sage: is_EllipticCurve(0)
False
from sage.schemes.elliptic_curves.ell_generic import is_EllipticCurve
E = EllipticCurve([1,2,3/4,7,19])
is_EllipticCurve(E)
is_EllipticCurve(0)
>>> from sage.all import *
>>> from sage.schemes.elliptic_curves.ell_generic import is_EllipticCurve
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3)/Integer(4),Integer(7),Integer(19)])
>>> is_EllipticCurve(E)
doctest:warning...
DeprecationWarning: The function is_EllipticCurve is deprecated; use 'isinstance(..., EllipticCurve_generic)' instead.
See https://github.com/sagemath/sage/issues/38022 for details.
True
>>> is_EllipticCurve(Integer(0))
False