# HG changeset patch
# User John Cremona <john.cremona@gmail.com>
# Date 1303483826 -3600
# Node ID 2053d9b1f2723b8b9ef48103582074c31584b0f9
# Parent  9418a12e694afd8af736d4892d1a66a7d6145641
#11220: implement CM j-invariants and orders for quadratic fields

diff -r 9418a12e694a -r 2053d9b1f272 sage/schemes/elliptic_curves/cm.py
--- a/sage/schemes/elliptic_curves/cm.py	Tue Apr 19 18:16:07 2011 +0000
+++ b/sage/schemes/elliptic_curves/cm.py	Fri Apr 22 15:50:26 2011 +0100
@@ -150,7 +150,7 @@
 
     INPUT:
     
-    - ``K`` -- a number field (currently only implemented for `K=\QQ`)
+    - ``K`` -- a number field (currently only implemented for `K` of degree at most 2)
 
     OUTPUT:
     
@@ -158,21 +158,31 @@
 
     .. note::
 
-       This is currently only implemented for the rationals.  David
-       Kohel has large tables for other fields, but they are not in
-       Sage yet.
+       This is currently only implemented for the rationals and
+       quadratic fields.  David Kohel has large tables for other
+       functions, but they are not in Sage yet.
 
     EXAMPLE::
     
         sage: cm_j_invariants(QQ)
         [0, 54000, -12288000, 1728, 287496, -3375, 16581375, 8000, -32768, -884736, -884736000, -147197952000, -262537412640768000]
 
-    ::
+    Over imaginary quadratic fields there are no more than over `QQ`::
     
-        sage: cm_j_invariants(QuadraticField(-1, 'i'))
+        sage: cm_j_invariants(QuadraticField(-1, 'i')) 
+        [0, 54000, -12288000, 1728, 287496, -3375, 16581375, 8000, -32768, -884736, -884736000, -147197952000, -262537412640768000]
+
+    Over real quadratic fields there may be more::
+    
+        sage: cm_j_invariants(QuadraticField(5, 'a'))  
+        [0, 54000, -12288000, 1728, 287496, -3375, 16581375, 8000, -32768, -884736, -884736000, -147197952000, -262537412640768000, 282880*a + 632000, -282880*a + 632000, 95178240*a + 212846400, -95178240*a + 212846400, 85995/2*a - 191025/2, -85995/2*a - 191025/2, 26378240*a - 58982400, -26378240*a - 58982400, 95673435586560*a - 213932305612800, -95673435586560*a - 213932305612800, 184068066743177379840*a - 411588709724712960000, -184068066743177379840*a - 411588709724712960000, 16554983445/2*a + 37018076625/2, -16554983445/2*a + 37018076625/2]
+
+    Over fields of higher degree this is not yet implemented::
+    
+        sage: K.<a> = NumberField(x^3-2)
+        sage: cm_j_invariants(K)                         
         Traceback (most recent call last):
-        ...
-        NotImplementedError: Enumeration of CM j-invariants over Number Field in i with defining polynomial x^2 + 1 not yet implemented
+        NotImplementedError: Enumeration of CM j-invariants over fields of degree 3 not yet implemented
 
     """
     if K == RationalField():
@@ -180,8 +190,14 @@
                                287496, -3375, 16581375, 8000, \
                                -32768,  -884736, -884736000,\
                                -147197952000, -262537412640768000]]
-    else:
-        raise NotImplementedError, "Enumeration of CM j-invariants over %s not yet implemented"%K
+    if K.degree()==2:
+        # list the discriminants of class number 2:
+        d2list = [-5,-6,-10,-13,-15,-22,-35,-37,-51,-58,-91,-115,-123,-187,-235,-267,-403,-427]
+        d2list = [d if d%4==1 else 4*d for d in d2list]
+        d2list = d2list + [-60] # the only non-maximal order of class number 2
+        return sum([hilbert_class_polynomial(D).roots(K,multiplicities=False) for D in d2list],cm_j_invariants(RationalField()))
+
+    raise NotImplementedError, "Enumeration of CM j-invariants over fields of degree %s not yet implemented"%K.degree()
 
 
 def cm_j_invariants_and_orders(K):
@@ -190,25 +206,36 @@
 
     INPUT:
 
-    - ``K`` -- a number field (currently only implemented for `K=\QQ`)
+    - ``K`` -- a number field (currently only implemented for `K` of degree at most 2)
 
     OUTPUT:
 
     (list) A list of 3-tuples `(D,f,j)` where `j` is a CM
-    `j`-invariant with quadratic fundamental discriminant `D` and
-    conductor `f`
+    `j`-invariant in `K` with quadratic fundamental discriminant `D`
+    and conductor `f`.
 
     EXAMPLE::
     
         sage: cm_j_invariants_and_orders(QQ)
         [(-3, 3, -12288000), (-3, 2, 54000), (-3, 1, 0), (-4, 2, 287496), (-4, 1, 1728), (-7, 2, 16581375), (-7, 1, -3375), (-8, 1, 8000), (-11, 1, -32768), (-19, 1, -884736), (-43, 1, -884736000), (-67, 1, -147197952000), (-163, 1, -262537412640768000)]
 
-    ::
+    Over an imaginary quadratic field there are no more than over `QQ`::
+
+        sage: cm_j_invariants_and_orders(QuadraticField(-1, 'i')) 
+        [(-3, 3, -12288000), (-3, 2, 54000), (-3, 1, 0), (-4, 2, 287496), (-4, 1, 1728), (-7, 2, 16581375), (-7, 1, -3375), (-8, 1, 8000), (-11, 1, -32768), (-19, 1, -884736), (-43, 1, -884736000), (-67, 1, -147197952000), (-163, 1, -262537412640768000)]
+
+    Over real quadratic fields there may be more::
+       
+        sage: cm_j_invariants_and_orders(QuadraticField(5,'a'))
+        [(-20, 1, 282880*a + 632000), (-24, 1, -282880*a + 632000), (-40, 1, 95178240*a + 212846400), (-52, 1, -95178240*a + 212846400), (-15, 1, 85995/2*a - 191025/2), (-88, 1, -85995/2*a - 191025/2), (-35, 1, 26378240*a - 58982400), (-148, 1, -26378240*a - 58982400), (-51, 1, 95673435586560*a - 213932305612800), (-232, 1, -95673435586560*a - 213932305612800), (-91, 1, 184068066743177379840*a - 411588709724712960000), (-115, 1, -184068066743177379840*a - 411588709724712960000), (-123, 1, 16554983445/2*a + 37018076625/2), (-187, 1, -16554983445/2*a + 37018076625/2), (-3, 3, -12288000), (-3, 2, 54000), (-3, 1, 0), (-4, 2, 287496), (-4, 1, 1728), (-7, 2, 16581375), (-7, 1, -3375), (-8, 1, 8000), (-11, 1, -32768), (-19, 1, -884736), (-43, 1, -884736000), (-67, 1, -147197952000), (-163, 1, -262537412640768000)]
+
+    Over fields of higher degree this is not yet implemented::
     
-        sage: cm_j_invariants_and_orders(QuadraticField(-1, 'i'))
+        sage: K.<a> = NumberField(x^3-2)
+        sage: cm_j_invariants_and_orders(K)                         
         Traceback (most recent call last):
-        ...
-        NotImplementedError: Enumeration of CM j-invariants over Number Field in i with defining polynomial x^2 + 1 not yet implemented
+        NotImplementedError: Enumeration of CM j-invariants over fields of degree 3 not yet implemented
+
 
     """
     if K == RationalField():
@@ -222,6 +249,15 @@
         T.sort()
         T.reverse()
         return T
-    else:
-        raise NotImplementedError, "Enumeration of CM j-invariants over %s not yet implemented"%K
 
+    if K.degree()==2:
+        # list the discriminants of class number 2:
+        dlist = [-5,-6,-10,-13,-15,-22,-35,-37,-51,-58,-91,-115,-123,-187,-235,-267,-403,-427]
+        dlist = [d if d%4==1 else 4*d for d in dlist]
+        d2list = dlist + [-60] # the only non-maximal order of class number 2
+        D2list = dlist + [-15]
+        flist = [1 for d in dlist] + [2]
+        return zip(D2list,flist,sum([hilbert_class_polynomial(D).roots(K,multiplicities=False) for D in d2list],[])) + cm_j_invariants_and_orders(RationalField())
+
+    raise NotImplementedError, "Enumeration of CM j-invariants over fields of degree %s not yet implemented"%K.degree()
+
