Elliptic curves over a general field - Elliptic curves

Skip to content
Back to top
View this page
Edit this page

# Elliptic curves over a general field

This module defines the class `EllipticCurve_field`, based on `EllipticCurve_generic`, for elliptic curves over general fields.

class sage.schemes.elliptic_curves.ell_field.EllipticCurve_field(R, data, category=None)

  Bases: `EllipticCurve_generic`, `ProjectivePlaneCurve_field`

  Constructor for elliptic curves over fields.

  Identical to the constructor for elliptic curves over general rings, except for setting the default category to `AbelianVarieties`.

  EXAMPLES:

  Sage

      sage: E = EllipticCurve(QQ, [1,1])
      sage: E.category()
      Category of abelian varieties over Rational Field
      sage: E = EllipticCurve(GF(101), [1,1])
      sage: E.category()
      Category of abelian varieties over Finite Field of size 101

  Python

      >>> from sage.all import *
      >>> E = EllipticCurve(QQ, [Integer(1),Integer(1)])
      >>> E.category()
      Category of abelian varieties over Rational Field
      >>> E = EllipticCurve(GF(Integer(101)), [Integer(1),Integer(1)])
      >>> E.category()
      Category of abelian varieties over Finite Field of size 101

  base_field()

    alias of `base_ring()`.

  descend_to(K, f=None)

    Given an elliptic curve `self` defined over a field \(L\) and a subfield \(K\) of \(L\), return all elliptic curves over \(K\) which are isomorphic over \(L\) to `self`.

    INPUT:

    - `K` – a field which embeds into the base field \(L\) of `self`

    - `f` – (optional) an embedding of \(K\) into \(L\); ignored if \(K\) is \(\QQ\)

    OUTPUT:

    A list (possibly empty) of elliptic curves defined over \(K\) which are isomorphic to `self` over \(L\), up to isomorphism over \(K\).

    Note

    Currently only implemented over number fields. To extend to other fields of characteristic not 2 or 3, what is needed is a method giving the preimages in \(K^*/(K^*)^m\) of an element of the base field, for \(m=2,4,6\).

    EXAMPLES:

    Sage

        sage: E = EllipticCurve([1,2,3,4,5])
        sage: E.descend_to(ZZ)
        Traceback (most recent call last):
        ...
        TypeError: Input must be a field.

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
        >>> E.descend_to(ZZ)
        Traceback (most recent call last):
        ...
        TypeError: Input must be a field.

    Sage

        sage: # needs sage.rings.number_field
        sage: F.<b> = QuadraticField(23)
        sage: x = polygen(ZZ, 'x')
        sage: G.<a> = F.extension(x^3 + 5)
        sage: E = EllipticCurve(j=1728*b).change_ring(G)
        sage: EF = E.descend_to(F); EF
        [Elliptic Curve defined by y^2 = x^3 + (27*b-621)*x + (-1296*b+2484)
          over Number Field in b with defining polynomial x^2 - 23
          with b = 4.795831523312720?]
        sage: all(Ei.change_ring(G).is_isomorphic(E) for Ei in EF)
        True

    [Python]

        >>> from sage.all import *
        >>> # needs sage.rings.number_field
        >>> F = QuadraticField(Integer(23), names=('b',)); (b,) = F._first_ngens(1)
        >>> x = polygen(ZZ, 'x')
        >>> G = F.extension(x**Integer(3) + Integer(5), names=('a',)); (a,) = G._first_ngens(1)
        >>> E = EllipticCurve(j=Integer(1728)*b).change_ring(G)
        >>> EF = E.descend_to(F); EF
        [Elliptic Curve defined by y^2 = x^3 + (27*b-621)*x + (-1296*b+2484)
          over Number Field in b with defining polynomial x^2 - 23
          with b = 4.795831523312720?]
        >>> all(Ei.change_ring(G).is_isomorphic(E) for Ei in EF)
        True

    Sage

        sage: # needs sage.rings.number_field
        sage: L.<a> = NumberField(x^4 - 7)
        sage: K.<b> = NumberField(x^2 - 7, embedding=a^2)
        sage: E = EllipticCurve([a^6, 0])
        sage: EK = E.descend_to(K); EK
        [Elliptic Curve defined by y^2 = x^3 + b*x over Number Field in b
          with defining polynomial x^2 - 7 with b = a^2,
         Elliptic Curve defined by y^2 = x^3 + 7*b*x over Number Field in b
          with defining polynomial x^2 - 7 with b = a^2]
        sage: all(Ei.change_ring(L).is_isomorphic(E) for Ei in EK)
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.number_field
        >>> L = NumberField(x**Integer(4) - Integer(7), names=('a',)); (a,) = L._first_ngens(1)
        >>> K = NumberField(x**Integer(2) - Integer(7), embedding=a**Integer(2), names=('b',)); (b,) = K._first_ngens(1)
        >>> E = EllipticCurve([a**Integer(6), Integer(0)])
        >>> EK = E.descend_to(K); EK
        [Elliptic Curve defined by y^2 = x^3 + b*x over Number Field in b
          with defining polynomial x^2 - 7 with b = a^2,
         Elliptic Curve defined by y^2 = x^3 + 7*b*x over Number Field in b
          with defining polynomial x^2 - 7 with b = a^2]
        >>> all(Ei.change_ring(L).is_isomorphic(E) for Ei in EK)
        True

    Sage

        sage: K.<a> = QuadraticField(17)                                            # needs sage.rings.number_field
        sage: E = EllipticCurve(j=2*a)                                              # needs sage.rings.number_field
        sage: E.descend_to(QQ)                                                      # needs sage.rings.number_field
        []

    [Python]

        >>> from sage.all import *
        >>> K = QuadraticField(Integer(17), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field
        >>> E = EllipticCurve(j=Integer(2)*a)                                              # needs sage.rings.number_field
        >>> E.descend_to(QQ)                                                      # needs sage.rings.number_field
        []

  division_field(n, names='t', map=False, **kwds)

    Given an elliptic curve over a number field or finite field \(F\) and a positive integer \(n\), construct the \(n\)-division field \(F(E[n])\).

    The \(n\)-division field is the smallest extension of \(F\) over which all \(n\)-torsion points of \(E\) are defined.

    INPUT:

    - `n` – positive integer

    - `names` – (default: `'t'`) a variable name for the division field

    - `map` – boolean (default: `False`); also return an embedding of the `base_field()` into the resulting field

    - `kwds` – additional keyword arguments passed to `splitting_field()`

    OUTPUT:

    If `map` is `False`, the division field \(K\) as an absolute number field or a finite field. If `map` is `True`, a tuple \((K, \phi)\) where \(\phi\) is an embedding of the base field in the division field \(K\).

    Warning

    This can take a very long time when the degree of the division field is large (e.g. when \(n\) is large or when the Galois representation is surjective). The `simplify` flag also has a big influence on the running time over number fields: sometimes `simplify=False` is faster, sometimes the default `simplify=True` is faster.

    EXAMPLES:

    The 2-division field is the same as the splitting field of the 2-division polynomial (therefore, it has degree 1, 2, 3 or 6):

    Sage

        sage: # needs sage.rings.number_field
        sage: E = EllipticCurve('15a1')
        sage: K.<b> = E.division_field(2); K
        Number Field in b with defining polynomial x
        sage: E = EllipticCurve('14a1')
        sage: K.<b> = E.division_field(2); K
        Number Field in b with defining polynomial x^2 + 5*x + 92
        sage: E = EllipticCurve('196b1')
        sage: K.<b> = E.division_field(2); K
        Number Field in b with defining polynomial x^3 + x^2 - 114*x - 127
        sage: E = EllipticCurve('19a1')
        sage: K.<b> = E.division_field(2); K
        Number Field in b with defining polynomial
         x^6 + 10*x^5 + 24*x^4 - 212*x^3 + 1364*x^2 + 24072*x + 104292

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.number_field
        >>> E = EllipticCurve('15a1')
        >>> K = E.division_field(Integer(2), names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial x
        >>> E = EllipticCurve('14a1')
        >>> K = E.division_field(Integer(2), names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial x^2 + 5*x + 92
        >>> E = EllipticCurve('196b1')
        >>> K = E.division_field(Integer(2), names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial x^3 + x^2 - 114*x - 127
        >>> E = EllipticCurve('19a1')
        >>> K = E.division_field(Integer(2), names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial
         x^6 + 10*x^5 + 24*x^4 - 212*x^3 + 1364*x^2 + 24072*x + 104292

    For odd primes \(n\), the division field is either the splitting field of the \(n\)-division polynomial, or a quadratic extension of it.

    Sage

        sage: # needs sage.rings.number_field
        sage: E = EllipticCurve('50a1')
        sage: F.<a> = E.division_polynomial(3).splitting_field(simplify_all=True); F
        Number Field in a
         with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
        sage: K.<b> = E.division_field(3, simplify_all=True); K
        Number Field in b
         with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3

    [Python]

        >>> from sage.all import *
        >>> # needs sage.rings.number_field
        >>> E = EllipticCurve('50a1')
        >>> F = E.division_polynomial(Integer(3)).splitting_field(simplify_all=True, names=('a',)); (a,) = F._first_ngens(1); F
        Number Field in a
         with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
        >>> K = E.division_field(Integer(3), simplify_all=True, names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b
         with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3

    If we take any quadratic twist, the splitting field of the 3-division polynomial remains the same, but the 3-division field becomes a quadratic extension:

    Sage

        sage: # needs sage.rings.number_field
        sage: E = E.quadratic_twist(5)  # 50b3
        sage: F.<a> = E.division_polynomial(3).splitting_field(simplify_all=True); F
        Number Field in a
         with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
        sage: K.<b> = E.division_field(3, simplify_all=True); K
        Number Field in b with defining polynomial x^12 - 3*x^11 + 8*x^10 - 15*x^9
         + 30*x^8 - 63*x^7 + 109*x^6 - 144*x^5 + 150*x^4 - 120*x^3 + 68*x^2 - 24*x + 4

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.number_field
        >>> E = E.quadratic_twist(Integer(5))  # 50b3
        >>> F = E.division_polynomial(Integer(3)).splitting_field(simplify_all=True, names=('a',)); (a,) = F._first_ngens(1); F
        Number Field in a
         with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
        >>> K = E.division_field(Integer(3), simplify_all=True, names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial x^12 - 3*x^11 + 8*x^10 - 15*x^9
         + 30*x^8 - 63*x^7 + 109*x^6 - 144*x^5 + 150*x^4 - 120*x^3 + 68*x^2 - 24*x + 4

    Try another quadratic twist, this time over a subfield of \(F\):

    Sage

        sage: # needs sage.rings.number_field
        sage: G.<c>,_,_ = F.subfields(3)[0]
        sage: E = E.base_extend(G).quadratic_twist(c); E
        Elliptic Curve defined
         by y^2 = x^3 + 5*a0*x^2 + (-200*a0^2)*x + (-42000*a0^2+42000*a0+126000)
         over Number Field in a0 with defining polynomial x^3 - 3*x^2 + 3*x + 9
        sage: K.<b> = E.division_field(3, simplify_all=True); K
        Number Field in b with defining polynomial x^12 + 5*x^10 + 40*x^8 + 315*x^6 + 750*x^4 + 675*x^2 + 2025

    [Python]

        >>> from sage.all import *
        >>> # needs sage.rings.number_field
        >>> G,_,_  = F.subfields(Integer(3))[Integer(0)]; (c,) = G._first_ngens(1)
        >>> E = E.base_extend(G).quadratic_twist(c); E
        Elliptic Curve defined
         by y^2 = x^3 + 5*a0*x^2 + (-200*a0^2)*x + (-42000*a0^2+42000*a0+126000)
         over Number Field in a0 with defining polynomial x^3 - 3*x^2 + 3*x + 9
        >>> K = E.division_field(Integer(3), simplify_all=True, names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial x^12 + 5*x^10 + 40*x^8 + 315*x^6 + 750*x^4 + 675*x^2 + 2025

    Some higher-degree examples:

    Sage

        sage: # needs sage.rings.number_field
        sage: E = EllipticCurve('11a1')
        sage: K.<b> = E.division_field(2); K
        Number Field in b with defining polynomial
         x^6 + 2*x^5 - 48*x^4 - 436*x^3 + 1668*x^2 + 28792*x + 73844
        sage: K.<b> = E.division_field(3); K        # long time
        Number Field in b with defining polynomial x^48 ...
        sage: K.<b> = E.division_field(5); K
        Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1
        sage: E.division_field(5, 'b', simplify=False)
        Number Field in b with defining polynomial x^4 + x^3 + 11*x^2 + 41*x + 101
        sage: E.base_extend(K).torsion_subgroup()   # long time
        Torsion Subgroup isomorphic to Z/5 + Z/5 associated to the Elliptic Curve
         defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20)
         over Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1

        sage: # needs sage.rings.number_field
        sage: E = EllipticCurve('27a1')
        sage: K.<b> = E.division_field(3); K
        Number Field in b with defining polynomial x^2 + 3*x + 9
        sage: K.<b> = E.division_field(2); K
        Number Field in b with defining polynomial
         x^6 + 6*x^5 + 24*x^4 - 52*x^3 - 228*x^2 + 744*x + 3844
        sage: K.<b> = E.division_field(2, simplify_all=True); K
        Number Field in b with defining polynomial x^6 - 3*x^5 + 5*x^3 - 3*x + 1
        sage: K.<b> = E.division_field(5); K        # long time
        Number Field in b with defining polynomial x^48 ...
        sage: K.<b> = E.division_field(7); K        # long time
        Number Field in b with defining polynomial x^72 ...

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.number_field
        >>> E = EllipticCurve('11a1')
        >>> K = E.division_field(Integer(2), names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial
         x^6 + 2*x^5 - 48*x^4 - 436*x^3 + 1668*x^2 + 28792*x + 73844
        >>> K = E.division_field(Integer(3), names=('b',)); (b,) = K._first_ngens(1); K        # long time
        Number Field in b with defining polynomial x^48 ...
        >>> K = E.division_field(Integer(5), names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1
        >>> E.division_field(Integer(5), 'b', simplify=False)
        Number Field in b with defining polynomial x^4 + x^3 + 11*x^2 + 41*x + 101
        >>> E.base_extend(K).torsion_subgroup()   # long time
        Torsion Subgroup isomorphic to Z/5 + Z/5 associated to the Elliptic Curve
         defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20)
         over Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1

        >>> # needs sage.rings.number_field
        >>> E = EllipticCurve('27a1')
        >>> K = E.division_field(Integer(3), names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial x^2 + 3*x + 9
        >>> K = E.division_field(Integer(2), names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial
         x^6 + 6*x^5 + 24*x^4 - 52*x^3 - 228*x^2 + 744*x + 3844
        >>> K = E.division_field(Integer(2), simplify_all=True, names=('b',)); (b,) = K._first_ngens(1); K
        Number Field in b with defining polynomial x^6 - 3*x^5 + 5*x^3 - 3*x + 1
        >>> K = E.division_field(Integer(5), names=('b',)); (b,) = K._first_ngens(1); K        # long time
        Number Field in b with defining polynomial x^48 ...
        >>> K = E.division_field(Integer(7), names=('b',)); (b,) = K._first_ngens(1); K        # long time
        Number Field in b with defining polynomial x^72 ...

    Over a number field:

    Sage

        sage: # needs sage.rings.number_field
        sage: R.<x> = PolynomialRing(QQ)
        sage: K.<i> = NumberField(x^2 + 1)
        sage: E = EllipticCurve([0,0,0,0,i])
        sage: L.<b> = E.division_field(2); L
        Number Field in b with defining polynomial x^4 - x^2 + 1
        sage: L.<b>, phi = E.division_field(2, map=True); phi
        Ring morphism:
          From: Number Field in i with defining polynomial x^2 + 1
          To:   Number Field in b with defining polynomial x^4 - x^2 + 1
          Defn: i |--> -b^3
        sage: L.<b>, phi = E.division_field(3, map=True)
        sage: L
        Number Field in b with defining polynomial x^24 - 6*x^22 - 12*x^21
         - 21*x^20 + 216*x^19 + 48*x^18 + 804*x^17 + 1194*x^16 - 13488*x^15
         + 21222*x^14 + 44196*x^13 - 47977*x^12 - 102888*x^11 + 173424*x^10
         - 172308*x^9 + 302046*x^8 + 252864*x^7 - 931182*x^6 + 180300*x^5
         + 879567*x^4 - 415896*x^3 + 1941012*x^2 + 650220*x + 443089
        sage: phi
        Ring morphism:
          From: Number Field in i with defining polynomial x^2 + 1
          To:   Number Field in b with defining polynomial x^24 ...
          Defn: i |--> -215621657062634529/183360797284413355040732*b^23 ...

    [Python]

        >>> from sage.all import *
        >>> # needs sage.rings.number_field
        >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
        >>> K = NumberField(x**Integer(2) + Integer(1), names=('i',)); (i,) = K._first_ngens(1)
        >>> E = EllipticCurve([Integer(0),Integer(0),Integer(0),Integer(0),i])
        >>> L = E.division_field(Integer(2), names=('b',)); (b,) = L._first_ngens(1); L
        Number Field in b with defining polynomial x^4 - x^2 + 1
        >>> L, phi  = E.division_field(Integer(2), map=True, names=('b',)); (b,) = L._first_ngens(1); phi
        Ring morphism:
          From: Number Field in i with defining polynomial x^2 + 1
          To:   Number Field in b with defining polynomial x^4 - x^2 + 1
          Defn: i |--> -b^3
        >>> L, phi  = E.division_field(Integer(3), map=True, names=('b',)); (b,) = L._first_ngens(1)
        >>> L
        Number Field in b with defining polynomial x^24 - 6*x^22 - 12*x^21
         - 21*x^20 + 216*x^19 + 48*x^18 + 804*x^17 + 1194*x^16 - 13488*x^15
         + 21222*x^14 + 44196*x^13 - 47977*x^12 - 102888*x^11 + 173424*x^10
         - 172308*x^9 + 302046*x^8 + 252864*x^7 - 931182*x^6 + 180300*x^5
         + 879567*x^4 - 415896*x^3 + 1941012*x^2 + 650220*x + 443089
        >>> phi
        Ring morphism:
          From: Number Field in i with defining polynomial x^2 + 1
          To:   Number Field in b with defining polynomial x^24 ...
          Defn: i |--> -215621657062634529/183360797284413355040732*b^23 ...

    Over a finite field:

    Sage

        sage: E = EllipticCurve(GF(431^2), [1,0])                                   # needs sage.rings.finite_rings
        sage: E.division_field(5, map=True)                                         # needs sage.rings.finite_rings
        (Finite Field in t of size 431^4,
         Ring morphism:
           From: Finite Field in z2 of size 431^2
           To:   Finite Field in t of size 431^4
           Defn: z2 |--> 52*t^3 + 222*t^2 + 78*t + 105)

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(431)**Integer(2)), [Integer(1),Integer(0)])                                   # needs sage.rings.finite_rings
        >>> E.division_field(Integer(5), map=True)                                         # needs sage.rings.finite_rings
        (Finite Field in t of size 431^4,
         Ring morphism:
           From: Finite Field in z2 of size 431^2
           To:   Finite Field in t of size 431^4
           Defn: z2 |--> 52*t^3 + 222*t^2 + 78*t + 105)

    Sage

        sage: E = EllipticCurve(GF(433^2), [1,0])                                   # needs sage.rings.finite_rings
        sage: K.<v> = E.division_field(7); K                                        # needs sage.rings.finite_rings
        Finite Field in v of size 433^16

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(433)**Integer(2)), [Integer(1),Integer(0)])                                   # needs sage.rings.finite_rings
        >>> K = E.division_field(Integer(7), names=('v',)); (v,) = K._first_ngens(1); K                                        # needs sage.rings.finite_rings
        Finite Field in v of size 433^16

    It also works for composite orders:

    Sage

        sage: E = EllipticCurve(GF(11), [5,5])
        sage: E.change_ring(E.division_field(8)).abelian_group().torsion_subgroup(8).invariants()
        (8, 8)
        sage: E.change_ring(E.division_field(9)).abelian_group().torsion_subgroup(9).invariants()
        (9, 9)
        sage: E.change_ring(E.division_field(10)).abelian_group().torsion_subgroup(10).invariants()
        (10, 10)
        sage: E.change_ring(E.division_field(36)).abelian_group().torsion_subgroup(36).invariants()
        (36, 36)
        sage: E.change_ring(E.division_field(11)).abelian_group().torsion_subgroup(11).invariants()
        (11,)
        sage: E.change_ring(E.division_field(66)).abelian_group().torsion_subgroup(66).invariants()
        (6, 66)

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(11)), [Integer(5),Integer(5)])
        >>> E.change_ring(E.division_field(Integer(8))).abelian_group().torsion_subgroup(Integer(8)).invariants()
        (8, 8)
        >>> E.change_ring(E.division_field(Integer(9))).abelian_group().torsion_subgroup(Integer(9)).invariants()
        (9, 9)
        >>> E.change_ring(E.division_field(Integer(10))).abelian_group().torsion_subgroup(Integer(10)).invariants()
        (10, 10)
        >>> E.change_ring(E.division_field(Integer(36))).abelian_group().torsion_subgroup(Integer(36)).invariants()
        (36, 36)
        >>> E.change_ring(E.division_field(Integer(11))).abelian_group().torsion_subgroup(Integer(11)).invariants()
        (11,)
        >>> E.change_ring(E.division_field(Integer(66))).abelian_group().torsion_subgroup(Integer(66)).invariants()
        (6, 66)

    …also over number fields:

    Sage

        sage: R.<x> = PolynomialRing(QQ)
        sage: K.<i> = NumberField(x^2 + 1)
        sage: E = EllipticCurve([0,0,0,0,i])
        sage: L,emb = E.division_field(6, names='b', map=True); L
        Number Field in b with defining polynomial x^24 + 12*x^23 + ...
        sage: E.change_ring(emb).torsion_subgroup().invariants()
        (6, 6)

    [Python]

        >>> from sage.all import *
        >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
        >>> K = NumberField(x**Integer(2) + Integer(1), names=('i',)); (i,) = K._first_ngens(1)
        >>> E = EllipticCurve([Integer(0),Integer(0),Integer(0),Integer(0),i])
        >>> L,emb = E.division_field(Integer(6), names='b', map=True); L
        Number Field in b with defining polynomial x^24 + 12*x^23 + ...
        >>> E.change_ring(emb).torsion_subgroup().invariants()
        (6, 6)

    See also

    To compute a basis of the \(n\)-torsion once the base field has been extended, you may use `sage.schemes.elliptic_curves.ell_number_field.EllipticCurve_number_field.torsion_subgroup()` or `sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field.torsion_basis()`.

    AUTHORS:

    - Jeroen Demeyer (2014-01-06): Issue #11905, use `splitting_field` method, moved from `gal_reps.py`, make it work over number fields.

    - Lorenz Panny (2022): extend to finite fields

    - Lorenz Panny (2023): extend to composite \(n\).

  endomorphism_ring_is_commutative()

    Check whether the endomorphism ring of this elliptic curve over its base field is commutative.

    ALGORITHM: The endomorphism ring is always commutative in characteristic zero. Over finite fields, it is commutative if and only if the Frobenius endomorphism is not in \(\ZZ\). All elliptic curves with non-commutative endomorphism ring are supersingular. (The converse holds over the algebraic closure, but here we consider endomorphisms over the field of definition.)

    EXAMPLES:

    Sage

        sage: EllipticCurve(QQ, [1,1]).endomorphism_ring_is_commutative()
        True
        sage: EllipticCurve(QQ, [1,0]).endomorphism_ring_is_commutative()
        True
        sage: EllipticCurve(GF(19), [1,1]).endomorphism_ring_is_commutative()
        True
        sage: EllipticCurve(GF(19^2), [1,1]).endomorphism_ring_is_commutative()
        True
        sage: EllipticCurve(GF(19), [1,0]).endomorphism_ring_is_commutative()
        True
        sage: EllipticCurve(GF(19^2), [1,0]).endomorphism_ring_is_commutative()
        False
        sage: EllipticCurve(GF(19^3), [1,0]).endomorphism_ring_is_commutative()
        True

    Python

        >>> from sage.all import *
        >>> EllipticCurve(QQ, [Integer(1),Integer(1)]).endomorphism_ring_is_commutative()
        True
        >>> EllipticCurve(QQ, [Integer(1),Integer(0)]).endomorphism_ring_is_commutative()
        True
        >>> EllipticCurve(GF(Integer(19)), [Integer(1),Integer(1)]).endomorphism_ring_is_commutative()
        True
        >>> EllipticCurve(GF(Integer(19)**Integer(2)), [Integer(1),Integer(1)]).endomorphism_ring_is_commutative()
        True
        >>> EllipticCurve(GF(Integer(19)), [Integer(1),Integer(0)]).endomorphism_ring_is_commutative()
        True
        >>> EllipticCurve(GF(Integer(19)**Integer(2)), [Integer(1),Integer(0)]).endomorphism_ring_is_commutative()
        False
        >>> EllipticCurve(GF(Integer(19)**Integer(3)), [Integer(1),Integer(0)]).endomorphism_ring_is_commutative()
        True

  genus()

    Return 1 for elliptic curves.

    EXAMPLES:

    Sage

        sage: E = EllipticCurve(GF(3), [0, -1, 0, -346, 2652])
        sage: E.genus()
        1

        sage: R = FractionField(QQ['z'])
        sage: E = EllipticCurve(R, [0, -1, 0, -346, 2652])
        sage: E.genus()
        1

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(3)), [Integer(0), -Integer(1), Integer(0), -Integer(346), Integer(2652)])
        >>> E.genus()
        1

        >>> R = FractionField(QQ['z'])
        >>> E = EllipticCurve(R, [Integer(0), -Integer(1), Integer(0), -Integer(346), Integer(2652)])
        >>> E.genus()
        1

  hasse_invariant()

    Return the Hasse invariant of this elliptic curve.

    OUTPUT:

    The Hasse invariant of this elliptic curve, as an element of the base field. This is only defined over fields of positive characteristic, and is an element of the field which is zero if and only if the curve is supersingular. Over a field of characteristic zero, where the Hasse invariant is undefined, a `ValueError` is raised.

    EXAMPLES:

    Sage

        sage: E = EllipticCurve([Mod(1,2), Mod(1,2), 0, 0, Mod(1,2)])
        sage: E.hasse_invariant()
        1
        sage: E = EllipticCurve([0, 0, Mod(1,3), Mod(1,3), Mod(1,3)])
        sage: E.hasse_invariant()
        0
        sage: E = EllipticCurve([0, 0, Mod(1,5), 0, Mod(2,5)])
        sage: E.hasse_invariant()
        0
        sage: E = EllipticCurve([0, 0, Mod(1,5), Mod(1,5), Mod(2,5)])
        sage: E.hasse_invariant()
        2

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve([Mod(Integer(1),Integer(2)), Mod(Integer(1),Integer(2)), Integer(0), Integer(0), Mod(Integer(1),Integer(2))])
        >>> E.hasse_invariant()
        1
        >>> E = EllipticCurve([Integer(0), Integer(0), Mod(Integer(1),Integer(3)), Mod(Integer(1),Integer(3)), Mod(Integer(1),Integer(3))])
        >>> E.hasse_invariant()
        0
        >>> E = EllipticCurve([Integer(0), Integer(0), Mod(Integer(1),Integer(5)), Integer(0), Mod(Integer(2),Integer(5))])
        >>> E.hasse_invariant()
        0
        >>> E = EllipticCurve([Integer(0), Integer(0), Mod(Integer(1),Integer(5)), Mod(Integer(1),Integer(5)), Mod(Integer(2),Integer(5))])
        >>> E.hasse_invariant()
        2

    Some examples over larger fields:

    Sage

        sage: # needs sage.rings.finite_rings
        sage: EllipticCurve(GF(101), [0,0,0,0,1]).hasse_invariant()
        0
        sage: EllipticCurve(GF(101), [0,0,0,1,1]).hasse_invariant()
        98
        sage: EllipticCurve(GF(103), [0,0,0,0,1]).hasse_invariant()
        20
        sage: EllipticCurve(GF(103), [0,0,0,1,1]).hasse_invariant()
        17
        sage: F.<a> = GF(107^2)
        sage: EllipticCurve(F, [0,0,0,a,1]).hasse_invariant()
        62*a + 75
        sage: EllipticCurve(F, [0,0,0,0,a]).hasse_invariant()
        0

    [Python]

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> EllipticCurve(GF(Integer(101)), [Integer(0),Integer(0),Integer(0),Integer(0),Integer(1)]).hasse_invariant()
        0
        >>> EllipticCurve(GF(Integer(101)), [Integer(0),Integer(0),Integer(0),Integer(1),Integer(1)]).hasse_invariant()
        98
        >>> EllipticCurve(GF(Integer(103)), [Integer(0),Integer(0),Integer(0),Integer(0),Integer(1)]).hasse_invariant()
        20
        >>> EllipticCurve(GF(Integer(103)), [Integer(0),Integer(0),Integer(0),Integer(1),Integer(1)]).hasse_invariant()
        17
        >>> F = GF(Integer(107)**Integer(2), names=('a',)); (a,) = F._first_ngens(1)
        >>> EllipticCurve(F, [Integer(0),Integer(0),Integer(0),a,Integer(1)]).hasse_invariant()
        62*a + 75
        >>> EllipticCurve(F, [Integer(0),Integer(0),Integer(0),Integer(0),a]).hasse_invariant()
        0

    Over fields of characteristic zero, the Hasse invariant is undefined:

    Sage

        sage: E = EllipticCurve([0,0,0,0,1])
        sage: E.hasse_invariant()
        Traceback (most recent call last):
        ...
        ValueError: Hasse invariant only defined in positive characteristic

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve([Integer(0),Integer(0),Integer(0),Integer(0),Integer(1)])
        >>> E.hasse_invariant()
        Traceback (most recent call last):
        ...
        ValueError: Hasse invariant only defined in positive characteristic

  is_isogenous(other, field=None)

    Return whether or not `self` is isogenous to `other`.

    INPUT:

    - `other` – another elliptic curve

    - `field` – (default: `None`) currently not implemented. A field containing the base fields of the two elliptic curves onto which the two curves may be extended to test if they are isogenous over this field. By default `is_isogenous` will not try to find this field unless one of the curves can be be extended into the base field of the `other`, in which case it will test over the larger base field.

    OUTPUT: boolean; `True` if there is an isogeny from curve `self` to curve `other` defined over `field`

    METHOD:

    Over general fields this is only implemented in trivial cases.

    EXAMPLES:

    Sage

        sage: E1 = EllipticCurve(CC, [1,18]); E1
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000
         over Complex Field with 53 bits of precision
        sage: E2 = EllipticCurve(CC, [2,7]); E2
        Elliptic Curve defined by y^2 = x^3 + 2.00000000000000*x + 7.00000000000000
         over Complex Field with 53 bits of precision
        sage: E1.is_isogenous(E2)
        Traceback (most recent call last):
        ...
        NotImplementedError: Only implemented for isomorphic curves over general fields.

        sage: E1 = EllipticCurve(Frac(PolynomialRing(ZZ,'t')), [2,19]); E1
        Elliptic Curve defined by y^2 = x^3 + 2*x + 19
         over Fraction Field of Univariate Polynomial Ring in t over Integer Ring
        sage: E2 = EllipticCurve(CC, [23,4]); E2
        Elliptic Curve defined by y^2 = x^3 + 23.0000000000000*x + 4.00000000000000
         over Complex Field with 53 bits of precision
        sage: E1.is_isogenous(E2)
        Traceback (most recent call last):
        ...
        NotImplementedError: Only implemented for isomorphic curves over general fields.

    Python

        >>> from sage.all import *
        >>> E1 = EllipticCurve(CC, [Integer(1),Integer(18)]); E1
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000
         over Complex Field with 53 bits of precision
        >>> E2 = EllipticCurve(CC, [Integer(2),Integer(7)]); E2
        Elliptic Curve defined by y^2 = x^3 + 2.00000000000000*x + 7.00000000000000
         over Complex Field with 53 bits of precision
        >>> E1.is_isogenous(E2)
        Traceback (most recent call last):
        ...
        NotImplementedError: Only implemented for isomorphic curves over general fields.

        >>> E1 = EllipticCurve(Frac(PolynomialRing(ZZ,'t')), [Integer(2),Integer(19)]); E1
        Elliptic Curve defined by y^2 = x^3 + 2*x + 19
         over Fraction Field of Univariate Polynomial Ring in t over Integer Ring
        >>> E2 = EllipticCurve(CC, [Integer(23),Integer(4)]); E2
        Elliptic Curve defined by y^2 = x^3 + 23.0000000000000*x + 4.00000000000000
         over Complex Field with 53 bits of precision
        >>> E1.is_isogenous(E2)
        Traceback (most recent call last):
        ...
        NotImplementedError: Only implemented for isomorphic curves over general fields.

  is_quadratic_twist(other)

    Determine whether this curve is a quadratic twist of another.

    INPUT:

    - `other` – an elliptic curve with the same base field as `self`

    OUTPUT:

    Either 0, if the curves are not quadratic twists, or \(D\) if `other` is `self.quadratic_twist(D)` (up to isomorphism). If `self` and `other` are isomorphic, returns 1.

    If the curves are defined over \(\QQ\), the output \(D\) is a squarefree integer.

    Note

    Not fully implemented in characteristic 2, or in characteristic 3 when both \(j\)-invariants are 0.

    EXAMPLES:

    Sage

        sage: E = EllipticCurve('11a1')
        sage: Et = E.quadratic_twist(-24)
        sage: E.is_quadratic_twist(Et)
        -6

        sage: E1 = EllipticCurve([0,0,1,0,0])
        sage: E1.j_invariant()
        0
        sage: E2 = EllipticCurve([0,0,0,0,2])
        sage: E1.is_quadratic_twist(E2)
        2
        sage: E1.is_quadratic_twist(E1)
        1
        sage: type(E1.is_quadratic_twist(E1)) == type(E1.is_quadratic_twist(E2))   # Issue #6574
        True

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve('11a1')
        >>> Et = E.quadratic_twist(-Integer(24))
        >>> E.is_quadratic_twist(Et)
        -6

        >>> E1 = EllipticCurve([Integer(0),Integer(0),Integer(1),Integer(0),Integer(0)])
        >>> E1.j_invariant()
        0
        >>> E2 = EllipticCurve([Integer(0),Integer(0),Integer(0),Integer(0),Integer(2)])
        >>> E1.is_quadratic_twist(E2)
        2
        >>> E1.is_quadratic_twist(E1)
        1
        >>> type(E1.is_quadratic_twist(E1)) == type(E1.is_quadratic_twist(E2))   # Issue #6574
        True

    Sage

        sage: E1 = EllipticCurve([0,0,0,1,0])
        sage: E1.j_invariant()
        1728
        sage: E2 = EllipticCurve([0,0,0,2,0])
        sage: E1.is_quadratic_twist(E2)
        0
        sage: E2 = EllipticCurve([0,0,0,25,0])
        sage: E1.is_quadratic_twist(E2)
        5

    [Python]

        >>> from sage.all import *
        >>> E1 = EllipticCurve([Integer(0),Integer(0),Integer(0),Integer(1),Integer(0)])
        >>> E1.j_invariant()
        1728
        >>> E2 = EllipticCurve([Integer(0),Integer(0),Integer(0),Integer(2),Integer(0)])
        >>> E1.is_quadratic_twist(E2)
        0
        >>> E2 = EllipticCurve([Integer(0),Integer(0),Integer(0),Integer(25),Integer(0)])
        >>> E1.is_quadratic_twist(E2)
        5

    Sage

        sage: # needs sage.rings.finite_rings
        sage: F = GF(101)
        sage: E1 = EllipticCurve(F, [4,7])
        sage: E2 = E1.quadratic_twist()
        sage: D = E1.is_quadratic_twist(E2); D != 0
        True
        sage: F = GF(101)
        sage: E1 = EllipticCurve(F, [4,7])
        sage: E2 = E1.quadratic_twist()
        sage: D = E1.is_quadratic_twist(E2)
        sage: E1.quadratic_twist(D).is_isomorphic(E2)
        True
        sage: E1.is_isomorphic(E2)
        False
        sage: F2 = GF(101^2,'a')
        sage: E1.change_ring(F2).is_isomorphic(E2.change_ring(F2))
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> F = GF(Integer(101))
        >>> E1 = EllipticCurve(F, [Integer(4),Integer(7)])
        >>> E2 = E1.quadratic_twist()
        >>> D = E1.is_quadratic_twist(E2); D != Integer(0)
        True
        >>> F = GF(Integer(101))
        >>> E1 = EllipticCurve(F, [Integer(4),Integer(7)])
        >>> E2 = E1.quadratic_twist()
        >>> D = E1.is_quadratic_twist(E2)
        >>> E1.quadratic_twist(D).is_isomorphic(E2)
        True
        >>> E1.is_isomorphic(E2)
        False
        >>> F2 = GF(Integer(101)**Integer(2),'a')
        >>> E1.change_ring(F2).is_isomorphic(E2.change_ring(F2))
        True

    A characteristic 3 example:

    Sage

        sage: # needs sage.rings.finite_rings
        sage: F = GF(3^5,'a')
        sage: E1 = EllipticCurve_from_j(F(1))
        sage: E2 = E1.quadratic_twist(-1)
        sage: D = E1.is_quadratic_twist(E2); D != 0
        True
        sage: E1.quadratic_twist(D).is_isomorphic(E2)
        True

    [Python]

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> F = GF(Integer(3)**Integer(5),'a')
        >>> E1 = EllipticCurve_from_j(F(Integer(1)))
        >>> E2 = E1.quadratic_twist(-Integer(1))
        >>> D = E1.is_quadratic_twist(E2); D != Integer(0)
        True
        >>> E1.quadratic_twist(D).is_isomorphic(E2)
        True

    Sage

        sage: # needs sage.rings.finite_rings
        sage: E1 = EllipticCurve_from_j(F(0))
        sage: E2 = E1.quadratic_twist()
        sage: D = E1.is_quadratic_twist(E2); D
        1
        sage: E1.is_isomorphic(E2)
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> E1 = EllipticCurve_from_j(F(Integer(0)))
        >>> E2 = E1.quadratic_twist()
        >>> D = E1.is_quadratic_twist(E2); D
        1
        >>> E1.is_isomorphic(E2)
        True

  is_quartic_twist(other)

    Determine whether this curve is a quartic twist of another.

    INPUT:

    - `other` – an elliptic curves with the same base field as `self`

    OUTPUT:

    Either 0, if the curves are not quartic twists, or \(D\) if `other` is `self.quartic_twist(D)` (up to isomorphism). If `self` and `other` are isomorphic, returns 1.

    Note

    Not fully implemented in characteristics 2 or 3.

    EXAMPLES:

    Sage

        sage: E = EllipticCurve_from_j(GF(13)(1728))
        sage: E1 = E.quartic_twist(2)
        sage: D = E.is_quartic_twist(E1); D!=0
        True
        sage: E.quartic_twist(D).is_isomorphic(E1)
        True

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve_from_j(GF(Integer(13))(Integer(1728)))
        >>> E1 = E.quartic_twist(Integer(2))
        >>> D = E.is_quartic_twist(E1); D!=Integer(0)
        True
        >>> E.quartic_twist(D).is_isomorphic(E1)
        True

    Sage

        sage: E = EllipticCurve_from_j(1728)
        sage: E1 = E.quartic_twist(12345)
        sage: D = E.is_quartic_twist(E1); D
        15999120
        sage: (D/12345).is_perfect_power(4)
        True

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve_from_j(Integer(1728))
        >>> E1 = E.quartic_twist(Integer(12345))
        >>> D = E.is_quartic_twist(E1); D
        15999120
        >>> (D/Integer(12345)).is_perfect_power(Integer(4))
        True

  is_sextic_twist(other)

    Determine whether this curve is a sextic twist of another.

    INPUT:

    - `other` – an elliptic curves with the same base field as `self`

    OUTPUT:

    Either 0, if the curves are not sextic twists, or \(D\) if `other` is `self.sextic_twist(D)` (up to isomorphism). If `self` and `other` are isomorphic, returns 1.

    Note

    Not fully implemented in characteristics 2 or 3.

    EXAMPLES:

    Sage

        sage: E = EllipticCurve_from_j(GF(13)(0))
        sage: E1 = E.sextic_twist(2)
        sage: D = E.is_sextic_twist(E1); D != 0
        True
        sage: E.sextic_twist(D).is_isomorphic(E1)
        True

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve_from_j(GF(Integer(13))(Integer(0)))
        >>> E1 = E.sextic_twist(Integer(2))
        >>> D = E.is_sextic_twist(E1); D != Integer(0)
        True
        >>> E.sextic_twist(D).is_isomorphic(E1)
        True

    Sage

        sage: E = EllipticCurve_from_j(0)
        sage: E1 = E.sextic_twist(12345)
        sage: D = E.is_sextic_twist(E1); D
        575968320
        sage: (D/12345).is_perfect_power(6)
        True

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve_from_j(Integer(0))
        >>> E1 = E.sextic_twist(Integer(12345))
        >>> D = E.is_sextic_twist(E1); D
        575968320
        >>> (D/Integer(12345)).is_perfect_power(Integer(6))
        True

  isogenies_degree(n, _intermediate)

    Return an iterator of all separable isogenies of given degree (up to post-composition with isomorphisms) with domain equal to `self`, which are defined over the base field of `self`.

    ALGORITHM:

    The prime factors \(p\) of \(n\) are processed one by one in decreasing order, each time “branching” out by taking isogenies of degree \(p\).

    INPUT:

    - `n` – integer, or its `Factorization`.

    - `_intermediate` – (bool, default: False): If set, the isogenies from this curve to the curves traversed within the depth-first search are returned. This is for internal use only.

    EXAMPLES:

    Sage

        sage: E = EllipticCurve(GF(11), [1, 1])
        sage: list(E.isogenies_degree(23 * 19))
        [Composite morphism of degree 437 = 23*19:
           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 + 8*x + 7 over Finite Field of size 11,
         Composite morphism of degree 437 = 23*19:
           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 + 6*x + 2 over Finite Field of size 11,
         Composite morphism of degree 437 = 23*19:
           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 + 2*x + 6 over Finite Field of size 11,
         Composite morphism of degree 437 = 23*19:
           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]

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(11)), [Integer(1), Integer(1)])
        >>> list(E.isogenies_degree(Integer(23) * Integer(19)))
        [Composite morphism of degree 437 = 23*19:
           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 + 8*x + 7 over Finite Field of size 11,
         Composite morphism of degree 437 = 23*19:
           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 + 6*x + 2 over Finite Field of size 11,
         Composite morphism of degree 437 = 23*19:
           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 + 2*x + 6 over Finite Field of size 11,
         Composite morphism of degree 437 = 23*19:
           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

        sage: E = EllipticCurve(GF(next_prime(2^32)), j=1728)
        sage: sorted([phi.codomain().j_invariant() for phi in E.isogenies_degree(11 * 17 * 19^2)])  # long time (:issue:`39569`)
        [1348157279, 1348157279, 1713365879, 1713365879, 3153894341, 3153894341,
         3225140514, 3225140514, 3673460198, 3673460198, 3994312564, 3994312564]
        sage: it = E.isogenies_degree(2^2); it
        <generator object EllipticCurve_field.isogenies_degree at 0x...>
        sage: all(phi.degree() == 2^2 for phi in it)
        True

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(next_prime(Integer(2)**Integer(32))), j=Integer(1728))
        >>> sorted([phi.codomain().j_invariant() for phi in E.isogenies_degree(Integer(11) * Integer(17) * Integer(19)**Integer(2))])  # long time (:issue:`39569`)
        [1348157279, 1348157279, 1713365879, 1713365879, 3153894341, 3153894341,
         3225140514, 3225140514, 3673460198, 3673460198, 3994312564, 3994312564]
        >>> it = E.isogenies_degree(Integer(2)**Integer(2)); it
        <generator object EllipticCurve_field.isogenies_degree at 0x...>
        >>> all(phi.degree() == Integer(2)**Integer(2) for phi in it)
        True

    We verify that the isogenies outputted are distinct. Note that we do not use a `set` or any hash-based data structure, as hashing isogenies is slow:

    Sage

        sage: import itertools
        sage: all_distinct = lambda arr: all(x != y for x, y in itertools.combinations(arr, 2))
        sage: K.<z> = GF((19, 2))
        sage: E = EllipticCurve(K, [11*z+5, 14*z+3])
        sage: S = list(E.isogenies_degree(5^2)); len(S), all_distinct(S)
        (3, True)
        sage: S = list(E.isogenies_degree(5^2*11)); len(S), all_distinct(S)
        (6, True)
        sage: S = list(E.isogenies_degree(5^2*11^4)); len(S), all_distinct(S)       # long time (2s)
        (15, True)

    Python

        >>> from sage.all import *
        >>> import itertools
        >>> all_distinct = lambda arr: all(x != y for x, y in itertools.combinations(arr, Integer(2)))
        >>> K = GF((Integer(19), Integer(2)), names=('z',)); (z,) = K._first_ngens(1)
        >>> E = EllipticCurve(K, [Integer(11)*z+Integer(5), Integer(14)*z+Integer(3)])
        >>> S = list(E.isogenies_degree(Integer(5)**Integer(2))); len(S), all_distinct(S)
        (3, True)
        >>> S = list(E.isogenies_degree(Integer(5)**Integer(2)*Integer(11))); len(S), all_distinct(S)
        (6, True)
        >>> S = list(E.isogenies_degree(Integer(5)**Integer(2)*Integer(11)**Integer(4))); len(S), all_distinct(S)       # long time (2s)
        (15, True)

    For curves over number fields, the number of distinct isogenies will usually be small:

    Sage

        sage: E = EllipticCurve(QQ, [0, 1, 0, -2, 0])
        sage: len(list(E.isogenies_degree(2**1)))
        3
        sage: len(list(E.isogenies_degree(2**5)))
        3
        sage: len(list(E.isogenies_degree(2**8)))                                   # long time (8s)
        1

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve(QQ, [Integer(0), Integer(1), Integer(0), -Integer(2), Integer(0)])
        >>> len(list(E.isogenies_degree(Integer(2)**Integer(1))))
        3
        >>> len(list(E.isogenies_degree(Integer(2)**Integer(5))))
        3
        >>> len(list(E.isogenies_degree(Integer(2)**Integer(8))))                                   # long time (8s)
        1

    Sage

        sage: pol = PolynomialRing(QQ, 'x')([529, 782, 1])
        sage: L.<a> = NumberField(pol)
        sage: E = EllipticCurve(j=-7072/1127*a + 2016)
        sage: len(list(E.isogenies_degree(2)))
        3
        sage: len(list(E.isogenies_degree(2**5)))
        3

    Python

        >>> from sage.all import *
        >>> pol = PolynomialRing(QQ, 'x')([Integer(529), Integer(782), Integer(1)])
        >>> L = NumberField(pol, names=('a',)); (a,) = L._first_ngens(1)
        >>> E = EllipticCurve(j=-Integer(7072)/Integer(1127)*a + Integer(2016))
        >>> len(list(E.isogenies_degree(Integer(2))))
        3
        >>> len(list(E.isogenies_degree(Integer(2)**Integer(5))))
        3

    Sage

        sage: pol = PolynomialRing(QQ, 'x')([1, -3, 5, -5, 5, -3, 1])
        sage: L.<a> = NumberField(pol)
        sage: js = hilbert_class_polynomial(-23).roots(L, multiplicities=False)
        sage: E = EllipticCurve(j=choice(js))
        sage: len(list(E.isogenies_degree(2^3)))                                    # long time (9s)
        10

    [Python]

        >>> from sage.all import *
        >>> pol = PolynomialRing(QQ, 'x')([Integer(1), -Integer(3), Integer(5), -Integer(5), Integer(5), -Integer(3), Integer(1)])
        >>> L = NumberField(pol, names=('a',)); (a,) = L._first_ngens(1)
        >>> js = hilbert_class_polynomial(-Integer(23)).roots(L, multiplicities=False)
        >>> E = EllipticCurve(j=choice(js))
        >>> len(list(E.isogenies_degree(Integer(2)**Integer(3))))                                    # long time (9s)
        10

  isogenies_prime_degree(l=None, max_l=31)

    Return a list of all separable isogenies (up to post-composition with isomorphisms) of given prime degree(s) with domain equal to `self`, which are defined over the base field of `self`.

    INPUT:

    - `l` – a prime or a list of primes

    - `max_l` – (default: 31) a bound on the primes to be tested. This is only used if `l` is `None`.

    OUTPUT:

    (list) All separable \(l\)-isogenies for the given \(l\) with domain `self`.

    ALGORITHM:

    Calls the generic function `isogenies_prime_degree()`. This is generic code, valid for all fields. It requires that certain operations have been implemented over the base field, such as root-finding for univariate polynomials.

    EXAMPLES:

    Examples over finite fields:

    Sage

        sage: # needs sage.libs.pari
        sage: E = EllipticCurve(GF(next_prime(1000000)), [7,8])
        sage: E.isogenies_prime_degree(2)
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003]
        sage: E.isogenies_prime_degree(3)
        []
        sage: E.isogenies_prime_degree(5)
        []
        sage: E.isogenies_prime_degree(7)
        []
        sage: E.isogenies_prime_degree(11)
        []
        sage: E.isogenies_prime_degree(13)
        [Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003]
        sage: E.isogenies_prime_degree(max_l=13)
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003]
        sage: E.isogenies_prime_degree()  # Default limit of 31
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003,
         Isogeny of degree 17
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 347438*x + 594729 over Finite Field of size 1000003,
         Isogeny of degree 17
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 674846*x + 7392 over Finite Field of size 1000003,
         Isogeny of degree 23
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 390065*x + 605596 over Finite Field of size 1000003]

        sage: E = EllipticCurve(GF(17), [2,0])
        sage: E.isogenies_prime_degree(3)
        []
        sage: E.isogenies_prime_degree(2)
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
          to Elliptic Curve defined by y^2 = x^3 + 9*x over Finite Field of size 17,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
          to Elliptic Curve defined by y^2 = x^3 + 5*x + 9 over Finite Field of size 17,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
          to Elliptic Curve defined by y^2 = x^3 + 5*x + 8 over Finite Field of size 17]

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.pari
        >>> E = EllipticCurve(GF(next_prime(Integer(1000000))), [Integer(7),Integer(8)])
        >>> E.isogenies_prime_degree(Integer(2))
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003]
        >>> E.isogenies_prime_degree(Integer(3))
        []
        >>> E.isogenies_prime_degree(Integer(5))
        []
        >>> E.isogenies_prime_degree(Integer(7))
        []
        >>> E.isogenies_prime_degree(Integer(11))
        []
        >>> E.isogenies_prime_degree(Integer(13))
        [Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003]
        >>> E.isogenies_prime_degree(max_l=Integer(13))
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003]
        >>> E.isogenies_prime_degree()  # Default limit of 31
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
         Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003,
         Isogeny of degree 17
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 347438*x + 594729 over Finite Field of size 1000003,
         Isogeny of degree 17
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 674846*x + 7392 over Finite Field of size 1000003,
         Isogeny of degree 23
          from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
            to Elliptic Curve defined by y^2 = x^3 + 390065*x + 605596 over Finite Field of size 1000003]

        >>> E = EllipticCurve(GF(Integer(17)), [Integer(2),Integer(0)])
        >>> E.isogenies_prime_degree(Integer(3))
        []
        >>> E.isogenies_prime_degree(Integer(2))
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
          to Elliptic Curve defined by y^2 = x^3 + 9*x over Finite Field of size 17,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
          to Elliptic Curve defined by y^2 = x^3 + 5*x + 9 over Finite Field of size 17,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
          to Elliptic Curve defined by y^2 = x^3 + 5*x + 8 over Finite Field of size 17]

    The base field matters, over a field extension we find more isogenies:

    Sage

        sage: E = EllipticCurve(GF(13), [2,8])
        sage: E.isogenies_prime_degree(max_l=3)
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
            to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field of size 13,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
            to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field of size 13]

        sage: # needs sage.rings.finite_rings
        sage: E = EllipticCurve(GF(13^6), [2,8])
        sage: E.isogenies_prime_degree(max_l=3)
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field in z6 of size 13^6,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (2*z6^5+6*z6^4+9*z6^3+8*z6+7)*x + (3*z6^5+9*z6^4+7*z6^3+12*z6+7) over Finite Field in z6 of size 13^6,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (11*z6^5+7*z6^4+4*z6^3+5*z6+9)*x + (10*z6^5+4*z6^4+6*z6^3+z6+10) over Finite Field in z6 of size 13^6,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field in z6 of size 13^6,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (3*z6^5+5*z6^4+8*z6^3+11*z6^2+5*z6+12)*x + (12*z6^5+6*z6^4+8*z6^3+4*z6^2+7*z6+6) over Finite Field in z6 of size 13^6,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (7*z6^4+12*z6^3+7*z6^2+4)*x + (6*z6^5+10*z6^3+12*z6^2+10*z6+8) over Finite Field in z6 of size 13^6,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (10*z6^5+z6^4+6*z6^3+8*z6^2+8*z6)*x + (8*z6^5+7*z6^4+8*z6^3+10*z6^2+9*z6+7) over Finite Field in z6 of size 13^6]

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(13)), [Integer(2),Integer(8)])
        >>> E.isogenies_prime_degree(max_l=Integer(3))
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
            to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field of size 13,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
            to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field of size 13]

        >>> # needs sage.rings.finite_rings
        >>> E = EllipticCurve(GF(Integer(13)**Integer(6)), [Integer(2),Integer(8)])
        >>> E.isogenies_prime_degree(max_l=Integer(3))
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field in z6 of size 13^6,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (2*z6^5+6*z6^4+9*z6^3+8*z6+7)*x + (3*z6^5+9*z6^4+7*z6^3+12*z6+7) over Finite Field in z6 of size 13^6,
         Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (11*z6^5+7*z6^4+4*z6^3+5*z6+9)*x + (10*z6^5+4*z6^4+6*z6^3+z6+10) over Finite Field in z6 of size 13^6,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field in z6 of size 13^6,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (3*z6^5+5*z6^4+8*z6^3+11*z6^2+5*z6+12)*x + (12*z6^5+6*z6^4+8*z6^3+4*z6^2+7*z6+6) over Finite Field in z6 of size 13^6,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (7*z6^4+12*z6^3+7*z6^2+4)*x + (6*z6^5+10*z6^3+12*z6^2+10*z6+8) over Finite Field in z6 of size 13^6,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
            to Elliptic Curve defined by y^2 = x^3 + (10*z6^5+z6^4+6*z6^3+8*z6^2+8*z6)*x + (8*z6^5+7*z6^4+8*z6^3+10*z6^2+9*z6+7) over Finite Field in z6 of size 13^6]

    If the degree equals the characteristic, we find only separable isogenies:

    Sage

        sage: E = EllipticCurve(GF(13), [2,8])
        sage: E.isogenies_prime_degree(13)
        [Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
            to Elliptic Curve defined by y^2 = x^3 + 6*x + 5 over Finite Field of size 13]
        sage: E = EllipticCurve(GF(5), [1,1])
        sage: E.isogenies_prime_degree(5)
        [Isogeny of degree 5
          from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
            to Elliptic Curve defined by y^2 = x^3 + x + 4 over Finite Field of size 5]

        sage: # needs sage.rings.finite_rings
        sage: k.<a> = GF(3^4)
        sage: E = EllipticCurve(k, [0,1,0,0,a])
        sage: E.isogenies_prime_degree(3)
        [Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + x^2 + a
               over Finite Field in a of size 3^4
            to Elliptic Curve defined by y^2 = x^3 + x^2 + (2*a^3+a^2+2)*x + (a^2+2)
               over Finite Field in a of size 3^4]

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(13)), [Integer(2),Integer(8)])
        >>> E.isogenies_prime_degree(Integer(13))
        [Isogeny of degree 13
          from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
            to Elliptic Curve defined by y^2 = x^3 + 6*x + 5 over Finite Field of size 13]
        >>> E = EllipticCurve(GF(Integer(5)), [Integer(1),Integer(1)])
        >>> E.isogenies_prime_degree(Integer(5))
        [Isogeny of degree 5
          from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
            to Elliptic Curve defined by y^2 = x^3 + x + 4 over Finite Field of size 5]

        >>> # needs sage.rings.finite_rings
        >>> k = GF(Integer(3)**Integer(4), names=('a',)); (a,) = k._first_ngens(1)
        >>> E = EllipticCurve(k, [Integer(0),Integer(1),Integer(0),Integer(0),a])
        >>> E.isogenies_prime_degree(Integer(3))
        [Isogeny of degree 3
          from Elliptic Curve defined by y^2 = x^3 + x^2 + a
               over Finite Field in a of size 3^4
            to Elliptic Curve defined by y^2 = x^3 + x^2 + (2*a^3+a^2+2)*x + (a^2+2)
               over Finite Field in a of size 3^4]

    In the supersingular case, there are no separable isogenies of degree equal to the characteristic:

    Sage

        sage: E = EllipticCurve(GF(5), [0,1])
        sage: E.isogenies_prime_degree(5)
        []

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(5)), [Integer(0),Integer(1)])
        >>> E.isogenies_prime_degree(Integer(5))
        []

    An example over a rational function field:

    Sage

        sage: R.<t> = GF(5)[]
        sage: K = R.fraction_field()
        sage: E = EllipticCurve(K, [1, t^5])
        sage: E.isogenies_prime_degree(5)
        [Isogeny of degree 5
          from Elliptic Curve defined by y^2 = x^3 + x + t^5 over Fraction Field
               of Univariate Polynomial Ring in t over Finite Field of size 5
            to Elliptic Curve defined by y^2 = x^3 + x + 4*t over Fraction Field
               of Univariate Polynomial Ring in t over Finite Field of size 5]

    Python

        >>> from sage.all import *
        >>> R = GF(Integer(5))['t']; (t,) = R._first_ngens(1)
        >>> K = R.fraction_field()
        >>> E = EllipticCurve(K, [Integer(1), t**Integer(5)])
        >>> E.isogenies_prime_degree(Integer(5))
        [Isogeny of degree 5
          from Elliptic Curve defined by y^2 = x^3 + x + t^5 over Fraction Field
               of Univariate Polynomial Ring in t over Finite Field of size 5
            to Elliptic Curve defined by y^2 = x^3 + x + 4*t over Fraction Field
               of Univariate Polynomial Ring in t over Finite Field of size 5]

    Examples over number fields (other than QQ):

    Sage

        sage: # needs sage.rings.number_field
        sage: x = polygen(ZZ, 'x')
        sage: QQroot2.<e> = NumberField(x^2 - 2)
        sage: E = EllipticCurve(QQroot2, j=8000)
        sage: E.isogenies_prime_degree()
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 = x^3 + (-36750)*x + 2401000
               over Number Field in e with defining polynomial x^2 - 2,
        Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 = x^3 + (220500*e-257250)*x + (54022500*e-88837000)
               over Number Field in e with defining polynomial x^2 - 2,
        Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 = x^3 + (-220500*e-257250)*x + (-54022500*e-88837000)
               over Number Field in e with defining polynomial x^2 - 2]
        sage: E = EllipticCurve(QQroot2, [1,0,1,4, -6]); E
        Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
         over Number Field in e with defining polynomial x^2 - 2
        sage: E.isogenies_prime_degree(2)
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-36)*x + (-70)
               over Number Field in e with defining polynomial x^2 - 2]
        sage: E.isogenies_prime_degree(3)
        [Isogeny of degree 3
          from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-1)*x
               over Number Field in e with defining polynomial x^2 - 2,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-171)*x + (-874)
               over Number Field in e with defining polynomial x^2 - 2]

    [Python]

        >>> from sage.all import *
        >>> # needs sage.rings.number_field
        >>> x = polygen(ZZ, 'x')
        >>> QQroot2 = NumberField(x**Integer(2) - Integer(2), names=('e',)); (e,) = QQroot2._first_ngens(1)
        >>> E = EllipticCurve(QQroot2, j=Integer(8000))
        >>> E.isogenies_prime_degree()
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 = x^3 + (-36750)*x + 2401000
               over Number Field in e with defining polynomial x^2 - 2,
        Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 = x^3 + (220500*e-257250)*x + (54022500*e-88837000)
               over Number Field in e with defining polynomial x^2 - 2,
        Isogeny of degree 2
          from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 = x^3 + (-220500*e-257250)*x + (-54022500*e-88837000)
               over Number Field in e with defining polynomial x^2 - 2]
        >>> E = EllipticCurve(QQroot2, [Integer(1),Integer(0),Integer(1),Integer(4), -Integer(6)]); E
        Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
         over Number Field in e with defining polynomial x^2 - 2
        >>> E.isogenies_prime_degree(Integer(2))
        [Isogeny of degree 2
          from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-36)*x + (-70)
               over Number Field in e with defining polynomial x^2 - 2]
        >>> E.isogenies_prime_degree(Integer(3))
        [Isogeny of degree 3
          from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-1)*x
               over Number Field in e with defining polynomial x^2 - 2,
         Isogeny of degree 3
          from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
               over Number Field in e with defining polynomial x^2 - 2
            to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-171)*x + (-874)
               over Number Field in e with defining polynomial x^2 - 2]

    These are not implemented yet:

    Sage

        sage: E = EllipticCurve(QQbar, [1,18]); E                                   # needs sage.rings.number_field
        Elliptic Curve defined by y^2 = x^3 + x + 18 over Algebraic Field
        sage: E.isogenies_prime_degree()                                            # needs sage.rings.number_field
        Traceback (most recent call last):
        ...
        NotImplementedError: This code could be implemented for QQbar, but has not been yet.

        sage: E = EllipticCurve(CC, [1,18]); E
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000
        over Complex Field with 53 bits of precision
        sage: E.isogenies_prime_degree(11)
        Traceback (most recent call last):
        ...
        NotImplementedError: This code could be implemented for general complex fields,
        but has not been yet.

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(QQbar, [Integer(1),Integer(18)]); E                                   # needs sage.rings.number_field
        Elliptic Curve defined by y^2 = x^3 + x + 18 over Algebraic Field
        >>> E.isogenies_prime_degree()                                            # needs sage.rings.number_field
        Traceback (most recent call last):
        ...
        NotImplementedError: This code could be implemented for QQbar, but has not been yet.

        >>> E = EllipticCurve(CC, [Integer(1),Integer(18)]); E
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000
        over Complex Field with 53 bits of precision
        >>> E.isogenies_prime_degree(Integer(11))
        Traceback (most recent call last):
        ...
        NotImplementedError: This code could be implemented for general complex fields,
        but has not been yet.

  isogeny(kernel, codomain=None, degree=None, model=None, check=True, algorithm=None, velu_sqrt_bound=None)

    Return an elliptic-curve isogeny from this elliptic curve.

    The isogeny can be specified in two ways, by passing either a polynomial or a set of torsion points. The methods used are:

    - Factored Isogenies (see `hom_composite`): Given a point, or a list of points which generate a composite-order subgroup, decomposes the isogeny into prime-degree steps. This can be used to construct isogenies of extremely large, smooth degree. When applicable, this algorithm is selected as default (see below). After factoring the degree single isogenies are computed using the other methods. This algorithm is selected using `algorithm="factored"`.

    - Vélu’s Formulas: Vélu’s original formulas for computing isogenies. This algorithm is selected by giving as the `kernel` parameter a single point generating a finite subgroup.

    - Kohel’s Formulas: Kohel’s original formulas for computing isogenies. This algorithm is selected by giving as the `kernel` parameter a monic polynomial (or a coefficient list in little endian) which will define the kernel of the isogeny. Kohel’s algorithm is currently only implemented for cyclic isogenies, with the exception of \([2]\).

    - √élu Algorithm (see `hom_velusqrt`): A variant of Vélu’s formulas with essentially square-root instead of linear complexity (in the degree). Currently only available over finite fields. The input must be a single kernel point of odd order \(\geq 5\). This algorithm is selected using `algorithm="velusqrt"`.

    INPUT:

    - `kernel` – a kernel; either a point on this curve, a list of points on this curve, a monic kernel polynomial, or `None`. If initializing from a codomain, this must be `None`.

    - `codomain` – an elliptic curve (default: `None`).

      - If `kernel` is `None`, then `degree` must be given as well and the given `codomain` must be the codomain of a cyclic, separable, normalized isogeny of the given degree.

      - If `kernel` is not `None`, then this must be isomorphic to the codomain of the separable isogeny defined by `kernel`; in this case, the isogeny is post-composed with an isomorphism so that the codomain equals the given curve.

    - `degree` – integer (default: `None`).

      - If `kernel` is `None`, then this is the degree of the isogeny from this curve to `codomain`.

      - If `kernel` is not `None`, then this is used to determine whether or not to skip a \(\gcd\) of the given kernel polynomial with the two-torsion polynomial of this curve.

    - `model` – string (default: `None`); supported values (cf. `compute_model()`):

      - `'minimal'`: if `self` is a curve over the rationals or over a number field, then the codomain is a global minimal model where this exists.

      - `'short_weierstrass'`: the codomain is a short Weierstrass curve, assuming one exists.

      - `'montgomery'`: the codomain is an (untwisted) Montgomery curve, assuming one exists over this field.

    - `check` – boolean (default: `True`); check whether the input is valid. Setting this to `False` can lead to significant speedups.

    - `algorithm` – string (optional); the possible choices are:

      - `'velusqrt'`: Use `EllipticCurveHom_velusqrt`.

      - `'factored'`: Use `EllipticCurveHom_composite` to decompose the isogeny into prime-degree steps.

      - `'traditional'`: Use `EllipticCurveIsogeny`.

      When `algorithm` is not specified, and `kernel` is not `None`, an algorithm is selected using the following criteria:

      > - if `kernel` is a list of multiple points, `'factored'` is selected.

      > - If `kernel` is a single point, or a list containing a single point:

      >   - if the order of the point is unknown, `'traditional'` is selected.

      >   - If the order is known and composite, `'factored'` is selected.

      >   - If the order is known and prime, a choice between `'velusqrt'` and `'traditional'` is done according to the `velu_sqrt_bound` parameter (see below).

      If none of the previous apply, `'traditional'` is selected.

    - `velu_sqrt_bound` – integer (default: `None`); establish the highest (prime) degree for which the `'traditional'` algorithm should be selected instead of `'velusqrt'`. If `None`, the default value from `_VeluBoundObj` is used. This value is initially set to 1000, but can be modified by the user. If an integer is supplied and the isogeny computation goes through the `'factored'` algorithm, the same integer is supplied to each factor.

    The `degree` parameter is not supported when an `algorithm` is specified.

    OUTPUT:

    An isogeny between elliptic curves. This is a morphism of curves. (In all cases, the returned object will be an instance of `EllipticCurveHom`.)

    EXAMPLES:

    Sage

        sage: # needs sage.rings.finite_rings
        sage: F = GF(2^5, 'alpha'); alpha = F.gen()
        sage: E = EllipticCurve(F, [1,0,1,1,1])
        sage: R.<x> = F[]
        sage: phi = E.isogeny(x + 1)
        sage: phi.rational_maps()
        ((x^2 + x + 1)/(x + 1), (x^2*y + x)/(x^2 + 1))

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> F = GF(Integer(2)**Integer(5), 'alpha'); alpha = F.gen()
        >>> E = EllipticCurve(F, [Integer(1),Integer(0),Integer(1),Integer(1),Integer(1)])
        >>> R = F['x']; (x,) = R._first_ngens(1)
        >>> phi = E.isogeny(x + Integer(1))
        >>> phi.rational_maps()
        ((x^2 + x + 1)/(x + 1), (x^2*y + x)/(x^2 + 1))

    Sage

        sage: E = EllipticCurve('11a1')
        sage: P = E.torsion_points()[1]
        sage: E.isogeny(P)
        Isogeny of degree 5
         from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20
              over Rational Field
           to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580
              over Rational Field

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve('11a1')
        >>> P = E.torsion_points()[Integer(1)]
        >>> E.isogeny(P)
        Isogeny of degree 5
         from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20
              over Rational Field
           to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580
              over Rational Field

    Sage

        sage: E = EllipticCurve(GF(19),[1,1])
        sage: P = E(15,3); Q = E(2,12)
        sage: (P.order(), Q.order())
        (7, 3)
        sage: phi = E.isogeny([P,Q]); phi
        Composite morphism of degree 21 = 7*3:
          From: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
          To:   Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
        sage: phi(E.random_point())  # all points defined over GF(19) are in the kernel
        (0 : 1 : 0)

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(19)),[Integer(1),Integer(1)])
        >>> P = E(Integer(15),Integer(3)); Q = E(Integer(2),Integer(12))
        >>> (P.order(), Q.order())
        (7, 3)
        >>> phi = E.isogeny([P,Q]); phi
        Composite morphism of degree 21 = 7*3:
          From: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
          To:   Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
        >>> phi(E.random_point())  # all points defined over GF(19) are in the kernel
        (0 : 1 : 0)

    Sage

        sage: E = EllipticCurve(GF(2^32 - 5), [170246996, 2036646110])              # needs sage.rings.finite_rings
        sage: P = E.lift_x(2)                                                       # needs sage.rings.finite_rings
        sage: E.isogeny(P, algorithm='factored')                                    # needs sage.rings.finite_rings
        Composite morphism of degree 1073721825 = 3^4*5^2*11*19*43*59:
          From: Elliptic Curve defined by y^2 = x^3 + 170246996*x + 2036646110
                 over Finite Field of size 4294967291
          To:   Elliptic Curve defined by y^2 = x^3 + 272790262*x + 1903695400
                 over Finite Field of size 4294967291

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(2)**Integer(32) - Integer(5)), [Integer(170246996), Integer(2036646110)])              # needs sage.rings.finite_rings
        >>> P = E.lift_x(Integer(2))                                                       # needs sage.rings.finite_rings
        >>> E.isogeny(P, algorithm='factored')                                    # needs sage.rings.finite_rings
        Composite morphism of degree 1073721825 = 3^4*5^2*11*19*43*59:
          From: Elliptic Curve defined by y^2 = x^3 + 170246996*x + 2036646110
                 over Finite Field of size 4294967291
          To:   Elliptic Curve defined by y^2 = x^3 + 272790262*x + 1903695400
                 over Finite Field of size 4294967291

    Not all polynomials define a finite subgroup (Issue #6384):

    Sage

        sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
        sage: phi = E.isogeny([14,27,4,1])
        Traceback (most recent call last):
        ...
        ValueError: the polynomial x^3 + 4*x^2 + 27*x + 14 does not define a finite
        subgroup of Elliptic Curve defined by y^2 + x*y = x^3 + x + 2
        over Finite Field of size 31

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(31)), [Integer(1),Integer(0),Integer(0),Integer(1),Integer(2)])
        >>> phi = E.isogeny([Integer(14),Integer(27),Integer(4),Integer(1)])
        Traceback (most recent call last):
        ...
        ValueError: the polynomial x^3 + 4*x^2 + 27*x + 14 does not define a finite
        subgroup of Elliptic Curve defined by y^2 + x*y = x^3 + x + 2
        over Finite Field of size 31

    Order of the point known and composite:

    Sage

        sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
        sage: P = E(26, 4)
        sage: assert P.order() == 12
        sage: print(P._order)
        12
        sage: E.isogeny(P)
        Composite morphism of degree 12 = 2^2*3:
          From: Elliptic Curve defined by y^2 + x*y = x^3 + x + 2 over Finite Field of size 31
          To:   Elliptic Curve defined by y^2 + x*y = x^3 + 26*x + 8 over Finite Field of size 31

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(31)), [Integer(1),Integer(0),Integer(0),Integer(1),Integer(2)])
        >>> P = E(Integer(26), Integer(4))
        >>> assert P.order() == Integer(12)
        >>> print(P._order)
        12
        >>> E.isogeny(P)
        Composite morphism of degree 12 = 2^2*3:
          From: Elliptic Curve defined by y^2 + x*y = x^3 + x + 2 over Finite Field of size 31
          To:   Elliptic Curve defined by y^2 + x*y = x^3 + 26*x + 8 over Finite Field of size 31

    `kernel` is a list of points:

    Sage

        sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
        sage: P = E(21,2)
        sage: Q = E(7, 12)
        sage: print(P.order())
        6
        sage: print(Q.order())
        2
        sage: E.isogeny([P, Q])
        Composite morphism of degree 12 = 2*3*2:
          From: Elliptic Curve defined by y^2 + x*y = x^3 + x + 2 over Finite Field of size 31
          To:   Elliptic Curve defined by y^2 + x*y = x^3 + 2*x + 26 over Finite Field of size 31

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(31)), [Integer(1),Integer(0),Integer(0),Integer(1),Integer(2)])
        >>> P = E(Integer(21),Integer(2))
        >>> Q = E(Integer(7), Integer(12))
        >>> print(P.order())
        6
        >>> print(Q.order())
        2
        >>> E.isogeny([P, Q])
        Composite morphism of degree 12 = 2*3*2:
          From: Elliptic Curve defined by y^2 + x*y = x^3 + x + 2 over Finite Field of size 31
          To:   Elliptic Curve defined by y^2 + x*y = x^3 + 2*x + 26 over Finite Field of size 31

    Multiple ways to set the `velu_sqrt_bound`:

    Sage

        sage: E = EllipticCurve_from_j(GF(97)(42))
        sage: P = E.gens()[0]*4
        sage: print(P.order())
        23
        sage: E.isogeny(P)
        Isogeny of degree 23 from Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97 to Elliptic Curve defined by y^2 = x^3 + 72*x + 29 over Finite Field of size 97
        sage: E.isogeny(P, velu_sqrt_bound=10)
        Elliptic-curve isogeny (using square-root Vélu) of degree 23:
          From: Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97
          To:   Elliptic Curve defined by y^2 = x^3 + 95*x + 68 over Finite Field of size 97
        sage: from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
        sage: _velu_sqrt_bound.set(10)
        sage: E.isogeny(P)
        Elliptic-curve isogeny (using square-root Vélu) of degree 23:
          From: Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97
          To:   Elliptic Curve defined by y^2 = x^3 + 95*x + 68 over Finite Field of size 97
        sage: _velu_sqrt_bound.set(1000) # Reset bound

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve_from_j(GF(Integer(97))(Integer(42)))
        >>> P = E.gens()[Integer(0)]*Integer(4)
        >>> print(P.order())
        23
        >>> E.isogeny(P)
        Isogeny of degree 23 from Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97 to Elliptic Curve defined by y^2 = x^3 + 72*x + 29 over Finite Field of size 97
        >>> E.isogeny(P, velu_sqrt_bound=Integer(10))
        Elliptic-curve isogeny (using square-root Vélu) of degree 23:
          From: Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97
          To:   Elliptic Curve defined by y^2 = x^3 + 95*x + 68 over Finite Field of size 97
        >>> from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
        >>> _velu_sqrt_bound.set(Integer(10))
        >>> E.isogeny(P)
        Elliptic-curve isogeny (using square-root Vélu) of degree 23:
          From: Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97
          To:   Elliptic Curve defined by y^2 = x^3 + 95*x + 68 over Finite Field of size 97
        >>> _velu_sqrt_bound.set(Integer(1000)) # Reset bound

    If the order of the point is unknown, fall back to `'traditional'`:

    Sage

        sage: E = EllipticCurve_from_j(GF(97)(42))
        sage: P = E(2, 39)
        sage: from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
        sage: _velu_sqrt_bound.set(1)
        sage: E.isogeny(P)
        Isogeny of degree 46 from Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97 to Elliptic Curve defined by y^2 = x^3 + 87*x + 47 over Finite Field of size 97
        sage: _velu_sqrt_bound.set(1000) # Reset bound

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve_from_j(GF(Integer(97))(Integer(42)))
        >>> P = E(Integer(2), Integer(39))
        >>> from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
        >>> _velu_sqrt_bound.set(Integer(1))
        >>> E.isogeny(P)
        Isogeny of degree 46 from Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97 to Elliptic Curve defined by y^2 = x^3 + 87*x + 47 over Finite Field of size 97
        >>> _velu_sqrt_bound.set(Integer(1000)) # Reset bound

    See also

    - `EllipticCurveHom`

    - `EllipticCurveIsogeny`

    - `EllipticCurveHom_composite`

  isogeny_codomain(kernel)

    Return the codomain of the isogeny from `self` with given kernel.

    INPUT:

    - `kernel` – either a list of points in the kernel of the isogeny, or a kernel polynomial (specified as either a univariate polynomial or a coefficient list)

    OUTPUT:

    An elliptic curve, the codomain of the separable normalized isogeny defined by this kernel.

    EXAMPLES:

    Sage

        sage: E = EllipticCurve('17a1')
        sage: R.<x> = QQ[]
        sage: E2 = E.isogeny_codomain(x - 11/4); E2
        Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 1461/16*x - 19681/64
         over Rational Field

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve('17a1')
        >>> R = QQ['x']; (x,) = R._first_ngens(1)
        >>> E2 = E.isogeny_codomain(x - Integer(11)/Integer(4)); E2
        Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 1461/16*x - 19681/64
         over Rational Field

  isogeny_ell_graph(l, directed=True, label_by_j=False)

    Return a graph representing the `l`-degree `K`-isogenies between `K`-isomorphism classes of elliptic curves for `K = self.base_field()`.

    INPUT:

    - `l` – prime degree of isogenies

    - `directed` – boolean (default: `True`); whether to return a directed or undirected graph. In the undirected case, the in-degrees and out-degrees of the vertices must be balanced and therefore the number of out-edges from the vertices corresponding to j-invariants 0 and 1728 (if they are part of the graph) are reduced to match the number of in-edges.

    - `label_by_j` – boolean (default: `False`); whether to label graph vertices by the j-invariant corresponding to the isomorphism class of curves. If the j-invariant is not unique in the isogeny class, append `*` to it to indicate a twist. Otherwise, if `False` label vertices by the equation of a representative curve.

    OUTPUT: a `Graph` or `DiGraph`

    EXAMPLES:

    Ordinary curve over finite extension field of degree 2:

    Sage

        sage: # needs sage.graphs sage.rings.finite_rings
        sage: x = polygen(ZZ, 'x')
        sage: E = EllipticCurve(GF(59^2, "i", x^2 + 1), j=5)
        sage: G = E.isogeny_ell_graph(5, directed=False, label_by_j=True); G
        Graph on 20 vertices
        sage: G.vertices(sort=True)
        ['1',
         '12',
         ...
         'i + 55']
        sage: G.edges(sort=True)
        [('1', '28*i + 11', None),
         ('1', '31*i + 11', None),
         ...
         ('8', 'i + 1', None)]

    Python

        >>> from sage.all import *
        >>> # needs sage.graphs sage.rings.finite_rings
        >>> x = polygen(ZZ, 'x')
        >>> E = EllipticCurve(GF(Integer(59)**Integer(2), "i", x**Integer(2) + Integer(1)), j=Integer(5))
        >>> G = E.isogeny_ell_graph(Integer(5), directed=False, label_by_j=True); G
        Graph on 20 vertices
        >>> G.vertices(sort=True)
        ['1',
         '12',
         ...
         'i + 55']
        >>> G.edges(sort=True)
        [('1', '28*i + 11', None),
         ('1', '31*i + 11', None),
         ...
         ('8', 'i + 1', None)]

    Supersingular curve over prime field:

    Sage

        sage: # needs sage.graphs sage.rings.finite_rings
        sage: E = EllipticCurve(GF(419), j=1728)
        sage: G3 = E.isogeny_ell_graph(3, directed=False, label_by_j=True); G3
        Graph on 27 vertices
        sage: G3.vertices(sort=True)
        ['0',
         '0*',
         ...
         '98*']
        sage: G3.edges(sort=True)
        [('0', '0*', None),
         ('0', '13', None),
         ...
         ('48*', '98*', None)]
         sage: G5 = E.isogeny_ell_graph(5, directed=False, label_by_j=True); G5
         Graph on 9 vertices
         sage: G5.vertices(sort=True)
         ['13', '13*', '407', '407*', '52', '62', '62*', '98', '98*']
         sage: G5.edges(sort=True)
         [('13', '52', None),
          ('13', '98', None),
          ...
          ('62*', '98*', None)]

    [Python]

        >>> from sage.all import *
        >>> # needs sage.graphs sage.rings.finite_rings
        >>> E = EllipticCurve(GF(Integer(419)), j=Integer(1728))
        >>> G3 = E.isogeny_ell_graph(Integer(3), directed=False, label_by_j=True); G3
        Graph on 27 vertices
        >>> G3.vertices(sort=True)
        ['0',
         '0*',
         ...
         '98*']
        >>> G3.edges(sort=True)
        [('0', '0*', None),
         ('0', '13', None),
         ...
         ('48*', '98*', None)]
        >>> G5 = E.isogeny_ell_graph(Integer(5), directed=False, label_by_j=True); G5
         Graph on 9 vertices
        >>> G5.vertices(sort=True)
         ['13', '13*', '407', '407*', '52', '62', '62*', '98', '98*']
        >>> G5.edges(sort=True)
         [('13', '52', None),
          ('13', '98', None),
          ...
          ('62*', '98*', None)]

    Supersingular curve over finite extension field of degree 2:

    Sage

        sage: # needs sage.graphs sage.rings.finite_rings
        sage: K = GF(431^2, "i", x^2 + 1)
        sage: E = EllipticCurve(K, j=0)
        sage: E.is_supersingular()
        True
        sage: G = E.isogeny_ell_graph(2, directed=True, label_by_j=True); G
        Looped multi-digraph on 37 vertices
        sage: G.vertices(sort=True)
        ['0',
         '102',
         ...
         '87*i + 190']
        sage: G.edges(sort=True)
        [('0', '125', None),
         ('0', '125', None),
         ...
         '81*i + 65', None)]
        sage: H = E.isogeny_ell_graph(2, directed=False, label_by_j=True); H
        Looped multi-graph on 37 vertices
        sage: H.vertices(sort=True)
        ['0',
         '102',
         ...
         '87*i + 190']
        sage: H.edges(sort=True)
        [('0', '125', None),
         ('102', '125', None),
         ...
         ('81*i + 65', '87*i + 190', None)]

    Python

        >>> from sage.all import *
        >>> # needs sage.graphs sage.rings.finite_rings
        >>> K = GF(Integer(431)**Integer(2), "i", x**Integer(2) + Integer(1))
        >>> E = EllipticCurve(K, j=Integer(0))
        >>> E.is_supersingular()
        True
        >>> G = E.isogeny_ell_graph(Integer(2), directed=True, label_by_j=True); G
        Looped multi-digraph on 37 vertices
        >>> G.vertices(sort=True)
        ['0',
         '102',
         ...
         '87*i + 190']
        >>> G.edges(sort=True)
        [('0', '125', None),
         ('0', '125', None),
         ...
         '81*i + 65', None)]
        >>> H = E.isogeny_ell_graph(Integer(2), directed=False, label_by_j=True); H
        Looped multi-graph on 37 vertices
        >>> H.vertices(sort=True)
        ['0',
         '102',
         ...
         '87*i + 190']
        >>> H.edges(sort=True)
        [('0', '125', None),
         ('102', '125', None),
         ...
         ('81*i + 65', '87*i + 190', None)]

    Curve over a quadratic number field:

    Sage

        sage: # needs sage.graphs sage.rings.finite_rings sage.rings.number_field
        sage: K.<e> = NumberField(x^2 - 2)
        sage: E = EllipticCurve(K, [1, 0, 1, 4, -6])
        sage: G2 = E.isogeny_ell_graph(2, directed=False)
        sage: G2.vertices(sort=True)
        ['y^2 + x*y + y = x^3 + (-130*e-356)*x + (-2000*e-2038)',
         'y^2 + x*y + y = x^3 + (-36)*x + (-70)',
         'y^2 + x*y + y = x^3 + (130*e-356)*x + (2000*e-2038)',
         'y^2 + x*y + y = x^3 + 4*x + (-6)']
        sage: G2.edges(sort=True)
        [('y^2 + x*y + y = x^3 + (-130*e-356)*x + (-2000*e-2038)',
          'y^2 + x*y + y = x^3 + (-36)*x + (-70)', None),
         ('y^2 + x*y + y = x^3 + (-36)*x + (-70)',
          'y^2 + x*y + y = x^3 + (130*e-356)*x + (2000*e-2038)', None),
         ('y^2 + x*y + y = x^3 + (-36)*x + (-70)',
          'y^2 + x*y + y = x^3 + 4*x + (-6)', None)]
        sage: G3 = E.isogeny_ell_graph(3, directed=False)
        sage: G3.vertices(sort=True)
        ['y^2 + x*y + y = x^3 + (-1)*x',
         'y^2 + x*y + y = x^3 + (-171)*x + (-874)',
         'y^2 + x*y + y = x^3 + 4*x + (-6)']
        sage: G3.edges(sort=True)
        [('y^2 + x*y + y = x^3 + (-1)*x',
          'y^2 + x*y + y = x^3 + 4*x + (-6)', None),
         ('y^2 + x*y + y = x^3 + (-171)*x + (-874)',
          'y^2 + x*y + y = x^3 + 4*x + (-6)', None)]

    [Python]

        >>> from sage.all import *
        >>> # needs sage.graphs sage.rings.finite_rings sage.rings.number_field
        >>> K = NumberField(x**Integer(2) - Integer(2), names=('e',)); (e,) = K._first_ngens(1)
        >>> E = EllipticCurve(K, [Integer(1), Integer(0), Integer(1), Integer(4), -Integer(6)])
        >>> G2 = E.isogeny_ell_graph(Integer(2), directed=False)
        >>> G2.vertices(sort=True)
        ['y^2 + x*y + y = x^3 + (-130*e-356)*x + (-2000*e-2038)',
         'y^2 + x*y + y = x^3 + (-36)*x + (-70)',
         'y^2 + x*y + y = x^3 + (130*e-356)*x + (2000*e-2038)',
         'y^2 + x*y + y = x^3 + 4*x + (-6)']
        >>> G2.edges(sort=True)
        [('y^2 + x*y + y = x^3 + (-130*e-356)*x + (-2000*e-2038)',
          'y^2 + x*y + y = x^3 + (-36)*x + (-70)', None),
         ('y^2 + x*y + y = x^3 + (-36)*x + (-70)',
          'y^2 + x*y + y = x^3 + (130*e-356)*x + (2000*e-2038)', None),
         ('y^2 + x*y + y = x^3 + (-36)*x + (-70)',
          'y^2 + x*y + y = x^3 + 4*x + (-6)', None)]
        >>> G3 = E.isogeny_ell_graph(Integer(3), directed=False)
        >>> G3.vertices(sort=True)
        ['y^2 + x*y + y = x^3 + (-1)*x',
         'y^2 + x*y + y = x^3 + (-171)*x + (-874)',
         'y^2 + x*y + y = x^3 + 4*x + (-6)']
        >>> G3.edges(sort=True)
        [('y^2 + x*y + y = x^3 + (-1)*x',
          'y^2 + x*y + y = x^3 + 4*x + (-6)', None),
         ('y^2 + x*y + y = x^3 + (-171)*x + (-874)',
          'y^2 + x*y + y = x^3 + 4*x + (-6)', None)]

  kernel_polynomial_from_divisor(f, l, check)

    Given an irreducible divisor \(f\) of the \(l\)-division polynomial on this curve, return the kernel polynomial defining the subgroup defined by \(f\).

    If the given polynomial does not define a rational subgroup, a `ValueError` is raised.

    This method is currently only implemented for prime \(l\).

    EXAMPLES:

    Sage

        sage: E = EllipticCurve(GF(101^2), [0,1])
        sage: f,_ = E.division_polynomial(5).factor()[0]
        sage: ker = E.kernel_polynomial_from_divisor(f, 5); ker
        x^2 + (49*z2 + 10)*x + 30*z2 + 80
        sage: E.isogeny(ker)
        Isogeny of degree 5
         from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 101^2
         to Elliptic Curve defined by y^2 = x^3 + (6*z2+16)*x + 18 over Finite Field in z2 of size 101^2

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(101)**Integer(2)), [Integer(0),Integer(1)])
        >>> f,_ = E.division_polynomial(Integer(5)).factor()[Integer(0)]
        >>> ker = E.kernel_polynomial_from_divisor(f, Integer(5)); ker
        x^2 + (49*z2 + 10)*x + 30*z2 + 80
        >>> E.isogeny(ker)
        Isogeny of degree 5
         from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 101^2
         to Elliptic Curve defined by y^2 = x^3 + (6*z2+16)*x + 18 over Finite Field in z2 of size 101^2

    The method detects invalid inputs:

    Sage

        sage: E = EllipticCurve(GF(101), [0,1])
        sage: f,_ = E.division_polynomial(5).factor()[-1]
        sage: E.kernel_polynomial_from_divisor(f, 5)
        Traceback (most recent call last):
        ...
        ValueError: given polynomial does not define a rational 5-isogeny

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(101)), [Integer(0),Integer(1)])
        >>> f,_ = E.division_polynomial(Integer(5)).factor()[-Integer(1)]
        >>> E.kernel_polynomial_from_divisor(f, Integer(5))
        Traceback (most recent call last):
        ...
        ValueError: given polynomial does not define a rational 5-isogeny

    Sage

        sage: E = EllipticCurve(GF(101), [1,1])
        sage: f,_ = E.division_polynomial(7).factor()[-1]
        sage: E.kernel_polynomial_from_divisor(f, 7)
        Traceback (most recent call last):
        ...
        ValueError: given polynomial does not define a rational 7-isogeny

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(101)), [Integer(1),Integer(1)])
        >>> f,_ = E.division_polynomial(Integer(7)).factor()[-Integer(1)]
        >>> E.kernel_polynomial_from_divisor(f, Integer(7))
        Traceback (most recent call last):
        ...
        ValueError: given polynomial does not define a rational 7-isogeny

    Sage

        sage: x = polygen(QQ)
        sage: K.<t> = NumberField(x^12 - 2*x^10 + 3*x^8 + 228/13*x^6 + 235/13*x^4 + 22/13*x^2 + 1/13)
        sage: E = EllipticCurve(K, [1,0])
        sage: ker = E.kernel_polynomial_from_divisor(x - t, 13); ker
        x^6 + (-169/64*t^10 + 169/32*t^8 - 247/32*t^6 - 377/8*t^4 - 2977/64*t^2 - 105/32)*x^4 + (-169/32*t^10 + 169/16*t^8 - 247/16*t^6 - 377/4*t^4 - 2977/32*t^2 - 89/16)*x^2 - 13/64*t^10 + 13/32*t^8 - 19/32*t^6 - 29/8*t^4 - 229/64*t^2 - 13/32
        sage: phi = E.isogeny(ker, check=True); phi
        Isogeny of degree 13
         from Elliptic Curve defined by y^2 = x^3 + x
          over Number Field in t with defining polynomial x^12 - 2*x^10 + 3*x^8 + 228/13*x^6 + 235/13*x^4 + 22/13*x^2 + 1/13
         to Elliptic Curve defined by y^2 = x^3 + (-2535/16*t^10+2535/8*t^8-3705/8*t^6-5655/2*t^4-44655/16*t^2-2047/8)*x
          over Number Field in t with defining polynomial x^12 - 2*x^10 + 3*x^8 + 228/13*x^6 + 235/13*x^4 + 22/13*x^2 + 1/13

    [Python]

        >>> from sage.all import *
        >>> x = polygen(QQ)
        >>> K = NumberField(x**Integer(12) - Integer(2)*x**Integer(10) + Integer(3)*x**Integer(8) + Integer(228)/Integer(13)*x**Integer(6) + Integer(235)/Integer(13)*x**Integer(4) + Integer(22)/Integer(13)*x**Integer(2) + Integer(1)/Integer(13), names=('t',)); (t,) = K._first_ngens(1)
        >>> E = EllipticCurve(K, [Integer(1),Integer(0)])
        >>> ker = E.kernel_polynomial_from_divisor(x - t, Integer(13)); ker
        x^6 + (-169/64*t^10 + 169/32*t^8 - 247/32*t^6 - 377/8*t^4 - 2977/64*t^2 - 105/32)*x^4 + (-169/32*t^10 + 169/16*t^8 - 247/16*t^6 - 377/4*t^4 - 2977/32*t^2 - 89/16)*x^2 - 13/64*t^10 + 13/32*t^8 - 19/32*t^6 - 29/8*t^4 - 229/64*t^2 - 13/32
        >>> phi = E.isogeny(ker, check=True); phi
        Isogeny of degree 13
         from Elliptic Curve defined by y^2 = x^3 + x
          over Number Field in t with defining polynomial x^12 - 2*x^10 + 3*x^8 + 228/13*x^6 + 235/13*x^4 + 22/13*x^2 + 1/13
         to Elliptic Curve defined by y^2 = x^3 + (-2535/16*t^10+2535/8*t^8-3705/8*t^6-5655/2*t^4-44655/16*t^2-2047/8)*x
          over Number Field in t with defining polynomial x^12 - 2*x^10 + 3*x^8 + 228/13*x^6 + 235/13*x^4 + 22/13*x^2 + 1/13

    ALGORITHM: [EPSV2023], Algorithm 3 (`KernelPolynomialFromDivisor`).

  kernel_polynomial_from_point(P, algorithm)

    Given a point \(P\) on this curve which generates a rational subgroup, return the kernel polynomial of that subgroup as a polynomial over the base field of the curve.

    The point \(P\) itself may be defined over an extension.

    EXAMPLES:

    Sage

        sage: E = EllipticCurve(GF(101), [1,1])
        sage: F = GF(101^3)
        sage: EE = E.change_ring(F)
        sage: xK = F([77, 28, 8]); xK
        8*z3^2 + 28*z3 + 77
        sage: K = EE.lift_x(xK); K.order()
        43
        sage: E.kernel_polynomial_from_point(K)
        x^21 + 7*x^20 + 22*x^19 + 4*x^18 + 7*x^17 + 81*x^16 + 41*x^15 + 68*x^14 + 18*x^13 + 58*x^12 + 31*x^11 + 26*x^10 + 62*x^9 + 20*x^8 + 73*x^7 + 23*x^6 + 66*x^5 + 79*x^4 + 12*x^3 + 40*x^2 + 50*x + 93

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(101)), [Integer(1),Integer(1)])
        >>> F = GF(Integer(101)**Integer(3))
        >>> EE = E.change_ring(F)
        >>> xK = F([Integer(77), Integer(28), Integer(8)]); xK
        8*z3^2 + 28*z3 + 77
        >>> K = EE.lift_x(xK); K.order()
        43
        >>> E.kernel_polynomial_from_point(K)
        x^21 + 7*x^20 + 22*x^19 + 4*x^18 + 7*x^17 + 81*x^16 + 41*x^15 + 68*x^14 + 18*x^13 + 58*x^12 + 31*x^11 + 26*x^10 + 62*x^9 + 20*x^8 + 73*x^7 + 23*x^6 + 66*x^5 + 79*x^4 + 12*x^3 + 40*x^2 + 50*x + 93

    The `'minpoly'` algorithm is often much faster than the `'basic'` algorithm:

    Sage

        sage: from sage.schemes.elliptic_curves.ell_field import EllipticCurve_field, point_of_order
        sage: p = 2^127 - 1
        sage: E = EllipticCurve(GF(p), [1,0])
        sage: P = point_of_order(E, 31)                                             # long time (8.5s)
        sage: %timeit E.kernel_polynomial_from_point(P, algorithm='basic')          # not tested
        4.38 ms ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
        sage: %timeit E.kernel_polynomial_from_point(P, algorithm='minpoly')        # not tested
        854 µs ± 1.56 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

    [Python]

        >>> from sage.all import *
        >>> from sage.schemes.elliptic_curves.ell_field import EllipticCurve_field, point_of_order
        >>> p = Integer(2)**Integer(127) - Integer(1)
        >>> E = EllipticCurve(GF(p), [Integer(1),Integer(0)])
        >>> P = point_of_order(E, Integer(31))                                             # long time (8.5s)
        >>> %timeit E.kernel_polynomial_from_point(P, algorithm='basic')          # not tested
        4.38 ms ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
        >>> %timeit E.kernel_polynomial_from_point(P, algorithm='minpoly')        # not tested
        854 µs ± 1.56 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

    Example of finding all the rational isogenies using this method:

    Sage

        sage: E = EllipticCurve(GF(71), [1,2,3,4,5])
        sage: F = E.division_field(11)
        sage: EE = E.change_ring(F)
        sage: fs = set()
        sage: for K in EE(0).division_points(11):
        ....:     if not K:
        ....:         continue
        ....:     Kp = EE.frobenius_isogeny()(K)
        ....:     if Kp.weil_pairing(K, 11) == 1:
        ....:         fs.add(E.kernel_polynomial_from_point(K))
        sage: fs = sorted(fs); fs
        [x^5 + 10*x^4 + 18*x^3 + 10*x^2 + 43*x + 46,
         x^5 + 65*x^4 + 39*x^2 + 20*x + 63]
        sage: from sage.schemes.elliptic_curves.isogeny_small_degree import is_kernel_polynomial
        sage: {is_kernel_polynomial(E, 11, f) for f in fs}
        {True}
        sage: isogs = [E.isogeny(f) for f in fs]
        sage: isogs[0]
        Isogeny of degree 11 from Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 71 to Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 34*x + 42 over Finite Field of size 71
        sage: isogs[1]
        Isogeny of degree 11 from Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 71 to Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 12*x + 40 over Finite Field of size 71
        sage: set(isogs) == set(E.isogenies_prime_degree(11))
        True

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(71)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
        >>> F = E.division_field(Integer(11))
        >>> EE = E.change_ring(F)
        >>> fs = set()
        >>> for K in EE(Integer(0)).division_points(Integer(11)):
        ...     if not K:
        ...         continue
        ...     Kp = EE.frobenius_isogeny()(K)
        ...     if Kp.weil_pairing(K, Integer(11)) == Integer(1):
        ...         fs.add(E.kernel_polynomial_from_point(K))
        >>> fs = sorted(fs); fs
        [x^5 + 10*x^4 + 18*x^3 + 10*x^2 + 43*x + 46,
         x^5 + 65*x^4 + 39*x^2 + 20*x + 63]
        >>> from sage.schemes.elliptic_curves.isogeny_small_degree import is_kernel_polynomial
        >>> {is_kernel_polynomial(E, Integer(11), f) for f in fs}
        {True}
        >>> isogs = [E.isogeny(f) for f in fs]
        >>> isogs[Integer(0)]
        Isogeny of degree 11 from Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 71 to Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 34*x + 42 over Finite Field of size 71
        >>> isogs[Integer(1)]
        Isogeny of degree 11 from Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 71 to Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 12*x + 40 over Finite Field of size 71
        >>> set(isogs) == set(E.isogenies_prime_degree(Integer(11)))
        True

    ALGORITHM:

    - The `'basic'` algorithm is to multiply together all the linear factors \((X - x([i]P))\) of the kernel polynomial using a product tree, then converting the result to the base field of the curve. Its complexity is \(\widetilde O(\ell k)\) where \(k\) is the extension degree.

    - The `'minpoly'` algorithm is [EPSV2023], Algorithm 4 (`KernelPolynomialFromIrrationalX`). Over finite fields, its complexity is \(O(\ell k) + \widetilde O(\ell)\) where \(k\) is the extension degree.

  period_lattice()

    Return the period lattice of the elliptic curve for the given embedding of its base field with respect to the differential \(dx/(2y + a_1x + a_3)\).

    Only supported for some base rings.

    EXAMPLES:

    Sage

        sage: EllipticCurve(RR, [1, 6]).period_lattice()
        Period lattice associated to Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 6.00000000000000 over Real Field with 53 bits of precision

    Python

        >>> from sage.all import *
        >>> EllipticCurve(RR, [Integer(1), Integer(6)]).period_lattice()
        Period lattice associated to Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 6.00000000000000 over Real Field with 53 bits of precision

  quadratic_twist(D=None)

    Return the quadratic twist of this curve by `D`.

    INPUT:

    - `D` – (default: `None`) the twisting parameter (see below)

    In characteristics other than 2, \(D\) must be nonzero, and the twist is isomorphic to `self` after adjoining \(\sqrt(D)\) to the base.

    In characteristic 2, \(D\) is arbitrary, and the twist is isomorphic to `self` after adjoining a root of \(x^2+x+D\) to the base.

    In characteristic 2 when \(j=0\), this is not implemented.

    If the base field \(F\) is finite, \(D\) need not be specified, and the curve returned is the unique curve (up to isomorphism) defined over \(F\) isomorphic to the original curve over the quadratic extension of \(F\) but not over \(F\) itself. Over infinite fields, an error is raised if \(D\) is not given.

    EXAMPLES:

    Sage

        sage: # needs sage.rings.finite_rings
        sage: E = EllipticCurve([GF(1103)(1), 0, 0, 107, 340]); E
        Elliptic Curve defined by y^2 + x*y  = x^3 + 107*x + 340
         over Finite Field of size 1103
        sage: F = E.quadratic_twist(-1); F
        Elliptic Curve defined by y^2  = x^3 + 1102*x^2 + 609*x + 300
         over Finite Field of size 1103
        sage: E.is_isomorphic(F)
        False
        sage: E.is_isomorphic(F, GF(1103^2,'a'))
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> E = EllipticCurve([GF(Integer(1103))(Integer(1)), Integer(0), Integer(0), Integer(107), Integer(340)]); E
        Elliptic Curve defined by y^2 + x*y  = x^3 + 107*x + 340
         over Finite Field of size 1103
        >>> F = E.quadratic_twist(-Integer(1)); F
        Elliptic Curve defined by y^2  = x^3 + 1102*x^2 + 609*x + 300
         over Finite Field of size 1103
        >>> E.is_isomorphic(F)
        False
        >>> E.is_isomorphic(F, GF(Integer(1103)**Integer(2),'a'))
        True

    A characteristic 2 example:

    Sage

        sage: E = EllipticCurve(GF(2), [1,0,1,1,1])
        sage: E1 = E.quadratic_twist(1)
        sage: E.is_isomorphic(E1)
        False
        sage: E.is_isomorphic(E1, GF(4,'a'))
        True

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve(GF(Integer(2)), [Integer(1),Integer(0),Integer(1),Integer(1),Integer(1)])
        >>> E1 = E.quadratic_twist(Integer(1))
        >>> E.is_isomorphic(E1)
        False
        >>> E.is_isomorphic(E1, GF(Integer(4),'a'))
        True

    Over finite fields, the twisting parameter may be omitted:

    Sage

        sage: # needs sage.rings.finite_rings
        sage: k.<a> = GF(2^10)
        sage: E = EllipticCurve(k, [a^2,a,1,a+1,1])
        sage: Et = E.quadratic_twist()
        sage: Et  # random (only determined up to isomorphism)
        Elliptic Curve defined
         by y^2 + x*y  = x^3 + (a^7+a^4+a^3+a^2+a+1)*x^2 + (a^8+a^6+a^4+1)
         over Finite Field in a of size 2^10
        sage: E.is_isomorphic(Et)
        False
        sage: E.j_invariant() == Et.j_invariant()
        True

        sage: # needs sage.rings.finite_rings
        sage: p = next_prime(10^10)
        sage: k = GF(p)
        sage: E = EllipticCurve(k, [1,2,3,4,5])
        sage: Et = E.quadratic_twist()
        sage: Et  # random (only determined up to isomorphism)
        Elliptic Curve defined
         by y^2  = x^3 + 7860088097*x^2 + 9495240877*x + 3048660957
         over Finite Field of size 10000000019
        sage: E.is_isomorphic(Et)
        False
        sage: k2 = GF(p^2,'a')
        sage: E.change_ring(k2).is_isomorphic(Et.change_ring(k2))
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> k = GF(Integer(2)**Integer(10), names=('a',)); (a,) = k._first_ngens(1)
        >>> E = EllipticCurve(k, [a**Integer(2),a,Integer(1),a+Integer(1),Integer(1)])
        >>> Et = E.quadratic_twist()
        >>> Et  # random (only determined up to isomorphism)
        Elliptic Curve defined
         by y^2 + x*y  = x^3 + (a^7+a^4+a^3+a^2+a+1)*x^2 + (a^8+a^6+a^4+1)
         over Finite Field in a of size 2^10
        >>> E.is_isomorphic(Et)
        False
        >>> E.j_invariant() == Et.j_invariant()
        True

        >>> # needs sage.rings.finite_rings
        >>> p = next_prime(Integer(10)**Integer(10))
        >>> k = GF(p)
        >>> E = EllipticCurve(k, [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
        >>> Et = E.quadratic_twist()
        >>> Et  # random (only determined up to isomorphism)
        Elliptic Curve defined
         by y^2  = x^3 + 7860088097*x^2 + 9495240877*x + 3048660957
         over Finite Field of size 10000000019
        >>> E.is_isomorphic(Et)
        False
        >>> k2 = GF(p**Integer(2),'a')
        >>> E.change_ring(k2).is_isomorphic(Et.change_ring(k2))
        True

  quartic_twist(D)

    Return the quartic twist of this curve by \(D\).

    INPUT:

    - `D` – (must be nonzero) the twisting parameter

    Note

    The characteristic must not be 2 or 3, and the \(j\)-invariant must be 1728.

    EXAMPLES:

    Sage

        sage: # needs sage.rings.finite_rings
        sage: E = EllipticCurve_from_j(GF(13)(1728)); E
        Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 13
        sage: E1 = E.quartic_twist(2); E1
        Elliptic Curve defined by y^2 = x^3 + 5*x over Finite Field of size 13
        sage: E.is_isomorphic(E1)
        False
        sage: E.is_isomorphic(E1, GF(13^2,'a'))
        False
        sage: E.is_isomorphic(E1, GF(13^4,'a'))
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> E = EllipticCurve_from_j(GF(Integer(13))(Integer(1728))); E
        Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 13
        >>> E1 = E.quartic_twist(Integer(2)); E1
        Elliptic Curve defined by y^2 = x^3 + 5*x over Finite Field of size 13
        >>> E.is_isomorphic(E1)
        False
        >>> E.is_isomorphic(E1, GF(Integer(13)**Integer(2),'a'))
        False
        >>> E.is_isomorphic(E1, GF(Integer(13)**Integer(4),'a'))
        True

  sextic_twist(D)

    Return the sextic twist of this curve by \(D\).

    INPUT:

    - `D` – (must be nonzero) the twisting parameter

    Note

    The characteristic must not be 2 or 3, and the \(j\)-invariant must be 0.

    EXAMPLES:

    Sage

        sage: # needs sage.rings.finite_rings
        sage: E = EllipticCurve_from_j(GF(13)(0)); E
        Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 13
        sage: E1 = E.sextic_twist(2); E1
        Elliptic Curve defined by y^2 = x^3 + 11 over Finite Field of size 13
        sage: E.is_isomorphic(E1)
        False
        sage: E.is_isomorphic(E1, GF(13^2,'a'))
        False
        sage: E.is_isomorphic(E1, GF(13^4,'a'))
        False
        sage: E.is_isomorphic(E1, GF(13^6,'a'))
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> E = EllipticCurve_from_j(GF(Integer(13))(Integer(0))); E
        Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 13
        >>> E1 = E.sextic_twist(Integer(2)); E1
        Elliptic Curve defined by y^2 = x^3 + 11 over Finite Field of size 13
        >>> E.is_isomorphic(E1)
        False
        >>> E.is_isomorphic(E1, GF(Integer(13)**Integer(2),'a'))
        False
        >>> E.is_isomorphic(E1, GF(Integer(13)**Integer(4),'a'))
        False
        >>> E.is_isomorphic(E1, GF(Integer(13)**Integer(6),'a'))
        True

  two_torsion_rank()

    Return the dimension of the 2-torsion subgroup of \(E(K)\).

    This will be 0, 1 or 2.

    EXAMPLES:

    Sage

        sage: E = EllipticCurve('11a1')
        sage: E.two_torsion_rank()
        0
        sage: K.<alpha> = QQ.extension(E.division_polynomial(2).monic())            # needs sage.rings.number_field
        sage: E.base_extend(K).two_torsion_rank()                                   # needs sage.rings.number_field
        1
        sage: E.reduction(53).two_torsion_rank()
        2

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve('11a1')
        >>> E.two_torsion_rank()
        0
        >>> K = QQ.extension(E.division_polynomial(Integer(2)).monic(), names=('alpha',)); (alpha,) = K._first_ngens(1)# needs sage.rings.number_field
        >>> E.base_extend(K).two_torsion_rank()                                   # needs sage.rings.number_field
        1
        >>> E.reduction(Integer(53)).two_torsion_rank()
        2

    Sage

        sage: E = EllipticCurve('14a1')
        sage: E.two_torsion_rank()
        1
        sage: f = E.division_polynomial(2).monic().factor()[1][0]
        sage: K.<alpha> = QQ.extension(f)                                           # needs sage.rings.number_field
        sage: E.base_extend(K).two_torsion_rank()                                   # needs sage.rings.number_field
        2

    [Python]

        >>> from sage.all import *
        >>> E = EllipticCurve('14a1')
        >>> E.two_torsion_rank()
        1
        >>> f = E.division_polynomial(Integer(2)).monic().factor()[Integer(1)][Integer(0)]
        >>> K = QQ.extension(f, names=('alpha',)); (alpha,) = K._first_ngens(1)# needs sage.rings.number_field
        >>> E.base_extend(K).two_torsion_rank()                                   # needs sage.rings.number_field
        2

    Sage

        sage: EllipticCurve('15a1').two_torsion_rank()
        2

    Python

        >>> from sage.all import *
        >>> EllipticCurve('15a1').two_torsion_rank()
        2

  weierstrass_p(prec=20, algorithm=None)

    Compute the Weierstrass \(\wp\)-function of this elliptic curve.

    ALGORITHM: `sage.schemes.elliptic_curves.ell_wp.weierstrass_p()`

    INPUT:

    - `prec` – precision

    - `algorithm` – string or `None` (default: `None`); a choice of algorithm among `'pari'`, `'fast'`, `'quadratic'` or `None` to let this function determine the best algorithm to use

    OUTPUT:

    A Laurent series in one variable \(z\) with coefficients in the base field \(k\) of \(E\).

    EXAMPLES:

    Sage

        sage: E = EllipticCurve('11a1')
        sage: E.weierstrass_p(prec=10)
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8 + O(z^10)
        sage: E.weierstrass_p(prec=8)
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)
        sage: Esh = E.short_weierstrass_model()
        sage: Esh.weierstrass_p(prec=8)
        z^-2 + 13392/5*z^2 + 1080432/7*z^4 + 59781888/25*z^6 + O(z^8)
        sage: E.weierstrass_p(prec=20, algorithm='fast')
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
        + 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
        + 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
        sage: E.weierstrass_p(prec=20, algorithm='pari')
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
        + 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
        + 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
        sage: E.weierstrass_p(prec=20, algorithm='quadratic')
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
        + 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
        + 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)

    Python

        >>> from sage.all import *
        >>> E = EllipticCurve('11a1')
        >>> E.weierstrass_p(prec=Integer(10))
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8 + O(z^10)
        >>> E.weierstrass_p(prec=Integer(8))
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)
        >>> Esh = E.short_weierstrass_model()
        >>> Esh.weierstrass_p(prec=Integer(8))
        z^-2 + 13392/5*z^2 + 1080432/7*z^4 + 59781888/25*z^6 + O(z^8)
        >>> E.weierstrass_p(prec=Integer(20), algorithm='fast')
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
        + 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
        + 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
        >>> E.weierstrass_p(prec=Integer(20), algorithm='pari')
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
        + 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
        + 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
        >>> E.weierstrass_p(prec=Integer(20), algorithm='quadratic')
        z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
        + 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
        + 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)

sage.schemes.elliptic_curves.ell_field.compute_model(E, name)

  Return a model of an elliptic curve `E` of the type specified in the `name` parameter.

  Used as a helper function in `EllipticCurveIsogeny`.

  INPUT:

  - `E` – elliptic curve

  - `name` – string; current options:

    - `'minimal'`: Return a global minimal model of `E` if it exists, and a semi-global minimal model otherwise. For this choice, `E` must be defined over a number field. See `global_minimal_model()`.

    - `'short_weierstrass'`: Return a short Weierstrass model of `E` assuming one exists. See `short_weierstrass_model()`.

    - `'montgomery'`: Return an (untwisted) Montgomery model of `E` assuming one exists over this field. See `montgomery_model()`.

  OUTPUT: an elliptic curve of the specified type isomorphic to \(E\)

  EXAMPLES:

  Sage

      sage: from sage.schemes.elliptic_curves.ell_field import compute_model
      sage: E = EllipticCurve([12/7, 405/49, 0, -81/8, 135/64])
      sage: compute_model(E, 'minimal')
      Elliptic Curve defined by y^2 = x^3 - x^2 - 7*x + 10 over Rational Field
      sage: compute_model(E, 'short_weierstrass')
      Elliptic Curve defined by y^2 = x^3 - 48114*x + 4035015 over Rational Field
      sage: compute_model(E, 'montgomery')
      Elliptic Curve defined by y^2 = x^3 + 5*x^2 + x over Rational Field

  Python

      >>> from sage.all import *
      >>> from sage.schemes.elliptic_curves.ell_field import compute_model
      >>> E = EllipticCurve([Integer(12)/Integer(7), Integer(405)/Integer(49), Integer(0), -Integer(81)/Integer(8), Integer(135)/Integer(64)])
      >>> compute_model(E, 'minimal')
      Elliptic Curve defined by y^2 = x^3 - x^2 - 7*x + 10 over Rational Field
      >>> compute_model(E, 'short_weierstrass')
      Elliptic Curve defined by y^2 = x^3 - 48114*x + 4035015 over Rational Field
      >>> compute_model(E, 'montgomery')
      Elliptic Curve defined by y^2 = x^3 + 5*x^2 + x over Rational Field

sage.schemes.elliptic_curves.ell_field.point_of_order(E, n)

  Given an elliptic curve \(E\) over a finite field or a number field and an integer \(n \geq 1\), construct a point of order \(n\) on \(E\), possibly defined over an extension of the base field of \(E\).

  Currently only prime powers \(n\) are supported.

  EXAMPLES:

  Sage

      sage: from sage.schemes.elliptic_curves.ell_field import point_of_order
      sage: E = EllipticCurve(GF(101), [1,2,3,4,5])
      sage: P = point_of_order(E, 5); P  # random
      (50*Y^5 + 48*Y^4 + 26*Y^3 + 37*Y^2 + 48*Y + 15 : 25*Y^5 + 31*Y^4 + 79*Y^3 + 39*Y^2 + 3*Y + 20 : 1)
      sage: P.base_ring()
      Finite Field in Y of size 101^6
      sage: P.order()
      5
      sage: P.curve().a_invariants()
      (1, 2, 3, 4, 5)

  Python

      >>> from sage.all import *
      >>> from sage.schemes.elliptic_curves.ell_field import point_of_order
      >>> E = EllipticCurve(GF(Integer(101)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
      >>> P = point_of_order(E, Integer(5)); P  # random
      (50*Y^5 + 48*Y^4 + 26*Y^3 + 37*Y^2 + 48*Y + 15 : 25*Y^5 + 31*Y^4 + 79*Y^3 + 39*Y^2 + 3*Y + 20 : 1)
      >>> P.base_ring()
      Finite Field in Y of size 101^6
      >>> P.order()
      5
      >>> P.curve().a_invariants()
      (1, 2, 3, 4, 5)

  Sage

      sage: Q = point_of_order(E, 8); Q  # random
      (69*x^5 + 24*x^4 + 100*x^3 + 65*x^2 + 88*x + 97 : 65*x^5 + 28*x^4 + 5*x^3 + 45*x^2 + 42*x + 18 : 1)
      sage: 8*Q == 0 and 4*Q != 0
      True

  [Python]

      >>> from sage.all import *
      >>> Q = point_of_order(E, Integer(8)); Q  # random
      (69*x^5 + 24*x^4 + 100*x^3 + 65*x^2 + 88*x + 97 : 65*x^5 + 28*x^4 + 5*x^3 + 45*x^2 + 42*x + 18 : 1)
      >>> Integer(8)*Q == Integer(0) and Integer(4)*Q != Integer(0)
      True

  Sage

      sage: from sage.schemes.elliptic_curves.ell_field import point_of_order
      sage: E = EllipticCurve(QQ, [7,7])
      sage: P = point_of_order(E, 3); P  # random
      (x : -Y : 1)
      sage: P.base_ring()
      Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field
      sage: P.base_ring().base_field()
      Number Field in x with defining polynomial x^4 + 14*x^2 + 28*x - 49/3
      sage: P.order()
      3
      sage: P.curve().a_invariants()
      (0, 0, 0, 7, 7)

  Python

      >>> from sage.all import *
      >>> from sage.schemes.elliptic_curves.ell_field import point_of_order
      >>> E = EllipticCurve(QQ, [Integer(7),Integer(7)])
      >>> P = point_of_order(E, Integer(3)); P  # random
      (x : -Y : 1)
      >>> P.base_ring()
      Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field
      >>> P.base_ring().base_field()
      Number Field in x with defining polynomial x^4 + 14*x^2 + 28*x - 49/3
      >>> P.order()
      3
      >>> P.curve().a_invariants()
      (0, 0, 0, 7, 7)

  Sage

      sage: Q = point_of_order(E, 4); Q  # random
      (x : Y : 1)
      sage: Q.base_ring()
      Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field
      sage: Q.base_ring().base_field()
      Number Field in x with defining polynomial x^6 + 35*x^4 + 140*x^3 - 245*x^2 - 196*x - 735
      sage: Q.order()
      4

  [Python]

      >>> from sage.all import *
      >>> Q = point_of_order(E, Integer(4)); Q  # random
      (x : Y : 1)
      >>> Q.base_ring()
      Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field
      >>> Q.base_ring().base_field()
      Number Field in x with defining polynomial x^6 + 35*x^4 + 140*x^3 - 245*x^2 - 196*x - 735
      >>> Q.order()
      4