From 8e95731eaec4211fd8e08d7ef3799a4640e5c107 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 7 Oct 2022 13:46:25 +0900 Subject: [PATCH] Minor edits mostly on spaces Minor edits --- .../elliptic_curves/ell_curve_isogeny.py | 23 ++----- src/sage/schemes/elliptic_curves/hom.py | 10 +-- .../schemes/elliptic_curves/hom_composite.py | 19 ++++-- .../schemes/elliptic_curves/hom_velusqrt.py | 66 +++++++++---------- 4 files changed, 52 insertions(+), 66 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index f6a90401f01..3a18e7d4a38 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -18,14 +18,18 @@ sage: Q = E(6,5) sage: phi = E.isogeny(Q) sage: phi - Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 11 to Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 11 + Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + x + 1 over + Finite Field of size 11 to Elliptic Curve defined by y^2 = x^3 + 7*x + 8 + over Finite Field of size 11 sage: P = E(4,5) sage: phi(P) (10 : 0 : 1) sage: phi.codomain() Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 11 sage: phi.rational_maps() - ((x^7 + 4*x^6 - 3*x^5 - 2*x^4 - 3*x^3 + 3*x^2 + x - 2)/(x^6 + 4*x^5 - 4*x^4 - 5*x^3 + 5*x^2), (x^9*y - 5*x^8*y - x^7*y + x^5*y - x^4*y - 5*x^3*y - 5*x^2*y - 2*x*y - 5*y)/(x^9 - 5*x^8 + 4*x^6 - 3*x^4 + 2*x^3)) + ((x^7 + 4*x^6 - 3*x^5 - 2*x^4 - 3*x^3 + 3*x^2 + x - 2)/(x^6 + 4*x^5 - 4*x^4 + - 5*x^3 + 5*x^2), (x^9*y - 5*x^8*y - x^7*y + x^5*y - x^4*y - 5*x^3*y - + 5*x^2*y - 2*x*y - 5*y)/(x^9 - 5*x^8 + 4*x^6 - 3*x^4 + 2*x^3)) The methods directly accessible from an elliptic curve ``E`` over a field are @@ -337,7 +341,6 @@ def compute_vw_kohel_even_deg3(b2, b4, s1, s2, s3): w = 3*(s1**3 - 3*s1*s2 + 3*s3) + (b2*temp1 + b4*s1)/2 return v, w - def compute_vw_kohel_odd(b2, b4, b6, s1, s2, s3, n): r""" Compute Vélu's `(v,w)` using Kohel's formulas for isogenies of odd @@ -374,7 +377,6 @@ def compute_vw_kohel_odd(b2, b4, b6, s1, s2, s3, n): w = 10*(s1**3 - 3*s1*s2 + 3*s3) + 2*b2*(s1**2 - 2*s2) + 3*b4*s1 + n*b6 return v, w - def compute_codomain_kohel(E, kernel): r""" Compute the codomain from the kernel polynomial using Kohel's @@ -481,7 +483,6 @@ def compute_codomain_kohel(E, kernel): return compute_codomain_formula(E, v, w) - def two_torsion_part(E, psi): r""" Return the greatest common divisor of ``psi`` and the 2-torsion @@ -516,6 +517,7 @@ def two_torsion_part(E, psi): psi_2 = E.two_division_polynomial(x) return psi.gcd(psi_2) + class EllipticCurveIsogeny(EllipticCurveHom): r""" This class implements separable isogenies of elliptic curves. @@ -1739,7 +1741,6 @@ def __setup_post_isomorphism(self, codomain, model): post_isom = oldE2.isomorphism_to(codomain) self.__set_post_isomorphism(codomain, post_isom) - ########################### # Velu's Formula Functions ########################### @@ -1873,7 +1874,6 @@ def __compute_codomain_via_velu(self): """ return compute_codomain_formula(self._domain, self.__v, self.__w) - @staticmethod def __velu_sum_helper(xQ, Qvalues, a1, a3, x, y): r""" @@ -1922,7 +1922,6 @@ def __velu_sum_helper(xQ, Qvalues, a1, a3, x, y): return tX, tY - def __compute_via_velu_numeric(self, xP, yP): r""" Private function that sorts the list of points in the kernel @@ -1952,7 +1951,6 @@ def __compute_via_velu_numeric(self, xP, yP): return self.__compute_via_velu(xP,yP) - def __compute_via_velu(self, xP, yP): r""" Private function for Vélu's formulas, to perform the summation. @@ -2018,7 +2016,6 @@ def __compute_via_velu(self, xP, yP): return X, Y - def __initialize_rational_maps_via_velu(self): r""" Private function for Vélu's formulas, helper function to @@ -2040,7 +2037,6 @@ def __initialize_rational_maps_via_velu(self): y = self.__mpoly_ring.gen(1) return self.__compute_via_velu(x,y) - def __init_kernel_polynomial_velu(self): r""" Private function for Vélu's formulas, helper function to @@ -2070,7 +2066,6 @@ def __init_kernel_polynomial_velu(self): self.__kernel_polynomial = psi - ################################### # Kohel's Variant of Velu's Formula ################################### @@ -2262,7 +2257,6 @@ def __init_even_kernel_polynomial(self, E, psi_G): return phi, omega, v, w, n, d - def __init_odd_kernel_polynomial(self, E, psi): r""" Return the isogeny parameters for a cyclic isogeny of odd degree. @@ -2363,7 +2357,6 @@ def __init_odd_kernel_polynomial(self, E, psi): return phi, omega, v, w, n, d - # # This is the fast omega computation that works when characteristic is not 2 # @@ -3246,7 +3239,6 @@ def split_kernel_polynomial(poly): from sage.misc.misc_c import prod return prod([p for p,e in poly.squarefree_decomposition()]) - def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="starks"): r""" Return the kernel polynomial of an isogeny of degree ``ell`` @@ -3487,7 +3479,6 @@ def compute_sequence_of_maps(E1, E2, ell): return pre_isom, post_isom, E1pr, E2pr, ker_poly - # Utility functions for manipulating isogeny degree matrices def fill_isogeny_matrix(M): diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index 76087e95c7f..f69c6ead9b3 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -20,7 +20,6 @@ - Lorenz Panny (2021): Refactor isogenies and isomorphisms into the common :class:`EllipticCurveHom` interface. """ - from sage.misc.cachefunc import cached_method from sage.structure.richcmp import richcmp_not_equal, richcmp, op_EQ, op_NE @@ -93,7 +92,6 @@ def _composition_(self, other, homset): from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite return EllipticCurveHom_composite.from_factors([other, self]) - @staticmethod def _comparison_impl(left, right, op): """ @@ -194,7 +192,6 @@ def _richcmp_(self, other, op): return richcmp(self.rational_maps(), other.rational_maps(), op) - def degree(self): r""" Return the degree of this elliptic-curve morphism. @@ -327,11 +324,10 @@ def x_rational_map(self): ... NotImplementedError: ... """ - #TODO: could have a default implementation that simply - # returns the first component of rational_maps() + # TODO: could have a default implementation that simply + # returns the first component of rational_maps() raise NotImplementedError('children must implement') - def scaling_factor(self): r""" Return the Weierstrass scaling factor associated to this @@ -409,7 +405,6 @@ def formal(self, prec=20): assert th.valuation() == +1, f"th has valuation {th.valuation()} (should be +1)" return th - def is_normalized(self): r""" Determine whether this morphism is a normalized isogeny. @@ -489,7 +484,6 @@ def is_normalized(self): """ return self.scaling_factor() == 1 - def is_separable(self): r""" Determine whether or not this morphism is separable. diff --git a/src/sage/schemes/elliptic_curves/hom_composite.py b/src/sage/schemes/elliptic_curves/hom_composite.py index 1e2ca2658b0..5d0b546488e 100644 --- a/src/sage/schemes/elliptic_curves/hom_composite.py +++ b/src/sage/schemes/elliptic_curves/hom_composite.py @@ -24,7 +24,9 @@ sage: EllipticCurveHom_composite(E, P) Composite morphism of degree 11150372599265311570767859136324180752990208 = 2^143: From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 33451117797795934712303577408972542258970623^2 - To: Elliptic Curve defined by y^2 = x^3 + (18676616716352953484576727486205473216172067*z2+32690199585974925193292786311814241821808308)*x + (3369702436351367403910078877591946300201903*z2+15227558615699041241851978605002704626689722) over Finite Field in z2 of size 33451117797795934712303577408972542258970623^2 + To: Elliptic Curve defined by y^2 = x^3 + (18676616716352953484576727486205473216172067*z2+32690199585974925193292786311814241821808308)*x + + (3369702436351367403910078877591946300201903*z2+15227558615699041241851978605002704626689722) + over Finite Field in z2 of size 33451117797795934712303577408972542258970623^2 Yet, the interface provided by :class:`EllipticCurveHom_composite` is identical to :class:`EllipticCurveIsogeny` and other instantiations @@ -40,10 +42,15 @@ sage: psi(E.lift_x(11)) (352 : 73 : 1) sage: psi.rational_maps() - ((x^35 + 162*x^34 + 186*x^33 + 92*x^32 - ... + 44*x^3 + 190*x^2 + 80*x - 72)/(x^34 + 162*x^33 - 129*x^32 + 41*x^31 + ... + 66*x^3 - 191*x^2 + 119*x + 21), - (x^51*y - 176*x^50*y + 115*x^49*y - 120*x^48*y + ... + 72*x^3*y + 129*x^2*y + 163*x*y + 178*y)/(x^51 - 176*x^50 + 11*x^49 + 26*x^48 - ... - 77*x^3 + 185*x^2 + 169*x - 128)) + ((x^35 + 162*x^34 + 186*x^33 + 92*x^32 - ... + 44*x^3 + 190*x^2 + 80*x - + 72)/(x^34 + 162*x^33 - 129*x^32 + 41*x^31 + ... + 66*x^3 - 191*x^2 + 119*x + + 21), (x^51*y - 176*x^50*y + 115*x^49*y - 120*x^48*y + ... + 72*x^3*y + + 129*x^2*y + 163*x*y + 178*y)/(x^51 - 176*x^50 + 11*x^49 + 26*x^48 - ... - + 77*x^3 + 185*x^2 + 169*x - 128)) sage: psi.kernel_polynomial() - x^17 + 81*x^16 + 7*x^15 + 82*x^14 + 49*x^13 + 68*x^12 + 109*x^11 + 326*x^10 + 117*x^9 + 136*x^8 + 111*x^7 + 292*x^6 + 55*x^5 + 389*x^4 + 175*x^3 + 43*x^2 + 149*x + 373 + x^17 + 81*x^16 + 7*x^15 + 82*x^14 + 49*x^13 + 68*x^12 + 109*x^11 + 326*x^10 + + 117*x^9 + 136*x^8 + 111*x^7 + 292*x^6 + 55*x^5 + 389*x^4 + 175*x^3 + + 43*x^2 + 149*x + 373 sage: psi.dual() Composite morphism of degree 35 = 7*5: From: Elliptic Curve defined by y^2 = x^3 + 101*x + 285 over Finite Field of size 419 @@ -82,7 +89,7 @@ from sage.schemes.elliptic_curves.ell_curve_isogeny import EllipticCurveIsogeny from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism -#TODO: implement sparse strategies? (cf. the SIKE cryptosystem) +# TODO: Implement sparse strategies? (cf. the SIKE cryptosystem) def _eval_factored_isogeny(phis, P): """ @@ -468,7 +475,6 @@ def factors(self): """ return self._phis - # EllipticCurveHom methods @staticmethod @@ -765,7 +771,6 @@ def is_injective(self): """ return all(phi.is_injective() for phi in self._phis) - @staticmethod def make_default(): r""" diff --git a/src/sage/schemes/elliptic_curves/hom_velusqrt.py b/src/sage/schemes/elliptic_curves/hom_velusqrt.py index 1c93950e6db..45a582782db 100644 --- a/src/sage/schemes/elliptic_curves/hom_velusqrt.py +++ b/src/sage/schemes/elliptic_curves/hom_velusqrt.py @@ -1,23 +1,18 @@ r""" -√élu Algorithm for Elliptic-Curve Isogenies - -The √élu algorithm computes isogenies of elliptic curves in time -`\tilde O(\sqrt\ell)` rather than naïvely `O(\ell)`, where `\ell` -is the degree. - -The core idea is to reindex the points in the kernel subgroup in -a baby-step-giant-step manner, then use fast resultant computations -to evaluate "elliptic polynomials" -(see :class:`FastEllipticPolynomial`) -in essentially square-root time. - -Based on experiments with Sage version 9.7, -the isogeny degree where -:class:`EllipticCurveHom_velusqrt` -begins to outperform +√élu algorithm for elliptic-curve isogenies + +The √élu algorithm computes isogenies of elliptic curves in time `\tilde +O(\sqrt\ell)` rather than naïvely `O(\ell)`, where `\ell` is the degree. + +The core idea is to reindex the points in the kernel subgroup in a +baby-step-giant-step manner, then use fast resultant computations to evaluate +"elliptic polynomials" (see :class:`FastEllipticPolynomial`) in essentially +square-root time. + +Based on experiments with Sage version 9.7, the isogeny degree where +:class:`EllipticCurveHom_velusqrt` begins to outperform :class:`~sage.schemes.elliptic_curves.ell_curve_isogeny.EllipticCurveIsogeny` -can be as low as `\approx 100`, -but is typically closer to `\approx 1000`, +can be as low as `\approx 100`, but is typically closer to `\approx 1000`, depending on the exact situation. REFERENCES: [BDLS2020]_ @@ -135,7 +130,7 @@ from sage.schemes.elliptic_curves.hom import EllipticCurveHom, compare_via_evaluation -#TODO: This is general. It should be elsewhere. +# TODO: This is general. It should be elsewhere. class ProductTree: r""" A simple product tree. @@ -264,7 +259,7 @@ def remainders(self, x): X = [X[i//2] % V[i] for i in range(len(V))] return X -#TODO: This is general. It should be elsewhere. +# TODO: This is general. It should be elsewhere. def prod_with_derivative(pairs): r""" Given a list of pairs `(f, \partial f)` of ring elements, return @@ -328,7 +323,6 @@ def __iter__(self): return tuple(prod(_aux(*tup) for tup in pairs)) - def _choose_IJK(n): r""" Helper function to choose an "index system" for the set @@ -408,6 +402,7 @@ def _points_range(rr, P, Q=None): for _ in range(a+s, b, s): yield (R := R + sP) + class FastEllipticPolynomial: r""" A class to represent and evaluate an *elliptic polynomial*, @@ -736,7 +731,7 @@ def _point_outside_subgroup(P): F = E.base_field().extension(d) E = E.base_extend(F) P = E(P) -# assert E.cardinality() > n + # assert E.cardinality() > n for _ in range(1000): Q = E.random_point() if n*Q or not P.weil_pairing(Q,n).is_one(): @@ -744,6 +739,7 @@ def _point_outside_subgroup(P): else: raise NotImplementedError('could not find a point outside the kernel') + class EllipticCurveHom_velusqrt(EllipticCurveHom): r""" This class implements separable odd-degree isogenies of elliptic @@ -1224,9 +1220,9 @@ def kernel_polynomial(self): sage: phi.kernel_polynomial().parent() Univariate Polynomial Ring in x over Finite Field in a of size 65537^2 """ - R,x = self._domain.base_ring()['x'].objgen() - h = self._h0(x) - h = h(self._pre_iso.x_rational_map()) + R, x = self._domain.base_ring()['x'].objgen() + h0 = self._h0(x) + h = h0(self._pre_iso.x_rational_map()) return R(h).monic() @cached_method @@ -1241,8 +1237,8 @@ def dual(self): EXAMPLES:: - sage: E = EllipticCurve(GF(101^2), [1,1,1,1,1]) - sage: K = E.cardinality()//11 * E.gens()[0] + sage: E = EllipticCurve(GF(101^2), [1, 1, 1, 1, 1]) + sage: K = E.cardinality() // 11 * E.gens()[0] sage: phi = E.isogeny(K, algorithm='velusqrt'); phi Elliptic-curve isogeny (using √élu) of degree 11: From: Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 + x + 1 over Finite Field in z2 of size 101^2 @@ -1254,7 +1250,7 @@ def dual(self): sage: phi * phi.dual() == phi.codomain().multiplication_by_m_isogeny(11) True """ - #FIXME This code fails if the degree is divisible by the characteristic. + # FIXME: This code fails if the degree is divisible by the characteristic. F = self._raw_domain.base_ring() from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism isom = ~WeierstrassIsomorphism(self._raw_domain, (~F(self._degree), 0, 0, 0)) @@ -1274,8 +1270,8 @@ def rational_maps(self): EXAMPLES:: - sage: E = EllipticCurve(GF(101^2), [1,1,1,1,1]) - sage: K = E.cardinality()//11 * E.gens()[0] + sage: E = EllipticCurve(GF(101^2), [1, 1, 1, 1, 1]) + sage: K = (E.cardinality() // 11) * E.gens()[0] sage: phi = E.isogeny(K, algorithm='velusqrt'); phi Elliptic-curve isogeny (using √élu) of degree 11: From: Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 + x + 1 over Finite Field in z2 of size 101^2 @@ -1303,7 +1299,7 @@ def rational_maps(self): def x_rational_map(self): r""" Return the `x`-coordinate rational map of this √élu isogeny - as a univariate rational expression in `x`. + as a univariate rational function in `x`. .. NOTE:: @@ -1311,8 +1307,8 @@ def x_rational_map(self): EXAMPLES:: - sage: E = EllipticCurve(GF(101^2), [1,1,1,1,1]) - sage: K = E.cardinality()//11 * E.gens()[0] + sage: E = EllipticCurve(GF(101^2), [1, 1, 1, 1, 1]) + sage: K = (E.cardinality() // 11) * E.gens()[0] sage: phi = E.isogeny(K, algorithm='velusqrt'); phi Elliptic-curve isogeny (using √élu) of degree 11: From: Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 + x + 1 over Finite Field in z2 of size 101^2 @@ -1348,8 +1344,8 @@ def scaling_factor(self): EXAMPLES:: - sage: E = EllipticCurve(GF(101^2), [1,1,1,1,1]) - sage: K = E.cardinality()//11 * E.gens()[0] + sage: E = EllipticCurve(GF(101^2), [1, 1, 1, 1, 1]) + sage: K = (E.cardinality() // 11) * E.gens()[0] sage: phi = E.isogeny(K, algorithm='velusqrt', model='montgomery'); phi Elliptic-curve isogeny (using √élu) of degree 11: From: Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 + x + 1 over Finite Field in z2 of size 101^2