[pypy-commit] pypy numpy-dtype-refactor: begin refactoring everything. nothing works.

alex_gaynor noreply at buildbot.pypy.org
Wed Nov 9 04:22:34 CET 2011


Author: Alex Gaynor <alex.gaynor at 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


More information about the pypy-commit mailing list