def __init__(self, E=None, urst=None, F=None):
        r""" 
        Constructor for WeierstrassIsomorphism class,

        INPUT:

        - ``E`` -- an EllipticCurve, or None (see below).

        - ``urst`` -- a 4-tuple `(u,r,s,t)`, or None (see below).

        - ``F`` -- an EllipticCurve, or None (see below).

        Given two Elliptic Curves ``E`` and ``F`` (represented by
        Weierstrass models as usual), and a transformation ``urst``
        from ``E`` to ``F``, construct an isomorphism from ``E`` to
        ``F``.  An exception is raised if ``urst(E)!=F``.  At most one
        of ``E``, ``F``, ``urst`` can be None.  If ``F==None`` then
        ``F`` is constructed as ``urst(E)``.  If ``E==None`` then
        ``E`` is constructed as ``urst^-1(F)``.  If ``urst==None``
        then an isomorphism from ``E`` to ``F`` is constructed if
        possible, and an exception is raised if they are not
        isomorphic.  Otherwise ``urst`` can be a tuple of length 4 or
        a object of type ``baseWI``.
        
        Users will not usually need to use this class directly, but instead use
        methods such as ``isomorphism`` of elliptic curves.   

        EXAMPLES::

            sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
            sage: WeierstrassIsomorphism(EllipticCurve([0,1,2,3,4]),(-1,2,3,4))
            Generic morphism:
            From: Abelian group of points on Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field
            To:   Abelian group of points on Elliptic Curve defined by y^2 - 6*x*y - 10*y = x^3 - 2*x^2 - 11*x - 2 over Rational Field
            Via:  (u,r,s,t) = (-1, 2, 3, 4)
            sage: E=EllipticCurve([0,1,2,3,4])
            sage: F=EllipticCurve(E.cremona_label())
            sage: WeierstrassIsomorphism(E,None,F)
            Generic morphism:
            From: Abelian group of points on Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field
            To:   Abelian group of points on Elliptic Curve defined by y^2  = x^3 + x^2 + 3*x + 5 over Rational Field
            Via:  (u,r,s,t) = (1, 0, 0, -1)
            sage: w=WeierstrassIsomorphism(None,(1,0,0,-1),F)
            sage: w._domain_curve==E
            True
        """
        from ell_generic import is_EllipticCurve

        if E != None:
            if not is_EllipticCurve(E):
                raise ValueError, "First argument must be an elliptic curve or None"
        if F != None:
            if not is_EllipticCurve(F):
                raise ValueError, "Third argument must be an elliptic curve or None"
        if urst != None:
            if len(urst) != 4:
                raise ValueError, "Second argument must be [u,r,s,t] or None"
        if len([par for par in [E, urst, F] if par != None]) < 2:
            raise ValueError, "At most 1 argument can be None"

        if F == None:  # easy case
            baseWI.__init__(self, *urst)
            F = EllipticCurve(baseWI.__call__(self, list(E.a_invariants())))
            Morphism.__init__(self, Hom(E(0).parent(), F(0).parent()))
            self._domain_curve = E
            self._codomain_curve = F
            return

        if E == None:  # easy case in reverse
            baseWI.__init__(self, *urst)
            inv_urst = baseWI.__invert__(self)
            E = EllipticCurve(baseWI.__call__(inv_urst,
                                              list(F.a_invariants())))
            Morphism.__init__(self, Hom(E(0).parent(), F(0).parent()))
            self._domain_curve = E
            self._codomain_curve = F
            return

        if urst == None:  # try to construct the morphism
            urst = isomorphisms(E, F, True)
            if urst == None:
                raise ValueError, "Elliptic curves not isomorphic."
            baseWI.__init__(self, *urst)
            Morphism.__init__(self, Hom(E(0).parent(), F(0).parent()))
            self._domain_curve = E
            self._codomain_curve = F
            return

        # none of the parameters is None:
        baseWI.__init__(self, *urst)
        if F != EllipticCurve(baseWI.__call__(self, list(E.a_invariants()))):
            raise ValueError, "second argument is not an isomorphism from first argument to third argument"
        else:
            Morphism.__init__(self, Hom(E(0).parent(), F(0).parent()))
            self._domain_curve = E
            self._codomain_curve = F
        return
    def __init__(self, E=None, urst=None, F=None):
        r"""
        Constructor for WeierstrassIsomorphism class,

        INPUT:

        - ``E`` -- an EllipticCurve, or None (see below).

        - ``urst`` -- a 4-tuple `(u,r,s,t)`, or None (see below).

        - ``F`` -- an EllipticCurve, or None (see below).

        Given two Elliptic Curves ``E`` and ``F`` (represented by
        Weierstrass models as usual), and a transformation ``urst``
        from ``E`` to ``F``, construct an isomorphism from ``E`` to
        ``F``.  An exception is raised if ``urst(E)!=F``.  At most one
        of ``E``, ``F``, ``urst`` can be None.  If ``F==None`` then
        ``F`` is constructed as ``urst(E)``.  If ``E==None`` then
        ``E`` is constructed as ``urst^-1(F)``.  If ``urst==None``
        then an isomorphism from ``E`` to ``F`` is constructed if
        possible, and an exception is raised if they are not
        isomorphic.  Otherwise ``urst`` can be a tuple of length 4 or
        a object of type ``baseWI``.

        Users will not usually need to use this class directly, but instead use
        methods such as ``isomorphism`` of elliptic curves.

        EXAMPLES::

            sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
            sage: WeierstrassIsomorphism(EllipticCurve([0,1,2,3,4]),(-1,2,3,4))
            Generic morphism:
            From: Abelian group of points on Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field
            To:   Abelian group of points on Elliptic Curve defined by y^2 - 6*x*y - 10*y = x^3 - 2*x^2 - 11*x - 2 over Rational Field
            Via:  (u,r,s,t) = (-1, 2, 3, 4)
            sage: E=EllipticCurve([0,1,2,3,4])
            sage: F=EllipticCurve(E.cremona_label())
            sage: WeierstrassIsomorphism(E,None,F)
            Generic morphism:
            From: Abelian group of points on Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field
            To:   Abelian group of points on Elliptic Curve defined by y^2  = x^3 + x^2 + 3*x + 5 over Rational Field
            Via:  (u,r,s,t) = (1, 0, 0, -1)
            sage: w=WeierstrassIsomorphism(None,(1,0,0,-1),F)
            sage: w._domain_curve==E
            True
        """
        from ell_generic import is_EllipticCurve

        if E!=None:
            if not is_EllipticCurve(E):
                raise ValueError("First argument must be an elliptic curve or None")
        if F!=None:
            if not is_EllipticCurve(F):
                raise ValueError("Third argument must be an elliptic curve or None")
        if urst!=None:
            if len(urst)!=4:
                raise ValueError("Second argument must be [u,r,s,t] or None")
        if len([par for par in [E,urst,F] if par!=None])<2:
            raise ValueError("At most 1 argument can be None")

        if F==None:  # easy case
            baseWI.__init__(self,*urst)
            F=EllipticCurve(baseWI.__call__(self,list(E.a_invariants())))
            Morphism.__init__(self, Hom(E(0).parent(), F(0).parent()))
            self._domain_curve = E
            self._codomain_curve = F
            return

        if E==None:  # easy case in reverse
            baseWI.__init__(self,*urst)
            inv_urst=baseWI.__invert__(self)
            E=EllipticCurve(baseWI.__call__(inv_urst,list(F.a_invariants())))
            Morphism.__init__(self, Hom(E(0).parent(), F(0).parent()))
            self._domain_curve = E
            self._codomain_curve = F
            return

        if urst==None: # try to construct the morphism
            urst=isomorphisms(E,F,True)
            if urst==None:
                raise ValueError("Elliptic curves not isomorphic.")
            baseWI.__init__(self, *urst)
            Morphism.__init__(self, Hom(E(0).parent(), F(0).parent()))
            self._domain_curve = E
            self._codomain_curve = F
            return


        # none of the parameters is None:
        baseWI.__init__(self,*urst)
        if F!=EllipticCurve(baseWI.__call__(self,list(E.a_invariants()))):
            raise ValueError("second argument is not an isomorphism from first argument to third argument")
        else:
            Morphism.__init__(self, Hom(E(0).parent(), F(0).parent()))
            self._domain_curve = E
            self._codomain_curve = F
        return
def isomorphisms(E, F, JustOne=False):
    r"""
    Returns one or all isomorphisms between two elliptic curves.

    INPUT:

    - ``E``, ``F`` (EllipticCurve) -- Two elliptic curves.

    - ``JustOne`` (bool) If True, returns one isomorphism, or None if
      the curves are not isomorphic.  If False, returns a (possibly
      empty) list of isomorphisms.

    OUTPUT:

    Either None, or a 4-tuple `(u,r,s,t)` representing an isomorphism,
    or a list of these.

    .. note::
    
       This function is not intended for users, who should use the
       interface provided by ``ell_generic``.

    EXAMPLES::

        sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
        sage: isomorphisms(EllipticCurve_from_j(0),EllipticCurve('27a3'))
        [(-1, 0, 0, -1), (1, 0, 0, 0)]
        sage: isomorphisms(EllipticCurve_from_j(0),EllipticCurve('27a3'),JustOne=True)
        (1, 0, 0, 0)
        sage: isomorphisms(EllipticCurve_from_j(0),EllipticCurve('27a1'))
        []
        sage: isomorphisms(EllipticCurve_from_j(0),EllipticCurve('27a1'),JustOne=True)
    """
    from ell_generic import is_EllipticCurve
    if not is_EllipticCurve(E) or not is_EllipticCurve(F):
        raise ValueError, "arguments are not elliptic curves"
    K = E.base_ring()
    #   if not K == F.base_ring(): return []
    j = E.j_invariant()
    if j != F.j_invariant():
        if JustOne: return None
        return []

    from sage.rings.all import PolynomialRing
    x = PolynomialRing(K, 'x').gen()

    a1E, a2E, a3E, a4E, a6E = E.ainvs()
    a1F, a2F, a3F, a4F, a6F = F.ainvs()

    char = K.characteristic()

    if char == 2:
        if j == 0:
            ulist = (x**3 - (a3E / a3F)).roots(multiplicities=False)
            ans = []
            for u in ulist:
                slist = (x**4 + a3E * x + (a2F**2 + a4F) * u**4 + a2E**2 +
                         a4E).roots(multiplicities=False)
                for s in slist:
                    r = s**2 + a2E + a2F * u**2
                    tlist = (x**2 + a3E * x + r**3 + a2E * r**2 + a4E * r +
                             a6E + a6F * u**6).roots(multiplicities=False)
                    for t in tlist:
                        if JustOne: return (u, r, s, t)
                        ans.append((u, r, s, t))
            if JustOne: return None
            ans.sort()
            return ans
        else:
            ans = []
            u = a1E / a1F
            r = (a3E + a3F * u**3) / a1E
            slist = [
                s[0]
                for s in (x**2 + a1E * x + (r + a2E + a2F * u**2)).roots()
            ]
            for s in slist:
                t = (a4E + a4F * u**4 + s * a3E + r * s * a1E + r**2)
                if JustOne: return (u, r, s, t)
                ans.append((u, r, s, t))
            if JustOne: return None
            ans.sort()
            return ans

    b2E, b4E, b6E, b8E = E.b_invariants()
    b2F, b4F, b6F, b8F = F.b_invariants()

    if char == 3:
        if j == 0:
            ulist = (x**4 - (b4E / b4F)).roots(multiplicities=False)
            ans = []
            for u in ulist:
                s = a1E - a1F * u
                t = a3E - a3F * u**3
                rlist = (x**3 - b4E * x +
                         (b6E - b6F * u**6)).roots(multiplicities=False)
                for r in rlist:
                    if JustOne: return (u, r, s, t + r * a1E)
                    ans.append((u, r, s, t + r * a1E))
            if JustOne: return None
            ans.sort()
            return ans
        else:
            ulist = (x**2 - (b2E / b2F)).roots(multiplicities=False)
            ans = []
            for u in ulist:
                r = (b4F * u**4 - b4E) / b2E
                s = (a1E - a1F * u)
                t = (a3E - a3F * u**3 + a1E * r)
                if JustOne: return (u, r, s, t)
                ans.append((u, r, s, t))
            if JustOne: return None
            ans.sort()
            return ans


# now char!=2,3:
    c4E, c6E = E.c_invariants()
    c4F, c6F = F.c_invariants()

    if j == 0:
        m, um = 6, c6E / c6F
    elif j == 1728:
        m, um = 4, c4E / c4F
    else:
        m, um = 2, (c6E * c4F) / (c6F * c4E)
    ulist = (x**m - um).roots(multiplicities=False)
    ans = []
    for u in ulist:
        s = (a1F * u - a1E) / 2
        r = (a2F * u**2 + a1E * s + s**2 - a2E) / 3
        t = (a3F * u**3 - a1E * r - a3E) / 2
        if JustOne: return (u, r, s, t)
        ans.append((u, r, s, t))
    if JustOne: return None
    ans.sort()
    return ans
def isomorphisms(E,F,JustOne=False):
    r"""
    Returns one or all isomorphisms between two elliptic curves.

    INPUT:

    - ``E``, ``F`` (EllipticCurve) -- Two elliptic curves.

    - ``JustOne`` (bool) If True, returns one isomorphism, or None if
      the curves are not isomorphic.  If False, returns a (possibly
      empty) list of isomorphisms.

    OUTPUT:

    Either None, or a 4-tuple `(u,r,s,t)` representing an isomorphism,
    or a list of these.

    .. note::

       This function is not intended for users, who should use the
       interface provided by ``ell_generic``.

    EXAMPLES::

        sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
        sage: isomorphisms(EllipticCurve_from_j(0),EllipticCurve('27a3'))
        [(-1, 0, 0, -1), (1, 0, 0, 0)]
        sage: isomorphisms(EllipticCurve_from_j(0),EllipticCurve('27a3'),JustOne=True)
        (1, 0, 0, 0)
        sage: isomorphisms(EllipticCurve_from_j(0),EllipticCurve('27a1'))
        []
        sage: isomorphisms(EllipticCurve_from_j(0),EllipticCurve('27a1'),JustOne=True)
    """
    from ell_generic import is_EllipticCurve
    if not is_EllipticCurve(E) or not is_EllipticCurve(F):
        raise ValueError("arguments are not elliptic curves")
    K = E.base_ring()
#   if not K == F.base_ring(): return []
    j=E.j_invariant()
    if  j != F.j_invariant():
        if JustOne: return None
        return []

    from sage.rings.all import PolynomialRing
    x=PolynomialRing(K,'x').gen()

    a1E, a2E, a3E, a4E, a6E = E.ainvs()
    a1F, a2F, a3F, a4F, a6F = F.ainvs()

    char=K.characteristic()

    if char==2:
        if j==0:
            ulist=(x**3-(a3E/a3F)).roots(multiplicities=False)
            ans=[]
            for u in ulist:
                slist=(x**4+a3E*x+(a2F**2+a4F)*u**4+a2E**2+a4E).roots(multiplicities=False)
                for s in slist:
                    r=s**2+a2E+a2F*u**2
                    tlist= (x**2 + a3E*x + r**3 + a2E*r**2 + a4E*r + a6E + a6F*u**6).roots(multiplicities=False)
                    for t in tlist:
                        if JustOne: return (u,r,s,t)
                        ans.append((u,r,s,t))
            if JustOne: return None
            ans.sort()
            return ans
        else:
            ans=[]
            u=a1E/a1F
            r=(a3E+a3F*u**3)/a1E
            slist=[s[0] for s in (x**2+a1E*x+(r+a2E+a2F*u**2)).roots()]
            for s in slist:
                t = (a4E+a4F*u**4 + s*a3E + r*s*a1E + r**2)
                if JustOne: return (u,r,s,t)
                ans.append((u,r,s,t))
            if JustOne: return None
            ans.sort()
            return ans

    b2E, b4E, b6E, b8E      = E.b_invariants()
    b2F, b4F, b6F, b8F      = F.b_invariants()

    if char==3:
        if j==0:
            ulist=(x**4-(b4E/b4F)).roots(multiplicities=False)
            ans=[]
            for u in ulist:
                s=a1E-a1F*u
                t=a3E-a3F*u**3
                rlist=(x**3-b4E*x+(b6E-b6F*u**6)).roots(multiplicities=False)
                for r in rlist:
                    if JustOne: return (u,r,s,t+r*a1E)
                    ans.append((u,r,s,t+r*a1E))
            if JustOne: return None
            ans.sort()
            return ans
        else:
            ulist=(x**2-(b2E/b2F)).roots(multiplicities=False)
            ans=[]
            for u in ulist:
                r = (b4F*u**4 -b4E)/b2E
                s = (a1E-a1F*u)
                t = (a3E-a3F*u**3 + a1E*r)
                if JustOne: return (u,r,s,t)
                ans.append((u,r,s,t))
            if JustOne: return None
            ans.sort()
            return ans

# now char!=2,3:
    c4E,c6E = E.c_invariants()
    c4F,c6F = F.c_invariants()

    if j==0:
        m,um = 6,c6E/c6F
    elif j==1728:
        m,um=4,c4E/c4F
    else:
        m,um=2,(c6E*c4F)/(c6F*c4E)
    ulist=(x**m-um).roots(multiplicities=False)
    ans=[]
    for u in ulist:
        s = (a1F*u - a1E)/2
        r = (a2F*u**2 + a1E*s + s**2 - a2E)/3
        t = (a3F*u**3 - a1E*r - a3E)/2
        if JustOne: return (u,r,s,t)
        ans.append((u,r,s,t))
    if JustOne: return None
    ans.sort()
    return ans