Curves over the Rationals#

Local Invariants#

Conductor(E): CrvEll -> RngIntElt#

The conductor of the elliptic curve \(E\) defined over \({\mathbb{Q}}\).

BadPrimes(E): CrvEll -> [ RngIntElt ]#

Given an elliptic curve \(E\) defined over \({\mathbb{Q}}\), return the sequence of primes dividing the minimal discriminant of \(E\). These are the primes at which the minimal model for \(E\) has bad reduction; note that there may be other primes dividing the discriminant of the given model of \(E\).

TamagawaNumber(E, p): CrvEll, RngIntElt -> RngIntElt#

Given an elliptic curve \(E\) defined over \({\mathbb{Q}}\) and a prime number \(p\), this function returns the local Tamagawa number of \(E\) at \(p\), which is the index in \(E({\mathbb{Q}}_p)\) of the subgroup \(E^0({\mathbb{Q}}_p)\) of points with nonsingular reduction modulo \(p\). For any prime \(p\) that is of good reduction for \(E\), this function returns \(1\).

TamagawaNumbers(E): CrvEll -> [ RngIntElt ]#

Given an elliptic curve \(E\) defined over \({\mathbb{Q}}\), this function returns the sequence of Tamagawa numbers at each of the bad primes of \(E\), as defined above.

LocalInformation(E, p): CrvEll, RngIntElt -> <RngIntElt, RngIntElt, RngIntElt, RngIntElt, SymKod, BoolElt>, CrvEll#

Given an elliptic curve \(E\) defined over \({\mathbb{Q}}\) and a prime number \(p\), this function returns the local information at the prime \(p\) as a tuple of the form \(<P, vpd, fp, c_p, K, split>\), consisting of \(p\), its multiplicity in the discriminant, its multiplicity in the conductor, the Tamagawa number at \(p\), the Kodaira symbol, and finally a boolean which is false iff the curve has nonsplit multiplicative reduction. The second object returned is a local minimal model for \(E\) at \(p\).

LocalInformation(E): CrvEll -> [ Tup ]#

Given an elliptic curve \(E\) this function returns a sequence of tuples of the kind described above, for the primes dividing the discriminant of \(E\).

ReductionType(E, p): CrvEll, RngIntElt -> MonStgElt#

Returns a string describing the reduction type of \(E\) at \(p\); the possibilities are “Good”, “Additive”, “Split multiplicative” or “Nonsplit multiplicative”. These correspond to the type of singularity (if any) on the reduced curve. This function is necessary as the Kodaira symbols (see below) do not distinguish between split and unsplit multiplicative reduction.

TraceOfFrobeniusDirect(E, p): CrvEll, RngIntElt -> RngIntElt#

This function provides an efficient way to obtain the trace of Frobenius of a rational elliptic curve \(E\) at a prime \(p\). The argument \(p\) is not checked to be prime.

TracesOfFrobenius(E, B): CrvEll, RngIntElt -> SeqEnum#

This function provides an efficient way to obtain the traces of Frobenius \(a_p(E)\) of the reduction mod \(p\) of \(E\), for all primes \(p\) up to \(B\).

Example: Frobenius Traces (ex-eca3aa)#
> E := EllipticCurve([ 0, 1, 1, 3, 5 ]);
> T := TracesOfFrobenius(E, 100); T;
[ 0, 1, -3, -2, -5, 1, -3, -1, 5, 6, 8, -1, -6, 7, -2, 1, 14, -1, -12,
16, -16, -7, 6, 12, 2 ]
> time T := TracesOfFrobenius(E, 10^6);
Time: 5.600

Run in calculator

Kodaira Symbols#

Kodaira symbols have their own type SymKod. Apart from the two functions that determine symbols for elliptic curves, there is a special creation function and a comparison operator to test Kodaira symbols.

KodairaSymbol(E, p): CrvEll, RngIntElt -> SymKod#

Given an elliptic curve \(E\) defined over \({\mathbb{Q}}\) and a prime number \(p\), this function returns the reduction type of \(E\) modulo \(p\) in the form of a Kodaira symbol.

KodairaSymbols(E): CrvEll -> [ SymKod ]#

Given an elliptic curve \(E\) defined over \({\mathbb{Q}}\), this function returns the reduction types of \(E\) modulo the bad primes in the form of a sequence of Kodaira symbols.

KodairaSymbol(s): MonStgElt -> SymKod#

Given a string \(s\), return the Kodaira symbol it represents. The values of \(s\) that are allowed are: "I0", "I1", "I2", …, "In", "II", "III", "IV", and "I0*", "I1*", "I2*", …, "In*", "II*", "III*", "IV*". The dots stand for "Ik" with \(k\) a positive integer. The ‘generic’ type "In" allows the matching of types "In" for any integer \(n>0\) (and similarly for "In*").

h eq k: SymKod, SymKod -> BoolElt#

Given two Kodaira symbols \(h\) and \(k\), this function returns true if and only if either both are identical, or one is generic (of the form "In", or "In*") and the other is specific of the same type: "In" will compare equal with any of "I1", "I2", "I3", etc., and "In*" will compare equal with any of "I1*", "I2*", "I3*", etc. Note however that "In" and "I3" are different from the point of view of set creation.

h ne k: SymKod, SymKod -> BoolElt#

The logical negation of eq.

Example: Kodaira (ex-c22679)#

We search for curves with a particular reduction type ‘I0*’ in a family of curves.

> S := [ ];
> for n := 2 to 100 do
>    E := EllipticCurve([n, 0]);
>    for p in BadPrimes(E) do
>       if KodairaSymbol(E, p) eq KodairaSymbol("I0*") then
>          Append(~S, <p, n>);
>       end if;
>    end for;
> end for;
> S;
[ <3, 9>, <3, 18>, <5, 25>, <3, 36>, <3, 45>, <7, 49>, <5, 50>,
<3, 63>, <3, 72>, <5, 75>, <3, 90>, <7, 98>, <3, 99>, <5, 100> ]

Run in calculator

Complex Multiplication#

HasComplexMultiplication(E): CrvEll -> BoolElt, RngIntElt#

Given an elliptic curve \(E\) over the rationals (or a number field), the function determines whether the curve has complex multiplication or not and, if so, also returns the discriminant of the CM quadratic order. The algorithm uses fairly straightforward analytic methods, which are not suited to very high degree j-invariants with CM by orders with discriminants more than a few thousand.

Isogenous Curves#

IsogenousCurves(E): CrvEll[FldRat] -> SeqEnum, RngIntElt#

The set of curves \({\mathbb{Q}}\)-isogenous to a rational elliptic curve \(E\). The method used is to proceed prime-by-prime. Mazur’s Theorem restricts the possibilities to a short list, and \(j\)-invariant considerations leave only \(p\)-isogenies for \(p = 2, 3, 5, 7, 13\) to be considered. For \(p = 2\) or \(3\), the method proceeds by finding the rational roots of the \(p\)-th division polynomial for the curve \(E\). From these roots, one can then recover the isogenous curves. The question as to whether or not there is a \(p\)-isogeny is entirely a function of the \(j\)-invariant of the curve, and this idea is used for \(p = 5, 7, 13\). In these cases the algorithm first takes a minimal twist of the elliptic curve, and then finds rational roots of the polynomial of degree \((p+1)\) that comes from a fibre of \(X_0(p)\). The isogenous curves of the minimal twist corresponding to these roots are then computed, and then these curves are twisted back to get the isogenous curves of \(E\). In all cases, if the conductor is squarefree, some small values of the Frobenius traces are checked mod \(p\) to ensure the feasibility of a \(p\)-isogeny. Other similar ideas involving checking congruences are also used to try to eliminate the possibility of a \(p\)-isogeny without finding roots. Tree-based methods are used to extend the isogeny tree from (say) \(2\)-isogenies to \(4\)-isogenies to \(8\)-isogenies, etc. The integer returned as a second argument corresponds to the largest degree of a cyclic isogeny between two curves in the isogeny class. The ordering of the list of curves returned is well-defined; the first curve is always the curve of minimal Faltings height, and the heights generically increase upon going down the list. However, when there are isogenies of two different prime degrees, a different ordering is used. In the case where there is a \(4\)-isogeny (or a certain type of \(9\)-isogeny), there is an arbitrary choice made on the bottom tree leaves in order to make the ordering consistent.

FaltingsHeight(E): CrvEll[FldRat] -> FldReElt#
Precision: RngIntElt                    Default: 

Computes the unstable Faltings height of an elliptic curve over the rationals. This is defined as \(-\log\sqrt{\Omega}\) where \(\Omega\) is the fundamental volume. Note that FaltingsHeight for an elliptic curve over a number fields uses a different normalization.

StableFaltingsHeight(E): CrvEll[FldRat] -> FldReElt#
Precision: RngIntElt                    Default: 

Computes the stable Faltings height of an elliptic curve over the rationals. This is defined as

\[{\log {\rm denom}(j_E)\over 12}-{\log|\Delta_E|\over 12}-\log\sqrt{\Omega}\]

where \(j_E\) is the \(j\)-invariant, \(\Delta_E\) is the (minimal) discriminant, and \(\Omega\) is the fundamental volume.

Example: Isog Curves (ex-17c07d)#

First we compute isogenous curves using DivisionPolynomial; in this special case we obtain the entire isogeny class by considering only \(3\)-isogenies directly from \(E\).

> E:=EllipticCurve([1,-1,1,1,-1]);
> F:=Factorization(DivisionPolynomial(E,3));
> I:=IsogenyFromKernel(E,F[1][1]); I;
Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 29*x - 53 over Rational
Field
> I:=IsogenyFromKernel(E,F[2][1]); I;
Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 14*x + 29 over Rational
Field

Run in calculator

Alternatively, we can get the IsogenousCurves directly. Note that IsogenyFromKernel also returns the map between the isogenous curves as a second argument.

> IsogenousCurves(E);
[
    Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 + x - 1 over Rational
    Field,
    Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 29*x - 53 over
    Rational Field,
    Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 14*x + 29 over
    Rational Field
]
9

Run in calculator

Heights and Height Pairing#

These functions require that the corresponding elliptic curve has integral coefficients.

NaiveHeight(P): PtEll -> FldPrElt#
WeilHeight(P): PtEll -> FldPrElt#

Given a point \(P=(a/b,c/d,1)\) on an elliptic curve \(E\) defined over \({\mathbb{Q}}\) with integral coefficients, this function returns the naive (or Weil) height \(h(P)\) whose definition is \(h(P) = \log \max \{|a|,|b|\}\).

Height(P: parameters): PtEll -> NFldComElt#
CanonicalHeight(P: parameters): PtEll -> NFldComElt#
Precision: RngIntElt                    Default: 

Given a point \(P\) on an elliptic curve \(E\) defined over \({\mathbb{Q}}\) with integral coefficients, this function returns the canonical height \(\hat{h}(P)\).

One definition of \(\hat{h}(P)\) is \(\hat{h}(P) = \lim_{n\to\infty} 4^{-n}h(2^n P)\), although this is of limited computational use. A more useful computational definition is as the sum of local heights: \(\hat{h}(P) = \sum_{p\le\infty} \hat{h}_p(P)\), where the sum ranges over each prime \(p\) and the so-called ‘infinite prime’. Each of these local heights can be evaluated fairly simply, and in fact most of them are \(0\). The function always uses a minimal model for the elliptic curve internally, as otherwise the local height computation could fail. The computation at the infinite prime uses a slight improvement over the \(\sigma\)-function methods given in Cohen, with the implementation being based on an AGM-trick due to Mestre.

LocalHeight(P, p): PtEll, RngIntElt -> FldComElt#
Precision      : RngIntElt                    Default: 
Check          : BoolElt                      Default: false
Renormalization: BoolElt                      Default: false

Given a point \(P\) on an elliptic curve \(E\) defined over \({\mathbb{Q}}\) with integral coefficients, this function returns \(\hat{h}_p(P)\), the local height of \(P\) at \(p\) as described in Height above. The integer \(p\) must be either a prime number or \(0\); in the latter case the height at the infinite prime is returned. The Check parameter determines whether to check if the second argument is prime. The Renormalization parameter changes what definition of heights is used. Without this flag, a factor of \({1\over 6}\log \Delta_v\) is added at every place.

HeightPairing(P, Q: parameters): PtEll, PtEll -> FldComElt#
Precision: RngIntElt                    Default: 

Given two points \(P, Q\) on the same elliptic curve defined over \({\mathbb{Q}}\) with integral coefficients, this function returns the height pairing of \(P\) and \(Q\), which is defined by \(\hat{h}(P, Q) = (\hat{h}(P+Q) - \hat{h}(P) - \hat{h}(Q))/2\).

HeightPairingMatrix(S: parameters): [PtEll] -> AlgMat#
HeightPairingMatrix(E: parameters): CrvEll -> AlgMat#
Precision: RngIntElt                    Default: 

Given a sequence of points on an elliptic curve defined over \({\mathbb{Q}}\) with integral coefficients, this function returns the height pairing matrix. If an elliptic curve is passed to it, the corresponding matrix for the Mordell–Weil generators is returned.

Regulator(S): [ PtEll ] -> FldComElt#
Precision: RngIntElt                    Default: 

Given a sequence of points \(S\) on an elliptic curve \(E\) over \({\mathbb{Q}}\), this function returns the determinant of the Néron-Tate height pairing matrix of the sequence.

Regulator(E): CrvEll -> FldComElt#
Precision: RngIntElt                    Default: 

Given an elliptic curve \(E\) this function returns the regulator of \(E\); i.e., the determinant of the Néron-Tate height pairing matrix of a basis of the free quotient of the Mordell–Weil group.

Example: Fun With Heights (ex-d6c540)#
> E := EllipticCurve([0,0,1,-7,6]);
%> RankBounds(E);
%3 3
> P1, P2, P3 := Explode(Generators(E));
> Height(P1);
0.6682051656519279350331420509
> IsZero(Abs(Height(2*P1) - 4*Height(P1)));
true
> BadPrimes(E);
[ 5077 ]

Run in calculator

The local height of a point \(P\) at a prime is 0 except possibly at the bad primes of \(E\), the ‘infinite’ prime, and those primes dividing the denominator of the \(x\)-coordinate of \(P\). Since these generators have denominator 1 we see that only two local heights need to be computed to find the canonical heights of these points.

> P2;
(2 : 0 : 1)
> LocalHeight(P2, 0);
-0.655035947159686182497278069814
> LocalHeight(P2, 5077); // 0 + Log(5077)/6
1.42207930249123238829272871637
> LocalHeight(P2, 0 : Renormalization);
0.767043355331546205795450646552
> LocalHeight(P2, 5077 : Renormalization);
0.000000000000000000000000000000
> Height(P2);
0.7670433553315462057954506466

Run in calculator

The above shows that the local height at a bad prime may still be zero, at least in the renormalised value.

SilvermanBound(H): SetPtEll -> FldPrElt#
SilvermanBound(E): CrvEll -> FldPrElt#

Given an elliptic curve \(E\) over \({\mathbb{Q}}\) with integral coefficients, this function returns the Silverman bound \(B\) of \(E\). For any point \(P\) on \(E\) we will have \(h(P) - \hat{h}(P) \le B\).

SiksekBound(H: parameters): SetPtEll -> FldPrElt#
SiksekBound(E: parameters): CrvEll -> FldPrElt#
Torsion: BoolElt                    Default: false

Given an elliptic curve \(E\) over \({\mathbb{Q}}\) which is a minimal model, this function returns a real number \(B\) such that for any point \(P\) on \(E\) \(h(P) - \hat{h}(P) \le B\). In many cases, the Siksek bound is much better than the Silverman bound.

If the parameter Torsion is true then a potentially better bound \(B_{\sl Tor}\) is computed, such that for any point \(P\) on \(E\) there exists a torsion point \(T\) so that \(h(P + T) - \hat{h}(P) \le B_{\sl Tor}\). Note that \(\hat{h}(P + T) = \hat{h}(P)\).

Example: Bounds (ex-0bdc03)#

We demonstrate the improvement of the Siksek bound over the Silverman bound for the three example curves from Siksek’s paper [Siksek, 1995].

> E := EllipticCurve([0, 0, 0, -73705, -7526231]);
> SilvermanBound(E);
13.00022113685530200655193
> SiksekBound(E);
0.82150471924479497959096194911
> E := EllipticCurve([0, 0, 1, -6349808647, 193146346911036]);
> SilvermanBound(E);
21.75416864448061105008
> SiksekBound(E);
0.617777290687848386342334921728509577480
> E := EllipticCurve([1, 0, 0, -5818216808130, 5401285759982786436]);
> SilvermanBound(E);
27.56255914401769757660
> SiksekBound(E);
15.70818965430290161142481294545

Run in calculator

This last curve has a torsion point, so we can further improve the bound:

> T := E![ 1402932, -701466 ];
> Order(T);
2
> SiksekBound(E : Torsion := true);
11.0309876231179839831829512652688

Run in calculator

Here is a point which demonstrates the applicability of the modified bound.

> P := E![ 14267166114 * 109, -495898392903126, 109^3 ];
> NaiveHeight(P) - Height(P);
12.193000709615680011116868901084
> NaiveHeight(P + T) - Height(P);
2.60218831527724007036

Run in calculator

IsLinearlyIndependent(P, Q): PtEll, PtEll -> BoolElt, ModTupElt#

Given points \(P\) and \(Q\) on an elliptic curve \(E\), this function returns true if and only if \(P\) and \(Q\) are independent free elements of the group of rational points of an elliptic curve (modulo torsion points). If false, the function returns a vector \(v = (r,s)\) as a second value such that \(rP + sQ\) is a torsion point.

IsLinearlyIndependent(S): [ PtEll ] -> BoolElt, ModTupElt#

Given a sequence of points \(S\) belonging to an elliptic curve \(E\), this function returns true if and only if the points in \(S\) are linearly independent (modulo torsion). If false, the function returns a vector \(v\) in the kernel of the height pairing matrix, i.e. giving a torsion point as a linear combination of the points in \(S\).

ReducedBasis(S): [ PtEll ] -> [ PtEll ]#

Given a sequence of points \(S\) belonging to an elliptic curve \(E\) over the rationals, the function returns a sequence of points that are independent modulo the torsion subgroup (equivalently, they have non-degenerate height pairing), and which generate the same subgroup of \(E({\mathbb{Q}})/E_{tors}({\mathbb{Q}})\) as points of \(S\).

Example: Linear Independence (ex-ce19b5)#

We demonstrate the linear independence test on an example curve with an 8-torsion point and four independent points. The torsion point is easily recognized and we establish the independence of the remaining points using the height function.

> E := EllipticCurve([0,1,0,-95549172512866864, 11690998742798553808334900]);
%>                           11690998742798553808334900]);
> P0 := E![ 39860582, 2818809365988 ];
> P1 := E![ 144658748, -946639447182 ];
> P2 := E![ 180065822, 569437198932 ];
> P3 := E![ -339374593, 2242867099638 ];
> P4 := E![ -3492442669/25, 590454479818404/125 ];
> S0 := [P0, P1, P2, P3, P4];
> IsLinearlyIndependent(S0);
false (1 0 0 0 0)
> Order(P0);
8
> S1 := [P1, P2, P3, P4];
> IsLinearlyIndependent(S1);
true

Run in calculator

We now demonstrate the process of solving for a nontrivial linear dependence among points on an elliptic curve by constructing a singular matrix, forming the corresponding linear combination of points, and establishing that the dependence is in the matrix kernel.

> M := Matrix(4, 4, [-3,-1,2,-1,3,3,3,-2,3,0,-1,-1,0,2,1,1]);
> Determinant(M);
0
> S2 := [ &+[ M[i, j]*S1[j] : j in [1..4] ] : i in [1..4] ];
> IsLinearlyIndependent(S2);
false ( 5 -3  8  7)
> Kernel(M);
RSpace of degree 4, dimension 1 over Integer Ring
Echelonized basis:
( 5 -3  8  7)

Run in calculator

Despite the moderate size of the numbers which appear in the matrix \(M\), we note that height is a quadratic function in the matrix coefficients. Since height is a logarithmic function of the coefficient size of the points, we see that the sizes of the points in this example are very large:

> [ RealField(16) | Height(P) : P in S2 ];
[ 137.376951049198, 446.51954933694, 52.724183282292, 59.091649046171 ]
> Q := S2[2];
> Log(Abs(Numerator(Q[1])));
467.6598587040659411808117253
> Log(Abs(Denominator(Q[1])));
449.2554587727840583949442765

Run in calculator

pAdicHeight(P, p): PtEll, RngIntElt -> FldPadElt#
Precision: RngIntElt                    Default: 0
E2       : FldPadElt                    Default: 0

Given a point \(P\) on an elliptic curve defined on the rationals and a prime \(p\ge 5\) of good ordinary reduction, this function computes the \(p\)-adic height of \(P\) to the desired precision. The value of the EisensteinTwo function for the curve can be passed as a parameter. The algorithm dates back to [Mazur and Tate, 1991] with improvements due to [Mazur et al., 2006] and [Harvey, 2008]. The normalization is that of the last-named paper and is \(2p\) (or \(-2p\) in some cases) as large as in other papers.

pAdicRegulator(S, p): [PtEll], RngIntElt -> FldPadElt#
Precision: RngIntElt                    Default: 0
E2       : FldPadElt                    Default: 0

Given a set of points \(S\) on an elliptic curve defined over the rationals and a prime \(p\ge 5\) of good ordinary reduction, this function computes the \(p\)-adic height regulator of \(S\) to the desired precision. Here the normalization divides out a power of \(p\) from the individual heights.

EisensteinTwo(E, p): CrvEll, RngIntElt -> FldPadElt#
Precision: RngIntElt                    Default: 0

Given an elliptic curve over the rationals and a prime \(p\ge 5\) of good ordinary reduction, this function computes the value of the Eisenstein series \(E_2\) using the Monsky-Washnitzer techniques via Kedlaya’s algorithm. See pAdicHeight above for references.

FrobeniusMatrix(E, p): CrvEll, RngIntElt -> Mtrx#
Precision: RngIntElt                    Default: 10

Given an elliptic curve over the rationals and a prime \(p\ge 5\) of good reduction, this function computes the matrix corresponding to the action of Frobenius, to the given precision. The basis used is \(\{dx/y,x(dx/y)\}\).

Example: Padic Height (ex-1e7aba)#

We give examples for computing \(p\)-adic heights.

> E := EllipticCurve("5077a");
> P1 := E ! [2, 0];
> P2 := E ! [1, 0];
> P3 := E ! [-3, 0];
> assert P1+P2+P3 eq E!0; // the three points sum to zero
> for p in PrimesInInterval(5,30) do pAdicHeight(P1, p); end for;
4834874647277 + O(5^20)
5495832406058373*7 + O(7^20)
-12403985313704524674*11 + O(11^20)
616727731594753360389*13 + O(13^20)
53144975867434108754867*17 + O(17^20)
651478754033733420744924*19 + O(19^20)
1382894029404692415656094*23^2 + O(23^20)
-2615503441214747688800993518*29 + O(29^20)
> pAdicHeight(P1, 37); // 37 is not ordinary for this curve
>> pAdicHeight(P1, 37); // 37 is not ordinary for this curve
Runtime error in 'pAdicHeight': p cannot be supersingular
> for p in PrimesInInterval(5,30) do pAdicRegulator([P1, P2], p); end for;
-263182161797834*5^-2 + O(5^20)
-35022392779944725 + O(7^20)
-331747503271490921584 + O(11^20)
246446095809126124462 + O(13^20)
-1528527915797227515067270 + O(17^20)
333884275695653846729970*19 + O(19^20)
412978398356115570280760602 + O(23^20)
-45973362301048046561945193743 + O(29^20)
> pAdicRegulator([P1, P2, P3], 23); // dependent points
O(23^20)
> eisen_two := EisensteinTwo(E, 13 : Precision:=40); eisen_two;
25360291252705414983472710631099471724343012 + O(13^40)
> pAdicRegulator([P1, P2], 13 : Precision:=40, E2:=eisen_two);
85894629213918025547455609490608727790695215 + O(13^40)

Run in calculator

Heegner Points#

For an elliptic curve of rank \(1\), it is possible to compute a generator by an analytic process; the elliptic logarithm of some multiple \(nP\) of the generator is the sum of the values of the modular parameterization at a series of points in the upper half-plane corresponding to a full set of class representatives for an appropriately-chosen quadratic field. There is no such thing as a free lunch, sadly; the calculation requires computing \(O(hN)\) terms to a precision of \(O(h)\) digits (where \(N\) is the conductor), so in practice it works best for curves contrived to have small conductors.

The calculation proceeds in three stages: choosing the quadratic field \({\mathbb{Q}}(\sqrt{-d})\), evaluating the modular parameterization, and recovering the generator from the elliptic logarithm value. Essentially, this is an implementation of the method of Gross and Zagier [Gross and Zagier, 1986]; Elkies performed some substantial computations using this method in 1994, and much of the work required to produce this implementation was done by Cremona and Womack. An array of tricks have been added, and are described to some extent in some notes of Watkins.

HeegnerPoint(E : parameters): CrvEll -> BoolElt, PtEll#
NaiveSearch    : RngIntElt                    Default: 1000
Discriminant   : RngIntElt                    Default: 
Cover          : Crv                          Default: 
DescentPossible: BoolElt                      Default: true
IsogenyPossible: BoolElt                      Default: true
Traces         : SeqEnum                      Default: []
verbose        : Heegner                      Default: Verbose : 1

Attempts to find a point on a rank 1 rational elliptic curve \(E\) using the method of Heegner points, returning true and the point if it finds one, otherwise false. An error is triggered if the (analytic) rank is not 1.

The parameter NaiveSearch indicates to what height the algorithm does a preliminary search for points on \(E\) (using Points). The Discriminant parameter allows the user to specify an auxiliary discriminant; this must satisfy the Heegner hypothesis, and the corresponding quadratic twist must have rank 0. The Cover option allows the user to specify a 2-cover or 4-cover (perhaps obtained from TwoDescent or FourDescent) to speed the calculation. This should be either a hyperelliptic curve or a quadric intersection, and there must be a map from the cover to the given elliptic curve. If the DescentPossible option is true, then the algorithm might perform such a descent in any case. If the IsogenyPossible option is true, then the algorithm will first try to guess the best isogenous curve on which to do the calculation — if a Cover is passed to the algorithm, it will be ignored if \(E\) is not the best isogenous curve. The Traces option takes an array of integers which correspond to the first however-many traces of Frobenius for the elliptic curve, thus saving having to recompute them.

The algorithm assumes that the Manin constant of the given elliptic curve is 1 (which is conjectured in this case), and does not return a generator for the Mordell–Weil group, but a point whose height is that given by a conjectural extension of the Gross–Zagier formula. This should be \(\sqrt{Sha}\) times a generator.

HeegnerPoint(C : parameters): CrvHyp -> BoolElt, PtHyp#
HeegnerPoint(f : parameters): RngUPolElt -> BoolElt, PtHyp#
HeegnerPoint(C : parameters): Crv -> BoolElt, Pt#
NaiveSearch : RngIntElt                    Default: 10000
Discriminant: RngIntElt                    Default: 
Traces      : SeqEnum                      Default: []
verbose     : Heegner                      Default: Verbose : 3

These are utility functions for the above. The input is either a hyperelliptic curve given by a polynomial of degree 4, or this quartic polynomial — in both cases the quartic should have no rational roots — or a nonsingular intersection of two quadrics in \({\mathbb{P}}^3\). These functions call HeegnerPoint on the underlying elliptic curve (which must have rank 1). They then aim to map the computed point back to the given covering curve, though this will not be possible when the Tate–Shafarevich group of the elliptic curve has even order. In such cases an error is triggered, so too when the cover corresponds to a torsion point.

The rational reconstruction step of the HeegnerPoint algorithm can be quite time-consuming for some coverings, especially if the index is large.

ModularParametrization(E, z, B : parameters): CrvEll[FldRat], FldComElt, RngIntElt -> FldComElt#
ModularParametrisation(E, z, B : parameters): CrvEll[FldRat], FldComElt, RngIntElt -> FldComElt#
ModularParametrization(E, z : parameters): CrvEll[FldRat], FldComElt -> FldComElt#
ModularParametrisation(E, z : parameters): CrvEll[FldRat], FldComElt -> FldComElt#
ModularParametrization(E, Z, B : parameters): CrvEll[FldRat], [FldComElt], RngIntElt -> [FldComElt]#
ModularParametrisation(E, Z, B : parameters): CrvEll[FldRat], [FldComElt], RngIntElt -> [FldComElt]#
ModularParametrization(E, Z : parameters): CrvEll[FldRat], [FldComElt] -> [FldComElt]#
ModularParametrisation(E, Z : parameters): CrvEll[FldRat], [FldComElt] -> [FldComElt]#
ModularParametrization(E, f, B : parameters): CrvEll[FldRat], QuadBinElt, RngIntElt -> FldComElt#
ModularParametrisation(E, f, B : parameters): CrvEll[FldRat], QuadBinElt, RngIntElt -> FldComElt#
ModularParametrization(E, f : parameters): CrvEll[FldRat], QuadBinElt -> FldComElt#
ModularParametrisation(E, f : parameters): CrvEll[FldRat], QuadBinElt -> FldComElt#
ModularParametrization(E, F, B : parameters): CrvEll[FldRat], [QuadBinElt], RngIntElt -> [FldComElt]#
ModularParametrisation(E, F, B : parameters): CrvEll[FldRat], [QuadBinElt], RngIntElt -> [FldComElt]#
ModularParametrization(E, F : parameters): CrvEll[FldRat], [QuadBinElt] -> [FldComElt]#
ModularParametrisation(E, F : parameters): CrvEll[FldRat], [QuadBinElt] -> [FldComElt]#
Traces: SeqEnum                    Default: []
Traces   : SeqEnum                      Default: []
Precision: RngIntElt                    Default: 

Given a rational elliptic curve \(E\) and a point \(z\) in the upper-half-plane, compute the modular parametrization \(\int_z^\infty f_E(\tau)\, d\tau\) where \(f_E\) is the modular form associated to \(E\). The version with a bound \(B\) uses the first \(B\) terms of the \(q\)-expansion, while the other version determines how many terms are needed. The optional parameter Traces allows the user to pass the first however-many traces of Frobenius. There are also versions which take an array \(Z\) of complex points, and versions which take positive definite binary quadratic forms \(f\) (or an array \(F\)) rather than points in the upper-half-plane (a Precision can be specified with the latter).

HeegnerDiscriminants(E, lo, hi): CrvEll[FldRat], RngIntElt, RngIntElt -> SeqEnum#
Fundamental: BoolElt                    Default: false
Strong     : BoolElt                    Default: false

Given a rational elliptic curve and a range from \(lo\) to \(hi\), compute the negative fundamental discriminant in this range that satisfies the Heegner hypothesis for the curve. The Fundamental option restricts to fundamental discriminants. The Strong option restricts to discriminants that satisfy a stronger Heegner hypothesis, namely that \(a_p=-1\) for all primes \(p\) that divide \(\gcd(D,N)\).

HeegnerForms(E, D : parameters): CrvEll[FldRat], RngIntElt -> SeqEnum#
UsePairing    : BoolElt                    Default: false
UseAtkinLehner: BoolElt                    Default: true
Use_wQ        : BoolElt                    Default: true
IgnoreTorsion : BoolElt                    Default: false

Given a rational elliptic curve of conductor \(N\) and a negative discriminant that meets the Heegner hypothesis for \(N\), the function computes representatives for the complex multiplication points on \(X_0(N)\).

In general the return value is a sequence of 3-tuples \((Q,m,T)\) where \(Q\) is a quadratic form, \(m\) is a multiplicity, and \(T\) is a torsion point on \(E\). Letting \(\phi\) be the modular parametrization map, the sum on \(E\) of the values \(m(\phi(Q)+T)\) is a Heegner point in \(E({\mathbb{Q}})\). When the number of these values equals the class number \(h=h(D)\) (and the multiplicities are all \(1\) or \(-1\)) then they are actually the images on \(E\) of the CM points on \(X_0(N)\). (They all correspond to a single choice of square root of \(D\) modulo \(4N\).)

If UsePairing is added, then CM points that give conjugate values under the modular parametrisation map are combined. If UseAtkinLehner is added, then more than one square root of \(D\) modulo \(4N\) can be used. If Use_wQ is added, then forms can appear with extra multiplicity, due to primes that divide the GCD of the conductor and the fundamental discriminant. If IgnoreTorsion is added, then the fact that Atkin-Lehner can change the result by a torsion point will be ignored. The UsePairing option requires that IgnoreTorsion be true.

This function requires (so as not to confuse the user) that the ManinConstant of the curve be equal to 1.

HeegnerForms(N, D : parameters): RngIntElt, RngIntElt -> SeqEnum#
AtkinLehner: [RngIntElt]                    Default: []

Given a level \(N\) and a discriminant that meets the Heegner hypothesis for the level, the function returns a sequence of binary quadratic forms which correspond to the Heegner points. The Atkin-Lehner option takes a sequence of \(q\) with \(\gcd(q,N/q)=1\) and has the effect of allowing more than one square root of \(D\) modulo \(4N\) to be used.

ManinConstant(E): CrvEll[FldRat] -> RngIntElt#

Compute the Manin constant of a rational elliptic curve. This is in most cases simply a conjectural value (and most often just 1).

HeegnerTorsionElement(E, Q): CrvEll[FldRat], RngIntElt -> PtEll#

Given a rational elliptic curve and an integer \(Q\) corresponding to an Atkin-Lehner involution (so that \(\gcd(Q,N/Q)=1\)), this function computes the torsion point on the curve corresponding to the period given by the integral from \(i\infty\) to \(w_Q(i\infty)\).

HeegnerPoints(E, D : parameters): CrvEll[FldRat], RngIntElt -> Tup, PtEll#
ReturnPoint: BoolElt                      Default: false
Precision  : RngIntElt                    Default: 100
verbose    : Heegner                      Default: Verbose : 1

Given an elliptic curve \(E\) over \({\mathbb{Q}}\), and a suitable discriminant \(D\) (of a quadratic field) this function computes the images on \(E\) under the modular parametrization of the CM points on \(X_0(N)\) associated to \(D\). It returns a tuple \(\langle p_D, m \rangle\), where \(p_D\) is an irreducible polynomial whose roots are the \(x\)-coordinates of these images, and where \(m\) is the multiplicity of each of these images (the number of CM points on \(X_0(N)\) mapping to a given point on \(E\)). These \(x\)-coordinates lie in the ring class field of \({\mathbb{Q}}(\sqrt{D})\), and the class number \(h(D)\) must equal either \(m \deg(p_D)\) or \(2m \deg(p_D)\).

The conductor of the order \({\mathbb{Q}}(\sqrt{D})\) is required to be coprime to the conductor of \(E\).

The second object returned by the function is one of the conjugate points, as an element of the point set \(E(H)\) where \(H\) is the field defined by \(p_D\), or a quadratic extension of it. This step can be time consuming; if ReturnPoint is set to false, the point is not computed.

Warning: The computation is not rigorous, as it involves computing over the complex numbers, and then recognising the coefficients of the polynomial as rationals. However, the program performs a heuristic check: it checks that the polynomial has the correct splitting at some small primes (sufficiently many to be sure that wrong answers will not occur in practice).

Example: Heegner (ex-f2bb35)#
> time HeegnerPoint(EllipticCurve([1,0,0,312,-3008])); //uses search
true (12 : -56 : 1)
Time: 0.240
> time HeegnerPoint(EllipticCurve([0,0,1,-22787553,-41873464535]));
true (11003637829478432203592984661004129/1048524607168660222036584535396 :
-1004181871409718654255966342764883958203316448270339/10736628855783147946
99393270058310986889998056 : 1)
Time: 1.380

Run in calculator

Example: Heegner2 (ex-350bc4)#

Here are some more complicated examples. In the first one, the curve has a 163-isogenous curve, which the algorithm uses to speed the computation. This occurs automatically, with most of the time taken being in computing the isogeny map.

> E := EllipticCurve([0,0,1,-57772164980,-5344733777551611]);
> b, pt:= HeegnerPoint(E);
> Height(pt);
373.478661569142379884077480412

Run in calculator

Example: Heegner3 (ex-24a537)#

In this next example, we first use descent to get a covering on which the desired point will have smaller height.

> E := EllipticCurve([0,-1,0,-71582788120,-7371563751267600]);
> T := TwoDescent(E : RemoveTorsion)[1];
> T;
Hyperelliptic Curve defined by y^2 = -2896*x^4 - 57928*x^3 - 202741*x^2
 + 868870*x - 651725 over Rational Field
> S := FourDescent(T : RemoveTorsion)[1];
> b, pt := HeegnerPoint(S);
> pt;
(-34940281640330765977951793/72963317481453011430052232 :
46087465795237503244048957/72963317481453011430052232 :
82501230298438806677528297/72963317481453011430052232 : 1)

Run in calculator

We obtain a point on \(S\), not on the original curve. We map it to \(E\) using the descent machinery.

> _, m := AssociatedEllipticCurve(S);
> PT := m(pt);
> PT;
(26935643239674824824611869793601774003477303945223677741244455058753
924460587724041316046901475913814274843012625394997597714766923750555
669810857471061235926971161094484197799515212721830555528087646969545
65/837619099331786545303500955405701693904657590793269053332825491870
645799230089011267382251975387071464373622714525213870033427638236014
2288012504288439077587496501436920044109243898570190931925860244164 :
410189886613094359515065087530226951251222017120181558101276037601794
678635473792334597914052557787798899390943937170051840037860568689664
871351793404398352109768736545284569745952273382778021947446766526118
621612003004627401344216069791103330332004546699363266079516476593864
98538303998567379869974143259174395/766601839981278884919411893932635
388671474045058772153268571977045787439290021029065740244648077391646
579430077900352635000328805236464794479797855430820809227462762666048
009219642700664370632930446228302292313415544188481623273194456758440
446505454248062292834244615276350323795396202280072306278575288 : 1)
> Height(PT);
476.811182818720336949724781780
> ConjecturalRegulator(E : Precision := 5);
476.81 1

Run in calculator

Example: Heegner4 (ex-6e096b)#

Finally, we do some Heegner point calculation with the curve 43A and the discriminant \(-327\). Note that the obtained trace down to the rationals is \(3\)-divisible, but the point over the Hilbert class field is not.

> E := EllipticCurve([0,1,1,0,0]);
> HeegnerDiscriminants(E,-350,-300);
[ -347, -344, -340, -335, -331, -328, -327, -323, -319, -308, -303 ]
> HF := HeegnerForms(E,-327); HF;
[ <<43,19,4>, 1, (0 : 1 : 0)>, <<43,67,28>, 1, (0 : 1 : 0)>,
<<86,105,33>, 1, (0 : 1 : 0)>, <<86,153,69>, 1, (0 : 1 : 0)>,
<<129,105,22>, 1, (0 : 1 : 0)>, <<129,153,46>, 1, (0 : 1 : 0)>,
<<172,67,7>, 1, (0 : 1 : 0)>, <<258,363,128>, 1, (0 : 1 : 0)>,
<<258,411,164>, 1, (0 : 1 : 0)>, <<301,67,4>, 1, (0 : 1 : 0)>,
<<473,621,204>, 1, (0 : 1 : 0)>, <<473,841,374>, 1, (0 : 1 : 0)> ]
> H := [x[1] : x in HF]; mul := [x[2] : x in HF];
> params := ModularParametrization(E,H : Precision := 10);
> wparams := [ mul[i]*params[i] : i in [1..#H]];
> hgpt := EllipticExponential(E,&+wparams);
> hgpt;
[ 1.000000002 - 1.098466121E-9*I, 1.000000003 - 1.830776870E-9*I ]
> HeegnerPt := E![1,1];
> DivisionPoints(HeegnerPt, 3);
[ (0 : -1 : 1) ]

Run in calculator

So the Heegner point is \(3\) times \((0,-1)\) in \(E({\mathbb{Q}})\). We now find algebraically one of the points (of which we took the trace to get \(HeegnerPt\)). This point will be defined over a subfield of the class field of \({\mathbb{Q}}(\sqrt{-327})\), and will have degree dividing the class number. The \(poly\) below is the minimal polynomial of the \(x\)-coordinate.

> ClassNumber(QuadraticField(-327));
12
> poly, pt := HeegnerPoints(E, -327 : ReturnPoint);
> poly;
<t^12 + 10*t^11 + 76*t^10 - 1150*t^9 + 475*t^8 - 4823*t^7 +
 997*t^6 - 5049*t^5 - 2418*t^4 - 468*t^3 - 3006*t^2 + 405*t - 675, 1>
> pt;
(u : 1/16976844562625*(58475062076*u^11 + 568781661961*u^10 +
 4238812569862*u^9 - 68932294336288*u^8 + 42534102728187*u^7 -
 238141610215111*u^6 + 134503848441911*u^5 - 122884262733563*u^4 -
 58148031982456*u^3 + 129014145075851*u^2 -
 68190988248855*u + 40320643901175) : 1)
> DivisionPoints(pt,3);
[]

Run in calculator

Here is another example of Heegner points over class fields.

Example: Heegner5 (ex-339f1a)#
> E := EllipticCurve([0,-1,0,-116,-520]);
> Conductor(E);
1460
> ConjecturalRegulator(E);
4.48887474770666173576726806264 1
> HeegnerDiscriminants(E,-200,-100);
[ -119, -111 ]
> P := HeegnerPoints(E,-119);
> P;
<1227609449333996689*t^10 - 106261506377143984603*t^9 +
    2459826667693945203684*t^8 - 12539974356047058417320*t^7 -
    298524708823654411408343*t^6 + 4440876684434597926161175*t^5 +
    7573549099120618979833241*t^4 - 393938048860406386108113130*t^3 -
    215318107135691628298668863*t^2 + 13958289016298162706904004974*t
    + 38624559371249968900024945369, 1>

Run in calculator

The function automatically performs a heuristic check that the polynomial has the right properties, using reduction mod small primes. A more expensive check is the following.

> G := GaloisGroup( P[1] );
> IsIsomorphic(G,DihedralGroup(10));
true

Run in calculator

The extension of \({\mathbb{Q}}(-119)\) defined by the polynomial is the class field. We now obtain a nice representation of it, and use this to compute the height of the point (which is a bit quicker than computing the height directly).

> K<u> := NumberField(P[1]);
> L<v>, m := OptimizedRepresentation(K);
> _<y> := PolynomialRing(Rationals());  // use 'y' for printing
> DefiningPolynomial(L);
y^10 + 2*y^9 - y^8 - 7*y^7 - 7*y^6 + 10*y^5 + 13*y^4 - 9*y^3 - 5*y^2 +
    5*y - 1
> PT := Points(ChangeRing(E,L),m(u))[1];  // y-coord is defined over L
> Height(PT);
6.97911761109714376876370533

Run in calculator

Analytic Information#

Periods(E: parameters): CrvEll -> [ FldComElt ]#
Precision: RngIntElt                    Default: 

Returns the sequence of periods of the Weierstrass \(\wp\)-function associated to the (rational) elliptic curve \(E\), to Precision digits. The first element of the sequence is the real period. The function accepts a non-minimal model, and returns the periods corresponding to that model. As with many algorithms involving analytic information on elliptic curves, the implementation exploits an AGM-trick due to Mestre. There is some functionality for elliptic curves over number fields (package level code), though the exact normalisation is not always given.

Periods(E, k): CrvEll, RngIntElt -> [ FldComElt ]#
Precision: RngIntElt                    Default: 

Given an elliptic curve over a number field an integer denoting the \(k\)th real embedding, calculate the periods. This uses the C implementation after turning the coefficients of the defining equation into real numbers. Again the first period in the returned array should be real.

EllipticCurveFromPeriods(om: parameters): [ FldComElt ] -> CrvEll#
Epsilon: FldReElt                    Default: 0.001

Given two complex numbers \(\omega_1,\omega_2\) such that \(\omega_2/\omega_1\) is in the upper half-plane that correspond to an integral model of an elliptic curve over \({\bf Q}\), return such a minimal model of such a curve. This uses the classical Eisenstein series, with the parameter Epsilon indicating how close to integers the computed \(-27c_4\) and \(-54c_6\) need to be.

RealPeriod(E: parameters): CrvEll -> FldReElt#
Precision: RngIntElt                    Default: 

Returns the real period of the Weierstrass \(\wp\)-function associated to the elliptic curve \(E\) to Precision digits.

EllipticExponential(E, z): CrvEll, FldComElt -> [ FldComElt ]#

Given a rational elliptic curve \(E\) and a complex number \(z\), the function computes the pair [\(\wp(z),\wp'(z)\)] where \(\wp(s)\) is the Weierstrass \(\wp\)-function. A nonminimal model may be given, though it should be integral. The algorithm used is taken from [Cohen, 1993] for small precision, and Newton iteration on EllipticLogarithm is used for high precision. The function returns a sequence rather than a point on the curve.

EllipticExponential(E, k, z): CrvEll, RngIntElt, FldComElt -> [ FldComElt ]#

Given an elliptic curve \(E\) over a number field, an integer denoting the \(k\)th real embedding, and a complex number \(z\), the function computes the pair [\(\wp(z),\wp'(z)\)] where \(\wp(s)\) is the Weierstrass \(\wp\)-function. As with Periods, the function proceeds by using the C implementation over the reals. There is no restriction that the curve equation be integral. The function returns a sequence rather than a point on the curve.

EllipticExponential(E, S): CrvEll, [ FldRat ] -> [ FldComElt ]#

Given a rational elliptic curve \(E\) and a sequence \(S = [p,q]\), where \(p\) and \(q\) are rational numbers, this function computes the elliptic exponential of \(p\) times the RealPeriod and \(q\) times the imaginary period.

EllipticLogarithm(P): PtEll[FldRat] -> FldComElt#
Precision: RngIntElt                    Default: 

Denote by \(\omega_1, \omega_2\) the periods of the Weierstrass \(\wp\)-function related to \(E\). This function returns the elliptic logarithm \(\phi(P)\) of the point \(P\), such that \(-\omega_1/2\le {\rm{Re}}(\phi(P)) < \omega_1/2\) and \(-\omega_2/2\le {\rm{Im}}(\phi(P)) < \omega_2/2\). The value is returned to Precision digits. As with Periods, a non-minimal model can be given (though the model must be integral), and the EllipticLogarithm will be computed with respect to it. The algorithm is again an AGM-trick due to Mestre.

EllipticLogarithm(P, k): PtEll[FldNum], RngIntElt -> FldComElt#
Precision: RngIntElt                    Default: 

Given an elliptic curve over a number field and a point on it, return the elliptic logarithm associated to the \(k\)th real embedding. There is no restriction that the model be integral.

EllipticLogarithm(E, S): CrvEll, [ FldComElt ] -> FldComElt#
Precision: RngIntElt                    Default: 
Check    : BoolElt                      Default: true

Given an elliptic curve \(E\) and a sequence \(S = [z_1, z_2]\), where \(z_1\) and \(z_2\) are complex numbers approximating a point \(P\) on \(E\), this function returns the elliptic logarithm \(\phi(P)\). For details see the previous intrinsic. When Check is false, \(z_1\) and \(z_2\) need not have any relation to a point on the curve, in which case only the \(x\)-coordinate matters up to (essentially) a choice of sign in the resulting logarithm.

pAdicEllipticLogarithm(P, p: parameters): PtEll, RngIntElt -> FldLocElt#
Precision: RngIntElt                    Default: 50

For a point \(P\) on an elliptic curve \(E\) which is a minimal model and a prime \(p\), returns the \(p\)-adic elliptic logarithm of \(P\) to Precision digits. The order of \(P\) must not be a power of \(p\).

Example: Ell Exp (ex-ca5786)#

Verify that EllipticExponential and EllipticLogarithm are inverses.

> C<I>:=ComplexField(96);
> E:=EllipticCurve([0,1,1,0,0]);
> P:=EllipticExponential(E,0.571+0.221*I); P;
[ 1.656947605210186238868298175 + -1.785440180067681418618695947*I,
-2.417077284700315330385200257 + 3.894153792661208360153853530*I ]
> EllipticLogarithm(E,P);
0.5710000000000000000000000000 + 0.2210000000000000000000000000*I

Run in calculator

Add points on a curve via Napier’s method.

> E:=EllipticCurve([0,0,1,-7,6]);
> P1:=E![0,2]; P2:=E![2,0]; P3:=E![1,0];
> L:=EllipticLogarithm(E!P1)+EllipticLogarithm(E!P2)+EllipticLogarithm(E!P3);
> L;
0.521748219757790769853120197937 + 1.48054826824141499330733111064*i
> P:=EllipticExponential(E,L);
> [Round(Real(x)) : x in P];
[ 4, -7 ]
> P1+P2+P3;
(4 : -7 : 1)

Run in calculator

Example: Ellexp Nf (ex-bd92df)#

Verify that the use of real embeddings works with Periods.

> Q := RationalsAsNumberField();
> E := EllipticCurve([0,1,1,0,0]);
> Periods (E : Precision:=15);
[ 5.46868952996758, 2.73434476498379 + 1.36318241817043*$.1 ]
> EQ := BaseChange (E, Q);
> Periods (EQ,1 : Precision:=15);
[ 5.46868952996758, 2.73434476498379 + 1.36318241817043*$.1 ]
> _<s> := QuadraticField(5);
> E := EllipticCurve([s+1,1,-1,-s,2]);
> Periods (E,1 : Precision:=15);
[ 3.87725004777908, 1.93862502388954 + 0.697984279657861*$.1 ]
> Periods (E,2 : Precision:=15);
[ 3.20379220349709, 1.60189610174854 + 1.31468730940820*$.1 ]

Run in calculator

And go back-and-forth with exponentials and logarithms.

> K<s> := QuadraticField(5);
> E := EllipticCurve([s+1,1,-1,-s,2]);
> P := Points(E,1)[1];
> Q := Points(E,1/2*(-9*s+11))[1];
> R := Points(E,1/2*(25*s + 55))[1];
> lP1 := EllipticLogarithm(P,1); lP1;
0.786501754500788971333154830602
> P1 := EllipticExponential(E,1,lP1); P1;
 0.999999999999999999999999999998 - 8.09833458701901575572176176187E-40*i,
-2.85410196624968454461376050309 - 5.80398551230662251457732924835E-40*i ]
> Abs(Conjugates(P[2])[1]-P1[2]); // y-coord diff is close to 0
3.15544362088404722170029225148E-30
> lQ2 := EllipticLogarithm(Q,2);
> lR2 := EllipticLogarithm(R,2);
> QR2 := EllipticExponential(E,2,lQ2+lR2);
[ 0.236067977499789696409173668732 - 9.28794630103153670720620051679E-40*i,
-1.09016994374947424102293417183 - 2.95168486889455241068806426790E-39*i ]
> Abs(Conjugates((Q+R)[1])[2]-QR2[1]);  // compare x-coords
1.18329135783151770848210977742E-30

Run in calculator

RootNumber(E): CrvEll -> RngIntElt#

Calculates the global root number of an elliptic curve \(E\) defined over \({\mathbb{Q}}\). This is equal to the sign in the functional equation of the \(L\)-series associated to the curve. The method used is to take a product of local root numbers over the primes of bad reduction.

RootNumber(E, p): CrvEll, RngIntElt -> RngIntElt#

Calculates the local root number at a prime \(p\) of an elliptic curve \(E\). The method used is due to Halberstadt; for \(p > 3\) it is a straightforward calculation involving the valuation of the discriminant, while for \(p = 2, 3\) it involves a more careful analysis of the reduction type.

AnalyticRank(E): CrvEll -> RngIntElt, FldReElt#
verbose  : AnalyticRank                    Default: Verbose : 1
Precision: RngIntElt                       Default: 5

Determine the analytic rank of the rational elliptic curve \(E\). The algorithm used is heuristic, computing derivatives of the \(L\)-function \(L(E,s)\) at \(s=1\) until one appears to be nonzero. Local power series methods are used to compute the special functions used for higher derivatives. The function returns the first nonzero derivative \(L^{(r)}(1)/r!\) as a second argument. The precision is optional, and is taken to be \(17\) bits if omitted; the time taken can increase dramatically if this is increased much beyond \(50\) digits as the time to compute the special functions then starts to dominate the running time.

ConjecturalRegulator(E): CrvEll -> FldReElt, RngIntElt#
Precision: RngIntElt                    Default: 

Using the AnalyticRank function, this function calculates an approximation, assuming that the Birch–Swinnerton-Dyer conjecture holds, to the product of the regulator of the elliptic curve \(E\) and the order of the Tate–Shafarevich group. The (assumed) analytic rank is returned as a second value.

ConjecturalRegulator(E, v): CrvEll, FldReElt -> FldReElt#

Given an elliptic curve \(E\) with \(L\)-function \(L(E,s)\) and the value \(v\) of the first nonzero derivative \(L^{(r)}(1)/r!\), this function calculates an approximation, assuming that the Birch–Swinnerton-Dyer conjecture holds, to the product of the regulator of the elliptic curve \(E\) and the order of its Tate–Shafarevich group.

Example: Analytic Rank (ex-293403)#
> E:=EllipticCurve([1,1,0,-2582,48720]);
> time r, Lvalue := AnalyticRank(E : Precision:=9); r,Lvalue;
Time: 17.930
6 320.781164
> ConjecturalRegulator(E,Lvalue);
68.2713770
> time G, map := MordellWeilGroup(E : HeightBound := 8); G;
Time: 21.540
Abelian Group isomorphic to Z (6 copies)
Defined on 6 generators (free)
> Regulator([map(g): g in OrderedGenerators(G)]);
68.2713769

Run in calculator

Example: Conjectural Regulator (ex-6c18ce)#
> ConjecturalRegulator(EllipticCurve([0,-1,1,0,0]) : Precision := 8);
1.0000000 0
> ConjecturalRegulator(EllipticCurve([0,-1,1,0,0]) : Precision := 21);
1.00000000000000000000 0
> ConjecturalRegulator(EllipticCurve([0,-1,1,0,0]) : Precision := 35);
1.0000000000000000000000000000000000 0
> ConjecturalRegulator(EllipticCurve([0,-1,1,0,0]) : Precision := 50);
1.0000000000000000000000000000000000000000000000000 0

Run in calculator

ModularDegree(E): CrvEll -> RngIntElt#
verbose: ModularDegree                    Default: Verbose : 1

Determine the modular degree of a rational elliptic curve \(E\). The algorithm used is described in [Watkins, 2002]. One computes the special value \(L(Sym^2 E,2)\) of the motivic symmetric-square \(L\)-function of the elliptic curve, and uses the formula

\[deg(\phi)=L(Sym^2 E,2)/(2*\Pi*\Omega)*(Nc^2)*E_p(2)\]

where \(\Omega\) is the area of the fundamental parallelogram of the curve, \(N\) is the conductor, \(c\) is the Manin constant, and \(E_p(2)\) is a product over primes whose square divides the conductor. The Manin constant is assumed to be \(1\) except in the cases described in [Stein and Watkins, n.d.], where it is conjectured that the optimal curves for parameterizations from \(X_1(N)\) and \(X_0(N)\) are different. A warning is given in these cases. The optimal curve for parameterizations from \(X_1(N)\) is assumed to be the curve in the isogeny class of \(E\) that has minimal Faltings height (maximal \(\Omega\)). The algorithm is based upon a sequence of real-number approximations converging to an integer — the use of verbose printing for ModularDegree allows the user to see the sequence of approximations.

Example: Mod Deg (ex-d0adbe)#

First we define a space of ModularForms.

> M:=ModularForms(Gamma0(389),2);

Run in calculator

The first of the newforms associated to M corresponds to an elliptic curve.

> f := Newform(M,1); f;
q - 2*q^2 - 2*q^3 + 2*q^4 - 3*q^5 + 4*q^6 - 5*q^7 + q^9 + 6*q^10 - 4*q^11 +
O(q^12)
> E := EllipticCurve(f); E;
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

Run in calculator

We can compute the modular degree of this using modular symbols.

> time ModularDegree(ModularSymbols(f));
40
Time: 0.200

Run in calculator

Or via the algorithm based on elliptic curves.

> time ModularDegree(E);
40
Time: 0.000

Run in calculator

The elliptic curve algorithm is capable of handling examples of high level, particularly when bad primes have multiplicative reduction.

> E := EllipticCurve([0,0,0,0,-(10^4+9)]);
> Conductor(E);
14425931664
> time ModularDegree(E);
6035544576
Time: 3.100

Run in calculator

Integral and \(S\)-integral Points#

Let \(E\) be an elliptic curve defined over the rational numbers \({\mathbb{Q}}\) and denote by \(S=\{p_1,\dots, p_{s-1},\infty\}\) a finite set of primes containing the prime at infinity. There are only finitely many \(S\)-integral points on \(E\). (That is, points where the denominators of the coordinates are only supported by primes in \(S\).) Note that the point at infinity on \(E\) is never returned, since it is supported at every prime.

The following algorithms use the technique of linear forms in complex and \(p\)-adic elliptic logarithms. They were initially implemented by Emmanuel Hermann in the late 90s, and then Steve Donnelly made various improvements. The main theoretical reference is Stroeker and Tzanakis [Stroeker and Tzanakis, 1994], and Tzanakis [Stroeker and T., 1996] for the case of a quartic equation.

The main routine here is (S)IntegralPoints for an elliptic curves. The functions listed afterwards, for determining integral points on various other kinds of genus one curves, are applications of the main routine.

IntegralPoints(E): CrvEll[FldRat] -> [ PtEll ]#
FBasis      : [ PtEll ]                    Default: 
SafetyFactor: RngIntElt                    Default: 1

Given an elliptic curve \(E\) over \({\mathbb{Q}}\), having integral coefficients, this returns a sequence containing all the integral points on \(E\), up to sign (only one of \(P\) and \(-P\) is listed).

The algorithm involves first computing generators of the Mordell–Weil group, using the tools available in Magma for this. Alternatively, the user may precompute generators and pass them to IntegralPoints as the optional parameter FBasis. This should be a sequence of points on \(E\) that are independent modulo torsion (for instance, as returned by ReducedBasis). IntegralPoints will then find all integral points on \(E\) that are in the group generated by FBasis and torsion.

If the optional argument SafetyFactor is specified, the search phase at the final step is extended as a safety check. (The number of points checked is increased by approximately this factor, which must be at least 1.)

SIntegralPoints(E, S): CrvEll, SeqEnum -> [ PtEll ]#
FBasis      : [ PtEll ]                    Default: 
SafetyFactor: RngIntElt                    Default: 1

Given an elliptic curve \(E\) over the rationals and a set \(S\) of finite primes, returns the sequence of all \(S\)-integral points, up to sign (only one of \(P\) and \(-P\) is listed).

The optional parameters FBasis and SafetyFactor have the same meaning as in IntegralPoints.

Example: Integral Points (ex-5cfac6)#

We find all integral points on a certain elliptic curve:

> E := EllipticCurve([0, 17]);
> Q, reps := IntegralPoints(E);
> Q;
[ (-2 : -3 : 1), (8 : 23 : 1), (43 : -282 : 1), (4 : 9 : 1),
(2 : -5 : 1), (-1 : 4 : 1), (52 : -375 : 1), (5234 : 378661 : 1) ]
> reps;
[
    [ <(-2 : -3 : 1), 1> ],
    [ <(-2 : -3 : 1), 2> ],
    [ <(-2 : -3 : 1), 1>, <(4 : -9 : 1), -2> ],
    [ <(4 : -9 : 1), -1> ],
    [ <(-2 : -3 : 1), 1>, <(4 : -9 : 1), -1> ],
    [ <(-2 : -3 : 1), 1>, <(4 : -9 : 1), 1> ],
    [ <(-2 : -3 : 1), 2>, <(4 : -9 : 1), 1> ],
    [ <(-2 : -3 : 1), 1>, <(4 : -9 : 1), 3> ]
]

Run in calculator

We see here that the chosen basis consists of the points \((-2 : -3 : 1)\) and \((4 : -9 : 1)\), and that coefficients which are zero are omitted.

Example: S Integral Points (ex-406509)#

We find all S-integral points on an elliptic curve of rank 2, for the set of primes \(S = \{2,3,5,7\}\).

> E := EllipticCurve([-228, 848]);
> Q := SIntegralPoints(E, [2, 3, 5, 7]);
> for P in Q do P; end for;    // Print one per line
(4 : 0 : 1)
(-11 : 45 : 1)
(16 : 36 : 1)
(97/4 : -783/8 : 1)
(-44/9 : -1160/27 : 1)
(857/4 : -25027/8 : 1)
(6361/400 : -282141/8000 : 1)
(534256 : -390502764 : 1)
(946/49 : -20700/343 : 1)
(-194/25 : -5796/125 : 1)
(34/9 : 172/27 : 1)
(814 : 23220 : 1)
(13 : 9 : 1)
(-16 : 20 : 1)
(1/4 : -225/8 : 1)
(52 : -360 : 1)
(53 : 371 : 1)
(16/49 : 9540/343 : 1)
(-16439/1024 : -631035/32768 : 1)
(34 : 180 : 1)
(-2 : 36 : 1)
(-14 : -36 : 1)
(14 : -20 : 1)
(754 : -20700 : 1)
(94/25 : -828/125 : 1)
(2 : 20 : 1)
(94 : 900 : 1)
(-818/49 : 468/343 : 1)
(49/16 : -855/64 : 1)
(196 : -2736 : 1)
(629/25 : 13133/125 : 1)
(1534/81 : -42020/729 : 1)
(8516/117649 : -1163623840/40353607 : 1)

Run in calculator

IntegralQuarticPoints(Q): [ RngIntElt ] -> [ SeqEnum ]#

If \(Q\) is a sequence of five integers \([a,b,c,d,e]\) where \(e\) is a square, this function returns all integral points (modulo negation) on the curve \(y^2=ax^4+bx^3+cx^2+dx+e\).

IntegralQuarticPoints(Q, P): [ RngIntElt ], [ RngIntElt ] -> [ SeqEnum ]#

If \(Q\) is a list of five integers \([a,b,c,d,e]\) defining the hyperelliptic quartic \(y^2=ax^4+bx^3+cx^2+dx+e\) and \(P\) is a sequence representing a rational point \([x, y]\), this function returns all integral points on \(Q\).

SIntegralQuarticPoints(Q, S): [ RngIntElt ], [ RngIntElt ] -> [ SeqEnum ]#

Given a sequence of integers \(Q = [a,b,c,d,e]\) where \(a\) is a square, this function returns all \(S\)-integral points on the quartic curve \(y^2 = ax^4 + bx^3 + cx^2 + dx + e\) for the set \(S\) of finite primes.

Example: Integral Points Sequence (ex-8d65c5)#

We find all integral points (modulo negation) on the curve \(y^2 = x^4 - 8x^2 + 8x + 1\). Since the constant term is a square we can use the first form and do not have to provide a point as well.

> IntegralQuarticPoints([1, 0, -8, 8, 1]);
[
    [ 2, -1 ],
    [ -6, 31 ],
    [ 0, 1 ]
]

Run in calculator

SIntegralLjunggrenPoints(Q, S): [ RngIntElt ], [ RngIntElt ] -> [ SeqEnum ]#

Given a sequence of integers \(Q = [a,b,c,d]\), this function returns all \(S\)-integral points on the curve \(C: ay^2 = bx^4 + cx^2 + d\) for the set \(S\) of finite primes, provided that \(C\) is nonsingular.

SIntegralDesbovesPoints(Q, S): [ RngIntElt ], [ RngIntElt ] -> [ SeqEnum ]#

Given a sequence of integers \(Q = [a,b,c,d]\), this function returns all \(S\)-integral points on \(C: ay^3+bx^3+cxy+d=0\) for the set \(S\) of finite primes, provided that \(C\) is nonsingular.

Example: Desboves (ex-1bb564)#

We find the points supported by \([2, 3, 5, 7]\) on the curve \(9y^3 + 2x^3 + xy + 8 = 0\).

> S := [2, 3, 5, 7];
> SIntegralDesbovesPoints([9, 2, 1, 8], S);
[
    [ 1, -1 ],
    [ -94/7, 172/21 ],
    [ -11/7, 2/7 ],
    [ 5, -3 ],
    [ 2, -4/3 ],
    [ 2/7, -20/21 ],
    [ -8/5, -2/15 ]
]

Run in calculator

Elliptic Curve Database#

Magma includes John Cremona’s database of all elliptic curves over \({\mathbb{Q}}\) of small conductor (up to \(499\,999\) as of September 2019). This section defines the interface to that database.

For each conductor in the range stored in the database the curves with that conductor are stored in a number of isogeny classes. Each curve in an isogeny class is isogenous (but not isomorphic) to the other curves in that class. Isogeny classes are referred to by number rather than the alphabetic form given in the Cremona tables.

All of the stored curves are global minimal models.

EllipticCurveDatabase(: parameters) -> DB#
CremonaDatabase(: parameters) -> DB#
BufferSize: RngIntElt                    Default: 10000

This function returns a database object which contains information about the elliptic curve database and is used in the functions which access it. The optional parameter BufferSize controls the size of an internal buffer — see the description of SetBufferSize for more information.

SetBufferSize(D, n): DB, RngIntElt#

The elliptic curve database \(D\) uses an internal buffer to cache disk reads; if the buffer is large enough then the entire file can be cached and will not need to be read from the disk more than once. On the other hand, if only a few curves will be accessed then a large buffer is not especially useful. SetBufferSize can be used to set the size \(n\) (in bytes) of this buffer. There are well defined useful minimum and maximum sizes for this buffer, and values outside this range will be treated as the nearest useful value.

LargestConductor(D): DB -> RngIntElt#

Returns the largest conductor of any elliptic curve stored in the database. It is an error to attempt to refer to larger conductors in the database.

ConductorRange(D): DB -> RngIntElt, RngIntElt#

Returns the smallest and largest conductors stored in the database. It is an error to attempt to refer to conductors outside of this range.

# D: DB -> RngIntElt#
NumberOfCurves(D): DB -> RngIntElt#

Returns the number of elliptic curves stored in the database.

NumberOfCurves(D, N): DB, RngIntElt -> RngIntElt#

Returns the number of elliptic curves stored in the database for conductor \(N\).

NumberOfCurves(D, N, i): DB, RngIntElt, RngIntElt -> RngIntElt#

Returns the number of elliptic curves stored in the database in the \(i\)-th isogeny class for conductor \(N\).

NumberOfIsogenyClasses(D, N): DB, RngIntElt -> RngIntElt#

Returns the number of isogeny classes stored in the database for conductor \(N\).

EllipticCurve(D, N, I, J): DB, RngIntElt, RngIntElt, RngIntElt -> CrvEll#
EllipticCurve(D, N, S, J): DB, RngIntElt, MonStgElt, RngIntElt -> CrvEll#

Returns the \(J\)-th elliptic curve of the \(I\)-th isogeny class of conductor \(N\) from the database. \(I\) may be specified either as an integer (first form) or as a label like "A" (second form).

EllipticCurve(D, S): DB, MonStgElt -> CrvEll#
EllipticCurve(S): MonStgElt -> CrvEll#

Returns a representative elliptic curve with label \(S\) (e.g., "101a" or "101a1") from the specified database (or if not specified, from the Cremona database).

Random(D): DB -> CrvEll#

Returns a random curve from the database.

CremonaReference(D, E): DB, CrvEll -> MonStgElt#
CremonaReference(E): CrvEll -> MonStgElt#

Returns the database reference to the minimal model for \(E\) (e.g., "101a1"). \(E\) must be defined over \({\mathbb{Q}}\) and its conductor must lie within the range of the database. The second form of this function must open the database for each call, so if it is being used many times the database should be created once and the first form used instead.

Example: ecdb1 (ex-d41275)#
> D := CremonaDatabase();
> #D;
3064705
> minC, maxC := ConductorRange(D);
> minC, maxC;
1 499999
> &+[ NumberOfCurves(D, C) : C in [ minC .. maxC ] ];
3064705

Run in calculator

The conductor in that range with the most curves is 369600.

> S := [ NumberOfCurves(D, C) : C in [ minC .. maxC ] ];
> cond := maxval + minC - 1 where _,maxval := Max(S);
> cond;
369600
> NumberOfCurves(D, cond);
1386
> NumberOfIsogenyClasses(D, cond);
612

Run in calculator

The unique curve of conductor 5077 has rank 3.

> NumberOfCurves(D, 5077);
1
> E := EllipticCurve(D, 5077, 1, 1);
> E;
Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
> CremonaReference(D, E);
5077a1
> Rank(E);
3

Run in calculator

EllipticCurves(D, N, I): DB, RngIntElt, RngIntElt -> [ CrvEll ]#
EllipticCurves(D, N, S): DB, RngIntElt, MonStgElt -> [ CrvEll ]#

Returns the sequence of elliptic curves in the \(I\)-th isogeny class for conductor \(N\) from the database. \(I\) may be specified either as an integer (first form) or as a label like "A" (second form).

EllipticCurves(D, N): DB, RngIntElt -> [ CrvEll ]#

The sequence of elliptic curves for conductor \(N\) from the database.

EllipticCurves(D, S): DB, MonStgElt -> [ CrvEll ]#

The sequence of elliptic curves with label \(S\) from the database. \(S\) may specify just a conductor (like "101"), or both a conductor and an isogeny class (like "101A").

EllipticCurves(D): DB -> [ CrvEll ]#

The sequence of elliptic curves stored in the database. Note: this function is extremely slow due to the number of curves involved. Where possible it would be much better to iterate through the database instead (see example).

Example: ecdb2 (ex-850f6b)#

Here are two ways to iterate through the database:

> D := CremonaDatabase();
> &+[ Discriminant(E) : E in D ];
-794859469677543528151728699560961881672278939536
> sum := 0;
> for E in D do sum +:= Discriminant(E); end for;
> sum;
-794859469677543528151728699560961881672278939536

Run in calculator

Now we choose a random curve from the database, and look up the other curves in the same isogeny class. (Note: when this input is entered, the random curve will probably be different to the example shown here!)

> E := Random(D);
> E;
Elliptic Curve defined by y^2 = x^3 - 225*x over Rational Field
> r := CremonaReference(E);
> r;
7200bg1
// remove the numeric characters from the end of the string r
> while r[#r] in "0123456789" do Prune(~r); end while;
> r;
7200bg
> EllipticCurves(D, r);
[
    Elliptic Curve defined by y^2 = x^3 - 225*x over Rational Field,
    Elliptic Curve defined by y^2 = x^3 - 2475*x - 47250 over Rational Field,
    Elliptic Curve defined by y^2 = x^3 - 2475*x + 47250 over Rational Field,
    Elliptic Curve defined by y^2 = x^3 + 900*x over Rational Field
]
> E in $1;
true

Run in calculator