37.5 Elliptic curves over a general ring

Module: sage.schemes.elliptic_curves.ell_generic

Elliptic curves over a general ring

Elliptic curves are always represented by `Weierstass Models' with five coefficients $ [a_1,a_2,a_3,a_4,a_6]$ in standard notation. In Magma, `Weierstrass Model' means a model with a1=a2=a3=0, which is called `Short Weierstrass Model' in Sage; these only exist in characteristics other than 2 and 3.

We construct an elliptic curve over an elaborate base ring:

sage: p = 97; a=1; b=3
sage: R, u = PolynomialRing(GF(p), 'u').objgen()
sage: S, v = PolynomialRing(R, 'v').objgen()
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

Author Log:

Module-level Functions

Hasse_bounds( q, [genus=1])

Return the Hasse bounds (lb,ub) for the cardinality of a curve of genus g (default 1) defined over GF(q)

sage: Hasse_bounds(2)
(1, 5)
sage: Hasse_bounds(next_prime(10^30))
(999999999999998000000000000058, 1000000000000002000000000000058)

is_EllipticCurve( x)

sage: E = EllipticCurve([1,2,3/4,7,19])
sage: is_EllipticCurve(E)
True
sage: is_EllipticCurve(0)
False

Class: EllipticCurve_generic

class EllipticCurve_generic
Elliptic curve over a generic base ring.

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)
EllipticCurve_generic( self, ainvs, [extra=None])

Constructor from [a1,a2,a3,a4,a6] or [a4,a6] (see constructor.py for more variants)

sage: E = EllipticCurve([1,2,3,4,5]); E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field
sage: E = EllipticCurve(GF(7),[1,2,3,4,5]); E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Finite Field of size 7

Constructor from [a4,a6] sets a1=a2=a3=0:

sage: EllipticCurve([4,5]).ainvs()
[0, 0, 0, 4, 5]

Base need not be a field:

sage: EllipticCurve(IntegerModRing(91),[1,2,3,4,5])
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Ring
of integers modulo 91

Functions: a1,$ \,$ a2,$ \,$ a3,$ \,$ a4,$ \,$ a6,$ \,$ a_invariants,$ \,$ ainvs,$ \,$ automorphisms,$ \,$ b2,$ \,$ b4,$ \,$ b6,$ \,$ b8,$ \,$ b_invariants,$ \,$ base_extend,$ \,$ base_field,$ \,$ base_ring,$ \,$ c4,$ \,$ c6,$ \,$ c_invariants,$ \,$ change_ring,$ \,$ change_weierstrass_model,$ \,$ discriminant,$ \,$ division_polynomial,$ \,$ formal,$ \,$ formal_group,$ \,$ full_division_polynomial,$ \,$ gen,$ \,$ gens,$ \,$ hyperelliptic_polynomials,$ \,$ is_isomorphic,$ \,$ is_on_curve,$ \,$ isomorphism_to,$ \,$ isomorphisms,$ \,$ j_invariant,$ \,$ lift_x,$ \,$ multiplication_by_m,$ \,$ plot,$ \,$ quadratic_twist,$ \,$ quartic_twist,$ \,$ rst_transform,$ \,$ scale_curve,$ \,$ sextic_twist,$ \,$ short_weierstrass_model,$ \,$ torsion_polynomial

a1( self)

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

a2( self)

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

a3( self)

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

a4( self)

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

a6( self)

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

a_invariants( self)

The a-invariants of this elliptic curve.

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.a_invariants()
[1, 2, 3, 4, 5]
sage: E = EllipticCurve([0,1])
sage: 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( self)

The a-invariants of this elliptic curve.

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.a_invariants()
[1, 2, 3, 4, 5]
sage: E = EllipticCurve([0,1])
sage: 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( self, [field=None])

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

sage: E = EllipticCurve(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  = x^3 +1 over Rational Field
Via:  (u,r,s,t) = (-1, 0, 0, 0), Generic endomorphism of Abelian group of
points on Elliptic Curve defined by y^2  = x^3 +1 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  = x^3 +1 over Number Field in a with defining polynomial x^2 + 3
Via:  (u,r,s,t) = (1, 0, 0, 0),
...
Generic endomorphism of Abelian group of points on Elliptic Curve defined
by y^2  = x^3 +1 over Number Field in a with defining polynomial x^2 + 3
Via:  (u,r,s,t) = (-1/2*a - 1/2, 0, 0, 0)]

sage: [ len(EllipticCurve(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( self)

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

b4( self)

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

b6( self)

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

b8( self)

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

b_invariants( self)

The b-invariants of this elliptic curve.

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.

Author: William Stein, 2005-04-25

base_extend( self, R)

Returns a new curve with the same a-invariants but defined over a new ring into which the original's a-invariants may be mapped. R is either a ring into which they may be coerced, or a morphism which may be applied to them.

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
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.base_extend(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

base_field( self)

Returns the base ring of the elliptic curves.

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

base_ring( self)

Returns the base ring of the elliptic curves.

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

c4( self)

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

c6( self)

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

c_invariants( self)

The c-invariants of this elliptic curve.

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 b invariants.

Author: William Stein, 2005-04-25

change_ring( self, R)

Return the elliptic curve defined by coercing the a-invariants of this elliptic curve into the ring R.

Input:

R
- ring

Output: an elliptic curve

sage: E = EllipticCurve([0, 0, 1, -1, 0])
sage: E.change_ring(GF(3))
Elliptic Curve defined by y^2 + y = x^3 + 2*x over Finite Field of size 3

change_weierstrass_model( self)

Return a new Weierstrass model of self under the transformation (on points)

$\displaystyle (x,y) \mapsto (x',y') = (u^2*x+r , u^3*y + s*u^2*x' + t) $

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( self)

Returns the discriminant of this elliptic curve.

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( self, n, [var=x], [i=0])

Returns the n-th torsion polynomial (a.k.a., division polynomial).

Input:

n
- non-negative integer
var
- string; the indeterminate of the polynomial (default: x)
i
- integer, either 0 (default) or 1.

Output:
Polynomial
- n-th torsion polynomial, which is a polynomial over the base field of the elliptic curve.

SEE ALSO: full_division_polynomial

ALIASES: division_polynomial, torsion_polynomial

sage: E = EllipticCurve([0,0,1,-1,0])
sage: E.division_polynomial(1)
1
sage: E.division_polynomial(2)
4*x^3 - 4*x + 1
sage: E.division_polynomial(3, 'z')
3*z^4 - 6*z^2 + 3*z - 1

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.torsion_polynomial(0)
0
sage: E.torsion_polynomial(1)
1
sage: E.torsion_polynomial(2)
4*x^3 - 4*x^2 - 40*x - 79
sage: E.torsion_polynomial(3)
3*x^4 - 4*x^3 - 60*x^2 - 237*x - 21
sage: E.torsion_polynomial(4)
8*x^9 - 24*x^8 - 464*x^7 - 2758*x^6 + 6636*x^5 + 34356*x^4 + 53510*x^3 +
99714*x^2 + 351024*x + 459859

sage: E = EllipticCurve([-4,0])
sage: E.torsion_polynomial(2)
4*x^3 - 16*x
sage: E.torsion_polynomial(5)
5*x^12 - 248*x^10 - 1680*x^8 + 19200*x^6 - 32000*x^4 + 51200*x^2 + 4096
sage: E.torsion_polynomial(6)
12*x^19 - 1200*x^17 - 18688*x^15 + 422912*x^13 - 2283520*x^11 + 9134080*x^9
- 27066368*x^7 + 19136512*x^5 + 19660800*x^3 - 3145728*x

Author: David Kohel (kohel@maths.usyd.edu.au), 2005-04-25

formal( self)

The formal group associated to this elliptic curve.

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( self)

The formal group associated to this elliptic curve.

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

full_division_polynomial( self, m, [use_divpoly=True])

Return the $ m$ -th bivariate division polynomial in $ x$ and $ y$ . When $ m$ is odd this is exactly the same as the usual $ m$ th division polynomial.

For the usual division polynomial only in $ x$ , see the division_polynomial function.

Input:

self
- elliptic curve in short Weierstrass form
m
- a positive integer
use_divpoly
- whether to call the division_polynomial function directly in case $ m$ is odd.
Output: a polynomial in two variables $ x$ , $ y$ .

NOTE: The result is cached.

REFERENCE: Exercise III.3.7 of Silverman AEC 1, 1986, page 105.

We create a curve and compute the first two full division polynomials.

sage: E = EllipticCurve([2,3])
sage: E.full_division_polynomial(1)
1
sage: E.full_division_polynomial(2)
2*y

Note that for odd input the full division polynomial is just the usual division polynomial, but not for even input:

sage: E.division_polynomial(2)
4*x^3 + 8*x + 12
sage: E.full_division_polynomial(3)
3*x^4 + 12*x^2 + 36*x - 4
sage: E.division_polynomial(3)
3*x^4 + 12*x^2 + 36*x - 4
sage: E.full_division_polynomial(4)
4*y*x^6 + 40*y*x^4 + 240*y*x^3 - 80*y*x^2 - 96*y*x - 320*y
sage: E.full_division_polynomial(5)
5*x^12 + 124*x^10 + 1140*x^9 - 420*x^8 + 1440*x^7 - 4560*x^6 - 8352*x^5 -
36560*x^4 - 45120*x^3 - 10240*x^2 - 39360*x - 22976

TESTS: We test that the full division polynomial as computed using the recurrence agrees with the norml division polynomial for a certain curve and all odd $ n$ up to $ 23$ :

sage: E = EllipticCurve([23,-105])
sage: for n in [1,3,..,23]:
...       assert E.full_division_polynomial(n, use_divpoly=False) ==
E.division_polynomial(n)

gen( self, i)

Function returning the i'th generator of this elliptic curve. Relies on gens() being implemented.

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( self)

Placeholder function to return generators of an elliptic curve: derived classes such as EllipticCurve_rational_field implement this functionality

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( self)
Returns a pair of polynomials g(x), h(x) such that this elliptic curve can be defined by the standard hyperelliptic equation

$\displaystyle y^2 + h(x)y = g(x)$

.

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( self, other, [field=None])

Returns whether or not self is isomorphic to other, i.e. they define the same curve over the same basering.

If field!=None then both curves must base_extend-able to it and the isomorphism is then checked over that field

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( self, x, y)

Returns True if the (x,y) is an affine point on this curve.

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

isomorphism_to( self, other)

Given another weierstrass model other of self, return a morphism from self to other.

If the curves in question are not isomorphic, raise a ValueError

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^3-7)
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( self, other, [field=None])

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

sage: E = EllipticCurve(QQ(0)) # a curve with j=0 over QQ
sage: F = EllipticCurve('36a1') # should be the same one
sage: E.isomorphisms(F);       
[Generic morphism:
From: Abelian group of points on Elliptic Curve defined by y^2  = x^3 +1
over Rational Field
To:   Abelian group of points on Elliptic Curve defined by y^2  = x^3 +1
over Rational Field
Via:  (u,r,s,t) = (-1, 0, 0, 0), Generic morphism:
From: Abelian group of points on Elliptic Curve defined by y^2  = x^3 +1
over Rational Field
To:   Abelian group of points on Elliptic Curve defined by y^2  = x^3 +1
over Rational Field
Via:  (u,r,s,t) = (1, 0, 0, 0)]

We can also find istomorphisms 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( self)

Returns the j-invariant of this elliptic curve.

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( self, x, [all=False])

Given the x-coordinate of a point on the curve, use the defining polynomial to find all affine points on this curve with the given x-coordinate.

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-cordinate 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

However, there are two such points in $ E(\mathbf{R})$ :

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(\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)

We can perform these operations over finite fields too:

sage: E = E.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 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(\mathbf{F}_{17})$ .

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

We can lift over more exotic rings too.

sage: E = EllipticCurve('37a');
sage: E.lift_x(pAdicField(17, 5)(6))
(6 + O(17^5) : 2 + 16*17 + 16*17^2 + 16*17^3 + 16*17^4 + O(17^5) : 1 +
O(17^5))
sage: K.<t> = PowerSeriesRing(QQ, 't', 5)
sage: E.lift_x(1+t)
(1 + t : 2*t - t^2 + 5*t^3 - 21*t^4 + O(t^5) : 1)
sage: K.<a> = GF(16)
sage: E = E.change_ring(K)
sage: E.lift_x(a^3)
(a^3 : a^3 + a : 1)

Author: Robert Bradshaw, 2007-04-24

TEST:

sage: E = EllipticCurve('37a').short_weierstrass_model().change_ring(GF(17))
sage: E.lift_x(3, all=True)
[]
sage: E.lift_x(7, all=True)
[(7 : 3 : 1), (7 : 14 : 1)]

multiplication_by_m( self, m, [x_only=False])

Return the multiplication-by-m map from self to self as a rational function.

Input:

self
- an elliptic curve in short Weierstrass form
m
- a positive integer
x_only
- bool (default: False) if True, return only the x coordinate of the map.

Output:
2-tuple
- (f(x), g(x,y)) where f and g are rational functions with the degree of y in g(x,y) at most 1.

NOTE: The result is not cached.

We create an elliptic curve.

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), (2*x^6 - 10*x^4 + 120*x^3 -
10*x^2 + 24*x - 142)/(16*y*x^3 - 16*y*x + 48*y))

Grab only the x-coordinate (less work):

sage: E.multiplication_by_m(2, x_only=True)
(x^4 + 2*x^2 - 24*x + 1)/(4*x^3 - 4*x + 12)

We check that it works on a point:

sage: P = E([2,3])
sage: f[0].subs(x=2,y=3)
-23/36
sage: f[1].subs(x=2,y=3)
397/216
sage: 2*P
(-23/36 : 397/216 : 1)

We do the same but with multiplication by 3:

sage: f = E.multiplication_by_m(3)
sage: f[0].subs(x=2,y=3)
-10534/9025
sage: f[1].subs(x=2,y=3)
-1376361/857375
sage: 3*P
(-10534/9025 : -1376361/857375 : 1)

And the same with multiplication by 4:

sage: f = E.multiplication_by_m(4)
sage: f[0].subs(x=2,y=3)
29084737/22695696
sage: f[1].subs(x=2,y=3)
-211407941663/108122295744
sage: 4*P
(29084737/22695696 : -211407941663/108122295744 : 1)

TESTS: Verify for this fairly random looking curve and point that multiplication by m returns the right result for the first 10 integers.

sage: E = EllipticCurve([23,-105])
sage: P = E([129/4, 1479/8])
sage: for n in [1..10]:
...       f = E.multiplication_by_m(n)
...       Q = n*P
...       assert f[0].subs(x=P[0],y=P[1]) == Q[0] and
f[1].subs(x=P[0],y=P[1]) == Q[1]

plot( self, [xmin=None], [xmax=None])

Draw a graph of this elliptic curve.

Input:

xmin, xmax
- points will be computed at least within this rings, but possibly farther. These may be left off.
**args
- all other options are passed to the line graphing primitive.

sage: E = EllipticCurve([0,-1])
sage: plot(E, rgbcolor=hue(0.7))

quadratic_twist( self, D)

Return the quadratic twist of this curve by D, which must be nonzero except in characteristic 2.

In characteristic!=2, D must be nonzero, and the twist is isomorphic to self after adjoining sqrt(D) to the base

In characteristic==2, D is arbitrary, and the twist is isomorphic to self after adjoining a root of $ x^2+x+D$ to the base

In characteristics 2 when j==0 this is not implemented (the twists are more complicated than quadratic!)

sage: E = EllipticCurve([GF(1103)(1), 0, 0, 107, 340]); E
Elliptic Curve defined by y^2 + x*y  = x^3 + 107*x + 340 over Finite Field
of size 1103
sage: F=E.quadratic_twist(-1); F
Elliptic Curve defined by y^2  = x^3 + 1102*x^2 + 609*x + 300 over Finite
Field of size 1103
sage: E.is_isomorphic(F)
False
sage: E.is_isomorphic(F,GF(1103^2,'a'))
True

A characteristic 2 example:

sage: E=EllipticCurve(GF(2),[1,0,1,1,1])
sage: E1=E.quadratic_twist(1)
sage: E.is_isomorphic(E1)
False
sage: E.is_isomorphic(E1,GF(4,'a'))
True

quartic_twist( self, D)

Return the quartic twist of this curve by D, which must be nonzero.

The characteristic must not be 2 or 3 and the j-invariant must be 1728

sage: E=EllipticCurve(GF(13)(1728)); E
Elliptic Curve defined by y^2  = x^3 + x over Finite Field of size 13
sage: E1=E.quartic_twist(2); E1
Elliptic Curve defined by y^2  = x^3 + 5*x over Finite Field of size 13
sage: E.is_isomorphic(E1)
False
sage: E.is_isomorphic(E1,GF(13^2,'a'))
False
sage: E.is_isomorphic(E1,GF(13^4,'a'))
True

rst_transform( self, r, s, t)

Transforms the elliptic curve using the unimodular (u=1) transform with standard parameters [r,s,t]. This is just a special case of change_weierstrass_model().

Returns the transformed curve.

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

scale_curve( self, u)

Transforms the elliptic curve using scale factor $ u$ , i.e. multiplies $ c_i$ by $ u^i$ . This is another special case of change_weierstrass_model().

Returns the transformed curve.

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

sextic_twist( self, D)

Return the sextic twist of this curve by D, which must be nonzero.

The characteristic must not be 2 or 3 and the j-invariant must be 0

sage: E=EllipticCurve(GF(13)(0)); E
Elliptic Curve defined by y^2  = x^3 +1 over Finite Field of size 13
sage: E1=E.sextic_twist(2); E1
Elliptic Curve defined by y^2  = x^3 + 11 over Finite Field of size 13
sage: E.is_isomorphic(E1)
False
sage: E.is_isomorphic(E1,GF(13^2,'a'))
False
sage: E.is_isomorphic(E1,GF(13^4,'a'))
False
sage: E.is_isomorphic(E1,GF(13^6,'a'))
True

short_weierstrass_model( self, [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 or 3. a,b = -27*c4, -54*c6

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. a,b,c = b2, 8*b4, 16*b6

sage: E = EllipticCurve([1,2,3,4,5])
sage: print 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: print 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: print F
Elliptic Curve defined by y^2  = x^3 + 9*x^2 + 88*x + 464 over Rational
Field
sage: print 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
sage: E.short_weierstrass_model()
Traceback (most recent call last):
...
ValueError: short_weierstrass_model(): no short model for Elliptic Curve
defined by y^2 + x*y  = x^3 + 2*x^2 + x + 2 over Finite Field of size 3
(characteristic is 3)

torsion_polynomial( self, n, [var=x], [i=0])

Returns the n-th torsion polynomial (a.k.a., division polynomial).

Input:

n
- non-negative integer
var
- string; the indeterminate of the polynomial (default: x)
i
- integer, either 0 (default) or 1.

Output:
Polynomial
- n-th torsion polynomial, which is a polynomial over the base field of the elliptic curve.

SEE ALSO: full_division_polynomial

ALIASES: division_polynomial, torsion_polynomial

sage: E = EllipticCurve([0,0,1,-1,0])
sage: E.division_polynomial(1)
1
sage: E.division_polynomial(2)
4*x^3 - 4*x + 1
sage: E.division_polynomial(3, 'z')
3*z^4 - 6*z^2 + 3*z - 1

sage: E = EllipticCurve([0, -1, 1, -10, -20])
sage: E.torsion_polynomial(0)
0
sage: E.torsion_polynomial(1)
1
sage: E.torsion_polynomial(2)
4*x^3 - 4*x^2 - 40*x - 79
sage: E.torsion_polynomial(3)
3*x^4 - 4*x^3 - 60*x^2 - 237*x - 21
sage: E.torsion_polynomial(4)
8*x^9 - 24*x^8 - 464*x^7 - 2758*x^6 + 6636*x^5 + 34356*x^4 + 53510*x^3 +
99714*x^2 + 351024*x + 459859

sage: E = EllipticCurve([-4,0])
sage: E.torsion_polynomial(2)
4*x^3 - 16*x
sage: E.torsion_polynomial(5)
5*x^12 - 248*x^10 - 1680*x^8 + 19200*x^6 - 32000*x^4 + 51200*x^2 + 4096
sage: E.torsion_polynomial(6)
12*x^19 - 1200*x^17 - 18688*x^15 + 422912*x^13 - 2283520*x^11 + 9134080*x^9
- 27066368*x^7 + 19136512*x^5 + 19660800*x^3 - 3145728*x

Author: David Kohel (kohel@maths.usyd.edu.au), 2005-04-25

Special Functions: __call__,$ \,$ __cmp__,$ \,$ __contains__,$ \,$ __getitem__,$ \,$ __init__,$ \,$ _defining_params_,$ \,$ _EllipticCurve_generic__is_over_RationalField,$ \,$ _homset_class,$ \,$ _latex_,$ \,$ _magma_init_,$ \,$ _pari_init_,$ \,$ _repr_,$ \,$ _symbolic_

__call__( self)

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

The point at infinity, which is the 0 element of the group:

sage: E(0)
(0 : 1 : 0)

The origin is a point on our curve:

sage: P = E([0,0])
sage: P
(0 : 0 : 1)

The curve associated to a point:

sage: P.curve()
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field

Points can be specified by given a 2-tuple or 3-tuple

sage: E([0,0])
(0 : 0 : 1)
sage: E([0,1,0])
(0 : 1 : 0)

Over a field, points are normalized so the right-most nonzero entry is 1:

sage: E(105, -69, 125)
(21/25 : -69/125 : 1)

We create points on an elliptic curve over a prime finite field.

sage: E = EllipticCurve([GF(7)(0), 1])
sage: E([2,3])
(2 : 3 : 1)
sage: E([0,0])
Traceback (most recent call last):
...
TypeError: coordinates [0, 0, 1] do not define a point on Elliptic Curve
defined by y^2  = x^3 +1 over Finite Field of size 7

We create a point on an elliptic curve over a number field.

sage: x = polygen(RationalField())
sage: K = NumberField(x**3 + x + 1, 'a'); a = K.gen()
sage: E = EllipticCurve([a,a])
sage: E
Elliptic Curve defined by y^2  = x^3 + a*x + a over Number Field in a with
defining polynomial x^3 + x + 1
sage: E = EllipticCurve([K(1),1])
sage: E
Elliptic Curve defined by y^2  = x^3 + x +1 over Number Field in a with
defining polynomial x^3 + x + 1
sage: P = E([a,0,1])
sage: P
(a : 0 : 1)
sage: P+P
(0 : 1 : 0)

Another example involving p-adics:

sage: E = EllipticCurve('37a1')
sage: P = E([0,0]); P
(0 : 0 : 1)
sage: R = pAdicField(3,20)
sage: Ep = E.base_extend(R); Ep
Elliptic Curve defined by y^2 + (1+O(3^20))*y = x^3 +
(2+2*3+2*3^2+2*3^3+2*3^4+2*3^5+2*3^6+2*3^7+2*3^8+2*3^9+2*3^10+2*3^11+2*3^12
+2*3^13+2*3^14+2*3^15+2*3^16+2*3^17+2*3^18+2*3^19+O(3^20))*x over 3-adic
Field with capped relative precision 20
sage: Ep(P)
(0 : 0 : 1 + O(3^20))

__cmp__( self, other)

Standard comparison function for elliptic curves, to allow sorting and equality testing.

sage: E=EllipticCurve(QQ,[1,1])
sage: F=EllipticCurve(QQ,[0,0,0,1,1])
sage: E==F
True

__contains__( self, P)

Returns True if and only if P defines is a point on the elliptic curve. P just has to be something that can be coerced to a point.

sage: E = EllipticCurve([0, 0, 1, -1, 0])
sage: (0,0) in E
True
sage: (1,3) in E
False
sage: E = EllipticCurve([GF(7)(0), 1])
sage: [0,0] in E
False
sage: [0,8] in E
True
sage: P = E(0,8)
sage: P
(0 : 1 : 1)
sage: P in E
True

__getitem__( self, n)

Placeholder for standard indexing function.

sage: E=EllipticCurve(QQ,[1,1])
sage: E[2]
Traceback (most recent call last):
...
NotImplementedError: not implemented.

_defining_params_( self)

Internal function. Returns a tuple of the base ring of this elliptic curve and its a-invariants, from which it can be reconstructed.

sage: E=EllipticCurve(QQ,[1,1])
sage: E._defining_params_()
(Rational Field, [0, 0, 0, 1, 1])
sage: EllipticCurve(*E._defining_params_()) == E
True

_EllipticCurve_generic__is_over_RationalField( self)

Internal function. Returns true iff the base ring of this elliptic curve is the field of rational numbers.

sage: E=EllipticCurve(QQ,[1,1])
sage: E._EllipticCurve_generic__is_over_RationalField()
True
sage: E=EllipticCurve(GF(5),[1,1])
sage: E._EllipticCurve_generic__is_over_RationalField()
False

_homset_class( self)

Internal function. Returns the (abstract) group of points on this elliptic curve over a ring.

sage: E=EllipticCurve(GF(5),[1,1])
sage: E._homset_class(GF(5^10,'a'),GF(5))
Abelian group of points on Finite Field in a of size 5^10

_latex_( self)

Internal function. Returns a latex string for this elliptic curve. Users will normally use latex() instead.

sage: E=EllipticCurve(QQ,[1,1])
sage: E._latex_()
'y^2  = x^3 + x +1 '
sage: latex(E)
y^2  = x^3 + x +1

_magma_init_( self)

Internal function. Returns a string to initialize this elliptic curve in the Magma subsystem.

sage: E=EllipticCurve(QQ,[1,1])
sage: E._magma_init_()
'EllipticCurve([0/1,0/1,0/1,1/1,1/1])'

_pari_init_( self)

Internal function. Returns a string to initialize this elliptic curve in the pari system.

sage: E=EllipticCurve(QQ,[1,1])
sage: E._pari_init_()
'ellinit([0/1,0/1,0/1,1/1,1/1])'

_repr_( self)

String representation of elliptic curve.

sage: EllipticCurve([1,2,3,4,5])
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field

sage: R.<x> = QQ['x']
sage: K.<a> = NumberField(x^3-17)
sage: EllipticCurve([a^2-3, -2/3*a + 3])
Elliptic Curve defined by y^2  = x^3 + (a^2-3)*x + (-2/3*a+3) over Number
Field in a
with defining polynomial x^3 - 17

_symbolic_( self, SR)

Many elliptic curves can be converted into a symbolic expression using the symbolic_expression command.

We find a torsion point on 11a.

sage: E = EllipticCurve('11a')
sage: E.torsion_subgroup().gens()
((5 : 5 : 1),)

We find the corresponding symbolic equality:

sage: eqn = symbolic_expression(E); eqn
y^2 + y == x^3 - x^2 - 10*x - 20
sage: print eqn
                          2        3    2
                         y  + y == x  - x  - 10 x - 20

We verify that the given point is on the curve:

sage: eqn(x=5,y=5)
30 == 30
sage: bool(eqn(x=5,y=5))
True

We create a single expression:

sage: F = eqn.lhs() - eqn.rhs(); print F
                          2        3    2
                         y  + y - x  + x  + 10 x + 20
sage: y = var('y')
sage: print F.solve(y)
[
                      3      2
            - sqrt(4 x  - 4 x  - 40 x - 79) - 1
        y == -----------------------------------
                             2,
                     3      2
             sqrt(4 x  - 4 x  - 40 x - 79) - 1
         y == ---------------------------------
                             2
]

You can also solve for x in terms of y, but the result is horrendous. Continuing with the above example, we can explicitly find points over random fields by substituting in values for x:

sage: v = F.solve(y)[0].rhs()   
sage: print v
                                3      2
                      - sqrt(4 x  - 4 x  - 40 x - 79) - 1
                      -----------------------------------
                                       2
sage: v(3)
(-sqrt(127)*I - 1)/2
sage: v(7)
(-sqrt(817) - 1)/2
sage: v(-7)
(-sqrt(1367)*I - 1)/2
sage: v(sqrt(2))
(-sqrt(-32*sqrt(2) - 87) - 1)/2

We can even do arithmetic with them, as follows:

sage: E2 = E.change_ring(SR); E2
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Symbolic
Ring
sage: P = E2.point((3, v(3), 1), check=False)
sage: P
(3 : (-sqrt(127)*I - 1)/2 : 1)
sage: P + P
(-756/127 : (sqrt(127)*I + 1)/2 + 12507*I/(127*sqrt(127)) - 1 : 1)

We can even throw in a transcendental:

sage: w = E2.point((pi,v(pi),1), check=False); w
(pi : (-sqrt(4*pi^3 - 4*pi^2 - 40*pi - 79) - 1)/2 : 1)
sage: 2*w
((3*pi^2 - 2*pi - 10)^2/(4*pi^3 - 4*pi^2 - 40*pi - 79) - 2*pi + 1 :
(sqrt(4*pi^3 - 4*pi^2 - 40*pi - 79) + 1)/2 - (3*pi^2 - 2*pi - 10)*(-(3*pi^2
- 2*pi - 10)^2/(4*pi^3 - 4*pi^2 - 40*pi - 79) + 3*pi - 1)/sqrt(4*pi^3 -
4*pi^2 - 40*pi - 79) - 1 : 1)

See About this document... for information on suggesting changes.