Hyperelliptic curves (smooth model) over a p-adic field

The functions in this module were prototyped at the 2007 Arizona Winter School by Robert Bradshaw and Ralf Gerkmann, working with Miljan Brakovevic and Kiran Kedlaya. They were adapted by Sabrina Kunzweiler, Gareth Ma, Giacomo Pope (2024) to work for hyperelliptic curves in weighted projective space.

All of the below is with respect to the Monsky Washnitzer cohomology.

AUTHORS:

  • Robert Bradshaw, Ralf Gerkmann, Miljan Brakovevic, Kiran Kedlaya (2007): initial version

  • Sabrina Kunzweiler, Gareth Ma, Giacomo Pope (2024): adapt to smooth model

class sage.schemes.hyperelliptic_curves.hyperelliptic_padic_field.HyperellipticCurve_padic_field(projective_model, f, h, genus: Integer, names=['x', 'y'])[source]

Bases: HyperellipticCurve_generic

Class of hyperelliptic curves (smooth model) over a \(p\)-adic field. In particular this class implements the necessary functionality to compute Coleman integrals.

EXAMPLES:

This is the curve with LMFDB label 1091.a.1091.1

sage: K = pAdicField(7,10)
sage: R.<x> = K[]
sage: H = HyperellipticCurve(x^5 + 1/4*x^4 -3/2* x^3 -1/4*x^2 + 1/2*x +  1/4)
sage: P0 = H(1,0,0)
sage: Q = H(-1,-1/2)
sage: P = H(0,1/2)

We note that \([P-P_0]\) has order \(7\) on the Jacobian, hence the Coleman integral \(\int_P^{P_0} dx/2y\) vanishes. On the other hand \([Q-Q_0]\) has infinite order, and the corresponding integral is nonzero:

sage: w = H.invariant_differential()
sage: H.coleman_integral(w,P,P0)
O(7^9)
sage: H.coleman_integral(w,Q,P0)
3*7 + 4*7^2 + 5*7^4 + 2*7^5 + 2*7^6 + 6*7^7 + 4*7^8 + O(7^9)
P_to_S(P, S)[source]

Given a finite Weierstrass point P and a point S in the same disc, compute the Coleman integrals \(\{\int_P^S x^i dx/2y \}_{i=0}^{2g-1}\)

INPUT:

  • P: finite Weierstrass point

  • S: point in disc of P

OUTPUT:

Coleman integrals \(\{\int_P^S x^i dx/2y \}_{i=0}^{2g-1}\)

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,4)
sage: HK = H.change_ring(K)
sage: P = HK(1,0)
sage: HJ = HK.curve_over_ram_extn(10)
sage: S = HK.get_boundary_point(HJ,P)
sage: HK.P_to_S(P, S)
(2*a + 4*a^3 + 2*a^11 + 4*a^13 + 2*a^17 + 2*a^19 + a^21 + 4*a^23 + a^25 + 2*a^27 + 2*a^29 + 3*a^31 + 4*a^33 + O(a^35), a^-5 + 2*a + 2*a^3 + a^7 + 3*a^11 + a^13 + 3*a^15 + 3*a^17 + 2*a^19 + 4*a^21 + 4*a^23 + 4*a^25 + 2*a^27 + a^29 + a^31 + O(a^33))

AUTHOR:

  • Jennifer Balakrishnan

S_to_Q(S, Q)[source]

Given S a point on self over an extension field, compute the Coleman integrals \(\{\int_S^Q x^i dx/2y \}_{i=0}^{2g-1}\)

one should be able to feed ``S,Q`` into coleman_integral, but currently that segfaults

INPUT:

  • S: a point with coordinates in an extension of \(\QQ_p\) (with unif. \(a\))

  • Q: a non-Weierstrass point defined over \(\QQ_p\)

OUTPUT:

the Coleman integrals \(\{\int_S^Q x^i dx/2y \}_{i=0}^{2g-1}\) in terms of \(a\)

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,6)
sage: HK = H.change_ring(K)
sage: J.<a> = K.extension(x^20-5)
sage: HJ  = H.change_ring(J)
sage: w = HK.invariant_differential()
sage: x,y = HK.monsky_washnitzer_gens()
sage: P = HK(1,0)
sage: Q = HK(0,3)
sage: S = HK.get_boundary_point(HJ,P)
sage: P_to_S = HK.P_to_S(P,S)
sage: S_to_Q = HJ.S_to_Q(S,Q)
sage: P_to_S + S_to_Q
(2*a^40 + a^80 + a^100 + O(a^105), a^20 + 2*a^40 + 4*a^60 + 2*a^80 + O(a^103))
sage: HK.coleman_integrals_on_basis(P,Q)
(2*5^2 + 5^4 + 5^5 + 3*5^6 + O(5^7), 5 + 2*5^2 + 4*5^3 + 2*5^4 + 5^6 + O(5^7))

AUTHOR:

  • Jennifer Balakrishnan

coleman_integral(w, P, Q, algorithm='None')[source]

Return the Coleman integral \(\int_P^Q w\).

INPUT:

  • w differential (if one of P,Q is Weierstrass, w must be odd)

  • P point on self

  • Q point on self

  • algorithm (optional) = None (uses Frobenius) or teichmuller (uses Teichmuller points)

OUTPUT:

the Coleman integral \(\int_P^Q w\)

EXAMPLES:

Example of Leprevost from Kiran Kedlaya The first two should be zero as \((P-Q) = 30(P-Q)\) in the Jacobian and \(dx/2y\) and \(x dx/2y\) are holomorphic.

sage: K = pAdicField(11, 6)
sage: x = polygen(K)
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
sage: P = C(-1, 1); P1 = C(-1, -1)
sage: Q = C(0, 1/4); Q1 = C(0, -1/4)
sage: x, y = C.monsky_washnitzer_gens()
sage: w = C.invariant_differential()
sage: w.coleman_integral(P, Q)
O(11^6)
sage: C.coleman_integral(x*w, P, Q)
O(11^6)
sage: C.coleman_integral(x^2*w, P, Q)
7*11 + 6*11^2 + 3*11^3 + 11^4 + 5*11^5 + O(11^6)
sage: p = 71; m = 4
sage: K = pAdicField(p, m)
sage: x = polygen(K)
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
sage: P = C(-1, 1); P1 = C(-1, -1)
sage: Q = C(0, 1/4); Q1 = C(0, -1/4)
sage: x, y = C.monsky_washnitzer_gens()
sage: w = C.invariant_differential()
sage: w.integrate(P, Q), (x*w).integrate(P, Q)
(O(71^4), O(71^4))
sage: R, R1 = C.lift_x(4, all=True)
sage: w.integrate(P, R)
50*71 + 3*71^2 + 43*71^3 + O(71^4)
sage: w.integrate(P, R) + w.integrate(P1, R1)
O(71^4)

A simple example, integrating dx:

sage: R.<x> = QQ['x']
sage: E= HyperellipticCurve(x^3-4*x+4)
sage: K = Qp(5,10)
sage: EK = E.change_ring(K)
sage: P = EK(2, 2)
sage: Q = EK.teichmuller(P)
sage: x, y = EK.monsky_washnitzer_gens()
sage: EK.coleman_integral(x.diff(), P, Q)
5 + 2*5^2 + 5^3 + 3*5^4 + 4*5^5 + 2*5^6 + 3*5^7 + 3*5^9 + O(5^10)
sage: Q[0] - P[0]
5 + 2*5^2 + 5^3 + 3*5^4 + 4*5^5 + 2*5^6 + 3*5^7 + 3*5^9 + O(5^10)

Yet another example:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x*(x-1)*(x+9))
sage: K = Qp(7,10)
sage: HK = H.change_ring(K)
sage: from sage.schemes.hyperelliptic_curves import monsky_washnitzer as mw
sage: M_frob, forms = mw.matrix_of_frobenius_hyperelliptic(HK)
sage: w = HK.invariant_differential()
sage: x,y = HK.monsky_washnitzer_gens()
sage: f = forms[0]
sage: S = HK(9,36)
sage: Q = HK.teichmuller(S)
sage: P = HK(-1,4)
sage: b = x*w*w._coeff.parent()(f)
sage: HK.coleman_integral(b,P,Q)
7 + 7^2 + 4*7^3 + 5*7^4 + 3*7^5 + 7^6 + 5*7^7 + 3*7^8 + 4*7^9 + 4*7^10 + O(7^11)
sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3+1)
sage: K = Qp(5,8)
sage: HK = H.change_ring(K)
sage: w = HK.invariant_differential()
sage: P = HK(0,1)
sage: Q = HK(5, 1 + 3*5^3 + 2*5^4 + 2*5^5 + 3*5^7)
sage: x,y = HK.monsky_washnitzer_gens()
sage: (2*y*w).coleman_integral(P,Q)
5 + O(5^9)
sage: xloc,yloc,zloc = HK.local_analytic_interpolation(P,Q)
sage: I2 = (xloc.derivative()/(2*yloc)).integral()
sage: I2.polynomial()(1) - I2(0)
3*5 + 2*5^2 + 2*5^3 + 5^4 + 4*5^6 + 5^7 + O(5^9)
sage: HK.coleman_integral(w,P,Q)
3*5 + 2*5^2 + 2*5^3 + 5^4 + 4*5^6 + 5^7 + O(5^9)

Integrals involving Weierstrass points:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,8)
sage: HK = H.change_ring(K)
sage: S = HK(1,0)
sage: P = HK(0,3)
sage: negP = HK(0,-3)
sage: T = HK(1,0,0)
sage: w = HK.invariant_differential()
sage: x,y = HK.monsky_washnitzer_gens()
sage: HK.coleman_integral(w*x^3,S,T)
0
sage: HK.coleman_integral(w*x^3,T,S)
0
sage: HK.coleman_integral(w,S,P)
2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9)
sage: HK.coleman_integral(w,T,P)
2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9)
sage: HK.coleman_integral(w*x^3,T,P)
5^2 + 2*5^3 + 3*5^6 + 3*5^7 + O(5^8)
sage: HK.coleman_integral(w*x^3,S,P)
5^2 + 2*5^3 + 3*5^6 + 3*5^7 + O(5^8)
sage: HK.coleman_integral(w, P, negP, algorithm='teichmuller')
5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 3*5^6 + 2*5^7 + 4*5^8 + O(5^9)
sage: HK.coleman_integral(w, P, negP)
5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 3*5^6 + 2*5^7 + 4*5^8 + O(5^9)

AUTHORS:

  • Robert Bradshaw (2007-03)

  • Kiran Kedlaya (2008-05)

  • Jennifer Balakrishnan (2010-02)

coleman_integral_P_to_S(w, P, S)[source]

Given a finite Weierstrass point P and a point S in the same disc, compute the Coleman integral \(\int_P^S w\)

INPUT:

  • w: differential

  • P: Weierstrass point

  • S: point in the same disc of P (S is defined over an extension of \(\QQ_p\); coordinates of S are given in terms of uniformizer \(a\))

OUTPUT:

Coleman integral \(\int_P^S w\) in terms of \(a\)

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,4)
sage: HK = H.change_ring(K)
sage: P = HK(1,0)
sage: J.<a> = K.extension(x^10-5)
sage: HJ  = H.change_ring(J)
sage: S = HK.get_boundary_point(HJ,P)
sage: x,y = HK.monsky_washnitzer_gens()
sage: S[0]-P[0] == HK.coleman_integral_P_to_S(x.diff(),P,S)
True
sage: HK.coleman_integral_P_to_S(HK.invariant_differential(),P,S) == HK.P_to_S(P,S)[0]
True

AUTHOR:

  • Jennifer Balakrishnan

coleman_integral_S_to_Q(w, S, Q)[source]

Compute the Coleman integral \(\int_S^Q w\)

one should be able to feed ``S,Q`` into coleman_integral, but currently that segfaults

INPUT:

  • w: a differential

  • S: a point with coordinates in an extension of \(\QQ_p\)

  • Q: a non-Weierstrass point defined over \(\QQ_p\)

OUTPUT:

the Coleman integral \(\int_S^Q w\)

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,6)
sage: HK = H.change_ring(K)
sage: J.<a> = K.extension(x^20-5)
sage: HJ  = H.change_ring(J)
sage: x,y = HK.monsky_washnitzer_gens()
sage: P = HK(1,0)
sage: Q = HK(0,3)
sage: S = HK.get_boundary_point(HJ,P)
sage: P_to_S = HK.coleman_integral_P_to_S(y.diff(),P,S)
sage: S_to_Q = HJ.coleman_integral_S_to_Q(y.diff(),S,Q)
sage: P_to_S  + S_to_Q
3 + O(a^119)
sage: HK.coleman_integral(y.diff(),P,Q)
3 + O(5^6)

AUTHOR:

  • Jennifer Balakrishnan

coleman_integral_from_weierstrass_via_boundary(w, P, Q, d)[source]

Computes the Coleman integral \(\int_P^Q w\) via a boundary point in the disc of P, defined over a degree d extension

INPUT:

  • w: a differential

  • P: a Weierstrass point

  • Q: a non-Weierstrass point

  • d: degree of extension where coordinates of boundary point lie

OUTPUT:

the Coleman integral \(\int_P^Q w\), written in terms of the uniformizer \(a\) of the degree \(d\) extension

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,6)
sage: HK = H.change_ring(K)
sage: P = HK(1,0)
sage: Q = HK(0,3)
sage: x,y = HK.monsky_washnitzer_gens()
sage: HK.coleman_integral_from_weierstrass_via_boundary(y.diff(),P,Q,20)
3 + O(a^119)
sage: HK.coleman_integral(y.diff(),P,Q)
3 + O(5^6)
sage: w = HK.invariant_differential()
sage: HK.coleman_integral_from_weierstrass_via_boundary(w,P,Q,20)
2*a^40 + a^80 + a^100 + O(a^105)
sage: HK.coleman_integral(w,P,Q)
2*5^2 + 5^4 + 5^5 + 3*5^6 + O(5^7)

AUTHOR:

  • Jennifer Balakrishnan

coleman_integrals_on_basis(P, Q, algorithm=None)[source]

Computes the Coleman integrals \(\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}\)

INPUT:

  • P point on self

  • Q point on self

  • algorithm (optional) = None (uses Frobenius) or teichmuller (uses Teichmuller points)

OUTPUT:

the Coleman integrals \(\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}\)

EXAMPLES:

sage: K = pAdicField(11, 5)
sage: x = polygen(K)
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
sage: P = C.lift_x(2)
sage: Q = C.lift_x(3)
sage: C.coleman_integrals_on_basis(P, Q)
(9*11^2 + 7*11^3 + 5*11^4 + O(11^5), 11 + 3*11^2 + 7*11^3 + 11^4 + O(11^5), 10*11 + 11^2 + 5*11^3 + 5*11^4 + O(11^5), 3 + 9*11^2 + 6*11^3 + 11^4 + O(11^5))
sage: C.coleman_integrals_on_basis(P, Q, algorithm='teichmuller')
(9*11^2 + 7*11^3 + 5*11^4 + O(11^5), 11 + 3*11^2 + 7*11^3 + 11^4 + O(11^5), 10*11 + 11^2 + 5*11^3 + 5*11^4 + O(11^5), 3 + 9*11^2 + 6*11^3 + 11^4 + O(11^5))
sage: K = pAdicField(11,5)
sage: x = polygen(K)
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
sage: P = C(11^-2, 10*11^-5 + 10*11^-4 + 10*11^-3 + 2*11^-2 + 10*11^-1)
sage: Q = C(3*11^-2, 11^-5 + 11^-3 + 10*11^-2 + 7*11^-1)
sage: C.coleman_integrals_on_basis(P, Q)
(6*11^3 + 3*11^4 + 8*11^5 + 4*11^6 + 9*11^7 + O(11^8), 11 + 10*11^2 + 8*11^3 + 7*11^4 + 5*11^5 + O(11^6), 6*11^-1 + 2 + 6*11 + 3*11^3 + O(11^4), 9*11^-3 + 9*11^-2 + 9*11^-1 + 2*11 + O(11^2))
sage: R = C(0,1/4)
sage: a = C.coleman_integrals_on_basis(P,R)  # long time (7s on sage.math, 2011)
sage: b = C.coleman_integrals_on_basis(R,Q)  # long time (9s on sage.math, 2011)
sage: c = C.coleman_integrals_on_basis(P,Q)  # long time
sage: a+b == c  # long time
True
sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,8)
sage: HK = H.change_ring(K)
sage: S = HK(1,0)
sage: P = HK(0,3)
sage: T = HK(1,0,0)
sage: Q = HK.lift_x(5^-2)
sage: R = HK.lift_x(4*5^-2)
sage: HK.coleman_integrals_on_basis(S,P)
(2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9), 5 + 2*5^2 + 4*5^3 + 2*5^4 + 3*5^6 + 4*5^7 + 2*5^8 + O(5^9))
sage: HK.coleman_integrals_on_basis(T,P)
(2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9), 5 + 2*5^2 + 4*5^3 + 2*5^4 + 3*5^6 + 4*5^7 + 2*5^8 + O(5^9))
sage: HK.coleman_integrals_on_basis(P,S) == -HK.coleman_integrals_on_basis(S,P)
True
sage: HK.coleman_integrals_on_basis(S,Q)
(5 + O(5^4), 4*5^-1 + 4 + 4*5 + 4*5^2 + O(5^3))
sage: HK.coleman_integrals_on_basis(Q,R)
(5 + 2*5^2 + 2*5^3 + 2*5^4 + 3*5^5 + 3*5^6 + 3*5^7 + 5^8 + O(5^9), 3*5^-1 + 2*5^4 + 5^5 + 2*5^6 + O(5^7))
sage: HK.coleman_integrals_on_basis(S,R) == HK.coleman_integrals_on_basis(S,Q) + HK.coleman_integrals_on_basis(Q,R)
True
sage: HK.coleman_integrals_on_basis(T,T)
(0, 0)
sage: HK.coleman_integrals_on_basis(S,T)
(0, 0)

AUTHORS:

  • Robert Bradshaw (2007-03): non-Weierstrass points

  • Jennifer Balakrishnan and Robert Bradshaw (2010-02): Weierstrass points

coleman_integrals_on_basis_hyperelliptic(P, Q, algorithm=None)[source]

alias of coleman_integrals_on_basis().

curve_over_ram_extn(deg)[source]

Return self over \(\QQ_p(p^(1/deg))\).

INPUT:

  • deg: the degree of the ramified extension

OUTPUT:

self over \(\QQ_p(p^(1/deg))\)

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
sage: K = Qp(11,5)
sage: HK = H.change_ring(K)
sage: HL = HK.curve_over_ram_extn(2)
sage: HL
Hyperelliptic Curve over 11-adic Eisenstein Extension Field in a defined by x^2 - 11 defined by (1 + O(a^10))*y^2 = (1 + O(a^10))*x^5 + (10 + 8*a^2 + 10*a^4 + 10*a^6 + 10*a^8 + O(a^10))*x^3 + (7 + a^2 + O(a^10))*x^2 + (7 + 3*a^2 + O(a^10))*x

AUTHOR:

  • Jennifer Balakrishnan

find_char_zero_weierstrass_point(Q)[source]

Given \(Q\) a point on self in a Weierstrass disc, finds the center of the Weierstrass disc (if defined over self.base_ring())

EXAMPLES:

Examples for a hyperelliptic curve with odd degree model:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,8)
sage: HK = H.change_ring(K)
sage: P = HK.lift_x(1 + 2*5^2)
sage: Q = HK.lift_x(5^-2)
sage: S = HK(1,0)
sage: T = HK(1,0,0)
sage: HK.find_char_zero_weierstrass_point(P)
(1 + O(5^8) : 0 : 1 + O(5^8))
sage: HK.find_char_zero_weierstrass_point(Q)
(1 + O(5^8) : 0 : 0)
sage: HK.find_char_zero_weierstrass_point(S)
(1 + O(5^8) : 0 : 1 + O(5^8))
sage: HK.find_char_zero_weierstrass_point(T)
(1 + O(5^8) : 0 : 0)

An example for a hyperelltiptic curve with split model:

sage: H = HyperellipticCurve(x^6+3, x^2+1)
sage: HK = H.change_ring(K)
sage: P = HK.lift_x(1+3*5+4*5^2+4*5^3)
sage: HK.find_char_zero_weierstrass_point(P)
(1 + 3*5 + 4*5^2 + 4*5^3 + 3*5^4 + 2*5^6 + 4*5^7 + O(5^8) : 4 + 5 + 3*5^2 + 4*5^3 + 2*5^5 + 4*5^6 + 4*5^7 + O(5^8) : 1 + O(5^8))

The input needs to be a point in a Weierstrass disc, otherwise an error is returned:

sage: Q = HK.point([1,1,0])
sage: HK.find_char_zero_weierstrass_point(Q)
Traceback (most recent call last):
...
ValueError: (1 + O(5^8) : 1 + O(5^8) : 0) is not in a Weierstrass disc.

AUTHOR:

  • Jennifer Balakrishnan

frobenius(P=None)[source]

Returns the \(p\)-th power lift of Frobenius of \(P\)

EXAMPLES:

sage: K = Qp(11, 5)
sage: R.<x> = K[]
sage: E = HyperellipticCurve(x^5 - 21*x - 20)
sage: P = E.lift_x(2)
sage: E.frobenius(P)
(2 + 10*11 + 5*11^2 + 11^3 + O(11^5) : 6 + 11 + 8*11^2 + 8*11^3 + 10*11^4 + O(11^5) : 1 + O(11^5))
sage: Q = E.teichmuller(P); Q
(2 + 10*11 + 4*11^2 + 9*11^3 + 11^4 + O(11^5) : 6 + 11 + 4*11^2 + 9*11^3 + 4*11^4 + O(11^5) : 1 + O(11^5))
sage: E.frobenius(Q)
(2 + 10*11 + 4*11^2 + 9*11^3 + 11^4 + O(11^5) : 6 + 11 + 4*11^2 + 9*11^3 + 4*11^4 + O(11^5) : 1 + O(11^5))
sage: R.<x> = QQ[]
sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
sage: Q = H(0,0)
sage: u,v = H.local_coord(Q,prec=100)
sage: K = Qp(11,5)
sage: L.<a> = K.extension(x^20-11)
sage: HL = H.change_ring(L)
sage: S = HL(u(a),v(a))
sage: HL.frobenius(S)
(8*a^22 + 10*a^42 + 4*a^44 + 2*a^46 + 9*a^48 + 8*a^50 + a^52 + 7*a^54 +
7*a^56 + 5*a^58 + 9*a^62 + 5*a^64 + a^66 + 6*a^68 + a^70 + 6*a^74 +
2*a^76 + 2*a^78 + 4*a^82 + 5*a^84 + 2*a^86 + 7*a^88 + a^90 + 6*a^92 +
a^96 + 5*a^98 + 2*a^102 + 2*a^106 + 6*a^108 + 8*a^110 + 3*a^112 +
a^114 + 8*a^116 + 10*a^118 + 3*a^120 + O(a^122) :
a^11 + 7*a^33 + 7*a^35 + 4*a^37 + 6*a^39 + 9*a^41 + 8*a^43 + 8*a^45 +
a^47 + 7*a^51 + 4*a^53 + 5*a^55 + a^57 + 7*a^59 + 5*a^61 + 9*a^63 +
4*a^65 + 10*a^69 + 3*a^71 + 2*a^73 + 9*a^75 + 10*a^77 + 6*a^79 +
10*a^81 + 7*a^85 + a^87 + 4*a^89 + 8*a^91 + a^93 + 8*a^95 + 2*a^97 +
7*a^99 + a^101 + 3*a^103 + 6*a^105 + 7*a^107 + 4*a^109 + O(a^111) :
1 + O(a^100))

AUTHORS:

  • Robert Bradshaw and Jennifer Balakrishnan (2010-02)

get_boundary_point(curve_over_extn, P)[source]

Given self over an extension field, find a point in the disc of \(P\) near the boundary

INPUT:

  • curve_over_extn: self over a totally ramified extension

  • P: Weierstrass point

OUTPUT:

a point in the disc of \(P\) near the boundary

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(3,6)
sage: HK = H.change_ring(K)
sage: P = HK(1,0)
sage: J.<a> = K.extension(x^30-3)
sage: HJ  = H.change_ring(J)
sage: S = HK.get_boundary_point(HJ,P)
sage: S
(1 + 2*a^2 + 2*a^6 + 2*a^18 + a^32 + a^34 + a^36 + 2*a^38 + 2*a^40 + a^42 + 2*a^44 + a^48 + 2*a^50 + 2*a^52 + a^54 + a^56 + 2*a^60 + 2*a^62 + a^70 + 2*a^72 + a^76 + 2*a^78 + a^82 + a^88 + a^96 + 2*a^98 + 2*a^102 + a^104 + 2*a^106 + a^108 + 2*a^110 + a^112 + 2*a^116 + a^126 + 2*a^130 + 2*a^132 + a^144 + 2*a^148 + 2*a^150 + a^152 + 2*a^154 + a^162 + a^164 + a^166 + a^168 + a^170 + a^176 + a^178 + O(a^180) : a + O(a^180) : 1 + O(a^180))

AUTHOR:

  • Jennifer Balakrishnan

is_in_weierstrass_disc(P)[source]

Checks if \(P\) is in a Weierstrass disc.

EXAMPLES:

For odd degree models, the points with \(y\)-coordinate equivalent to zero are contained in a Weierstrass discs:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,8)
sage: HK = H.change_ring(K)
sage: P = HK(0,3)
sage: HK.is_in_weierstrass_disc(P)
False
sage: Q = HK(1,0,0)
sage: HK.is_in_weierstrass_disc(Q)
True
sage: S = HK(1,0)
sage: HK.is_in_weierstrass_disc(S)
True
sage: T = HK.lift_x(1+3*5^2); T
(1 + 3*5^2 + O(5^8) : 3*5 + 4*5^2 + 5^4 + 3*5^5 + 5^6 + O(5^7) : 1 + O(5^8))
sage: HK.is_in_weierstrass_disc(T)
True

The method is also implemented for general models of hyperelliptic curves:

sage: H = HyperellipticCurve(x^6+3, x^2+1)
sage: HK = H.change_ring(K)
sage: P = HK.lift_x(1+3*5+4*5^2+4*5^3); P
(1 + 3*5 + 4*5^2 + 4*5^3 + O(5^8) : 4 + 5 + 4*5^2 + 5^3 + 3*5^4 + 5^5 + O(5^6) : 1 + O(5^8))
sage: HK.is_in_weierstrass_disc(P)
True

Note that \(y = - y - h(x)\) for Weierstrass points. We check that this relation is satisfied for the point above (mod p):

sage: f,h = H.hyperelliptic_polynomials()
sage: (2*P[1] + h(P[0])).valuation() > 0
True

AUTHOR:

  • Jennifer Balakrishnan (2010-02)

is_same_disc(P, Q)[source]

Checks if \(P,Q\) are in same residue disc

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,8)
sage: HK = H.change_ring(K)
sage: P = HK.lift_x(1 + 2*5^2)
sage: Q = HK.lift_x(5^-2)
sage: S = HK(1,0)
sage: HK.is_same_disc(P,Q)
False
sage: HK.is_same_disc(P,S)
True
sage: HK.is_same_disc(Q,S)
False
local_analytic_interpolation(P, Q)[source]

For points P, Q in the same residue disc, construct an interpolation from P to Q (in weighted homogeneous coordinates) in a power series in the local parameter \(t\), with precision equal to the \(p\)-adic precision of the underlying ring.

INPUT:

  • P and Q points on self in the same residue disc

OUTPUT:

Returns a point \(X(t) = ( x(t) : y(t) : z(t) )\) such that:

  1. \(X(0) = P\) and \(X(1) = Q\) if \(P, Q\) are not in the infinite disc

  2. \(X(P[1]/P[0]^(g+1)) = P\) and \(X(Q[1]/Q[0]^(g+1)) = Q\) if \(P, Q\) are in the infinite disc

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,8)
sage: HK = H.change_ring(K)

A non-Weierstrass disc:

sage: P = HK(0,3)
sage: Q = HK(5, 3 + 3*5^2 + 2*5^3 + 3*5^4 + 2*5^5 + 2*5^6 + 3*5^7 + O(5^8))
sage: x,y,z, = HK.local_analytic_interpolation(P,Q)
sage: x(0) == P[0], x(1) == Q[0], y(0) == P[1], y.polynomial()(1) == Q[1]
(True, True, True, True)

A finite Weierstrass disc:

sage: P = HK.lift_x(1 + 2*5^2)
sage: Q = HK.lift_x(1 + 3*5^2)
sage: x,y,z = HK.local_analytic_interpolation(P,Q)
sage: x(0) == P[0], x.polynomial()(1) == Q[0], y(0) == P[1], y(1) == Q[1]
(True, True, True, True)

The infinite disc:

sage: g = HK.genus()
sage: P = HK.lift_x(5^-2)
sage: Q = HK.lift_x(4*5^-2)
sage: x,y,z = HK.local_analytic_interpolation(P,Q)
sage: x = x/z
sage: y = y/z^(g+1)
sage: x(P[1]/P[0]^(g+1)) == P[0]
True
sage: x(Q[1]/Q[0]^(g+1)) == Q[0]
True
sage: y(P[1]/P[0]^(g+1)) == P[1]
True
sage: y(Q[1]/Q[0]^(g+1)) == Q[1]
True

An error if points are not in the same disc:

sage: x,y,z = HK.local_analytic_interpolation(P,HK(1,0))
Traceback (most recent call last):
...
ValueError: (5^-2 + O(5^6) : 4*5^-3 + 4*5^-2 + 4*5^-1 + 4 + 4*5 + 3*5^3 + 5^4 + O(5^5) : 1 + O(5^8)) and (1 + O(5^8) : 0 : 1 + O(5^8)) are not in the same residue disc

AUTHORS:

  • Robert Bradshaw (2007-03)

  • Jennifer Balakrishnan (2010-02)

  • Sabrina Kunzweiler, Gareth Ma, Giacomo Pope (2024): adapt to smooth model

newton_sqrt(f, x0, prec)[source]

Takes the square root of the power series \(f\) by Newton’s method

NOTE:

this function should eventually be moved to \(p\)-adic power series ring

INPUT:

  • f – power series with coefficients in \(\QQ_p\) or an extension

  • x0 – seeds the Newton iteration

  • prec – precision

OUTPUT: the square root of \(f\)

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
sage: Q = H(0,0)
sage: u,v = H.local_coord(Q,prec=100)
sage: K = Qp(11,5)
sage: HK = H.change_ring(K)
sage: L.<a> = K.extension(x^20-11)
sage: HL = H.change_ring(L)
sage: S = HL(u(a),v(a))
sage: f = H.hyperelliptic_polynomials()[0]
sage: y = HK.newton_sqrt( f(u(a)^11), a^11,5)
sage: y^2 - f(u(a)^11)
O(a^122)

AUTHOR:

  • Jennifer Balakrishnan

residue_disc(P)[source]

Gives the residue disc of \(P\)

TODO: Really, this gives the reduction over the residue field. Isn’t the residue disc a disc over the p-adics? Maybe rename to residue_point or reduction ?

EXAMPLES:

We compute the residue discs for diffferent points on the elliptic curve \(y^2 = x^3 = 10*x + 9\) over the \(5\)-adics:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3-10*x+9)
sage: K = Qp(5,8)
sage: HK = H.change_ring(K)
sage: P = HK.lift_x(1 + 2*5^2)
sage: HK.residue_disc(P)
(1 : 0 : 1)
sage: Q = HK(0,3)
sage: HK.residue_disc(Q)
(0 : 3 : 1)
sage: S = HK.lift_x(5^-2)
sage: HK.residue_disc(S)
(1 : 0 : 0)
sage: T = HK(1,0,0)
sage: HK.residue_disc(T)
(1 : 0 : 0)

We can also compute residue discs for points on curves with a split or inert model:

sage: H = HyperellipticCurve(x^6+3, x^2+1)
sage: H.is_split()
True
sage: HK = H.change_ring(K)
sage: P = HK.lift_x(1+3*5+4*5^2+4*5^3)
sage: Pbar = HK.residue_disc(P); Pbar
(1 : 4 : 1)

We note that \(P\) is in a Weierstrass disc and its reduction is indeed a Weierstrass point.

sage: HK.is_in_weierstrass_disc(P) True sage: HF = HK.change_ring(FiniteField(5)) sage: HF.is_weierstrass_point(Pbar) True

AUTHOR:

  • Jennifer Balakrishnan

teichmuller(P)[source]

Find a Teichm:uller point in the same residue class of \(P\).

Because this lift of frobenius acts as \(x \mapsto x^p\), take the Teichmuller lift of \(x\) and then find a matching \(y\) from that.

EXAMPLES:

sage: K = pAdicField(7, 5)
sage: R.<x> = K[]
sage: E = HyperellipticCurve(x^3 - 31/3*x - 2501/108) # 11a
sage: P = E(K(14/3), K(11/2))
sage: E.frobenius(P) == P
False
sage: TP = E.teichmuller(P); TP
(0 : 2 + 3*7 + 3*7^2 + 3*7^4 + O(7^5) : 1 + O(7^5))
sage: E.frobenius(TP) == TP
True
sage: (TP[0] - P[0]).valuation() > 0, (TP[1] - P[1]).valuation() > 0
(True, True)
tiny_integrals(F, P, Q)[source]

Evaluate the integrals of \(f_i dx/2y\) from \(P\) to \(Q\) for each \(f_i\) in \(F\) by formally integrating a power series in a local parameter \(t\)

\(P\) and \(Q\) MUST be in the same residue disc for this result to make sense.

INPUT:

  • F a list of functions \(f_i\)

  • P a point on self

  • Q a point on self (in the same residue disc as P)

OUTPUT:

The integrals \(\int_P^Q f_i dx/2y\)

EXAMPLES:

sage: K = pAdicField(17, 5)
sage: E = EllipticCurve(K, [-31/3, -2501/108]) # 11a
sage: P = E(K(14/3), K(11/2))
sage: TP = E.teichmuller(P);
sage: x,y = E.monsky_washnitzer_gens()
sage: E.tiny_integrals([1,x],P, TP) == E.tiny_integrals_on_basis(P,TP)
True
sage: K = pAdicField(11, 5)
sage: x = polygen(K)
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
sage: P = C.lift_x(11^(-2))
sage: Q = C.lift_x(3*11^(-2))
sage: C.tiny_integrals([1],P,Q)
(5*11^3 + 7*11^4 + 2*11^5 + 6*11^6 + 11^7 + O(11^8))

Note that this fails if the points are not in the same residue disc:

sage: S = C(0,1/4)
sage: C.tiny_integrals([1,x,x^2,x^3],P,S)
Traceback (most recent call last):
...
ValueError: (11^-2 + O(11^3) : 11^-5 + 8*11^-2 + O(11^0) : 1 + O(11^5)) and
 (0 : 3 + 8*11 + 2*11^2 + 8*11^3 + 2*11^4 + O(11^5) : 1 + O(11^5)) are not in the same residue disc
tiny_integrals_on_basis(P, Q)[source]

Evaluate the integrals \(\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}\) by formally integrating a power series in a local parameter \(t\). \(P\) and \(Q\) MUST be in the same residue disc for this result to make sense.

INPUT:

  • P a point on self

  • Q a point on self (in the same residue disc as P)

OUTPUT:

The integrals \(\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}\)

EXAMPLES:

sage: K = pAdicField(17, 5)
sage: E = EllipticCurve(K, [-31/3, -2501/108]) # 11a
sage: P = E(K(14/3), K(11/2))
sage: TP = E.teichmuller(P);
sage: E.tiny_integrals_on_basis(P, TP)
(17 + 14*17^2 + 17^3 + 8*17^4 + O(17^5), 16*17 + 5*17^2 + 8*17^3 + 14*17^4 + O(17^5))
sage: K = pAdicField(11, 5)
sage: x = polygen(K)
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
sage: P = C.lift_x(11^(-2))
sage: Q = C.lift_x(3*11^(-2))
sage: C.tiny_integrals_on_basis(P,Q)
(5*11^3 + 7*11^4 + 2*11^5 + 6*11^6 + 11^7 + O(11^8), 10*11 + 2*11^3 + 3*11^4 + 5*11^5 + O(11^6), 5*11^-1 + 8 + 4*11 + 10*11^2 + 7*11^3 + O(11^4), 2*11^-3 + 11^-2 + 11^-1 + 10 + 8*11 + O(11^2))

Note that this fails if the points are not in the same residue disc:

sage: S = C(0,1/4)
sage: C.tiny_integrals_on_basis(P,S)
Traceback (most recent call last):
...
ValueError: (11^-2 + O(11^3) : 11^-5 + 8*11^-2 + O(11^0) : 1 + O(11^5)) and (0 : 3 + 8*11 + 2*11^2 + 8*11^3 + 2*11^4 + O(11^5) : 1 + O(11^5)) are not in the same residue disc