Author: Manuel Jacob Branch: remove-remaining-smm Changeset: r69299:4286faa95835 Date: 2014-02-23 21:36 +0100 http://bitbucket.org/pypy/pypy/changeset/4286faa95835/
Log: Kill complextype.py, kill conjugate SMM. diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -6,7 +6,7 @@ from pypy.objspace.std.floattype import float_typedef from pypy.objspace.std.unicodeobject import W_UnicodeObject from pypy.objspace.std.intobject import W_IntObject -from pypy.objspace.std.complextype import complex_typedef +from pypy.objspace.std.complexobject import W_ComplexObject from rpython.rlib.rarithmetic import LONG_BIT from rpython.rtyper.lltypesystem import rffi from rpython.tool.sourcetools import func_with_new_name @@ -770,7 +770,7 @@ imag = GetSetProperty(W_ComplexFloatingBox.descr_get_imag), ) -W_Complex128Box.typedef = TypeDef("complex128", (W_ComplexFloatingBox.typedef, complex_typedef), +W_Complex128Box.typedef = TypeDef("complex128", (W_ComplexFloatingBox.typedef, W_ComplexObject.typedef), __module__ = "numpy", __new__ = interp2app(W_Complex128Box.descr__new__.im_func), __reduce__ = interp2app(W_Complex128Box.descr_reduce), @@ -785,7 +785,7 @@ __reduce__ = interp2app(W_FloatLongBox.descr_reduce), ) - W_ComplexLongBox.typedef = TypeDef("complex%d" % (long_double_size * 16), (W_ComplexFloatingBox.typedef, complex_typedef), + W_ComplexLongBox.typedef = TypeDef("complex%d" % (long_double_size * 16), (W_ComplexFloatingBox.typedef, W_ComplexObject.typedef), __module__ = "numpy", __new__ = interp2app(W_ComplexLongBox.descr__new__.im_func), __reduce__ = interp2app(W_ComplexLongBox.descr_reduce), diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py --- a/pypy/objspace/std/complexobject.py +++ b/pypy/objspace/std/complexobject.py @@ -1,18 +1,27 @@ -from pypy.interpreter import gateway -from pypy.interpreter.error import OperationError +import math + +from pypy.interpreter.error import OperationError, oefmt +from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault from pypy.objspace.std import newformat +from pypy.objspace.std.floatobject import W_FloatObject, _hash_float from pypy.objspace.std.intobject import W_IntObject +from pypy.objspace.std.longobject import W_LongObject from pypy.objspace.std.model import registerimplementation, W_Object +from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.register_all import register_all -from pypy.objspace.std.floatobject import W_FloatObject, _hash_float -from pypy.objspace.std.longobject import W_LongObject +from pypy.objspace.std.stdtypedef import GetSetProperty, StdTypeDef +from rpython.rlib import jit, rcomplex +from rpython.rlib.rarithmetic import intmask, r_ulonglong from rpython.rlib.rbigint import rbigint from rpython.rlib.rfloat import ( - formatd, DTSF_STR_PRECISION, isinf, isnan, copysign) -from rpython.rlib import jit, rcomplex -from rpython.rlib.rarithmetic import intmask, r_ulonglong + formatd, DTSF_STR_PRECISION, isinf, isnan, copysign, string_to_float) +from rpython.rlib.rstring import ParseStringError -import math + +# ERRORCODES + +ERR_WRONG_SECOND = "complex() can't take second arg if first is a string" +ERR_MALFORMED = "complex() arg is a malformed string" class W_AbstractComplexObject(W_Object): @@ -47,10 +56,168 @@ return space.newlong_from_rbigint(val) +def _split_complex(s): + slen = len(s) + if slen == 0: + raise ValueError + realstart = 0 + realstop = 0 + imagstart = 0 + imagstop = 0 + imagsign = ' ' + i = 0 + # ignore whitespace at beginning and end + while i < slen and s[i] == ' ': + i += 1 + while slen > 0 and s[slen-1] == ' ': + slen -= 1 + + if s[i] == '(' and s[slen-1] == ')': + i += 1 + slen -= 1 + # ignore whitespace after bracket + while i < slen and s[i] == ' ': + i += 1 + + # extract first number + realstart = i + pc = s[i] + while i < slen and s[i] != ' ': + if s[i] in ('+','-') and pc not in ('e','E') and i != realstart: + break + pc = s[i] + i += 1 + + realstop = i + + # ignore whitespace + while i < slen and s[i] == ' ': + i += 1 + + # return appropriate strings is only one number is there + if i >= slen: + newstop = realstop - 1 + if newstop < 0: + raise ValueError + if s[newstop] in ('j', 'J'): + if realstart == newstop: + imagpart = '1.0' + elif realstart == newstop-1 and s[realstart] == '+': + imagpart = '1.0' + elif realstart == newstop-1 and s[realstart] == '-': + imagpart = '-1.0' + else: + imagpart = s[realstart:newstop] + return '0.0', imagpart + else: + return s[realstart:realstop], '0.0' + + # find sign for imaginary part + if s[i] == '-' or s[i] == '+': + imagsign = s[i] + if imagsign == ' ': + raise ValueError + + i+=1 + # whitespace + while i < slen and s[i] == ' ': + i += 1 + if i >= slen: + raise ValueError + + imagstart = i + pc = s[i] + while i < slen and s[i] != ' ': + if s[i] in ('+','-') and pc not in ('e','E'): + break + pc = s[i] + i += 1 + + imagstop = i - 1 + if imagstop < 0: + raise ValueError + if s[imagstop] not in ('j','J'): + raise ValueError + if imagstop < imagstart: + raise ValueError + + while i<slen and s[i] == ' ': + i += 1 + if i < slen: + raise ValueError + + realpart = s[realstart:realstop] + if imagstart == imagstop: + imagpart = '1.0' + else: + imagpart = s[imagstart:imagstop] + if imagsign == '-': + imagpart = imagsign + imagpart + + return realpart, imagpart + + + +def unpackcomplex(space, w_complex, strict_typing=True): + """ + convert w_complex into a complex and return the unwrapped (real, imag) + tuple. If strict_typing==True, we also typecheck the value returned by + __complex__ to actually be a complex (and not e.g. a float). + See test___complex___returning_non_complex. + """ + from pypy.objspace.std.complexobject import W_ComplexObject + if type(w_complex) is W_ComplexObject: + return (w_complex.realval, w_complex.imagval) + # + # test for a '__complex__' method, and call it if found. + # special case old-style instances, like CPython does. + w_z = None + if space.is_oldstyle_instance(w_complex): + try: + w_method = space.getattr(w_complex, space.wrap('__complex__')) + except OperationError, e: + if not e.match(space, space.w_AttributeError): + raise + else: + w_z = space.call_function(w_method) + else: + w_method = space.lookup(w_complex, '__complex__') + if w_method is not None: + w_z = space.get_and_call_function(w_method, w_complex) + # + if w_z is not None: + # __complex__() must return a complex or (float,int,long) object + # (XXX should not use isinstance here) + if not strict_typing and (space.isinstance_w(w_z, space.w_int) or + space.isinstance_w(w_z, space.w_long) or + space.isinstance_w(w_z, space.w_float)): + return (space.float_w(w_z), 0.0) + elif isinstance(w_z, W_ComplexObject): + return (w_z.realval, w_z.imagval) + raise OperationError(space.w_TypeError, + space.wrap("__complex__() must return" + " a complex number")) + + # + # no '__complex__' method, so we assume it is a float, + # unless it is an instance of some subclass of complex. + if space.isinstance_w(w_complex, space.gettypefor(W_ComplexObject)): + real = space.float(space.getattr(w_complex, space.wrap("real"))) + imag = space.float(space.getattr(w_complex, space.wrap("imag"))) + return (space.float_w(real), space.float_w(imag)) + # + # Check that it is not a string (on which space.float() would succeed). + if (space.isinstance_w(w_complex, space.w_str) or + space.isinstance_w(w_complex, space.w_unicode)): + raise oefmt(space.w_TypeError, + "complex number expected, got '%T'", w_complex) + # + return (space.float_w(space.float(w_complex)), 0.0) + + class W_ComplexObject(W_AbstractComplexObject): """This is a reimplementation of the CPython "PyComplexObject" """ - from pypy.objspace.std.complextype import complex_typedef as typedef _immutable_fields_ = ['realval', 'imagval'] def __init__(self, realval=0.0, imgval=0.0): @@ -115,6 +282,67 @@ def int(self, space): raise OperationError(space.w_TypeError, space.wrap("can't convert complex to int; use int(abs(z))")) + @staticmethod + @unwrap_spec(w_real = WrappedDefault(0.0)) + def descr__new__(space, w_complextype, w_real, w_imag=None): + from pypy.objspace.std.complexobject import W_ComplexObject + + # if w_real is already a complex number and there is no second + # argument, return it. Note that we cannot return w_real if + # it is an instance of a *subclass* of complex, or if w_complextype + # is itself a subclass of complex. + noarg2 = w_imag is None + if (noarg2 and space.is_w(w_complextype, space.w_complex) + and space.is_w(space.type(w_real), space.w_complex)): + return w_real + + if space.isinstance_w(w_real, space.w_str) or \ + space.isinstance_w(w_real, space.w_unicode): + # a string argument + if not noarg2: + raise OperationError(space.w_TypeError, + space.wrap("complex() can't take second arg" + " if first is a string")) + try: + realstr, imagstr = _split_complex(space.str_w(w_real)) + except ValueError: + raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED)) + try: + realval = string_to_float(realstr) + imagval = string_to_float(imagstr) + except ParseStringError: + raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED)) + + else: + # non-string arguments + realval, imagval = unpackcomplex(space, w_real, strict_typing=False) + + # now take w_imag into account + if not noarg2: + # complex(x, y) == x+y*j, even if 'y' is already a complex. + realval2, imagval2 = unpackcomplex(space, w_imag, strict_typing=False) + + # try to preserve the signs of zeroes of realval and realval2 + if imagval2 != 0.0: + realval -= imagval2 + + if imagval != 0.0: + imagval += realval2 + else: + imagval = realval2 + # done + w_obj = space.allocate_instance(W_ComplexObject, w_complextype) + W_ComplexObject.__init__(w_obj, realval, imagval) + return w_obj + + def descr___getnewargs__(self, space): + return space.newtuple([space.newfloat(self.realval), + space.newfloat(self.imagval)]) + + def descr_conjugate(self, space): + """(A+Bj).conjugate() -> A-Bj""" + return space.newcomplex(self.realval, -self.imagval) + registerimplementation(W_ComplexObject) w_one = W_ComplexObject(1, 0) @@ -250,11 +478,6 @@ def float__Complex(space, w_complex): raise OperationError(space.w_TypeError, space.wrap("can't convert complex to float; use abs(z)")) -def complex_conjugate__Complex(space, w_self): - #w_real = space.call_function(space.w_float,space.wrap(w_self.realval)) - #w_imag = space.call_function(space.w_float,space.wrap(-w_self.imagval)) - return space.newcomplex(w_self.realval,-w_self.imagval) - def format_float(x, code, precision): # like float2string, except that the ".0" is not necessary if isinf(x): @@ -291,5 +514,26 @@ def format__Complex_ANY(space, w_complex, w_format_spec): return newformat.run_formatter(space, w_format_spec, "format_complex", w_complex) -from pypy.objspace.std import complextype -register_all(vars(), complextype) +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 GetSetProperty(fget) + +W_ComplexObject.typedef = 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__ = interp2app(W_ComplexObject.descr__new__), + __getnewargs__ = interp2app(W_ComplexObject.descr___getnewargs__), + real = complexwprop('realval'), + imag = complexwprop('imagval'), + conjugate = interp2app(W_ComplexObject.descr_conjugate) + ) + +W_ComplexObject.typedef.registermethods(globals()) +register_all(vars(), globals()) diff --git a/pypy/objspace/std/complextype.py b/pypy/objspace/std/complextype.py deleted file mode 100644 --- a/pypy/objspace/std/complextype.py +++ /dev/null @@ -1,257 +0,0 @@ -from pypy.interpreter.error import OperationError, oefmt -from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault -from pypy.objspace.std.register_all import register_all -from pypy.objspace.std.noneobject import W_NoneObject -from pypy.objspace.std.stdtypedef import GetSetProperty, StdTypeDef -from pypy.objspace.std.stdtypedef import StdObjSpaceMultiMethod -from rpython.rlib.rfloat import string_to_float -from rpython.rlib.rstring import ParseStringError - -# ERRORCODES - -ERR_WRONG_SECOND = "complex() can't take second arg if first is a string" -ERR_MALFORMED = "complex() arg is a malformed string" - -complex_conjugate = StdObjSpaceMultiMethod('conjugate', 1, - doc="(A+Bj).conjugate() -> A-Bj") - -register_all(vars(),globals()) - -def _split_complex(s): - slen = len(s) - if slen == 0: - raise ValueError - realstart = 0 - realstop = 0 - imagstart = 0 - imagstop = 0 - imagsign = ' ' - i = 0 - # ignore whitespace at beginning and end - while i < slen and s[i] == ' ': - i += 1 - while slen > 0 and s[slen-1] == ' ': - slen -= 1 - - if s[i] == '(' and s[slen-1] == ')': - i += 1 - slen -= 1 - # ignore whitespace after bracket - while i < slen and s[i] == ' ': - i += 1 - - # extract first number - realstart = i - pc = s[i] - while i < slen and s[i] != ' ': - if s[i] in ('+','-') and pc not in ('e','E') and i != realstart: - break - pc = s[i] - i += 1 - - realstop = i - - # ignore whitespace - while i < slen and s[i] == ' ': - i += 1 - - # return appropriate strings is only one number is there - if i >= slen: - newstop = realstop - 1 - if newstop < 0: - raise ValueError - if s[newstop] in ('j', 'J'): - if realstart == newstop: - imagpart = '1.0' - elif realstart == newstop-1 and s[realstart] == '+': - imagpart = '1.0' - elif realstart == newstop-1 and s[realstart] == '-': - imagpart = '-1.0' - else: - imagpart = s[realstart:newstop] - return '0.0', imagpart - else: - return s[realstart:realstop], '0.0' - - # find sign for imaginary part - if s[i] == '-' or s[i] == '+': - imagsign = s[i] - if imagsign == ' ': - raise ValueError - - i+=1 - # whitespace - while i < slen and s[i] == ' ': - i += 1 - if i >= slen: - raise ValueError - - imagstart = i - pc = s[i] - while i < slen and s[i] != ' ': - if s[i] in ('+','-') and pc not in ('e','E'): - break - pc = s[i] - i += 1 - - imagstop = i - 1 - if imagstop < 0: - raise ValueError - if s[imagstop] not in ('j','J'): - raise ValueError - if imagstop < imagstart: - raise ValueError - - while i<slen and s[i] == ' ': - i += 1 - if i < slen: - raise ValueError - - realpart = s[realstart:realstop] - if imagstart == imagstop: - imagpart = '1.0' - else: - imagpart = s[imagstart:imagstop] - if imagsign == '-': - imagpart = imagsign + imagpart - - return realpart, imagpart - - -@unwrap_spec(w_real = WrappedDefault(0.0)) -def descr__new__(space, w_complextype, w_real, w_imag=None): - from pypy.objspace.std.complexobject import W_ComplexObject - - # if w_real is already a complex number and there is no second - # argument, return it. Note that we cannot return w_real if - # it is an instance of a *subclass* of complex, or if w_complextype - # is itself a subclass of complex. - noarg2 = w_imag is None - if (noarg2 and space.is_w(w_complextype, space.w_complex) - and space.is_w(space.type(w_real), space.w_complex)): - return w_real - - if space.isinstance_w(w_real, space.w_str) or \ - space.isinstance_w(w_real, space.w_unicode): - # a string argument - if not noarg2: - raise OperationError(space.w_TypeError, - space.wrap("complex() can't take second arg" - " if first is a string")) - try: - realstr, imagstr = _split_complex(space.str_w(w_real)) - except ValueError: - raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED)) - try: - realval = string_to_float(realstr) - imagval = string_to_float(imagstr) - except ParseStringError: - raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED)) - - else: - # non-string arguments - realval, imagval = unpackcomplex(space, w_real, strict_typing=False) - - # now take w_imag into account - if not noarg2: - # complex(x, y) == x+y*j, even if 'y' is already a complex. - realval2, imagval2 = unpackcomplex(space, w_imag, strict_typing=False) - - # try to preserve the signs of zeroes of realval and realval2 - if imagval2 != 0.0: - realval -= imagval2 - - if imagval != 0.0: - imagval += realval2 - else: - imagval = realval2 - # done - w_obj = space.allocate_instance(W_ComplexObject, w_complextype) - W_ComplexObject.__init__(w_obj, realval, imagval) - return w_obj - - -def unpackcomplex(space, w_complex, strict_typing=True): - """ - convert w_complex into a complex and return the unwrapped (real, imag) - tuple. If strict_typing==True, we also typecheck the value returned by - __complex__ to actually be a complex (and not e.g. a float). - See test___complex___returning_non_complex. - """ - from pypy.objspace.std.complexobject import W_ComplexObject - if type(w_complex) is W_ComplexObject: - return (w_complex.realval, w_complex.imagval) - # - # test for a '__complex__' method, and call it if found. - # special case old-style instances, like CPython does. - w_z = None - if space.is_oldstyle_instance(w_complex): - try: - w_method = space.getattr(w_complex, space.wrap('__complex__')) - except OperationError, e: - if not e.match(space, space.w_AttributeError): - raise - else: - w_z = space.call_function(w_method) - else: - w_method = space.lookup(w_complex, '__complex__') - if w_method is not None: - w_z = space.get_and_call_function(w_method, w_complex) - # - if w_z is not None: - # __complex__() must return a complex or (float,int,long) object - # (XXX should not use isinstance here) - if not strict_typing and (space.isinstance_w(w_z, space.w_int) or - space.isinstance_w(w_z, space.w_long) or - space.isinstance_w(w_z, space.w_float)): - return (space.float_w(w_z), 0.0) - elif isinstance(w_z, W_ComplexObject): - return (w_z.realval, w_z.imagval) - raise OperationError(space.w_TypeError, - space.wrap("__complex__() must return" - " a complex number")) - - # - # no '__complex__' method, so we assume it is a float, - # unless it is an instance of some subclass of complex. - if space.isinstance_w(w_complex, space.gettypefor(W_ComplexObject)): - real = space.float(space.getattr(w_complex, space.wrap("real"))) - imag = space.float(space.getattr(w_complex, space.wrap("imag"))) - return (space.float_w(real), space.float_w(imag)) - # - # Check that it is not a string (on which space.float() would succeed). - if (space.isinstance_w(w_complex, space.w_str) or - space.isinstance_w(w_complex, space.w_unicode)): - raise oefmt(space.w_TypeError, - "complex number expected, got '%T'", w_complex) - # - return (space.float_w(space.float(w_complex)), 0.0) - - -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 GetSetProperty(fget) - -def descr___getnewargs__(space, w_self): - from pypy.objspace.std.complexobject import W_ComplexObject - assert isinstance(w_self, W_ComplexObject) - return space.newtuple([space.newfloat(w_self.realval), - space.newfloat(w_self.imagval)]) - -complex_typedef = 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__ = interp2app(descr__new__), - __getnewargs__ = interp2app(descr___getnewargs__), - real = complexwprop('realval'), - imag = complexwprop('imagval'), - ) - -complex_typedef.registermethods(globals()) diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py --- a/pypy/objspace/std/model.py +++ b/pypy/objspace/std/model.py @@ -33,7 +33,6 @@ class result: from pypy.objspace.std.objecttype import object_typedef from pypy.objspace.std.floattype import float_typedef - from pypy.objspace.std.complextype import complex_typedef from pypy.objspace.std.typeobject import type_typedef from pypy.objspace.std.slicetype import slice_typedef from pypy.objspace.std.nonetype import none_typedef @@ -58,6 +57,7 @@ from pypy.objspace.std import typeobject from pypy.objspace.std import sliceobject from pypy.objspace.std import longobject + from pypy.objspace.std import complexobject from pypy.objspace.std import noneobject from pypy.objspace.std import iterobject from pypy.objspace.std import unicodeobject @@ -82,6 +82,7 @@ self.pythontypes.append(intobject.W_IntObject.typedef) self.pythontypes.append(boolobject.W_BoolObject.typedef) self.pythontypes.append(longobject.W_LongObject.typedef) + self.pythontypes.append(complexobject.W_ComplexObject.typedef) # the set of implementation types self.typeorder = { diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py --- a/pypy/objspace/std/objspace.py +++ b/pypy/objspace/std/objspace.py @@ -270,7 +270,7 @@ return W_ComplexObject(realval, imagval) def unpackcomplex(self, w_complex): - from pypy.objspace.std.complextype import unpackcomplex + from pypy.objspace.std.complexobject import unpackcomplex return unpackcomplex(self, w_complex) def newlong(self, val): # val is an int diff --git a/pypy/objspace/std/test/test_complexobject.py b/pypy/objspace/std/test/test_complexobject.py --- a/pypy/objspace/std/test/test_complexobject.py +++ b/pypy/objspace/std/test/test_complexobject.py @@ -1,7 +1,6 @@ import py from pypy.objspace.std.complexobject import W_ComplexObject, \ - pow__Complex_Complex_ANY -from pypy.objspace.std import complextype as cobjtype + pow__Complex_Complex_ANY, _split_complex from pypy.objspace.std.multimethod import FailedToImplement from pypy.objspace.std import StdObjSpace @@ -21,7 +20,7 @@ _t_complex(r,i) def test_parse_complex(self): - f = cobjtype._split_complex + f = _split_complex def test_cparse(cnum, realnum, imagnum): result = f(cnum) assert len(result) == 2 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit