# HG changeset patch
# User Craig Citro <craigcitro@gmail.com>
# Date 1264015449 28800
# Node ID b8bd60b9d5c825902b1227447d241e04f6eae515
# Parent  212756566252363b6fde0689605629575f4ffbaf
Patch for trac #7262 -- first step in making E.multiplication_by_m return an isogeny.

diff -r 212756566252 -r b8bd60b9d5c8 sage/schemes/elliptic_curves/ell_curve_isogeny.py
--- a/sage/schemes/elliptic_curves/ell_curve_isogeny.py	Thu Jan 14 11:41:30 2010 -0800
+++ b/sage/schemes/elliptic_curves/ell_curve_isogeny.py	Wed Jan 20 11:24:09 2010 -0800
@@ -1,11 +1,16 @@
 r"""
 Isogenies
 
-An isogeny `\varphi: E_1\to E_2` between two elliptic curves `E_1` and `E_2` is a morphism of curves that sends the 
-origin of `E_1` to the origin of `E_2`. Such a morphism is automatically a morphism of group schemes and the kernel is a finite subgroup scheme of `E_1`.
-Such a subscheme can either be given by a list of generators, which have to be torsion points, or by a polynomial in the coordinate `x` of the Weierstrass equation of `E_1`.
+An isogeny `\varphi: E_1\to E_2` between two elliptic curves `E_1` and
+`E_2` is a morphism of curves that sends the origin of `E_1` to the
+origin of `E_2`. Such a morphism is automatically a morphism of group
+schemes and the kernel is a finite subgroup scheme of `E_1`.  Such a
+subscheme can either be given by a list of generators, which have to
+be torsion points, or by a polynomial in the coordinate `x` of the
+Weierstrass equation of `E_1`.
 
-The usual way to create and work with isogenies is illustrated with the following example::
+The usual way to create and work with isogenies is illustrated with
+the following example::
     
     sage: k = GF(11)
     sage: E = EllipticCurve(k,[1,1])
@@ -21,7 +26,8 @@
     sage: phi.rational_maps()
     ((x^7 + 4*x^6 - 3*x^5 - 2*x^4 - 3*x^3 + 3*x^2 + x - 2)/(x^6 + 4*x^5 - 4*x^4 - 5*x^3 + 5*x^2), (x^9*y - 5*x^8*y - x^7*y + x^5*y - x^4*y - 5*x^3*y - 5*x^2*y - 2*x*y - 5*y)/(x^9 - 5*x^8 + 4*x^6 - 3*x^4 + 2*x^3))
 
-The functions directly accessible from an elliptic curve ``E`` over a field are ``isogeny`` and ``isogeny_codomain``.
+The functions directly accessible from an elliptic curve ``E`` over a
+field are ``isogeny`` and ``isogeny_codomain``.
 
 The most useful functions that apply to isogenies are
 
@@ -34,7 +40,8 @@
 
 .. Warning::
 
-   Only cyclic isogenies are implemented (except for [2]). Some algorithms may need the isogeny to be normalized.
+   Only cyclic isogenies are implemented (except for [2]). Some
+   algorithms may need the isogeny to be normalized.
 
 AUTHORS:
 
@@ -72,15 +79,19 @@
 from sage.sets.set import Set
 
 #
-# Private function for parsing input to determine the type of algorithm
+# Private function for parsing input to determine the type of
+# algorithm
 #
 def isogeny_determine_algorithm(E, kernel, codomain, degree, model):
     r"""
-    Helper function that allows the various isogeny functions to infer the algorithm type from the parameters passed in.
+    Helper function that allows the various isogeny functions to infer
+    the algorithm type from the parameters passed in.
 
-    If ``kernel`` is a list of points on the EllipticCurve `E`, then we assume the algorithm to use is Velu.
+    If ``kernel`` is a list of points on the EllipticCurve `E`, then
+    we assume the algorithm to use is Velu.
 
-    If ``kernel`` is a list of coefficients or a univariate polynomial we try to use the Kohel's algorithms.
+    If ``kernel`` is a list of coefficients or a univariate polynomial
+    we try to use the Kohel's algorithms.
 
     EXAMPLES:
 
@@ -129,13 +140,17 @@
 
     - ``E`` - The domain elliptic curve.
 
-    - ``kernel`` - Either a list of points in the kernel of the isogeny, or a kernel polynomial (specified as a either a univariate polynomial or a coefficient list.)
+    - ``kernel`` - Either a list of points in the kernel of the isogeny, or a
+                   kernel polynomial (specified as a either a univariate
+                   polynomial or a coefficient list.)
 
-    - ``degree`` - an integer, (default:``None``)  optionally specified degree of the kernel.
+    - ``degree`` - an integer, (default:``None``)  optionally specified degree
+                   of the kernel.
 
     OUTPUT:
 
-    (elliptic curve) the codomain of the separable normalized isogeny from this kernel
+    (elliptic curve) the codomain of the separable normalized isogeny
+    from this kernel
 
     EXAMPLES::
 
@@ -172,7 +187,7 @@
 
 def compute_codomain_formula(E, v, w):
     r"""
-    Given parameters `v` and `w` (as in velu / kohel / etc formulas)
+    Given parameters `v` and `w` (as in Velu / Kohel / etc formulas)
     computes the codomain curve.
 
     EXAMPLES:
@@ -201,7 +216,8 @@
 
 def compute_vw_kohel_even_deg1(x0, y0, a1, a2, a4):
     r"""
-    The formula for computing `v` and `w` using Kohel's formulas for isogenies of degree 2.
+    The formula for computing `v` and `w` using Kohel's formulas for
+    isogenies of degree 2.
 
     EXAMPLES:
 
@@ -228,7 +244,8 @@
 
 def compute_vw_kohel_even_deg3(b2,b4,s1,s2,s3):
     r"""
-    The formula for computing `v` and `w` using Kohel's formulas for isogenies of degree 3.
+    The formula for computing `v` and `w` using Kohel's formulas for
+    isogenies of degree 3.
 
     EXAMPLES:
 
@@ -283,8 +300,8 @@
 
 def compute_codomain_kohel(E, kernel, degree):
     r"""
-
-    This function computes the codomain from the kernel polynomial as per Kohel's formulas.
+    This function computes the codomain from the kernel polynomial as
+    per Kohel's formulas.
 
     EXAMPLES::
 
@@ -403,11 +420,13 @@
 def two_torsion_part(E, poly_ring, psi, degree):
     r"""
 
-    Returns the greatest common divisor of ``psi`` and the 2 torsion polynomial of `E`.
+    Returns the greatest common divisor of ``psi`` and the 2 torsion
+    polynomial of `E`.
 
     EXAMPLES:
     
-    Every function that computes the kernel polynomial via Kohel's formulas will call this function::
+    Every function that computes the kernel polynomial via Kohel's
+    formulas will call this function::
 
         sage: E = EllipticCurve(GF(19), [1,2,3,4,5])
         sage: R.<x> = GF(19)[]
@@ -442,35 +461,60 @@
     r"""
     Class Implementing Isogenies of Elliptic Curves
 
-    This class implements cyclic, separable, normalized isogenies of elliptic curves.
+    This class implements cyclic, separable, normalized isogenies of
+    elliptic curves.
 
-    Several different algorithms for computing isogenies are available.  These include:
+    Several different algorithms for computing isogenies are
+    available.  These include:
 
     - Velu's Formulas: Velu's original formulas for computing
-      isogenies.  This algorithm is selected by giving as the ``kernel`` parameter
-      a list of points which generate a finite subgroup.
+      isogenies.  This algorithm is selected by giving as the
+      ``kernel`` parameter a list of points which generate 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 (little endian)) which will define the kernel of the isogeny.
+    - 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
+      (little endian)) which will define the kernel of the isogeny.
   
     INPUT:
 
-    - ``E``         - an elliptic curve, the domain of the isogeny to initialize.
-    - ``kernel``    - a kernel, either a point in ``E``, a list of points in ``E``, a monic kernel polynomial, or ``None``.
-      If initiating from a domain/codomain, this must be set to None.
-    - ``codomain``  - an elliptic curve (default:``None``).  If ``kernel`` is ``None``, then this must be the codomain of a cyclic, separable, normalized isogeny, furthermore, ``degree`` must be the degree of the isogeny from ``E`` to ``codomain``. If ``kernel`` is not ``None``, then this must be isomorphic to the codomain of the cyclic normalized separable isogeny defined by ``kernel``, in this case, the isogeny is post composed with an isomorphism so that this parameter is the codomain.
+    - ``E``         - an elliptic curve, the domain of the isogeny to
+                      initialize.
+                      
+    - ``kernel``    - a kernel, either a point in ``E``, a list of points
+                      in ``E``, a monic kernel polynomial, or ``None``.
+                      If initializing from a domain/codomain, this must be
+                      set to None.
+                      
+    - ``codomain``  - an elliptic curve (default:``None``).  If ``kernel``
+                      is ``None``, then this must be the codomain of a cyclic,
+                      separable, normalized isogeny, furthermore, ``degree``
+                      must be the degree of the isogeny from ``E`` to
+                      ``codomain``. If ``kernel`` is not ``None``, then this
+                      must be isomorphic to the codomain of the cyclic normalized
+                      separable isogeny defined by ``kernel``, in this case, the
+                      isogeny is post composed with an isomorphism so that this
+                      parameter is the codomain.
+                      
     - ``degree``    - an integer (default:``None``).
-      If ``kernel`` is ``None``, then this is the degree of the isogeny from ``E`` to ``codomain``.
-      If ``kernel`` is not ``None``, then this is used to determine whether or not to skip a gcd 
-      of the kernel polynomial with the two torsion polynomial of ``E``.
-    - ``model``     - a string (default:``None``).  Only supported variable is ``minimal``, in which case if 
-      ``E`` is a curve over the rationals, then the codomain is set to be the unique global minimum model.
+                      If ``kernel`` is ``None``, then this is the degree of the
+                      isogeny from ``E`` to ``codomain``.
+                      If ``kernel`` is not ``None``, then this is used to determine
+                      whether or not to skip a gcd of the kernel polynomial with the
+                      two torsion polynomial of ``E``.
+                      
+    - ``model``     - a string (default:``None``).  Only supported variable is
+                      ``minimal``, in which case if ``E`` is a curve over the
+                      rationals, then the codomain is set to be the unique global
+                      minimum model.
+                      
     - ``check`` (default: ``True``) checks if the input is valid to define an isogeny
 
     EXAMPLES:
 
-    A simple example of creating an isogeny of a field of small characteristic::
+    A simple example of creating an isogeny of a field of small
+    characteristic::
 
         sage: E = EllipticCurve(GF(7), [0,0,0,1,0])
         sage: phi = EllipticCurveIsogeny(E, E((0,0)) ); phi
@@ -518,7 +562,8 @@
         sage: phi_k(P) == phi_v.codomain()(0)
         True
 
-    We can create an isogeny that has kernel equal to the full 2 torsion::
+    We can create an isogeny that has kernel equal to the full 2
+    torsion::
 
         sage: E = EllipticCurve(GF(3), [0,0,0,1,1])
         sage: ker_list = E.division_polynomial(2).list()
@@ -610,7 +655,8 @@
         sage: phi_k.is_separable()
         True
 
-    We can also do this same example over the number field defined by the irreducible two torsion polynomial of `E`::
+    We can also do this same example over the number field defined by
+    the irreducible two torsion polynomial of `E`::
 
         sage: E = EllipticCurve('11a1')
         sage: P_list = E.torsion_points()
@@ -640,7 +686,8 @@
         sage: phi_v.is_separable()
         True
 
-    The following example shows how to specify an isogeny from domain and codomain::
+    The following example shows how to specify an isogeny from domain
+    and codomain::
 
         sage: E = EllipticCurve('11a1')
         sage: R.<x> = QQ[]
@@ -655,15 +702,16 @@
         sage: phi_s.rational_maps() == phi.rational_maps()
         True
 
-    However only cyclic normalized isogenies can be constructed this way. So it won't find the
-    isogeny [3]::
+    However only cyclic normalized isogenies can be constructed this
+    way. So it won't find the isogeny [3]::
  
         sage: E.isogeny(None, codomain=E,degree=9)
         Traceback (most recent call last):
         ...
         ValueError: The two curves are not linked by a cyclic normalized isogeny of degree 9
 
-    Also the presumed isogeny between the domain and codomain must be normalized::
+    Also the presumed isogeny between the domain and codomain must be
+    normalized::
 
         sage: E2.isogeny(None,codomain=E,degree=5)
         Traceback (most recent call last):
@@ -674,7 +722,8 @@
         sage: phi.dual().is_normalized()
         False
 
-    Here an example of a construction of a endomorphisms with cyclic kernel on a cm-curve::
+    Here an example of a construction of a endomorphisms with cyclic
+    kernel on a CM-curve::
 
         sage: K.<i> = NumberField(x^2+1)
         sage: E = EllipticCurve(K, [1,0])
@@ -828,8 +877,9 @@
         if not is_EllipticCurve(E):
             raise ValueError, "E parameter must be an EllipticCurve."
 
-        if type(kernel) != type([1,1]) and kernel in E : # a single point was given, we put it in a list
-                                                    # the first condition assures that [1,1] is treated as x+1
+        if type(kernel) != type([1,1]) and kernel in E :
+            # a single point was given, we put it in a list
+            # the first condition assures that [1,1] is treated as x+1
             kernel = [kernel]
 
         # if the kernel is None and the codomain isn't
@@ -839,9 +889,9 @@
 
         self.__check = check
 
-        if (None == kernel) and (None != codomain):
+        if (kernel is None) and (codomain is not None):
 
-            if (None == degree):
+            if (degree is None):
                 raise ValueError, "If specifying isogeny by domain and codomain, degree parameter must be set."
 
             # save the domain/codomain: really used now (trac #7096)
@@ -865,10 +915,10 @@
 
         self.__setup_post_isomorphism(codomain, model)
 
-        if (None != pre_isom):
+        if (pre_isom is not None):
             self.set_pre_isomorphism(pre_isom)
 
-        if (None != post_isom):
+        if (post_isom is not None):
             self.__set_post_isomorphism(old_codomain, post_isom)   #(trac #7096)
 
         # Inheritance house keeping
@@ -880,7 +930,8 @@
 
     def __call__(self, P, output_base_ring=None):
         r"""
-        Function that implements the call-ability of elliptic curve isogenies.
+        Function that implements the call-ability of elliptic curve
+        isogenies.
 
         EXAMPLES::
         
@@ -929,7 +980,7 @@
             raise InputError, "Input point must be on the domain curve of this isogeny."
 
         # if there is a pre isomorphism, apply it
-        if (None != self.__pre_isomorphism):
+        if (self.__pre_isomorphism is not None):
             temp_xP = self.__prei_x_coord_ratl_map(x=xP, y=yP)
             temp_yP = self.__prei_y_coord_ratl_map(x=xP, y=yP)
             (xP, yP) = (temp_xP, temp_yP)
@@ -945,13 +996,13 @@
             return self.__E2(0)
 
         # if there is a post isomorphism, apply it
-        if (None != self.__post_isomorphism):
+        if (self.__post_isomorphism is not None):
             tempX = self.__posti_x_coord_ratl_map(x=outP[0], y=outP[1])
             tempY = self.__posti_y_coord_ratl_map(x=outP[0], y=outP[1])
             outP = [tempX, tempY]
 
         if change_output_ring:
-            if (None == output_base_ring):
+            if (output_base_ring is None):
                 output_base_ring = E_P.base_ring()
             outE2 = self.__E2.change_ring(output_base_ring)
         else:
@@ -963,14 +1014,29 @@
         return outE2.point([R(outP[0]), R(outP[1]), R(1)], check=False)
 
 
+    def __getitem__(self, i):
+        self.__initialize_rational_maps()
+        if (i < 0) or (i > 2):
+            raise IndexError
+
+        if i == 0:
+            return self.__X_coord_rational_map
+        else:
+            return self.__Y_coord_rational_map
+
+    def __iter__(self):
+        self.__initialize_rational_maps()
+        return iter((self.__X_coord_rational_map, self.__Y_coord_rational_map))
 
     def __hash__(self):
         r"""
         Function that implements the hash ability of Isogeny objects.
 
-        This hashes the underlying kernel polynomial so that equal isogeny objects have the same hash value.
-        Also, this hashes the base field, and domain and codomain curves as well, so that isogenies with
-        the same kernel polynomial (over different base fields / curves) hash to different values.
+        This hashes the underlying kernel polynomial so that equal
+        isogeny objects have the same hash value.  Also, this hashes
+        the base field, and domain and codomain curves as well, so
+        that isogenies with the same kernel polynomial (over different
+        base fields / curves) hash to different values.
 
         EXAMPLES::
 
@@ -991,12 +1057,12 @@
             
         """
 
-        if (None != self.__this_hash):
+        if (self.__this_hash is not None):
             return self.__this_hash
 
         ker_poly_list = self.__kernel_polynomial_list
 
-        if (None == ker_poly_list):
+        if (ker_poly_list is None):
             ker_poly_list = self.__init_kernel_polynomial()
 
         this_hash = 0
@@ -1017,7 +1083,8 @@
         r"""
         Function that implements comparisons between isogeny objects.
 
-        This function works by comparing the underlying kernel objects.
+        This function works by comparing the underlying kernel
+        objects.
 
         EXAMPLES::
 
@@ -1043,7 +1110,7 @@
         if (not isinstance(other, EllipticCurveIsogeny)):
             return -1
 
-        if (None == self.__kernel_polynomial):
+        if (self.__kernel_polynomial is None):
             self.__init_kernel_polynomial()
 
         return cmp(self.__kernel_polynomial, other.kernel_polynomial())
@@ -1051,8 +1118,9 @@
 
     def __neg__(self):
         r"""
-        Function to implement unary negation (-) operator on isogenies.
-        Returns a copy of this isogeny that has been negated.
+        Function to implement unary negation (-) operator on
+        isogenies. Returns a copy of this isogeny that has been
+        negated.
 
         EXAMPLES: 
 
@@ -1107,7 +1175,8 @@
 
     def _repr_(self):
         r"""
-        Special sage specific function that implement the functionality to display the isogeny self as a string.
+        Special sage specific function that implement the
+        functionality to display the isogeny self as a string.
 
         EXAMPLES::
 
@@ -1128,9 +1197,11 @@
 
     def _latex_(self):
         r"""
-        Special sage specific function that implements functionality to display an isogeny object as a latex string.
+        Special sage specific function that implements functionality
+        to display an isogeny object as a latex string.
 
-        This function returns a latex string representing the isogeny self as the `x` and `y` coordinate rational functions.
+        This function returns a latex string representing the isogeny
+        self as the `x` and `y` coordinate rational functions.
 
         EXAMPLES::
 
@@ -1158,7 +1229,8 @@
     # delete the hash value
     def __clear_cached_values(self):
         r"""
-        A private function to clear the hash if the codomain has been modified by a pre or post isomorphism.
+        A private function to clear the hash if the codomain has been
+        modified by a pre or post isomorphism.
 
         EXAMPLES::
 
@@ -1207,11 +1279,13 @@
     # performs the inheritance house keeping
     def __perform_inheritance_housekeeping(self):
         r"""
-        Internal helper function, sets values on the super classes of this class.
+        Internal helper function, sets values on the super classes of
+        this class.
         
         EXAMPLES:
 
-        The following examples will implicitly exercise this function::
+        The following examples will implicitly exercise this
+        function::
 
             sage: E = EllipticCurve(GF(43), [2,3,5,7,11])
             sage: R.<x> = GF(43)[]; f = x + 42
@@ -1241,7 +1315,8 @@
     # initializes the base field
     def __init_algebraic_structs(self, E):
         r"""
-        An internal function for EllipticCurveIsogeny objects that sets up the member variables necessary for algebra.
+        An internal function for EllipticCurveIsogeny objects that
+        sets up the member variables necessary for algebra.
 
         EXAMPLES:
 
@@ -1308,9 +1383,14 @@
 
 
     # initializes the rational maps fields
-    def __initialize_rational_maps(self):
+    def __initialize_rational_maps(self, precomputed_maps=None):
         r"""
-        Private function that computes and initializes the rational maps.
+        Private function that computes and initializes the rational
+        maps.
+
+        INPUT:
+
+        - ``
 
         EXAMPLES:
 
@@ -1334,19 +1414,22 @@
         if (self.__rational_maps_initialized):
             return
 
-        if ("velu"==self.__algorithm):
-            (X_map, Y_map) = self.__initialize_rational_maps_via_velu()
-        if ("kohel"==self.__algorithm):
-            (X_map, Y_map) = self.__initialize_rational_maps_via_kohel()
+        if precomputed_maps is None:
+            if ("velu"==self.__algorithm):
+                (X_map, Y_map) = self.__initialize_rational_maps_via_velu()
+            if ("kohel"==self.__algorithm):
+                (X_map, Y_map) = self.__initialize_rational_maps_via_kohel()
+        else:
+            X_map, Y_map = precomputed_maps
 
-        if (None != self.__prei_x_coord_ratl_map):
+        if (self.__prei_x_coord_ratl_map is not None):
             prei_X_map = self.__prei_x_coord_ratl_map
             prei_Y_map = self.__prei_y_coord_ratl_map
 
             X_map = X_map.subs(x=prei_X_map, y=prei_Y_map)
             Y_map = Y_map.subs(x=prei_X_map, y=prei_Y_map)
 
-        if (None != self.__posti_x_coord_ratl_map):
+        if (self.__posti_x_coord_ratl_map is not None):
             X_map = self.__posti_x_coord_ratl_map.subs(x=X_map, y=Y_map)
             Y_map = self.__posti_y_coord_ratl_map.subs(x=X_map, y=Y_map)
 
@@ -1360,8 +1443,8 @@
 
     def __init_kernel_polynomial(self):
         r"""
-        Private function that initializes the kernel polynomial
-        (if the algorithm does not take it as a parameter.)
+        Private function that initializes the kernel polynomial (if
+        the algorithm does not take it as a parameter.)
 
         EXAMPLES:
 
@@ -1376,7 +1459,7 @@
             
         """
 
-        if (None != self.__kernel_polynomial_list):
+        if (self.__kernel_polynomial_list is not None):
             return self.__kernel_polynomial_list
 
         if ("velu" == self.__algorithm):
@@ -1389,7 +1472,8 @@
 
     def __set_pre_isomorphism(self, domain, isomorphism):
         r"""
-        Private function to set the pre isomorphism and domain (and keep track of the domain of the isogeny.)
+        Private function to set the pre isomorphism and domain (and
+        keep track of the domain of the isogeny.)
 
         EXAMPLES::
 
@@ -1422,7 +1506,7 @@
         self.__prei_x_coord_ratl_map = (x - r)/u**2
         self.__prei_y_coord_ratl_map = (y - s*(x-r) - t)/u**3
 
-        if (None != self.__kernel_polynomial):
+        if (self.__kernel_polynomial is not None):
             ker_poly = self.__kernel_polynomial
             ker_poly = ker_poly.subs(x=self.__prei_x_coord_ratl_map)
             kp_lc = ker_poly.univariate_polynomial().leading_coefficient()
@@ -1436,7 +1520,8 @@
 
     def __set_post_isomorphism(self, codomain, isomorphism):
         r"""
-        Private function to set the post isomorphism and codomain (and keep track of the codomain of the isogeny.)
+        Private function to set the post isomorphism and codomain (and
+        keep track of the codomain of the isogeny.)
 
         EXAMPLES:
 
@@ -1477,7 +1562,8 @@
 
     def __setup_post_isomorphism(self, codomain, model):
         r"""
-        Private function to set up the post isomorphism given the codomain.
+        Private function to set up the post isomorphism given the
+        codomain.
 
         EXAMPLES:
 
@@ -1514,9 +1600,9 @@
 
         oldE2 = self.__E2
 
-        if (None != model):
+        if (model is not None):
 
-            if (None != codomain):
+            if (codomain is not None):
                 raise ValueError, "Cannot specify a codomain and model flag simultaneously."
 
             if ('minimal' == model):
@@ -1530,7 +1616,7 @@
             else:
                 raise ValueError, "Unknown value of model flag."
 
-        elif (None != codomain):
+        elif (codomain is not None):
             if (not is_EllipticCurve(codomain)):
                 raise ValueError,  "Codomain parameter must be an elliptic curve."
 
@@ -1540,7 +1626,7 @@
             newE2 = codomain
             post_isom = oldE2.isomorphism_to(newE2) 
             
-        if (None != post_isom):
+        if (post_isom is not None):
             self.__set_post_isomorphism(newE2, post_isom)
 
         return
@@ -1556,7 +1642,8 @@
 
     def __init_from_kernel_list(self, kernel_gens):
         r"""
-        Private function that initializes the isogeny from a list of points which generate the kernel (For Velu's formulas.)
+        Private function that initializes the isogeny from a list of
+        points which generate the kernel (For Velu's formulas.)
 
         EXAMPLES:
 
@@ -1598,8 +1685,9 @@
     #
     def __sort_kernel_list(self):
         r"""
-        Private function that sorts the list of points in the kernel (For Velu's formulas.)
-        sorts out the 2 torsion points, and puts them in a dictionary.
+        Private function that sorts the list of points in the kernel
+        (For Velu's formulas). Sorts out the 2 torsion points, and
+        puts them in a dictionary.
 
         EXAMPLES:
 
@@ -1655,7 +1743,8 @@
     #
     def __compute_E2_via_velu(self):
         r"""
-        Private function that computes the codomain via Velu's formulas.
+        Private function that computes the codomain via Velu's
+        formulas.
 
         EXAMPLES:
 
@@ -1678,7 +1767,8 @@
 
     def __velu_sum_helper(self, Qvalues, a1, a3, x, y):
         r"""
-        Private function for Velu's formulas, helper function to help perform the summation.
+        Private function for Velu's formulas, helper function to help
+        perform the summation.
 
         EXAMPLES:
 
@@ -1728,8 +1818,9 @@
 
     def __compute_via_velu_numeric(self, xP, yP):
         r"""
-        Private function that sorts the list of points in the kernel (For Velu's formulas.)
-        sorts out the 2 torsion points, and puts them in a diction
+        Private function that sorts the list of points in the kernel
+        (for Velu's formulas). Sorts out the 2 torsion points, and
+        puts them in a diction
 
         EXAMPLES:
 
@@ -1761,7 +1852,8 @@
 
     def __compute_via_velu(self, xP, yP):
         r"""
-        Private function for Velu's formulas, to perform the summation.
+        Private function for Velu's formulas, to perform the
+        summation.
 
         EXAMPLES:
 
@@ -1838,7 +1930,8 @@
 
     def __init_kernel_polynomial_velu(self):
         r"""
-        Private function for Velu's formulas, helper function to initialize the rational maps.
+        Private function for Velu's formulas, helper function to
+        initialize the rational maps.
 
         EXAMPLES:
 
@@ -1859,7 +1952,7 @@
 
         invX = 0
 
-        if (None != self.__pre_isomorphism):
+        if (self.__pre_isomorphism is not None):
             pre_isom = self.__pre_isomorphism
             u = pre_isom.u
             r = pre_isom.r
@@ -1892,7 +1985,8 @@
 
     def __init_from_kernel_polynomial(self, kernel_polynomial, degree=None):
         r"""
-        Private function that initializes the isogeny from a kernel polynomial.
+        Private function that initializes the isogeny from a kernel
+        polynomial.
 
         EXAMPLES:
 
@@ -1976,8 +2070,8 @@
 
     def __init_even_kernel_polynomial(self, E, psi_G):
         r"""
-        Private function that initializes the isogeny from a kernel polynomial,
-        for Kohel's algorithm in the even degree case.
+        Private function that initializes the isogeny from a kernel
+        polynomial, for Kohel's algorithm in the even degree case.
 
         EXAMPLES:
 
@@ -2083,7 +2177,8 @@
 
     def __init_odd_kernel_polynomial(self, E, psi):
         r"""
-        Private function that initializes the isogeny from a kernel polynomial.
+        Private function that initializes the isogeny from a kernel
+        polynomial.
 
         EXAMPLES:
 
@@ -2116,7 +2211,6 @@
              3)
 
         """
-
         n = psi.degree()
         d = 2*n + 1
 
@@ -2170,8 +2264,9 @@
     #
     def __compute_omega_fast(self, E, psi, psi_pr, phi, phi_pr):
         r"""
-        Private function that initializes the omega polynomial (from Kohel's formulas)
-        in the case that the characteristic of the underlying field is not 2.
+        Private function that initializes the omega polynomial (from
+        Kohel's formulas) in the case that the characteristic of the
+        underlying field is not 2.
 
         EXAMPLES:
 
@@ -2213,8 +2308,9 @@
 
     def __compute_omega_general(self, E, psi, psi_pr, phi, phi_pr):
         r"""
-        Private function that initializes the omega polynomial (from Kohel's formulas)
-        in the case of general characteristic of the underlying field.
+        Private function that initializes the omega polynomial (from
+        Kohel's formulas) in the case of general characteristic of the
+        underlying field.
 
         EXAMPLES:
 
@@ -2295,7 +2391,8 @@
 
     def __compute_via_kohel_numeric(self, xP, yP):
         r"""
-        Private function that computes a numeric result of this isogeny (via Kohel's formulas.)
+        Private function that computes a numeric result of this
+        isogeny (via Kohel's formulas.)
 
         EXAMPLES:
 
@@ -2382,7 +2479,8 @@
 
     def __initialize_rational_maps_via_kohel(self):
         r"""
-        Private function that computes and initializes the rational maps of this isogeny.
+        Private function that computes and initializes the rational
+        maps of this isogeny.
 
         EXAMPLES:
 
@@ -2413,7 +2511,8 @@
     #
     def __compute_E2_via_kohel(self):
         r"""
-        Private function that computes and initializes the codomain of the isogeny (via Kohel's.)
+        Private function that computes and initializes the codomain of
+        the isogeny (via Kohel's.)
 
         EXAMPLES:
 
@@ -2528,9 +2627,11 @@
 
     def is_separable(self):
         r"""
-        This function returns a bool indicating whether or not this isogeny is separable.
+        This function returns a bool indicating whether or not this
+        isogeny is separable.
 
-        This function always returns ``True`` as currently this class only implements separable isogenies.
+        This function always returns ``True`` as currently this class
+        only implements separable isogenies.
 
         EXAMPLES::
 
@@ -2577,7 +2678,7 @@
 
 
         """
-        if(None == self.__kernel_polynomial):
+        if (self.__kernel_polynomial is None):
             self.__init_kernel_polynomial()
 
         return self.__kernel_polynomial.univariate_polynomial()
@@ -2585,7 +2686,8 @@
 
     def set_pre_isomorphism(self, preWI):
         r"""
-        Modifies this isogeny object to pre compose with the given Weierstrass isomorphism.
+        Modifies this isogeny object to pre compose with the given
+        Weierstrass isomorphism.
 
         EXAMPLES::
 
@@ -2650,7 +2752,7 @@
         if (self.__E1 != WIcod):
             raise ValueError, "Invalid parameter: isomorphism must have codomain curve equal to this isogenies' domain."
 
-        if (None == self.__pre_isomorphism):
+        if (self.__pre_isomorphism is None):
             isom = preWI
             domain = WIdom
         else:
@@ -2666,7 +2768,8 @@
 
     def set_post_isomorphism(self, postWI):
         r"""
-        Modifies this isogeny object to post compose with the given Weierstrass isomorphism.
+        Modifies this isogeny object to post compose with the given
+        Weierstrass isomorphism.
 
         EXAMPLES::
 
@@ -2713,7 +2816,7 @@
         if (self.__E2 != WIdom):
             raise ValueError, "Invalid parameter: isomorphism must have domain curve equal to this isogenies' codomain."
 
-        if (None == self.__post_isomorphism):
+        if (self.__post_isomorphism is None):
             isom = postWI
             codomain = WIcod
         else:
@@ -2729,8 +2832,8 @@
 
     def get_pre_isomorphism(self):
         r"""
-        Returns the pre-isomorphism of this isogeny.
-        If there has been no pre-isomorphism set, this returns ``None``.
+        Returns the pre-isomorphism of this isogeny.  If there has
+        been no pre-isomorphism set, this returns ``None``.
 
         EXAMPLES::
 
@@ -2764,8 +2867,8 @@
 
     def get_post_isomorphism(self):
         r"""
-        Returns the post-isomorphism of this isogeny.
-        If there has been no post-isomorphism set, this returns ``None``.
+        Returns the post-isomorphism of this isogeny.  If there has
+        been no post-isomorphism set, this returns ``None``.
 
         EXAMPLES::
 
@@ -2852,15 +2955,19 @@
 
     def is_normalized(self, via_formal=True, check_by_pullback=True):
         r"""
-        Returns ``True`` if this isogeny is normalized. An isogeny `\varphi\colon E\to E_2` between two given Weierstrass
-        equations is said to be normalized if the constant `c` is `1` in `\varphi*(\omega_2) = c\cdot\omega`, where `\omega` and `omega_2`
-        are the invariant differentials on `E` and `E_2` corresponding to the given equation.
+        Returns ``True`` if this isogeny is normalized. An isogeny
+        `\varphi\colon E\to E_2` between two given Weierstrass
+        equations is said to be normalized if the constant `c` is `1`
+        in `\varphi*(\omega_2) = c\cdot\omega`, where `\omega` and
+        `omega_2` are the invariant differentials on `E` and `E_2`
+        corresponding to the given equation.
 
         INPUT:
 
-        - ``via_formal`` - (default: ``True``) If ``True`` it simply checks if the leading
-          term of the formal series is 1. Otherwise it uses a deprecated algorithm
-          involving the second optional argument.
+        - ``via_formal`` - (default: ``True``) If ``True`` it simply checks if
+                           the leading term of the formal series is 1. Otherwise
+                           it uses a deprecated algorithm involving the second
+                           optional argument.
 
         - ``check_by_pullback`` -  (default:``True``) Deprecated.
 
@@ -2960,10 +3067,12 @@
             if (1 == inv_diff_quo):
                 f_normalized = True
             else:
-                # For some reason, in certain cases, when the isogeny is pre or post composed with a translation
-                # the resulting rational functions are too complicated for sage to simplify down to a constant
-                # in this case, we do some cheating by checking if the post-composition by isogeny has
-                # a non 1 scaling factor
+                # For some reason, in certain cases, when the isogeny
+                # is pre or post composed with a translation the
+                # resulting rational functions are too complicated for
+                # sage to simplify down to a constant in this case, we
+                # do some cheating by checking if the post-composition
+                # by isogeny has a non 1 scaling factor
                 if ( inv_diff_quo.numerator().is_constant() and (inv_diff_quo.denominator().is_constant) ):
                     f_normalized = False
                 else:
@@ -2971,16 +3080,17 @@
         else:
             check_prepost_isomorphism = True
         
-        #
-        # If we skip checking by the pullback of the invariant differential OR if that was inconclusive
-        # We explicitly check if there is a post isomorphism and if it has a non 1 scaling factor
-        # or if it is a just a translation.
-        # NOTE: This only works because we are using algorithms for calculating the isogenies that calculate 
-        # a separable normalized isogeny, if this changes, this check will no longer be correct.
+        # If we skip checking by the pullback of the invariant
+        # differential OR if that was inconclusive We explicitly check
+        # if there is a post isomorphism and if it has a non 1 scaling
+        # factor or if it is a just a translation.  NOTE: This only
+        # works because we are using algorithms for calculating the
+        # isogenies that calculate a separable normalized isogeny, if
+        # this changes, this check will no longer be correct.
         #
         if (check_prepost_isomorphism):
             post_isom = self.__post_isomorphism
-            if (None != post_isom):
+            if (post_isom is not None):
                 if (1 == self.__base_field(post_isom.u)):
                     f_post_normalized = True
                 else:
@@ -2989,7 +3099,7 @@
                 f_post_normalized = True
 
             pre_isom = self.__pre_isomorphism
-            if (None != pre_isom):
+            if (pre_isom is not None):
                 if (1 == self.__base_field(pre_isom.u)):
                     f_pre_normalized = True
                 else:
@@ -3003,9 +3113,11 @@
 
     def dual(self):
         r"""
-        Computes and returns the dual isogeny of this isogeny. If `\varphi\colon E \to E_2` is the given isogeny,
-        then the dual is by definition the unique isogeny `\hat\varphi\colon E_2\to E` such that the compositions
-        `\hat\varphi\circ\varphi` and `\varphi\circ\hat\varphi` are the multiplication `[n]` by the 
+        Computes and returns the dual isogeny of this isogeny. If
+        `\varphi\colon E \to E_2` is the given isogeny, then the dual
+        is by definition the unique isogeny `\hat\varphi\colon E_2\to
+        E` such that the compositions `\hat\varphi\circ\varphi` and
+        `\varphi\circ\hat\varphi` are the multiplication `[n]` by the
         degree of `\varphi` on `E` and `E_2` respectively.
 
         EXAMPLES::
@@ -3085,7 +3197,7 @@
         if (self.__base_field.characteristic() in [2,3]):
             raise NotImplemented
 
-        if (None != self.__dual):
+        if (self.__dual is not None):
             return self.__dual
        
         # trac 7096
@@ -3142,12 +3254,13 @@
 
     def formal(self,prec=20):
         r"""
-        Computes the formal isogeny as a power series in the variable `t=-x/y`
-        on the domain curve.
+        Computes the formal isogeny as a power series in the variable
+        `t=-x/y` on the domain curve.
 
         INPUT:
 
-        - ``prec``: (default = 20), the precision with which the computations in the formal group are carried out.
+        - ``prec`` - (default = 20), the precision with which the computations
+                     in the formal group are carried out.
         
         EXAMPLES::
         
@@ -3204,8 +3317,8 @@
 
     def is_injective(self):
         r"""
-        Method inherited from the morphism class.
-        Returns ``True`` if and only if this isogeny has trivial kernel.
+        Method inherited from the morphism class.  Returns ``True`` if
+        and only if this isogeny has trivial kernel.
 
         EXAMPLES::
 
@@ -3236,7 +3349,8 @@
 
     def is_surjective(self):
         r"""
-        For elliptic curve isogenies, always returns ``True`` (as a non-constant map of algebraic curves must be surjective).
+        For elliptic curve isogenies, always returns ``True`` (as a
+        non-constant map of algebraic curves must be surjective).
 
         EXAMPLES::
 
@@ -3313,7 +3427,8 @@
 
     def n(self):
         r"""
-        Numerical Approximation inherited from Map (through morphism), nonsensical for isogenies.
+        Numerical Approximation inherited from Map (through morphism),
+        nonsensical for isogenies.
 
         EXAMPLES::
 
@@ -3344,7 +3459,8 @@
 
     OUTPUT:
 
-    polynomial -- over the field of definition of ``E1``, ``E2``, that is the kernel polynomial of the isogeny from ``E1`` to ``E2``.
+    polynomial -- over the field of definition of ``E1``, ``E2``, that is the
+                  kernel polynomial of the isogeny from ``E1`` to ``E2``.
 
     ALGORITHM:
     
@@ -3506,9 +3622,9 @@
 
 def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="starks"):
     r"""
-    Computes the kernel polynomial of the degree ``ell`` isogeny between ``E1`` and ``E2``.
-    There must be a degree ``ell``, cyclic, separable, normalized isogeny from
-    ``E1`` to ``E2``.  
+    Computes the kernel polynomial of the degree ``ell`` isogeny
+    between ``E1`` and ``E2``.  There must be a degree ``ell``,
+    cyclic, separable, normalized isogeny from ``E1`` to ``E2``.
 
     INPUT:
 
@@ -3522,7 +3638,8 @@
 
     OUTPUT:
     
-    polynomial -- over the field of definition of ``E1``, ``E2``, that is the kernel polynomial of the isogeny from ``E1`` to ``E2``.
+    polynomial -- over the field of definition of ``E1``, ``E2``, that is the
+                  kernel polynomial of the isogeny from ``E1`` to ``E2``.
 
     EXAMPLES::
 
@@ -3561,7 +3678,8 @@
     Intermediate domain and intermediate codomain, are in short
     Weierstrass form.
     
-    This is used so we can compute `\wp` functions from the short Weierstrass model more easily.
+    This is used so we can compute `\wp` functions from the short
+    Weierstrass model more easily.
 
     The underlying field must be of characteristic not equal to 2,3.
 
@@ -3572,7 +3690,8 @@
 
     OUTPUT:
     
-    tuple -- (``pre_isomorphism``, ``post_isomorphism``, ``intermediate_domain``, ``intermediate_codomain``):
+    tuple -- (``pre_isomorphism``, ``post_isomorphism``, ``intermediate_domain``,
+              ``intermediate_codomain``):
     
     - ``intermediate_domain``: a short Weierstrass model isomorphic to ``E1``
     - ``intermediate_codomain``: a short Weierstrass model isomorphic to ``E2``
@@ -3652,7 +3771,10 @@
 
 def compute_sequence_of_maps(E1, E2, ell):
     r"""
-    Given domain ``E1`` and codomain ``E2`` such that there is a degree ``ell`` separable normalized isogeny from ``E1`` to ``E2``,    returns pre/post isomorphism, as well as intermediate domain and codomain, and kernel polynomial.
+    Given domain ``E1`` and codomain ``E2`` such that there is a
+    degree ``ell`` separable normalized isogeny from ``E1`` to ``E2``,
+    returns pre/post isomorphism, as well as intermediate domain and
+    codomain, and kernel polynomial.
 
     EXAMPLES::
 
diff -r 212756566252 -r b8bd60b9d5c8 sage/schemes/elliptic_curves/ell_field.py
--- a/sage/schemes/elliptic_curves/ell_field.py	Thu Jan 14 11:41:30 2010 -0800
+++ b/sage/schemes/elliptic_curves/ell_field.py	Wed Jan 20 11:24:09 2010 -0800
@@ -44,8 +44,8 @@
     - Quartic twist: only if `j=1728\not=0` (so not if char=2,3).
     - Sextic  twist: only if `j=0\not=1728` (so not if char=2,3).
     
-    More complicated twists exist in theory for char=2,3 and
-    j=0=1728, but are not implemented.
+    More complicated twists exist in theory for char=2,3 and j=0=1728,
+    but are not implemented.
     """
 
     def quadratic_twist(self, D=None):
@@ -56,19 +56,21 @@
 
         - ``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 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, `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)
+        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.
+        quadratic extension of `F` but not over `F` itself.  Over
+        infinite fields, an error is raised if `D` is not given.
 
         EXAMPLES::
         
@@ -267,7 +269,8 @@
         ``other`` is ``self.quadratic_twist(D)`` (up to isomorphism).
         If ``self`` and ``other`` are isomorphic, returns 1.
 
-        If the curves are defined over `\mathbb{Q}`, the output `D` is a squarefree integer.
+        If the curves are defined over `\mathbb{Q}`, the output `D` is
+        a squarefree integer.
 
         .. note::
 
@@ -549,24 +552,54 @@
         r"""
         Returns an elliptic curve isogeny from self.
  
-        The isogeny can be determined in two ways, either by a polynomial or a set of torsion points.
-        The methods used are:
+        The isogeny can be determined in two ways, either by a
+        polynomial or a set of torsion points.  The methods used are:
 
         - Velu's Formulas: Velu's original formulas for computing
-          isogenies.  This algorithm is selected by giving as the ``kernel`` parameter a point or a list of points which generate a finite subgroup.
+          isogenies.  This algorithm is selected by giving as the
+          ``kernel`` parameter a point or a list of points which
+          generate a finite subgroup.
 
-        - Kohel's Formulas:
-          Kohel's original formulas for computing isogenies.
-          This algorithm is selected by giving as the ``kernel`` parameter a polynomial (or a coefficient list (little endian)) which will define the kernel of the isogeny.
+        - Kohel's Formulas: Kohel's original formulas for computing
+          isogenies.  This algorithm is selected by giving as the
+          ``kernel`` parameter a polynomial (or a coefficient list
+          (little endian)) which will define the kernel of the
+          isogeny.
       
         INPUT:
 
-        - ``E``         - an elliptic curve, the domain of the isogeny to initialize.
-        - ``kernel``    - a kernel, either a point in ``E``, a list of points in ``E``, a univariate kernel polynomial or ``None``. If initiating from a domain/codomain, this must be set to None.
-        - ``codomain``  - an elliptic curve (default:None).  If ``kernel`` is None, then this must be the codomain of a separable normalized isogeny, furthermore, ``degree`` must be the degree of the isogeny from ``E`` to ``codomain``. If ``kernel`` is not None, then this must be isomorphic to the codomain of the normalized separable isogeny defined by ``kernel``, in this case, the isogeny is post composed with an isomorphism so that this parameter is the codomain.
-        - ``degree``    - an integer (default:None). If ``kernel`` is None, then this is the degree of the isogeny from ``E`` to ``codomain``. If ``kernel`` is not None, then this is used to determine whether or not to skip a gcd of the kernel polynomial with the two torsion polynomial of ``E``.
-        - ``model``     - a string (default:None).  Only supported variable is "minimal", in which case if``E`` is a curve over the rationals, then the codomain is set to be the unique global minimum model.
-        - ``check`` (default: True) checks if the input is valid to define an isogeny
+        - ``E``         - an elliptic curve, the domain of the isogeny to
+                          initialize.
+                          
+        - ``kernel``    - a kernel, either a point in ``E``, a list of points
+                          in ``E``, a univariate kernel polynomial or ``None``.
+                          If initiating from a domain/codomain, this must be
+                          set to None.
+                          
+        - ``codomain``  - an elliptic curve (default:None).  If ``kernel`` is
+                          None, then this must be the codomain of a separable
+                          normalized isogeny, furthermore, ``degree`` must be
+                          the degree of the isogeny from ``E`` to ``codomain``.
+                          If ``kernel`` is not None, then this must be
+                          isomorphic to the codomain of the normalized separable
+                          isogeny defined by ``kernel``, in this case, the
+                          isogeny is post composed with an isomorphism so that
+                          this parameter is the codomain.
+                          
+        - ``degree``    - an integer (default:None). If ``kernel`` is None, 
+                          then this is the degree of the isogeny from ``E`` to
+                          ``codomain``. If ``kernel`` is not None, then this is
+                          used to determine whether or not to skip a gcd of the
+                          kernel polynomial with the two torsion polynomial of
+                          ``E``.
+        
+        - ``model``     - a string (default:None).  Only supported variable is
+                          "minimal", in which case if``E`` is a curve over the
+                          rationals, then the codomain is set to be the unique
+                          global minimum model.
+        
+        - ``check`` (default: True) checks if the input is valid to define an
+                          isogeny
 
         OUTPUT:
 
@@ -609,18 +642,22 @@
 
     def isogeny_codomain(self, kernel, degree=None):
         r"""
-        Returns the codomain of the isogeny from self with given kernel.
+        Returns 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 a either a univariate polynomial or a coefficient list.)
+        - ``kernel`` - Either a list of points in the kernel of the isogeny,
+                       or a kernel polynomial (specified as a either a
+                       univariate polynomial or a coefficient list.)
 
-        - ``degree`` - an integer, (default:None) optionally specified degree of the kernel.
+        - ``degree`` - an integer, (default:None) optionally specified degree
+                       of the kernel.
 
         OUTPUT:
 
-        An elliptic curve, the codomain of the separable normalized isogeny from   this kernel
-
+        An elliptic curve, the codomain of the separable normalized
+        isogeny from this kernel
 
         EXAMPLES::
 
@@ -638,12 +675,17 @@
         
         INPUT:
         
-        - ``mprec`` - precision 
-        - ``algorithm`` - string (default:``None``) an algorithm identifier indicating using the ``pari``, ``fast`` or ``quadratic`` algorithm. If the algorithm is ``None``, then this function determines the best algorithm to use.
+        - ``mprec`` - precision
+        
+        - ``algorithm`` - string (default:``None``) an algorithm identifier
+                      indicating using the ``pari``, ``fast`` or ``quadratic``
+                      algorithm. If the algorithm is ``None``, then this
+                      function determines the best algorithm to use.
 
         OUTPUT:
 
-        a Laurent series in one variable `z` with coefficients in the base field `k` of `E`.
+        a Laurent series in one variable `z` with coefficients in the
+        base field `k` of `E`.
 
         EXAMPLES::
 
diff -r 212756566252 -r b8bd60b9d5c8 sage/schemes/elliptic_curves/ell_generic.py
--- a/sage/schemes/elliptic_curves/ell_generic.py	Thu Jan 14 11:41:30 2010 -0800
+++ b/sage/schemes/elliptic_curves/ell_generic.py	Wed Jan 20 11:24:09 2010 -0800
@@ -2136,6 +2136,43 @@
 
         return mx, my
 
+    def multiplication_by_m_isogeny(self, m):
+        r"""
+        Return the ``EllipticCurveIsogeny`` object associated to the
+        multiplication-by-`m` map on self. The resulting isogeny will
+        have the associated rational maps (i.e. those returned by
+        `self.multiplication_by_m()`) already computed.
+
+        NOTE: This function is currently *much* slower than the
+        result of ``self.multiplication_by_m()``, because
+        constructing an isogeny precomputes a significant amount
+        of information. See trac tickets #7368 and #8014 for the
+        status of improving this situation.
+        
+        INPUT:        
+
+        -  ``m`` - a nonzero integer
+
+        OUTPUT:
+
+        - An ``EllipticCurveIsogeny`` object associated to the
+        multiplication-by-`m` map on self.
+
+        EXAMPLES::
+
+            sage: E = EllipticCurve('11a1')
+            sage: E.multiplication_by_m_isogeny(7)
+            Isogeny of degree 49 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 - 10*x - 20 over Rational Field
+            
+        """
+        mx, my = self.multiplication_by_m(m)
+
+        torsion_poly = self.torsion_polynomial(m).monic()
+        phi = self.isogeny(torsion_poly, codomain=self)
+        phi._EllipticCurveIsogeny__initialize_rational_maps(precomputed_maps=(mx, my))
+
+        return phi
+
     def isomorphism_to(self, other):
         """
         Given another weierstrass model ``other`` of self, return an
