Index: pull
===================================================================
--- pull	(revision 1282)
+++ pull	(revision 1282)
@@ -0,0 +1,1 @@
+hg pull ssh://was@sage.math.washington.edu/www/sage/hg/sage-main
Index: sage/functions/constants.py
===================================================================
--- sage/functions/constants.py	(revision 1097)
+++ sage/functions/constants.py	(revision 1283)
@@ -200,4 +200,7 @@
         return R.pi()
 
+    def _real_double_(self):
+        return sage.rings.all.RD.pi()
+
     def __abs__(self):
         if self.str()[0] != '-':
@@ -260,4 +263,7 @@
         return Integer(2)
 
+    def _real_double_(self):
+        return sage.rings.all.RD.e()
+
     # This just gives a string in singular anyways, and it's
     # *REALLY* slow!
@@ -284,4 +290,7 @@
     def _mpfr_(self,R):
         return R('NaN') #??? nan in mpfr: void mpfr_set_nan (mpfr_t x)
+
+    def _real_double_(self):
+        return sage.rings.all.RD.nan()
 
 NaN = NotANumber()
@@ -318,4 +327,12 @@
     def __float__(self):
         return float(0.5)*(float(1.0)+math.sqrt(float(5.0)))
+
+    def _real_double_(self):
+        """
+        EXAMPLES:
+            sage: RealDoubleField()(golden_ratio)
+            1.61803398874989484820458
+        """
+        return sage.rings.all.RDF(1.61803398874989484820458)
 
     def _mpfr_(self,R):  #is this OK for _mpfr_ ?
@@ -368,4 +385,12 @@
         return math.log(2) 
 
+    def _real_double_(self):
+        """
+        EXAMPLES:
+            sage: RealDoubleField()(log2)
+            0.69314718055994530941723212145817656808   # 64-bit
+        """
+        return sage.rings.all.RD.log2()
+
     def _mpfr_(self,R):
         return R.log2()
@@ -407,4 +432,12 @@
         return R.euler_constant()
 
+    def _real_double_(self):
+        """
+        EXAMPLES:
+            sage: RealDoubleField()(euler_gamma)
+            0.57721566490153287
+        """
+        return sage.rings.all.RD.euler()
+
     def floor(self):
         return Integer(0)
@@ -432,4 +465,20 @@
     def _mpfr_(self, R):  
         return R.catalan_constant() 
+
+    def _real_double_(self):
+        """
+        EXAMPLES:
+            sage: RealDoubleField()(catalan)
+            0.91596559417721901
+        """
+        return sage.rings.all.RDF(0.91596559417721901505460351493252)
+
+    def __float__(self):
+        """
+        EXAMPLES:
+            sage: float(catalan)
+            0.91596559417721901
+        """
+        return 0.91596559417721901505460351493252
 
     def floor(self):
@@ -470,4 +519,13 @@
         raise NotImplementedError, "Khinchin's constant only available up to %s bits"%self.__bits
 
+    def _real_double_(self):
+        """
+        EXAMPLES:
+            sage: RealDoubleField()(khinchin)
+            2.6854520010653064453
+        """
+	return sage.rings.all.RDF(2.685452001065306445309714835481795693820)
+
+
     def __float__(self): 
         return 2.685452001065306445309714835481795693820
@@ -512,4 +570,12 @@
         raise NotImplementedError, "Twin Prime constant only available up to %s bits"%self.__bits
 
+    def _real_double_(self):
+        """
+        EXAMPLES:
+            sage: RealDoubleField()(twinprime)
+            0.66016181584686962
+        """
+	return sage.rings.all.RDF(0.660161815846869573927812110014555778432)
+
     def __float__(self):
         """
@@ -565,4 +631,12 @@
         raise NotImplementedError, "Merten's constant only available up to %s bits"%self.__bits
 
+    def _real_double_(self):
+        """
+        EXAMPLES:
+            sage: RealDoubleField()(merten)
+            0.261497212847642783755426838608695859051
+        """
+        return sage.rings.all.RDF(0.261497212847642783755426838608695859051)
+
     def __float__(self):
         """
@@ -620,4 +694,12 @@
         raise NotImplementedError, "Brun's constant only available up to %s bits"%self.__bits
 
+    def _real_double_(self):
+        """
+        EXAMPLES:
+            sage: RealDoubleField()(brun)
+            1.9021605831040
+        """
+        return sage.rings.all.RDF(1.9021605831040)
+
     def __float__(self):
         """
Index: sage/rings/all.py
===================================================================
--- sage/rings/all.py	(revision 1271)
+++ sage/rings/all.py	(revision 1283)
@@ -80,4 +80,6 @@
 Reals = RealField
 
+from real_double import RealDoubleField, RDF, RealDoubleElement
+
 # Complex numbers
 from complex_field import ComplexField, is_ComplexField, CC
Index: sage/rings/finite_field_element.py
===================================================================
--- sage/rings/finite_field_element.py	(revision 924)
+++ sage/rings/finite_field_element.py	(revision 1287)
@@ -141,4 +141,21 @@
         Return a square root of this finite field element in its
         finite field, if there is one.  Otherwise, raise a ValueError.
+
+        EXAMPLES:
+          sage: F = GF(7^2)
+          sage: F(2).square_root()
+          3
+          sage: F(3).square_root()
+          2*a + 6
+          sage: F(3).square_root()**2
+          3
+          sage: F(4).square_root()
+          2
+          sage: K = GF(7^3)
+          sage: K(3).square_root()
+          Traceback (most recent call last):
+          ...
+          ValueError: must be a perfect square.
+
         """
         R = polynomial_ring.PolynomialRing(self.parent())
@@ -146,5 +163,5 @@
         g = f.factor()
         if len(g) == 2 or g[0][1] == 2:
-            return -g[0][0]
+            return -g[0][0][0]
         raise ValueError, "must be a perfect square."
 
Index: sage/rings/real_double.pyx
===================================================================
--- sage/rings/real_double.pyx	(revision 1283)
+++ sage/rings/real_double.pyx	(revision 1283)
@@ -0,0 +1,1116 @@
+include '../ext/cdefs.pxi'
+include '../ext/interrupt.pxi'
+include '../gsl/gsl.pxi'
+
+import operator
+
+from sage.misc.sage_eval import sage_eval
+
+cimport sage.ext.element
+import sage.ext.element
+
+cimport sage.ext.ring
+import sage.ext.ring
+
+import sage.misc.functional
+#import real_number
+
+
+cdef class RealDoubleField_class(sage.ext.ring.Field):
+    """
+    The field of real double precision numbers.
+
+    ALGORITHM: Arithmetic is done through pyrex.
+    """
+
+    def __cmp__(self, other):
+        """
+        Returns True if and only if other is the unique real double field.
+
+        EXAMPLES:
+            sage: RR == RDF
+            False
+            sage: RDF == RealDoubleField     # RDF is the shorthand
+            True
+        """
+        if other is RealDoubleField:
+            return 0
+        return -1
+
+    def __repr__(self):
+        """
+        Print out this real double field.
+
+        EXAMPLES:
+            sage: RealDoubleField
+            Real Double Field
+            sage: RDF
+            Real Double Field
+        """
+        return "Real Double Field"
+    
+    def __call__(self, x):
+        """
+        Create a real double using x.
+        
+        EXAMPLES:
+            sage: RDF(1)
+            1.0
+            sage: RDF(2/3)
+            0.666666666667
+
+        A TypeError is raised if the coercion doesn't make sense:
+            sage: RDF(QQ['x'].0)
+            Traceback (most recent call last):
+            ...
+            TypeError: cannot coerce nonconstant polynomial to float
+
+        One can convert back and forth between double precision real
+        numbers and higher-precision ones, though of course there may
+        be loss of precision:
+            sage: a = RealField(200)(2).sqrt(); a
+            1.4142135623730950488016887242096980785696718753769480731766796
+            sage: b = RDF(a); b
+            1.41421353817
+            sage: a.parent()(b)
+            1.4142135623700000000000000000000000000000000000000000000000002        
+        """
+        return RealDoubleElement(x)
+
+    def gen(self, n=0):
+        """
+        Return the generator of the real double field.
+        EXAMPLES:
+            sage: CDF.0
+            1.0
+            sage: CDF.gens()
+            (1.0,)
+        """
+        if n != 0:
+            raise ValueError, "only 1 generator"
+        return 1.0
+
+    def ngens(self):
+        return 1
+
+    def is_atomic_repr(self):
+        """
+        Returns True, to signify that elements of this field print
+        without sums, so parenthesis aren't required, e.g., in
+        coefficients of polynomials.
+
+        EXAMPLES:
+            sage: RealDoubleField().is_atomic_repr()
+            True
+        """
+        return True
+
+    def is_finite(self):
+        """
+        Returns False, since the field of real numbers is not finite.
+        Technical note:  There exists an upper bound on the double representation.
+        
+        EXAMPLES:
+            sage: RealDoubleField().is_finite()
+            False
+        """
+        return False
+
+    def characteristic(self):
+        """
+        Returns 0, since the field of real numbers has characteristic 0.
+
+        EXAMPLES:
+            sage: RealField(0).characteristic()
+            0
+        """
+        return 0
+    
+    def name(self):
+        return "RealDoubleField"
+    
+    def __hash__(self):
+        return hash(self.name())
+    
+    def pi(self):
+        """
+        Returns pi to double-precision.
+
+        EXAMPLES:
+            sage: R = RealField(100)
+            sage: RDF.pi()
+            3.14159265359
+            sage: RDF.pi().sqrt()/2
+            0.88622692545275801364908374167063
+        """
+        return self(M_PI)
+
+
+    def euler_constant(self):
+        """
+        Returns Euler's gamma constant to double precision
+
+        EXAMPLES:
+            sage: RDF.euler_constant()
+            0.577215664902
+        """
+        return self(M_EULER)
+
+    def log2(self):
+        """
+        Returns log(2) to the precision of this field.
+
+        EXAMPLES:
+            sage: RDF.log2() 
+            0.69314718056
+            sage: RDF(2).log()
+            0.69314718056
+        """
+        return self(M_LN2)
+
+    def factorial(self, int n):
+        """
+        Return the factorial of the integer n as a real number.
+        EXAMPLES:
+            sage: RDF.factorial(100)
+            9.33262154439e+157
+        """
+        if n < 0:
+            raise ArithmeticError, "n must be nonnegative"
+        return self(gsl_sf_fact(n))
+        
+    def zeta(self, n=2):
+        """
+        Return an $n$-th root of unity in the real field,
+        if one exists, or raise a ValueError otherwise.
+
+        EXAMPLES:
+            sage: RDF.zeta()
+            -1.0
+            sage: RDF.zeta(1)
+            1.0
+            sage: R.zeta(5)
+            Traceback (most recent call last):
+            ...
+            ValueError: No 5th root of unity in self
+        """
+        if n == 1:
+            return self(1)
+        elif n == 2:
+            return self(-1)
+        raise ValueError, "No %sth root of unity in self"%n
+
+
+
+
+
+cdef class RealDoubleElement(sage.ext.element.FieldElement):
+    cdef double _value
+    def __init__(self, x):
+        self._value = float(x)
+
+    def real(self):
+        """
+        Returns itself -- we're already real.
+
+        EXAMPLES:
+            sage: a = RDF(3)
+            sage: a.real()
+            3.0
+        """
+        return self
+
+    def imag(self):
+        """
+        Returns the imaginary part of this number.  (hint: it's zero.)
+
+        EXAMPLES:
+            sage: a = RDF(3)
+            sage: a.imag()
+            0.0
+        """
+        return 0
+
+    def __complex__(self):
+        """
+        EXAMPLES:
+            sage: a = 2303
+            sage: RDF(a)
+            2303.0
+            sage: complex(RDF(a))
+            (2303+0j)
+        """
+        return complex(self._value,0)
+
+    def parent(self):
+        """
+        Return the real double field, which is the parent of self.
+
+        EXAMPLES:
+            sage: a = RDF(2,3)
+            sage: a.parent()
+            Real Double Field
+            sage: parent(a)
+            Real Double Field            
+        """
+        return RDF
+    
+    def __repr__(self):
+        """
+        Return print version of self.
+
+        EXAMPLES:
+            sage: a = RDF(2); a
+            2.0
+            sage: a^2
+            4.0
+        """
+        return self.str()
+
+    def _latex_(self):
+        return self.str()
+
+    def __hash__(self):
+        return hash(self.str())
+
+    def _im_gens_(self, codomain, im_gens):
+        return codomain(self) # since 1 |--> 1
+
+    def str(self, no_sci=None):
+        if gsl_isnan(self._value):
+            return "nan"
+        else:
+            v = gsl_isinf(self._value)
+            if v == 1:
+                return "inf"
+            elif v == -1:
+                return "-inf"
+        if no_sci is not None and not no_sci:
+            return "%e"%self._value
+        else:
+            return str(self._value)
+
+    def copy(self):
+        cdef RealDoubleElement z
+        z = RealDoubleElement(self._value)
+        return z
+
+    def integer_part(self):
+        """
+        If in decimal this number is written n.defg, returns n.
+        """
+        return sage.rings.all.integer.Integer(int(self._value))
+
+
+    ########################
+    #   Basic Arithmetic
+    ########################
+    def _add_(RealDoubleElement self, RealDoubleElement other):
+        """
+        Add two real numbers with the same parent.
+        
+        EXAMPLES:
+            sage: R = RealDoubleField()
+            sage: R(-1.5) + R(2.5)
+            1.0
+        """
+        return RealDoubleElement(self._value + other._value)
+        
+    def __invert__(self):
+        """
+        Compute the multiplicative inverse of self.
+        
+        EXAMPLES:
+            sage: a = RDF(-1.5)*RDF(2.5)
+            sage: a.__invert__()
+            -0.266666666667
+        """
+        return RealDoubleElement(1/self._value)
+    
+    def _sub_(RealDoubleElement self, RealDoubleElement other):
+        """
+        Subtract two real numbers with the same parent.
+        
+        EXAMPLES:
+            sage: R = RealDoubleField()
+            sage: R(-1.5) - R(2.5)
+            -4.0
+        """
+        return RealDoubleElement(self._value - other._value)
+        
+    def _mul_(RealDoubleElement self, RealDoubleElement other):
+        """
+        Multiply two real numbers with the same parent.
+        
+        EXAMPLES:
+            sage: R = RealDoubleField()
+            sage: R(-1.5) * R(2.5)
+            -3.75
+        """
+        return RealDoubleElement(self._value * other._value)
+    
+    def __div_(RealDoubleElement self, RealDoubleElement other):
+        if not other:
+            raise ZeroDivisionError, "RealDoubleElement division by zero"
+        return RealDoubleElement(self._value / other._value)
+        
+    def __div__(x, y):
+        """
+        EXAMPLES:
+            sage: R = RealDoubleField()
+            sage: R(-1.5) / R(2.5)
+            -0.6
+        """
+        if isinstance(x, RealDoubleElement) and isinstance(y, RealDoubleElement):
+            return x.__div_(y)
+        return sage.rings.coerce.bin_op(x, y, operator.div)
+    
+    def __neg__(self):
+        return RealDoubleElement(-self._value)
+
+    def __pos__(self):
+        return self
+
+    def __abs__(self):
+        return self.abs()
+
+    cdef RealDoubleElement abs(RealDoubleElement self):
+        return RealDoubleElement(abs(self._value))
+
+    def __lshift__(x, y):
+        """
+        LShifting a double is not supported; nor is lshifting a RealDoubleElement.    
+        """
+        raise TypeError, "unsupported operand type(s) for <<: '%s' and '%s'"%(typeof(self), typeof(n))
+
+    def __rshift__(x, y):
+        """
+        RShifting a double is not supported; nor is rshifting a RealDoubleElement.
+        """
+        raise TypeError, "unsupported operand type(s) for >>: '%s' and '%s'"%(typeof(self), typeof(n))
+    
+    def multiplicative_order(self):
+        if self == 1:
+            return 1
+        elif self == -1:
+            return -1
+        return sage.rings.infinity.infinity
+
+    def sign(self):
+        """
+        Returns -1,0, or 1 if self is negative, zero, or positive; respectively.
+
+        Examples:
+            sage: RDF(-1.5).sign()
+            -1
+            sage: RDF(0).sign()
+            0
+            sage: RDF(2.5).sign()
+            1
+        """
+        if not self._value:
+            return 0
+        if self._value > 0:
+            return 1
+        return -1
+
+
+    ###################
+    # Rounding etc
+    ###################
+
+    def round(self):
+        """
+        Given real number x, rounds up if fractional part is greater than .5,
+        rounds down if fractional part is lesser than .5.
+        EXAMPLES:
+            sage: RDF(0.49).round()
+            0.0
+            sage: RDF(0.51).round()
+            1.0
+        """
+        return RealDoubleElement(round(self._value))
+
+    def floor(self):
+        """
+        Returns the floor of this number
+
+        EXAMPLES:
+            sage: RDF(2.99).floor()
+            2
+            sage: RDF(2.00).floor()
+            2
+            sage: RDF(-5/2).floor()
+            -3
+        """
+        return RealDoubleElement(sage.misc.functional.floor(self._value))
+
+    def ceil(self):
+        """
+        Returns the ceiling of this number
+
+        OUTPUT:
+            integer
+
+        EXAMPLES:
+            sage: RDF(2.99).ceil()
+            3.0
+            sage: RDF(2.00).ceil()
+            2.0
+            sage: RDF(-5/2).ceil()
+            -3.0
+        """
+        return RealDoubleElement(sage.misc.functional.ceil(self._value))
+
+    def ceiling(self):
+        return self.ceil()
+
+    def trunc(self):
+        """
+        Truncates this number (returns integer part).
+
+        EXAMPLES:
+            sage: RDF(2.99).trunc()
+            2.0
+            sage: RDF(-2.00).trunc()
+            -2.0
+            sage: RDF(0.00).trunc()
+            0.0
+        """
+        return RealDoubleElement(int(self._value))
+
+    def frac(self):
+        """
+        frac returns a real number > -1 and < 1. it satisfies the
+        relation:
+            x = x.trunc() + x.frac()
+
+        EXAMPLES:
+            sage: RDF(2.99).frac()
+            0.99
+            sage: RDF(2.50).frac()
+            0.5
+            sage: RDF(-2.79).frac()
+            -0.79
+        """
+        return RealDoubleElement(self._value - int(self._value))
+
+    ###########################################
+    # Conversions
+    ###########################################
+
+    def __float__(self):
+        return self._value
+    
+    def __int__(self):
+        """
+        Returns integer truncation of this real number.
+        """
+        return int(self._value)
+
+    def __long__(self):
+        """
+        Returns long integer truncation of this real number.
+        """
+        return long(self._value)
+
+    def _complex_number_(self):
+        return sage.rings.complex_field.ComplexField()(self)
+
+    def _complex_double_(self):
+         return sage.rings.complex_double.ComplexDoubleField(self)
+
+    def _pari_(self):
+        return sage.libs.pari.all.pari.new_with_bits_prec("%.15e"%self._value, 64)
+        
+
+    ###########################################
+    # Comparisons: ==, !=, <, <=, >, >=
+    ###########################################
+
+    def is_NaN(self):
+        return bool(gsl_isnan(self._value))
+
+    cdef int cmp(RealDoubleElement self, RealDoubleElement x):
+        return cmp(self._value, x._value)
+
+    def __cmp__(RealDoubleElement self, RealDoubleElement x):
+        return self.cmp(x)
+
+    def __richcmp__(RealDoubleElement self, x, int op):
+        cdef int n
+        if not isinstance(x, RealDoubleElement):
+            try:
+                x = RealDoubleElement(x)
+            except TypeError:
+                n = sage.rings.coerce.cmp(self, x)
+            else:
+                n = self.cmp(x)
+        else:
+            n = self.cmp(x)
+        if op == 0:
+            return bool(n < 0)
+        elif op == 1:
+            return bool(n <= 0)
+        elif op == 2:
+            return bool(n == 0)
+        elif op == 3:
+            return bool(n != 0)
+        elif op == 4:
+            return bool(n > 0)
+        elif op == 5:
+            return bool(n >= 0)
+    
+
+    ############################
+    # Special Functions
+    ############################
+
+    def sqrt(self):
+        """
+        Return a square root of self.
+
+        If self is negative a complex number is returned.
+
+        If you use self.square_root() then a real number will always
+        be returned (though it will be NaN if self is negative).
+
+        EXAMPLES:
+            sage: r = 4.0
+            sage: r.sqrt()
+            2.0000000000000000
+            sage: r.sqrt()^2 == r
+            True
+
+            sage: r = 4344
+            sage: r.sqrt()
+            65.909028213136324
+            sage: r.sqrt()^2 == r
+            True
+
+            sage: r = -2.0
+            sage: r.sqrt()
+            1.4142135623730951*I
+            """
+        if self >= 0:
+            return self.square_root()
+        return self._complex_double_().sqrt()
+        
+
+    def square_root(self):
+        """
+        Return a square root of self.  A real number will always be
+        returned (though it will be NaN if self is negative).
+
+        Use self.sqrt() to get a complex number if self is negative.
+
+        EXAMPLES:
+            sage: r = -2.0
+            sage: r.square_root()
+            NaN
+            sage: r.sqrt()
+            1.4142135623730951*I
+        """
+        return RealDoubleElement(sqrt(self._value))
+
+    def cube_root(self):
+        """
+        Return the cubic root (defined over the real numbers) of self.
+
+        EXAMPLES:
+            sage: r = RDF(125.0); r.cube_root()
+            5.0
+            sage: r = RDF(-119.0)
+            sage: r.cube_root()^3 - r       # illustrates precision loss
+            -0.000000000000014210854715202004
+        """
+        return self.nth_root(3)
+
+
+    def nth_root(self, int n):
+        """
+        Returns the n^{th} root of self.
+        EXAMPLES:
+            sage: r = RDF(-125.0); r.nth_root(3)
+            -5.0
+            sage: r.nth_root(5)
+            -2.6265278044
+        """
+        if n == 0:
+            return RealDoubleElement(float('nan'))
+        if self._value < 0 and GSL_IS_EVEN(n):
+            pass #return self._complex_double_().pow(1.0/n)
+        else:
+            return RealDoubleElement(self.__nth_root(n))
+
+    cdef double __nth_root(RealDoubleElement self, int n):
+        cdef int m
+        cdef double x
+        cdef double x0
+        cdef double dx
+        cdef double dx0
+        m  = n-1
+        x  = ( m + self._value ) / n
+        x0 = 0
+        dx = abs(x - x0)
+        dx0= dx + 1
+        while dx < dx0:
+            x0= x
+            dx0 = dx
+            x = ( m*x + self._value / gsl_pow_int(x,m) ) / n
+            dx=abs(x - x0)
+        return x
+
+    def __pow(self, RealDoubleElement exponent):
+        return RealDoubleElement(self._value**exponent._value)
+
+    def __pow_int(self, int exponent):
+        return RealDoubleElement(gsl_pow_int(self._value, exponent))
+
+    def __pow__(self, exponent, modulus):
+        """
+        Compute self raised to the power of exponent, rounded in
+        the direction specified by the parent of self.
+
+        If the result is not a real number, self and the exponent are
+        both coerced to complex numbers (with sufficient precision),
+        then the exponentiation is computed in the complex numbers.
+        Thus this function can return either a real or complex number.
+        
+        EXAMPLES:
+            sage: a = RDF('1.23456')
+            sage: a^20
+            67.646297455
+            sage: a^a
+            1.2971114814
+        """
+        cdef RealDoubleElement x
+        if isinstance(self, RealDoubleElement):
+            return self.__pow(RealDoubleElement(exponent))
+        if isinstance(exponent, (int,Integer)):
+            return self.__pow_int(int(exponent))
+        elif not isinstance(exponent, RealDoubleElement):
+            x = RealDoubleElement(exponent)
+        else:
+            x = exponent
+        return self.__pow(x)
+
+
+    def __log_(self, double log_of_base):
+        if self._value < 2:
+            if self._value == 0:
+                return -1./0
+            if self._value < 0:
+                return 0./0
+            return RealDoubleElement(gsl_sf_log_1plusx(self._value - 1) / log_of_base)
+        return RealDoubleElement(gsl_sf_log(self._value) / log_of_base)
+
+    def log(self, base='e'):
+        """
+        EXAMPLES:
+            sage: RDF(2).log()
+            0.69314718056
+            sage: RDF(2).log(2)
+            1.0
+            sage: RDF(2).log(pi)
+            0.605511561398
+            sage: RDF(2).log(10)
+            0.301029995664
+            sage: RDF(2).log(1.5)
+            1.70951129135
+            sage: RDF(0).log()
+            -inf
+            sage: RDF(-1).log()
+            nan
+        """
+        if base == 'e':
+            return self.__log_(1)
+        elif base == 'pi':
+            return self.logpi()
+        elif base == 2:
+            return self.log2()
+        elif base == 10:
+            return self.log10()
+        else:
+            if isinstance(base, RealDouble):
+                return self.__log_(base.__log_(1))
+            else:
+                return self.__log_(gsl_sf_log(float(base)))
+
+    def log2(self):
+        """
+        Returns log to the base 2 of self
+
+        EXAMPLES:
+            sage: r = RDF(16.0)
+            sage: r.log2()
+            4.0
+
+            sage: r = RDF(31.9); r.log2()
+            4.99548451888
+
+        """
+        return RealDoubleElement(gsl_sf_log(self._value) / M_LN2)
+
+
+    def log10(self):
+        """
+        Returns log to the base 10 of self
+
+        EXAMPLES:
+            sage: r = RDF(16.0); r.log10()
+            1.20411998266
+            sage: r.log() / log(10)
+            1.20411998266
+            sage: r = 39.9; r.log10()
+            1.60097289569
+        """
+        return RealDoubleElement(gsl_sf_log(self._value) / M_LN10)
+
+    def logpi(self):
+        """
+        Returns log to the base pi of self
+
+        EXAMPLES:
+            sage: r = 16.0; r.logpi()
+            1.20411998266
+            sage: r.log() / log(pi)
+            1.20411998266
+            sage: r = 39.9; r.logpi()
+            1.60097289569
+        """
+        return RealDoubleElement(gsl_sf_log(self._value) / M_LNPI)
+
+    def exp(self):
+        r"""
+        Returns $e^\code{self}$
+
+        EXAMPLES:
+            sage: r = RDF(0.0)
+            sage: r.exp()
+            1.0
+
+            sage: r = RDF(32.3)
+            sage: a = r.exp(); a
+            1.06588847275e+14
+            sage: a.log()
+            32.3
+
+            sage: r = RDF(-32.3)
+            sage: r.exp()
+            9.3818445885e-15
+        """
+        return RealDoubleElement(gsl_sf_exp(self._value))
+
+    def exp2(self):
+        """
+        Returns $2^\code{self}$
+
+        EXAMPLES:
+            sage: r = RDF(0.0)
+            sage: r.exp2()
+            1.0
+            
+            sage: r = RDF(32.0)
+            sage: r.exp2()
+            4294967296.0
+
+            sage: r = RDF(-32.3)
+            sage: r.exp2()
+            1.89117248253e-10
+
+        """
+        return RealDoubleElement(gsl_sf_exp(self._value * M_LN2))
+
+    def exp10(self):
+        r"""
+        Returns $10^\code{self}$
+
+        EXAMPLES:
+            sage: r = RDF(0.0)
+            sage: r.exp10()
+            1.0
+            
+            sage: r = RDF(32.0)
+            sage: r.exp10()
+            1e+32
+
+            sage: r = RDF(-32.3)
+            sage: r.exp10()
+            5.01187233627e-33
+        """
+        return RealDoubleElement(gsl_sf_exp(self._value * M_LN10))
+
+    def cos(self):
+        """
+        Returns the cosine of this number
+
+        EXAMPLES:
+            sage: t=RDF.pi()/2
+            sage: t.cos()
+            6.12323399574e-17
+        """
+        return RealDoubleElement(gsl_sf_cos(self._value))
+
+    def sin(self):
+        """
+        Returns the sine of this number
+        
+        EXAMPLES:
+            sage: RDF(2).sin()
+            0.909297426826
+        """
+        return RealDoubleElement(gsl_sf_sin(self._value))
+    
+    def tan(self):
+        """
+        Returns the tangent of this number
+        
+        EXAMPLES:
+            sage: q = RDF.pi()/3
+            sage: q.tan()
+            1.73205080757
+            sage: q = RDF.pi()/6
+            sage: q.tan()
+            0.57735026919
+        """
+        return RealDoubleElement(tan(self._value))
+
+    def sincos(self):
+        """
+        Returns a pair consisting of the sine and cosine.
+
+        EXAMPLES:
+            sage: t = RDF.pi()/6
+            sage: t.sincos()
+            (0.5, 0.866025403784)
+        """
+        return self.sin(), self.cos()
+
+    def hypot(self, other):
+        return RealDoubleElement(gsl_sf_hypot(self._value, float(other)))
+
+    def acos(self):
+        """
+        Returns the inverse cosine of this number
+
+        EXAMPLES:
+            sage: q = RDF.pi()/3
+            sage: i = q.cos()
+            sage: i.acos() == q
+            True
+        """
+        return RealDoubleElement(acos(self._value))
+
+    def asin(self):
+        """
+        Returns the inverse sine of this number
+
+        EXAMPLES:
+            sage: q = RDF.pi()/5
+            sage: i = q.sin()
+            sage: i.asin() == q
+            True
+        """
+        return RealDoubleElement(asin(self._value))
+
+    def atan(self):
+        """
+        Returns the inverse tangent of this number
+
+        EXAMPLES:
+            sage: q = RDF.pi()/5
+            sage: i = q.tan()
+            sage: i.atan() == q
+            True
+        """
+        return RealDoubleElement(atan(self._value))
+
+
+    def cosh(self):
+        """
+        Returns the hyperbolic cosine of this number
+
+        EXAMPLES:
+            sage: q = RDF.pi()/12
+            sage: q.cosh()
+            1.0344656401
+        """
+        return RealDoubleElement(cosh(self._value))
+
+    def sinh(self):
+        """
+        Returns the hyperbolic sine of this number
+
+        EXAMPLES:
+            sage: q = RDF.pi()/12
+            sage: q.sinh()
+            0.264800227602
+            
+        """
+        return RealDoubleElement(sinh(self._value))
+
+    def tanh(self):
+        """
+        Returns the hyperbolic tangent of this number
+
+        EXAMPLES:
+            sage: q = RDF.pi()/12
+            sage: q.tanh()
+            0.255977789246
+        """
+        return RealDoubleElement(tanh(self._value))
+
+    def acosh(self):
+        """
+        Returns the hyperbolic inverse cosine of this number
+
+        EXAMPLES:
+            sage: q = RDF.pi()/2 
+            sage: i = q.cosh() ; i
+            2.50917847866
+            sage: i.acosh() == q
+            True
+        """
+        return RealDoubleElement(gsl_acosh(self._value))
+
+    def asinh(self):
+        """
+        Returns the hyperbolic inverse sine of this number
+
+        EXAMPLES:
+            sage: q = RDF.pi()/2 
+            sage: i = q.sinh() ; i
+            2.30129890231
+            sage: i.asinh() == q
+            True
+        """
+        return RealDoubleElement(gsl_asinh(self._value))
+
+    def atanh(self):
+        """
+        Returns the hyperbolic inverse tangent of this number
+
+        EXAMPLES:
+            sage: q = RDF.pi()/2 
+            sage: i = q.tanh() ; i
+            0.917152335667
+            sage: i.atanh() == q
+            True
+        """
+        return RealDoubleElement(gsl_atanh(self._value))
+
+    def agm(self, other):
+        """
+        Return the arithmetic-geometric mean of self and other. The
+        arithmetic-geometric mean is the common limit of the sequences
+        $u_n$ and $v_n$, where $u_0$ is self, $v_0$ is other,
+        $u_{n+1}$ is the arithmetic mean of $u_n$ and $v_n$, and
+        $v_{n+1}$ is the geometric mean of u_n and v_n. If any operand
+        is negative, the return value is \code{NaN}.
+        """
+        return RealDoubleElement(sage.rings.all.RR(self).agm(sage.rings.all.RR(other)))
+    
+    def erf(self):
+        """ 
+        Returns the value of the error function on self. 
+
+        EXAMPLES:                                                           
+           sage: RDF(6).erf()
+           1.0
+        """
+        return RealDoubleElement(gsl_sf_erf(self._value))
+
+    def gamma(self):
+        """
+        The Euler gamma function. Return gamma of self.
+
+        EXAMPLES:
+           sage: RDF(6).gamma()
+           120.0
+           sage: RDF(1.5).gamma()
+           0.886226925453
+        """
+        return RealDoubleElement(gsl_sf_gamma(self._value))
+
+    def zeta(self):
+        r"""
+        Return the Riemann zeta function evaluated at this real number.
+
+        \note{PARI is vastly more efficient at computing the Riemann zeta
+        function.   See the example below for how to use it.}
+
+        EXAMPLES:
+            sage: RDF(2).zeta()
+            1.64493406685
+            sage: RDF.pi()^2/6
+            1.64493406685
+            sage: RDF(-2).zeta()
+            0.0
+            sage: RDF(1).zeta()
+            inf
+
+        Computing zeta using PARI is much more efficient in difficult cases.
+        Here's how to compute zeta with at least a given precision:
+        
+             sage: z = pari.new_with_bits_prec(2, 53).zeta(); z
+             1.644934066848226436472415167              # 32-bit
+             1.6449340668482264364724151666460251892    # 64-bit
+
+        Note that the number of bits of precision in the constructor only
+        effects the internel precision of the pari number, not the number
+        of digits that gets displayed.  To increase that you must
+        use \code{pari.set_real_precision}.
+        
+             sage: type(z)
+             <type 'gen.gen'>
+             sage: R(z)
+             1.6449340668482264
+        """
+        return RealDoubleElement(gsl_sf_zeta(self._value))
+
+    def algdep(self, n):
+        """
+        Returns a polynomial of degree at most $n$ which is approximately
+        satisfied by this number.  Note that the returned polynomial
+        need not be irreducible, and indeed usually won't be if this number
+        is a good approximation to an algebraic number of degree less than $n$.
+
+        ALGORITHM: Uses the PARI C-library algdep command.
+
+        EXAMPLE:
+             sage: r = RDF(2).sqrt(); r
+             1.41421356237
+             sage: r.algdep(5)
+             x^4 - 2*x^2        
+        """
+        return sage.rings.arith.algdep(self,n)
+
+    def algebraic_dependency(self, n):
+        """
+         Returns a polynomial of degree at most $n$ which is approximately
+         satisfied by this number.  Note that the returned polynomial
+         need not be irreducible, and indeed usually won't be if this number
+         is a good approximation to an algebraic number of degree less than $n$.
+
+         ALGORITHM: Uses the PARI C-library algdep command.
+
+         EXAMPLE:
+              sage: r = sqrt(2); r
+              1.41421356237
+              sage: r.algdep(5)
+              x^4 - 2*x^2        
+        """
+        return sage.rings.arith.algdep(self,n)
+
+
+#####################################################
+# unique objects
+#####################################################
+RealDoubleField = RealDoubleField_class()
+RDF = RealDoubleField
+
+
+
+
+
Index: sage/schemes/elliptic_curves/ell_finite_field.py
===================================================================
--- sage/schemes/elliptic_curves/ell_finite_field.py	(revision 1097)
+++ sage/schemes/elliptic_curves/ell_finite_field.py	(revision 1288)
@@ -22,5 +22,5 @@
 from ell_field import EllipticCurve_field
 import sage.rings.ring as ring
-from sage.rings.all import Integer
+from sage.rings.all import Integer, PolynomialRing
 import gp_cremona
 import sea
@@ -127,16 +127,25 @@
         
     def __points_over_arbitrary_field(self):
-        # TODO -- rewrite this insanely stupid implementation!!
-        print "WARNING: Using very very stupid algorithm for finding points over"
-        print "non-prime finite field.  Please rewrite.  See the file ell_finite.field.py."
-        # The best way to rewrite is to extend Cremona's code (either gp or mwrank) so
-        # it works over non-prime fields (should be easy), then generate up the group.
+        # todo: This function used to have the following comment:
+
+        ### TODO -- rewrite this insanely stupid implementation!!
+        ### print "WARNING: Using very very stupid algorithm for finding points over"
+        ### print "non-prime finite field.  Please rewrite.  See the file ell_finite.field.py."
+        ### The best way to rewrite is to extend Cremona's code (either gp or mwrank) so
+        ### it works over non-prime fields (should be easy), then generate up the group.
+
+        # I changed the algorithm so that it's not as naive as it used to be.
+        # But it's still surely far from optimal; I don't know anything about
+        # point enumeration algorithms. -- David Harvey (2006-09-24)
+        
         points = [self(0)]
+        R = PolynomialRing(self.base_ring())
+        a1, a2, a3, a4, a6 = self.ainvs()
         for x in self.base_field():
-            for y in self.base_field():
-                try:
-                    points.append(self([x,y]))
-                except TypeError:
-                    pass
+            f = R([-(x**3 + a2*x**2 + a4*x + a6), (a1*x + a3), 1])
+            factors = f.factor()
+            if len(factors) == 2 or factors[0][1] == 2:
+                for factor in factors:
+                    points.append(self([x, -factor[0][0]]))
         return points
 
@@ -145,10 +154,58 @@
         All the points on this elliptic curve.
 
-        If the base field is another other than $\FF_p$, this function currently
-        uses a VERY VERY naive algorithm.   The problem is that Cremona's gp
-        script \code{ell_zp.gp} currently only treats the case of prime fields.
-        If you need more general functionality, please volunteer to implement
-        it, either by extending \code{ell_zp.gp} (if you know PARI/GP well) or
-        by writing new \sage code.
+        EXAMPLES:
+          sage: p = 5
+          sage: F = GF(p)
+          sage: E = EllipticCurve(F, [1, 3])
+          sage: a_sub_p = E.change_ring(QQ).ap(p); a_sub_p
+          2
+
+          sage: len(E.points())
+          4
+          sage: p + 1 - a_sub_p
+          4
+          sage: E.points()
+          [(0 : 1 : 0), (4 : 1 : 1), (1 : 0 : 1), (4 : 4 : 1)]
+
+          sage: K = GF(p**2)
+          sage: E = E.change_ring(K)
+          sage: len(E.points())
+          32
+          sage: (p + 1)**2 - a_sub_p**2
+          32
+          sage: E.points()
+          [(0 : 1 : 0),
+           (0 : 2*a + 4 : 1),
+           (0 : 3*a + 1 : 1),
+           (1 : 0 : 1),
+           (2 : 2*a + 4 : 1),
+           (2 : 3*a + 1 : 1),
+           (3 : 2*a + 4 : 1),
+           (3 : 3*a + 1 : 1),
+           (4 : 1 : 1),
+           (4 : 4 : 1),
+           (a : 1 : 1),
+           (a : 4 : 1),
+           (a + 2 : a + 1 : 1),
+           (a + 2 : 4*a + 4 : 1),
+           (a + 3 : a : 1),
+           (a + 3 : 4*a : 1),
+           (a + 4 : 0 : 1),
+           (2*a : 2*a : 1),
+           (2*a : 3*a : 1),
+           (2*a + 4 : a + 1 : 1),
+           (2*a + 4 : 4*a + 4 : 1),
+           (3*a + 1 : a + 3 : 1),
+           (3*a + 1 : 4*a + 2 : 1),
+           (3*a + 2 : 2*a + 3 : 1),
+           (3*a + 2 : 3*a + 2 : 1),
+           (4*a : 0 : 1),
+           (4*a + 1 : 1 : 1),
+           (4*a + 1 : 4 : 1),
+           (4*a + 3 : a + 3 : 1),
+           (4*a + 3 : 4*a + 2 : 1),
+           (4*a + 4 : a + 4 : 1),
+           (4*a + 4 : 4*a + 1 : 1)]
+           
         """
         try:
@@ -191,5 +248,5 @@
         return q + 1 - self.cardinality()
 
-    def cardinality(self, algorithm='heuristic', early_abort=False):
+    def cardinality(self, algorithm='heuristic', early_abort=False, disable_warning=False):
         r"""
         Return the number of points on this elliptic curve over this
@@ -197,6 +254,7 @@
         
         \note{If the cardinality of the base field is not prime, this
-        function currently uses a very very naive enumeration of all
-        points.  It's so stupid, that it prints a warning.}
+        function literally enumerates the points and counts them. It's so
+        stupid, it prints a warning. You can disable the warning with the
+        disable_warning flag.}
 
         INPUT:
@@ -221,10 +279,12 @@
         EXAMPLES:
             sage: EllipticCurve(GF(4),[1,2,3,4,5]).cardinality()
-            WARNING: Using very very stupid algorithm for finding points over
-            non-prime finite field.  Please rewrite.  See the file ell_finite.field.py.
+            WARNING: Using very very stupid algorithm for counting
+            points over non-prime finite field. Please rewrite.
+            See the file ell_finite_field.py.
             8
             sage: EllipticCurve(GF(9),[1,2,3,4,5]).cardinality()
-            WARNING: Using very very stupid algorithm for finding points over
-            non-prime finite field.  Please rewrite.  See the file ell_finite.field.py.
+            WARNING: Using very very stupid algorithm for counting
+            points over non-prime finite field. Please rewrite.
+            See the file ell_finite_field.py.
             16
             sage: EllipticCurve(GF(10007),[1,2,3,4,5]).cardinality()
@@ -260,4 +320,8 @@
                 
         if N == 0:
+            if not disable_warning:
+                print "WARNING: Using very very stupid algorithm for counting "
+                print "points over non-prime finite field. Please rewrite."
+                print "See the file ell_finite_field.py."
             N = len(self.points())
         self.__cardinality = Integer(N)
Index: sage/schemes/elliptic_curves/ell_generic.py
===================================================================
--- sage/schemes/elliptic_curves/ell_generic.py	(revision 1169)
+++ sage/schemes/elliptic_curves/ell_generic.py	(revision 1290)
@@ -559,4 +559,288 @@
 
 
+    def pseudo_torsion_polynomial(self, n, x=None, cache=None):
+        r"""
+        Returns the n-th torsion polynomial (division polynomial), without
+        the 2-torsion factor if n is even, as a polynomial in $x$.
+
+        These are the polynomials $g_n$ defined in Mazur/Tate (``The p-adic
+        sigma function''), but with the sign flipped for even $n$, so that
+        the leading coefficient is always positive.
+
+        The full torsion polynomials may be recovered as follows:
+        \begin{itemize}
+        \item $\psi_n = g_n$ for odd $n$.
+        \item $\psi_n = (2y + a_1 x + a_3) g_n$ for even $n$.
+        \end{itemize}
+
+        Note that the $g_n$'s are always polynomials in $x$, whereas the
+        $\psi_n$'s require the appearance of a $y$.
+
+        SEE ALSO:
+            -- torsion_polynomial()
+            -- multiple_x_numerator()
+            -- multiple_x_denominator()
+
+        INPUT:
+            n -- positive integer, or the special values -1 and -2 which
+                 mean $B_6 = (2y + a_1 x + a_3)^2$ and $B_6^2$ respectively
+                 (in the notation of Mazur/Tate).
+            x -- optional ring element to use as the "x" variable. If x
+                 is None, then a new polynomial ring will be constructed over
+                 the base ring of the elliptic curve, and its generator will
+                 be used as x. Note that x does not need to be a generator of
+                 a polynomial ring; any ring element is ok. This permits fast
+                 calculation of the torsion polynomial *evaluated* on any
+                 element of a ring.
+            cache -- optional dictionary, with integer keys. If the key m
+                 is in cache, then cache[m] is assumed to be the value of
+                 pseudo_torsion_polynomial(m) for the supplied x. New entries
+                 will be added to the cache as they are computed.
+
+        ALGORITHM:
+            -- Recursion described in Mazur/Tate. The recursive formulae are
+            evaluated $O((log n)^2)$ times.
+
+        TODO:
+            -- for better unity of code, it might be good to make the regular
+            torsion_polynomial() function use this as a subroutine.
+
+        AUTHORS:
+            -- David Harvey (2006-09-24)
+
+        EXAMPLES:
+           sage: E = EllipticCurve("37a")
+           sage: E.pseudo_torsion_polynomial(1)
+           1
+           sage: E.pseudo_torsion_polynomial(2)
+           1
+           sage: E.pseudo_torsion_polynomial(3)
+           3*x^4 - 6*x^2 + 3*x - 1
+           sage: E.pseudo_torsion_polynomial(4)
+           2*x^6 - 10*x^4 + 10*x^3 - 10*x^2 + 2*x + 1
+           sage: E.pseudo_torsion_polynomial(5)
+           5*x^12 - 62*x^10 + 95*x^9 - 105*x^8 - 60*x^7 + 285*x^6 - 174*x^5 - 5*x^4 - 5*x^3 + 35*x^2 - 15*x + 2
+           sage: E.pseudo_torsion_polynomial(6)
+           3*x^16 - 72*x^14 + 168*x^13 - 364*x^12 + 1120*x^10 - 1144*x^9 + 300*x^8 - 540*x^7 + 1120*x^6 - 588*x^5 - 133*x^4 + 252*x^3 - 114*x^2 + 22*x - 1
+           sage: E.pseudo_torsion_polynomial(7)
+           7*x^24 - 308*x^22 + 986*x^21 - 2954*x^20 + 28*x^19 + 17171*x^18 - 23142*x^17 + 511*x^16 - 5012*x^15 + 43804*x^14 - 7140*x^13 - 96950*x^12 + 111356*x^11 - 19516*x^10 - 49707*x^9 + 40054*x^8 - 124*x^7 - 18382*x^6 + 13342*x^5 - 4816*x^4 + 1099*x^3 - 210*x^2 + 35*x - 3
+           sage: E.pseudo_torsion_polynomial(8)
+           4*x^30 - 292*x^28 + 1252*x^27 - 5436*x^26 + 2340*x^25 + 39834*x^24 - 79560*x^23 + 51432*x^22 - 142896*x^21 + 451596*x^20 - 212040*x^19 - 1005316*x^18 + 1726416*x^17 - 671160*x^16 - 954924*x^15 + 1119552*x^14 + 313308*x^13 - 1502818*x^12 + 1189908*x^11 - 160152*x^10 - 399176*x^9 + 386142*x^8 - 220128*x^7 + 99558*x^6 - 33528*x^5 + 6042*x^4 + 310*x^3 - 406*x^2 + 78*x - 5
+
+           sage: E.pseudo_torsion_polynomial(18) % E.pseudo_torsion_polynomial(6) == 0
+           True
+
+          An example to illustrate the relationship with torsion points.
+           sage: F = GF(11)
+           sage: E = EllipticCurve(F, [0, 2]); E
+           Elliptic Curve defined by y^2  = x^3 + 2 over Finite Field of size 11
+           sage: f = E.pseudo_torsion_polynomial(5); f
+           5*x^12 + x^9 + 8*x^6 + 4*x^3 + 7
+           sage: f.factor()
+           (5) * (x^2 + 5) * (x^2 + 2*x + 5) * (x^2 + 5*x + 7) * (x^2 + 7*x + 7) * (x^2 + 9*x + 5) * (x^2 + 10*x + 7)
+
+          This indicates that the x-coordinates of all the 5-torsion points
+          of E are in GF(11^2), and therefore the y-coordinates are in
+          GF(11^4).
+           sage: K = GF(11^4)
+           sage: X = E.change_ring(K)
+           sage: f = X.pseudo_torsion_polynomial(5)
+           sage: x_coords = [root for (root, _) in f.roots()]; x_coords
+            [a^3 + 7*a^2 + 6*a,
+             2*a^3 + 3*a^2 + a + 7,
+             3*a^3 + 10*a^2 + 7*a + 1,
+             3*a^3 + 10*a^2 + 7*a + 3,
+             3*a^3 + 10*a^2 + 7*a + 8,
+             5*a^3 + 2*a^2 + 8*a + 7,
+             6*a^3 + 9*a^2 + 3*a + 4,
+             8*a^3 + a^2 + 4*a + 4,
+             8*a^3 + a^2 + 4*a + 8,
+             8*a^3 + a^2 + 4*a + 10,
+             9*a^3 + 8*a^2 + 10*a + 8,
+             10*a^3 + 4*a^2 + 5*a + 6]
+           
+          Now we check that these are exactly the x coordinates of the
+          5-torsion points of E.
+           sage: for x in x_coords:
+           ...       y = (x**3 + 2).square_root()
+           ...       P = X([x, y])
+           ...       assert P.order(disable_warning=True) == 5
+
+          todo: need to show an example where the 2-torsion is missing
+
+        """
+        if cache is None:
+            cache = {}
+        else:
+            try:
+                return cache[n]
+            except KeyError:
+                pass
+
+        if x is None:
+            x = rings.PolynomialRing(self.base_ring()).gen()
+
+        b2, b4, b6, b8 = self.b_invariants()
+
+        n = int(n)
+        if n <= 4:
+            if n == -1:
+                answer = 4*x**3 + b2*x**2 + 2*b4*x + b6
+            elif n == -2:
+                answer = self.pseudo_torsion_polynomial(-1, x, cache) ** 2
+            elif n == 1 or n == 2:
+                answer = x.parent()(1)
+            elif n == 3:
+                answer = 3*x**4 + b2*x**3 + 3*b4*x**2 + 3*b6*x + b8
+            elif n == 4:
+                answer = -self.pseudo_torsion_polynomial(-2, x, cache) + \
+                         (6*x**2 + b2*x + b4) * \
+                         self.pseudo_torsion_polynomial(3, x, cache)
+            else:
+                raise ValueError, "n must be a positive integer (or -1 or -2)"
+        else:
+            if n % 2 == 0:
+                m = (n-2) // 2
+                g_mplus3 = self.pseudo_torsion_polynomial(m+3, x, cache)
+                g_mplus2 = self.pseudo_torsion_polynomial(m+2, x, cache)
+                g_mplus1 = self.pseudo_torsion_polynomial(m+1, x, cache)
+                g_m      = self.pseudo_torsion_polynomial(m,   x, cache)
+                g_mless1 = self.pseudo_torsion_polynomial(m-1, x, cache)
+                answer = g_mplus1 * \
+                         (g_mplus3 * g_m**2 - g_mless1 * g_mplus2**2)
+            else:
+                m = (n-1) // 2
+                g_mplus2 = self.pseudo_torsion_polynomial(m+2, x, cache)
+                g_mplus1 = self.pseudo_torsion_polynomial(m+1, x, cache)
+                g_m      = self.pseudo_torsion_polynomial(m,   x, cache)
+                g_mless1 = self.pseudo_torsion_polynomial(m-1, x, cache)
+                B6_sqr   = self.pseudo_torsion_polynomial(-2, x, cache)
+                if m % 2 == 0:
+                    answer = B6_sqr * g_mplus2 * g_m**3 - \
+                             g_mless1 * g_mplus1**3
+                else:
+                    answer = g_mplus2 * g_m**3 - \
+                             B6_sqr * g_mless1 * g_mplus1**3
+
+        cache[n] = answer
+        return answer
+
+
+    def multiple_x_numerator(self, n, x=None, cache=None):
+        r"""
+        Returns the numerator of the x-coordinate of the nth multiple of
+        a point, using torsion polynomials (division polynomials).
+
+        The inputs n, x, cache are as described in pseudo_torsion_polynomial().
+
+        The result is adjusted to be correct for both even and odd n.
+
+        WARNING:
+          -- There may of course be cancellation between the numerator and
+          the denominator (multiple_x_denominator()). Be careful. For more
+          information on how to avoid cancellation, see Christopher Wuthrich's
+          thesis.
+
+        SEE ALSO:
+          -- multiple_x_denominator()
+
+        AUTHORS:
+           -- David Harvey (2006-09-24)
+
+        EXAMPLES:
+          sage: E = EllipticCurve("37a")
+          sage: P = E.gens()[0]
+          sage: x = P[0]
+
+          sage: (35*P)[0]
+          -804287518035141565236193151/1063198259901027900600665796
+          sage: E.multiple_x_numerator(35, x)
+          -804287518035141565236193151
+          sage: E.multiple_x_denominator(35, x)
+          1063198259901027900600665796
+
+          sage: (36*P)[0]
+          54202648602164057575419038802/15402543997324146892198790401
+          sage: E.multiple_x_numerator(36, x)
+          54202648602164057575419038802
+          sage: E.multiple_x_denominator(36, x)
+          15402543997324146892198790401
+
+        An example where cancellation occurs:
+          sage: E = EllipticCurve("88a1")
+          sage: P = E.gens()[0]
+          sage: n = E.multiple_x_numerator(11, P[0]); n
+          442446784738847563128068650529343492278651453440
+          sage: d = E.multiple_x_denominator(11, P[0]); d
+          1427247692705959881058285969449495136382746624
+          sage: n/d
+          310
+          sage: 11*P
+          (310 : -5458 : 1)
+          
+        """
+        if cache is None:
+            cache = {}
+
+        if x is None:
+            x = rings.PolynomialRing(self.base_ring()).gen()
+
+        n = int(n)
+        if n < 2:
+            print "n must be at least 2"
+
+        self.pseudo_torsion_polynomial( -2, x, cache)
+        self.pseudo_torsion_polynomial(n-1, x, cache)
+        self.pseudo_torsion_polynomial(n  , x, cache)
+        self.pseudo_torsion_polynomial(n+1, x, cache)
+
+        if n % 2 == 0:
+            return x * cache[-1] * cache[n]**2 - cache[n-1] * cache[n+1]
+        else:
+            return x * cache[n]**2 - cache[-1] * cache[n-1] * cache[n+1]
+
+
+    def multiple_x_denominator(self, n, x=None, cache=None):
+        r"""
+        Returns the denominator of the x-coordinate of the nth multiple of
+        a point, using torsion polynomials (division polynomials).
+
+        The inputs n, x, cache are as described in pseudo_torsion_polynomial().
+
+        The result is adjusted to be correct for both even and odd n.
+
+        SEE ALSO:
+          -- multiple_x_numerator()
+
+        TODO: the numerator and denominator versions share a calculation,
+        namely squaring $\psi_n$. Maybe would be good to offer a combined
+        version to make this more efficient.
+
+        EXAMPLES:
+           -- see multiple_x_numerator()
+
+        AUTHORS:
+           -- David Harvey (2006-09-24)
+
+        """
+        if cache is None:
+            cache = {}
+
+        if x is None:
+            x = rings.PolynomialRing(self.base_ring()).gen()
+
+        n = int(n)
+        if n < 2:
+            print "n must be at least 2"
+
+        self.pseudo_torsion_polynomial(-2, x, cache)
+        self.pseudo_torsion_polynomial(n , x, cache)
+
+        if n % 2 == 0:
+            return cache[-1] * cache[n]**2
+        else:
+            return cache[n]**2
+
+
     def torsion_polynomial(self, n, i=0):
         """
@@ -570,4 +854,7 @@
             Polynomial -- n-th torsion polynomial, which is a polynomial over
                           the base field of the elliptic curve. 
+
+        SEE ALSO:
+            pseudo_torsion_polynomial()
 
         EXAMPLES:
Index: sage/schemes/elliptic_curves/ell_point.py
===================================================================
--- sage/schemes/elliptic_curves/ell_point.py	(revision 1097)
+++ sage/schemes/elliptic_curves/ell_point.py	(revision 1289)
@@ -286,5 +286,5 @@
 
 class EllipticCurvePoint_finite_field(EllipticCurvePoint_field):
-    def order(self):
+    def order(self, disable_warning=False):
         """
         Return the order of this point on the elliptic curve.
@@ -315,5 +315,6 @@
             self.__order = rings.Integer(e.ellzppointorder(list(self.xy())))
         else:
-            print "WARNING -- using naive point order finding over finite field!"
+            if not disable_warning:
+                print "WARNING -- using naive point order finding over finite field!"
             # TODO: This is very very naive!!  -- should use baby-step giant step; maybe in mwrank
             #      note that this is *not* implemented in PARI!
Index: sage/server/notebook/notebook.py
===================================================================
--- sage/server/notebook/notebook.py	(revision 1184)
+++ sage/server/notebook/notebook.py	(revision 1285)
@@ -330,4 +330,5 @@
 import shutil
 import socket
+import re           # regular expressions
 
 # SAGE libraries
@@ -454,6 +455,23 @@
         os.system(cmd)
         D = os.listdir(tmp)[0]
+        worksheet = load('%s/%s/%s.sobj'%(tmp,D,D), compress=False)
+        names = self.worksheet_names()
+        if D in names:
+            m = re.match('.*?([0-9]+)$',D)
+            if m is None:
+                n = 0
+            else:
+                n = int(m.groups()[0])
+            while "%s%d"%(D,n) in names:
+                n += 1
+            cmd = 'mv %s/%s/%s.sobj %s/%s/%s%d.sobj'%(tmp,D,D,tmp,D,D,n)
+            print cmd
+            os.system(cmd)
+            cmd = 'mv %s/%s %s/%s%d'%(tmp,D,tmp,D,n)
+            print cmd
+            os.system(cmd)
+            D = "%s%d"%(D,n)
+            worksheet.set_name(D)
         print D
-        worksheet = load('%s/%s/%s.sobj'%(tmp,D,D), compress=False)
         S = self.__worksheet_dir 
         cmd = 'rm -rf "%s/%s"'%(S,D)
@@ -1055,5 +1073,6 @@
              jsmath      = True,
              show_debug  = False,
-             warn        = True):
+             warn        = True,
+             ignore_lock = False):
     r"""
     Start a SAGE notebook web server at the given port.
@@ -1130,4 +1149,21 @@
         if not (os.path.exists('%s/nb.sobj'%dir) or os.path.exists('%s/nb-backup.sobj'%dir)):
             raise RuntimeError, '"%s" is not a valid SAGE notebook directory (missing nb.sobj).'%dir
+        if os.path.exists('%s/pid'%dir) and not ignore_lock:
+            f = file('%s/pid'%dir)
+            p = f.read()
+            f.close()
+            try:
+                #This is a hack to check whether or not the process is running.
+                os.kill(int(p),0)
+                print "\n".join([" This notebook appears to be running with PID %s.  If it is"%p,
+                                 " not responding, you will need to kill that process to continue.",
+                                 " If another (non-sage) process is running with that PID, call",
+                                 " notebook(..., ignore_lock = True, ...). " ])
+                return
+            except OSError:
+                pass
+        f = file('%s/pid'%dir, 'w')
+        f.write("%d"%os.getpid())
+        f.close()
         try:
             nb = load('%s/nb.sobj'%dir, compress=False)
@@ -1167,4 +1203,5 @@
     from sage.misc.misc import delete_tmpfiles
     delete_tmpfiles()
+    os.remove('%s/pid'%dir)
     return nb
     
Index: sage/server/notebook/worksheet.py
===================================================================
--- sage/server/notebook/worksheet.py	(revision 1184)
+++ sage/server/notebook/worksheet.py	(revision 1285)
@@ -19,5 +19,5 @@
 import traceback
 import time
-
+import crypt
 import pexpect
 
@@ -50,5 +50,6 @@
         self.__name = name
         self.__notebook = notebook
-        self.__passcode = passcode
+        self.__passcode = crypt.crypt(passcode, self.__salt)
+        self.__passcrypt= True
         dir = list(name)
         for i in range(len(dir)):
@@ -83,10 +84,25 @@
                 C.set_worksheet(self)
 
+    def salt(self):
+        try:
+            return self.__salt
+        except AttributeError:
+            self.__salt = "%f"%time.time()
+            return self.__salt
+
     def passcode(self):
         try:
+            c = self.__passcrypt
+        except AttributeError:
+            self.__passcrypt = False
+        try:
+            if not self.__passcrypt:
+                self.__passcode = crypt.crypt(self.__passcode, self.salt())
+                self.__passcrypt = True
             return self.__passcode
         except AttributeError:
-            self.__passcode = ''
-            return ''
+            self.__passcode = crypt.crypt(self.__passcode, self.salt())
+            self.__passcrypt = True
+            return self.__passcode
 
     def filename(self):
@@ -546,8 +562,5 @@
 
     def auth(self, passcode):
-        if self.passcode() == '':
-            return True
-        else:
-            return self.passcode() == passcode
+        return self.passcode() == crypt.crypt(passcode, self.__salt)
 
     def _strip_synchro_from_start_of_output(self, s):
@@ -1011,4 +1024,7 @@
         return self.__name
 
+    def set_name(self, name):
+        self.__name = name
+
     def append(self, L):
         self.__cells.append(L)
Index: setup.py
===================================================================
--- setup.py	(revision 1292)
+++ setup.py	(revision 1293)
@@ -164,4 +164,8 @@
                 libraries = ['gsl', CBLAS])
 
+real_double = Extension('sage.rings.real_double',
+                ['sage/rings/real_double.pyx'],
+                libraries = ['gsl', CBLAS])
+
 complex_double = Extension('sage.rings.complex_double',
                            ['sage/rings/complex_double.pyx'],
@@ -195,4 +199,5 @@
     gsl_interpolation,
     gsl_callback,
+    real_double,
     complex_double,
 
