Elliptic curves over a general ring¶
Sage defines an elliptic curve over a ring \(R\) as a ‘Weierstrass Model’ with five coefficients \([a_1,a_2,a_3,a_4,a_6]\) in \(R\) given by
\(y^2 + a_1 xy + a_3 y = x^3 +a_2 x^2 +a_4 x +a_6\).
Note that the (usual) schemetheoretic definition of an elliptic curve over \(R\) would require the discriminant to be a unit in \(R\), Sage only imposes that the discriminant is nonzero. Also, in Magma, ‘Weierstrass Model’ means a model with \(a1=a2=a3=0\), which is called ‘Short Weierstrass Model’ in Sage; these do not always exist in characteristics 2 and 3.
EXAMPLES:
We construct an elliptic curve over an elaborate base ring:
sage: p = 97; a=1; b=3
sage: R.<u> = GF(p)[]
sage: S.<v> = R[]
sage: T = S.fraction_field()
sage: E = EllipticCurve(T, [a, b]); E
Elliptic Curve defined by y^2 = x^3 + x + 3 over Fraction Field of Univariate Polynomial Ring in v over Univariate Polynomial Ring in u over Finite Field of size 97
sage: latex(E)
y^2 = x^{3} + x + 3
AUTHORS:
William Stein (2005): Initial version
Robert Bradshaw et al….
John Cremona (200801): isomorphisms, automorphisms and twists in all characteristics
Julian Rueth (20140411): improved caching

class
sage.schemes.elliptic_curves.ell_generic.
EllipticCurve_generic
(K, ainvs)¶ Bases:
sage.misc.fast_methods.WithEqualityById
,sage.schemes.curves.projective_curve.ProjectivePlaneCurve
Elliptic curve over a generic base ring.
EXAMPLES:
sage: E = EllipticCurve([1,2,3/4,7,19]); E Elliptic Curve defined by y^2 + x*y + 3/4*y = x^3 + 2*x^2 + 7*x + 19 over Rational Field sage: loads(E.dumps()) == E True sage: E = EllipticCurve([1,3]) sage: P = E([1,1,1]) sage: 5*P (179051/80089 : 91814227/22665187 : 1)

a1
()¶ Return the \(a_1\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,6]) sage: E.a1() 1

a2
()¶ Return the \(a_2\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,6]) sage: E.a2() 2

a3
()¶ Return the \(a_3\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,6]) sage: E.a3() 3

a4
()¶ Return the \(a_4\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,6]) sage: E.a4() 4

a6
()¶ Return the \(a_6\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,6]) sage: E.a6() 6

a_invariants
()¶ The \(a\)invariants of this elliptic curve, as a tuple.
OUTPUT:
(tuple)  a 5tuple of the \(a\)invariants of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,5]) sage: E.a_invariants() (1, 2, 3, 4, 5) sage: E = EllipticCurve([0,1]); E Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field sage: E.a_invariants() (0, 0, 0, 0, 1) sage: E = EllipticCurve([GF(7)(3),5]) sage: E.a_invariants() (0, 0, 0, 3, 5)

ainvs
()¶ The \(a\)invariants of this elliptic curve, as a tuple.
OUTPUT:
(tuple)  a 5tuple of the \(a\)invariants of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,5]) sage: E.a_invariants() (1, 2, 3, 4, 5) sage: E = EllipticCurve([0,1]); E Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field sage: E.a_invariants() (0, 0, 0, 0, 1) sage: E = EllipticCurve([GF(7)(3),5]) sage: E.a_invariants() (0, 0, 0, 3, 5)

automorphisms
(field=None)¶ Return the set of isomorphisms from self to itself (as a list).
INPUT:
field
(defaultNone
) – 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 curveself
to itself defined overfield
.EXAMPLES:
sage: E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ sage: E.automorphisms(); [Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Rational Field Via: (u,r,s,t) = (1, 0, 0, 1), Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Rational Field Via: (u,r,s,t) = (1, 0, 0, 0)]
We can also find automorphisms defined over extension fields:
sage: K.<a> = NumberField(x^2+3) # adjoin roots of unity sage: E.automorphisms(K) [Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3 Via: (u,r,s,t) = (1, 0, 0, 1), ... Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3 Via: (u,r,s,t) = (1, 0, 0, 0)]
sage: [ len(EllipticCurve_from_j(GF(q,'a')(0)).automorphisms()) for q in [2,4,3,9,5,25,7,49]] [2, 24, 2, 12, 2, 6, 6, 6]

b2
()¶ Return the \(b_2\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,5]) sage: E.b2() 9

b4
()¶ Return the \(b_4\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,5]) sage: E.b4() 11

b6
()¶ Return the \(b_6\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,5]) sage: E.b6() 29

b8
()¶ Return the \(b_8\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,5]) sage: E.b8() 35

b_invariants
()¶ Return the \(b\)invariants of this elliptic curve, as a tuple.
OUTPUT:
(tuple)  a 4tuple of the \(b\)invariants of this elliptic curve.
This method is cached.
EXAMPLES:
sage: E = EllipticCurve([0, 1, 1, 10, 20]) sage: E.b_invariants() (4, 20, 79, 21) sage: E = EllipticCurve([4,0]) sage: E.b_invariants() (0, 8, 0, 16) sage: E = EllipticCurve([1,2,3,4,5]) sage: E.b_invariants() (9, 11, 29, 35) sage: E.b2() 9 sage: E.b4() 11 sage: E.b6() 29 sage: E.b8() 35
ALGORITHM:
These are simple functions of the \(a\)invariants.
AUTHORS:
William Stein (20050425)

base_extend
(R)¶ Return the base extension of
self
to \(R\).INPUT:
R
– either a ring into which the \(a\)invariants ofself
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 Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 5^3

base_ring
()¶ Return the base ring of the elliptic curve.
EXAMPLES:
sage: E = EllipticCurve(GF(49, 'a'), [3,5]) sage: E.base_ring() Finite Field in a of size 7^2
sage: E = EllipticCurve([1,1]) sage: E.base_ring() Rational Field
sage: E = EllipticCurve(ZZ, [3,5]) sage: E.base_ring() Integer Ring

c4
()¶ Return the \(c_4\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([0, 1, 1, 10, 20]) sage: E.c4() 496

c6
()¶ Return the \(c_6\) invariant of this elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([0, 1, 1, 10, 20]) sage: E.c6() 20008

c_invariants
()¶ Return the \(c\)invariants of this elliptic curve, as a tuple.
This method is cached.
OUTPUT:
(tuple)  a 2tuple of the \(c\)invariants of the elliptic curve.
EXAMPLES:
sage: E = EllipticCurve([0, 1, 1, 10, 20]) sage: E.c_invariants() (496, 20008) sage: E = EllipticCurve([4,0]) sage: E.c_invariants() (192, 0)
ALGORITHM:
These are simple functions of the \(a\)invariants.
AUTHORS:
William Stein (20050425)

change_ring
(R)¶ Return the base change of
self
to \(R\).This has the same effect as
self.base_extend(R)
.EXAMPLES:
sage: F2 = GF(5^2,'a'); a = F2.gen() sage: F4 = GF(5^4,'b'); b = F4.gen() sage: h = F2.hom([a.charpoly().roots(ring=F4,multiplicities=False)[0]],F4) sage: E = EllipticCurve(F2,[1,a]); E Elliptic Curve defined by y^2 = x^3 + x + a over Finite Field in a of size 5^2 sage: E.change_ring(h) Elliptic Curve defined by y^2 = x^3 + x + (4*b^3+4*b^2+4*b+3) over Finite Field in b of size 5^4

change_weierstrass_model
(*urst)¶ Return a new Weierstrass model of self under the standard transformation \((u,r,s,t)\)
\[(x,y) \mapsto (x',y') = (u^2x + r , u^3y + su^2x + t).\]EXAMPLES:
sage: E = EllipticCurve('15a') sage: F1 = E.change_weierstrass_model([1/2,0,0,0]); F1 Elliptic Curve defined by y^2 + 2*x*y + 8*y = x^3 + 4*x^2  160*x  640 over Rational Field sage: F2 = E.change_weierstrass_model([7,2,1/3,5]); F2 Elliptic Curve defined by y^2 + 5/21*x*y + 13/343*y = x^3 + 59/441*x^2  10/7203*x  58/117649 over Rational Field sage: F1.is_isomorphic(F2) True

discriminant
()¶ Return the discriminant of this elliptic curve.
This method is cached.
EXAMPLES:
sage: E = EllipticCurve([0,0,1,1,0]) sage: E.discriminant() 37 sage: E = EllipticCurve([0, 1, 1, 10, 20]) sage: E.discriminant() 161051 sage: E = EllipticCurve([GF(7)(2),1]) sage: E.discriminant() 1

division_polynomial
(m, x=None, two_torsion_multiplicity=2)¶ Return the \(m^{th}\) division polynomial of this elliptic curve evaluated at
x
.INPUT:
m
 positive integer.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 ok. This permits fast calculation of the torsion polynomial evaluated on any element of a ring.two_torsion_multiplicity
 0,1 or 2If 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. Similarly 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: when x is None, a bivariate polynomial over the base ring of the curve is returned, which includes a factor \(2*y+a1*x+a3\) which has 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.
EXAMPLES:
sage: E = EllipticCurve([0,0,1,1,0]) sage: E.division_polynomial(1) 1 sage: E.division_polynomial(2, two_torsion_multiplicity=0) 1 sage: E.division_polynomial(2, two_torsion_multiplicity=1) 2*y + 1 sage: E.division_polynomial(2, two_torsion_multiplicity=2) 4*x^3  4*x + 1 sage: E.division_polynomial(2) 4*x^3  4*x + 1 sage: [E.division_polynomial(3, two_torsion_multiplicity=i) for i in range(3)] [3*x^4  6*x^2 + 3*x  1, 3*x^4  6*x^2 + 3*x  1, 3*x^4  6*x^2 + 3*x  1] sage: [type(E.division_polynomial(3, two_torsion_multiplicity=i)) for i in range(3)] [<... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>, <... 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>, <... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>]
sage: E = EllipticCurve([0, 1, 1, 10, 20]) sage: R.<z>=PolynomialRing(QQ) sage: E.division_polynomial(4,z,0) 2*z^6  4*z^5  100*z^4  790*z^3  210*z^2  1496*z  5821 sage: E.division_polynomial(4,z) 8*z^9  24*z^8  464*z^7  2758*z^6 + 6636*z^5 + 34356*z^4 + 53510*z^3 + 99714*z^2 + 351024*z + 459859
This does not work, since when two_torsion_multiplicity is 1, we compute a bivariate polynomial, and must evaluate at a tuple of length 2:
sage: E.division_polynomial(4,z,1) Traceback (most recent call last): ... ValueError: x should be a tuple of length 2 (or None) when two_torsion_multiplicity is 1 sage: R.<z,w>=PolynomialRing(QQ,2) sage: E.division_polynomial(4,(z,w),1).factor() (2*w + 1) * (2*z^6  4*z^5  100*z^4  790*z^3  210*z^2  1496*z  5821)
We can also evaluate this bivariate polynomial at a point:
sage: P = E(5,5) sage: E.division_polynomial(4,P,two_torsion_multiplicity=1) 1771561

division_polynomial_0
(n, x=None)¶ Return the \(n^{th}\) torsion (division) polynomial, without the 2torsion factor if \(n\) is even, as a polynomial in \(x\).
These are the polynomials \(g_n\) defined in [MT1991], but with the sign flipped for even \(n\), so that the leading coefficient is always positive.
Note
This function is intended for internal use; users should use
division_polynomial()
.See also
multiple_x_numerator()
multiple_x_denominator()
division_polynomial()
INPUT:
n
 positive integer, or the special values1
and2
which mean \(B_6 = (2y + a_1 x + a_3)^2\) and \(B_6^2\) respectively (in the notation of [MT1991]); or a list of integers.x
 a ring element to use as the “x” variable orNone
(default:None
). IfNone
, then a new polynomial ring will be constructed over the base ring of the elliptic curve, and its generator will be used asx
. Note thatx
does not need to be a generator of a polynomial ring; any ring element is ok. This permits fast calculation of the torsion polynomial evaluated on any element of a ring.
ALGORITHM:
Recursion described in [MT1991]. The recursive formulae are evaluated \(O(\log^2 n)\) times.
AUTHORS:
David Harvey (20060924): initial version
John Cremona (20080826): unified division polynomial code
EXAMPLES:
sage: E = EllipticCurve("37a") sage: E.division_polynomial_0(1) 1 sage: E.division_polynomial_0(2) 1 sage: E.division_polynomial_0(3) 3*x^4  6*x^2 + 3*x  1 sage: E.division_polynomial_0(4) 2*x^6  10*x^4 + 10*x^3  10*x^2 + 2*x + 1 sage: E.division_polynomial_0(5) 5*x^12  62*x^10 + 95*x^9  105*x^8  60*x^7 + 285*x^6  174*x^5  5*x^4  5*x^3 + 35*x^2  15*x + 2 sage: E.division_polynomial_0(6) 3*x^16  72*x^14 + 168*x^13  364*x^12 + 1120*x^10  1144*x^9 + 300*x^8  540*x^7 + 1120*x^6  588*x^5  133*x^4 + 252*x^3  114*x^2 + 22*x  1 sage: E.division_polynomial_0(7) 7*x^24  308*x^22 + 986*x^21  2954*x^20 + 28*x^19 + 17171*x^18  23142*x^17 + 511*x^16  5012*x^15 + 43804*x^14  7140*x^13  96950*x^12 + 111356*x^11  19516*x^10  49707*x^9 + 40054*x^8  124*x^7  18382*x^6 + 13342*x^5  4816*x^4 + 1099*x^3  210*x^2 + 35*x  3 sage: E.division_polynomial_0(8) 4*x^30  292*x^28 + 1252*x^27  5436*x^26 + 2340*x^25 + 39834*x^24  79560*x^23 + 51432*x^22  142896*x^21 + 451596*x^20  212040*x^19  1005316*x^18 + 1726416*x^17  671160*x^16  954924*x^15 + 1119552*x^14 + 313308*x^13  1502818*x^12 + 1189908*x^11  160152*x^10  399176*x^9 + 386142*x^8  220128*x^7 + 99558*x^6  33528*x^5 + 6042*x^4 + 310*x^3  406*x^2 + 78*x  5
sage: E.division_polynomial_0(18) % E.division_polynomial_0(6) == 0 True
An example to illustrate the relationship with torsion points:
sage: F = GF(11) sage: E = EllipticCurve(F, [0, 2]); E Elliptic Curve defined by y^2 = x^3 + 2 over Finite Field of size 11 sage: f = E.division_polynomial_0(5); f 5*x^12 + x^9 + 8*x^6 + 4*x^3 + 7 sage: f.factor() (5) * (x^2 + 5) * (x^2 + 2*x + 5) * (x^2 + 5*x + 7) * (x^2 + 7*x + 7) * (x^2 + 9*x + 5) * (x^2 + 10*x + 7)
This indicates that the \(x\)coordinates of all the 5torsion points of \(E\) are in \(\GF{11^2}\), and therefore the \(y\)coordinates are in \(\GF{11^4}\):
sage: K = GF(11^4, 'a') sage: X = E.change_ring(K) sage: f = X.division_polynomial_0(5) sage: x_coords = f.roots(multiplicities=False); x_coords [10*a^3 + 4*a^2 + 5*a + 6, 9*a^3 + 8*a^2 + 10*a + 8, 8*a^3 + a^2 + 4*a + 10, 8*a^3 + a^2 + 4*a + 8, 8*a^3 + a^2 + 4*a + 4, 6*a^3 + 9*a^2 + 3*a + 4, 5*a^3 + 2*a^2 + 8*a + 7, 3*a^3 + 10*a^2 + 7*a + 8, 3*a^3 + 10*a^2 + 7*a + 3, 3*a^3 + 10*a^2 + 7*a + 1, 2*a^3 + 3*a^2 + a + 7, a^3 + 7*a^2 + 6*a]
Now we check that these are exactly the \(x\)coordinates of the 5torsion points of \(E\):
sage: for x in x_coords: ....: assert X.lift_x(x).order() == 5
The roots of the polynomial are the \(x\)coordinates of the points \(P\) such that \(mP=0\) but \(2P\not=0\):
sage: E = EllipticCurve('14a1') sage: T = E.torsion_subgroup() sage: [n*T.0 for n in range(6)] [(0 : 1 : 0), (9 : 23 : 1), (2 : 2 : 1), (1 : 1 : 1), (2 : 5 : 1), (9 : 33 : 1)] sage: pol = E.division_polynomial_0(6) sage: xlist = pol.roots(multiplicities=False); xlist [9, 2, 1/3, 5] sage: [E.lift_x(x, all=True) for x in xlist] [[(9 : 23 : 1), (9 : 33 : 1)], [(2 : 2 : 1), (2 : 5 : 1)], [], []]
Note
The point of order 2 and the identity do not appear. The points with \(x=1/3\) and \(x=5\) are not rational.

formal
()¶ Return the formal group associated to this elliptic curve.
This method is cached.
EXAMPLES:
sage: E = EllipticCurve("37a") sage: E.formal_group() Formal Group associated to the Elliptic Curve defined by y^2 + y = x^3  x over Rational Field

formal_group
()¶ Return the formal group associated to this elliptic curve.
This method is cached.
EXAMPLES:
sage: E = EllipticCurve("37a") sage: E.formal_group() Formal Group associated to the Elliptic Curve defined by y^2 + y = x^3  x over Rational Field

gen
(i)¶ Function returning the i’th generator of this elliptic curve.
Note
Relies on gens() being implemented.
EXAMPLES:
sage: R.<a1,a2,a3,a4,a6>=QQ[] sage: E = EllipticCurve([a1,a2,a3,a4,a6]) sage: E.gen(0) Traceback (most recent call last): ... NotImplementedError: not implemented.

gens
()¶ Placeholder function to return generators of an elliptic curve.
Note
This functionality is implemented in certain derived classes, such as EllipticCurve_rational_field.
EXAMPLES:
sage: R.<a1,a2,a3,a4,a6>=QQ[] sage: E = EllipticCurve([a1,a2,a3,a4,a6]) sage: E.gens() Traceback (most recent call last): ... NotImplementedError: not implemented. sage: E = EllipticCurve(QQ,[1,1]) sage: E.gens() [(0 : 1 : 1)]

hyperelliptic_polynomials
()¶ Return a pair of polynomials \(g(x)\), \(h(x)\) such that this elliptic curve can be defined by the standard hyperelliptic equation
\[y^2 + h(x)y = g(x).\]EXAMPLES:
sage: R.<a1,a2,a3,a4,a6>=QQ[] sage: E = EllipticCurve([a1,a2,a3,a4,a6]) sage: E.hyperelliptic_polynomials() (x^3 + a2*x^2 + a4*x + a6, a1*x + a3)

is_isomorphic
(other, field=None)¶ Return whether or not self is isomorphic to other.
INPUT:
other
– another elliptic curve.field
(default None) – a field into which the coefficients of the curves may be coerced (by default, uses the base field of the curves).
OUTPUT:
(bool) True if there is an isomorphism from curve
self
to curveother
defined overfield
.EXAMPLES:
sage: E = EllipticCurve('389a') sage: F = E.change_weierstrass_model([2,3,4,5]); F Elliptic Curve defined by y^2 + 4*x*y + 11/8*y = x^3  3/2*x^2  13/16*x over Rational Field sage: E.is_isomorphic(F) True sage: E.is_isomorphic(F.change_ring(CC)) False

is_on_curve
(x, y)¶ Return True if \((x,y)\) is an affine point on this curve.
INPUT:
x
,y
 elements of the base ring of the curve.
EXAMPLES:
sage: E = EllipticCurve(QQ,[1,1]) sage: E.is_on_curve(0,1) True sage: E.is_on_curve(1,1) False

is_x_coord
(x)¶ Return True if
x
is the \(x\)coordinate of a point on this curve.Note
See also
lift_x()
to find the point(s) with a given \(x\)coordinate. This function may be useful in cases where testing an element of the base field for being a square is faster than finding its square root.EXAMPLES:
sage: E = EllipticCurve('37a'); E Elliptic Curve defined by y^2 + y = x^3  x over Rational Field sage: E.is_x_coord(1) True sage: E.is_x_coord(2) True
There are no rational points with xcoordinate 3:
sage: E.is_x_coord(3) False
However, there are such points in \(E(\RR)\):
sage: E.change_ring(RR).is_x_coord(3) True
And of course it always works in \(E(\CC)\):
sage: E.change_ring(RR).is_x_coord(3) False sage: E.change_ring(CC).is_x_coord(3) True
AUTHORS:
John Cremona (20080807): adapted from
lift_x()

isomorphism_to
(other)¶ Given another weierstrass model
other
of self, return an isomorphism from self toother
.INPUT:
other
– an elliptic curve isomorphic toself
.
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 Generic morphism: From: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3  x over Rational Field To: Abelian group of points on Elliptic Curve defined by y^2 = x^3  16*x + 16 over Rational Field Via: (u,r,s,t) = (1/2, 0, 0, 1/2) sage: P = E(0,1,1) sage: w(P) (0 : 4 : 1) sage: w(5*P) (1 : 1 : 1) sage: 5*w(P) (1 : 1 : 1) sage: 120*w(P) == w(120*P) True
We can also handle injections to different base rings:
sage: K.<a> = NumberField(x^37) sage: E.isomorphism_to(E.change_ring(K)) Generic morphism: From: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3  x over Rational Field To: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 + (1)*x over Number Field in a with defining polynomial x^3  7 Via: (u,r,s,t) = (1, 0, 0, 0)

isomorphisms
(other, field=None)¶ Return the set of isomorphisms from self to other (as a list).
INPUT:
other
– another elliptic curve.field
(defaultNone
) – 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 curveself
to the curveother
defined overfield
.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); [Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Rational Field Via: (u,r,s,t) = (1, 0, 0, 1), Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Rational Field Via: (u,r,s,t) = (1, 0, 0, 0)]
We can also find isomorphisms defined over extension fields:
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')) [Generic morphism: From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 7^2 To: Abelian group of points on 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), Generic morphism: From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 7^2 To: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 6 over Finite Field in a of size 7^2 Via: (u,r,s,t) = (6*a + 4, 0, 0, 0)]

j_invariant
()¶ Return the \(j\)invariant of this elliptic curve.
This method is cached.
EXAMPLES:
sage: E = EllipticCurve([0,0,1,1,0]) sage: E.j_invariant() 110592/37 sage: E = EllipticCurve([0, 1, 1, 10, 20]) sage: E.j_invariant() 122023936/161051 sage: E = EllipticCurve([4,0]) sage: E.j_invariant() 1728 sage: E = EllipticCurve([GF(7)(2),1]) sage: E.j_invariant() 1

lift_x
(x, all=False, extend=False)¶ Return one or all points with given \(x\)coordinate.
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 basechange of this curve to a larger ring.
See also
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 : 0 : 1) sage: E.lift_x(2) (2 : 2 : 1) sage: E.lift_x(1/4, all=True) [(1/4 : 3/8 : 1), (1/4 : 5/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 xcoordinate 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 (3 : y : 1) sage: P.curve() Elliptic Curve defined by y^2 + y = x^3 + (1)*x over Number Field in y with defining polynomial y^2 + y  24
Or we can extend scalars. There are two such points in \(E(\RR)\):
sage: E.change_ring(RR).lift_x(3, all=True) [(3.00000000000000 : 4.42442890089805 : 1.00000000000000), (3.00000000000000 : 5.42442890089805 : 1.00000000000000)]
And of course it always works in \(E(\CC)\):
sage: E.change_ring(RR).lift_x(.5, all=True) [] sage: E.change_ring(CC).lift_x(.5) (0.500000000000000 : 0.500000000000000 + 0.353553390593274*I : 1.00000000000000)
In this example we start with a curve defined over \(\QQ\) which has no rational points with \(x=0\), but using
extend = True
we can construct such a point over a quadratic field:sage: E = EllipticCurve([0,0,0,0,2]); E Elliptic Curve defined by y^2 = x^3 + 2 over Rational Field sage: P = E.lift_x(0, extend=True); P (0 : y : 1) sage: P.curve() 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 : 11 : 1) sage: E.lift_x(3) Traceback (most recent call last): ... ValueError: No point with xcoordinate 3 on Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17
Note that there is only one lift with \(x\)coordinate 10 in \(E(\GF{17})\):
sage: E.lift_x(10, all=True) [(10 : 8 : 1)]
We can lift over more exotic rings too. If the supplied x value is in an extension of the base, note that the point returned is on the baseextended curve:
sage: E = EllipticCurve('37a') sage: P = E.lift_x(pAdicField(17, 5)(6)); P (6 + O(17^5) : 2 + 16*17 + 16*17^2 + 16*17^3 + 16*17^4 + O(17^5) : 1 + O(17^5)) sage: P.curve() 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 17adic Field with capped relative precision 5 sage: K.<t> = PowerSeriesRing(QQ, 't', 5) sage: P = E.lift_x(1+t); P (1 + t : 2*t  t^2 + 5*t^3  21*t^4 + O(t^5) : 1) sage: K.<a> = GF(16) sage: P = E.change_ring(K).lift_x(a^3); P (a^3 : a^3 + a : 1) sage: P.curve() Elliptic Curve defined by y^2 + y = x^3 + x over Finite Field in a of size 2^4
We can extend the base field to include the associated \(y\) value(s):
sage: E = EllipticCurve([0,0,0,0,2]); E Elliptic Curve defined by y^2 = x^3 + 2 over Rational Field sage: x = polygen(QQ) sage: P = E.lift_x(x, extend=True); P (x : y : 1)
This point is a generic point on E:
sage: P.curve() Elliptic Curve defined by y^2 = x^3 + 2 over Univariate Quotient Polynomial Ring in y over Fraction Field of Univariate Polynomial Ring in x over Rational Field with modulus y^2  x^3  2 sage: P (x : y : 1) sage: 2*P ((1/4*x^4  4*x)/(x^3 + 2) : ((1/8*x^6 + 5*x^3  4)/(x^6 + 4*x^3 + 4))*y : 1)
Check that trac ticket #30297 is fixed:
sage: K = Qp(5) sage: E = EllipticCurve([K(0), K(1)]) sage: E.lift_x(1, extend=True) (1 + O(5^20) : y + O(5^20) : 1 + O(5^20))
AUTHOR:
Robert Bradshaw (20070424)
John Cremona (20171110)

multiplication_by_m
(m, x_only=False)¶ Return the multiplicationby\(m\) map from
self
toself
The result is a pair of rational functions in two variables \(x\), \(y\) (or a rational function in one variable \(x\) if
x_only
isTrue
).INPUT:
m
 a nonzero integerx_only
 boolean (default:False
) ifTrue
, 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
isTrue
Note
The result is not cached.
m
is allowed to be negative (but not 0).
EXAMPLES:
sage: E = EllipticCurve([1,3])
We verify that multiplication by 1 is just the identity:
sage: E.multiplication_by_m(1) (x, y)
Multiplication by 2 is more complicated:
sage: f = E.multiplication_by_m(2) sage: f ((x^4 + 2*x^2  24*x + 1)/(4*x^3  4*x + 12), (8*x^6*y  40*x^4*y + 480*x^3*y  40*x^2*y + 96*x*y  568*y)/(64*x^6  128*x^4 + 384*x^3 + 64*x^2  384*x + 576))
Grab only the xcoordinate (less work):
sage: mx = E.multiplication_by_m(2, x_only=True); mx (1/4*x^4 + 1/2*x^2  6*x + 1/4)/(x^3  x + 3) sage: mx.parent() Fraction Field of Univariate Polynomial Ring in x over Rational Field
We check that it works on a point:
sage: P = E([2,3]) sage: eval = lambda f,P: [fi(P[0],P[1]) for fi in f] sage: assert E(eval(f,P)) == 2*P
We do the same but with multiplication by 3:
sage: f = E.multiplication_by_m(3) sage: assert E(eval(f,P)) == 3*P
And the same with multiplication by 4:
sage: f = E.multiplication_by_m(4) sage: assert E(eval(f,P)) == 4*P
And the same with multiplication by 1,2,3,4:
sage: for m in [1,2,3,4]: ....: f = E.multiplication_by_m(m) ....: assert E(eval(f,P)) == m*P

multiplication_by_m_isogeny
(m)¶ Return the
EllipticCurveIsogeny
object associated to the multiplicationby\(m\) map on self.The resulting isogeny will have the associated rational maps (i.e. those returned by \(self.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 trac ticket #7368 and trac ticket #8014 for the status of improving this situation.INPUT:
m
 a nonzero integer
OUTPUT:
An
EllipticCurveIsogeny
object associated to the multiplicationby\(m\) map on self.
EXAMPLES:
sage: E = EllipticCurve('11a1') sage: E.multiplication_by_m_isogeny(7) Isogeny of degree 49 from Elliptic Curve defined by y^2 + y = x^3  x^2  10*x  20 over Rational Field to Elliptic Curve defined by y^2 + y = x^3  x^2  10*x  20 over Rational Field

pari_curve
()¶ Return the PARI curve corresponding to this elliptic curve.
The result is cached.
EXAMPLES:
sage: E = EllipticCurve([RR(0), RR(0), RR(1), RR(1), RR(0)]) sage: e = E.pari_curve() sage: type(e) <... 'cypari2.gen.Gen'> sage: e.type() 't_VEC' sage: e.disc() 37.0000000000000
Over a finite field:
sage: EllipticCurve(GF(41),[2,5]).pari_curve() [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: Qp = pAdicField(5, prec=3) sage: E = EllipticCurve(Qp,[3, 4]) sage: E.pari_curve() [0, 0, 0, 3, 4, 0, 6, 16, 9, 144, 3456, 8640, 1728/5, Vecsmall([2]), [O(5^3)], [0, 0]] sage: E.j_invariant() 3*5^1 + O(5)
Over a number field:
sage: K.<a> = QuadraticField(2) sage: E = EllipticCurve([1,a]) sage: E.pari_curve() [Mod(0, y^2  2), Mod(0, y^2  2), Mod(0, y^2  2), Mod(1, y^2  2), Mod(y, y^2  2), Mod(0, y^2  2), 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], [1, 1; 1, 1], [2, 0; 0, 4], [4, 0; 0, 2], [2, 0; 0, 1], [2, [0, 2; 1, 0]], []], [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]) sage: E.j_invariant() # the jinvariant is a padic integer 2 + 4*5^2 + O(5^3) sage: E.pari_curve() [0, 0, 0, 1, 1, 0, 2, 4, 1, 48, 864, 496, 6912/31, Vecsmall([2]), [O(5^3)], [0, 0]]

plot
(xmin=None, xmax=None, components='both', **args)¶ Draw a graph of this elliptic curve.
The plot method is only implemented when there is a natural coercion from the base ring of
self
toRR
. In this case,self
is plotted as if it was defined overRR
.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 appearbounded
– 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 tosage.plot.generate_plot_points()
adaptive_tolerance
– passed tosage.plot.generate_plot_points()
adaptive_recursion
– passed tosage.plot.generate_plot_points()
randomize
– passed tosage.plot.generate_plot_points()
**args
 all other options are passed tosage.plot.line.Line
EXAMPLES:
sage: E = EllipticCurve([0,1]) sage: plot(E, rgbcolor=hue(0.7)) Graphics object consisting of 1 graphics primitive sage: E = EllipticCurve('37a') sage: plot(E) Graphics object consisting of 2 graphics primitives sage: plot(E, xmin=25,xmax=26) Graphics object consisting of 2 graphics primitives
With trac ticket #12766 we added the components keyword:
sage: E.real_components() 2 sage: E.plot(components='bounded') Graphics object consisting of 1 graphics primitive sage: E.plot(components='unbounded') 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') 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() Traceback (most recent call last): ... NotImplementedError: plotting of curves over Complex Field with 53 bits of precision is not implemented yet

rst_transform
(r, s, t)¶ Return the transform of the curve by \((r,s,t)\) (with \(u=1\)).
INPUT:
r
,s
,t
– three elements of the base ring.
OUTPUT:
The elliptic curve obtained from self by the standard Weierstrass transformation \((u,r,s,t)\) with \(u=1\).
Note
This is just a special case of
change_weierstrass_model()
, with \(u=1\).EXAMPLES:
sage: R.<r,s,t>=QQ[] sage: E = EllipticCurve([1,2,3,4,5]) sage: E.rst_transform(r,s,t) Elliptic Curve defined by y^2 + (2*s+1)*x*y + (r+2*t+3)*y = x^3 + (s^2+3*rs+2)*x^2 + (3*r^2r*s2*s*t+4*r3*st+4)*x + (r^3+2*r^2r*tt^2+4*r3*t+5) over Multivariate Polynomial Ring in r, s, t over Rational Field

scale_curve
(u)¶ Return the transform of the curve by scale factor \(u\).
INPUT:
u
– an invertible element of the base ring.
OUTPUT:
The elliptic curve obtained from self by the standard Weierstrass transformation \((u,r,s,t)\) with \(r=s=t=0\).
Note
This is just a special case of
change_weierstrass_model()
, with \(r=s=t=0\).EXAMPLES:
sage: K = Frac(PolynomialRing(QQ,'u')) sage: u = K.gen() sage: E = EllipticCurve([1,2,3,4,5]) sage: E.scale_curve(u) Elliptic Curve defined by y^2 + u*x*y + 3*u^3*y = x^3 + 2*u^2*x^2 + 4*u^4*x + 5*u^6 over Fraction Field of Univariate Polynomial Ring in u over Rational Field

short_weierstrass_model
(complete_cube=True)¶ Return a short Weierstrass model for self.
INPUT:
complete_cube
 bool (default: True); for meaning, see below.
OUTPUT:
An elliptic curve.
If
complete_cube=True
: Return a model of the form \(y^2 = x^3 + a*x + b\) for this curve. The characteristic must not be 2; in characteristic 3, it is only possible if \(b_2=0\).If
complete_cube=False
: Return a model of the form \(y^2 = x^3 + ax^2 + bx + c\) for this curve. The characteristic must not be 2.EXAMPLES:
sage: E = EllipticCurve([1,2,3,4,5]) sage: E Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field sage: F = E.short_weierstrass_model() sage: F Elliptic Curve defined by y^2 = x^3 + 4941*x + 185166 over Rational Field sage: E.is_isomorphic(F) True sage: F = E.short_weierstrass_model(complete_cube=False) sage: F Elliptic Curve defined by y^2 = x^3 + 9*x^2 + 88*x + 464 over Rational Field sage: E.is_isomorphic(F) True
sage: E = EllipticCurve(GF(3),[1,2,3,4,5]) sage: E.short_weierstrass_model(complete_cube=False) Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 3
This used to be different see trac ticket #3973:
sage: E.short_weierstrass_model() Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 3
More tests in characteristic 3:
sage: E = EllipticCurve(GF(3),[0,2,1,2,1]) sage: E.short_weierstrass_model() Traceback (most recent call last): ... ValueError: short_weierstrass_model(): no short model for Elliptic Curve defined by y^2 + y = x^3 + 2*x^2 + 2*x + 1 over Finite Field of size 3 (characteristic is 3) sage: E.short_weierstrass_model(complete_cube=False) Elliptic Curve defined by y^2 = x^3 + 2*x^2 + 2*x + 2 over Finite Field of size 3 sage: E.short_weierstrass_model(complete_cube=False).is_isomorphic(E) True

torsion_polynomial
(m, x=None, two_torsion_multiplicity=2)¶ Return the \(m^{th}\) division polynomial of this elliptic curve evaluated at
x
.INPUT:
m
 positive integer.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 ok. This permits fast calculation of the torsion polynomial evaluated on any element of a ring.two_torsion_multiplicity
 0,1 or 2If 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. Similarly 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: when x is None, a bivariate polynomial over the base ring of the curve is returned, which includes a factor \(2*y+a1*x+a3\) which has 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.
EXAMPLES:
sage: E = EllipticCurve([0,0,1,1,0]) sage: E.division_polynomial(1) 1 sage: E.division_polynomial(2, two_torsion_multiplicity=0) 1 sage: E.division_polynomial(2, two_torsion_multiplicity=1) 2*y + 1 sage: E.division_polynomial(2, two_torsion_multiplicity=2) 4*x^3  4*x + 1 sage: E.division_polynomial(2) 4*x^3  4*x + 1 sage: [E.division_polynomial(3, two_torsion_multiplicity=i) for i in range(3)] [3*x^4  6*x^2 + 3*x  1, 3*x^4  6*x^2 + 3*x  1, 3*x^4  6*x^2 + 3*x  1] sage: [type(E.division_polynomial(3, two_torsion_multiplicity=i)) for i in range(3)] [<... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>, <... 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>, <... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>]
sage: E = EllipticCurve([0, 1, 1, 10, 20]) sage: R.<z>=PolynomialRing(QQ) sage: E.division_polynomial(4,z,0) 2*z^6  4*z^5  100*z^4  790*z^3  210*z^2  1496*z  5821 sage: E.division_polynomial(4,z) 8*z^9  24*z^8  464*z^7  2758*z^6 + 6636*z^5 + 34356*z^4 + 53510*z^3 + 99714*z^2 + 351024*z + 459859
This does not work, since when two_torsion_multiplicity is 1, we compute a bivariate polynomial, and must evaluate at a tuple of length 2:
sage: E.division_polynomial(4,z,1) Traceback (most recent call last): ... ValueError: x should be a tuple of length 2 (or None) when two_torsion_multiplicity is 1 sage: R.<z,w>=PolynomialRing(QQ,2) sage: E.division_polynomial(4,(z,w),1).factor() (2*w + 1) * (2*z^6  4*z^5  100*z^4  790*z^3  210*z^2  1496*z  5821)
We can also evaluate this bivariate polynomial at a point:
sage: P = E(5,5) sage: E.division_polynomial(4,P,two_torsion_multiplicity=1) 1771561

two_division_polynomial
(x=None)¶ Return the 2division polynomial of this elliptic curve evaluated at
x
.INPUT:
x
 optional ring element to use as the \(x\) variable. Ifx
isNone
, then a new polynomial ring will be constructed over the base ring of the elliptic curve, and its generator will be used asx
. Note thatx
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.
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]) sage: E.two_division_polynomial() x^3 + 2*x^2 + 2 sage: E.two_division_polynomial().roots() [(2, 1), (2*a, 1), (a + 2, 1)]


sage.schemes.elliptic_curves.ell_generic.
is_EllipticCurve
(x)¶ Utility function to test if
x
is an instance of an Elliptic Curve class.EXAMPLES:
sage: from sage.schemes.elliptic_curves.ell_generic import is_EllipticCurve sage: E = EllipticCurve([1,2,3/4,7,19]) sage: is_EllipticCurve(E) True sage: is_EllipticCurve(0) False