Path: blob/master/sage/schemes/hyperelliptic_curves/jacobian_morphism.py
4128 views
r"""1Jacobian 'morphism' as a class in the Picard group23This module implements the group operation in the Picard group of a4hyperelliptic curve, represented as divisors in Mumford5representation, using Cantor's algorithm.67A divisor on the hyperelliptic curve `y^2 + y h(x) = f(x)`8is stored in Mumford representation, that is, as two polynomials9`u(x)` and `v(x)` such that:1011- `u(x)` is monic,1213- `u(x)` divides `f(x) - h(x) v(x) - v(x)^2`,1415- `deg(v(x)) < deg(u(x)) \le g`.1617REFERENCES:1819A readable introduction to divisors, the Picard group, Mumford20representation, and Cantor's algorithm:2122- J. Scholten, F. Vercauteren. An Introduction to Elliptic and23Hyperelliptic Curve Cryptography and the NTRU Cryptosystem. To24appear in B. Preneel (Ed.) State of the Art in Applied Cryptography25- COSIC '03, Lecture Notes in Computer Science, Springer 2004.2627A standard reference in the field of cryptography:2829- R. Avanzi, H. Cohen, C. Doche, G. Frey, T. Lange, K. Nguyen, and F.30Vercauteren, Handbook of Elliptic and Hyperelliptic Curve31Cryptography. CRC Press, 2005.3233EXAMPLES: The following curve is the reduction of a curve whose34Jacobian has complex multiplication.3536::3738sage: x = GF(37)['x'].gen()39sage: H = HyperellipticCurve(x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x); H40Hyperelliptic Curve over Finite Field of size 37 defined41by y^2 = x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x4243At this time, Jacobians of hyperelliptic curves are handled44differently than elliptic curves::4546sage: J = H.jacobian(); J47Jacobian of Hyperelliptic Curve over Finite Field of size 37 defined48by y^2 = x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x49sage: J = J(J.base_ring()); J50Set of rational points of Jacobian of Hyperelliptic Curve over Finite Field51of size 37 defined by y^2 = x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x5253Points on the Jacobian are represented by Mumford's polynomials.54First we find a couple of points on the curve::5556sage: P1 = H.lift_x(2); P157(2 : 11 : 1)58sage: Q1 = H.lift_x(10); Q159(10 : 18 : 1)6061Observe that 2 and 10 are the roots of the polynomials in x,62respectively::6364sage: P = J(P1); P65(x + 35, y + 26)66sage: Q = J(Q1); Q67(x + 27, y + 19)6869::7071sage: P + Q72(x^2 + 25*x + 20, y + 13*x)73sage: (x^2 + 25*x + 20).roots(multiplicities=False)74[10, 2]7576Frobenius satisfies7778.. math::7980x^4 + 12*x^3 + 78*x^2 + 444*x + 13698182on the Jacobian of this reduction and the order of the Jacobian is83`N = 1904`.8485::8687sage: 1904*P88(1)89sage: 34*P == 090True91sage: 35*P == P92True93sage: 33*P == -P94True9596::9798sage: Q*190499(1)100sage: Q*238 == 0101True102sage: Q*239 == Q103True104sage: Q*237 == -Q105True106"""107108#*****************************************************************************109# Copyright (C) 2005 David Kohel <[email protected]>110# Distributed under the terms of the GNU General Public License (GPL)111# http://www.gnu.org/licenses/112#*****************************************************************************113114from sage.misc.all import latex115116from sage.structure.element import AdditiveGroupElement117from sage.schemes.generic.morphism import SchemeMorphism118119def cantor_reduction_simple(a, b, f, genus):120r"""121Return the unique reduced divisor linearly equivalent to122`(a, b)` on the curve `y^2 = f(x).`123124See the docstring of125:mod:`sage.schemes.hyperelliptic_curves.jacobian_morphism` for126information about divisors, linear equivalence, and reduction.127128EXAMPLES::129130sage: x = QQ['x'].gen()131sage: f = x^5 - x132sage: H = HyperellipticCurve(f); H133Hyperelliptic Curve over Rational Field defined by y^2 = x^5 - x134sage: J = H.jacobian()(QQ); J135Set of rational points of Jacobian of Hyperelliptic Curve over Rational Field136defined by y^2 = x^5 - x137138The following point is 2-torsion::139140sage: P = J(H.lift_x(-1)); P141(x + 1, y)142sage: 2 * P # indirect doctest143(1)144"""145a2 = (f - b**2) // a146a2 = a2.monic()147b2 = -b % (a2);148if a2.degree() == a.degree():149# XXX150assert a2.degree() == genus+1151print "Returning ambiguous form of degree genus+1."152return (a2, b2)153elif a2.degree() > genus:154return cantor_reduction_simple(a2, b2, f, genus)155return (a2, b2)156157def cantor_reduction(a, b, f, h, genus):158r"""159Return the unique reduced divisor linearly equivalent to160`(a, b)` on the curve `y^2 + y h(x) = f(x)`.161162See the docstring of163:mod:`sage.schemes.hyperelliptic_curves.jacobian_morphism` for164information about divisors, linear equivalence, and reduction.165166EXAMPLES::167168sage: x = QQ['x'].gen()169sage: f = x^5 - x170sage: H = HyperellipticCurve(f, x); H171Hyperelliptic Curve over Rational Field defined by y^2 + x*y = x^5 - x172sage: J = H.jacobian()(QQ); J173Set of rational points of Jacobian of Hyperelliptic Curve over174Rational Field defined by y^2 + x*y = x^5 - x175176The following point is 2-torsion::177178sage: Q = J(H.lift_x(0)); Q179(x, y)180sage: 2*Q # indirect doctest181(1)182183The next point is not 2-torsion::184185sage: P = J(H.lift_x(-1)); P186(x + 1, y - 1)187sage: 2 * J(H.lift_x(-1)) # indirect doctest188(x^2 + 2*x + 1, y - 3*x - 4)189sage: 3 * J(H.lift_x(-1)) # indirect doctest190(x^2 - 487*x - 324, y - 10754*x - 7146)191"""192assert a.degree() < 2*genus+1193assert b.degree() < a.degree()194k = f - h*b - b**2195if 2*a.degree() == k.degree():196# must adjust b to include the point at infinity197g1 = a.degree()198x = a.parent().gen()199r = (x**2 + h[g1]*x - f[2*g1]).roots()[0][0]200b = b + r*(x**g1 - (x**g1) % (a))201k = f - h*b - b**2202assert k % (a) == 0203a = (k // a).monic()204b = -(b+h) % (a)205if a.degree() > genus:206return cantor_reduction(a, b, f, h, genus)207return (a, b)208209def cantor_composition_simple(D1,D2,f,genus):210r"""211Given `D_1` and `D_2` two reduced Mumford212divisors on the Jacobian of the curve `y^2 = f(x)`,213computes a representative `D_1 + D_2`.214215.. warning::216217The representative computed is NOT reduced! Use218:func:`cantor_reduction_simple` to reduce it.219220EXAMPLES::221222sage: x = QQ['x'].gen()223sage: f = x^5 + x224sage: H = HyperellipticCurve(f); H225Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x226227::228229sage: F.<a> = NumberField(x^2 - 2, 'a')230sage: J = H.jacobian()(F); J231Set of rational points of Jacobian of Hyperelliptic Curve over232Number Field in a with defining polynomial x^2 - 2 defined233by y^2 = x^5 + x234235::236237sage: P = J(H.lift_x(F(1))); P238(x - 1, y - a)239sage: Q = J(H.lift_x(F(0))); Q240(x, y)241sage: 2*P + 2*Q # indirect doctest242(x^2 - 2*x + 1, y - 3/2*a*x + 1/2*a)243sage: 2*(P + Q) # indirect doctest244(x^2 - 2*x + 1, y - 3/2*a*x + 1/2*a)245sage: 3*P # indirect doctest246(x^2 - 25/32*x + 49/32, y - 45/256*a*x - 315/256*a)247"""248a1, b1 = D1249a2, b2 = D2250if a1 == a2 and b1 == b2:251# Duplication law:252d, h1, h3 = a1.xgcd(2*b1)253a = (a1 // d)**2254b = (b1 + h3*((f - b1**2) // d)) % (a)255else:256d0, _, h2 = a1.xgcd(a2)257if d0 == 1:258a = a1*a2259b = (b2 + h2*a2*(b1-b2)) % (a)260else:261d, l, h3 = d0.xgcd(b1 + b2)262a = (a1*a2) // (d**2)263b = ((b2 + l*h2*(b1-b2)*(a2 // d)) + h3*((f - b2**2) // d)) % (a)264a =a.monic()265return (a, b)266267def cantor_composition(D1,D2,f,h,genus):268r"""269EXAMPLES::270271sage: F.<a> = GF(7^2, 'a')272sage: x = F['x'].gen()273sage: f = x^7 + x^2 + a274sage: H = HyperellipticCurve(f, 2*x); H275Hyperelliptic Curve over Finite Field in a of size 7^2 defined by y^2 + 2*x*y = x^7 + x^2 + a276sage: J = H.jacobian()(F); J277Set of rational points of Jacobian of Hyperelliptic Curve over278Finite Field in a of size 7^2 defined by y^2 + 2*x*y = x^7 + x^2 + a279280::281282sage: Q = J(H.lift_x(F(1))); Q283(x + 6, y + 2*a + 2)284sage: 10*Q # indirect doctest285(x^3 + (3*a + 1)*x^2 + (2*a + 5)*x + a + 5, y + (4*a + 5)*x^2 + (a + 1)*x + 6*a + 3)286sage: 7*8297*Q287(1)288289::290291sage: Q = J(H.lift_x(F(a+1))); Q292(x + 6*a + 6, y + 2)293sage: 7*8297*Q # indirect doctest294(1)295296A test over a prime field:297298sage: F = GF(next_prime(10^30))299sage: x = F['x'].gen()300sage: f = x^7 + x^2 + 1301sage: H = HyperellipticCurve(f, 2*x); H302Hyperelliptic Curve over Finite Field of size 1000000000000000000000000000057 defined by y^2 + 2*x*y = x^7 + x^2 + 1303sage: J = H.jacobian()(F); J304verbose 0 (...: multi_polynomial_ideal.py, dimension) Warning: falling back to very slow toy implementation.305Set of rational points of Jacobian of Hyperelliptic Curve over306Finite Field of size 1000000000000000000000000000057 defined307by y^2 + 2*x*y = x^7 + x^2 + 1308sage: Q = J(H.lift_x(F(1))); Q309(x + 1000000000000000000000000000056, y + 1000000000000000000000000000056)310sage: 10*Q # indirect doctest311(x^3 + 150296037169838934997145567227*x^2 + 377701248971234560956743242408*x + 509456150352486043408603286615, y + 514451014495791237681619598519*x^2 + 875375621665039398768235387900*x + 861429240012590886251910326876)312sage: 7*8297*Q313(x^3 + 35410976139548567549919839063*x^2 + 26230404235226464545886889960*x + 681571430588959705539385624700, y + 999722365017286747841221441793*x^2 + 262703715994522725686603955650*x + 626219823403254233972118260890)314"""315a1, b1 = D1316a2, b2 = D2317if a1 == a2 and b1 == b2:318# Duplication law:319d, h1, h3 = a1.xgcd(2*b1 + h)320a = (a1 // d)**2;321b = (b1 + h3*((f-h*b1-b1**2) // d)) % (a)322else:323d0, _, h2 = a1.xgcd(a2)324if d0 == 1:325a = a1*a2;326b = (b2 + h2*a2*(b1-b2)) % (a)327else:328e0 = b1+b2+h329if e0 == 0:330a = (a1*a2) // (d0**2)331b = (b2 + h2*(b1-b2)*(a2 // d0)) % (a)332else:333d, l, h3 = d0.xgcd(e0)334a = (a1*a2) // (d**2)335b = (b2 + l*h2*(b1-b2)*(a2 // d) + h3*((f-h*b2-b2**2) // d)) % (a)336a = a.monic()337return (a, b)338339class JacobianMorphism_divisor_class_field(AdditiveGroupElement, SchemeMorphism):340r"""341An element of a Jacobian defined over a field, i.e. in342`J(K) = \mathrm{Pic}^0_K(C)`.343"""344def __init__(self, parent, polys, check=True):345r"""346Create a new Jacobian element in Mumford representation.347348INPUT: parent: the parent Homset polys: Mumford's `u` and349`v` polynomials check (default: True): if True, ensure that350polynomials define a divisor on the appropriate curve and are351reduced352353.. warning::354355Not for external use! Use ``J(K)([u, v])`` instead.356357EXAMPLES::358359sage: x = GF(37)['x'].gen()360sage: H = HyperellipticCurve(x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x)361sage: J = H.jacobian()(GF(37)); J362Set of rational points of Jacobian of Hyperelliptic Curve over363Finite Field of size 37 defined by364y^2 = x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x365366::367368sage: P1 = J(H.lift_x(2)); P1 # indirect doctest369(x + 35, y + 26)370sage: P1.parent()371Set of rational points of Jacobian of Hyperelliptic Curve over372Finite Field of size 37 defined by373y^2 = x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x374sage: type(P1)375<class 'sage.schemes.hyperelliptic_curves.jacobian_morphism.JacobianMorphism_divisor_class_field'>376"""377SchemeMorphism.__init__(self, parent)378if check:379C = parent.curve()380f, h = C.hyperelliptic_polynomials()381a, b = polys382if not (b**2 + h*b - f)%a == 0:383raise ValueError, \384"Argument polys (= %s) must be divisor on curve %s."%(385polys, C)386genus = C.genus()387if a.degree() > genus:388polys = cantor_reduction(a, b, f, h, genus)389self.__polys = polys390391def _printing_polys(self):392r"""393Internal function formatting Mumford polynomials for printing.394395TESTS::396397sage: F.<a> = GF(7^2, 'a')398sage: x = F['x'].gen()399sage: f = x^7 + x^2 + a400sage: H = HyperellipticCurve(f, 2*x)401sage: J = H.jacobian()(F)402403::404405sage: Q = J(H.lift_x(F(1))); Q # indirect doctest406(x + 6, y + 2*a + 2)407"""408a, b = self.__polys409P = self.parent()._printing_ring410y = P.gen()411x = P.base_ring().gen()412return (a(x), y - b(x))413414def _repr_(self):415r"""416Return a string representation of this Mumford divisor.417418EXAMPLES::419420sage: F.<a> = GF(7^2, 'a')421sage: x = F['x'].gen()422sage: f = x^7 + x^2 + a423sage: H = HyperellipticCurve(f, 2*x)424sage: J = H.jacobian()(F)425426::427428sage: Q = J(0); Q # indirect doctest429(1)430sage: Q = J(H.lift_x(F(1))); Q # indirect doctest431(x + 6, y + 2*a + 2)432sage: Q + Q # indirect doctest433(x^2 + 5*x + 1, y + 3*a*x + 6*a + 2)434"""435if self.is_zero():436return "(1)"437a, b = self._printing_polys()438return "(%s, %s)" % (a, b)439440def _latex_(self):441r"""442Return a LaTeX string representing this Mumford divisor.443444EXAMPLES::445446sage: F.<alpha> = GF(7^2)447sage: x = F['x'].gen()448sage: f = x^7 + x^2 + alpha449sage: H = HyperellipticCurve(f, 2*x)450sage: J = H.jacobian()(F)451452::453454sage: Q = J(0); print latex(Q) # indirect doctest455\left(1\right)456sage: Q = J(H.lift_x(F(1))); print latex(Q) # indirect doctest457\left(x + 6, y + 2 \alpha + 2\right)458459::460461sage: print latex(Q + Q)462\left(x^{2} + 5 x + 1, y + 3 \alpha x + 6 \alpha + 2\right)463"""464if self.is_zero():465return "\\left(1\\right)"466a, b = self._printing_polys()467return "\\left(%s, %s\\right)" % (latex(a), latex(b))468469def scheme(self):470r"""471Return the scheme this morphism maps to; or, where this divisor472lives.473474.. warning::475476Although a pointset is defined over a specific field, the477scheme returned may be over a different (usually smaller)478field. The example below demonstrates this: the pointset479is determined over a number field of absolute degree 2 but480the scheme returned is defined over the rationals.481482EXAMPLES::483484sage: x = QQ['x'].gen()485sage: f = x^5 + x486sage: H = HyperellipticCurve(f)487sage: F.<a> = NumberField(x^2 - 2, 'a')488sage: J = H.jacobian()(F); J489Set of rational points of Jacobian of Hyperelliptic Curve over490Number Field in a with defining polynomial x^2 - 2 defined491by y^2 = x^5 + x492493::494495sage: P = J(H.lift_x(F(1)))496sage: P.scheme()497Jacobian of Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x498"""499return self.codomain()500501502def __list__(self):503r"""504Return a list `(a(x), b(x))` of the polynomials giving the505Mumford representation of self.506507TESTS::508509sage: x = QQ['x'].gen()510sage: f = x^5 + x511sage: H = HyperellipticCurve(f)512sage: F.<a> = NumberField(x^2 - 2, 'a')513sage: J = H.jacobian()(F); J514Set of rational points of Jacobian of Hyperelliptic Curve over515Number Field in a with defining polynomial x^2 - 2 defined516by y^2 = x^5 + x517518::519520sage: P = J(H.lift_x(F(1)))521sage: list(P) # indirect doctest522[x - 1, a]523"""524return list(self.__polys)525526def __tuple__(self):527r"""528Return a tuple `(a(x), b(x))` of the polynomials giving the529Mumford representation of self.530531TESTS::532533sage: x = QQ['x'].gen()534sage: f = x^5 + x535sage: H = HyperellipticCurve(f)536sage: F.<a> = NumberField(x^2 - 2, 'a')537sage: J = H.jacobian()(F); J538Set of rational points of Jacobian of Hyperelliptic Curve over539Number Field in a with defining polynomial x^2 - 2 defined540by y^2 = x^5 + x541542::543544sage: P = J(H.lift_x(F(1)))545sage: tuple(P) # indirect doctest546(x - 1, a)547"""548return tuple(self.__polys)549550def __getitem__(self, n):551r"""552Return the `n`-th item of the pair `(a(x), b(x))`553of polynomials giving the Mumford representation of self.554555TESTS::556557sage: x = QQ['x'].gen()558sage: f = x^5 + x559sage: H = HyperellipticCurve(f)560sage: F.<a> = NumberField(x^2 - 2, 'a')561sage: J = H.jacobian()(F); J562Set of rational points of Jacobian of Hyperelliptic Curve over563Number Field in a with defining polynomial x^2 - 2 defined564by y^2 = x^5 + x565566::567568sage: P = J(H.lift_x(F(1)))569sage: P[0] # indirect doctest570x - 1571sage: P[1] # indirect doctest572a573sage: P[-1] # indirect doctest574a575sage: P[:1] # indirect doctest576[x - 1]577"""578return list(self.__polys)[n]579580def __cmp__(self, other):581r"""582Compare self and other.583584TESTS::585586sage: x = QQ['x'].gen()587sage: f = x^5 - x588sage: H = HyperellipticCurve(f); H589Hyperelliptic Curve over Rational Field defined by y^2 = x^5 - x590sage: J = H.jacobian()(QQ); J591Set of rational points of Jacobian of Hyperelliptic Curve over592Rational Field defined by y^2 = x^5 - x593594The following point is 2-torsion::595596sage: P = J(H.lift_x(-1)); P597(x + 1, y)598sage: 0 == 2 * P # indirect doctest599True600sage: P == P601True602603::604605sage: Q = J(H.lift_x(-1))606sage: Q == P607True608609::610611sage: 2 == Q612False613sage: P == False614False615616Let's verify the same "points" on different schemes are not equal::617618sage: x = QQ['x'].gen()619sage: f = x^5 + x620sage: H2 = HyperellipticCurve(f)621sage: J2 = H2.jacobian()(QQ)622623::624625sage: P1 = J(H.lift_x(0)); P1626(x, y)627sage: P2 = J2(H2.lift_x(0)); P2628(x, y)629sage: P1 == P2630False631"""632if not isinstance(other, JacobianMorphism_divisor_class_field):633try:634other = self.parent()(other)635except TypeError:636return -1637if self.scheme() != other.scheme():638return -1639# since divisors are internally represented as Mumford divisors,640# comparing polynomials is well-defined641return cmp(self.__polys, other.__polys)642643def __nonzero__(self):644r"""645Return True if this divisor is not the additive identity element.646647EXAMPLES::648649sage: x = GF(37)['x'].gen()650sage: H = HyperellipticCurve(x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x)651sage: J = H.jacobian()(GF(37))652653::654655sage: P1 = J(H.lift_x(2)); P1656(x + 35, y + 26)657sage: P1 == 0 # indirect doctest658False659sage: P1 - P1 == 0 # indirect doctest660True661"""662return self.__polys[0] != 1663664def __neg__(self):665r"""666Return the additive inverse of this divisor.667668EXAMPLES::669670sage: x = GF(37)['x'].gen()671sage: H = HyperellipticCurve(x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x)672sage: J = H.jacobian()(GF(37))673sage: P1 = J(H.lift_x(2)); P1674(x + 35, y + 26)675sage: - P1 # indirect doctest676(x + 35, y + 11)677sage: P1 - P1 # indirect doctest678(1)679680::681682sage: H2 = HyperellipticCurve(x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x, x)683sage: J2 = H2.jacobian()(GF(37))684sage: P2 = J2(H2.lift_x(2)); P2685(x + 35, y + 15)686sage: - P2 # indirect doctest687(x + 35, y + 24)688sage: P2 - P2 # indirect doctest689(1)690"""691if self.is_zero():692return self693polys = self.__polys694X = self.parent()695f, h = X.curve().hyperelliptic_polynomials()696if h.is_zero():697D = (polys[0],-polys[1])698else:699D = (polys[0],-polys[1]-h % (polys[0]))700return JacobianMorphism_divisor_class_field(X, D, check=False)701702def _add_(self,other):703r"""704Return a Mumford representative of the divisor self + other.705706EXAMPLES::707708sage: x = GF(37)['x'].gen()709sage: H = HyperellipticCurve(x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x)710sage: J = H.jacobian()(GF(37))711712::713714sage: P1 = J(H.lift_x(2)); P1715(x + 35, y + 26)716sage: P1 + P1 # indirect doctest717(x^2 + 33*x + 4, y + 13*x)718"""719X = self.parent()720C = X.curve()721f, h = C.hyperelliptic_polynomials()722genus = C.genus()723if h == 0:724D = cantor_composition_simple(self.__polys, other.__polys, f, genus)725if D[0].degree() > genus:726D = cantor_reduction_simple(D[0], D[1], f, genus)727else:728D = cantor_composition(self.__polys, other.__polys, f, h, genus)729if D[0].degree() > genus:730D = cantor_reduction(D[0], D[1], f, h, genus)731return JacobianMorphism_divisor_class_field(X, D, check=False)732733def _sub_(self, other):734r"""735Return a Mumford representative of the divisor self - other.736737EXAMPLES::738739sage: x = GF(37)['x'].gen()740sage: H = HyperellipticCurve(x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x)741sage: J = H.jacobian()(GF(37))742743::744745sage: P1 = J(H.lift_x(2)); P1746(x + 35, y + 26)747sage: P1 - P1 # indirect doctest748(1)749750::751752sage: P2 = J(H.lift_x(4)); P2753(x + 33, y + 34)754755Observe that the `x`-coordinates are the same but the756`y`-coordinates differ::757758sage: P1 - P2 # indirect doctest759(x^2 + 31*x + 8, y + 7*x + 12)760sage: P1 + P2 # indirect doctest761(x^2 + 31*x + 8, y + 4*x + 18)762sage: (P1 - P2) - (P1 + P2) + 2*P2 # indirect doctest763(1)764"""765return self + (-other)766767768