A Pari/GP Tutorial: by Robert B. Ash, Jan. 2007
A Pari/GP Tutorial: by Robert B. Ash, Jan. 2007
A Pari/GP Tutorial
by Robert B. Ash, Jan. 2007
The Pari/GP home page is located at http://pari.math.u-bordeaux.fr/
1. Pari Types
There are 15 types of elements (numbers, polynomials, matrices etc.) recognized by
Pari/GP (henceforth abbreviated GP). They are listed below, along with instructions on
how to create an element of the given type. After typing an instruction, hit return to
execute. A semicolon at the end of an instruction suppresses the output. To activate the
program, type gp, and to quit, type quit or \q
1. Integers
Type the relevant integer, with a plus or minus sign if desired.
2. Rational Numbers
Type a rational number as a fraction a/b, with a and b integers.
3. Real Numbers
Type the number with a decimal point to make sure that it is a real number rather than an
integer or a rational number. Alternatively, use scientific notation, for example, 8.46E17
The default precision is 28 significant digits. To change the precision, for example to 32
digits, type \p 32.
4. Complex Numbers
Type a complex number as a + b ∗ I or a + I ∗ b, where a and b are real numbers, rational
numbers or integers.
5. Integers Modulo n
To enter n mod m, type Mod(n, m).
6. Polynomials
Type a polynomial in the usual way, but don’t forget that ∗ must be used for multiplica-
tion. For example, type xˆ3 + 3*xˆ2 -1/7*x +8.
7. Rational Functions
Type a ratio P/Q of polynomials P and Q.
8. Polynomials Modulo a Polynomial P
To enter Q mod P , type Mod(Q, P ).
9. Vectors
Type a row vector as, for example, [1,2,3], and a column vector as [1,2,3]˜. The i-th
component of a vector v can be recovered via v[i].
10. Matrices
Separate components by commas, lines by semicolons. Thus [1, 2, 3; 4, 5, 6] gives the matrix
1 2 3
.
4 5 6
2
To recover the ij element of a matrix A, type A[i, j]. The i-th row is A[i, ] and the j-th
column is A[, j].
11. Lists
L=listcreate(4) creates an empty list of (maximum) length 4. Then listput(L, a, 1) sets
the first entry of L to a. Similarly, after listput(L, b, 2), listput(L, c, 3), and listput(L, d, 4),
we have L = [a, b, c, d]. To recover the third entry, type L[3], just as with a row vector.
12. Strings
A string is any sequence of symbols. It is identified by enclosing it in quotation marks.
For example, s = “The following sequence is exact”.
13. Power Series and Laurent Series with Finitely Many Negative Powers
We can truncate the series at any point. For example,
4 ∗ z3 + 3 ∗ z2 + 2 ∗ z + 1
+ O(z 2 )
z2
will produce the output
z −2 + 2 ∗ z −1 + 3 + 4 ∗ z + O(z 2 )
GP will stop computing a Taylor or Laurent series at O(x16 ). To change the series
precision to something else, type, for example, \ps 19
14. p-adic Numbers
The syntax is similar to #13. For example, 905/7 + O(73 ) will produce output
2 ∗ 7−1 + 3 + 4 ∗ 7 + 2 ∗ 72 + O(73 )
We can find the expansion of any integer in any base. For example, to find the base 6
expansion of 86, type 86 + O(63 ) (or 86 + O(6r ), r > 3), to get 2 + 2 ∗ 6 + 2 ∗ 62 + O(63 ).
Replacing O(63 ) by O(62 ) will truncate the expansion.
15. Quadratic Numbers (Elements of a Quadratic Number Field)
√
If the number field is Q( m), then there is a canonical √ integral
√ basis (1, w), as follows.
If the discriminant d is congruent to 0√mod 4, then w√= m = d/2 and d = 4m. If d is
congruent to 1 mod 4, then w = (1 + m)/2 = (1 + d)/2 and d = m. Therefore m ≡ 1
mod 4, so the first case corresponds to m ≡ 1 mod 4. This allows a quadratic number
field to be identified by its discriminant d, and this is what GP does via the instruction
w = quadgen(d). You might as well use w in this instruction, because GP will change
anything you write to w. The general element of the quadratic number field is written as
x + y ∗ w with x and y integers.
Some general advice
It is very convenient to name objects. If you are working with the polynomial x2 +
3 ∗ x + 4, type f=xˆ2+3*x+4, and then you can use f in any computation.
Creating functions is easy. Type f (x) = x2 + 3 ∗ x + 4, and then f (2) will return
4+6+4=14. Similarly for functions of several variables.
There are some reserved symbols that cannot be used as variable names. They include
I (the square root of -1), Pi (3.14159...), and O (big oh). Also, if you create a function
called g, you cannot use g as a variable name.
3
Several expressions can be combined on a single line by separating them with semi-
colons.
Typing # activates a toggle switch that turns the timer on and off. Typing ## prints
the time taken by the latest computation.
To redefine a variable s, first type kill(s). To kill a function f , kill all of its variables
and then type kill (f ).
Outputs are numbered %1,%2,... It is quite legal in a computation to use %n as
an abbreviation for the n-th output. Also, % with no number attached refers to the
immediately preceding output.
To display an output, use the print command. For example, if x = 3, the command
print(2 ∗ x + 1) will display the answer 7. If you want to call the output y, type
print(”y = ”, 2 ∗ x + 1). Then y = 7 will be displayed.
The Boolean comparison operators are
< less than
> greater than
<= less than or equal to
>= greater than or equal to
== equal
!= unequal
3. Arithmetic Functions
We now begin to do number theory. As an interesting example , we look at the problem of
expressing an integer in binary and other bases. (Also see the discussion of p-adic numbers
in Section 1.) Binary expansions are nice; if x is an integer, just type binary(x). For
example, b = binary(142) yields [1,0,0,0,1,1,1,0]. But what if we want base 4? Here is a
“workaround”. Type c = 142 + O(4k ) where any k ≥ 4 will do (we must have 4k ≥ 142).
The output is 2 + 3 ∗ 4 + 2 ∗ 43 + O(4k ), which displays the desired base 4 expansion.
Converting from base 4 back to decimal is accomplished via d=truncate(c), which chops
away the O(4k ) and sums the series to get 142.
Let’s do a very quick refresher on continued fractions. The Euclidean algorithm for
dividing 41 by 18 looks like this:
41 = 2 × 18 + 5
18 = 3 × 5 + 3
5=1×3+2
3=1×2+1
2=2×1+0
The corresponding continued fraction expansion is obtained from the column immediately
to the right of the equals sign, traversed from top to bottom. We have
41 1
=2+
18 3 + 1+ 1 1
1+ 1
2
which is abbreviated
1 1 1 1
2+
3+ 1+ 1+ 2
or [2,3,1,1,2]. Note that division of 18 by 41 begins with 18 = 0 × 41 + 18 and then
proceeds as above. Thus 18/41 = [0, 2, 3, 1, 1, 2].
If x = 41/18, the command contfrac(x) gives the continued fraction expansion of x,
namely [2, 3, 1, 1, 2].
If x = [a0 , a1 , . . . , an ] is a finite continued fraction, the convergents pi /qi , 0 ≤ i ≤ n, of
x are the successive continued fractions [a0 ], [a0 , a1 ], . . . , [a0 , . . . , an ]. The pi and qi can
be computed recursively by
The sequence under the overbar repeats periodically, so the complete expansion is
√
21 = [4, 1, 1, 2, 1, 1, 8, 1, 1, 2, 1, 1, 8, 1, 1, 2, 1, 1, 8, . . . ]
where the segment a1 , . . . , an is symmetrical about its midpoint. If n is odd, then the
n-th convergent gives a minimal solution of Pell’s equation. In our case, n = 5 and the
command contfracpnqn([4,1,1,2,1,1]) returns pn /qn = 55/12. And indeed we have
Now consider
√
29 = 5; 2, 1, 1, 2, 10
log 1 = 0, log 2 = 14, log 3 = 1, log 4 = 12, log 5 = 5, log 6 = 15, log 7 = 11, log 8 = 10,
9
The degree of f is 2 and the degree of g is 3, and there are 3 columns occupied by the
coefficients of f and their shifts, and 2 columns occupied by the coefficients of g and their
shifts.
polroots(f ) returns a column vector whose components are the roots, each repeated
according to multiplicity. polroots(f,1) uses the Newton-Raphson algorithm, which is
faster but not guaranteed to converge.
polsym(f,s) returns a column vector givingn the power sums of the roots x1 , . . . , xn of f ,
up to the power s. The power sum tr is i=1 xri , with t0 = n.
poltchebi(n,v) gives the n-th Chebyshev polynomial with variable v (default is x).
subst(f,y,z) replaces y by z in f , where f is a polynomial, rational function or power
series.
taylor(f,x) computes the Taylor expansion of f , regarded as a function of x, around
x = 0.
5. Linear Algebra
lindep(x), where x is a vector with real or complex coefficients, finds a linear dependence
relation satisfied by the components of x. For example, lindep([1,2,3,4]) returns [0, 1−2, 1].
matadjoint(A) computes the adjoint of the square matrix A (as in Cramer’s rule).
matcompanion(f ) returns the left companion matrix of the polynomial f . For example,
if f = 7y 3 + 2y 2 + 3y + 4, then the output is
0 0 −4/7
1 0 −3/7
0 1 −2/7
mathnf(A) computes the upper triangular Hermite normal form. (Allowable operations
are interchange of columns and addition of a constant times one column to another col-
umn.)
matid(n) creates an n by n identity matrix.
matimage(A) finds a basis for the image (column space) of A.
Assume that matrices A and B have the same number of rows, and the columns of each
matrix are linearly independent. Then
matintersect(A,B) finds a basis for the intersection of the column spaces (over Q).
matinverseimage(A,b) computes A−1 b.
matisdiagonal(A) returns true iff A is a diagonal matrix.
matker(A) finds a matrix whose columns give a basis for the kernel (null space) of the
matrix A. If A is known to have integer entries, use matker(A,1).
matmuldiagonal(A,v) gives the same result as A∗matdiagonal(v), but is faster.
matmultodiagonal(A,B) gives the diagonal entries of A ∗ B, with zeros elsewhere. It
is faster than A ∗ B if the product is known to be diagonal.
matrank(A) returns the rank of A.
matsize(A) gives the number of rows and columns of A.
matsnf(A) computes the Smith normal form of A.
matsolvemod(A,m,y) generalizes the Chinese remainder theorem. A is a matrix with
integer entries, m is a column vector of positive integer moduli, and
y is a column vector
with components in Z. The output is a “small” integer solution to j aij xj ≡ yi mod mi .
matsolvemod(A,m,y,1) returns, in addition to the column vector x just found, a matrix
whose columns are a basis for the homogeneous system Ax ≡ 0.
For example, consider the simultaneous equations x + y ≡ 0 mod 3, x + 2y ≡ 5
mod 7. Then A = [1, 1; 1, 2], m = [3, 7]˜, y = [0, 5]˜. The program returns the column
vector [1, 2]˜, indicating the solution x = 1, y = 2. If matsolvemod(A, m, y, 1) is used
(we say that the flag is set at 1), the output contains in addition the matrix [−21, 5; 0, 1].
Thus [−21, 0]˜ and [5, 1]˜ are a basis for x + y ≡ 0 mod 3, x + 2y ≡ 0 mod 7.
matsupplement(A) extends the columns of the matrix A (assumed linearly independent,
otherwise there will be an error message), to a basis for the entire space.
mattranspose(x) transposes a matrix or vector x.
qfgaussred(A) reduces the quadratic form associated with the symmetric matrix A to
a sum of squares. For example, let A = [1, 2, 3; 2, 4, 5; 3, 5, 6], with associated quadratic
form q = x2 + 4xy + 6xz + 4y 2 + 10yz + 6z 2 . The output is the matrix
1 2 3
B = 0 1/3 0
0 1/3 −3
The formula predicts what you might do in hand computation. Multiply out (x+2y+3z)2 ;
in order to get q, you need to add −3z 2 − 2yz. Complete the square to get −3(z + y/3)2 .
You still need y 2 /3, which is already in the desired form. The general formula is
q= bii (xi + bij xj )2 .
i j=i
The columns of this matrix are the eigenvectors, with column 1 associated with the
eigenvalue 8 and columns 2 and 3 with 2.
qfsign(A) is the signature of the quadratic form associated with the symmetric matrix A,
that is, the number of positive terms and the number of negative terms in the reduction
to a sum of squares. If A = 1, 2, 3; 2, 4, 5; 3, 5, 6], the matrix considered in connection with
the instruction qfgaussred(A), there are two positive terms and one negative term, and
the signature is [2, 1].
trace(A) is the sum of the diagonal entries of the square matrix A.
GP regards a set as a row vector with strictly increasing entries, but you must instruct
the program to convert a vector to a set. For example, if v = [5, 4, 3, 2, 1], type Set(v),
and the result will be displayed as [“1”, “2”, “3”, “4”, “5”]. If v contains repeated entries,
the repetition will be ignored. Several natural operations are available.
setisset(x) returns 1 (true) iff x is a set.
setintersect(x,y) is x ∩ y.
setminus(x,y) is x \ y.
setsearch(x,y) returns j if y occupies position j of the set x. If y ∈
/ x, the output is 0.
setunion(x,y) is x ∪ y.
vecsort(v) sorts the vector v in ascending order.
For example, to integrate e1/x from 1 to 2, type intnum(x = 1, 2, exp(1/x)). The result is
2.0200586244...
b
prod(x=a,b,f(x),j) computes x=a f (x). If the flag j is 1 or omitted, the computation
is done exactly. If j = 1., the computation uses real numbers with the default precision
(28 significant figures). If j = 1 + O(xk ), the computation uses power series with precision
at most k.
100 100
For example, i=1 (1 − xi ) is a polynomial of degree i=1 i = 5050. If we type the
instruction prod(i = 1, 100, 1 − xˆi, 1 + O(xˆ101)), the output will display the polynomial
up to the term of degree 100, namely
1 − x − x2 + x5 + x7 − x12 − x15 + x22 + x26 − x35 − x40 + x51 + x57 − x70 − x77 + x92
+x100 + O(x101 ).
prodeuler(x=a,b,f(x)) computes the product of f (x) as x ranges over all primes p such
that a ≤ p ≤ b.
∞
prodinf(x=a,f(x)) computes x=a f (x).
∞
prodinf(x=a,f(x),1) computes x=a (1 + f (x)).
solve(x=a,b,f(x)) finds a real root of f (x) between a and b, assuming f (a) ∗ f (b) ≤ 0.
b
sum(x=a,b,f(x),j) computes x=a f (x). See prod for syntax, with 1 replaced by 0
in the setting of the flag j. For example, the instruction sum(i = 1, 5000, 1/i) yields a
rational number with a huge numerator and denominator, but sum(i = 1, 5000, 1/i, 0.)
results in a much faster computation and the comprehensible result 9.094508852984. . . .
A tricky point: sum(i = 1, 5000, 1/i, 1.) will compute with real numbers, but will add 1
to the original sum to get 10.094508852984 . . . . Similarly, replacing j = 1. in prod by
j = 2. will multiply the original product by 2.
∞
sumalt(x=a,f(x)) computes x=a f (x), where the series is alternating.
sumdiv(n,x,f(x)) sums f (x) over all positive divisors of n. Note that sumdiv(n, x, xk )
is the same as sigma(x, k), but computation of sigma(x, k) is much faster because it takes
advantage of the multiplicativity of xk .
∞
suminf(x=a,f(x)) computes x=a f (x).
7. Basic Programming
for(x=a,b,seq) evaluates seq from x = a to x = b in increments of 1, where a and b are
real numbers. (If a > b, the program does nothing.) Note that the local variable x cannot
be used to define a function inside the for loop. Functions should be defined before the
loop is entered, as in the example below.
f (x) = x + 1
g(x) = x2
for(n = 1, 5, print(f (n) + g(n))
The output is 3,7,13,21,31. (f (4) + g(4) = 5 + 16 = 21, etc.)
14
fordiv(n,x,seq) evaluates seq as x goes through all positive divisors of the integer n.
With f and g as above,
fordiv(12, x, print(f (x) + g(x)))
yields the output 3,7,13,21,43,157, corresponding to the divisors 1,2,3,4,6 and 12.
forprime(x=a,b,seq) evaluates seq as x goes through all primes p such that a ≤ x ≤ b.
At the end of each iteration, x is incremented to the next higher prime, so the last term
evaluated is the largest prime less than or equal to b.
forstep(x=a,b,s,seq) evaluates seq as x goes from a to b in increments of s, where s is
a nonzero real number, possibly negative.
forvec(w=v,seq) can be used to implement multiple for loops. Here is a sample program
with annotations.
w = [x, y] %w is a vector of variables
v = [[1, 3], [1, 4]]% v is a vector indicating the range of the variables, namely
1 ≤ x ≤ 3, 1 ≤ y ≤ 4.
forvec(w = v, print(w[1] + 2 ∗ w[2]))
% We are evaluating x + 2y for x and y in the given range. Variables farther to the right
move first, so y moves before x. Thus the output is 1 + 2 ∗ 1 = 3, 1 + 2 ∗ 2 = 5, 1 + 2 ∗ 3 =
7, 1+2∗4 = 9, 2+2∗1 = 4, 2+2∗2 = 6, etc. The entire sequence is 3,5,7,9,4,6,8,10,5,7,9,11.
if(a,seq) evaluates seq if the Boolean variable a is not zero, otherwise does nothing.
if(a,,seq) (note the two commas) evaluates seq if a = 0, and otherwise does nothing. An
equivalent command is if(!a,seq). (The exclamation mark indicates “not”.)
if(a,seq1,seq2) evaluates seq1 if a = 0, else evaluates seq2.
If we want to test whether a statement a = b is true or false, we write the statement
as a==b.
As an example, we will find integer solutions to f (x, y) = x3 − y 2 − 2 = 0 for x and y
between 0 and 100. Assuming that f has already been defined, a program is
w = [x, y]
v = [[1, 100], [1, 100]]
forvec(w = v, if(f (w[1], w[2]) == 0, print(“x = ”, w[1], “y = ”, w[2])))
The output is x = 3, y = 5. With x and y arbitrary integers, it can be shown that the
only solutions are (3, ±5).
If you want to type the print instruction on a new line without triggering an error
message, enclose the entire loop in braces, i.e. {forvec(...,print(...))}.
The same computation can be implemented via two for loops:
for(x = 1, 100, for(y = 1, 100, if(f (x, y) == 0 ,print(“x = ”, x, “y = ”, y))))
Here is a simple example illustrating how to name a procedure.
mult(f, g) = f ∗ g
f = x2
g = x3
mult(f, g)
//The output is x5
15
where x is a root of f .
nfdisc(f ) finds the field discriminant 18981.
The representation of ideals is tricky. Suppose f = x5 − 3 and F = nfinit(f ) creates
the number field defined by f . nfbasis(f ) yields the integral basis 1, x, x2 , x3 , x4 . Let
g = 1 + x + x2 . Then g generates a principal ideal in the ring of algebraic integers. The
command
idealhnf(F,g) gives a Z-basis for this ideal, not a basis of algebraic integers (hnf stands
for Hermite normal form). The result is the 5 by 5 matrix
13 4 10 12 4
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
The generators are 13w1 , 4w1 + w2 , 10w1 + w3 , 12w1 + w4 , and 4w1 + w5 , where the wi are
components of the integral basis just found. The instruction idealhnf(F,g,h) will give a
Z-basis for the ideal generated by g and h, but the program will not accept more than two
generators. (An ideal in a Dedekind domain can be generated by at most two elements.)
We now consider factoring of prime ideals in extensions. Let F be the number field
defined by the monic irreducible polynomial f (x) = x3 + 10 ∗ x + 1.
idealprimedec(F,2) factors (2) in the ring of algebraic integers of F . The output is
[[2,[1,1,0]˜,1,1,[1,1,1]˜,[2,[1,1,1]]˜,1,2], [1,1,0]˜]]]. The first factor is (2, 1 + x) (coefficients
are on an integral basis, in this case 1, x, x2 ). The ramification index and residue class
degree are e = 1 and f = 1. The term [1,1,1]˜ can be ignored. The second factor is
(2, 1 + x + x2 ) with e = 1 and f = 2.
Similarly, the command idealprimedec(F, 13) yields, ignoring the last term of the out-
put, [[13,[13,0,0]˜,1,3]]. Thus (13) remains prime, with e = 1 and f = 3. The command
factormod (f, 13) confirms that f is irreducible over F13 .
Here are some other useful commands.
polred(f ) finds polynomials with “reasonably small” coefficients defining subfields of the
number field defined by f .
idealinv(F,i) computes the inverse of the ideal i in the number field F .
ideallist(F,B) lists all ideals of norm n, n = 1, 2, . . . , B.
idealnorm(F,i) computes the norm of the ideal i in the number field F .
idealpow(F,i,k) computes the k-th power of the ideal i in the number field F .
idealprincipal(F,a) creates the principal ideal generated by the algebraic number a in
the number field F .
bnfisprincipal(F,i) tests whether the ideal i is principal (this holds iff the first compo-
nent of the output is zero).
idealval(F,i,P) gives the valuation of the ideal i at the prime ideal P .
nfeltval(F,x,P) gives the valuation of the ideal (x) at the prime ideal P .
F.diff gives a Z-basis for the different of the number field F (components with respect
to an integral basis).
nfalgtobasis(F,a) converts the expression for the algebraic integer a in the number field
F in terms of algebraic numbers to an expression in terms of an integral basis.
nfbasistoalg(F,a)
√ √is the inverse of nfalgtobasis. For example, in the number field
Q( 13), with x = 13, nfalgtobasis
√ will convert x to [-1,2]˜.√Since the
√ integral basis
consists of 1 and 1/2 + 1/2 ∗ 13, we get −1 + 2 ∗ (1/2 + 1/2 ∗ 13) = 13. The inverse
operation will convert the vector [-1,2]˜ to x, represented as Mod(x, x2 − 13).
nfrootsof1(F) will find the number t of roots of unity in the number field F , and a
primitive t-th root of unity, expressed in terms of an integral basis.
nffactor(F,g) factors the polynomial g over the number field F . Use y for the variable
of the defining polynomial f , and x as the variable of g (x has higher priority than y).
nfroots(F,g) finds the roots of g in the number field F , with the same variable-naming
convention as in nffactor.
nffactormod(F,g,P) factors g mod the prime ideal P , with the same variable-naming
convention as above.
nfsubfields(F,d) finds all subfields of F of degree d. If d is omitted,
nfsubfields(F) finds all subfields of F .
Additional Number Field Ideas (Thanks to Darrin Doud)
If an ideal i is principal, the second component of bnfisprincipal(F,i) will provide a
generator. In general, idealtwoelt(F,i) will give two generators of i as OF -module. If
one of the generators is 0, the ideal is principal. An example:
19
f = x3 + 10x + 1
F = bnfinit(f );
i = idealhnf(F, 2, 1 + x)//[2,1,1;0,1,0;0,0,1]
idealtwoelt(F, i)//[2,[1,1,0]˜]. The generators are 2 and 1 + x, as expected.
polcompositum(f,g) produces a list of polynomials defining a number field Q(a, b),
where a is a root of f and b is a root of g. The list may contain more than one member
because of relations between the roots. For example, let f = g = x3 − 3. There are
two polynomials on the list, and the first defines Q(a, a) = Q(a). The second defines
Q(a, b), Q(a, c), or Q(b, c). (These three fields are isomorphic.) To (possibly) simplify
one of these polynomials h, type polredabs(h).
We have seen that in the finite field GF(32 ), the polynomial x2 + 1 is irreducible but
not primitive. Here is a general script that will find a primitive polynomial. The algorithm
successively eliminates elements whose order properly divides pn − 1.
primpoly(p, n, w, s, f ) = f = wp −1) − 1; s = divisors(pn − 1); for(k = 1,length(s) − 1, f =
n
9. Elliptic Curves
An elliptic curve is represented in general Weierstrass form: y 2 +a1 xy +a3 y = x3 +a2 x2 +
a4 x + a6 .
E=ellinit([a1,a2,a3,a4,a6],1) creates an elliptic curve E with the given coefficients.
The short Weierstrass form has a1 = a2 = a3 = 0. If the flag (the “1” at the end of the
sequence) is 0 or omitted, the output of E will contain 19 quantities instead of 13. In par-
ticular, if the curve is defined over R, then E[14] will return the roots of the Weierstrass
equation. In both cases, the first 13 quantities are a1 , a2 , a3 , a4 , a6 , b2 , b4 , b6 , b8 , c4 , c6 , ∆
(the discriminant) and j (the j-invariant). The discriminant can be recovered by either
E[12] or E.disc, and the j-invariant by E[13] or E.j
elladd(E,z1,z2) adds the points z1 and z2 on the elliptic curve E, with addition ac-
cording to the group law. Points on the curve are represented by [x, y], with the point at
infinity represented by [0].
ellak(E,n) computes the coefficient an of the L-function of the elliptic curve E. If n is
not prime to the conductor, E must be in minimal Weierstrass form. If it isn’t, then first
use ellglobalred(E).
ellan(E,n) outputs a vector containing the first n coefficients of the L-function.
20
ellap(E,p), with p prime, computes ap , where the number of finite points in E(Fp ) is
p − ap . (Counting the point at infinity, we have p + 1 − ap .) For example,
E = ellinit([0, 0, 0, −4, 0]) creates the elliptic curve y 2 = x3 − 4x. Then ellap(E, 11) yields
output 0, so the number of finite points of E over F11 is 11. This can be checked by the
following program:
w = [x, y]
v = [[0, 10], [0, 10]]
forvec(w = v, if(Mod(w[1]3 − 4 ∗ w[1] − w[2]2 , 11) == 0, print(w)))
The 11 points are (0, 0), (2, 0), (3, ±2), (4, ±2), (6, ±4), (9, 0), (10, ±5).
To add the points (3,2) and (10,5), type elladd(E,Mod([3,2],11),Mod([10,5],11)). The
result is the point (2,0).
A change of coordinates that preserves Weierstrass form is given by x = u2 x + r, y =
u y + su2 x + t.
3
ellchangecurve(E,v), where v is the vector [u, r, s, t], gives the coefficients of the Wer-
erstrass equation in the new coordinate system.
ellchangepoint(x,v) gives the coordinates of the point x in the new system.
ellisoncurve(E,z) is true iff z is on E.
elllseries(E,s) returns the L-series of E at the real number s. Note that the command
has three consecutive l’s.
ellorder(E,z) gives the order of z if z is a torsion element, otherwise retuns 0.
ellordinate(E,x) finds y such that (x, y) is on E. If there is no such y, then the output
is [ ]. If there is exactly one y, the output is [y], and if there are two or more y’s, the
output produces two of them, in the form [y1, y2].
ellpow(E,z,n) computes nz, where z is on the curve E.
ellsub(E,z1,z2) finds z1 − z2, where z1 and z2 are points on E. To get the inverse of z,
take z1 = [0] and z2 = z.
elltors(E), where E is defined over Q, returns [t, v1, v2], where t is the order of the tor-
sion subgroup, v1 gives the structure of the torsion group as a product of cyclic groups,
sorted in increasing order, and v2 gives generators of the cyclic groups. For example,
E = ellinit([0, 0, 0, −1, 0]) creates the elliptic curve y 2 = x3 − x. Then elltors(E) outputs
[4, [2, 2], [[0, 0], [1, 0]]]. The torsion subgroup has order 4 and is isomorphic to the product
of two cyclic groups of order 2. Generators for the cyclic groups are [0,0] and [1,0].