Example #1
0
def EllipticCurve(x=None, y=None, j=None, minimal_twist=True):
    r"""
    There are several ways to construct an elliptic curve:
    
    .. math::
    
       y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.       
    
    
    - EllipticCurve([a1,a2,a3,a4,a6]): Elliptic curve with given
      a-invariants. The invariants are coerced into the parent of the
      first element. If all are integers, they are coerced into the
      rational numbers.
    
    - EllipticCurve([a4,a6]): Same as above, but a1=a2=a3=0.
    
    - EllipticCurve(label): Returns the elliptic curve over Q from the
      Cremona database with the given label. The label is a string, such
      as "11a" or "37b2". The letters in the label *must* be lower case
      (Cremona's new labeling).
    
    - EllipticCurve(R, [a1,a2,a3,a4,a6]): Create the elliptic curve
      over R with given a-invariants. Here R can be an arbitrary ring.
      Note that addition need not be defined.
    
            
    - EllipticCurve(j=j0) or EllipticCurve_from_j(j0): Return an
      elliptic curve with j-invariant `j0`.

    In each case above where the input is a list of length 2 or 5, one
    can instead give a 2 or 5-tuple instead.
    
    EXAMPLES: We illustrate creating elliptic curves.
    
    ::
    
        sage: EllipticCurve([0,0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
    
    We create a curve from a Cremona label::
    
        sage: EllipticCurve('37b2')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field
        sage: EllipticCurve('5077a')
        Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
        sage: EllipticCurve('389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

    Old Cremona labels are allowed::

        sage: EllipticCurve('2400FF')
        Elliptic Curve defined by y^2 = x^3 + x^2 + 2*x + 8 over Rational Field

    Unicode labels are allowed::

        sage: EllipticCurve(u'389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

    We create curves over a finite field as follows::

        sage: EllipticCurve([GF(5)(0),0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
        sage: EllipticCurve(GF(5), [0, 0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5

    Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type
    "elliptic curve over a finite field"::

        sage: F = Zmod(101)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'>
        sage: E.category()
        Category of schemes over Ring of integers modulo 101

    In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite
    are of type "generic elliptic curve"::

        sage: F = Zmod(95)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'>
        sage: E.category()
        Category of schemes over Ring of integers modulo 95

    The following is a curve over the complex numbers::
    
        sage: E = EllipticCurve(CC, [0,0,1,-1,0])
        sage: E
        Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision
        sage: E.j_invariant()
        2988.97297297297
    
    We can also create elliptic curves by giving the Weierstrass equation::
    
        sage: x, y = var('x,y')
        sage: EllipticCurve(y^2 + y ==  x^3 + x - 9)
        Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field
        
        sage: R.<x,y> = GF(5)[]
        sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x)
        Elliptic Curve defined by y^2 + x*y  = x^3 + x^2 + 2 over Finite Field of size 5

    We can explicitly specify the `j`-invariant::

        sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label()
        Elliptic Curve defined by y^2 = x^3 - x over Rational Field
        1728
        '32a2'

        sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant()
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
        2

    See trac #6657::

        sage: EllipticCurve(GF(144169),j=1728)
        Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169

    By default, when a rational value of `j` is given, the constructed
    curve is a minimal twist (minimal conductor for curves with that
    `j`-invariant).  This can be changed by setting the optional
    parameter ``minimal_twist``, which is True by default, to False::


        sage: EllipticCurve(j=100)
        Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
        sage: E =EllipticCurve(j=100); E
        Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
        sage: E.conductor()
        33129800
        sage: E.j_invariant()
        100
        sage: E =EllipticCurve(j=100, minimal_twist=False); E
        Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field
        sage: E.conductor()
        298168200
        sage: E.j_invariant()
        100

    Without this option, constructing the curve could take a long time
    since both `j` and `j-1728` have to be factored to compute the
    minimal twist (see :trac:`13100`)::

       sage: E = EllipticCurve_from_j(2^256+1,minimal_twist=False)
       sage: E.j_invariant() == 2^256+1
       True

    TESTS::

        sage: R = ZZ['u', 'v']
        sage: EllipticCurve(R, [1,1])
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v
        over Integer Ring
    
    We create a curve and a point over QQbar (see #6879)::
    
        sage: E = EllipticCurve(QQbar,[0,1])
        sage: E(0)
        (0 : 1 : 0)
        sage: E.base_field()
        Algebraic Field

        sage: E = EllipticCurve(RR,[1,2]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: EllipticCurve(CC,[3,4]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field
        Algebraic Field

    See trac #6657::

        sage: EllipticCurve(3,j=1728)
        Traceback (most recent call last):
        ...
        ValueError: First parameter (if present) must be a ring when j is specified

        sage: EllipticCurve(GF(5),j=3/5)
        Traceback (most recent call last):
        ...
        ValueError: First parameter must be a ring containing 3/5

    If the universe of the coefficients is a general field, the object
    constructed has type EllipticCurve_field.  Otherwise it is
    EllipticCurve_generic.  See trac #9816::

        sage: E = EllipticCurve([QQbar(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>

        sage: E = EllipticCurve([RR(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>

        sage: E = EllipticCurve([i,i]); E
        Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
        sage: E.category()
        Category of schemes over Symbolic Ring
        sage: SR in Fields()
        True

        sage: F = FractionField(PolynomialRing(QQ,'t'))
        sage: t = F.gen()
        sage: E = EllipticCurve([t,0]); E
        Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
        sage: E.category()
        Category of schemes over Fraction Field of Univariate Polynomial Ring in t over Rational Field

    See :trac:`12517`::

        sage: E = EllipticCurve([1..5])
        sage: EllipticCurve(E.a_invariants())
        Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field

    See :trac:`11773`::

        sage: E = EllipticCurve()
        Traceback (most recent call last):
        ...
        TypeError: invalid input to EllipticCurve constructor

    """
    import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field  # here to avoid circular includes
    
    if j is not None:
        if not x is None:
            if rings.is_Ring(x):
                try:
                    j = x(j)
                except (ZeroDivisionError, ValueError, TypeError):
                    raise ValueError, "First parameter must be a ring containing %s"%j
            else:
                raise ValueError, "First parameter (if present) must be a ring when j is specified"
        return EllipticCurve_from_j(j, minimal_twist)

    if x is None:
        raise TypeError, "invalid input to EllipticCurve constructor"
    
    if is_SymbolicEquation(x):
        x = x.lhs() - x.rhs()
    
    if parent(x) is SR:
        x = x._polynomial_(rings.QQ['x', 'y'])
    
    if rings.is_MPolynomial(x) and y is None:
        f = x
        if f.degree() != 3:
            raise ValueError, "Elliptic curves must be defined by a cubic polynomial."
        if f.degrees() == (3,2):
            x, y = f.parent().gens()
        elif f.degree() == (2,3):
            y, x = f.parent().gens()
        elif len(f.parent().gens()) == 2 or len(f.parent().gens()) == 3 and f.is_homogeneous():
            # We'd need a point too...
            raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented."
        else:
            raise ValueError, "Defining polynomial must be a cubic polynomial in two variables."

        try:
            if f.coefficient(x**3) < 0:
                f = -f
            # is there a nicer way to extract the coefficients?
            a1 = a2 = a3 = a4 = a6 = 0
            for coeff, mon in f:
                if mon == x**3:
                    assert coeff == 1
                elif mon == x**2:
                    a2 = coeff
                elif mon == x:
                    a4 = coeff
                elif mon == 1:
                    a6 = coeff
                elif mon == y**2:
                    assert coeff == -1
                elif mon == x*y:
                    a1 = -coeff
                elif mon == y:
                    a3 = -coeff
                else:
                    assert False
            return EllipticCurve([a1, a2, a3, a4, a6])
        except AssertionError:
            raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented."
    
    if rings.is_Ring(x):
        if rings.is_RationalField(x):
            return ell_rational_field.EllipticCurve_rational_field(x, y)
        elif rings.is_FiniteField(x) or (rings.is_IntegerModRing(x) and x.characteristic().is_prime()):
            return ell_finite_field.EllipticCurve_finite_field(x, y)
        elif rings.is_pAdicField(x):
            return ell_padic_field.EllipticCurve_padic_field(x, y)
        elif rings.is_NumberField(x):
            return ell_number_field.EllipticCurve_number_field(x, y)
        elif x in _Fields:
            return ell_field.EllipticCurve_field(x, y)
        return ell_generic.EllipticCurve_generic(x, y)

    if isinstance(x, unicode):
        x = str(x)

    if isinstance(x, str):
        return ell_rational_field.EllipticCurve_rational_field(x)

    if rings.is_RingElement(x) and y is None:
        raise TypeError, "invalid input to EllipticCurve constructor"

    if not isinstance(x, (list, tuple)):
        raise TypeError, "invalid input to EllipticCurve constructor"

    x = Sequence(x)
    if not (len(x) in [2,5]):
        raise ValueError, "sequence of coefficients must have length 2 or 5"
    R = x.universe()

    if isinstance(x[0], (rings.Rational, rings.Integer, int, long)):
        return ell_rational_field.EllipticCurve_rational_field(x, y)

    elif rings.is_NumberField(R):
        return ell_number_field.EllipticCurve_number_field(x, y)

    elif rings.is_pAdicField(R):
        return ell_padic_field.EllipticCurve_padic_field(x, y)
    
    elif rings.is_FiniteField(R) or (rings.is_IntegerModRing(R) and R.characteristic().is_prime()):
        return ell_finite_field.EllipticCurve_finite_field(x, y)

    elif R in _Fields:
        return ell_field.EllipticCurve_field(x, y)

    return ell_generic.EllipticCurve_generic(x, y)
Example #2
0
def EllipticCurve(x=None, y=None, j=None):
    r"""
    There are several ways to construct an elliptic curve:
    
    .. math::
    
       y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.       
    
    
    - EllipticCurve([a1,a2,a3,a4,a6]): Elliptic curve with given
      a-invariants. The invariants are coerced into the parent of the
      first element. If all are integers, they are coerced into the
      rational numbers.
    
    - EllipticCurve([a4,a6]): Same as above, but a1=a2=a3=0.
    
    - EllipticCurve(label): Returns the elliptic curve over Q from the
      Cremona database with the given label. The label is a string, such
      as "11a" or "37b2". The letters in the label *must* be lower case
      (Cremona's new labeling).
    
    - EllipticCurve(R, [a1,a2,a3,a4,a6]): Create the elliptic curve
      over R with given a-invariants. Here R can be an arbitrary ring.
      Note that addition need not be defined.
    
            
    - EllipticCurve(j): Return an elliptic curve with j-invariant
      `j`.  Warning: this is deprecated.  Use ``EllipticCurve_from_j(j)`` 
      or ``EllipticCurve(j=j)`` instead.         

    In each case above where the input is a list of length 2 or 5, one
    can instead give a 2 or 5-tuple instead.
    
    EXAMPLES: We illustrate creating elliptic curves.
    
    ::
    
        sage: EllipticCurve([0,0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
    
    We create a curve from a Cremona label::
    
        sage: EllipticCurve('37b2')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field
        sage: EllipticCurve('5077a')
        Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
        sage: EllipticCurve('389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

    Unicode labels are allowed::

        sage: EllipticCurve(u'389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
    
    We create curves over a finite field as follows::
    
        sage: EllipticCurve([GF(5)(0),0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
        sage: EllipticCurve(GF(5), [0, 0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5

    Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type
    "elliptic curve over a finite field"::

        sage: F = Zmod(101)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'>
        sage: E.category()
        Category of schemes over Ring of integers modulo 101

    In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite
    are of type "generic elliptic curve"::

        sage: F = Zmod(95)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'>
        sage: E.category()
        Category of schemes over Ring of integers modulo 95

    The following is a curve over the complex numbers::
    
        sage: E = EllipticCurve(CC, [0,0,1,-1,0])
        sage: E
        Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision
        sage: E.j_invariant()
        2988.97297297297
    
    We can also create elliptic curves by giving the Weierstrass equation::
    
        sage: x, y = var('x,y')
        sage: EllipticCurve(y^2 + y ==  x^3 + x - 9)
        Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field
        
        sage: R.<x,y> = GF(5)[]
        sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x)
        Elliptic Curve defined by y^2 + x*y  = x^3 + x^2 + 2 over Finite Field of size 5

    We can explicitly specify the `j`-invariant::

        sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label()
        Elliptic Curve defined by y^2 = x^3 - x over Rational Field
        1728
        '32a2'

        sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant()
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
        2

    See trac #6657::    

        sage: EllipticCurve(GF(144169),j=1728)
        Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169


    TESTS::
    
        sage: R = ZZ['u', 'v']
        sage: EllipticCurve(R, [1,1])
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v
        over Integer Ring
    
    We create a curve and a point over QQbar (see #6879)::
    
        sage: E = EllipticCurve(QQbar,[0,1])
        sage: E(0)
        (0 : 1 : 0)
        sage: E.base_field()
        Algebraic Field

        sage: E = EllipticCurve(RR,[1,2]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: EllipticCurve(CC,[3,4]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field
        Algebraic Field

    See trac #6657::

        sage: EllipticCurve(3,j=1728)
        Traceback (most recent call last):
        ...
        ValueError: First parameter (if present) must be a ring when j is specified

        sage: EllipticCurve(GF(5),j=3/5)
        Traceback (most recent call last):
        ...
        ValueError: First parameter must be a ring containing 3/5

    If the universe of the coefficients is a general field, the object
    constructed has type EllipticCurve_field.  Otherwise it is
    EllipticCurve_generic.  See trac #9816::

        sage: E = EllipticCurve([QQbar(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>

        sage: E = EllipticCurve([RR(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>

        sage: E = EllipticCurve([i,i]); E
        Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
        sage: E.category()
        Category of schemes over Symbolic Ring
        sage: is_field(SR)
        True

        sage: F = FractionField(PolynomialRing(QQ,'t'))
        sage: t = F.gen()
        sage: E = EllipticCurve([t,0]); E
        Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
        sage: E.category()
        Category of schemes over Fraction Field of Univariate Polynomial Ring in t over Rational Field

    See :trac:`12517`::

        sage: E = EllipticCurve([1..5])
        sage: EllipticCurve(E.a_invariants())
        Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
    """
    import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field  # here to avoid circular includes
    
    if j is not None:
        if not x is None:
            if rings.is_Ring(x):
                try:
                    j = x(j)
                except (ZeroDivisionError, ValueError, TypeError):                    
                    raise ValueError, "First parameter must be a ring containing %s"%j
            else:
                raise ValueError, "First parameter (if present) must be a ring when j is specified"
        return EllipticCurve_from_j(j)

    assert x is not None
    
    if is_SymbolicEquation(x):
        x = x.lhs() - x.rhs()
    
    if parent(x) is SR:
        x = x._polynomial_(rings.QQ['x', 'y'])
    
    if rings.is_MPolynomial(x) and y is None:
        f = x
        if f.degree() != 3:
            raise ValueError, "Elliptic curves must be defined by a cubic polynomial."
        if f.degrees() == (3,2):
            x, y = f.parent().gens()
        elif f.degree() == (2,3):
            y, x = f.parent().gens()
        elif len(f.parent().gens()) == 2 or len(f.parent().gens()) == 3 and f.is_homogeneous():
            # We'd need a point too...
            raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented."
        else:
            raise ValueError, "Defining polynomial must be a cubic polynomial in two variables."

        try:
            if f.coefficient(x**3) < 0:
                f = -f
            # is there a nicer way to extract the coefficients?
            a1 = a2 = a3 = a4 = a6 = 0
            for coeff, mon in f:
                if mon == x**3:
                    assert coeff == 1
                elif mon == x**2:
                    a2 = coeff
                elif mon == x:
                    a4 = coeff
                elif mon == 1:
                    a6 = coeff
                elif mon == y**2:
                    assert coeff == -1
                elif mon == x*y:
                    a1 = -coeff
                elif mon == y:
                    a3 = -coeff
                else:
                    assert False
            return EllipticCurve([a1, a2, a3, a4, a6])
        except AssertionError:
            raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented."
    
    if rings.is_Ring(x):
        if rings.is_RationalField(x):
            return ell_rational_field.EllipticCurve_rational_field(x, y)
        elif rings.is_FiniteField(x) or (rings.is_IntegerModRing(x) and x.characteristic().is_prime()):
            return ell_finite_field.EllipticCurve_finite_field(x, y)
        elif rings.is_pAdicField(x):
            return ell_padic_field.EllipticCurve_padic_field(x, y)
        elif rings.is_NumberField(x):
            return ell_number_field.EllipticCurve_number_field(x, y)
        elif rings.is_Field(x):
            return ell_field.EllipticCurve_field(x, y)
        return ell_generic.EllipticCurve_generic(x, y)

    if isinstance(x, unicode):
        x = str(x)
        
    if isinstance(x, str):
        return ell_rational_field.EllipticCurve_rational_field(x)
        
    if rings.is_RingElement(x) and y is None:
        from sage.misc.misc import deprecation
        deprecation("'EllipticCurve(j)' is deprecated; use 'EllipticCurve_from_j(j)' or 'EllipticCurve(j=j)' instead.")
        # Fixed for all characteristics and cases by John Cremona
        j=x
        F=j.parent().fraction_field()
        char=F.characteristic()
        if char==2:
            if j==0:
                return EllipticCurve(F, [ 0, 0, 1, 0, 0 ])
            else:
                return EllipticCurve(F, [ 1, 0, 0, 0, 1/j ])
        if char==3:
            if j==0:
                return EllipticCurve(F, [ 0, 0, 0, 1, 0 ])
            else:
                return EllipticCurve(F, [ 0, j, 0, 0, -j**2 ])
        if j == 0:
            return EllipticCurve(F, [ 0, 0, 0, 0, 1 ])
        if j == 1728:
            return EllipticCurve(F, [ 0, 0, 0, 1, 0 ])
        k=j-1728
        return EllipticCurve(F, [0,0,0,-3*j*k, -2*j*k**2])

    if not isinstance(x, (list, tuple)):
        raise TypeError, "invalid input to EllipticCurve constructor"

    x = Sequence(x)
    if not (len(x) in [2,5]):
        raise ValueError, "sequence of coefficients must have length 2 or 5"
    R = x.universe()

    if isinstance(x[0], (rings.Rational, rings.Integer, int, long)):
        return ell_rational_field.EllipticCurve_rational_field(x, y)

    elif rings.is_NumberField(R):
        return ell_number_field.EllipticCurve_number_field(x, y)

    elif rings.is_pAdicField(R):
        return ell_padic_field.EllipticCurve_padic_field(x, y)
    
    elif rings.is_FiniteField(R) or (rings.is_IntegerModRing(R) and R.characteristic().is_prime()):
        return ell_finite_field.EllipticCurve_finite_field(x, y)

    elif rings.is_Field(R):
        return ell_field.EllipticCurve_field(x, y)

    return ell_generic.EllipticCurve_generic(x, y)
Example #3
0
def EllipticCurve(x=None, y=None, j=None, minimal_twist=True):
    r"""
    Construct an elliptic curve.

    In Sage, an elliptic curve is always specified by its a-invariants

    .. math::

       y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.

    INPUT:

    There are several ways to construct an elliptic curve:

    - ``EllipticCurve([a1,a2,a3,a4,a6])``: Elliptic curve with given
      a-invariants. The invariants are coerced into the parent of the
      first element. If all are integers, they are coerced into the
      rational numbers.

    - ``EllipticCurve([a4,a6])``: Same as above, but `a_1=a_2=a_3=0`.

    - ``EllipticCurve(label)``: Returns the elliptic curve over Q from
      the Cremona database with the given label. The label is a
      string, such as ``"11a"`` or ``"37b2"``. The letters in the
      label *must* be lower case (Cremona's new labeling).

    - ``EllipticCurve(R, [a1,a2,a3,a4,a6])``: Create the elliptic
      curve over ``R`` with given a-invariants. Here ``R`` can be an
      arbitrary ring. Note that addition need not be defined.

    - ``EllipticCurve(j=j0)`` or ``EllipticCurve_from_j(j0)``: Return
      an elliptic curve with j-invariant ``j0``.

    - ``EllipticCurve(polynomial)``: Read off the a-invariants from
      the polynomial coefficients, see
      :func:`EllipticCurve_from_Weierstrass_polynomial`.

    In each case above where the input is a list of length 2 or 5, one
    can instead give a 2 or 5-tuple instead.

    EXAMPLES:

    We illustrate creating elliptic curves::

        sage: EllipticCurve([0,0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field

    We create a curve from a Cremona label::

        sage: EllipticCurve('37b2')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field
        sage: EllipticCurve('5077a')
        Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
        sage: EllipticCurve('389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

    Old Cremona labels are allowed::

        sage: EllipticCurve('2400FF')
        Elliptic Curve defined by y^2 = x^3 + x^2 + 2*x + 8 over Rational Field

    Unicode labels are allowed::

        sage: EllipticCurve(u'389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

    We create curves over a finite field as follows::

        sage: EllipticCurve([GF(5)(0),0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
        sage: EllipticCurve(GF(5), [0, 0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5

    Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type
    "elliptic curve over a finite field"::

        sage: F = Zmod(101)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'>
        sage: E.category()
        Category of schemes over Ring of integers modulo 101

    In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite
    are of type "generic elliptic curve"::

        sage: F = Zmod(95)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'>
        sage: E.category()
        Category of schemes over Ring of integers modulo 95

    The following is a curve over the complex numbers::

        sage: E = EllipticCurve(CC, [0,0,1,-1,0])
        sage: E
        Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision
        sage: E.j_invariant()
        2988.97297297297

    We can also create elliptic curves by giving the Weierstrass equation::

        sage: x, y = var('x,y')
        sage: EllipticCurve(y^2 + y ==  x^3 + x - 9)
        Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field

        sage: R.<x,y> = GF(5)[]
        sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x)
        Elliptic Curve defined by y^2 + x*y  = x^3 + x^2 + 2 over Finite Field of size 5

    We can explicitly specify the `j`-invariant::

        sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label()
        Elliptic Curve defined by y^2 = x^3 - x over Rational Field
        1728
        '32a2'

        sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant()
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
        2

    See :trac:`6657` ::

        sage: EllipticCurve(GF(144169),j=1728)
        Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169

    By default, when a rational value of `j` is given, the constructed
    curve is a minimal twist (minimal conductor for curves with that
    `j`-invariant).  This can be changed by setting the optional
    parameter ``minimal_twist``, which is True by default, to False::


        sage: EllipticCurve(j=100)
        Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
        sage: E =EllipticCurve(j=100); E
        Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
        sage: E.conductor()
        33129800
        sage: E.j_invariant()
        100
        sage: E =EllipticCurve(j=100, minimal_twist=False); E
        Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field
        sage: E.conductor()
        298168200
        sage: E.j_invariant()
        100

    Without this option, constructing the curve could take a long time
    since both `j` and `j-1728` have to be factored to compute the
    minimal twist (see :trac:`13100`)::

       sage: E = EllipticCurve_from_j(2^256+1,minimal_twist=False)
       sage: E.j_invariant() == 2^256+1
       True

    TESTS::

        sage: R = ZZ['u', 'v']
        sage: EllipticCurve(R, [1,1])
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v
        over Integer Ring

    We create a curve and a point over QQbar (see #6879)::

        sage: E = EllipticCurve(QQbar,[0,1])
        sage: E(0)
        (0 : 1 : 0)
        sage: E.base_field()
        Algebraic Field

        sage: E = EllipticCurve(RR,[1,2]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: EllipticCurve(CC,[3,4]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field
        Algebraic Field

    See :trac:`6657` ::

        sage: EllipticCurve(3,j=1728)
        Traceback (most recent call last):
        ...
        ValueError: First parameter (if present) must be a ring when j is specified

        sage: EllipticCurve(GF(5),j=3/5)
        Traceback (most recent call last):
        ...
        ValueError: First parameter must be a ring containing 3/5

    If the universe of the coefficients is a general field, the object
    constructed has type EllipticCurve_field.  Otherwise it is
    EllipticCurve_generic.  See :trac:`9816` ::

        sage: E = EllipticCurve([QQbar(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>

        sage: E = EllipticCurve([RR(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>

        sage: E = EllipticCurve([i,i]); E
        Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
        sage: E.category()
        Category of schemes over Symbolic Ring
        sage: SR in Fields()
        True

        sage: F = FractionField(PolynomialRing(QQ,'t'))
        sage: t = F.gen()
        sage: E = EllipticCurve([t,0]); E
        Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
        sage: E.category()
        Category of schemes over Fraction Field of Univariate Polynomial Ring in t over Rational Field

    See :trac:`12517`::

        sage: E = EllipticCurve([1..5])
        sage: EllipticCurve(E.a_invariants())
        Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field

    See :trac:`11773`::

        sage: E = EllipticCurve()
        Traceback (most recent call last):
        ...
        TypeError: invalid input to EllipticCurve constructor

    """
    import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field  # here to avoid circular includes

    if j is not None:
        if not x is None:
            if rings.is_Ring(x):
                try:
                    j = x(j)
                except (ZeroDivisionError, ValueError, TypeError):
                    raise ValueError, "First parameter must be a ring containing %s"%j
            else:
                raise ValueError, "First parameter (if present) must be a ring when j is specified"
        return EllipticCurve_from_j(j, minimal_twist)

    if x is None:
        raise TypeError, "invalid input to EllipticCurve constructor"

    if is_SymbolicEquation(x):
        x = x.lhs() - x.rhs()

    if parent(x) is SR:
        x = x._polynomial_(rings.QQ['x', 'y'])

    if rings.is_MPolynomial(x):
        if y is None:
            return EllipticCurve_from_Weierstrass_polynomial(x)
        else:
            return EllipticCurve_from_cubic(x, y, morphism=False)

    if rings.is_Ring(x):
        if rings.is_RationalField(x):
            return ell_rational_field.EllipticCurve_rational_field(x, y)
        elif rings.is_FiniteField(x) or (rings.is_IntegerModRing(x) and x.characteristic().is_prime()):
            return ell_finite_field.EllipticCurve_finite_field(x, y)
        elif rings.is_pAdicField(x):
            return ell_padic_field.EllipticCurve_padic_field(x, y)
        elif rings.is_NumberField(x):
            return ell_number_field.EllipticCurve_number_field(x, y)
        elif x in _Fields:
            return ell_field.EllipticCurve_field(x, y)
        return ell_generic.EllipticCurve_generic(x, y)

    if isinstance(x, unicode):
        x = str(x)

    if isinstance(x, basestring):
        return ell_rational_field.EllipticCurve_rational_field(x)

    if rings.is_RingElement(x) and y is None:
        raise TypeError, "invalid input to EllipticCurve constructor"

    if not isinstance(x, (list, tuple)):
        raise TypeError, "invalid input to EllipticCurve constructor"

    x = Sequence(x)
    if not (len(x) in [2,5]):
        raise ValueError, "sequence of coefficients must have length 2 or 5"
    R = x.universe()

    if isinstance(x[0], (rings.Rational, rings.Integer, int, long)):
        return ell_rational_field.EllipticCurve_rational_field(x, y)

    elif rings.is_NumberField(R):
        return ell_number_field.EllipticCurve_number_field(x, y)

    elif rings.is_pAdicField(R):
        return ell_padic_field.EllipticCurve_padic_field(x, y)

    elif rings.is_FiniteField(R) or (rings.is_IntegerModRing(R) and R.characteristic().is_prime()):
        return ell_finite_field.EllipticCurve_finite_field(x, y)

    elif R in _Fields:
        return ell_field.EllipticCurve_field(x, y)

    return ell_generic.EllipticCurve_generic(x, y)
Example #4
0
def EllipticCurve(x=None, y=None, j=None):
    r"""
    There are several ways to construct an elliptic curve:
    
    .. math::
    
       y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.       
    
    
    - EllipticCurve([a1,a2,a3,a4,a6]): Elliptic curve with given
      a-invariants. The invariants are coerced into the parent of the
      first element. If all are integers, they are coerced into the
      rational numbers.
    
    - EllipticCurve([a4,a6]): Same as above, but a1=a2=a3=0.
    
    - EllipticCurve(label): Returns the elliptic curve over Q from the
      Cremona database with the given label. The label is a string, such
      as "11a" or "37b2". The letters in the label *must* be lower case
      (Cremona's new labeling).
    
    - EllipticCurve(R, [a1,a2,a3,a4,a6]): Create the elliptic curve
      over R with given a-invariants. Here R can be an arbitrary ring.
      Note that addition need not be defined.
    
            
    - EllipticCurve(j): Return an elliptic curve with j-invariant
      `j`.  Warning: this is deprecated.  Use ``EllipticCurve_from_j(j)`` 
      or ``EllipticCurve(j=j)`` instead.         

    
    EXAMPLES: We illustrate creating elliptic curves.
    
    ::
    
        sage: EllipticCurve([0,0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
    
    We create a curve from a Cremona label::
    
        sage: EllipticCurve('37b2')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field
        sage: EllipticCurve('5077a')
        Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
        sage: EllipticCurve('389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

    Unicode labels are allowed::

        sage: EllipticCurve(u'389a')
        Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
    
    We create curves over a finite field as follows::
    
        sage: EllipticCurve([GF(5)(0),0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
        sage: EllipticCurve(GF(5), [0, 0,1,-1,0])
        Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5

    Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type
    "elliptic curve over a finite field"::

        sage: F = Zmod(101)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field'>
            
    In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite
    are of type "generic elliptic curve"::

        sage: F = Zmod(95)
        sage: EllipticCurve(F, [2, 3])
        Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95
        sage: E = EllipticCurve([F(2), F(3)])
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic'>
    
    The following is a curve over the complex numbers::
    
        sage: E = EllipticCurve(CC, [0,0,1,-1,0])
        sage: E
        Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision
        sage: E.j_invariant()
        2988.97297297297
    
    We can also create elliptic curves by giving the Weierstrass equation::
    
        sage: x, y = var('x,y')
        sage: EllipticCurve(y^2 + y ==  x^3 + x - 9)
        Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field
        
        sage: R.<x,y> = GF(5)[]
        sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x)
        Elliptic Curve defined by y^2 + x*y  = x^3 + x^2 + 2 over Finite Field of size 5

    We can explicitly specify the `j`-invariant::

        sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label()
        Elliptic Curve defined by y^2 = x^3 - x over Rational Field
        1728
        '32a2'

        sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant()
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
        2

    See trac #6657::    

        sage: EllipticCurve(GF(144169),j=1728)
        Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169


    TESTS::
    
        sage: R = ZZ['u', 'v']
        sage: EllipticCurve(R, [1,1])
        Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v
        over Integer Ring
    
    We create a curve and a point over QQbar (see #6879)::
    
        sage: E = EllipticCurve(QQbar,[0,1])
        sage: E(0)
        (0 : 1 : 0)
        sage: E.base_field()
        Algebraic Field

        sage: E = EllipticCurve(RR,[1,2]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: EllipticCurve(CC,[3,4]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000 over Complex Field with 53 bits of precision
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000 over Real Field with 53 bits of precision
        Real Field with 53 bits of precision
        sage: E = EllipticCurve(QQbar,[5,6]); E; E.base_field()
        Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field
        Algebraic Field

    See trac #6657::

        sage: EllipticCurve(3,j=1728)
        Traceback (most recent call last):
        ...
        ValueError: First parameter (if present) must be a ring when j is specified

        sage: EllipticCurve(GF(5),j=3/5)
        Traceback (most recent call last):
        ...
        ValueError: First parameter must be a ring containing 3/5

    If the universe of the coefficients is a general field, the object
    constructed has type EllipticCurve_field.  Otherwise it is
    EllipticCurve_generic.  See trac #9816::

        sage: E = EllipticCurve([QQbar(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field'>

        sage: E = EllipticCurve([RR(1),3]); E
        Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000 over Real Field with 53 bits of precision
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field'>

        sage: E = EllipticCurve([i,i]); E
        Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field'>
        sage: is_field(SR)
        True

        sage: F = FractionField(PolynomialRing(QQ,'t'))
        sage: t = F.gen()
        sage: E = EllipticCurve([t,0]); E
        Elliptic Curve defined by y^2 = x^3 + t*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field
        sage: type(E)
        <class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field'>


    """
    import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field  # here to avoid circular includes
    
    if j is not None:
        if not x is None:
            if rings.is_Ring(x):
                try:
                    j = x(j)
                except (ZeroDivisionError, ValueError, TypeError):                    
                    raise ValueError, "First parameter must be a ring containing %s"%j
            else:
                raise ValueError, "First parameter (if present) must be a ring when j is specified"
        return EllipticCurve_from_j(j)

    assert x is not None
    
    if is_SymbolicEquation(x):
        x = x.lhs() - x.rhs()
    
    if parent(x) is SR:
        x = x._polynomial_(rings.QQ['x', 'y'])
    
    if rings.is_MPolynomial(x) and y is None:
        f = x
        if f.degree() != 3:
            raise ValueError, "Elliptic curves must be defined by a cubic polynomial."
        if f.degrees() == (3,2):
            x, y = f.parent().gens()
        elif f.degree() == (2,3):
            y, x = f.parent().gens()
        elif len(f.parent().gens()) == 2 or len(f.parent().gens()) == 3 and f.is_homogeneous():
            # We'd need a point too...
            raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented."
        else:
            raise ValueError, "Defining polynomial must be a cubic polynomial in two variables."

        try:
            if f.coefficient(x**3) < 0:
                f = -f
            # is there a nicer way to extract the coefficients?
            a1 = a2 = a3 = a4 = a6 = 0
            for coeff, mon in f:
                if mon == x**3:
                    assert coeff == 1
                elif mon == x**2:
                    a2 = coeff
                elif mon == x:
                    a4 = coeff
                elif mon == 1:
                    a6 = coeff
                elif mon == y**2:
                    assert coeff == -1
                elif mon == x*y:
                    a1 = -coeff
                elif mon == y:
                    a3 = -coeff
                else:
                    assert False
            return EllipticCurve([a1, a2, a3, a4, a6])
        except AssertionError:
            raise NotImplementedError, "Construction of an elliptic curve from a generic cubic not yet implemented."
    
    if rings.is_Ring(x):
        if rings.is_RationalField(x):
            return ell_rational_field.EllipticCurve_rational_field(x, y)
        elif rings.is_FiniteField(x) or (rings.is_IntegerModRing(x) and x.characteristic().is_prime()):
            return ell_finite_field.EllipticCurve_finite_field(x, y)
        elif rings.is_pAdicField(x):
            return ell_padic_field.EllipticCurve_padic_field(x, y)
        elif rings.is_NumberField(x):
            return ell_number_field.EllipticCurve_number_field(x, y)
        elif rings.is_Field(x):
            return ell_field.EllipticCurve_field(x, y)
        return ell_generic.EllipticCurve_generic(x, y)

    if isinstance(x, unicode):
        x = str(x)
        
    if isinstance(x, str):
        return ell_rational_field.EllipticCurve_rational_field(x)
        
    if rings.is_RingElement(x) and y is None:
        from sage.misc.misc import deprecation
        deprecation("'EllipticCurve(j)' is deprecated; use 'EllipticCurve_from_j(j)' or 'EllipticCurve(j=j)' instead.")
        # Fixed for all characteristics and cases by John Cremona
        j=x
        F=j.parent().fraction_field()
        char=F.characteristic()
        if char==2:
            if j==0:
                return EllipticCurve(F, [ 0, 0, 1, 0, 0 ])
            else:
                return EllipticCurve(F, [ 1, 0, 0, 0, 1/j ])
        if char==3:
            if j==0:
                return EllipticCurve(F, [ 0, 0, 0, 1, 0 ])
            else:
                return EllipticCurve(F, [ 0, j, 0, 0, -j**2 ])
        if j == 0:
            return EllipticCurve(F, [ 0, 0, 0, 0, 1 ])
        if j == 1728:
            return EllipticCurve(F, [ 0, 0, 0, 1, 0 ])
        k=j-1728
        return EllipticCurve(F, [0,0,0,-3*j*k, -2*j*k**2])

    if not isinstance(x,list):
        raise TypeError, "invalid input to EllipticCurve constructor"

    x = Sequence(x)
    if not (len(x) in [2,5]):
        raise ValueError, "sequence of coefficients must have length 2 or 5"
    R = x.universe()

    if isinstance(x[0], (rings.Rational, rings.Integer, int, long)):
        return ell_rational_field.EllipticCurve_rational_field(x, y)

    elif rings.is_NumberField(R):
        return ell_number_field.EllipticCurve_number_field(x, y)

    elif rings.is_pAdicField(R):
        return ell_padic_field.EllipticCurve_padic_field(x, y)
    
    elif rings.is_FiniteField(R) or (rings.is_IntegerModRing(R) and R.characteristic().is_prime()):
        return ell_finite_field.EllipticCurve_finite_field(x, y)

    elif rings.is_Field(R):
        return ell_field.EllipticCurve_field(x, y)

    return ell_generic.EllipticCurve_generic(x, y)