Author: Alex Gaynor <alex.gay...@gmail.com> Branch: numpy-dtype-refactor Changeset: r48983:f9f4bedbab84 Date: 2011-11-08 22:22 -0500 http://bitbucket.org/pypy/pypy/changeset/f9f4bedbab84/
Log: begin refactoring everything. nothing works. diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py --- a/pypy/module/micronumpy/compile.py +++ b/pypy/module/micronumpy/compile.py @@ -4,7 +4,8 @@ """ from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root -from pypy.module.micronumpy.interp_dtype import W_Float64Dtype, W_BoolDtype +from pypy.module.micronumpy.interp_boxes import W_GenericBox +from pypy.module.micronumpy.interp_dtype import get_dtype_cache from pypy.module.micronumpy.interp_numarray import (Scalar, BaseArray, descr_new_array, scalar_w, SingleDimArray) from pypy.module.micronumpy import interp_ufuncs @@ -40,7 +41,7 @@ def __init__(self): """NOT_RPYTHON""" self.fromcache = InternalSpaceCache(self).getorbuild - self.w_float64dtype = W_Float64Dtype(self) + self.w_float64dtype = get_dtype_cache(self).w_float64dtype def issequence_w(self, w_obj): return isinstance(w_obj, ListObject) or isinstance(w_obj, SingleDimArray) @@ -73,7 +74,7 @@ return w_obj def float_w(self, w_obj): - assert isinstance(w_obj, FloatObject) + assert isinstance(w_obj, FloatObject) return w_obj.floatval def int_w(self, w_obj): @@ -206,18 +207,18 @@ elif self.name == '*': w_res = w_lhs.descr_mul(interp.space, w_rhs) elif self.name == '-': - w_res = w_lhs.descr_sub(interp.space, w_rhs) + w_res = w_lhs.descr_sub(interp.space, w_rhs) elif self.name == '->': if isinstance(w_rhs, Scalar): index = int(interp.space.float_w( - w_rhs.value.wrap(interp.space))) + w_rhs.value)) dtype = interp.space.fromcache(W_Float64Dtype) return Scalar(dtype, w_lhs.get_concrete().eval(index)) else: raise NotImplementedError else: raise NotImplementedError - if not isinstance(w_res, BaseArray): + if not isinstance(w_res, BaseArray) and not isinstance(w_res, W_GenericBox): dtype = interp.space.fromcache(W_Float64Dtype) w_res = scalar_w(interp.space, dtype, w_res) return w_res @@ -236,8 +237,7 @@ return space.wrap(self.v) def execute(self, interp): - dtype = interp.space.fromcache(W_Float64Dtype) - assert isinstance(dtype, W_Float64Dtype) + dtype = get_dtype_cache(interp.space).w_float64dtype return Scalar(dtype, dtype.box(self.v)) class RangeConstant(Node): @@ -269,7 +269,7 @@ def execute(self, interp): w_list = self.wrap(interp.space) - dtype = interp.space.fromcache(W_Float64Dtype) + dtype = get_dtype_cache(interp.space).w_float64dtype return descr_new_array(interp.space, None, w_list, w_dtype=dtype) def __repr__(self): @@ -414,7 +414,7 @@ assert lgt >= 0 rhs = self.parse_constant_or_identifier(l[1][:lgt]) return l[0], rhs - + def parse_statement(self, line): if '=' in line: lhs, rhs = line.split("=") @@ -422,7 +422,7 @@ if '[' in lhs: name, index = self.parse_array_subscript(lhs) return ArrayAssignment(name, index, self.parse_expression(rhs)) - else: + else: return Assignment(lhs, self.parse_expression(rhs)) else: return Execute(self.parse_expression(line)) diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -1,519 +1,132 @@ -import functools -import math - from pypy.interpreter.baseobjspace import Wrappable -from pypy.interpreter.error import OperationError -from pypy.interpreter.gateway import interp2app -from pypy.interpreter.typedef import TypeDef, interp_attrproperty, GetSetProperty -from pypy.module.micronumpy import signature -from pypy.objspace.std.floatobject import float2string -from pypy.rlib import rarithmetic, rfloat -from pypy.rlib.rarithmetic import LONG_BIT, widen -from pypy.rlib.objectmodel import specialize, enforceargs -from pypy.rlib.unroll import unrolling_iterable +from pypy.module.micronumpy import types, signature +from pypy.rlib.objectmodel import specialize +from pypy.rlib.rarithmetic import LONG_BIT from pypy.rpython.lltypesystem import lltype, rffi +STORAGE_TYPE = lltype.Array(lltype.Char, hints={"nolength": True}) + UNSIGNEDLTR = "u" SIGNEDLTR = "i" BOOLLTR = "b" FLOATINGLTR = "f" class W_Dtype(Wrappable): + def __init__(self, itemtype, num, kind): + self.signature = signature.BaseSignature() + self.itemtype = itemtype + self.num = num + self.kind = kind + + def malloc(self, length): + # XXX find out why test_zjit explodes with tracking of allocations + return lltype.malloc(STORAGE_TYPE, self.itemtype.get_element_size() * length, + zero=True, flavor="raw", + track_allocation=False, add_memory_pressure=True + ) + + @specialize.argtype(1) + def box(self, value): + return self.itemtype.box(value) + + def coerce(self, space, w_item): + return self.itemtype.coerce(space, w_item) + + def getitem(self, storage, i): + struct_ptr = rffi.ptradd(storage, i * self.itemtype.get_element_size()) + return self.itemtype.read(struct_ptr, 0) + + def setitem(self, storage, i, box): + struct_ptr = rffi.ptradd(storage, i * self.itemtype.get_element_size()) + self.itemtype.store(struct_ptr, 0, box) + + +class DtypeCache(object): def __init__(self, space): - pass + self.w_booldtype = W_Dtype( + types.Bool(), + num=0, + kind=BOOLLTR, + ) + self.w_int8dtype = W_Dtype( + types.Int8(), + num=1, + kind=SIGNEDLTR, + ) + self.w_uint8dtype = W_Dtype( + types.UInt8(), + num=2, + kind=UNSIGNEDLTR, + ) + self.w_int16dtype = W_Dtype( + types.Int16(), + num=3, + kind=SIGNEDLTR, + ) + self.w_uint16dtype = W_Dtype( + types.UInt16(), + num=4, + kind=UNSIGNEDLTR, + ) + self.w_int32dtype = W_Dtype( + types.Int32(), + num=5, + kind=SIGNEDLTR, + ) + self.w_uint32dtype = W_Dtype( + types.UInt32(), + num=6, + kind=UNSIGNEDLTR, + ) + if LONG_BIT == 32: + longtype = types.Int32() + unsigned_longtype = types.UInt32() + elif LONG_BIT == 64: + longtype = types.Int64() + unsigned_longtype = types.UInt64() + self.w_longdtype = W_Dtype( + longtype, + num=7, + kind=SIGNEDLTR, + ) + self.w_ulongdtype = W_Dtype( + unsigned_longtype, + num=8, + kind=UNSIGNEDLTR, + ) + self.w_int64dtype = W_Dtype( + types.Int64(), + num=9, + kind=SIGNEDLTR, + ) + self.w_uint64dtype = W_Dtype( + types.UInt64(), + num=10, + kind=UNSIGNEDLTR, + ) + self.w_float32dtype = W_Dtype( + types.Float32(), + num=11, + kind=FLOATINGLTR, + ) + self.w_float64dtype = W_Dtype( + types.Float64(), + num=12, + kind=FLOATINGLTR, + ) - def descr__new__(space, w_subtype, w_dtype): - if space.is_w(w_dtype, space.w_None): - return space.fromcache(W_Float64Dtype) - elif space.isinstance_w(w_dtype, space.w_str): - dtype = space.str_w(w_dtype) - for alias, dtype_class in dtypes_by_alias: - if alias == dtype: - return space.fromcache(dtype_class) - elif isinstance(space.interpclass_w(w_dtype), W_Dtype): - return w_dtype - elif space.isinstance_w(w_dtype, space.w_type): - for typename, dtype_class in dtypes_by_apptype: - if space.is_w(getattr(space, "w_%s" % typename), w_dtype): - return space.fromcache(dtype_class) - raise OperationError(space.w_TypeError, space.wrap("data type not understood")) + self.builtin_dtypes = [ + self.w_booldtype, self.w_int8dtype, self.w_uint8dtype, + self.w_int16dtype, self.w_uint16dtype, self.w_int32dtype, + self.w_uint32dtype, self.w_longdtype, self.w_ulongdtype, + self.w_int64dtype, self.w_uint64dtype, self.w_float32dtype, + self.w_float64dtype + ] + self.dtypes_by_num_bytes = sorted( + (dtype.itemtype.get_element_size(), dtype) + for dtype in self.builtin_dtypes + ) - def descr_repr(self, space): - return space.wrap("dtype('%s')" % self.name) - - def descr_str(self, space): - return space.wrap(self.name) - - def descr_get_shape(self, space): - return space.newtuple([]) - - -class BaseBox(object): - pass - -VOID_TP = lltype.Ptr(lltype.Array(lltype.Void, hints={'nolength': True, "uncast_on_llgraph": True})) - -def create_low_level_dtype(num, kind, name, aliases, applevel_types, T, valtype, - expected_size=None): - - class Box(BaseBox): - def __init__(self, val): - self.val = val - - def wrap(self, space): - val = self.val - if valtype is rarithmetic.r_singlefloat: - val = float(val) - return space.wrap(val) - - def convert_to(self, dtype): - return dtype.adapt_val(self.val) - Box.__name__ = "%sBox" % T._name - - TP = lltype.Ptr(lltype.Array(T, hints={'nolength': True})) - class W_LowLevelDtype(W_Dtype): - signature = signature.BaseSignature() - - def erase(self, storage): - return rffi.cast(VOID_TP, storage) - - def unerase(self, storage): - return rffi.cast(TP, storage) - - @enforceargs(None, valtype) - def box(self, value): - return Box(value) - - def unbox(self, box): - assert isinstance(box, Box) - return box.val - - def unwrap(self, space, w_item): - raise NotImplementedError - - def malloc(self, size): - # XXX find out why test_zjit explodes with tracking of allocations - return self.erase(lltype.malloc(TP.TO, size, - zero=True, flavor="raw", - track_allocation=False, add_memory_pressure=True - )) - - def getitem(self, storage, i): - return Box(self.unerase(storage)[i]) - - def setitem(self, storage, i, item): - self.unerase(storage)[i] = self.unbox(item) - - def setitem_w(self, space, storage, i, w_item): - self.setitem(storage, i, self.unwrap(space, w_item)) - - def fill(self, storage, item, start, stop): - storage = self.unerase(storage) - item = self.unbox(item) - for i in xrange(start, stop): - storage[i] = item - - @specialize.argtype(1) - def adapt_val(self, val): - return self.box(rffi.cast(TP.TO.OF, val)) - - W_LowLevelDtype.__name__ = "W_%sDtype" % name.capitalize() - W_LowLevelDtype.num = num - W_LowLevelDtype.kind = kind - W_LowLevelDtype.name = name - W_LowLevelDtype.aliases = aliases - W_LowLevelDtype.applevel_types = applevel_types - W_LowLevelDtype.num_bytes = rffi.sizeof(T) - if expected_size is not None: - assert W_LowLevelDtype.num_bytes == expected_size - return W_LowLevelDtype - - -def binop(func): - @functools.wraps(func) - def impl(self, v1, v2): - return self.adapt_val(func(self, - self.for_computation(self.unbox(v1)), - self.for_computation(self.unbox(v2)), - )) - return impl - -def raw_binop(func): - # Returns the result unwrapped. - @functools.wraps(func) - def impl(self, v1, v2): - return func(self, - self.for_computation(self.unbox(v1)), - self.for_computation(self.unbox(v2)) - ) - return impl - -def unaryop(func): - @functools.wraps(func) - def impl(self, v): - return self.adapt_val(func(self, self.for_computation(self.unbox(v)))) - return impl - -class ArithmeticTypeMixin(object): - _mixin_ = True - - @binop - def add(self, v1, v2): - return v1 + v2 - @binop - def sub(self, v1, v2): - return v1 - v2 - @binop - def mul(self, v1, v2): - return v1 * v2 - - @unaryop - def pos(self, v): - return +v - @unaryop - def neg(self, v): - return -v - @unaryop - def abs(self, v): - return abs(v) - - @binop - def max(self, v1, v2): - return max(v1, v2) - @binop - def min(self, v1, v2): - return min(v1, v2) - - def bool(self, v): - return bool(self.for_computation(self.unbox(v))) - @raw_binop - def eq(self, v1, v2): - return v1 == v2 - @raw_binop - def ne(self, v1, v2): - return v1 != v2 - @raw_binop - def lt(self, v1, v2): - return v1 < v2 - @raw_binop - def le(self, v1, v2): - return v1 <= v2 - @raw_binop - def gt(self, v1, v2): - return v1 > v2 - @raw_binop - def ge(self, v1, v2): - return v1 >= v2 - - -class FloatArithmeticDtype(ArithmeticTypeMixin): - _mixin_ = True - - def unwrap(self, space, w_item): - return self.adapt_val(space.float_w(space.float(w_item))) - - def for_computation(self, v): - return float(v) - - def str_format(self, item): - return float2string(self.for_computation(self.unbox(item)), 'g', rfloat.DTSF_STR_PRECISION) - - @binop - def div(self, v1, v2): - try: - return v1 / v2 - except ZeroDivisionError: - if v1 == v2 == 0.0: - return rfloat.NAN - return rfloat.copysign(rfloat.INFINITY, v1 * v2) - @binop - def mod(self, v1, v2): - return math.fmod(v1, v2) - @binop - def pow(self, v1, v2): - return math.pow(v1, v2) - - @unaryop - def sign(self, v): - if v == 0.0: - return 0.0 - return rfloat.copysign(1.0, v) - @unaryop - def reciprocal(self, v): - if v == 0.0: - return rfloat.copysign(rfloat.INFINITY, v) - return 1.0 / v - @unaryop - def fabs(self, v): - return math.fabs(v) - @unaryop - def floor(self, v): - return math.floor(v) - - @binop - def copysign(self, v1, v2): - return math.copysign(v1, v2) - @unaryop - def exp(self, v): - try: - return math.exp(v) - except OverflowError: - return rfloat.INFINITY - @unaryop - def sin(self, v): - return math.sin(v) - @unaryop - def cos(self, v): - return math.cos(v) - @unaryop - def tan(self, v): - return math.tan(v) - @unaryop - def arcsin(self, v): - if not -1.0 <= v <= 1.0: - return rfloat.NAN - return math.asin(v) - @unaryop - def arccos(self, v): - if not -1.0 <= v <= 1.0: - return rfloat.NAN - return math.acos(v) - @unaryop - def arctan(self, v): - return math.atan(v) - @unaryop - def arcsinh(self, v): - return math.asinh(v) - @unaryop - def arctanh(self, v): - if v == 1.0 or v == -1.0: - return math.copysign(rfloat.INFINITY, v) - if not -1.0 < v < 1.0: - return rfloat.NAN - return math.atanh(v) - -class IntegerArithmeticDtype(ArithmeticTypeMixin): - _mixin_ = True - - def unwrap(self, space, w_item): - return self.adapt_val(space.int_w(space.int(w_item))) - - def for_computation(self, v): - return widen(v) - - def str_format(self, item): - return str(widen(self.unbox(item))) - - @binop - def div(self, v1, v2): - if v2 == 0: - return 0 - return v1 / v2 - @binop - def mod(self, v1, v2): - return v1 % v2 - -class SignedIntegerArithmeticDtype(IntegerArithmeticDtype): - _mixin_ = True - - @unaryop - def sign(self, v): - if v > 0: - return 1 - elif v < 0: - return -1 - else: - assert v == 0 - return 0 - -class UnsignedIntegerArithmeticDtype(IntegerArithmeticDtype): - _mixin_ = True - - @unaryop - def sign(self, v): - return int(v != 0) - - -W_BoolDtype = create_low_level_dtype( - num = 0, kind = BOOLLTR, name = "bool", - aliases = ["?", "bool", "bool8"], - applevel_types = ["bool"], - T = lltype.Bool, - valtype = bool, -) -class W_BoolDtype(SignedIntegerArithmeticDtype, W_BoolDtype): - def unwrap(self, space, w_item): - return self.adapt_val(space.is_true(w_item)) - - def str_format(self, item): - v = self.unbox(item) - return "True" if v else "False" - - def for_computation(self, v): - return int(v) - -W_Int8Dtype = create_low_level_dtype( - num = 1, kind = SIGNEDLTR, name = "int8", - aliases = ["b", "int8", "i1"], - applevel_types = [], - T = rffi.SIGNEDCHAR, - valtype = rffi.SIGNEDCHAR._type, - expected_size = 1, -) -class W_Int8Dtype(SignedIntegerArithmeticDtype, W_Int8Dtype): - pass - -W_UInt8Dtype = create_low_level_dtype( - num = 2, kind = UNSIGNEDLTR, name = "uint8", - aliases = ["B", "uint8", "I1"], - applevel_types = [], - T = rffi.UCHAR, - valtype = rffi.UCHAR._type, - expected_size = 1, -) -class W_UInt8Dtype(UnsignedIntegerArithmeticDtype, W_UInt8Dtype): - pass - -W_Int16Dtype = create_low_level_dtype( - num = 3, kind = SIGNEDLTR, name = "int16", - aliases = ["h", "int16", "i2"], - applevel_types = [], - T = rffi.SHORT, - valtype = rffi.SHORT._type, - expected_size = 2, -) -class W_Int16Dtype(SignedIntegerArithmeticDtype, W_Int16Dtype): - pass - -W_UInt16Dtype = create_low_level_dtype( - num = 4, kind = UNSIGNEDLTR, name = "uint16", - aliases = ["H", "uint16", "I2"], - applevel_types = [], - T = rffi.USHORT, - valtype = rffi.USHORT._type, - expected_size = 2, -) -class W_UInt16Dtype(UnsignedIntegerArithmeticDtype, W_UInt16Dtype): - pass - -W_Int32Dtype = create_low_level_dtype( - num = 5, kind = SIGNEDLTR, name = "int32", - aliases = ["i", "int32", "i4"], - applevel_types = [], - T = rffi.INT, - valtype = rffi.INT._type, - expected_size = 4, -) -class W_Int32Dtype(SignedIntegerArithmeticDtype, W_Int32Dtype): - pass - -W_UInt32Dtype = create_low_level_dtype( - num = 6, kind = UNSIGNEDLTR, name = "uint32", - aliases = ["I", "uint32", "I4"], - applevel_types = [], - T = rffi.UINT, - valtype = rffi.UINT._type, - expected_size = 4, -) -class W_UInt32Dtype(UnsignedIntegerArithmeticDtype, W_UInt32Dtype): - pass - -W_Int64Dtype = create_low_level_dtype( - num = 9, kind = SIGNEDLTR, name = "int64", - aliases = ["q", "int64", "i8"], - applevel_types = ["long"], - T = rffi.LONGLONG, - valtype = rffi.LONGLONG._type, - expected_size = 8, -) -class W_Int64Dtype(SignedIntegerArithmeticDtype, W_Int64Dtype): - pass - -W_UInt64Dtype = create_low_level_dtype( - num = 10, kind = UNSIGNEDLTR, name = "uint64", - aliases = ["Q", "uint64", "I8"], - applevel_types = [], - T = rffi.ULONGLONG, - valtype = rffi.ULONGLONG._type, - expected_size = 8, -) -class W_UInt64Dtype(UnsignedIntegerArithmeticDtype, W_UInt64Dtype): - pass - -if LONG_BIT == 32: - long_dtype = W_Int32Dtype - ulong_dtype = W_UInt32Dtype -elif LONG_BIT == 64: - long_dtype = W_Int64Dtype - ulong_dtype = W_UInt64Dtype -else: - assert False - -class W_LongDtype(long_dtype): - num = 7 - aliases = ["l"] - applevel_types = ["int"] - -class W_ULongDtype(ulong_dtype): - num = 8 - aliases = ["L"] - -W_Float32Dtype = create_low_level_dtype( - num = 11, kind = FLOATINGLTR, name = "float32", - aliases = ["f", "float32", "f4"], - applevel_types = [], - T = lltype.SingleFloat, - valtype = rarithmetic.r_singlefloat, - expected_size = 4, -) -class W_Float32Dtype(FloatArithmeticDtype, W_Float32Dtype): - pass - -W_Float64Dtype = create_low_level_dtype( - num = 12, kind = FLOATINGLTR, name = "float64", - aliases = ["d", "float64", "f8"], - applevel_types = ["float"], - T = lltype.Float, - valtype = float, - expected_size = 8, -) -class W_Float64Dtype(FloatArithmeticDtype, W_Float64Dtype): - pass - -ALL_DTYPES = [ - W_BoolDtype, - W_Int8Dtype, W_UInt8Dtype, W_Int16Dtype, W_UInt16Dtype, - W_Int32Dtype, W_UInt32Dtype, W_LongDtype, W_ULongDtype, - W_Int64Dtype, W_UInt64Dtype, - W_Float32Dtype, W_Float64Dtype, -] - -dtypes_by_alias = unrolling_iterable([ - (alias, dtype) - for dtype in ALL_DTYPES - for alias in dtype.aliases -]) -dtypes_by_apptype = unrolling_iterable([ - (apptype, dtype) - for dtype in ALL_DTYPES - for apptype in dtype.applevel_types -]) -dtypes_by_num_bytes = unrolling_iterable(sorted([ - (dtype.num_bytes, dtype) - for dtype in ALL_DTYPES -])) - -W_Dtype.typedef = TypeDef("dtype", - __module__ = "numpy", - __new__ = interp2app(W_Dtype.descr__new__.im_func), - - __repr__ = interp2app(W_Dtype.descr_repr), - __str__ = interp2app(W_Dtype.descr_str), - - num = interp_attrproperty("num", cls=W_Dtype), - kind = interp_attrproperty("kind", cls=W_Dtype), - itemsize = interp_attrproperty("num_bytes", cls=W_Dtype), - shape = GetSetProperty(W_Dtype.descr_get_shape), -) -W_Dtype.typedef.acceptable_as_base_class = False +def get_dtype_cache(space): + return space.fromcache(DtypeCache) \ No newline at end of file diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -31,7 +31,7 @@ arr = SingleDimArray(len(l), dtype=dtype) i = 0 for w_elem in l: - dtype.setitem_w(space, arr.storage, i, w_elem) + dtype.setitem(arr.storage, i, dtype.coerce(space, w_elem)) i += 1 return arr @@ -187,7 +187,7 @@ ]) else: nums = [ - dtype.str_format(self.eval(index)) + dtype.itemtype.str_format(self.eval(index)) for index in range(self.find_size()) ] return nums diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py --- a/pypy/module/micronumpy/interp_ufuncs.py +++ b/pypy/module/micronumpy/interp_ufuncs.py @@ -2,7 +2,7 @@ from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty -from pypy.module.micronumpy import interp_dtype, signature +from pypy.module.micronumpy import interp_dtype, signature, types from pypy.rlib import jit from pypy.rlib.rarithmetic import LONG_BIT from pypy.tool.sourcetools import func_with_new_name @@ -148,7 +148,7 @@ return self.func(calc_dtype, w_lhs.value.convert_to(calc_dtype), w_rhs.value.convert_to(calc_dtype) - ).wrap(space) + ) new_sig = signature.Signature.find_sig([ self.signature, w_lhs.signature, w_rhs.signature @@ -178,7 +178,7 @@ dt1, dt2 = dt2, dt1 # Some operations promote op(bool, bool) to return int8, rather than bool if promote_bools and (dt1.kind == dt2.kind == interp_dtype.BOOLLTR): - return space.fromcache(interp_dtype.W_Int8Dtype) + return interp_dtype.get_dtype_cache(space).w_int8dtype if promote_to_float: return find_unaryop_result_dtype(space, dt2, promote_to_float=True) # If they're the same kind, choose the greater one. @@ -221,15 +221,16 @@ def find_unaryop_result_dtype(space, dt, promote_to_float=False, promote_bools=False, promote_to_largest=False): if promote_bools and (dt.kind == interp_dtype.BOOLLTR): - return space.fromcache(interp_dtype.W_Int8Dtype) + return interp_dtype.get_dtype_cache(space).w_int8dtype if promote_to_float: if dt.kind == interp_dtype.FLOATINGLTR: return dt if dt.num >= 5: - return space.fromcache(interp_dtype.W_Float64Dtype) - for bytes, dtype in interp_dtype.dtypes_by_num_bytes: - if dtype.kind == interp_dtype.FLOATINGLTR and dtype.num_bytes > dt.num_bytes: - return space.fromcache(dtype) + return interp_dtype.get_dtype_cache(space).w_float64dtype + for bytes, dtype in interp_dtype.get_dtype_cache(space).dtypes_by_num_bytes: + if (dtype.kind == interp_dtype.FLOATINGLTR and + dtype.itemtype.get_element_size() > dt.itemtype.get_element_size()): + return dtype if promote_to_largest: if dt.kind == interp_dtype.BOOLLTR or dt.kind == interp_dtype.SIGNEDLTR: return space.fromcache(interp_dtype.W_Int64Dtype) @@ -264,12 +265,13 @@ def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func): + assert hasattr(types.BaseType, op_name) if argcount == 1: def impl(res_dtype, value): - return getattr(res_dtype, op_name)(value) + return getattr(res_dtype.itemtype, op_name)(value) elif argcount == 2: def impl(res_dtype, lvalue, rvalue): - res = getattr(res_dtype, op_name)(lvalue, rvalue) + res = getattr(res_dtype.itemtype, op_name)(lvalue, rvalue) if comparison_func: booldtype = space.fromcache(interp_dtype.W_BoolDtype) assert isinstance(booldtype, interp_dtype.W_BoolDtype) @@ -327,7 +329,7 @@ identity = extra_kwargs.get("identity") if identity is not None: - identity = space.fromcache(interp_dtype.W_LongDtype).adapt_val(identity) + identity = interp_dtype.get_dtype_cache(space).w_longdtype.box(identity) extra_kwargs["identity"] = identity func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount, diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py --- a/pypy/module/micronumpy/test/test_base.py +++ b/pypy/module/micronumpy/test/test_base.py @@ -1,5 +1,5 @@ from pypy.conftest import gettestobjspace -from pypy.module.micronumpy import interp_dtype +from pypy.module.micronumpy.interp_dtype import get_dtype_cache from pypy.module.micronumpy.interp_numarray import SingleDimArray, Scalar from pypy.module.micronumpy.interp_ufuncs import (find_binop_result_dtype, find_unaryop_result_dtype) @@ -11,7 +11,8 @@ class TestSignature(object): def test_binop_signature(self, space): - float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype) + float64_dtype = get_dtype_cache(space).w_float64dtype + bool_dtype = get_dtype_cache(space).w_booldtype ar = SingleDimArray(10, dtype=float64_dtype) v1 = ar.descr_add(space, ar) @@ -22,7 +23,7 @@ v4 = ar.descr_add(space, ar) assert v1.signature is v4.signature - bool_ar = SingleDimArray(10, dtype=space.fromcache(interp_dtype.W_BoolDtype)) + bool_ar = SingleDimArray(10, dtype=bool_dtype) v5 = ar.descr_add(space, bool_ar) assert v5.signature is not v1.signature assert v5.signature is not v2.signature @@ -30,7 +31,9 @@ assert v5.signature is v6.signature def test_slice_signature(self, space): - ar = SingleDimArray(10, dtype=space.fromcache(interp_dtype.W_Float64Dtype)) + float64_dtype = get_dtype_cache(space).w_float64dtype + + ar = SingleDimArray(10, dtype=float64_dtype) v1 = ar.descr_getitem(space, space.wrap(slice(1, 5, 1))) v2 = ar.descr_getitem(space, space.wrap(slice(4, 6, 1))) assert v1.signature is v2.signature @@ -41,10 +44,10 @@ class TestUfuncCoerscion(object): def test_binops(self, space): - bool_dtype = space.fromcache(interp_dtype.W_BoolDtype) - int8_dtype = space.fromcache(interp_dtype.W_Int8Dtype) - int32_dtype = space.fromcache(interp_dtype.W_Int32Dtype) - float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype) + bool_dtype = get_dtype_cache(space).w_booldtype + int8_dtype = get_dtype_cache(space).w_int8dtype + int32_dtype = get_dtype_cache(space).w_int32dtype + float64_dtype = get_dtype_cache(space).w_float64dtype # Basic pairing assert find_binop_result_dtype(space, bool_dtype, bool_dtype) is bool_dtype @@ -62,19 +65,19 @@ assert find_binop_result_dtype(space, bool_dtype, float64_dtype, promote_to_float=True) is float64_dtype def test_unaryops(self, space): - bool_dtype = space.fromcache(interp_dtype.W_BoolDtype) - int8_dtype = space.fromcache(interp_dtype.W_Int8Dtype) - uint8_dtype = space.fromcache(interp_dtype.W_UInt8Dtype) - int16_dtype = space.fromcache(interp_dtype.W_Int16Dtype) - uint16_dtype = space.fromcache(interp_dtype.W_UInt16Dtype) - int32_dtype = space.fromcache(interp_dtype.W_Int32Dtype) - uint32_dtype = space.fromcache(interp_dtype.W_UInt32Dtype) - long_dtype = space.fromcache(interp_dtype.W_LongDtype) - ulong_dtype = space.fromcache(interp_dtype.W_ULongDtype) - int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype) - uint64_dtype = space.fromcache(interp_dtype.W_UInt64Dtype) - float32_dtype = space.fromcache(interp_dtype.W_Float32Dtype) - float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype) + bool_dtype = get_dtype_cache(space).w_booldtype + int8_dtype = get_dtype_cache(space).w_int8dtype + uint8_dtype = get_dtype_cache(space).w_uint8dtype + int16_dtype = get_dtype_cache(space).w_int16dtype + uint16_dtype = get_dtype_cache(space).w_uint16dtype + int32_dtype = get_dtype_cache(space).w_int32dtype + uint32_dtype = get_dtype_cache(space).w_uint32dtype + long_dtype = get_dtype_cache(space).w_longdtype + ulong_dtype = get_dtype_cache(space).w_ulongdtype + int64_dtype = get_dtype_cache(space).w_int64dtype + uint64_dtype = get_dtype_cache(space).w_uint64dtype + float32_dtype = get_dtype_cache(space).w_float32dtype + float64_dtype = get_dtype_cache(space).w_float64dtype # Normal rules, everything returns itself assert find_unaryop_result_dtype(space, bool_dtype) is bool_dtype _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit