[pypy-svn] r23147 - in pypy/dist/pypy/objspace/std: . test

stephan at codespeak.net stephan at codespeak.net
Wed Feb 8 16:23:04 CET 2006


Author: stephan
Date: Wed Feb  8 16:22:59 2006
New Revision: 23147

Added:
   pypy/dist/pypy/objspace/std/complexobject.py
   pypy/dist/pypy/objspace/std/complextype.py
   pypy/dist/pypy/objspace/std/test/helper.py
   pypy/dist/pypy/objspace/std/test/test_complexobject.py
Modified:
   pypy/dist/pypy/objspace/std/model.py
   pypy/dist/pypy/objspace/std/objspace.py
Log:
this is the initial check in for native complex numbers in standard objspace.
Since there are still some bugs und pypy can't be translated at the moment
with complex numbers enabled, the complex numbers are disabled at the moment.
To enable them, edit model.py and objspace.py. Look out for the string 'complex'.


Added: pypy/dist/pypy/objspace/std/complexobject.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/complexobject.py	Wed Feb  8 16:22:59 2006
@@ -0,0 +1,264 @@
+import pypy.objspace.std.objspace as poso
+from pypy.interpreter import gateway
+from pypy.objspace.std.noneobject import W_NoneObject
+from pypy.objspace.std.floatobject import W_FloatObject, _hash_float
+from pypy.objspace.std.longobject import _AsDouble
+import math
+
+class W_ComplexObject(poso.W_Object):
+    """This is a reimplementation of the CPython "PyComplexObject"
+    """
+
+    from pypy.objspace.std.complextype import complex_typedef as typedef
+
+    def __init__(w_self, space, realval=0.0, imgval=0.0):
+        poso.W_Object.__init__(w_self, space)
+        w_self._real = float(realval)
+        w_self._imag = float(imgval)
+
+    def __repr__(self):
+        return "<W_ComplexObject(%f,%f)>" % (self._real, self._imag)
+
+poso.registerimplementation(W_ComplexObject)
+
+c_1 = (1.0, 0.0)
+
+def _sum(c1, c2):
+    return (c1[0]+c2[0],c1[1]+c2[1])
+
+def _diff(c1, c2):
+    return (c1[0]-c2[0],c1[1]-c2[1])
+
+def _neg(c):
+    return (-c[0],-c[1])
+
+def _prod(c1, c2):
+    r = c1[0]*c2[0] - c1[1]*c2[1]
+    i = c1[0]*c2[1] + c1[1]*c2[0]
+    return (r,i)
+
+def _quot(c1,c2):
+    r1, i1 = c1
+    r2, i2 = c2
+    if r2 < 0:
+        abs_r2 = - r2
+    else:
+        abs_r2 = r2
+    if i2 < 0:
+        abs_i2 = - i2
+    else:
+        abs_i2 = i2
+    if abs_r2 >= abs_i2:
+        if abs_r2 == 0.0:
+            raise ZeroDivisionError
+        else:
+            ratio = i2 / r2
+            denom = r2 + i2 * ratio
+            rr = (r1 + i1 * ratio) / denom
+            ir = (i1 - r1 * ratio) / denom
+    else:
+        ratio = r2 / i2
+        denom = r2 * ratio + i2
+        assert i2 != 0.0
+        rr = (r1 * ratio + i1) / denom
+        ir = (i1 + ratio - r1) / denom
+    return (rr,ir)
+
+def _pow(c1,c2):
+    r1, i1 = c1
+    r2, i2 = c2
+    if r2 == 0.0 and i2 == 0.0:
+        rr, ir = c_1
+    elif r1 == 0.0 and i1 == 0.0:
+        if i2 != 0.0 or r2 < 0.0:
+            raise ZeroDivisionError("0.0 to a negative or complex power")
+        rr, ir = (0.0, 0.0)
+    else:
+        vabs = math.hypot(r1,i1)
+        len = math.pow(vabs,r2)
+        at = math.atan2(i1,r1)
+        phase = at * r2
+        if i2 != 0.0:
+            len /= math.exp(at * i2)
+            phase += i2 * math.log(vabs)
+        rr = len * math.cos(phase)
+        ir = len * math.sin(phase)
+    return (rr, ir)
+
+def _powu(c,n):
+    mask = 1;
+    rr, ir = c_1
+    rp = c[0]
+    ip = c[1]
+    while mask > 0 and n >= mask:
+        if n & mask:
+            rr, ir = _prod((rr, ir), (rp, ip))
+        mask <<= 1
+        rp, ip = _prod((rp, ip), (rp, ip))
+
+    return (rr, ir)
+
+def _powi(c,n):
+    if n > 100 or n < -100:
+        return _pow(c,(1.0 * n, 0.0))
+    elif n > 0:
+        return _powu(c, n)
+    else:
+        return _quot(c_1, _powu(c, -n))
+
+
+
+def delegate_Bool2Complex(w_bool):
+    space = w_bool.space
+    return W_ComplexObject(space, w_bool.boolval, 0.0)
+
+def delegate_Int2Complex(w_int):
+    space = w_int.space
+    return W_ComplexObject(space, w_int.intval, 0.0)
+
+def delegate_Long2Complex(w_long):
+    space = w_long.space
+    try:
+        dval =  _AsDouble(w_long)
+    except OverflowError, e:
+        raise poso.OperationError(space.w_OverflowError, space.wrap(str(e)))
+    return W_ComplexObject(space, dval, 0.0)
+
+def delegate_Float2Complex(w_float):
+    space = w_float.space
+    return W_ComplexObject(space, w_float.floatval, 0.0)
+
+def hash__Complex(space, w_value):
+    #this is straight out of CPython complex implementation
+
+    hashreal = _hash_float(space, w_value._real)
+    if hashreal == -1:
+        return -1
+    hashimg = _hash_float(space, w_value._imag)
+    if hashimg == -1:
+        return -1
+    combined = hashreal + 1000003 * hashimg
+    if (combined == -1):
+        combined = -2
+    return space.newint(combined)
+
+def _w2t(w_complex):
+    return w_complex._real, w_complex._imag
+
+def _t2w(space, c):
+    return W_ComplexObject(space, c[0], c[1])
+
+def add__Complex_Complex(space, w_complex1, w_complex2):
+    return _t2w(space, _sum(_w2t(w_complex1), _w2t(w_complex2)))
+
+def sub__Complex_Complex(space, w_complex1, w_complex2):
+    return _t2w(space, _diff(_w2t(w_complex1), _w2t(w_complex2)))
+
+def mul__Complex_Complex(space, w_complex1, w_complex2):
+    return _t2w(space, _prod(_w2t(w_complex1), _w2t(w_complex2)))
+
+def div__Complex_Complex(space, w_complex1, w_complex2):
+    try:
+        return _t2w(space, _quot(_w2t(w_complex1), _w2t(w_complex2)))
+    except ZeroDivisionError, e:
+        raise poso.OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
+
+truediv__Complex_Complex = div__Complex_Complex
+
+def mod__Complex_Complex(space, w_complex1, w_complex2):
+    try:
+        div = _quot(_w2t(w_complex1), _w2t(w_complex2))
+    except ZeroDivisionError, e:
+        raise poso.OperationError(space.w_ZeroDivisionError, space.wrap("complex remainder"))
+    div = (math.floor(div[0]), 0.0)
+    mod = _diff(_w2t(w_complex1), _prod(_w2t(w_complex2), div))
+
+    return _t2w(space, mod)
+
+def divmod__Complex_Complex(space, w_complex1, w_complex2):
+    try:
+        div = _quot(_w2t(w_complex1), _w2t(w_complex2))
+    except ZeroDivisionError, e:
+        raise poso.OperationError(space.w_ZeroDivisionError, space.wrap("complex divmod()"))
+    div = (math.floor(div[0]), 0.0)
+    mod = _diff(_w2t(w_complex1), _prod(_w2t(w_complex2), div))
+    w_div = _t2w(space, div)
+    w_mod = _t2w(space, mod)
+    return space.newtuple([w_div, w_mod])
+
+def floordiv__Complex_Complex(space, w_complex1, w_complex2):
+    try:
+        div = _quot(_w2t(w_complex1), _w2t(w_complex2))
+    except ZeroDivisionError, e:
+        raise poso.OperationError(space.w_ZeroDivisionError, space.wrap("complex floordiv()"))
+    div = (math.floor(div[0]), 0.0)
+    return _t2w(space, div)
+
+def pow__Complex_Complex_ANY(space, w_complex1, w_complex2, thirdArg):
+    if not isinstance(thirdArg, W_NoneObject):
+        raise poso.OperationError(space.w_ValueError, space.wrap('complex module'))
+    try:
+        v = _w2t(w_complex1)
+        exponent = _w2t(w_complex2)
+        int_exponent = int(exponent[0])
+        if exponent[1] == 0.0 and exponent[0] == int_exponent:
+            p = _powi(v, int_exponent)
+        else:
+            p = _pow(v, exponent)
+    except ZeroDivisionError:
+        raise poso.OperationError(space.w_ZeroDivisionError, space.wrap("0.0 to a negative or complex power"))
+    except OverflowError:
+        raise poso.OperationError(space.w_OverflowError, space.wrap("complex exponentiation"))
+    return _t2w(space, p)
+
+def neg__Complex(space, w_complex):
+    return W_ComplexObject(space, -w_complex._real, -w_complex._imag)
+
+def pos__Complex(space, w_complex):
+    return W_ComplexObject(space, w_complex._real, w_complex._imag)
+
+def abs__Complex(space, w_complex):
+    return space.wrap(math.hypot(w_complex._real, w_complex._imag))
+
+def eq__Complex_Complex(space, w_complex1, w_complex2):
+    return space.newbool((w_complex1._real == w_complex2._real) and 
+            (w_complex1._imag == w_complex2._imag))
+
+def ne__Complex_Complex(space, w_complex1, w_complex2):
+    return space.newbool((w_complex1._real != w_complex2._real) or 
+            (w_complex1._imag != w_complex2._imag))
+
+def nonzero__Complex(space, w_complex):
+    return space.newbool(w_complex._real or w_complex._imag)
+
+def coerce__Complex_Complex(space, w_complex1, w_complex2):
+    return space.newtuple([w_complex1, w_complex2])
+
+app = gateway.applevel(""" 
+    import math
+    def possint(f):
+        ff = math.floor(f)
+        if f == ff:
+            return int(ff)
+        return f
+
+    def repr__Complex(f):
+        if not f.real:
+            return repr(possint(f.imag))+'j'
+        imag = f.imag
+        sign = ((imag >= 0) and '+') or ''
+        return '('+repr(possint(f.real)) + sign + repr(possint(f.imag))+'j)'
+
+    def str__Complex(f):
+        if not f.real:
+            return repr(possint(f.imag))+'j'
+        imag = f.imag
+        sign = ((imag >= 0) and '+') or ''
+        return "'("+repr(possint(f.real)) + sign + repr(possint(f.imag))+"j)'"
+
+""", filename=__file__) 
+
+repr__Complex = app.interphook('repr__Complex') 
+str__Complex = app.interphook('str__Complex') 
+
+poso.register_all(vars())

Added: pypy/dist/pypy/objspace/std/complextype.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/complextype.py	Wed Feb  8 16:22:59 2006
@@ -0,0 +1,115 @@
+import pypy.objspace.std.stdtypedef as poss
+from pypy.interpreter.error import OperationError
+from pypy.objspace.std.strutil import interp_string_to_float, ParseStringError
+from pypy.objspace.std.noneobject import W_NoneObject
+
+# ERRORCODES
+
+ERR_WRONG_SECOND = "complex() can't take second arg if first is a string"
+ERR_MALFORMED = "complex() arg is a malformed string"
+
+def _split_complex(s):
+    s = s.replace(' ','')
+    slen = len(s)
+    realnum = '0.0'
+    imagnum = '0.0'
+    pc = ''
+    i = 0
+    bp = 0
+    while i < slen:
+        c = s[i]
+        if c in ('+','-') and pc not in ('e','E'):
+            bp = i
+            break
+        pc = c
+        i += 1
+    if bp:
+        if s[-1] not in ['j','J']:
+            raise ValueError('complex() arg is a malformed string')
+        realnum = s[:bp]
+        imagnum = s[bp+1:-1]
+    else:
+        if s[-1] in ['j','J']:
+            imagnum = s[:-1]
+        else:
+            realnum = s
+
+    return realnum, imagnum
+
+
+
+def check_second_arg(space, w_c):
+    if space.is_true(space.isinstance(w_c, space.w_str)):
+        raise TypeError()
+    return True
+
+def descr__new__(space, w_complextype, w_real=0.0, w_imag=None):
+    from pypy.objspace.std.complexobject import W_ComplexObject
+    # @@ bad hack
+    try:
+        w_real = space.call_method(w_real,'__complex__')
+    except OperationError:pass
+    # @@ end bad hack
+    try:
+        check_second_arg(space, w_imag)
+    except TypeError:
+        raise OperationError(space.w_TypeError,space.wrap("complex() second arg can't be a string"))
+
+    if space.is_true(space.isinstance(w_real, space.w_complex)) and \
+            space.eq_w(w_imag, space.w_None):
+        return w_real
+    elif not space.is_true(space.isinstance(w_real, space.w_str)) and \
+            not space.eq_w(w_imag, space.w_None):
+        w_imag = space.mul(w_imag,space.newcomplex(0.0,1.0))
+        return space.add(w_real,w_imag)
+    if space.is_true(space.isinstance(w_real, space.w_str)) or \
+            space.is_true(space.isinstance(w_real, space.w_unicode)):
+        if not space.eq_w(w_imag,space.w_None):
+            raise OperationError(space.w_ValueError, 
+                    space.wrap(ERR_WRONG_SECOND))
+        try:
+            realstr, imagstr = _split_complex(space.str_w(w_real))
+
+        except ValueError:
+            raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED))
+        try:
+            realval = interp_string_to_float(space, realstr)
+            imagval = interp_string_to_float(space, imagstr)
+        except ParseStringError:
+            raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED))
+    else:
+        if space.eq_w(w_imag,space.w_None):
+            w_imag = space.wrap(0.0)
+        try:
+            realval = space.float_w(w_real)
+            imagval = space.float_w(w_imag)
+        except ValueError, e:
+            raise OperationError(space.w_ValueError, space.wrap(e.msg))
+    w_obj = space.allocate_instance(W_ComplexObject, w_complextype)
+    W_ComplexObject.__init__(w_obj, space, realval, imagval)
+
+    return w_obj
+
+def descr_conjugate(space, w_self):
+    from pypy.objspace.std.complexobject import W_ComplexObject
+    return W_ComplexObject(space,w_self._real, -w_self._imag)
+
+def complexwprop(name):
+    def fget(space, w_obj):
+        from pypy.objspace.std.complexobject import W_ComplexObject
+        if not isinstance(w_obj, W_ComplexObject):
+            raise OperationError(space.w_TypeError,
+                                 space.wrap("descriptor is for 'complex'"))
+        return space.newfloat(getattr(w_obj, name))
+    return poss.GetSetProperty(fget)
+
+complex_typedef = poss.StdTypeDef("complex",
+    __doc__ = """complex(real[, imag]) -> complex number
+        
+Create a complex number from a real part and an optional imaginary part.
+This is equivalent to (real + imag*1j) where imag defaults to 0.""",
+    __new__ = poss.newmethod(descr__new__),
+    real = complexwprop('_real'),
+    imag = complexwprop('_imag'),
+    conjugate = poss.newmethod(descr_conjugate)
+    )

Modified: pypy/dist/pypy/objspace/std/model.py
==============================================================================
--- pypy/dist/pypy/objspace/std/model.py	(original)
+++ pypy/dist/pypy/objspace/std/model.py	Wed Feb  8 16:22:59 2006
@@ -18,6 +18,7 @@
             from pypy.objspace.std.booltype   import bool_typedef
             from pypy.objspace.std.inttype    import int_typedef
             from pypy.objspace.std.floattype  import float_typedef
+            #from pypy.objspace.std.complextype  import complex_typedef
             from pypy.objspace.std.tupletype  import tuple_typedef
             from pypy.objspace.std.listtype   import list_typedef
             from pypy.objspace.std.dicttype   import dict_typedef
@@ -40,6 +41,7 @@
         from pypy.objspace.std import boolobject
         from pypy.objspace.std import intobject
         from pypy.objspace.std import floatobject
+        #from pypy.objspace.std import complexobject
         from pypy.objspace.std import tupleobject
         from pypy.objspace.std import listobject
         from pypy.objspace.std import dictobject
@@ -62,6 +64,7 @@
             boolobject.W_BoolObject: [],
             intobject.W_IntObject: [],
             floatobject.W_FloatObject: [],
+            #complexobject.W_ComplexObject: [],
             tupleobject.W_TupleObject: [],
             listobject.W_ListObject: [],
             dictobject.W_DictObject: [],
@@ -94,13 +97,19 @@
             (intobject.W_IntObject,     boolobject.delegate_Bool2Int),
             (longobject.W_LongObject,   longobject.delegate_Bool2Long),
             (floatobject.W_FloatObject, floatobject.delegate_Bool2Float),
+            #(complexobject.W_ComplexObject, complexobject.delegate_Bool2Complex),
             ]
         self.typeorder[intobject.W_IntObject] += [
             (longobject.W_LongObject,   longobject.delegate_Int2Long),
             (floatobject.W_FloatObject, floatobject.delegate_Int2Float),
+            #(complexobject.W_ComplexObject, complexobject.delegate_Int2Complex),
             ]
         self.typeorder[longobject.W_LongObject] += [
             (floatobject.W_FloatObject, floatobject.delegate_Long2Float),
+            #(complexobject.W_ComplexObject, complexobject.delegate_Long2Complex),
+            ]
+        self.typeorder[floatobject.W_FloatObject] += [
+            #(complexobject.W_ComplexObject, complexobject.delegate_Float2Complex),
             ]
         self.typeorder[stringobject.W_StringObject] += [
          (unicodeobject.W_UnicodeObject, unicodeobject.delegate_String2Unicode),

Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py	(original)
+++ pypy/dist/pypy/objspace/std/objspace.py	Wed Feb  8 16:22:59 2006
@@ -276,6 +276,7 @@
             return W_SliceObject(self, self.wrap(x.start),
                                        self.wrap(x.stop),
                                        self.wrap(x.step))
+        # SD disable for native complex
         if isinstance(x, complex):
             # XXX is this right?   YYY no, this is wrong right now  (CT)
             # ZZZ hum, seems necessary for complex literals in co_consts (AR)
@@ -284,6 +285,10 @@
                                       self.wrap(x.real), 
                                       self.wrap(x.imag))
 
+        # SD activate for native complex
+        #if isinstance(x, complex):
+        #    return W_ComplexObject(self, x.real, x.imag)
+
         if self.options.nofaking:
             # annotation should actually not get here 
             raise OperationError(self.w_RuntimeError,
@@ -321,6 +326,10 @@
     def newfloat(self, floatval):
         return W_FloatObject(self, floatval)
 
+    # SD needed for complex
+    #def newcomplex(self, realval, imagval):
+    #    return W_ComplexObject(self, realval, imagval)
+
     def newlong(self, val): # val is an int
         return W_LongObject.fromint(self, val)
 

Added: pypy/dist/pypy/objspace/std/test/helper.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/test/helper.py	Wed Feb  8 16:22:59 2006
@@ -0,0 +1,63 @@
+EPS = 1e-9
+
+def raises(excp, func, *args):
+    try:
+        func(*args)
+        assert 1 == 0
+    except excp:pass
+
+def assertEqual(a, b):
+    assert a == b
+
+def assertAlmostEqual(a, b):
+    if isinstance(a, complex):
+        if isinstance(b, complex):
+            assert a.real - b.real < EPS
+            assert a.imag - b.imag < EPS
+        else:
+            assert a.real - b < EPS
+            assert a.imag < EPS
+    else:
+        if isinstance(b, complex):
+            assert a - b.real < EPS
+            assert b.imag < EPS
+        else:
+            assert a - b < EPS
+
+def assertCloseAbs(x, y, eps=1e-9):
+    """Return true iff floats x and y "are close\""""
+    # put the one with larger magnitude second
+    if abs(x) > abs(y):
+        x, y = y, x
+    if y == 0:
+        return abs(x) < eps
+    if x == 0:
+        return abs(y) < eps
+    # check that relative difference < eps
+    assert abs((x-y)/y) < eps
+
+def assertClose(x, y, eps=1e-9):
+    """Return true iff complexes x and y "are close\""""
+    assertCloseAbs(x.real, y.real, eps)
+    assertCloseAbs(x.imag, y.imag, eps)
+
+def assertIs(a, b):
+    assert a is b
+
+def check_div(x, y):
+    """Compute complex z=x*y, and check that z/x==y and z/y==x."""
+    z = x * y
+    if x != 0:
+        q = z / x
+        assertClose(q, y)
+        q = z.__div__(x)
+        assertClose(q, y)
+        q = z.__truediv__(x)
+        assertClose(q, y)
+    if y != 0:
+        q = z / y
+        assertClose(q, x)
+        q = z.__div__(y)
+        assertClose(q, x)
+        q = z.__truediv__(y)
+        assertClose(q, x)

Added: pypy/dist/pypy/objspace/std/test/test_complexobject.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/test/test_complexobject.py	Wed Feb  8 16:22:59 2006
@@ -0,0 +1,320 @@
+import autopath
+from pypy.objspace.std import complexobject as cobj
+from pypy.objspace.std import complextype as cobjtype
+from pypy.objspace.std.objspace import FailedToImplement
+from pypy.objspace.std.stringobject import W_StringObject
+from pypy.objspace.std import StdObjSpace
+
+EPS = 1e-9
+
+class TestW_ComplexObject:
+
+    def _test_instantiation(self):
+        def _t_complex(r=0.0,i=0.0):
+            c = cobj.W_ComplexObject(self.space, r, i)
+            assert c.real == float(r) and c.imag == float(i)
+        pairs = (
+            (1, 1),
+            (1.0, 2.0),
+            (2L, 3L),
+        )
+        for r,i in pairs:
+            _t_complex(r,i)
+
+    def test_parse_complex(self):
+        f = cobjtype._split_complex
+        def test_cparse(cnum, realnum, imagnum):
+            result = f(cnum)
+            assert len(result) == 2
+            r, i = result
+            assert r == realnum
+            assert i == imagnum
+
+        test_cparse('3', '3', '0.0')
+        test_cparse('3+3j', '3', '3')
+        test_cparse('3.0+3j', '3.0', '3')
+        test_cparse('3L+3j', '3L', '3')
+        test_cparse('3j', '0.0', '3')
+        test_cparse('.e+5', '.e+5', '0.0')
+
+    def test_pow(self):
+        assert cobj._pow((0.0,2.0),(0.0,0.0)) == (1.0,0.0)
+        assert cobj._pow((0.0,0.0),(2.0,0.0)) == (0.0,0.0)
+        rr, ir = cobj._pow((0.0,1.0),(2.0,0.0))
+        assert abs(-1.0 - rr) < EPS
+        assert abs(0.0 - ir) < EPS
+
+        assert cobj._powu((0.0,2.0),0) == (1.0,0.0)
+        assert cobj._powu((0.0,0.0),2) == (0.0,0.0)
+        assert cobj._powu((0.0,1.0),2) == (-1.0,0.0)
+        assert cobj._powi((0.0,2.0),0) == (1.0,0.0)
+        assert cobj._powi((0.0,0.0),2) == (0.0,0.0)
+        assert cobj._powi((0.0,1.0),2) == (-1.0,0.0)
+        c = cobj.W_ComplexObject(self.space,0.0,1.0)
+        p = cobj.W_ComplexObject(self.space,2.0,0.0)
+        r = cobj.pow__Complex_Complex_ANY(self.space,c,p,self.space.wrap(None))
+        assert r._real == -1.0
+        assert r._imag == 0.0
+
+
+class AppTestAppComplexTest:
+    def x_test_div(self):
+        import helper as h
+        simple_real = [float(i) for i in xrange(-5, 6)]
+        simple_complex = [complex(x, y) for x in simple_real for y in simple_real]
+        for x in simple_complex:
+            for y in simple_complex:
+                h.check_div(x, y)
+
+        # A naive complex division algorithm (such as in 2.0) is very prone to
+        # nonsense errors for these (overflows and underflows).
+        h.check_div(complex(1e200, 1e200), 1+0j)
+        h.check_div(complex(1e-200, 1e-200), 1+0j)
+
+        # Just for fun.
+        for i in xrange(100):
+            h.check_div(complex(random(), random()),
+                           complex(random(), random()))
+
+        h.raises(ZeroDivisionError, complex.__div__, 1+1j, 0+0j)
+        # FIXME: The following currently crashes on Alpha
+        # raises(OverflowError, pow, 1e200+1j, 1e200+1j)
+
+    def test_truediv(self):
+        import helper as h
+        h.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)
+        raises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
+
+    def test_floordiv(self):
+        import helper as h
+        h.assertAlmostEqual(complex.__floordiv__(3+0j, 1.5+0j), 2)
+        raises(ZeroDivisionError, complex.__floordiv__, 3+0j, 0+0j)
+
+    def test_coerce(self):
+        import helper as h
+        h.raises(OverflowError, complex.__coerce__, 1+1j, 1L<<10000)
+
+    def x_test_richcompare(self):
+        import helper as h
+        h.raises(OverflowError, complex.__eq__, 1+1j, 1L<<10000)
+        h.assertEqual(complex.__lt__(1+1j, None), NotImplemented)
+        h.assertIs(complex.__eq__(1+1j, 1+1j), True)
+        h.assertIs(complex.__eq__(1+1j, 2+2j), False)
+        h.assertIs(complex.__ne__(1+1j, 1+1j), False)
+        h.assertIs(complex.__ne__(1+1j, 2+2j), True)
+        h.raises(TypeError, complex.__lt__, 1+1j, 2+2j)
+        h.raises(TypeError, complex.__le__, 1+1j, 2+2j)
+        h.raises(TypeError, complex.__gt__, 1+1j, 2+2j)
+        h.raises(TypeError, complex.__ge__, 1+1j, 2+2j)
+
+    def test_mod(self):
+        import helper as h
+        raises(ZeroDivisionError, (1+1j).__mod__, 0+0j)
+
+        a = 3.33+4.43j
+        try:
+            a % 0
+        except ZeroDivisionError:
+            pass
+        else:
+            self.fail("modulo parama can't be 0")
+
+    def test_divmod(self):
+        import helper as h
+        raises(ZeroDivisionError, divmod, 1+1j, 0+0j)
+
+    def test_pow(self):
+        import helper as h
+        h.assertAlmostEqual(pow(1+1j, 0+0j), 1.0)
+        h.assertAlmostEqual(pow(0+0j, 2+0j), 0.0)
+        raises(ZeroDivisionError, pow, 0+0j, 1j)
+        h.assertAlmostEqual(pow(1j, -1), 1/1j)
+        h.assertAlmostEqual(pow(1j, 200), 1)
+        raises(ValueError, pow, 1+1j, 1+1j, 1+1j)
+
+        a = 3.33+4.43j
+        h.assertEqual(a ** 0j, 1)
+        h.assertEqual(a ** 0.+0.j, 1)
+
+        h.assertEqual(3j ** 0j, 1)
+        h.assertEqual(3j ** 0, 1)
+
+        try:
+            0j ** a
+        except ZeroDivisionError:
+            pass
+        else:
+            self.fail("should fail 0.0 to negative or complex power")
+
+        try:
+            0j ** (3-2j)
+        except ZeroDivisionError:
+            pass
+        else:
+            self.fail("should fail 0.0 to negative or complex power")
+
+        # The following is used to exercise certain code paths
+        h.assertEqual(a ** 105, a ** 105)
+        h.assertEqual(a ** -105, a ** -105)
+        h.assertEqual(a ** -30, a ** -30)
+
+        h.assertEqual(0.0j ** 0, 1)
+
+        b = 5.1+2.3j
+        h.raises(ValueError, pow, a, b, 0)
+
+    def test_boolcontext(self):
+        from random import random
+        import helper as h
+        for i in xrange(100):
+            assert complex(random() + 1e-6, random() + 1e-6)
+        assert not complex(0.0, 0.0)
+
+    def test_conjugate(self):
+        import helper as h
+        h.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
+
+    def x_test_constructor(self):
+        import helper as h
+        class OS:
+            def __init__(self, value): self.value = value
+            def __complex__(self): return self.value
+        class NS(object):
+            def __init__(self, value): self.value = value
+            def __complex__(self): return self.value
+        h.assertEqual(complex(OS(1+10j)), 1+10j)
+        h.assertEqual(complex(NS(1+10j)), 1+10j)
+        h.raises(TypeError, complex, OS(None))
+        h.raises(TypeError, complex, NS(None))
+
+        h.assertAlmostEqual(complex("1+10j"), 1+10j)
+        h.assertAlmostEqual(complex(10), 10+0j)
+        h.assertAlmostEqual(complex(10.0), 10+0j)
+        h.assertAlmostEqual(complex(10L), 10+0j)
+        h.assertAlmostEqual(complex(10+0j), 10+0j)
+        h.assertAlmostEqual(complex(1,10), 1+10j)
+        h.assertAlmostEqual(complex(1,10L), 1+10j)
+        h.assertAlmostEqual(complex(1,10.0), 1+10j)
+        h.assertAlmostEqual(complex(1L,10), 1+10j)
+        h.assertAlmostEqual(complex(1L,10L), 1+10j)
+        h.assertAlmostEqual(complex(1L,10.0), 1+10j)
+        h.assertAlmostEqual(complex(1.0,10), 1+10j)
+        h.assertAlmostEqual(complex(1.0,10L), 1+10j)
+        h.assertAlmostEqual(complex(1.0,10.0), 1+10j)
+        h.assertAlmostEqual(complex(3.14+0j), 3.14+0j)
+        h.assertAlmostEqual(complex(3.14), 3.14+0j)
+        h.assertAlmostEqual(complex(314), 314.0+0j)
+        h.assertAlmostEqual(complex(314L), 314.0+0j)
+        h.assertAlmostEqual(complex(3.14+0j, 0j), 3.14+0j)
+        h.assertAlmostEqual(complex(3.14, 0.0), 3.14+0j)
+        h.assertAlmostEqual(complex(314, 0), 314.0+0j)
+        h.assertAlmostEqual(complex(314L, 0L), 314.0+0j)
+        h.assertAlmostEqual(complex(0j, 3.14j), -3.14+0j)
+        h.assertAlmostEqual(complex(0.0, 3.14j), -3.14+0j)
+        h.assertAlmostEqual(complex(0j, 3.14), 3.14j)
+        h.assertAlmostEqual(complex(0.0, 3.14), 3.14j)
+        h.assertAlmostEqual(complex("1"), 1+0j)
+        h.assertAlmostEqual(complex("1j"), 1j)
+        h.assertAlmostEqual(complex(),  0)
+        h.assertAlmostEqual(complex("-1"), -1)
+        h.assertAlmostEqual(complex("+1"), +1)
+
+        class complex2(complex): pass
+        h.assertAlmostEqual(complex(complex2(1+1j)), 1+1j)
+        h.assertAlmostEqual(complex(real=17, imag=23), 17+23j)
+        h.assertAlmostEqual(complex(real=17+23j), 17+23j)
+        h.assertAlmostEqual(complex(real=17+23j, imag=23), 17+46j)
+        h.assertAlmostEqual(complex(real=1+2j, imag=3+4j), -3+5j)
+
+        c = 3.14 + 1j
+        assert complex(c) is c
+        del c
+
+        h.raises(TypeError, complex, "1", "1")
+        h.raises(TypeError, complex, 1, "1")
+
+        h.assertEqual(complex("  3.14+J  "), 3.14+1j)
+        #h.assertEqual(complex(unicode("  3.14+J  ")), 3.14+1j)
+
+        # SF bug 543840:  complex(string) accepts strings with \0
+        # Fixed in 2.3.
+        h.raises(ValueError, complex, '1+1j\0j')
+
+        h.raises(TypeError, int, 5+3j)
+        h.raises(TypeError, long, 5+3j)
+        h.raises(TypeError, float, 5+3j)
+        h.raises(ValueError, complex, "")
+        h.raises(TypeError, complex, None)
+        h.raises(ValueError, complex, "\0")
+        h.raises(TypeError, complex, "1", "2")
+        h.raises(TypeError, complex, "1", 42)
+        h.raises(TypeError, complex, 1, "2")
+        h.raises(ValueError, complex, "1+")
+        h.raises(ValueError, complex, "1+1j+1j")
+        h.raises(ValueError, complex, "--")
+#        if x_test_support.have_unicode:
+#            h.raises(ValueError, complex, unicode("1"*500))
+#            h.raises(ValueError, complex, unicode("x"))
+#
+        class EvilExc(Exception):
+            pass
+
+        class evilcomplex:
+            def __complex__(self):
+                raise EvilExc
+
+        h.raises(EvilExc, complex, evilcomplex())
+
+        class float2:
+            def __init__(self, value):
+                self.value = value
+            def __float__(self):
+                return self.value
+
+        h.assertAlmostEqual(complex(float2(42.)), 42)
+        h.assertAlmostEqual(complex(real=float2(17.), imag=float2(23.)), 17+23j)
+        h.raises(TypeError, complex, float2(None))
+
+    def test_hash(self):
+        import helper as h
+        for x in xrange(-30, 30):
+            h.assertEqual(hash(x), hash(complex(x, 0)))
+            x /= 3.0    # now check against floating point
+            h.assertEqual(hash(x), hash(complex(x, 0.)))
+
+    def x_test_abs(self):
+        import helper as h
+        nums = [complex(x/3., y/7.) for x in xrange(-9,9) for y in xrange(-9,9)]
+        for num in nums:
+            self.assertAlmostEqual((num.real**2 + num.imag**2)  ** 0.5, abs(num))
+
+    def x_test_repr(self):
+        import helper as h
+        self.assertEqual(repr(1+6j), '(1+6j)')
+        self.assertEqual(repr(1-6j), '(1-6j)')
+
+        self.assertNotEqual(repr(-(1+0j)), '(-1+-0j)')
+
+    def x_test_neg(self):
+        import helper as h
+        self.assertEqual(-(1+6j), -1-6j)
+
+    def x_test_file(self):
+        import helper as h
+        a = 3.33+4.43j
+        b = 5.1+2.3j
+
+        fo = None
+        try:
+            fo = open(test_support.TESTFN, "wb")
+            print >>fo, a, b
+            fo.close()
+            fo = open(test_support.TESTFN, "rb")
+            self.assertEqual(fo.read(), "%s %s\n" % (a, b))
+        finally:
+            if (fo is not None) and (not fo.closed):
+                fo.close()
+            try:
+                os.remove(test_support.TESTFN)
+            except (OSError, IOError):
+                pass



More information about the Pypy-commit mailing list