In Sage, an elliptic curve is always specified by (the coefficient of) a long Weierstrass equation
\[y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.\]
So
EllipticCurve([a,b,c,d,e])
will yield
\[y^2 + a xy + c y = x^3 + b x^2 + d x + e.\]
E = EllipticCurve([1,2,3,4,5])
E
E = EllipticCurve([-2,2])
E
F = EllipticCurve([-2,1.1])
F
plot(E, xmax=5, ymin=-5, ymax=5, figsize=6, thickness=4) + plot(F, color='aqua', thickness=4)
For this curve, the number of rational solutions over \(\mathbb Z/ {p \mathbb Z}\) where the prime is \(5\) is \(9.\)
# The number of integer solutions modulus 5 is:
E.Np(5)
Emod5 = EllipticCurve(Zmod(5), [1,2,3,4,5])
Emod5.points()
From the Cremona index:
plot(EllipticCurve('37b2'))
E = EllipticCurve([2,5])
print(E)
Emod5 = EllipticCurve(Zmod(5), [2,5])
Emod5.points()
So we have the point \((0,0)\) as a solution because \(0^2\equiv_{(\text{mod} 5)} 0^3 + 2\times 0 +5.\) There are no other integer solutions.
The second point \((0:1:0)\) is just infinite.
Algebraically, this can be understood as homogeneous coordinates, in which initially there is a change of variables as to translate the \(x-y\) Cartesian plane where the curve is plotted to a plane translated \(1\) unit up along a newly introduced \(z\) axis so that the range of points on the plane are connected to the origin as a projection of a cone of lines emanating from the origin or “pencil of lines.” This is projective geometry.
This is explained in this lecture by Bill Shillito and in this video by NJ Wildberger.
After this transformation, if we imagine the points on any of these lines to be \([X, Y ,Z],\) the points of the curve on the translated plane would be \([\frac X Z, \frac Y Z, 1]\), which corresponds to scaling any of the lines connecting the origin to the points (\([X,Y,Z]\)) by \(Z\). This is called the projective plane \(\left(\mathbb P^2\right)\) and forms and equivalence relation where \((1,1,1)\equiv (2,2,2)\).
Notice the upper case of the new variables \(X, Y.\)
Plugging these back into the initial equation of an elliptic curve \(y^2 =x^3 - 2x +2\) would result in \(\left(\frac Y Z \right)^2 = \left(\frac X Z \right)^3 - 2 \left(\frac X Z \right) + 2.\)
To convert into the homogeneous expression, all the terms should be of the same degree, which is achieved by getting rid of the denominators as in \(( Y^2 Z) = (X)^3 - 2(X Z^2) + 2X^3\).
What is the advantage of homogeneous coordinates? The allow interpreting the points at infinity more readily:The points at infinity are not in the new plane at \(Z=1\), rather, \(Z=0.\)
Therefore we end up with \(Y^2 \, 0 = X^3.\) This means that \(X\) has to be zero, and \(Y\) can take any value. Hence \((0:1:0),\) as above. This is explained in here.
There are explanations about mapping the infinity plane to a sphere to visualize the point at infinity as in here, or here or here.
Imaging the curve on a unit sphere allows imagining the point at infinity as the North Pole, and the original plot as in here:
The equations for a unit sphere centered at \((0,0)\) are:
\[ \begin{align} \left(\frac{2x}{x^2 + y^2 + 1}, \frac{2y}{x^2 + y^2 + 1}, \frac{-1 + x^2 + y^2}{x^2 + y^2 + 1} \right) \end{align}\]
as in here.
It turns out that elliptic curves have a group structure with the addition operation defined as:
If P and Q are two points on the curve, then we can uniquely describe a third point P + Q in the following way. First, draw the line that intersects P and Q. This will generally intersect the cubic at a third point, R. We then take P + Q to be −R, the point opposite R.
Why reflect across the \(x\)-axis? So that the point at infinity \(\mathcal O\) is the identity element. Without reflection, \(\mathcal O + P = –P\) instead of \(\mathcal O + P = P.\)
The following visualization makes operations on points across the \(x\) axis understandable:
It is clear therefore, why \(P + Q + P = \mathcal O.\)
For modulo \(7\) it may be necessary to use an ad hoc function as in here because the curve is singular.
def points_mod(modulus):
i = 1
for x in range(modulus):
for y in range(modulus):
if (y^2 - (x^3 + 2*x + 5)) % modulus == 0:
print(f"{i}: (x, y) = ({x}, {y})")
i += 1
print(E.Np(7)) # 7 points
points_mod(7) # 6 points plus infinity
The difference between the number of solutions of an elliptic curve
over a finite field \(\mathbb F_p\) and
\(p-1\) is \(\epsilon_p,\) which is calculated as
E.ap().
What is a finite field?
A field \(\mathbb F_p\) is finite if it has \(p\) elements, such that \(p = q^r\), where \(q\) is prime. From Wikipedia:
If \(p = q^r\), all fields of order \(p\) are isomorphic. Moreover, a field cannot contain two different finite subfields with the same order. One may therefore identify all finite fields with the same order, and they are unambiguously denoted \(\mathbb{F}_{p}\) or \(\text{GF}(p)\), where the letters GF stand for “Galois field”.
The number of solutions to an elliptical curve on a finite field is related to the Legendre symbol by:
\[\vert E(\mathbb F_p) \vert= \sum_{x \in \mathbb F_p} 1 + \left (\frac{f(x)}{p} \right) + 1 = p + 1 + \left (\frac{f(x)}{p} \right)= p + 1 - a_p\]
The first \(1\) is because when the Legendre symbol is \(1,\) we have a square, and the negative of it, will also be a solution. If it is not a square it will cancel the \(-1\) from the Legendre symbol. The last \(1\) is the \(\mathcal O.\) The symbol \(a_p = - \left (\frac{f(x)}{p} \right).\)
The upper-bound of \(a_p\) (the cone the plots below) is given by \(2 \sqrt p\) and the lower bound by \(2 \sqrt p\) (Hasse-Weil bound).
ap_list = []
for i in primes_first_n(5000):
ap_list += [E.ap(i)]
import numpy
list_plot(numpy.array(ap_list), size=1, figsize=8)
What follows is a simple example illustrating Elliptic Curve Cryptography from a YT presentation by Robert Pierce.
From here:
In cryptography, an elliptic curve is a group which has a given size \(n\). We normally work in a subgroup of prime order \(r\), where \(r\) divides \(n\). The “cofactor” is \(h = n/r\).
The curve used below is \[y^2 = x^3 + 2x +2\]
over the field \(\mathbb Z/{p\mathbb Z}= \text{mod }(17).\)
And the cyclic subgroup used has the generating point \(G=(5,1).\)
F = Zmod(17)
E = EllipticCurve(F,[2,2])
print(E)
plot(E, figsize=8)
This group is of order
\[\vert E(\mathbb Z/ {p \mathbb Z}\vert=18\]
The cyclic group generated by the point \(G = (5,1)\) hits all the points in the curve and therefore it has order:
\[\text{ord}(G)= 18\]
with cofactor
\[h=\frac{\vert E(\mathbb Z/ {p \mathbb Z}\vert}{\text{ord {(G)}}}=1\]
plot(E, color='red', figsize=3) + points(((5,1), (6,3), (10,6), (3,1), (9,16), (16,13),
(0,6), (13,7), (7,6), (7,11), (13,10), (0,11),
(16,4), (9,1), (3,16), (10,11), (6,14), (5,16)), color='red', figsize=8)
Em = EllipticCurve(Zmod(2503), [3,7])
Em
plot(Em, figsize=8, size=1)
E = EllipticCurve(GF(11),[2,7])
print(E)
E.plot()
From this presentation, here is an exampe of the curve \[E: y^2 = x^3 + x + 1\] over \(\mathbb Q\) with two points we are going to add: \(P=(1,1)\) and \(Q=(2,3).\)
The line between \(P\) and \(Q\) is \(y = \frac{3 - 1}{2 - 1}x - 1 = 2x - 1.\)
Substituting this into the \(E\)
\[(2x-1)^2 = x^3 + x + 1\]
which can be foiled into
\[0 = (x-1)^2 (x-2)^2\]
which implies that the point \(P=(1,1)\) has multiplicity \(2\) because of \((x-1)^{\color{red}2}\). Therefore the third point of intersection between \(E\) and this line is thought of hitting \((1,1)\) twice.
Reflecting it over the \(x\)-axis, we get \((1,-1).\)
E = EllipticCurve([1,-1])
print(E)
Eplot = E.plot()
points = [(1,1),(2,3)]
Eplot += plot(2*x-1, (x,0,2.5), color='green')
Eplot += list_plot(points, color='red', pointsize=45)
P=E([1,1]); Q=E([2,3])
P+Q
Eplot + list_plot([(1,-1)],color='gold', pointsize=45)
E = EllipticCurve([-5,4])
print(E)
P = E([1,0]); Q = E(0,2) # Two points on the curve.
P + Q
P + P # This is the point to infinity
Mordell–Weil’s theorem shows \(E(\mathbb Q )\) is a finitely generated abelian group, thus \(\displaystyle E(\mathbb {Q} )\cong E(\mathbb {Q} )_{tors}\times \mathbb {Z} ^{r}\) where \(E(\mathbb {Q} )_{tors}\) is the finite torsion subgroup and \(r\) is the rank of the elliptic curve.
\[y^2 = x^3 -x\]
E = EllipticCurve([-1,0])
E
It’s group is isomorphic to \(\mathbb Z/2\mathbb Z \oplus \mathbb Z/2\mathbb Z\)
E.torsion_subgroup()
E.rank() # Rank 0: There are no points of infinite order, only finite order points
E.torsion_points()
2*E((-1 , 0 , 1))
4*E((0 , 0 , 1))
E((1 , 0 , 1)) + E((1 , 0 , 1))
| \[y^2 + y = x^3 - x\] |
sage E = EllipticCurve([0,0,1,-1,0]) E |
sage E.torsion_subgroup() |
sage E.rank() |
\(y^2 = x^3 − 5x + 4\)
E = EllipticCurve([-5,4])
E
E.torsion_subgroup()
E.torsion_points()
E.rank()
E.gens()
You can construct infinitely many points on E, by adding a torsion point and some multiple of the generator
P = E(1,0) + 9 * E(0,2)
P # P is on the curve. To check just run E(P)
E(P)
E.modular_form()
In the study of arithmetic geometry, the L-function of an elliptic curve \(E\) over \(\mathbb{Q}\) is a powerful complex-analytic tool that packages deep arithmetic information about the curve—specifically, the number of points it has over finite fields. The L-function acts as a bridge between the algebraic world of the curve and the analytic world of modular forms, a connection famously solidified by the modularity theorem.
On the algebraic side we look at the curve over \(\mathbb{F}_p\), find the Frobenius trace, and get the integer \(a_p\). All this will be explained below. On the analytic side we look at the modular form \(f(\tau)\), look at the \(p\)-th coefficient of its \(q\)-expansion, and find \(a_p\). The bridge to the analytic side is \(q = \exp(2 \pi i \tau)\). It allows us to turn a function of a complex variable \(\tau\) into a power series, known as a Fourier expansion or q-expansion:
\[f(\tau) = \sum_{n=1}^{\infty} a_n q^n\]
It is called “analytic” because once you express the curve’s data as a \(q\)-expansion, you can use the heavy machinery of complex analysis: 1. Analytic Continuation: You can define the L-function even where the sum doesn’t normally converge. 2. Functional Equations: You can prove the function has a perfect symmetry when you reflect it across a specific line (usually \(s=1\)). 3. The BSD Conjecture: You can use the “steepness” of this complex function at \(s=1\) to predict the rank of the elliptic curve (how many infinite points it has).
Let \(E\) be an elliptic curve defined over a finite field \(\mathbb{F}_p\). The Frobenius map \(\phi_p\) is a specific geometric transformation that takes a point \((x, y)\) on the curve and raises its coordinates to the \(p\)-th power:
\[\phi_p(x, y) = (x^p, y^p)\]
Because of the way finite fields work, and specifically Fermat’s Little Theorem, where
\[x^p \equiv x \pmod p\]
a point \(P\) known to be on the curve \(E\) is fixed by this map if and only if its coordinates are in the base field \(\mathbb{F}_p\), i.e. $x, y \(\mathbb{F}_p\) In other words:
\[P \in E(\mathbb{F}_p) \iff \phi_p(P) = P\]
This means that finding the number of points on \(E(\mathbb{F}_p)\) is equivalent to finding the number of fixed points of the Frobenius map.
Since \(\mathcal{O}\) doesn’t have standard \((x, y)\) coordinates (it’s a direction in projective space), we usually define \(\phi_p(\mathcal{O}) = \mathcal{O}\) by default. Thus, the equivalence \(P \in E(\mathbb{F}_p) \iff \phi_p(P) = P\) remains true even for the point at infinity.
Let’s analyze this:
\(\implies\): If \(P\) is a point on the curve whose coordinates are simple integers (in \(\mathbb{F}_p\)) - big parenthesis to explain…
“simple integers”: These are just the numbers \(\{0, 1, 2, \dots, p-1\}\). They are finite because they stop at \(p\). The \(p\)-adic integer (the infinite to the left string) is denoted \(\mathbb{Z}_p\) is an infinite expansions:
\[d_0 + d_1 p + d_2 p^2 + d_3 p^3 + \dots\]
The “simple integer” in \(\mathbb{F}_p\) is just the first digit (\(d_0\)) of a \(p\)-adic integer.
A point in the curve with \(x\) and \(y\) coordinates simple integers, i.e. \(E(\mathbb{F}_p),\) is a solution to the curve equation modulo \(p\). A point in \(E(\mathbb{Z}_p)\) is a lift of that solution. It is the infinite string that starts with \(d_0\) and continues forever in a way that always satisfies the equation at every higher power of \(p\).
… End of parenthesis… Continuing…
then the Frobenius map \(x^p \equiv x\) won’t move it, because the Frobenius map doesn’t move any of the base field numbers.
\(\impliedby\): If you find a point on the curve (even a “ghost point” in the extension field) (remember that \(P\) by definition is on the curve), and the Frobenius map doesn’t move it, i.e. \(\phi_p(P)=P,\) that proves its coordinates must have actually been simple integers all along, i.e. \(P \in E(\mathbb F_p)\) - no need to extend it the field to \(\mathbb Z_p.\) We only use the extension to \(\mathbb{Z}_p\) as a computational tool. It allows us to calculate the \(a_p\) with enough precision to distinguish it from other numbers. If we stayed only at the \(\mathbb{F}_p\) level, we might know \(a_p \pmod 5\), but we wouldn’t be able to find the true integer value of \(a_p\) as easily.
To count these fixed points mathematically, we define a new map: \((\phi_p - id)\).
\(id\) is the identity map (it does nothing: \(id(P) = P\)).
\((\phi_p - id)\) takes a point \(P\) and calculates the difference between its Frobenius transform and itself.
If \(P\) is a fixed point, then \(\phi_p(P) - id(P) = \mathcal{O}\) (the zero point).
In the world of algebraic geometry, the number of points that a map sends to zero is called the degree of that map. Therefore:
Degrees are hard to calculate directly. We want to turn this geometry into simple matrix algebra. In arithmetic geometry, we often use \(p\) to refer to the prime we are “counting modulo” (the field \(\mathbb{F}_p\)). To avoid confusion, we pick a different prime to help us probe the curve’s internal structure. We call this second prime \(\ell\). \(\ell\) can be any prime number as long as it isn’t \(p\). If \(p=5\), we might pick \(\ell=2\) or \(\ell=3\). \(\ell\) is like a measurement tool we use to see how the curve is shaped.
An elliptic curve is a group. If you add a point \(P\) to itself \(\ell\) times, we write that as \(\ell \cdot P\). A point \(P\) is called an \(\ell\)-torsion point if adding it to itself \(\ell\) times brings you back to the zero of the curve (the point at infinity, denoted \(\mathcal{O}\)):
\[\underbrace{P + P + \dots + P}_{\ell \text{ times}} = \mathcal{O}\]
We look at the \(\ell\)-torsion points of the curve. These are points \(P\) where \(\ell \cdot P = \mathcal{O}\).
The size of \(\ell\) relative to \(p\) does not matter at all. \(\ell\) can be much smaller (like \(2\)) or much larger (like \(1,000,009\)). The math works exactly the same in both cases. When we say a point is “\(\ell\)-torsional,” we are saying it is a solution to a specific algebraic equation.
On an elliptic curve, adding a point to itself \(\ell\) times is a process that can be written as a massive polynomial. Finding \(\ell\)-torsion points is essentially just finding the roots of a polynomial, called division polynomial, denoted as \(\psi_n(x, y)\). These are the “massive polynomials” that define the \(n\)-torsion points of an elliptic curve.
For an elliptic curve \(E: y^2 = x^3 + Ax + B\), a point \(P = (x, y)\) satisfies \(n \cdot P = \mathcal{O}\) if and only if \(\psi_n(x, y) = 0\).
Every time you draw a line and find an intersection, you are essentially solving a system of equations formed by the equation of the line \(y = mx + c,\) and the equation of the curve \(y^2 = x^3 + Ax + B\). When we substitute the line into the curve, we get a cubic equation in \(x\):
\[(mx + c)^2 = x^3 + Ax + B\]
The roots of that cubic are the \(x\)-coordinates of the three intersection points.
When you add a point to itself, the slope \(m\) is a function of the coordinates: \(m = \frac{3x^2 + A}{2y}\). The equation \(m = \frac{3x^2 + A}{2y}\) is the formula for the tangent slope at a point \(P = (x, y)\) on the curve \(y^2 = x^3 + Ax + B\). Using implicit differentiation (taking the derivative of both sides with respect to \(x\)): Since \(y\) is a function of \(x\), we use the chain rule to get \(2y \frac{dy}{dx}\). On the right side (\(x^3 + Ax + B\)): \(3x^2 + A\). Equate them: \(2y \frac{dy}{dx} = 3x^2 + A\) and solve for the slope (\(m = \frac{dy}{dx}\)): \(m = \frac{3x^2 + A}{2y}.\)
Because the group law for an elliptic curve is defined by rational functions, the result of \([n]P\) is always going to be some massive expression:
\[[n]P = \left( \frac{\text{Poly}_1(x,y)}{\text{Poly}_2(x,y)}, \frac{\text{Poly}_3(x,y)}{\text{Poly}_4(x,y)} \right)\]
\([n]P\) is shorthand for scalar multiplication. It means adding the point \(P\) to itself \(n\) times:\[[n]P = \underbrace{P + P + \dots + P}_{n \text{ times}}\]
The division polynomial \(\psi_n\) is essentially the denominator of these expressions.
To explicitly determine the \(x\)-coordinates of these \(n\)-torsion points, we introduce the division polynomials. These polynomials provide a recursive algebraic framework for point multiplication, where the zeros of \(\psi_n\) correspond precisely to the \(x\)-coordinates of the points in \(E[n] \setminus \{ \mathcal{O} \}\). Their roots tell us exactly where the \(n\)-torsion points live on the \(x\)-axis.
The division polynomial is fixed for a given curve because it represents the intrinsic geometry of that curve. The lines change based on the point. The polynomial changes based on the curve (the coefficients \(A\) and \(B\)). For the elliptic curve \(y^2=x^3 +A + B\), when you add a point to itself, the slope \(m\) is a function of the coordinates: \(m = \frac{3x^2 + A}{2y}\), and the intersection with the equation for the elliptic curve, for instance, \(y^2 = x^3 + x\), determines the division polynomial, in this case \(\psi_3 = 3x^4 + 6x^2 - 1\). \(\psi_3(x)\) is the master equation for all points that satisfy \([3]P = \mathcal{O}\). On a donut (the complex torus), the 3rd torsion points form a \(3 \times 3\) grid, giving \(9\) points total. There is a general formula for \(\psi_3\) for any curve \(y^2 = x^3 + Ax + B\):
\[\psi_3(x) = 3x^4 + 6Ax^2 + 12Bx - A^2\]
If you plug in your curve’s coefficients (\(A=1\) and \(B=0\)): \(3x^4\) stays \(3x^4\). \(6(1)x^2\) becomes \(6x^2\). \(12(0)x\) disappears. \(-(1)^2\) becomes \(-1\). This gives you exactly the \(3x^4 + 6x^2 - 1.\)
A polynomial of degree \(n\) always has exactly \(n\) roots, provided we are willing to use complex enough numbers. For an elliptic curve, the torsion polynomial for \(\ell\) always has roots. When you solve it, you always find exactly \(\ell^2\) points. Even if your starting field \(\mathbb{F}_p\) is tiny (say \(p=2\)) and the curve has only one point there, the mathematical “ghost” of the \(2 \times 2\) grid is still there. If we expand your our to \(\mathbb{F}_{2^2}, \mathbb{F}_{2^3}, \dots\) eventually all \(\ell^2\) points will show up.
In the field \(\mathbb{F}_p\), we only have the integers \(\{0, 1, \dots, p-1\}\). If we have a polynomial — like the one that defines the \(\ell\)-torsion points — and it has no roots in \(\mathbb{F}_p\), we do exactly what we do in high school algebra: we invent them: \(\mathbb{F}_p \to \mathbb{F}_{p^k}\) (where \(k\) is the degree of the extension). We call \(\mathbb{F}_{p^k}\) an extension field. It contains \(\mathbb{F}_p\), but it also contains all the “complex” coordinates needed to describe the \(\ell\)-torsion points that were missing from the original field. If you keep adding roots for every possible polynomial, you eventually reach the algebraic closure, denoted \(\overline{\mathbb{F}}_p\). This is the ultimate “super field.” It is infinite in size. Every polynomial has all its roots here. This is the place where the full \(2 \times 2\) grid of \(\ell^2\) torsion points is guaranteed to exist.
Recapping, we want to spot the \(\ell\)-torsion points (the \(x, y\) coordinates that satisfy \([ \ell ]P = \mathcal{O}\)). We start on the “ground floor” at \(\mathbb{F}_p\). Usually, we will only find a few \(\ell\)-torsion points here — sometimes only the point at infinity. The rest are “ghosts” that are mathematically required to exist but don’t have coordinates in our current number system. To find them, we expand outward to \(\mathbb{F}_{p^k}\). As we increase \(k\) new points appear. We keep increasing \(k\) until we find the full \(\ell^2\) grid (for \(\ell=3\), that’s the \(9\)-point grid). This is a field expansion. It’s about “horizontal” discovery. Once we have spotted these points in \(\mathbb{F}_{p^k}\), we only have their “blurry” versions (just the first digit, \(d_0\)). To calculate a precise L-function, we need to know exactly how the Frobenius map shuffles them. We expand upward into the \(p\)-adic tower \(\mathbb{Z}_q\) (where \(q=p^k\)). As we increase the power of \(p\) (e.g., \(p^{20}\)) points stay the same; we aren’t finding new points anymore; we’ve already found the grid. We are calculating \(d_1, d_2, d_3 \dots d_{19}\). We are getting more and more “decimal places” (to the left) for the points we already caught. This is a ring expansion. It’s about “vertical” precision. Now that we have a “high-definition” grid, we apply the Frobenius map: \((x, y) \to (x^p, y^p)\). Because our points are high-precision, we can see exactly which point in the grid moved to which other point. We turn this shuffle into a \(2 \times 2\) matrix of integers. The trace (\(a_p\)) of this matrix is the final “integer signature” of the curve at that prime.
The coefficients for powers of \(p\) (like \(a_{p^2}, a_{p^3}\)) are not new independent data. They are forced by a recurrence relation based entirely on \(a_p\) and \(p\):\(a_{p^2} = a_p^2 - p\)\(a_{p^3} = a_p \cdot a_{p^2} - p \cdot a_p\).
Notice that \(\mathbb{F}_{p^k}\) is a finite field. It contains simple digits \(0,1,2,\dots p^k\) in the \(d_0\) of the \(p\)-adic expansion. You can add, subtract, multiply, and (crucially) divide. Every non-zero element has an inverse. This is where we “spot” the \(\ell^2\) points. However, every coordinate is effectively just a single complex digit modulo \(p\). The purpose is to find the “ghost” points that don’t exist in the base field. Yet, it is low resolution.
That’s why we “lift” our coordinates from the field into the \(p\)-adic ring \(\mathbb{Z}_q\): it is the ring of integers in a \(p\)-adic field. We keep adding digits to the left (\(\dots d_2 d_1 d_0\)) until the coordinate is precise enough that our matrix math doesn’t have any rounding errors. It is not a field because you can divide by \(3\), but you cannot divide by \(5\). If you try to calculate \(1/5\), the string would have to shift to the right of the decimal point (the radix), which makes it no longer a p-adic integer. In the \(p\)-adic ring \(\mathbb{Z}_q\), we can divide by many things, but never by \(p\). We can divide by any number that doesn’t have \(p\) as a factor. For example, \(1/2\) exists in the \(5\)-adics because \(2\) is “coprime” to \(5\). It just looks like an infinite string of digits. But we cannot calculate \(1/5\) inside \(\mathbb{Z}_5\). If we try to write a string starting with \(d_0 + d_1 \cdot 5 \dots\) that equals \(1/5\), it’s impossible. However, in the field \(\mathbb{Q}_q\) we include the \(p\)-adics with negative powers of \(p\).
The points in \(E(\mathbb{F}_p)\) are the “frozen” points under Frobenius. Their \(p\)-adic expansion is just a single digit at the \(p^0\) position followed by infinite zeros to the left (\(\dots00000d.\)). Frobenius cannot move them. But there are torsion points that can only be seen in the extension \(\mathbb F_{p^k}\): These are the “movers.” Their \(p\)-adic expansions are infinite, non-zero strings to the left. Frobenius shuffles them around the grid. We use the moving points to calculate the “shuffle” (the Frobenius matrix). The Trace (\(a_p\)) of that matrix then tells us the exact count of the frozen points (\(N_p = p + 1 - a_p\)).
Therefore, to determine \(a_p\) (and \(N_p\)), the trick is to use the \(\ell\)-torsion grid to measure the Frobenius map (find below a more detailed explanation (*)). The total set of residents with coordinates in the base field \(\mathbb{F}_p\) is called \(E(\mathbb{F}_p)\), and it forms a finite abelian group. Since every element of a finite group has finite order, adding any resident to itself a certain number of times will hit \(\mathcal{O}\), which means that every resident is, by definition, a torsion point of some order.
When we ask for \(N_p\) (the number of points on the curve over \(\mathbb{F}_p\)), we are effectively asking: “Which of the torsion points have coordinates that are just simple integers \(\dots00000d.\)?” Since we can’t always see the points directly, we use the Frobenius map as a filter. The Frobenius map shuffles any point that has “ghostly” coordinates (non-zero digits to the left). The Frobenius map leaves alone any point whose coordinates are in \(\mathbb{F}_p\).
This is ultimately why we use \(p\)-adics. If we only work modulo \(p\) (in \(\mathbb{F}_p\)), we only see the world in “low resolution.” We might find that \(a_p \equiv 2 \pmod 5\), but we wouldn’t know if \(a_p\) is \(2, 7, -3,\) or \(12\). By lifting the coordinates to \(\mathbb{Z}_p\), we are essentially adding “decimal places” (to the left). This allows us to calculate the Frobenius matrix with zero error, and ensure that when we take the trace, we get the exact integer \(a_p\), not just a remainder.
\(\mathbb{F}_p\) is a coarse filter; it only sees points with simple coordinates. \(\mathbb{F}_{p^k}\) is a finer filter; it lets you see “complex” points that were previously invisible. We can think of the complex extension as looking at the fundamental domain (the square that makes the donut) and realizing it is actually tiled by smaller sub-tiles. By going to a larger field, we aren’t changing the donut; we are just increasing the “pixel density” so we can finally see where the \(\ell\)-torsion points are sitting.
If the \(x\)-coordinates of our torsion points don’t fit in \(\mathbb{F}_p\), we must expand the field. We go to larger powers of \(p\) (the extension field \(\mathbb{F}_{p^k}\)) to find the ghost points, and higher \(p\)-adic precision (\(\mathbb{Z}_p \pmod{p^{20}}\)) to calculate \(a_p\). A \(3 \times 3\) grid only tells us \(a_p \pmod 3\). To know if \(a_p\) is \(1\), \(4\), or \(10\), we must look at \(9 \times 9, 27 \times 27\), etc. Each larger power of \(\ell\) provides one more digit of precision. Even though these represent “smaller” distances in the \(\ell\)-adic world, they require a larger (more complex) grid to measure.
We can think of the lattice \(\Lambda\) in the definition of an elliptic curve as \(\mathbb C/\Lambda\) as a grid of stakes driven into an infinite flat field. Every stake represents the zero point (\(\mathcal{O}\)) because when we wrap the field into a donut, all those stakes land on the exact same spot. The original lattice \(\Lambda\) contains points like \((1, 0)\) or \((0, 1)\) (in terms of the basis vectors \(\omega_1, \omega_2\)). The \(3 \times 3\) grid contains points like \((\frac{1}{3}, 0)\), \((\frac{2}{3}, 0)\), \((\frac{1}{3}, \frac{1}{3})\), and so on. This is just a way of explaining it: Instead of a fraction, a point in the Tate module is an \(\ell\)-adic vector \(v = \begin{pmatrix} x \\ y \end{pmatrix}\), where \(x\) and \(y\) are \(\ell\)-adic integers (\(\mathbb{Z}_\ell\)). These \(x\) and \(y\) are essentially the infinite strings of digits that tell us exactly where the point sits in the “infinite subdivision.”
The Tate module \(T_\ell(E)\) is the inverse limit of the torsion groups:
\[T_\ell(E) = \varprojlim E[\ell^n]\]
In the torsion group \(E[\ell^n]\), the elements are the points \((x, y)\) that satisfy the algebraic condition \([\ell^n]P = \mathcal{O}\). Geometrically, if we imagine the torus (donut) as a square field with the sides glued together, the elements are the points on a perfectly spaced grid. Algebraically, each element can be identified by its “grid coordinate.” Point addition is the group operation. In the torsion group \(E[\ell^n]\), the “multiplication” by \(\ell^n\) is simply adding a point to itself \(\ell^n\) times.
\(E[\ell^1]\): The \(3 \times 3\) grid (for \(\ell=3\)). It contains \(9\) elements:\[(0,0), (1,0), (2,0), (0,1), (1,1), (2,1), (0,2), (1,2), (2,2)\](Note: These are indices, not the \(p\)-adic coordinates of the points.)
\(E[\ell^2]\): The \(9 \times 9\) grid.
Each point in the \(3 \times 3\) grid “splits” into \(9\) smaller points.
\(E[\ell^\infty]\): The Tate module.
It captures the coordinates of a point as it moves through this infinite subdivision. It is the limit of all the \(\ell\)-power grids: a high-precision coordinate system for the curves’s internal symmetry. The Tate module is an infinitely dense grid (fractal) which by definition includes all the coordinates where the torsion points can live: it assigns GPS coordinates to any point on the curve, turning geometry into linear algebra: The Frobenius map acts on the entire structure at once.
A vector space is a special kind of module with scalars belonging to a field, whereas in a module the scalars belong to a ring, which in this case is \(\mathbb Z_l\), the ring of \(\ell\)-adic integers (infinite expansions to the left).
We use \(p\)-adic - not \(\ell\)-adic - numbers to calculate the \(\ell\)-adic shuffle (torsion). There are no strict laws that say \(p\) must be the one we count (field prime) and \(\ell\) must be the grid - pattern prime. If we chose to look at the curve over \(\mathbb{F}_3\) and study its \(5\)-torsion, then \(p=3\) and \(\ell=5\). But we can as well look at the curve over \(\mathbb{F}_5\) and study its \(3\)-torsion, so \(p=5\) and \(\ell=3\). The only rule is \(\ell \neq p\) because if they were the same, the “grid” would collapse (this is called the “supersingular” or “anomalous” case, where the geometry gets very messy).
The Tate module gives every torsion point a permanent “seat number” in the grid. For a \(3\)-torsion point, the seat number is an \(\ell\)-adic vector like \(v = \begin{pmatrix} 1 \\ 0 \end{pmatrix}\). This “\(1\)” is an \(\ell\)-adic integer (\(\dots00001.\) in base \(3\)). It tells the math: “This is the first basis point of the grid. The actual values of the \(x\) and \(y\) coordinates for that specific seat are \(p\)-adic integers. The coordinates are strings like \(x = \dots42314.\) (in base \(5\)). The coincidence between these two systems happens through the elliptic curve equation. When you take the \(p\)-adic values from the”occupant” and plug them into the equation \(y^2 = x^3 + Ax + B\), the math confirms that this specific occupant belongs in the torsion grid labeled by \(\mathbb{Z}_\ell\). The Tate module is the structure that ensures that as you apply the Frobenius map, the “occupant” moves to a new “seat” in a way that is perfectly consistent with linear algebra. We use the \(p\)-adic values to track the movement, but you use the \(\ell\)-adic labels to write down the matrix.
The grid isn’t just a visual overlay; it is defined by a specific algebraic requirement. A point \(P = (x, y)\) is in the \(\ell\)-torsion grid if and only if: \([\ell]P = \mathcal{O}\). This means if you add the point to itself \(\ell\) times using the group law (the slope formulas discussed earlier), we must land on the point at infinity. It is the division polynomial that links the EC to the Tate module or grid structure.
The use of \(p\)-adic numbers works because we are considering a small set of numbers (roots of polynomials, i.e. algebraic numbers) that live in both worlds. The \(3\)-torsion point \(x\)-coordinate may be a root of \(3x^4 + 6x - 1 = 0\). This root can be “embedded” into \(\mathbb{C}\) as a decimal like \(0.165\dots\). The exact same root can be “embedded” into \(\mathbb{Z}_3\) as a 3-adic expansion \(\dots 2101\). The \(\ell\)-adic numbers are the “completion” of these roots in one direction, and \(\mathbb{C}\) is the “completion” in the other.
Going back to the analogy these fractional points are not in the original lattice \(\Lambda\). However, they have a very special relationship to it: if you multiply them by \(3,\) they land exactly on a stake in \(\Lambda\). We talk about “tiling the grid with larger copies,” but it is often more helpful to think of it as subdividing the original tile. Start with our Fundamental Domain (the parallelogram formed by \(\Lambda\)). To find the \(3\)-torsion, you divide that parallelogram into \(9\) smaller “mini-parallelograms.” The corners of these mini-parallelograms are our \(3\)-torsion points. These corners are “new” points in the complex plane, but in the group theory of the donut, they are the only points that know how to get back to the lattice stakes in exactly \(3\) steps. Now, when you move to \(9 \times 9\), we are subdividing those mini-parallelograms even further. The \(3\)-torsion points are at coordinates like \(\frac{1}{3}, \frac{2}{3}\). The \(9\)-torsion points are at coordinates like \(\frac{1}{9}, \frac{2}{9}, \frac{3}{9}, \dots\) Notice that \(\frac{3}{9}\) is the same as \(\frac{1}{3}\). This is why the \(3 \times 3\) grid is contained within the \(9 \times 9\) grid. The \(9 \times 9\) system has a higher density of points, and it “swallows” the \(3 \times 3\) grid. The Tate Module is the limit of this subdivision process. Imagine we subdivide the parallelogram by \(\ell, \ell^2, \ell^3 \dots\) forever. The points are getting closer and closer together in the complex plane. In the \(\ell\)-adic world, these points are forming a continuous space (a “free module”). The Frobenius map \(\phi_p\) acts on this infinite subdivision. Because it is a linear map, it doesn’t just move one point; it maps the entire “subdivided tiling” to another “subdivided tiling.”
For a prime \(\ell\) (where \(\ell \neq p\)), there are exactly \(\ell^2\) torsion points. They form a \(2 \times 2\) grid, much like a vector space.
In SageMath we can find the torsion points with complex numbers:
E = EllipticCurve([1, 0]) # y^2 = x^3 + x
ell = 3
# 1. Move to the Algebraic Closure to see the "ghost" points
K = QQbar
E_K = E.base_extend(K)
# 2. Get the Origin point (Point at Infinity)
Origin = E_K(0)
# 3. Find points P such that 3*P = Origin
# We call division_points on the Point object itself
points = Origin.division_points(ell)
# Print the 3rd division polynomial
print(f"The elliptic curve is: {E}")
print("-" * 30)
print(f"The {ell}-rd division polynomial (l=3) psi_{ell} is: {E.division_polynomial(ell)}")
print(f"Total {ell}-torsion points found: {len(points)}")
print("-" * 30)
print(f"TORSION POINTS (in algebraic coordinates):")
for i, P in enumerate(points):
# Formatting to show the algebraic coordinates clearly
print(f"Point {i}: ({P[0]} : {P[1]} : {P[2]})")
---
# OUTPUT:
---
The elliptic curve is: Elliptic Curve defined by y^2 = x^3 + x over Rational Field
------------------------------
The 3-rd division polynomial (l=3) psi_3 is: 3*x^4 + 6*x^2 - 1
------------------------------
TORSION POINTS (in algebraic coordinates):
Total 3-torsion points found: 9
Point 0: (0 : 1 : 0)
Point 1: (-0.3933198931903287? : -0.6739189064139262?*I : 1)
Point 2: (-0.3933198931903287? : 0.?e-15 + 0.673918906413926?*I : 1)
Point 3: (-1.467889825013871?*I : -0.9205903462520508? - 0.9205903462520508?*I : 1)
Point 4: (-1.467889825013871?*I : 0.9205903462520508? + 0.9205903462520508?*I : 1)
Point 5: (1.467889825013871?*I : -0.9205903462520508? + 0.9205903462520508?*I : 1)
Point 6: (1.467889825013871?*I : 0.9205903462520508? - 0.9205903462520508?*I : 1)
Point 7: (0.3933198931903287? : -0.6739189064139262? : 1)
Point 8: (0.3933198931903287? : 0.6739189064139262? : 1)
QQbar (\(\overline{\mathbb{Q}}\)) is the Field of algebraic aumbers. It contains every number that is a root of a polynomial with rational coefficients. This includes all integers, fractions, square roots (\(\sqrt{2}\)), and imaginary numbers (\(i\)).
But we can get p-adics:
E = EllipticCurve([1, 0])
ell = 3 # The order of torsion
p = 11 # The p-adic prime
# 1. The Division Polynomial for the ell-torsion
psi = E.division_polynomial(ell)
# 2. The Algebraic View (The "True" Root)
# We find the root in the algebraic closure
root_alg = psi.roots(QQbar, multiplicities=False)[0]
print(f"--- Algebraic Perspective ---")
print(f"Investigating {ell}-torsion for {E}")
print(f"Division polynomial psi_{ell}: {psi}")
print(f"A root x is: {root_alg}")
# 3. The p-adic View (The "Local" Address)
K_p = Qp(p, prec=5)
padic_roots = psi.roots(K_p, multiplicities=False)
print("-" * 30)
print(f"--- {p}-adic Perspective ---")
if padic_roots:
root_padic = padic_roots[0]
print(f"In Q_{p}, that same root looks like: {root_padic}")
print(f"Expansion: {root_padic.expansion()}")
else:
print(f"The {ell}-torsion x-coordinates are not in Q_{p} directly.")
---
OUTPUT:
--- Algebraic Perspective ---
Investigating 3-torsion for Elliptic Curve defined by y^2 = x^3 + x over Rational Field
Division polynomial psi_3: 3*x^4 + 6*x^2 - 1
A root x is: -0.3933198931903287?
------------------------------
--- 11-adic Perspective ---
In Q_11, that same root looks like: 5 + 4*11 + 2*11^2 + 7*11^3 + 7*11^4 + O(11^5)
Expansion: 11-adic expansion of 5 + 4*11 + 2*11^2 + 7*11^3 + 7*11^4 + O(11^5)
Interpretation: It shows exactly how a single geometric point on our donut (the elliptic curve) is translated into two different mathematical languages: the “analog” (complex) and the “digital” (\(p\)-adic).
The algebraic blueprint (QQbar): This is the “analog”
view of the point. The Value \((-0.3933...)\): This is a decimal
approximation of where the point sits on the complex plane. It’s hard to
do exact arithmetic with it.
The \(11\)-adic digital address
(Qp): We are looking at the exact same point, but expressed
as a “digital string” in base \(11.\)
The “\(5\)” (The first digit): This is
the “coarse address.” If you looked at your donut through a very blurry
lens (modulo \(11\)), the point would
be sitting at \(x=5\).
The expansion (\(5 + 4 \cdot 11 + 2 \cdot 11^2 \dots\)): This is the “high-resolution Address.”The \(4 * 11\) tells us which “sub-tile” the point is in. The \(2 * 11^2\) zooms in further.
The \(O(11^5)\): This is our “zoom Level.” We have calculated the position of this torsion point down to \(5\) digits of \(11\)-adic precision.
The L-function doesn’t care about the decimal \(-0.3933.\) It cares about the symmetry. The address (\(11\)-adic string) changes depending on the prime. The Tate Module is the “registry” that tracks how these addresses (like \(5 + 4 \cdot 11 \dots\)) are shuffled by the Frobenius map. When we run the Frobenius shuffle, we are literally watching that string of digits (\(5, 4, 2, 7, 7\)) be transformed into the expansion of a different root of the same division polynomial (\(3x^4 + 6x^2 - 1 = 0\)). The trace (\(a_p\)) is the summary of that transformation.
The Frobenius map \(\pi_p\) acts on the coordinates of the point. If a point \(P\) has coordinates \((x, y)\), the Frobenius map sends it to \((x^p, y^p)\). If \(x\) and \(y\) are simple integers (or elements of \(\mathbb{F}_p\)), then \(x^p \equiv x \pmod{p}\). These points stay put. For a torsion point, the \(x\)-coordinate is usually a root of a polynomial that doesn’t factor easily. These roots are spread out across the field extension. Frobenius acts like a permutation: it picks up one root of the division polynomial and moves it to a different root of the same polynomial. For example, imagine the roots of \(\psi_3\) are \(\{r_1, r_2, r_3, r_4\}\). The Frobenius map looks at the \(11\)-adic string for \(r_1\); it does the “Frobenius math” (\(x^{11}, y^{11}\)), and the result is a new \(11\)-adic string that matches the expansion of \(r_2\). When we talk about the Frobenius map \(\pi_p\) acting on the \(n\)-torsion points of an elliptic curve, we are describing a specific Galois automorphism. In the \(p\)-adic setting, we call it the Frobenius element in the local Galois group \(Gal(\overline{\mathbb{Q}}_p/\mathbb{Q}_p)\).
The Frobenius map is an automorphism, which means it must preserve the entire algebraic structure of the field. If it moves the “coarse address” (\(11^0\)), it must move the “fine details” (\(11^1, 11^2, \dots\)) in a way that is perfectly consistent with the curve’s equation.
If we look at all the points that satisfy \(\ell \cdot P = \mathcal{O}\), there aren’t just \(\ell\) of them. There are \(\ell^2\) of them. Geometrically, an elliptic curve (over complex numbers) is shaped like a torus (a donut). To “cycle” around a donut and get back to where we started, we can go two ways: around the tube or through the hole. Because there are two independent directions to move, the torsion points form a \(2\)-dimensional structure. If \(\ell = 3\), we have \(3^2 = 9\) points. We can think of these points as being organized like a grid: \(3\) points along the tube direction, and \(3\) points along the hole direction.
If we take two points from the grid and add them together, we stay in the grid. Since it has two directions and behaves like a grid, it acts exactly like a \(2\)-dimensional vector space over the field \(\mathbb{F}_\ell\) (the integers modulo \(\ell\)). In a normal 2D vector space, any point can be written as \((x, y)\). Here, every \(\ell\)-torsion point can be identified by its “coordinates” on that grid.
The Frobenius map \(\phi_p\) is defined by:
\[\phi_p(x, y) = (x^p, y^p)\]
If a point \(P = (x, y)\) is an \(\ell\)-torsion point, it means that adding \(P\) to itself \(\ell\) times gives the zero point: \(\ell \cdot P = \mathcal{O}\). Now, because the Frobenius map is an endomorphism (a map from the curve to itself that respects addition), it has a very important property:
\[\phi_p(P + Q) = \phi_p(P) + \phi_p(Q)\]
This implies that
\[\phi_p(\ell \cdot P) = \ell \cdot \phi_p(P)\]
If \(P\) is an \(\ell\)-torsion point, then \(\ell \cdot P = \mathcal{O}\), and we know \(\phi_p(\mathcal{O}) = \mathcal{O}\). Therefore:
\[\ell \cdot \phi_p(P) = \mathcal{O}\]
Notice that if \(P\) is an \(\ell\)-torsion point, it is automatically an \(\ell^k\)-torsion point for any \(k \ge 1\).
The Frobenius map takes an \(\ell\)-torsion point and lands it precisely on another \(\ell\)-torsion point. It shuffles the points within that \(2 \times 2\) grid. If a point is in \(\mathbb{F}_p\): \(\phi_p(x,y) = (x^p, y^p) = (x, y)\), it lands on itself. If a point is “complex” (extension field): \(\phi_p(x,y) = (x^p, y^p) \neq (x, y),\) it lands on a “sibling” point in the grid.
However, counting points only tells us about the curve at one specific resolution (\(\mathbb{F}_p\)). But an elliptic curve is a “global” object. If you know the Frobenius Matrix \(M_p\), you don’t just know the count for \(\mathbb{F}_p\). You automatically know the count for every possible extension field (\(\mathbb{F}_{p^2}, \mathbb{F}_{p^3}, \mathbb{F}_{p^4} \dots\)). The number of points in \(\mathbb{F}_{p^k}\) is determined by the formula:
\[N_{p^k} = p^k + 1 - (\alpha^k + \beta^k)\]
where \(\alpha\) and \(\beta\) are the eigenvalues of your Frobenius matrix. Without the matrix, we’d have to start our counting from scratch every time you moved to a larger field. The goal of the L-function isn’t just to store a list of point counts. Its goal is to bridge the gap between arithmetic (counting) and analysis (calculus and modular forms).
Since there are \(\ell^2\) points in this grid, and they form a structure like a 2D vector space \((\mathbb{Z}/\ell\mathbb{Z})^2\), we can choose a basis. Pick two “primary” \(\ell\)-torsion points, \(E_1\) and \(E_2\), that are not multiples of each other. Every other torsion point \(P\) in the grid can be written as:
\[P = c_1 E_1 + c_2 E_2\]
where \(c_1\) and \(c_2\) are coefficients from \(0\) to \(\ell-1\). When we apply \(\phi_p\) to our basis points, they must land somewhere in the grid, so they can also be written in terms of that basis: \(\phi_p(E_1) = a E_1 + c E_2\) and \(\phi_p(E_2) = b E_1 + d E_2\)
This gives us our \(2 \times 2\) matrix over the field \(\mathbb{F}_\ell\):
\[M_{\phi_p, \ell} = \begin{pmatrix} a & b \\ c & d \end{pmatrix}\]
The Trace of this matrix is simply \(a + d\). If you were to pick \(\ell = 2\) (the \(2 \times 2\) grid), the matrix would tell you how \(\phi_p\) swaps the three non-zero torsion points. When we say the \(\ell\)-torsion points form an \(\ell \times \ell\) grid, the total number of points is exactly \(\ell^2\). For \(\ell = 2\), the grid has \(2^2 = \mathbf{4}\) points. However, one of those points is always the identity element (the point at infinity, \(\mathcal{O}\)), which acts like the “zero” in a vector space. In any vector space, the zero vector is always fixed by any linear transformation. Because the Frobenius map \(\phi_p\) is a linear map (it respects the addition of points): \(\phi_p(\mathcal{O})\) is always \(\mathcal{O}\). The map cannot “move” the origin; it can only shuffle the remaining points. If you pick \(\ell = 3\) (the \(3 \times 3\) grid), the matrix would be larger in values, but the “sum of the diagonal” (\(a+d\)) would still be equivalent to the same \(a_p\) (modulo \(\ell\)).
The Tate module \(T_\ell(E)\) uses \(\ell\)-adic integers \(\mathbb{Z}_\ell\). If we only look at the \(\ell\)-torsion, we only know \(a_p \pmod \ell\). That isn’t enough information to know the exact value of \(a_p\). If \(\ell=2\) and \(a_p \equiv 1 \pmod 2\), \(a_p\) could be \(1, 3, 5, \dots\). To find the exact integer \(a_p\), we look at \(\ell^2\)-torsion, \(\ell^3\)-torsion, and so on. By looking at the action on the whole Tate module (the “tower” of all \(\ell^n\)-torsion), we are essentially looking at a matrix with \(\ell\)-adic entries. This matrix has a trace that is an \(\ell\)-adic integer. Since \(a_p\) is a fixed integer and the Tate module construction works for any \(\ell^n\), this \(\ell\)-adic trace converges to the actual integer \(a_p\) that we use in the L-function.
In the following SageMath code, we attempt to get the polynomial sitting in the denominator of the L-function
\[L(E, s) = \prod_{p} \frac{1}{1 - a_p p^{-s} + p^{1-2s}}\]
for a single prime \(p=3\). By
constructing L_poly = 1 - ap*T + p*T^2, we are manually
building the polynomial that sits in the denominator for the prime \(p\). To this end we need to extract the two
parameters for that local polynomial: The prime (\(p=3\)), which defines the “degree” or
weight of the quadratic term, and the trace (\(a_p\)), which defines the linear term and
carries the specific data about the curve’s point-count at that
prime.
The Local L-factor is the “slice” of the L-function at a specific prime \(p\). The global L-function \(L(E, s)\) is built by multiplying an infinite number of these local pieces together (an Euler Product). For a prime of good reduction, the L-factor is the denominator of the Euler factor:
\[L_p(T) = 1 - a_p T + p T^2\]
We cannot see the trace \(a_p\) directly by looking at the curve’s equation. To measure \(a_p\), we have to see how the curve’s points behave. The \(\ell\)-torsion points act as a representative sample of the whole curve. The Tate module is built entirely out of these torsion points. For a prime \(\ell\), the \(\ell\)-adic Tate module \(T_\ell(E)\) is the “limit” of all the \(\ell^n\)-torsion points as you zoom in deeper and deeper. Mathematically, it is defined as the inverse limit:\[T_\ell(E) = \varprojlim_{n} E[\ell^n]\] Essentially, you are stacking the torsion groups:
At level 1, we have \(E[\ell] \cong (\mathbb{Z}/\ell\mathbb{Z})^2\).
At level 2, we have \(E[\ell^2] \cong (\mathbb{Z}/\ell^2\mathbb{Z})^2\)
…and so on.
The result is a 2-dimensional vector space over the \(\ell\)-adic integers \(\mathbb{Z}_\ell\). It’s 2-dimensional because of the lattice structure of these different levels of zooming in: At level \(1,\) the grid is \(\ell \times \ell\). We need \(2\) generators (\(P_1, P_2\)). At level \(2,\) the grid is \(\ell^2 \times \ell^2\). We still only need 2 generators (\(Q_1, Q_2\)), they just have higher “resolution.”
When the code prints the torsion points, it is showing you the raw data that the Frobenius map is about to shuffle. The Trace is just a summary of that shuffle.
E = EllipticCurve([1, 0]) # y^2 = x^3 + x
p = 3
ell = 3
# 1. Get the pieces for the L-factor
ap = E.ap(p) # Trace of Frobenius at p
print(f"Trace of Frobenius (a_p) at p={p}: {ap}")
# 2. Manually construct the Local L-factor polynomial
# Using T as the variable to match standard L-function notation
R.<T> = PolynomialRing(ZZ)
L_poly = 1 - ap*T + p*T^2
print(f"Local L-factor (Denominator): {L_poly}")
print(f"\n--- Torsion & p-adic Resolution ---")
psi = E.division_polynomial(ell)
print(f"{ell}-Division Polynomial: {psi}")
# Using p=11 for the p-adic view
p_view = 11
K_p = Qp(p_view, prec=5)
padic_roots = psi.roots(K_p, multiplicities=False)
if padic_roots:
root = padic_roots[0]
print(f"x-coord in {p_view}-adics: {root}")
print(f"Expansion: {root.expansion()}")
---
OUTPUT:
Trace of Frobenius (a_p) at p=3: 0
Local L-factor (Denominator): 3*T^2 + 1
--- Torsion & p-adic Resolution ---
3-Division Polynomial: 3*x^4 + 6*x^2 - 1
x-coord in 11-adics: 5 + 4*11 + 2*11^2 + 7*11^3 + 7*11^4 + O(11^5)
Expansion: 11-adic expansion of 5 + 4*11 + 2*11^2 + 7*11^3 + 7*11^4 + O(11^5)
Interpretation: When the Frobenius map \(\phi_3\) (the map \((x, y) \to (x^3, y^3)\)) acted on the \(3 \times 3\) torsion grid, it was a perfect rotation. Because the trace is \(0\), it means that none of the \(8\) non-trivial points on the “donut” landed on themselves. They were all shuffled to new positions. In the language of point counting (\(N_p = p + 1 - a_p\)), this tells us there are exactly \(3 + 1 - 0 = 4\) points on the curve over \(\mathbb{F}_3\).
The L-factor: \(3T^2 + 1\) This is the “DNA capsule” for the prime \(p=3\). The formula is \(1 - a_p x + p x^2\). Since \(a_p = 0\), the middle term vanishes. Why it matters: When we build the L-function, we turn this into a fraction in which \(T\) is replaced by \(3^{-s}\) : \(\frac{1}{1 + 3(3^{-2s})} = \frac{1}{1 + 3^{1-2s}}\). This specific polynomial “weights” the importance of the prime \(3\) in the global L-series.
The \(3\)-Division Polynomial: \(3x^4 + 6x^2 - 1\) This is the blueprint for the \(3 \times 3\) grid. Every \(x\)-coordinate of the \(9\) points in the torsion grid must be a root of this polynomial (or the point at infinity). Notice it is degree \(4.\) Since each \(x\) usually gives two \(y\) values (\(\pm y\)), these \(4\) roots correspond to the \(8\) points sitting on the “tube” and “hole” of the donut.
The \(p\)-adic address: \(5 + 4 \cdot 11 + 2 \cdot 11^2 \dots\) It’s the high-resolution coordinate of one of those \(9\) points. The base \((11)\): We looked at the point through the “lens” of the prime \(11.\)
The digits (\(5, 4, 2, 7, 7\)): This is the “GPS coordinate” of the point in the Tate Module. The \(5\) is the location on a coarse \(11 \times 11\) grid. The \(4 * 11\) is the correction needed to find the point on a finer \(121 \times 121\) grid. The \(O(11^5)\): This is the “zoom level.” It means we know exactly where this “fractional stake” is located down to a resolution of \(11^5\) (\(161,051\) sub-tiles).
To get a complete picture, we don’t just look at \(\ell\)-torsion, but \(\ell^2, \ell^3, \dots\) and so on. We “stack” these layers together to create the Tate Module \(T_\ell(E)\). Because we are stacking powers of \(\ell\), the coordinates of these points naturally live in the \(\ell\)-adic integers \(\mathbb{Z}_\ell\). The Tate Module is a 2-dimensional space over \(\mathbb{Z}_\ell\).
While SageMath doesn’t typically output a “matrix of digits” for the Tate module in a single command, you can compute the representation of the Galois action (which is what the Frobenius matrix \(M\) is) on the \(\ell\)-torsion points.
E = EllipticCurve([1, 0]) # y^2 = x^3 + x
p = 5
ell = 3
K_p = Qp(p, prec=20)
psi = E.division_polynomial(ell)
psi_mod_p = psi.change_ring(GF(p))
factors_mod_p = psi_mod_p.factor()
E = EllipticCurve([1, 0])
p = 5
ell = 3
# 1. Get the division polynomial
psi = E.division_polynomial(ell)
# 2. Find the splitting field modulo p
# This automatically determines the correct degree 'd'
K_finite = GF(p)['x'](psi).splitting_field('a_bar')
d = K_finite.degree()
# 3. Use that degree to build your p-adic extension
K_ext = Qq(p^d, prec=20, names='a')
print(f"Detected required degree: {d}")
print(f"Defining polynomial for the p-adic digits: {K_ext.defining_polynomial()}")
print(f"The 'digit' a satisfies: {def_poly}")
psi_over_ext = psi.change_ring(K_ext)
roots_in_ext = psi_over_ext.roots(multiplicities=False)
print(f"--- {p}-adic Grid Shuffle (The Frobenius Lift) ---")
for i, root in enumerate(roots_in_ext):
frob_root = root.frobenius()
val = psi_over_ext(frob_root).valuation()
is_still_root = val >= 20
print(f"Root {i})
print(f"Root {i} maps to: {frob_root}")
print(f" -> Still in the grid? {is_still_root} (Valuation: {val})")
print("-" * 35)
print(f"Trace a_p at p={p}: {E.ap(p)}")
---
OUTPUT:
Detected required degree: 4
Defining polynomial for the p-adic extension: (1 + O(5^20))*x^4 + O(5^20)*x^3 + (4 + O(5^20))*x^2 + (4 + O(5^20))*x + 2 + O(5^20)
The generator 'a' satisfies: (1 + O(5^20))*x^4 + O(5^20)*x^3 + (4 + O(5^20))*x^2 + (4 + O(5^20))*x + 2 + O(5^20)
--- 5-adic Grid Shuffle (The Frobenius Lift) ---
Root 0: (a^3 + 3*a^2 + 3*a + 4) + (a^2 + 4*a + 3)*5 + (2*a^2 + 4*a + 4)*5^2 + (4*a^3 + 2*a^2 + 4*a + 1)*5^3 + (a + 3)*5^4 + (4*a^3 + a^2 + 4)*5^5 + (a^3 + 4*a)*5^6 + (3*a^2 + a + 2)*5^7 + (3*a^3 + a^2 + 2*a + 2)*5^8 + (3*a^3 + 2*a^2 + 2*a)*5^9 + a^2*5^10 + (2*a^3 + 3*a + 2)*5^11 + (a^3 + 3*a + 4)*5^12 + (4*a^3 + 4*a^2 + a)*5^13 + (3*a^3 + 4*a + 3)*5^14 + (4*a^2 + a)*5^15 + (3*a^3 + 2*a^2)*5^16 + (4*a^3 + 4*a^2 + a + 3)*5^17 + 3*a^2*5^18 + (2*a^2 + 3*a + 1)*5^19 + O(5^20)
Root 0 maps to: (4*a^3 + 3*a + 2) + (a^3 + 4*a)*5 + (2*a^3 + 3*a + 2)*5^2 + (a^3 + 2*a + 4)*5^3 + (a^3 + a^2)*5^4 + (4*a^2 + 3*a + 4)*5^5 + (a^3 + 3*a^2 + a)*5^6 + (a^3 + 4*a)*5^7 + (2*a^3 + 4*a + 2)*5^8 + (a^3 + a^2 + 2*a + 1)*5^9 + (4*a^3 + 3*a^2 + a + 4)*5^10 + (2*a^3 + 4*a^2 + a + 2)*5^11 + a^2*5^12 + (3*a^3 + 4*a^2 + a + 3)*5^13 + (2*a^3 + a^2 + 1)*5^14 + (a^3 + 2*a^2 + 2*a + 4)*5^15 + (2*a^3 + 2*a^2 + 4*a + 1)*5^16 + (3*a^3 + 4*a^2 + 2*a + 4)*5^17 + (3*a^2 + 4)*5^18 + (a^3 + 3*a^2)*5^19 + O(5^20)
-> Still in the grid? True (Valuation: 20)
-----------------------------------
Root 1: (a^3 + 2*a + 3) + (3*a^3 + 4)*5 + (2*a^3 + a + 2)*5^2 + (3*a^3 + 2*a)*5^3 + (3*a^3 + 4*a^2 + 4*a + 4)*5^4 + (4*a^3 + a)*5^5 + (3*a^3 + a^2 + 3*a + 4)*5^6 + (3*a^3 + 4*a^2 + 4)*5^7 + (2*a^3 + 4*a^2 + 2)*5^8 + (3*a^3 + 3*a^2 + 2*a + 3)*5^9 + (a^2 + 3*a)*5^10 + (2*a^3 + 3*a + 2)*5^11 + (4*a^3 + 3*a^2 + 4*a + 4)*5^12 + (a^3 + 3*a + 1)*5^13 + (2*a^3 + 3*a^2 + 4*a + 3)*5^14 + (3*a^3 + 2*a^2 + 2*a)*5^15 + (2*a^3 + 2*a^2 + 3)*5^16 + (a^3 + 2*a)*5^17 + (4*a^3 + a^2 + 4*a)*5^18 + (3*a^3 + a^2 + 4*a + 4)*5^19 + O(5^20)
Root 1 maps to: (a^3 + 3*a^2 + 3*a + 4) + (a^2 + 4*a + 3)*5 + (2*a^2 + 4*a + 4)*5^2 + (4*a^3 + 2*a^2 + 4*a + 1)*5^3 + (a + 3)*5^4 + (4*a^3 + a^2 + 4)*5^5 + (a^3 + 4*a)*5^6 + (3*a^2 + a + 2)*5^7 + (3*a^3 + a^2 + 2*a + 2)*5^8 + (3*a^3 + 2*a^2 + 2*a)*5^9 + a^2*5^10 + (2*a^3 + 3*a + 2)*5^11 + (a^3 + 3*a + 4)*5^12 + (4*a^3 + 4*a^2 + a)*5^13 + (3*a^3 + 4*a + 3)*5^14 + (4*a^2 + a)*5^15 + (3*a^3 + 2*a^2)*5^16 + (4*a^3 + 4*a^2 + a + 3)*5^17 + 3*a^2*5^18 + (2*a^2 + 3*a + 1)*5^19 + O(5^20)
-> Still in the grid? True (Valuation: 20)
-----------------------------------
Root 2: (4*a^3 + 2*a^2 + 2*a + 1) + (4*a^3 + 3*a^2 + 1)*5 + (4*a^3 + 2*a^2)*5^2 + (2*a^2 + 3)*5^3 + (4*a^3 + 4*a^2 + 3*a + 1)*5^4 + (3*a^2 + 4*a)*5^5 + (3*a^3 + 4*a^2 + 4)*5^6 + (4*a^3 + a^2 + 3*a + 2)*5^7 + (a^3 + 3*a^2 + 2*a + 2)*5^8 + (a^3 + 2*a^2 + 2*a + 4)*5^9 + (4*a^3 + 3*a^2 + 4*a + 4)*5^10 + (2*a^3 + 4*a^2 + a + 2)*5^11 + (3*a^3 + 4*a^2 + a)*5^12 + (3*a + 4)*5^13 + (a^3 + 4*a^2 + 1)*5^14 + (4*a^3 + 3*a + 4)*5^15 + (a^3 + 2*a^2 + 4*a + 4)*5^16 + (3*a + 1)*5^17 + (4*a^3 + a^2 + 4*a + 4)*5^18 + (4*a^3 + 2*a^2 + a + 3)*5^19 + O(5^20)
Root 2 maps to: (a^3 + 2*a + 3) + (3*a^3 + 4)*5 + (2*a^3 + a + 2)*5^2 + (3*a^3 + 2*a)*5^3 + (3*a^3 + 4*a^2 + 4*a + 4)*5^4 + (4*a^3 + a)*5^5 + (3*a^3 + a^2 + 3*a + 4)*5^6 + (3*a^3 + 4*a^2 + 4)*5^7 + (2*a^3 + 4*a^2 + 2)*5^8 + (3*a^3 + 3*a^2 + 2*a + 3)*5^9 + (a^2 + 3*a)*5^10 + (2*a^3 + 3*a + 2)*5^11 + (4*a^3 + 3*a^2 + 4*a + 4)*5^12 + (a^3 + 3*a + 1)*5^13 + (2*a^3 + 3*a^2 + 4*a + 3)*5^14 + (3*a^3 + 2*a^2 + 2*a)*5^15 + (2*a^3 + 2*a^2 + 3)*5^16 + (a^3 + 2*a)*5^17 + (4*a^3 + a^2 + 4*a)*5^18 + (3*a^3 + a^2 + 4*a + 4)*5^19 + O(5^20)
-> Still in the grid? True (Valuation: 20)
-----------------------------------
Root 3: (4*a^3 + 3*a + 2) + (a^3 + 4*a)*5 + (2*a^3 + 3*a + 2)*5^2 + (a^3 + 2*a + 4)*5^3 + (a^3 + a^2)*5^4 + (4*a^2 + 3*a + 4)*5^5 + (a^3 + 3*a^2 + a)*5^6 + (a^3 + 4*a)*5^7 + (2*a^3 + 4*a + 2)*5^8 + (a^3 + a^2 + 2*a + 1)*5^9 + (4*a^3 + 3*a^2 + a + 4)*5^10 + (2*a^3 + 4*a^2 + a + 2)*5^11 + a^2*5^12 + (3*a^3 + 4*a^2 + a + 3)*5^13 + (2*a^3 + a^2 + 1)*5^14 + (a^3 + 2*a^2 + 2*a + 4)*5^15 + (2*a^3 + 2*a^2 + 4*a + 1)*5^16 + (3*a^3 + 4*a^2 + 2*a + 4)*5^17 + (3*a^2 + 4)*5^18 + (a^3 + 3*a^2)*5^19 + O(5^20)
Root 3 maps to: (4*a^3 + 2*a^2 + 2*a + 1) + (4*a^3 + 3*a^2 + 1)*5 + (4*a^3 + 2*a^2)*5^2 + (2*a^2 + 3)*5^3 + (4*a^3 + 4*a^2 + 3*a + 1)*5^4 + (3*a^2 + 4*a)*5^5 + (3*a^3 + 4*a^2 + 4)*5^6 + (4*a^3 + a^2 + 3*a + 2)*5^7 + (a^3 + 3*a^2 + 2*a + 2)*5^8 + (a^3 + 2*a^2 + 2*a + 4)*5^9 + (4*a^3 + 3*a^2 + 4*a + 4)*5^10 + (2*a^3 + 4*a^2 + a + 2)*5^11 + (3*a^3 + 4*a^2 + a)*5^12 + (3*a + 4)*5^13 + (a^3 + 4*a^2 + 1)*5^14 + (4*a^3 + 3*a + 4)*5^15 + (a^3 + 2*a^2 + 4*a + 4)*5^16 + (3*a + 1)*5^17 + (4*a^3 + a^2 + 4*a + 4)*5^18 + (4*a^3 + 2*a^2 + a + 3)*5^19 + O(5^20)
-> Still in the grid? True (Valuation: 20)
-----------------------------------
Trace a_p at p=5: 2
Interpretation: This output is the definitive proof that the
L-function of an elliptic curve is built on a foundation of perfect
\(p\)-adic symmetry. The
Still in the grid? True: seeing
True (Valuation: 20): By using the
.frobenius() lifting in the Qq extension, we
successfully shuffled the torsion points without causing them to
“drift.”
The Precision: A valuation of \(20\) means that even at a resolution of \(5^{20}\) (about \(95\) trillion sub-tiles on our donut), the point landed exactly in another seat in the grid. This confirms that the Frobenius map is a true automorphism of the curve’s arithmetic structure.
Look at the expanded strings like \((4*a^3 + 3*a + 2) + (a^3 + 4*a)*5\dots\) The first term (e.g., \(4a^3 + 3a + 2\)): This is the location of the point on the “coarse” grid of the finite field \(\mathbb{F}_{5^d}\). The powers of \(5:\) These are the “digital signatures” of the Tate Module. Each subsequent term is a higher-resolution refinement of the point’s position.
The Trace \(a_p = 2\): This single integer is the ultimate “summary” of that massive digital shuffle. In our experiment, the Frobenius map took each of the \(4\) roots and moved them to different addresses. The Trace (\(a_5 = 2\)) is the mathematical result of summing the “diagonal” of the \(2 \times 2\) matrix that represents this shuffle. This number tells us that over the finite field \(\mathbb{F}_5\), the curve has \(N_p = p + 1 - a_p = 5 + 1 - 2 = \mathbf{4}\) points.
We have just manually verified one “Euler Factor” of the L-function. Because the grid stayed intact (True), we know the representation is stable. The L-function is just a massive product: \(L(E, s) = \prod_{p} \frac{1}{1 - a_p p^{-s} + p^{1-2s}}\). For \(p=3\), we found \(a_3 = 0\). For \(p=5\), we found \(a_5 = 2\). Each prime \(p\) provides one of these \(a_p\) “heartbeats.” By proving that the \(p\)-adic addresses shuffle perfectly, we’ve shown that the curve’s internal geometry is consistent enough to be studied as a global analytic function.
We’ve moved from the Geometric \((y^2 = x^3 + x)\) to the Arithmetic (p-adic addresses) to the Analytic (\(a_p\) values). This is the exact path taken by researchers proving the Modularity Theorem. We are essentially looking at the “source code” of the connection between elliptic curves and modular forms.
But how are these roots constructed?
The structure of the “digits” (\(a\)) comes from the prime \(\ell\), but the “resolution” (\(5^0, 5^1, 5^2 \dots\)) comes from the prime \(p\). The digits are calculated to satisfy the the division polynomial across higher powers of \(p\)
In a \(p\)-adic expansion like:
\[\text{root of }\psi_{\ell} = d_0 + d_1 p^1 + d_2 p^2 + \dots\]
Each coefficient (\(d_k\)) is found by looking at the division polynomial \(\psi_{\ell}\) modulo higher powers of \(p\).
\(d_0\) is a root of \(\psi_{\ell} \pmod p\).
\(d_1\) is calculated so that \((d_0 + d_1 p)\) is a root of \(\psi_{\ell} \pmod{p^2}\).
\(d_2\) is calculated so that \((d_0 + d_1 p + d_2 p^2)\) is a root of \(\psi_{\ell} \pmod{p^3}\).
This process is called Hensel’s Lemma. It is like using Newton’s method to find a root, but instead of getting more decimal places, you are getting more \(p\)-adic places (powers of \(p\)).
From the basics, what is a:
Each digit \(d_i\) in our \(p\)-adic string \(d_0 + d_1 p^1 + d_2 p^2 + \dots\) is a polynomial in \(a\):
\[d_i = c_0 + c_1 a + c_2 a^2 + c_3 a^3\]
The coefficients \(c_j\) are just integers from \(\{0, 1, 2, 3, 4\}\).
The \(a\) is essentially a placeholder for the internal symmetry of the donut’s loops. a is the root of the polynomial that defines the symmetry of the \(\ell=3\) torsion.
Since you are looking at \(3\)-torsion, there are \(8\) non-trivial points (\(3^2 - 1\)).
The division polynomial \(\psi_3(x)\) can be found in the lines:
Defining polynomial for the p-adic digits: (1 + O(5^20))*x^4 + O(5^20)*x^3 + (4 + O(5^20))*x^2 + (4 + O(5^20))*x + 2 + O(5^20)
The 'digit' a satisfies: (1 + O(5^20))*x^4 + O(5^20)*x^3 + (4 + O(5^20))*x^2 + (4 + O(5^20))*x + 2 + O(5^20)
i.e. the polynomial \[\psi_3(x) = 3x^4 + 6x^2 - 1\]
If \(i\) in complex numbers is defined by the rule \(i^2 + 1 = 0\), what is the specific “rule” for \(a\)?
For the curve \(y^2 = x^3 + x\) and the prime \(p=5\), we can actually find the rule. The \(3\)-division polynomial is:
\[\psi_3(x) = 3x^4 + 6x^2 - 1\]
which does not change with higher powers of \(p\): we are simply solving the same \(\ell\)-related equation
\[\psi_{\ell}(x) \equiv0 \mod p^n\]
to higher and higher precision. If \(x_i\) is a root modulo \(p^i\)
\[\psi_l(x) \equiv 0 \mod p^i\]
what’s the next digit such that \(x_{i+1}=x_i + d_i p^i,\) where \(x_{i+1}\) is the root modulo \(p^{i+1}\):
\[\psi'(x_0) \cdot d_i \equiv -\frac{\psi(x_i)}{p^i}\mod p\]
or
\[d_i\equiv - \frac{\psi(x_i)}{p^i}\left[ \psi'(x_0)\right]^{-1} \mod p\] The result is a polynomial in \(a\).
When we look at this modulo \(5\), \(\psi_{\ell}(x)\) polynomial becomes:
\[3x^4 + x^2 + 4 \equiv 0 \pmod 5\]
If you factor this over \(\mathbb{F}_5\), you find it is irreducible (it has no roots in the normal numbers \(0, 1, 2, 3, 4\)). So, just as \(i\) is the root of \(x^2+1\), Sage “invents” \(a\) to be the root of this polynomial (or one of its factors).
The rule for your \(a\) is:
\[3a^4 + a^2 + 4 = 0 \mod 5\]
a is the generator of the limited field extension \(\mathbb F_{p^d}.\)
a is the exact symbolic representation of the torsion point. We don’t need to solve for \(a\) because the interest is in how the points move. The shuffling provides the trace \(a_p\), which is a number.
Each digit \(d_k\) in \(d_0 + d_1 p + d_2 p^2 + \cdots\) is a polynomial in \(a.\) For instance \(2a^2 + 4a +4.\) Frobenius applies a field automorphism:
\[\phi_5(2a^2 + 4a +4) = 2(a^5)^2+4(a^5) +4\]
and because \(a\) is defined by \(3a^4+a^2+4=0,\) \(a^5\) can be simplified to a lower power so it stays withing \(4\) dimensional bounds.
To get to the trace \(a_p\) one \(\ell\) is all that is needed. These are the next steps:
We take the roots of your division polynomial \(\psi_\ell\) and label them. For \(\ell=3\), there are \(4\) distinct \(x\)-coordinates. Let’s call them: \(X = \{r_0, r_1, r_2, r_3\}.\) These are the “seats.” In the code output, these were those long \(p\)-adic strings involving \(a\), as for example:
Root 0: (a^3 + 3*a^2 + 3*a + 4) + (a^2 + 4*a + 3)*5 + (2*a^2 + 4*a + 4)*5^2 + (4*a^3 + 2*a^2 + 4*a + 1)*5^3 + (a + 3)*5^4 + (4*a^3 + a^2 + 4)*5^5 + (a^3 + 4*a)*5^6 + (3*a^2 + a + 2)*5^7 + (3*a^3 + a^2 + 2*a + 2)*5^8 + (3*a^3 + 2*a^2 + 2*a)*5^9 + a^2*5^10 + (2*a^3 + 3*a + 2)*5^11 + (a^3 + 3*a + 4)*5^12 + (4*a^3 + 4*a^2 + a)*5^13 + (3*a^3 + 4*a + 3)*5^14 + (4*a^2 + a)*5^15 + (3*a^3 + 2*a^2)*5^16 + (4*a^3 + 4*a^2 + a + 3)*5^17 + 3*a^2*5^18 + (2*a^2 + 3*a + 1)*5^19 + O(5^20)
Next we need to apply the Frobenius map \(\phi_p\) to each root. The Frobenius doesn’t create new roots; it just moves the existing ones around. For example, your output might show:\(\phi_p(r_0) = r_2\), \(\phi_p(r_2) = r_0\), \(\phi_p(r_1) = r_3\), and \(\phi_p(r_3) = r_1\). This is a permutation. In this example, the Frobenius is swapping two pairs of roots.
Move from \(x\)-coordinates to points (The 2D grid). This is the most critical step. An \(x\)-coordinate is just a shadow. Each \(x\)-coordinate (except where \(y=0\)) corresponds to two points on the curve: \((x, y)\) and \((x, -y)\). The \(3\)-torsion points form a \(2\)-dimensional vector space over \(\mathbb{F}_3\) (the “donut grid”). We pick a basis for this grid—two points \(P\) and \(Q\) that can generate all others.
\(P = (x_1, y_1)\)
\(Q = (x_2, y_2)\)
To build that \(2 \times 2\) matrix, we need to pick a basis for the torsion group. Since the \(3\)-torsion group is 2-dimensional (like a \(3 \times 3\) grid on a donut), we pick two points, \(P\) and \(Q\), that aren’t just multiples of each other. \(P\) has an \(x\)-coordinate, let’s call it \(x_P\). \(Q\) has an \(x\)-coordinate, let’s call it \(x_Q\). These \(x_P\) and \(x_Q\) are indeed two of the roots (the \(r_i\) values) from your division polynomial \(\psi_3.\)
Next we build the matrix. We watch where Frobenius sends our basis points \(P\) and \(Q\). Because the Frobenius is a linear transformation, the result must be some combination of \(P\) and \(Q\):
\(\text{Frob}_p(P) = A \cdot P + C \cdot Q\)
\(\text{Frob}_p(Q) = B \cdot P + D \cdot Q\)
The coefficients \(A, B, C, D\) (which are numbers in \(\mathbb{F}_\ell\)) form our Frobenius Matrix:
\[\text{Frob}_p = \begin{pmatrix} A & B \\ C & D \end{pmatrix}\]
Let’s say we’ve applied the Frobenius to our basis points and gotten two new points, which we will call \(P'\) and \(Q'\): \(\text{Frob}_p(P) = P'\)\(\text{Frob}_p(Q) = Q'\) At this stage, \(P'\) and \(Q'\) are just \(p\)-adic coordinates. You know they are “in the grid,” but you don’t yet know their “grid coordinates” (how many \(P\)s and \(Q\)s they are made of).
Solving for the first column (\(A\) and \(C\)): We need to find which combination of \(P\) and \(Q\) equals \(P'\). In the finite world of \(\ell\)-torsion, there are only \(\ell^2\) possibilities (for \(\ell=3\), that’s only \(9\) points). Test the combinations: Is \(P' = [0]P + [1]Q\)? Is \(P' = [1]P + [1]Q\)? Is \(P' = [2]P + [1]Q\)? When we find the match such that \(P' = [A]P + [C]Q\), we have found the first column of your matrix.
Solving for the second column (\(B\) and \(D\)): We do the exact same thing for \(Q'\). We test combinations until we find: \[Q' = [B]P + [D]Q\] These coefficients \(B\) and \(D\) give us the second column.
Finally, extract the trace (\(a_p\)). Once we have the matrix, the \(a_p \pmod \ell\) is simply the trace:
\[a_p \equiv A + D \pmod \ell\]
If the matrix is
\[\begin{pmatrix} 1 & 1 \\ 0 & 1 \end{pmatrix}\] the trace is \(1+1=2\).
This matches the \(a_p = 2\) in our output!
Now, the Frobenius map \(\phi_p\) acts on this 2D space \(T_\ell(E)\) just like a \(2 \times 2\) matrix. From linear algebra, every \(2 \times 2\) matrix \(M\) has a characteristic polynomial:
\[P(T) = \det(T \cdot I - M) = T^2 - \text{Tr}(M)T + \det(M)\]
When we apply this to the Frobenius matrix:
The Determinant is always \(p\).
The Trace (the sum of the diagonal) is exactly our \(a_p\).
So the polynomial that describes the curve’s “DNA” at prime \(p\) is:
\[P_p(T) = T^2 - a_p T + p\]
Finally, to get the L-function, we take these individual polynomials \(P_p(T)\) and “package” them. We use the reciprocal of the polynomial and evaluate it at \(T = p^{-s}\) in what are known as Euler factors or local factors:
\[L_p(s) = \frac{1}{1 - a_p p^{-s} + p \cdot p^{-2s}}\]
The shift from \(T^2 - a_p T + p\) to \(1 - a_p T + p T^2\) happens because we aren’t just plugging in a value; we are moving to the reciprocal polynomial. In linear algebra, if a matrix \(M\) has eigenvalues \(\lambda_1, \lambda_2\), its characteristic polynomial is:
\[P(T) = \text{det}(T \cdot I - M) = T^2 - \text{Trace}(M)T + \text{det}(M)\]
However, when we build a generating function (like an L-function), we want to describe the “flow” of the data using a power series. To do this, we use the Reciprocal Polynomial, which is defined as:
\[P^*(T) = T^2 P(1/T) = 1 - \text{Trace}(M)T + \text{det}(M)T^2\]
The “1 -” structure is required for the Euler Product to work. In number theory, we want to represent the L-function as a sum that looks like the Riemann Zeta function:
\[\sum \frac{a_n}{n^s} = \prod_p \frac{1}{\text{Polynomial}(p^{-s})}\]
For a fraction like \(\frac{1}{1 - X}\) to be expanded into a series (\(1 + X + X^2 + \dots\)), the denominator must start with 1. If we used \(T^2 - a_p T + p\), the expansion would be messy and wouldn’t match the \(a_n\) coefficients of our elliptic curve. By using \(1 - a_p T + p T^2\), the expansion begins:
\[1 + (a_p)T + (a_p^2 - p)T^2 + \dots\]
When you plug in \(T = p^{-s}\), the first term is \(1\), and the second term is \(a_p p^{-s}\), which is exactly the \(p\)-th term of the Dirichlet series we are trying to build.
The packaging of all these polynomials usually is written as
\[L(E, s) = \prod_{p \nmid \Delta} \frac{1}{1 - a_p p^{-s} + p \cdot p^{-2s}} \times \prod_{p \mid \Delta} L_p(s)\]
\(p \nmid \Delta\) are the good primes: For almost all primes (those where the curve doesn’t have a “glitch” or singularity), the factor is exactly the product of Euler factors. It represents the characteristic polynomial of the \(2 \times 2\) Frobenius matrix. The \(p^{-2s}\) term is there specifically because the matrix is 2-dimensional.
\(p \mid \Delta\)): For the few primes where the curve has a cusp or a node, the matrix collapses. If it collapses to \(1\)D, the factor is \(\frac{1}{1 - a_p p^{-s}}\). If it collapses to \(0\)D, the factor is simply \(1\). This is why the product is usually written in two parts.
When you multiply this infinite “wall” of fractions together, you get the Dirichlet series (see below (**)):
\[L(E, s) = \sum_{n=1}^{\infty} \frac{a_n}{n^s}\]
The polynomial \(P_p(T) = T^2 - a_p T + p\) is the standard characteristic polynomial of the Frobenius matrix \(M\): the Frobenius matrix \(M\) is the linear representation of the Frobenius endomorphism \(\phi_p\) as it acts on the Tate module \(T_\ell(E)\). Because the Tate module is a 2-dimensional vector space over the \(\ell\)-adic integers \(\mathbb{Z}_\ell\), any linear transformation on it (like Frobenius) can be written as a \(2 \times 2\) matrix:
\[M = \begin{pmatrix} \alpha & \beta \\ \gamma & \delta \end{pmatrix}\]
The entries \(\alpha, \beta, \gamma, \delta\) are \(\ell\)-adic integers. Their specific values depend on the basis you choose for your grid of torsion points. While the individual entries change if you pick a different basis, the invariants of the matrix do not change. For any elliptic curve \(E\) at a prime \(p\) of good reduction:
The Trace: \(\text{Tr}(M) = \alpha + \delta = a_p\)
The Determinant: \(\det(M) = \alpha\delta - \beta\gamma = p\)
The characteristic polynomial \(P_p(T)\) is defined as the determinant of
\[(T \cdot I - M)\]
Using the invariants above:
\[P_p(T) = \det(T \cdot I - M)\]
\[P_p(T) = \det \begin{pmatrix} T - \alpha & -\beta \\ -\gamma & T - \delta \end{pmatrix}\]
\[P_p(T) = (T - \alpha)(T - \delta) - (-\beta)(-\gamma)\]
\[P_p(T) = T^2 - (\alpha + \delta)T + (\alpha\delta - \beta\gamma)\]
\[P_p(T) = T^2 - a_p T + p\]
However, when we build an L-function, we aren’t interested in the eigenvalues themselves as much as we are interested in how they “scale” our series. In complex analysis and number theory, we use a slightly different determinant construction for Euler products:
\[\text{Local Factor} = \frac{1}{\det(I - M \cdot T)}\]
where \(T = p^{-s}\).
Watch what happens when we expand \(\det(I - M \cdot T)\) for a \(2 \times 2\) matrix \(M\): The identity \(I\) is \(\begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}\). The term \(M \cdot T\) is
\[\begin{pmatrix} m_{11}T & m_{12}T \\ m_{21}T & m_{22}T \end{pmatrix}\]
The subtraction \(I - MT\) is
\[\begin{pmatrix} 1 - m_{11}T & -m_{12}T \\ -m_{21}T & 1 - m_{22}T \end{pmatrix}\]
When you calculate the determinant of that result:
\[\det(I - MT) = (1 - m_{11}T)(1 - m_{22}T) - (-m_{12}T)(-m_{21}T)\]
\[= 1 - (m_{11} + m_{22})T + (m_{11}m_{22} - m_{12}m_{21})T^2\]
Notice the results: The constant is now \(1\).The coefficient of \(T\) is the Trace (\(a_p\)). The coefficient of \(T^2\) is the Determinant (\(p\)).
The reason we want the “1” at the front is to allow the local factor to be expanded into a geometric series. If the denominator started with \(p\) (like \(p - a_p T + T^2\)), we couldn’t easily turn it into an infinite sum starting with \(1\). By having the denominator start with \(1\):
\[\frac{1}{1 - (a_p T - p T^2)} = 1 + (a_p T - p T^2) + (a_p T - p T^2)^2 + \dots\]
This expansion ensures that the very first term of the L-function is \(1\). When you multiply all these local factors together (\(1 \cdot 1 \cdot 1 \dots\)), we get the starting term of the global Dirichlet series:
\[L(E, s) = \mathbf{1} + \frac{a_2}{2^s} + \frac{a_3}{3^s} + \dots\]
In summary\(T^2 - a_p T + p\) is the polynomial whose roots are the eigenvalues of Frobenius.
\(1 - a_p T + p T^2\) is the reciprocal polynomial. Its roots are the inverses of the eigenvalues. We use the reciprocal version because it lets us expand the L-function into a series that starts with \(1\), perfectly matching the structure of the integers in our sum.
The global L-function is simply the product of all these local pieces for every prime \(p\):
\[L(E, s) = \prod_{p} L_p(s)\]
This product, when multiplied out, creates the infinite sum (Dirichlet series) \(\sum a_n n^{-s}\) that links the curve’s point-counting to the world of complex analysis and modular forms.
Let’s look at a concrete example using a very small prime so we can see every “ingredient” at work. We’ll take the elliptic curve \(E\):
\[y^2 = x^3 + x\]
And we will look at it through the lens of the prime \(p = 3\).
First, we look for points in our field \(\mathbb{F}_3 = \{0, 1, 2\}\). We test every \(x\):
If \(x=0\): \(y^2 = 0 \implies y=0\). Point: \((0,0)\)
If \(x=1\): \(y^2 = 1+1 = 2\). In \(\mathbb{F}_3\), there is no number that squared equals \(2\). No points.
If \(x=2\): \(y^2 = 8 + 2 = 10 \equiv 1 \pmod 3 \implies y=1\) or \(y=2\). Points: \((2,1)\) and \((2,2)\)
Don’t forget the Point at infinity: \(\mathcal{O}\)
Total points \(N_3 = 4\). Our trace of Frobenius is \(a_3 = (3 + 1) - 4 = \mathbf{0}\).
Now, let’s pick our “measuring stick” \(\ell = 2\). We want to find the \(2^2 = 4\) points that satisfy \(2P = \mathcal{O}\).
These are the points where \(y=0\), because adding a point twice resulting in the point at infinity means that the tangent is vertical, which means \(x^3 + x = 0\).
Solving \(x(x^2 + 1) = 0\) in \(\mathbb{F}_3\):
\(x = 0\) (We already found this: \((0,0)\))
\(x^2 + 1 = 0 \implies x^2 = -1 \equiv 2 \pmod 3\)
In \(\mathbb{F}_3\), there is no square root of \(2\). To find these points, we must go to the “complex” extension field \(\mathbb{F}_{3^2}\) (which we can think of as \(\mathbb{F}_3[i]\) where \(i^2 = 2\)). In this larger field, our missing \(x\)-coordinates are \(i\) and \(-i\). In \(\mathbb{F}_3\), notice that: \(2 \equiv -1 \pmod 3\). So \(i^2 = 2\) is literally saying \(i^2 = -1\). This makes \(i\) the perfect name for this element! It behaves almost exactly like the imaginary unit we know from calculus or physics, but it lives in a world with only 9 numbers total (\(\mathbb{F}_{3^2}\)).
Our 2-torsion grid is:
\[\{\mathcal{O}, (0,0), (i, 0), (-i, 0)\}\]
Now we apply the “shuffling engine” \(\phi_3(x, y) = (x^3, y^3)\) to our grid:
\[\phi_3(\mathcal{O}) = \mathcal{O}\quad\text{fixed}\]
\[\phi_3(0, 0) = (0^3, 0^3) = (0,0)\quad\text{fixed}\]
\[\phi_3(i, 0) = (i^3, 0^3)\]
What is \(i^3\)? Since \(i^2 = 2\), then \(i^3 = 2i \equiv -i \pmod 3\). So, \(\phi_3\) swaps the two “complex” points:
\[(i, 0) \to (-i, 0) \quad \text{and} \quad (-i, 0) \to (i, 0)\]
To make the matrix, we choose a basis. Let \(E_1 = (0,0)\) and \(E_2 = (i,0)\).
\(\phi_3(E_1) = 1 \cdot E_1 + 0 \cdot E_2\) (It stayed put)
\(\phi_3(E_2) = 0 \cdot E_1 + (-1) \cdot E_2\) (It became its negative sibling)
The matrix is:
\[M = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}\]
Now, calculate the “DNA” of the matrix:
Determinant: \((1)(-1) - (0)(0) = -1\). Wait! We expected \(p=3\). But remember, this matrix is working in the world of \(\ell=2\). In the world of “integers modulo \(2\),” \(-1 \equiv 1 \pmod 2\).
Trace: \(1 + (-1) = \mathbf{0}\).
Our matrix approach gave us a Trace of \(0.\) Our “counting points” approach in Step 1 gave us \(a_3 = 0\). They match perfectly. The “complex” shuffling of the hidden points in the extension field tells us exactly how many “real” points were in our starting field.
For the L-function, we now know the piece for \(p=3\) is:
\[L_p(E, s) = \frac{1}{1 - a_p p^{-s} + p \cdot p^{-2s}}\]
and therefore,
\[L_3(s) = \frac{1}{1 - 0(3^{-s}) + 3(3^{-2s})} = \frac{1}{1 + 3^{1-2s}}\]
(*) On one side we have a purely arbitrary decision: we choose any prime number different to \(p\). Say, \(111181821213.\) We are now imagining a lattice of \(111181821213^2\) points. And we say, we want \(a_5\). So we have to operate \(p =5.\) No problem. We have to find the torsion points with coordinates \(x\) and \(y\) in \(\mathbb F_{p^k}\) among all the points on the curve under the field \(\mathbb F_{p^k}\) that are \(111181821213\)-torsion points, i.e. points such that \(111181821213 P =\mathcal O.\) To do so we would need a much larger number system than \(\mathbb F_5\) to describe them, and hence the horizontal extension to \(\mathbb F_{p^k}\). Now, we don’t actually do this literally. We just get two points instead by using the division polynomial, build a matrix (Frobenius) and use linearity to get the trace. Since the \(\ell\)-torsion grid is essentially a 2D plane (the \(2 \times 2\) matrix), you only need two independent points to see how the whole plane rotates. If you find one point in \(\mathbb{F}_{p^{234}}\), you’ve found a “spoke” of the wheel.
But the idea is that if there were points, say \(w \in W,\) with coordinates \(x\) and \(y\) in the base field \(\mathbb F_5,\) which multiplied \(111181821213 w =\mathcal O\) the Frobenius map would not move them. The chances of finding any \(w\) besides \(\mathcal O\) may be zero; however, we don’t care because we have a division polynomial that expects \(111181821213\) roots in \(F_{p^k},\) so all we have to do is extend the \(k.\)
Because we are interested in the trace of a linear transformation, we only need two independent ‘spokes’ to define the rotation of the entire lattice. Suppose one of these points, \(q\), is found in the extension field \(\mathbb{F}_{p^{234}}\). At this stage, the coordinates of \(q\) are only known at precision \(1,\) meaning we only see the first digit, \(v = d_0 \pmod p\). We need two of these points to construct the Frobenius matrix, but we cannot afford any ‘blurriness’ in our calculation of the trace (\(a_p\)). If we stayed at this low resolution, we couldn’t tell the difference between the true \(p\)-adic coordinate and one shifted by a multiple of \(p\) (e.g., \(v\) vs. \(v + 6p\)). Since \(a_p\) is a specific integer like \(-3\), and matrix math compounds any small errors, a ‘blurry’ coordinate would leave us unable to distinguish the correct \(a_p\) from a sea of massive, incorrect integers. To fix this, we make \(q\) precise by lifting with Hensel, increasing the resolution from \(\pmod p\) to a high-definition string known to \(\pmod{p^{20}}\).
To translate from the field \(\mathbb{F}_{p^{234}}\) to the ring \(\mathbb{Z}_{p^{20}}\), we take the “flat” element from the finite field and treat it as the seed for an infinite \(p\)-adic string (integer). The intersection between these two systems exists because the first floor of the \(p\)-adic ring \(\mathbb{Z}_p\) is identical to the base field \(\mathbb{F}_p\). Mathematically, we say there is a map:
\[\mathbb{Z}_p \to \mathbb{Z}/p\mathbb{Z} \cong \mathbb{F}_p\]
When we create \(\mathbb{F}_{p^{234}}\), we aren’t just making the base field larger. We are adding a new, symbolic element — let’s call it \(\alpha\) — that acts as a root to an irreducible polynomial of degree \(234.\) Every number in this field is forced to be written as a combination of powers of that \(\alpha\). If you found a point \(q\) in this field, its \(x\)-coordinate isn’t a single digit. It looks like this:
\[x_q = c_0 + c_1 \alpha + c_2 \alpha^2 + \dots + c_{233} \alpha^{233}\]
Each \(c_i\) is a number from the base field \(\mathbb{F}_p\) (like \(0, 1, 2, 3,\) or \(4\) if \(p=5\)). This is the polynomial.
Example:
The field extension (\(\mathbb{F}_{5^2}\)): Imagine our torsion point \(q\) exists in a field where we’ve added a “ghost” number \(\alpha\) such that \(\alpha^2 = 2\), akin to \(i^2=-1\). In this field, every number is a polynomial: \(c_0 + c_1\alpha\). Let’s say we find a point \(q\) in the field \(\mathbb{F}_{5^2}\) with \(x\)-coordinate:
\[x_q = 1 + 2\alpha\]
This is our \(d_0\). It’s a “polynomial digit.” Now we want to lift this to Precision 2 (\(\pmod{25}\)). Now we are looking for a “first floor” \(d_1\), but this \(d_1\) must also be a polynomial in \(\alpha\).
(**) Take one piece of the product for a prime \(p\). Using the geometric series formula \(\frac{1}{1-X} = 1 + X + X^2 + \dots\), we expand the denominator:
\[L_p(s) = \frac{1}{1 - a_p p^{-s} + p \cdot p^{-2s}}\]
If we let \(T = p^{-s}\), the factor looks like
\[\frac{1}{1 - (a_p T - p T^2)}\]
When you expand this out,
\[X = (a_p T - p T^2)\]
Using the formula \(\frac{1}{1-X} = 1 + X + X^2 + X^3 + \dots\), and plugging in your \(X\), we get:
\[1 + (a_p T - p T^2) + (a_p T - p T^2)^2 + (a_p T - p T^2)^3 + \dots\]
Expanding out:
The 0th power: \(1\)
The 1st power \((X^1)\): \(a_p T - p T^2\)
The 2nd power \((X^2)\): \((a_p T - p T^2)^2 = (a_p T)^2 - 2(a_p T)(p T^2) + (p T^2)^2= a_p^2 T^2 - 2a_p p T^3 + p^2 T^4\)
The 3rd power \((X^3)\): \((a_p T - p T^2)^3 = (a_p T)^3 - 3(a_p T)^2(p T^2) + \dots= a_p^3 T^3 - 3a_p^2 p T^4 + \dots\)
Now we “harvest” all the pieces for each specific power of \(T\):
For \(T^1\): The only place a \(T^1\) appears is in the first power \((X^1)\). Coefficient: \(a_p\)
For \(T^2\): We get a \(-p\) from the \(X^1\) term and an \(a_p^2\) from the \(X^2\) term. Coefficient: \((a_p^2 - p)\)
For \(T^3\):We get a \(-2a_p p\) from the \(X^2\) term and an \(a_p^3\) from the \(X^3\) term. Coefficient: \((a_p^3 - 2a_p p)\)
Finally we get:
\[1 + (a_p)T + (a_p^2 - p)T^2 + (a_p^3 - 2pa_p)T^3 + \dots\]
Now, we define \(a_{p^k}\) to be the coefficient of the \(T^k\) term (which is \(p^{-ks}\)).
For \(k=1\): \(a_p = a_p\)
For \(k=2\): \(a_{p^2} = a_p^2 - p\)
For \(k=3\): \(a_{p^3} = a_p a_{p^2} - p a_p\)
This recurrence relation is actually the recursive “DNA” of the elliptic curve. It tells you exactly how to build the value for a power of a prime using only the \(a_p\) and the prime \(p\) itself.
Multiplying the Primes Together. Now, imagine doing this for \(p=2\), \(p=3\), \(p=5\), and so on:
\[L(E, s) = \left( 1 + \frac{a_2}{2^s} + \frac{a_4}{4^s} + \dots \right) \times \left( 1 + \frac{a_3}{3^s} + \frac{a_9}{9^s} + \dots \right) \times \left( 1 + \frac{a_5}{5^s} + \dots \right)\]
When you multiply these together, you pick one term from every set of parentheses. For example, picking \(\frac{a_2}{2^s}\) and \(\frac{a_3}{3^s}\) gives you \(\frac{a_2 a_3}{(2 \cdot 3)^s}\), which we define as \(\frac{a_6}{6^s}\).
Because every integer \(n\) has a unique prime factorization, every possible fraction \(\frac{a_n}{n^s}\) appears exactly once in the final result. The “wall of fractions” has successfully been converted into a single, infinite sum:
\[L(E, s) = \frac{a_1}{1^s} + \frac{a_2}{2^s} + \frac{a_3}{3^s} + \frac{a_4}{4^s} + \dots = \sum_{n=1}^{\infty} \frac{a_n}{n^s}\]