Some functions regarding geometric endomorphism rings of Jacobians of

hyperelliptic curves.

There are currently two main functions in this module, associated to the Jacobian J of a genus 2 curve over the rational numbers Q:

  • get_is_geom_field

  • is_geom_trivial_when_field

get_is_geom_field determines whether the geometric endomorphism algebra textup{End}_{overline{QQ}}(J) otimes QQ` is a field.

is_geom_trivial_when_field determines whether the geometric endomorphism ring EndQ(J) is equal to the integer ring Z, assuming the geometric endomorphism algebra is a field. If this is the case, one says that J is generic.

These functions are used in jacobiangeneric.py in the following two analogous methods associated to the Jacobian J of a genus 2 curve over the rational numbers Q:

  • geometric_endomorphism_algebra_is_field(J)

  • geometric_endomorphism_ring_is_ZZ(J)

Both of these are important attributes of the Jacobian J.

The algorithms in the functions in this module are implementations of Algorithms 4.10 and 4.15 from Lombardo’s paper [Lom2019].

The following examples have been verified with the corresponding LMFDB entries.

EXAMPLES:

Here is an example of a generic Jacobian; the LMFDB label of the curve is 249.a.249.1:

sage: R.<x> = QQ[]
sage: f = x^6 + 2*x^3 + 4*x^2 + 4*x + 1
sage: C = HyperellipticCurve(f)
sage: A = C.jacobian()
sage: A.geometric_endomorphism_ring_is_ZZ()
True
>>> from sage.all import *
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> f = x**Integer(6) + Integer(2)*x**Integer(3) + Integer(4)*x**Integer(2) + Integer(4)*x + Integer(1)
>>> C = HyperellipticCurve(f)
>>> A = C.jacobian()
>>> A.geometric_endomorphism_ring_is_ZZ()
True
R.<x> = QQ[]
f = x^6 + 2*x^3 + 4*x^2 + 4*x + 1
C = HyperellipticCurve(f)
A = C.jacobian()
A.geometric_endomorphism_ring_is_ZZ()

Here is an example of a Jacobian whose endomorphism algebra is a field but not the rational number field; the LMFDB label of the curve is 529.a.529.1:

sage: f = x^6 - 4*x^5 + 2*x^4 + 2*x^3 + x^2 + 2*x + 1
sage: C = HyperellipticCurve(f)
sage: A = C.jacobian()
sage: A.geometric_endomorphism_algebra_is_field()
True
sage: A.geometric_endomorphism_ring_is_ZZ()
False
>>> from sage.all import *
>>> f = x**Integer(6) - Integer(4)*x**Integer(5) + Integer(2)*x**Integer(4) + Integer(2)*x**Integer(3) + x**Integer(2) + Integer(2)*x + Integer(1)
>>> C = HyperellipticCurve(f)
>>> A = C.jacobian()
>>> A.geometric_endomorphism_algebra_is_field()
True
>>> A.geometric_endomorphism_ring_is_ZZ()
False
f = x^6 - 4*x^5 + 2*x^4 + 2*x^3 + x^2 + 2*x + 1
C = HyperellipticCurve(f)
A = C.jacobian()
A.geometric_endomorphism_algebra_is_field()
A.geometric_endomorphism_ring_is_ZZ()

Here is an example of a Jacobian whose endomorphism algebra is not a field; the LMFDB label of the curve is 169.a.169.1:

sage: f = x^6 + 4*x^5 + 6*x^4 + 2*x^3 + x^2 + 2*x + 1
sage: C = HyperellipticCurve(f)
sage: A = C.jacobian()
sage: A.geometric_endomorphism_algebra_is_field()
False
>>> from sage.all import *
>>> f = x**Integer(6) + Integer(4)*x**Integer(5) + Integer(6)*x**Integer(4) + Integer(2)*x**Integer(3) + x**Integer(2) + Integer(2)*x + Integer(1)
>>> C = HyperellipticCurve(f)
>>> A = C.jacobian()
>>> A.geometric_endomorphism_algebra_is_field()
False
f = x^6 + 4*x^5 + 6*x^4 + 2*x^3 + x^2 + 2*x + 1
C = HyperellipticCurve(f)
A = C.jacobian()
A.geometric_endomorphism_algebra_is_field()

Warning

There is a very small chance that the algorithms return False for the two methods described above when in fact one or both of them are True. In this case, as explained in the discussion immediately preceding Algorithm 4.15 of [Lom2019], this can be established by increasing the optional B parameter of the two methods. Mathematically, the algorithms give the correct answer only in the limit as B, although in practice B=200 was sufficient to correctly verify every single entry in the LMFDB.

AUTHORS:

  • Barinder S. Banwait and Davide Lombardo (2021-06-09): initial version

sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils.get_is_geom_field(f, C, bad_primes, B=200)[source]

Determine whether the geometric endomorphism algebra is a field.

This is Algorithm 4.10 in [Lom2019]. The computation done here may allow one to immediately conclude that the geometric endomorphism ring is trivial (i.e. the integer ring); this information is output in a second boolean to avoid unnecessary subsequent computation.

An additional optimisation comes from Part (2) of Theorem 4.8 in [Lom2019], from which we can conclude that the endomorphism ring is geometrically trivial, and from Proposition 4.7 in loc. cit. from which we can rule out potential QM.

INPUT:

  • f – a polynomial defining the hyperelliptic curve

  • C – the hyperelliptic curve

  • bad_primes – the list of odd primes of bad reduction

  • B – (default: 200) the bound which appears in the statement of the algorithm from [Lom2019]

OUTPUT:

Pair of booleans (bool1, bool2). bool1 indicates if the geometric endomorphism algebra is a field; bool2 indicates if the geometric endomorphism algebra is the field of rational numbers.

WARNING:

There is a very small chance that this algorithm return False when in fact it is True. In this case, as explained in the discussion immediately preceding Algorithm 4.15 of [Lom2019], this can be established by increasing the optional B parameter. Mathematically, this algorithm gives the correct answer only in the limit as B, although in practice B=200 was sufficient to correctly verify every single entry in the LMFDB. However, strictly speaking, a False returned by this function is not provably False.

EXAMPLES:

This is LMFDB curve 940693.a.960693.1:

sage: from sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils import get_is_geom_field
sage: R.<x> = QQ[]
sage: f = 4*x^6 - 12*x^5 + 20*x^3 - 8*x^2 - 4*x + 1
sage: C = HyperellipticCurve(f)
sage: get_is_geom_field(f,C,[13,269])
(False, False)
>>> from sage.all import *
>>> from sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils import get_is_geom_field
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> f = Integer(4)*x**Integer(6) - Integer(12)*x**Integer(5) + Integer(20)*x**Integer(3) - Integer(8)*x**Integer(2) - Integer(4)*x + Integer(1)
>>> C = HyperellipticCurve(f)
>>> get_is_geom_field(f,C,[Integer(13),Integer(269)])
(False, False)
from sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils import get_is_geom_field
R.<x> = QQ[]
f = 4*x^6 - 12*x^5 + 20*x^3 - 8*x^2 - 4*x + 1
C = HyperellipticCurve(f)
get_is_geom_field(f,C,[13,269])

This is LMFDB curve 3125.a.3125.1:

sage: f = 4*x^5 + 1
sage: C = HyperellipticCurve(f)
sage: get_is_geom_field(f,C,[5])
(True, False)
>>> from sage.all import *
>>> f = Integer(4)*x**Integer(5) + Integer(1)
>>> C = HyperellipticCurve(f)
>>> get_is_geom_field(f,C,[Integer(5)])
(True, False)
f = 4*x^5 + 1
C = HyperellipticCurve(f)
get_is_geom_field(f,C,[5])

This is LMFDB curve 277.a.277.2:

sage: f = 4*x^6 - 36*x^4 + 56*x^3 - 76*x^2 + 44*x - 23
sage: C = HyperellipticCurve(f)
sage: get_is_geom_field(f,C,[277])
(True, True)
>>> from sage.all import *
>>> f = Integer(4)*x**Integer(6) - Integer(36)*x**Integer(4) + Integer(56)*x**Integer(3) - Integer(76)*x**Integer(2) + Integer(44)*x - Integer(23)
>>> C = HyperellipticCurve(f)
>>> get_is_geom_field(f,C,[Integer(277)])
(True, True)
f = 4*x^6 - 36*x^4 + 56*x^3 - 76*x^2 + 44*x - 23
C = HyperellipticCurve(f)
get_is_geom_field(f,C,[277])
sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils.is_geom_trivial_when_field(C, bad_primes, B=200)[source]

Determine if the geometric endomorphism ring is trivial assuming the geometric endomorphism algebra is a field.

This is Algorithm 4.15 in [Lom2019].

INPUT:

  • C – the hyperelliptic curve

  • bad_primes – the list of odd primes of bad reduction

  • B – (default: 200) the bound which appears in the statement of the algorithm from [Lom2019]

OUTPUT:

Boolean indicating whether or not the geometric endomorphism algebra is the field of rational numbers.

WARNING:

There is a very small chance that this algorithm returns False when in fact it is True. In this case, as explained in the discussion immediately preceding Algorithm 4.15 of [Lom2019], this can be established by increasing the optional B parameter. Mathematically, this algorithm gives the correct answer only in the limit as B, although in practice B=200 was sufficient to correctly verify every single entry in the LMFDB. However, strictly speaking, a False returned by this function is not provably False.

EXAMPLES:

This is LMFDB curve 461.a.461.2:

sage: from sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils import is_geom_trivial_when_field
sage: R.<x> = QQ[]
sage: f = 4*x^5 - 4*x^4 - 156*x^3 + 40*x^2 + 1088*x - 1223
sage: C = HyperellipticCurve(f)
sage: is_geom_trivial_when_field(C,[461])
True
>>> from sage.all import *
>>> from sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils import is_geom_trivial_when_field
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> f = Integer(4)*x**Integer(5) - Integer(4)*x**Integer(4) - Integer(156)*x**Integer(3) + Integer(40)*x**Integer(2) + Integer(1088)*x - Integer(1223)
>>> C = HyperellipticCurve(f)
>>> is_geom_trivial_when_field(C,[Integer(461)])
True
from sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils import is_geom_trivial_when_field
R.<x> = QQ[]
f = 4*x^5 - 4*x^4 - 156*x^3 + 40*x^2 + 1088*x - 1223
C = HyperellipticCurve(f)
is_geom_trivial_when_field(C,[461])

This is LMFDB curve 4489.a.4489.1:

sage: f = x^6 + 4*x^5 + 2*x^4 + 2*x^3 + x^2 - 2*x + 1
sage: C = HyperellipticCurve(f)
sage: is_geom_trivial_when_field(C,[67])
False
>>> from sage.all import *
>>> f = x**Integer(6) + Integer(4)*x**Integer(5) + Integer(2)*x**Integer(4) + Integer(2)*x**Integer(3) + x**Integer(2) - Integer(2)*x + Integer(1)
>>> C = HyperellipticCurve(f)
>>> is_geom_trivial_when_field(C,[Integer(67)])
False
f = x^6 + 4*x^5 + 2*x^4 + 2*x^3 + x^2 - 2*x + 1
C = HyperellipticCurve(f)
is_geom_trivial_when_field(C,[67])
sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils.satisfies_coefficient_condition(g, p)[source]

This is the coefficient condition in the definition of Omega_K’ on page 912 of the published version of paper.

EXAMPLES:

sage: from sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils import satisfies_coefficient_condition
sage: R.<x> = ZZ[]
sage: f = x^4 + x^3 + 17*x^2 + 5*x
sage: satisfies_coefficient_condition(f,17)
False
sage: f = x^4 + x^3 + 17*x^2 + 23*x + 23^2
sage: satisfies_coefficient_condition(f,23)
True
>>> from sage.all import *
>>> from sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils import satisfies_coefficient_condition
>>> R = ZZ['x']; (x,) = R._first_ngens(1)
>>> f = x**Integer(4) + x**Integer(3) + Integer(17)*x**Integer(2) + Integer(5)*x
>>> satisfies_coefficient_condition(f,Integer(17))
False
>>> f = x**Integer(4) + x**Integer(3) + Integer(17)*x**Integer(2) + Integer(23)*x + Integer(23)**Integer(2)
>>> satisfies_coefficient_condition(f,Integer(23))
True
from sage.schemes.hyperelliptic_curves.jacobian_endomorphism_utils import satisfies_coefficient_condition
R.<x> = ZZ[]
f = x^4 + x^3 + 17*x^2 + 5*x
satisfies_coefficient_condition(f,17)
f = x^4 + x^3 + 17*x^2 + 23*x + 23^2
satisfies_coefficient_condition(f,23)