From 8923a6a5bd2e8461563110336b288a9faed63fa6 Mon Sep 17 00:00:00 2001 From: Riccardo Invernizzi Date: Thu, 18 Jan 2024 15:30:38 +0100 Subject: [PATCH 1/2] Adding methods .x() and .y() for EllipticCurvePoint --- .../schemes/elliptic_curves/ell_generic.py | 2 +- src/sage/schemes/elliptic_curves/ell_point.py | 62 ++++++++++++++++--- src/sage/schemes/elliptic_curves/height.py | 2 +- src/sage/schemes/elliptic_curves/hom_sum.py | 2 +- .../schemes/elliptic_curves/hom_velusqrt.py | 26 ++++---- 5 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index 57003863b1b..2e8509cfcfe 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -619,7 +619,7 @@ def _reduce_point(self, R, p): sage: E = EllipticCurve([1,-1,0,94,9]) sage: R = E([0,3]) + 5*E([8,31]) - sage: factor(R.xy()[0].denominator()) + sage: factor(R.x().denominator()) 2^2 * 11^2 * 1457253032371^2 Since 11 is a factor of the denominator, this point corresponds to the diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 1bf84e9a766..f2303b3bfc3 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -778,6 +778,52 @@ def xy(self): else: return self[0]/self[2], self[1]/self[2] + def x(self): + """ + Return the `x` coordinate of this point, as an element of the base field. + If this is the point at infinity, a :class:`ZeroDivisionError` is raised. + + EXAMPLES:: + + sage: E = EllipticCurve('389a') + sage: P = E([-1,1]) + sage: P.x() + -1 + sage: Q = E(0); Q + (0 : 1 : 0) + sage: Q.x() + Traceback (most recent call last): + ... + ZeroDivisionError: rational division by zero + """ + if self[2] == 1: + return self[0] + else: + return self[0]/self[2] + + def y(self): + """ + Return the `y` coordinate of this point, as an element of the base field. + If this is the point at infinity, a :class:`ZeroDivisionError` is raised. + + EXAMPLES:: + + sage: E = EllipticCurve('389a') + sage: P = E([-1,1]) + sage: P.y() + 1 + sage: Q = E(0); Q + (0 : 1 : 0) + sage: Q.y() + Traceback (most recent call last): + ... + ZeroDivisionError: rational division by zero + """ + if self[2] == 1: + return self[1] + else: + return self[1]/self[2] + def is_divisible_by(self, m): """ Return True if there exists a point `Q` defined over the same @@ -1473,7 +1519,7 @@ def _miller_(self, Q, n): sage: Fx. = GF((2,(4*5))) sage: Ex = EllipticCurve(Fx, [0,0,1,1,1]) sage: phi = Hom(F,Fx)(F.gen().minpoly().roots(Fx)[0][0]) - sage: Px = Ex(phi(P.xy()[0]), phi(P.xy()[1])) + sage: Px = Ex(phi(P.x()), phi(P.y())) sage: Qx = Ex(b^19 + b^18 + b^16 + b^12 + b^10 + b^9 + b^8 + b^5 + b^3 + 1, ....: b^18 + b^13 + b^10 + b^8 + b^5 + b^4 + b^3 + b) sage: Px._miller_(Qx,41) == b^17 + b^13 + b^12 + b^9 + b^8 + b^6 + b^4 + 1 @@ -1658,7 +1704,7 @@ def weil_pairing(self, Q, n, algorithm=None): sage: Fx. = GF((2, 4*5)) sage: Ex = EllipticCurve(Fx, [0,0,1,1,1]) sage: phi = Hom(F, Fx)(F.gen().minpoly().roots(Fx)[0][0]) - sage: Px = Ex(phi(P.xy()[0]), phi(P.xy()[1])) + sage: Px = Ex(phi(P.x()), phi(P.y())) sage: O = Ex(0) sage: Qx = Ex(b^19 + b^18 + b^16 + b^12 + b^10 + b^9 + b^8 + b^5 + b^3 + 1, ....: b^18 + b^13 + b^10 + b^8 + b^5 + b^4 + b^3 + b) @@ -1898,7 +1944,7 @@ def tate_pairing(self, Q, n, k, q=None): sage: Fx. = GF((2,4*5)) sage: Ex = EllipticCurve(Fx,[0,0,1,1,1]) sage: phi = Hom(F, Fx)(F.gen().minpoly().roots(Fx)[0][0]) - sage: Px = Ex(phi(P.xy()[0]), phi(P.xy()[1])) + sage: Px = Ex(phi(P.x()), phi(P.y())) sage: Qx = Ex(b^19 + b^18 + b^16 + b^12 + b^10 + b^9 + b^8 + b^5 + b^3 + 1, ....: b^18 + b^13 + b^10 + b^8 + b^5 + b^4 + b^3 + b) sage: Px.tate_pairing(Qx, n=41, k=4) @@ -2070,7 +2116,7 @@ def ate_pairing(self, Q, n, k, t, q=None): sage: Fx. = GF(q^k) sage: Ex = EllipticCurve(Fx, [0,0,1,1,1]) sage: phi = Hom(F, Fx)(F.gen().minpoly().roots(Fx)[0][0]) - sage: Px = Ex(phi(P.xy()[0]), phi(P.xy()[1])) + sage: Px = Ex(phi(P.x()), phi(P.y())) sage: Qx = Ex(b^19+b^18+b^16+b^12+b^10+b^9+b^8+b^5+b^3+1, ....: b^18+b^13+b^10+b^8+b^5+b^4+b^3+b) sage: Qx = Ex(Qx[0]^q, Qx[1]^q) - Qx # ensure Qx is in ker(pi - q) @@ -3862,14 +3908,14 @@ def padic_elliptic_logarithm(self,Q, p): for k in range(0,p): Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + k * p for t in E.a_invariants() ]) - P_Qps = Eqp.lift_x(ZZ(self.xy()[0]), all=True) + P_Qps = Eqp.lift_x(ZZ(self.x()), all=True) for P_Qp in P_Qps: - if F(P_Qp.xy()[1]) == self.xy()[1]: + if F(P_Qp.y()) == self.y(): break - Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True) + Q_Qps = Eqp.lift_x(ZZ(Q.x()), all=True) for Q_Qp in Q_Qps: - if F(Q_Qp.xy()[1]) == Q.xy()[1]: + if F(Q_Qp.y()) == Q.y(): break pP = p * P_Qp diff --git a/src/sage/schemes/elliptic_curves/height.py b/src/sage/schemes/elliptic_curves/height.py index 78736209ee5..309603a1aa5 100644 --- a/src/sage/schemes/elliptic_curves/height.py +++ b/src/sage/schemes/elliptic_curves/height.py @@ -1177,7 +1177,7 @@ def psi(self, xi, v): 3.51086196882538 sage: L(P) / L.real_period() 0.867385122699931 - sage: xP = v(P.xy()[0]) + sage: xP = v(P.x()) sage: H = E.height_function() sage: H.psi(xP, v) 0.867385122699931 diff --git a/src/sage/schemes/elliptic_curves/hom_sum.py b/src/sage/schemes/elliptic_curves/hom_sum.py index 6660035634d..3727ff67e76 100644 --- a/src/sage/schemes/elliptic_curves/hom_sum.py +++ b/src/sage/schemes/elliptic_curves/hom_sum.py @@ -306,7 +306,7 @@ def to_isogeny_chain(self): from sage.groups.generic import multiples from sage.misc.misc_c import prod x = polygen(Kl.base_ring()) - poly = prod(x - T.xy()[0] for T in multiples(Kl, l//2, Kl)) + poly = prod(x - T.x() for T in multiples(Kl, l//2, Kl)) poly = poly.change_ring(self.base_ring()) psi = phi.codomain().isogeny(poly) diff --git a/src/sage/schemes/elliptic_curves/hom_velusqrt.py b/src/sage/schemes/elliptic_curves/hom_velusqrt.py index fbe4887dbae..33bccacd137 100644 --- a/src/sage/schemes/elliptic_curves/hom_velusqrt.py +++ b/src/sage/schemes/elliptic_curves/hom_velusqrt.py @@ -260,7 +260,7 @@ class FastEllipticPolynomial: Fast elliptic polynomial prod(Z - x(i*P) for i in range(1,n,2)) with n = 19, P = (4 : 35 : 1) sage: hP(7) 19 - sage: prod(7 - (i*P).xy()[0] for i in range(1,P.order(),2)) + sage: prod(7 - (i*P).x() for i in range(1,P.order(),2)) 19 Passing `Q` changes the index set:: @@ -269,7 +269,7 @@ class FastEllipticPolynomial: sage: hPQ = FastEllipticPolynomial(E, P.order(), P, Q) sage: hPQ(7) 58 - sage: prod(7 - (Q+i*P).xy()[0] for i in range(P.order())) + sage: prod(7 - (Q+i*P).x() for i in range(P.order())) 58 The call syntax has an optional keyword argument ``derivative``, which @@ -279,7 +279,7 @@ class FastEllipticPolynomial: sage: hP(7, derivative=True) (19, 15) sage: R. = E.base_field()[] - sage: HP = prod(Z - (i*P).xy()[0] for i in range(1,P.order(),2)) + sage: HP = prod(Z - (i*P).x() for i in range(1,P.order(),2)) sage: HP Z^9 + 16*Z^8 + 57*Z^7 + 6*Z^6 + 45*Z^5 + 31*Z^4 + 46*Z^3 + 10*Z^2 + 28*Z + 41 sage: HP(7) @@ -292,7 +292,7 @@ class FastEllipticPolynomial: sage: hPQ(7, derivative=True) (58, 62) sage: R. = E.base_field()[] - sage: HPQ = prod(Z - (Q+i*P).xy()[0] for i in range(P.order())) + sage: HPQ = prod(Z - (Q+i*P).x() for i in range(P.order())) sage: HPQ Z^19 + 53*Z^18 + 67*Z^17 + 39*Z^16 + 56*Z^15 + 32*Z^14 + 44*Z^13 + 6*Z^12 + 27*Z^11 + 29*Z^10 + 38*Z^9 + 48*Z^8 + 38*Z^7 + 43*Z^6 + 21*Z^5 + 25*Z^4 + 33*Z^3 + 49*Z^2 + 60*Z sage: HPQ(7) @@ -342,9 +342,9 @@ def __init__(self, E, n, P, Q=None): ) I, J, K = IJK - xI = (R.xy()[0] for R in _points_range(I, P, Q)) - xJ = [R.xy()[0] for R in _points_range(J, P )] - xK = (R.xy()[0] for R in _points_range(K, P, Q)) + xI = (R.x() for R in _points_range(I, P, Q)) + xJ = [R.x() for R in _points_range(J, P )] + xK = (R.x() for R in _points_range(K, P, Q)) self.hItree = ProductTree(Z - xi for xi in xI) @@ -766,7 +766,7 @@ def _raw_eval(self, x, y=None): sage: phi._raw_codomain Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 65537 sage: Q = E(42, 15860) - sage: phi._raw_eval(Q.xy()[0]) + sage: phi._raw_eval(Q.x()) 11958 sage: phi._raw_eval(*Q.xy()) (11958, 42770) @@ -794,8 +794,8 @@ def _raw_eval(self, x, y=None): h0, h0d = self._h0(x, derivative=True) h1, h1d = self._h1(x, derivative=True) -# assert h0 == prod(x - ( i*self._P).xy()[0] for i in range(1,self._P.order(),2)) -# assert h1 == prod(x - (self._Q+i*self._P).xy()[0] for i in range( self._P.order() )) +# assert h0 == prod(x - ( i*self._P).x() for i in range(1,self._P.order(),2)) +# assert h1 == prod(x - (self._Q+i*self._P).x() for i in range( self._P.order() )) if not h0: return () @@ -805,8 +805,8 @@ def _raw_eval(self, x, y=None): if y is None: return xx -# assert h0d == sum(prod(x - ( i*self._P).xy()[0] for i in range(1,self._P.order(),2) if i!=j) for j in range(1,self._P.order(),2)) -# assert h1d == sum(prod(x - (self._Q+i*self._P).xy()[0] for i in range( self._P.order() ) if i!=j) for j in range( self._P.order() )) +# assert h0d == sum(prod(x - ( i*self._P).x() for i in range(1,self._P.order(),2) if i!=j) for j in range(1,self._P.order(),2)) +# assert h1d == sum(prod(x - (self._Q+i*self._P).x() for i in range( self._P.order() ) if i!=j) for j in range( self._P.order() )) yy = y * (h1d - 2 * h1 / h0 * h0d) / h0**2 @@ -1026,7 +1026,7 @@ def kernel_polynomial(self): x^15 + 21562*x^14 + 8571*x^13 + 20029*x^12 + 1775*x^11 + 60402*x^10 + 17481*x^9 + 46543*x^8 + 46519*x^7 + 18590*x^6 + 36554*x^5 + 36499*x^4 + 48857*x^3 + 3066*x^2 + 23264*x + 53937 sage: h == E.isogeny(K).kernel_polynomial() True - sage: h(K.xy()[0]) + sage: h(K.x()) 0 TESTS:: From ac527fbac3c17e7de73bc1cbaf21bcb93e6d7d23 Mon Sep 17 00:00:00 2001 From: Riccardo Invernizzi Date: Sun, 21 Jan 2024 20:32:27 +0100 Subject: [PATCH 2/2] Replaced `== 1` with the faster `.is_one()` method for `.x()`, `.y()` and `.xy(). --- src/sage/schemes/elliptic_curves/ell_point.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index f2303b3bfc3..7635678ff3b 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -773,7 +773,7 @@ def xy(self): ... ZeroDivisionError: rational division by zero """ - if self[2] == 1: + if self[2].is_one(): return self[0], self[1] else: return self[0]/self[2], self[1]/self[2] @@ -796,7 +796,7 @@ def x(self): ... ZeroDivisionError: rational division by zero """ - if self[2] == 1: + if self[2].is_one(): return self[0] else: return self[0]/self[2] @@ -819,7 +819,7 @@ def y(self): ... ZeroDivisionError: rational division by zero """ - if self[2] == 1: + if self[2].is_one(): return self[1] else: return self[1]/self[2]