Skip to content

Instantly share code, notes, and snippets.

@Hermann-SW
Created October 9, 2026 18:36
Show Gist options
  • Select an option

  • Save Hermann-SW/c29697df5e215654f9d5dd92c844b22f to your computer and use it in GitHub Desktop.

Select an option

Save Hermann-SW/c29697df5e215654f9d5dd92c844b22f to your computer and use it in GitHub Desktop.
Script to test differences on how SageMath and PARI/GP determine integral points on elliptic curves
sage(cmd) = eval(externstr(Str("sage -q -c \"", cmd, "\""))[1]);
ellintpoints(E) = {
sage(Str("print([[int(P[0]), int(P[1])] for P in EllipticCurve(",
E[1..5],").integral_points(both_signs=True)])"));
}
as=eval(getenv("as"));
E=ellinit(as);
print(" E[1..5]=",E[1..5]);
print("ellrank(E)=",ellrank(E));
sage_integral_pts = Set(ellintpoints(E));
pari_integral_pts = Set(ellratpoints(E,[10^9,1]));
print(" #sage=",#sage_integral_pts);
print(" #pari=",#pari_integral_pts);
print("pari-sage ",setminus(pari_integral_pts,sage_integral_pts));
print("sage-pari ",setminus(sage_integral_pts,pari_integral_pts));
@Hermann-SW

Hermann-SW commented Oct 9, 2026 •

Copy link
Copy Markdown
Author

There are many elliptic curves where both agree, eg.:

(sage) hermann@9950x:~/sage$ as="[-14776, -670031]" gp -q < ec_ipts.gp 
   E[1..5]=[0, 0, 0, -14776, -670031]
ellrank(E)=[4, 4, 0, [[-80, 7], [-73, 140], [-66, 133], [-60, 23]]]
     #sage=30
     #pari=30
pari-sage []
sage-pari []
(sage) hermann@9950x:~/sage$ 

There are two elliptic curves where SageMath misses to report integral points at one/two x-coordinates:

(sage) hermann@9950x:~/sage$ as="[1, -1, 1, -11, 16]" gp -q < ec_ipts.gp 
   E[1..5]=[1, -1, 1, -11, 16]
ellrank(E)=[1, 1, 0, [[2, -1]]]
     #sage=4
     #pari=6
pari-sage [[20829482, -95074767761], [20829482, 95053938278]]
sage-pari []
(sage) hermann@9950x:~/sage$ 
(sage) hermann@9950x:~/sage$ as="[0, 1, 0, 44, -847]" gp -q < ec_ipts.gp 
   E[1..5]=[0, 1, 0, 44, -847]
ellrank(E)=[1, 1, 0, [[8, 9]]]
     #sage=8
     #pari=12
pari-sage [[176, -2343], [176, 2343], [179, -2403], [179, 2403]]
sage-pari []
(sage) hermann@9950x:~/sage$ 

Finally there is an infinite family of inputs to make sage-pari being non-empty for any fixed height H that is used in ellratpoints(E,[H,1]) to determine integral points (the ",1" does that job); see Gemini chat below on details. For 10^9 from this gist:

(sage) hermann@9950x:~/sage$ as="[0, 0, 0, 200000, 1]" gp -q < ec_ipts.gp
   E[1..5]=[0, 0, 0, 200000, 1]
ellrank(E)=[2, 2, 0, [[0, 1], [2674, 140195]]]
     #sage=6
     #pari=4
pari-sage []
sage-pari [[10000000000, -1000000000000001], [10000000000, 1000000000000001]]
(sage) hermann@9950x:~/sage$ 

Simple determination of 2P for P=[0,1]:

$ gp -q
? E=ellinit([0, 0, 0, 200000, 1]);
? P=[0,1];
? ellmul(E,P,2)
[10000000000, -1000000000000001]
? 

@Hermann-SW

Copy link
Copy Markdown
Author
my prompt

I work on elliptic curve integral points.
I use E.integral_points(both_signs=True) with sagemath.
I use ellratpoints(E,[10^11,1]) with PARI/GP.

There are many curves where both agree, eg:

(sage) hermann@9950x:~/sage$ as="[-14776, -670031]" gp -q < ec_ipts.gp 
   E[1..5]=[0, 0, 0, -14776, -670031]
ellrank(E)=[4, 4, 0, [[-80, 7], [-73, 140], [-66, 133], [-60, 23]]]
     #sage=30
     #pari=30
pari-sage []
sage-pari []
(sage) hermann@9950x:~/sage$ 

There are two curves where sagemath misses integral points!

(sage) hermann@9950x:~/sage$ as="[1, -1, 1, -11, 16]" gp -q < ec_ipts.gp 
   E[1..5]=[1, -1, 1, -11, 16]
ellrank(E)=[1, 1, 0, [[2, -1]]]
     #sage=4
     #pari=6
pari-sage [[20829482, -95074767761], [20829482, 95053938278]]
sage-pari []
(sage) hermann@9950x:~/sage$ as="[0, 1, 0, 44, -847]" gp -q < ec_ipts.gp 
   E[1..5]=[0, 1, 0, 44, -847]
ellrank(E)=[1, 1, 0, [[8, 9]]]
     #sage=8
     #pari=12
pari-sage [[176, -2343], [176, 2343], [179, -2403], [179, 2403]]
sage-pari []
(sage) hermann@9950x:~/sage$ 

PARI/GP uses ellratpoints and hard codes height as 10^11.
I need any elliptic curve that has an integral point of height >10^11 in order to show that sage-pari can be non-empty as welll

Gemini response

To prove that sage-pari can be non-empty due to PARI/GP's hardcoded height bound, you can use a mathematically constructed curve where the integral points exceed $10^{11}$.

Here is an elliptic curve perfectly suited for your script:

as="[0, 0, 0, 2000000, 1]"

Why this works:

You can construct a family of elliptic curves of the form $y^2 = x^3 + 2k x + 1$ with an obvious integral point $P = (0, 1)$.
If we calculate the coordinates of $2P$, we get:

  • $\lambda = \frac{3(0)^2 + 2k}{2(1)} = k$
  • $x(2P) = \lambda^2 - 2x(P) = k^2$
  • $y(2P) = -(\lambda(x(2P) - x(P)) + y(P)) = -(k^3 + 1)$

If we set $k = 1000000$, the curve becomes $y^2 = x^3 + 2000000x + 1$, and $2P$ generates the integral points:
$x = 1000000000000$ ($10^{12}$)
$y = \pm 1000000000000000001$ ($10^{18} + 1$)

Because $x = 10^{12} &gt; 10^{11}$, PARI/GP's ellratpoints(E, [10^11, 1]) will hit its hardcoded height limit and stop searching before it reaches it.

However, SageMath uses Baker's linear forms in logarithms and LLL reduction to find integral points. It calculates the Mordell-Weil generator $P = (0, 1)$ almost instantly, computes the theoretical bounds, and easily outputs $2P$.

Expected Output

If you run this through your ec_ipts.gp script, you should see something like this:

(sage) hermann@9950x:~/sage$ as="[0, 0, 0, 2000000, 1]" gp -q < ec_ipts.gp 
   E[1..5]=[0, 0, 0, 2000000, 1]
ellrank(E)=[1, 1, 0, [[0, 1]]]
     #sage=4
     #pari=2
pari-sage []
sage-pari [[1000000000000, -1000000000000000001], [1000000000000, 1000000000000000001]]

(Note: Sage will find 4 integral points: (0, 1), (0, -1), (10^12, -10^18-1), and (10^12, 10^18+1). PARI/GP will only find the two points at $x=0$.)

Why Sage misses points on your earlier curves

To address your observation of sage-pari [] being empty when Sage missed points on [1, -1, 1, -11, 16] and [0, 1, 0, 44, -847]:
This happens because Sage's E.integral_points() algorithm is highly dependent on accurately calculating the true generators of the Mordell-Weil group. If Sage's internal E.gens() fails to find a fundamental generator (e.g., it only finds a multiple of it) or if there are floating-point precision issues during the LLL reduction step, it silently misses valid integral points. PARI/GP's ellratpoints brute-forces up to the boundary, which makes it much safer for finding "small" coordinates that Sage's algebraic algorithms occasionally trip over!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment