Ticket #13100: trac13100-elliptic-rebased.patch

File trac13100-elliptic-rebased.patch, 7.7 KB (added by jhpalmieri, 7 years ago)
  • sage/schemes/elliptic_curves/constructor.py

    # HG changeset patch
    # User John Cremona <john.cremona@gmail.com>
    # Date 1339347560 -3600
    # Node ID d4dbb7c7c3ccb43799d25e9a875dfbe646f8d75f
    # Parent  a2757f0d701177bcde58f1ff1d115d9033d1845d
    #13100 -- enhancements to elliptic curve constructor
    
    diff --git a/sage/schemes/elliptic_curves/constructor.py b/sage/schemes/elliptic_curves/constructor.py
    a b from sage.symbolic.ring import SR 
    3232from sage.symbolic.expression import is_SymbolicEquation
    3333
    3434
    35 def EllipticCurve(x=None, y=None, j=None):
     35def EllipticCurve(x=None, y=None, j=None, minimal_twist=True):
    3636    r"""
    3737    There are several ways to construct an elliptic curve:
    3838   
    def EllipticCurve(x=None, y=None, j=None 
    5858      Note that addition need not be defined.
    5959   
    6060           
    61     - EllipticCurve(j): Return an elliptic curve with j-invariant
    62       `j`.  Warning: this is deprecated.  Use ``EllipticCurve_from_j(j)``
    63       or ``EllipticCurve(j=j)`` instead.         
     61    - EllipticCurve(j=j0) or EllipticCurve_from_j(j0): Return an
     62      elliptic curve with j-invariant `j0`.
    6463
    6564    In each case above where the input is a list of length 2 or 5, one
    6665    can instead give a 2 or 5-tuple instead.
    def EllipticCurve(x=None, y=None, j=None 
    146145        Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
    147146        2
    148147
    149     See trac #6657::   
     148    See trac #6657::
    150149
    151150        sage: EllipticCurve(GF(144169),j=1728)
    152151        Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169
    153152
     153    By default, when a rational value of `j` is given, the constructed
     154    curve is a minimal twist (minimal conductor for curves with that
     155    `j`-invariant).  This can be changed by setting the optional
     156    parameter ``minimal_twist``, which is True by default, to False::
     157
     158
     159        sage: EllipticCurve(j=100)
     160        Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
     161        sage: E =EllipticCurve(j=100); E
     162        Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
     163        sage: E.conductor()
     164        33129800
     165        sage: E.j_invariant()
     166        100
     167        sage: E =EllipticCurve(j=100, minimal_twist=False); E
     168        Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field
     169        sage: E.conductor()
     170        298168200
     171        sage: E.j_invariant()
     172        100
     173
     174    Without this option, constructing the curve could take a long time
     175    since both `j` and `j-1728` have to be factored to compute the
     176    minimal twist (see :trac:`13100`)::
     177
     178       sage: E = EllipticCurve_from_j(2^256+1,minimal_twist=False)
     179       sage: E.j_invariant() == 2^256+1
     180       True
    154181
    155182    TESTS::
    156    
     183
    157184        sage: R = ZZ['u', 'v']
    158185        sage: EllipticCurve(R, [1,1])
    159186        Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v
    def EllipticCurve(x=None, y=None, j=None 
    227254        sage: E = EllipticCurve([1..5])
    228255        sage: EllipticCurve(E.a_invariants())
    229256        Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
     257
     258    See :trac:`11773`::
     259
     260        sage: E = EllipticCurve()
     261        Traceback (most recent call last):
     262        ...
     263        TypeError: invalid input to EllipticCurve constructor
     264
    230265    """
    231266    import ell_generic, ell_field, ell_finite_field, ell_number_field, ell_rational_field, ell_padic_field  # here to avoid circular includes
    232267   
    def EllipticCurve(x=None, y=None, j=None 
    235270            if rings.is_Ring(x):
    236271                try:
    237272                    j = x(j)
    238                 except (ZeroDivisionError, ValueError, TypeError):                   
     273                except (ZeroDivisionError, ValueError, TypeError):
    239274                    raise ValueError, "First parameter must be a ring containing %s"%j
    240275            else:
    241276                raise ValueError, "First parameter (if present) must be a ring when j is specified"
    242         return EllipticCurve_from_j(j)
     277        return EllipticCurve_from_j(j, minimal_twist)
    243278
    244     assert x is not None
     279    if x is None:
     280        raise TypeError, "invalid input to EllipticCurve constructor"
    245281   
    246282    if is_SymbolicEquation(x):
    247283        x = x.lhs() - x.rhs()
    def EllipticCurve(x=None, y=None, j=None 
    304340
    305341    if isinstance(x, unicode):
    306342        x = str(x)
    307        
     343
    308344    if isinstance(x, str):
    309345        return ell_rational_field.EllipticCurve_rational_field(x)
    310        
     346
    311347    if rings.is_RingElement(x) and y is None:
    312         from sage.misc.superseded import deprecation
    313         deprecation(5673, "'EllipticCurve(j)' is deprecated; use 'EllipticCurve_from_j(j)' or 'EllipticCurve(j=j)' instead.")
    314         # Fixed for all characteristics and cases by John Cremona
    315         j=x
    316         F=j.parent().fraction_field()
    317         char=F.characteristic()
    318         if char==2:
    319             if j==0:
    320                 return EllipticCurve(F, [ 0, 0, 1, 0, 0 ])
    321             else:
    322                 return EllipticCurve(F, [ 1, 0, 0, 0, 1/j ])
    323         if char==3:
    324             if j==0:
    325                 return EllipticCurve(F, [ 0, 0, 0, 1, 0 ])
    326             else:
    327                 return EllipticCurve(F, [ 0, j, 0, 0, -j**2 ])
    328         if j == 0:
    329             return EllipticCurve(F, [ 0, 0, 0, 0, 1 ])
    330         if j == 1728:
    331             return EllipticCurve(F, [ 0, 0, 0, 1, 0 ])
    332         k=j-1728
    333         return EllipticCurve(F, [0,0,0,-3*j*k, -2*j*k**2])
     348        raise TypeError, "invalid input to EllipticCurve constructor"
    334349
    335350    if not isinstance(x, (list, tuple)):
    336351        raise TypeError, "invalid input to EllipticCurve constructor"
    def EllipticCurve_from_c4c6(c4, c6): 
    379394        K = K.fraction_field()
    380395    return EllipticCurve([-K(c4)/K(48), -K(c6)/K(864)])
    381396
    382 def EllipticCurve_from_j(j):
     397def EllipticCurve_from_j(j, minimal_twist=True):
    383398    """
    384399    Return an elliptic curve with given `j`-invariant.
    385400   
     401    INPUT:
     402
     403    - ``j`` -- an element of some field.
     404
     405    - ``minimal_twist`` (boolean, default True) -- If True and ``j`` is in `\QQ`, the curve returned is a
     406      minimal twist, i.e. has minimal conductor.  If `j` is not in `\QQ` this parameter is ignored.
     407
     408    OUTPUT:
     409
     410    (elliptic curve) An elliptic curve with `j`-invariant `j`.
     411
    386412    EXAMPLES::
    387413
    388414        sage: E = EllipticCurve_from_j(0); E; E.j_invariant(); E.label()
    def EllipticCurve_from_j(j): 
    399425        Elliptic Curve defined by y^2 + x*y = x^3 + 36*x + 3455 over Rational Field
    400426        1
    401427
     428     The ``minimal_twist`` parameter (ignored except over `\QQ` and
     429     True by default) controls whether or not a minimal twist is
     430     computed::
     431
     432        sage: EllipticCurve_from_j(100)
     433        Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
     434        sage: _.conductor()
     435        33129800
     436        sage: EllipticCurve_from_j(100, minimal_twist=False)
     437        Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field
     438        sage: _.conductor()
     439        298168200
     440
     441    Since computing the minimal twist requires factoring both `j` and
     442    `j-1728` the following example would take a long time without
     443    setting `minimal_twist` to False::
     444
     445       sage: E = EllipticCurve_from_j(2^256+1,minimal_twist=False)
     446       sage: E.j_invariant() == 2^256+1
     447       True
     448
    402449    """
    403450    try:
    404451        K = j.parent()
    def EllipticCurve_from_j(j): 
    428475        if j == 1728:
    429476            return EllipticCurve(K, [ 0, 0, 0, -1, 0 ]) # 32a2
    430477
     478        if not minimal_twist:
     479            k=j-1728
     480            return EllipticCurve(K, [0,0,0,-3*j*k, -2*j*k**2])
     481
    431482        n = j.numerator()
    432483        m = n-1728*j.denominator()
    433484        a4 = -3*n*m