Skip to content

Commit 6224890

Browse files
author
Release Manager
committed
gh-37094: Fix bug with pari interface in `classical_modular_polynomial` There is a bug in the new `classical_modular_polynomial` function created in #36190. A simple example to reproduce the bug is the following ``` p = 2^216 * 3^137 - 1 F.<i> = GF(p^2, modulus=[1,0,1]) E = EllipticCurve(F, [0, 6, 0, 1, 0]) classical_modular_polynomial(2, E.j_invariant()) ``` This will fail with a `TypeError`. The bug is due to the interface with the pari function `polmodular`. In particular, contrary to the [documentation](http://pari.math.u- bordeaux.fr/dochtml/ref/Polynomials_and_power_series.html#polmodular), the `polmodular` function will only evaluate $\Phi_\ell(j, Y)$ for $j$-invariants that are defined over $\mathbb F_p$, and not over any generic finite field. If however `j.parent()` is a generic finite field, but `j` itself is defined over the prime field, pari will evaluate that and the current implementation fails to convert back to a sage polynomial. The proposed fix is to cast the result of the pari call to `ZZ['Y']`, since the result of `polmodular` currently returns a polynomial in the correct $\mathbb Z/n\mathbb Z[Y]$. #sd123 URL: #37094 Reported by: Riccardo Zanotto Reviewer(s): Frédéric Chapoton, Peter Bruin, Riccardo Zanotto
2 parents 36b13d7 + b372660 commit 6224890

File tree

1 file changed

+22
-3
lines changed

1 file changed

+22
-3
lines changed

src/sage/schemes/elliptic_curves/mod_poly.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,24 @@ def classical_modular_polynomial(l, j=None):
8585
sage: j = GF(q).random_element()
8686
sage: l = random_prime(50)
8787
sage: Y = polygen(parent(j), 'Y')
88-
sage: classical_modular_polynomial(l,j) == classical_modular_polynomial(l)(j,Y)
88+
sage: classical_modular_polynomial(l, j) == classical_modular_polynomial(l)(j, Y)
89+
True
90+
sage: p = 2^216 * 3^137 - 1
91+
sage: F.<i> = GF((p,2), modulus=[1,0,1])
92+
sage: l = random_prime(50)
93+
sage: j = F.random_element()
94+
sage: Y = polygen(parent(j), 'Y')
95+
sage: classical_modular_polynomial(l, j) == classical_modular_polynomial(l)(j, Y)
96+
True
97+
sage: E = EllipticCurve(F, [0, 6, 0, 1, 0])
98+
sage: j = E.j_invariant()
99+
sage: l = random_prime(50)
100+
sage: classical_modular_polynomial(l, j) == classical_modular_polynomial(l)(j, Y)
101+
True
102+
sage: R.<Y> = QQ['Y']
103+
sage: j = QQ(1/2)
104+
sage: l = random_prime(50)
105+
sage: classical_modular_polynomial(l, j) == classical_modular_polynomial(l)(j, Y)
89106
True
90107
"""
91108
l = ZZ(l)
@@ -133,12 +150,14 @@ def classical_modular_polynomial(l, j=None):
133150
# Now try to get the instantiated modular polynomial directly from PARI.
134151
# This should be slightly more efficient (in particular regarding memory
135152
# usage) than computing and evaluating the generic modular polynomial.
153+
# This currently only works if we are over Z/nZ.
136154
try:
137155
pari_Phi = pari.polmodular(l, 0, j)
156+
return R(pari_Phi)
138157
except PariError:
139158
pass
140-
else:
141-
return R(pari_Phi)
159+
except TypeError:
160+
return R(ZZ['Y'](pari_Phi))
142161

143162
# Nothing worked. Fall back to computing the generic modular polynomial
144163
# and simply evaluating it.

0 commit comments

Comments
 (0)