[pypy-commit] pypy default: Merge the numpy-dtype-refactor branch, it refactors the internals of numpy, and exposes the numpy box classes, it also sets the stage for complex and custom dtypes.

alex_gaynor noreply at buildbot.pypy.org
Fri Dec 2 18:47:58 CET 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: 
Changeset: r50072:8c67eefdff41
Date: 2011-12-02 12:47 -0500
http://bitbucket.org/pypy/pypy/changeset/8c67eefdff41/

Log:	Merge the numpy-dtype-refactor branch, it refactors the internals of
	numpy, and exposes the numpy box classes, it also sets the stage for
	complex and custom dtypes.

diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -1432,6 +1432,10 @@
     res = _getinteriorfield_raw(libffi.types.slong, array, index, width, ofs)
     return res
 
+def do_getinteriorfield_raw_float(array, index, width, ofs):
+    res = _getinteriorfield_raw(libffi.types.double, array, index, width, ofs)
+    return res
+
 def _getfield_raw(struct, fieldnum):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
     ptr = cast_from_int(lltype.Ptr(STRUCT), struct)
@@ -1516,6 +1520,7 @@
         return libffi.array_setitem(ffitype, width, addr, index, ofs, newvalue)
     return do_setinteriorfield_raw
 do_setinteriorfield_raw_int = new_setinteriorfield_raw(libffi.types.slong)
+do_setinteriorfield_raw_float = new_setinteriorfield_raw(libffi.types.double)
 
 def do_setfield_raw_int(struct, fieldnum, newvalue):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -16,8 +16,22 @@
         'fromstring': 'interp_support.fromstring',
         'flatiter': 'interp_numarray.W_FlatIterator',
 
-        'True_': 'space.w_True',
-        'False_': 'space.w_False',
+        'True_': 'types.Bool.True',
+        'False_': 'types.Bool.False',
+
+        'generic': 'interp_boxes.W_GenericBox',
+        'number': 'interp_boxes.W_NumberBox',
+        'integer': 'interp_boxes.W_IntegerBox',
+        'signedinteger': 'interp_boxes.W_SignedIntegerBox',
+        'bool_': 'interp_boxes.W_BoolBox',
+        'int8': 'interp_boxes.W_Int8Box',
+        'int16': 'interp_boxes.W_Int16Box',
+        'int32': 'interp_boxes.W_Int32Box',
+        'int64': 'interp_boxes.W_Int64Box',
+        'int_': 'interp_boxes.W_LongBox',
+        'inexact': 'interp_boxes.W_InexactBox',
+        'floating': 'interp_boxes.W_FloatingBox',
+        'float64': 'interp_boxes.W_Float64Box',
     }
 
     # ufuncs
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
@@ -3,13 +3,16 @@
 It should not be imported by the module itself
 """
 
+import re
+
 from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
-from pypy.module.micronumpy.interp_dtype import W_Float64Dtype, W_BoolDtype
+from pypy.module.micronumpy import interp_boxes
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
 from pypy.module.micronumpy.interp_numarray import (Scalar, BaseArray,
      descr_new_array, scalar_w, NDimArray)
 from pypy.module.micronumpy import interp_ufuncs
-from pypy.rlib.objectmodel import specialize
-import re
+from pypy.rlib.objectmodel import specialize, instantiate
+
 
 class BogusBytecode(Exception):
     pass
@@ -48,15 +51,12 @@
     def __init__(self):
         """NOT_RPYTHON"""
         self.fromcache = InternalSpaceCache(self).getorbuild
-        self.w_float64dtype = W_Float64Dtype(self)
 
     def issequence_w(self, w_obj):
         return isinstance(w_obj, ListObject) or isinstance(w_obj, NDimArray)
 
     def isinstance_w(self, w_obj, w_tp):
-        if w_obj.tp == w_tp:
-            return True
-        return False
+        return w_obj.tp == w_tp
 
     def decode_index4(self, w_idx, size):
         if isinstance(w_idx, IntObject):
@@ -97,8 +97,10 @@
     fixedview = listview
 
     def float(self, w_obj):
-        assert isinstance(w_obj, FloatObject)
-        return w_obj
+        if isinstance(w_obj, FloatObject):
+            return w_obj
+        assert isinstance(w_obj, interp_boxes.W_GenericBox)
+        return self.float(w_obj.descr_float(self))
 
     def float_w(self, w_obj):
         assert isinstance(w_obj, FloatObject)
@@ -112,7 +114,10 @@
         raise NotImplementedError
 
     def int(self, w_obj):
-        return w_obj
+        if isinstance(w_obj, IntObject):
+            return w_obj
+        assert isinstance(w_obj, interp_boxes.W_GenericBox)
+        return self.int(w_obj.descr_int(self))
 
     def is_true(self, w_obj):
         assert isinstance(w_obj, BoolObject)
@@ -135,6 +140,9 @@
         assert isinstance(what, tp)
         return what
 
+    def allocate_instance(self, klass, w_subtype):
+        return instantiate(klass)
+
     def len_w(self, w_obj):
         if isinstance(w_obj, ListObject):
             return len(w_obj.items)
@@ -247,7 +255,7 @@
             w_rhs = self.rhs.execute(interp)
         if not isinstance(w_lhs, BaseArray):
             # scalar
-            dtype = interp.space.fromcache(W_Float64Dtype)
+            dtype = get_dtype_cache(interp.space).w_float64dtype
             w_lhs = scalar_w(interp.space, dtype, w_lhs)
         assert isinstance(w_lhs, BaseArray)
         if self.name == '+':
@@ -264,8 +272,9 @@
             w_res = w_lhs.descr_getitem(interp.space, w_rhs)
         else:
             raise NotImplementedError
-        if not isinstance(w_res, BaseArray):
-            dtype = interp.space.fromcache(W_Float64Dtype)
+        if (not isinstance(w_res, BaseArray) and
+            not isinstance(w_res, interp_boxes.W_GenericBox)):
+            dtype = get_dtype_cache(interp.space).w_float64dtype
             w_res = scalar_w(interp.space, dtype, w_res)
         return w_res
 
@@ -283,7 +292,7 @@
         return space.wrap(self.v)
 
     def execute(self, interp):
-        return FloatObject(self.v)
+        return interp.space.wrap(self.v)
 
 class RangeConstant(Node):
     def __init__(self, v):
@@ -291,8 +300,9 @@
 
     def execute(self, interp):
         w_list = interp.space.newlist(
-            [interp.space.wrap(float(i)) for i in range(self.v)])
-        dtype = interp.space.fromcache(W_Float64Dtype)
+            [interp.space.wrap(float(i)) for i in range(self.v)]
+        )
+        dtype = get_dtype_cache(interp.space).w_float64dtype
         return descr_new_array(interp.space, None, w_list, w_dtype=dtype,
                                w_order=None)
 
@@ -315,7 +325,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,
                                w_order=None)
 
@@ -384,9 +394,11 @@
             if isinstance(w_res, BaseArray):
                 return w_res
             if isinstance(w_res, FloatObject):
-                dtype = interp.space.fromcache(W_Float64Dtype)
+                dtype = get_dtype_cache(interp.space).w_float64dtype
             elif isinstance(w_res, BoolObject):
-                dtype = interp.space.fromcache(W_BoolDtype)
+                dtype = get_dtype_cache(interp.space).w_booldtype
+            elif isinstance(w_res, interp_boxes.W_GenericBox):
+                dtype = w_res.get_dtype(interp.space)
             else:
                 dtype = None
             return scalar_w(interp.space, dtype, w_res)
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -0,0 +1,267 @@
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef
+from pypy.objspace.std.floattype import float_typedef
+from pypy.objspace.std.inttype import int_typedef
+from pypy.objspace.std.typeobject import W_TypeObject
+from pypy.rlib.rarithmetic import LONG_BIT
+from pypy.tool.sourcetools import func_with_new_name
+
+
+MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else ()
+
+def new_dtype_getter(name):
+    def get_dtype(space):
+        from pypy.module.micronumpy.interp_dtype import get_dtype_cache
+        return getattr(get_dtype_cache(space), "w_%sdtype" % name)
+    def new(space, w_subtype, w_value):
+        dtype = get_dtype(space)
+        return dtype.itemtype.coerce_subtype(space, w_subtype, w_value)
+    return func_with_new_name(new, name + "_box_new"), staticmethod(get_dtype)
+
+class PrimitiveBox(object):
+    _mixin_ = True
+
+    def __init__(self, value):
+        self.value = value
+
+    def convert_to(self, dtype):
+        return dtype.box(self.value)
+
+class W_GenericBox(Wrappable):
+    _attrs_ = ()
+
+    def descr__new__(space, w_subtype, __args__):
+        assert isinstance(w_subtype, W_TypeObject)
+        raise operationerrfmt(space.w_TypeError, "cannot create '%s' instances",
+            w_subtype.get_module_type_name()
+        )
+
+    def descr_str(self, space):
+        return self.descr_repr(space)
+
+    def descr_repr(self, space):
+        return space.wrap(self.get_dtype(space).itemtype.str_format(self))
+
+    def descr_int(self, space):
+        box = self.convert_to(W_LongBox.get_dtype(space))
+        assert isinstance(box, W_LongBox)
+        return space.wrap(box.value)
+
+    def descr_float(self, space):
+        box = self.convert_to(W_Float64Box.get_dtype(space))
+        assert isinstance(box, W_Float64Box)
+        return space.wrap(box.value)
+
+    def descr_nonzero(self, space):
+        dtype = self.get_dtype(space)
+        return space.wrap(dtype.itemtype.bool(self))
+
+    def _binop_impl(ufunc_name):
+        def impl(self, space, w_other):
+            from pypy.module.micronumpy import interp_ufuncs
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other])
+        return func_with_new_name(impl, "binop_%s_impl" % ufunc_name)
+
+    def _binop_right_impl(ufunc_name):
+        def impl(self, space, w_other):
+            from pypy.module.micronumpy import interp_ufuncs
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self])
+        return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
+
+    def _unaryop_impl(ufunc_name):
+        def impl(self, space):
+            from pypy.module.micronumpy import interp_ufuncs
+            return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
+        return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name)
+
+    descr_add = _binop_impl("add")
+    descr_sub = _binop_impl("subtract")
+    descr_mul = _binop_impl("multiply")
+    descr_div = _binop_impl("divide")
+    descr_eq = _binop_impl("equal")
+    descr_ne = _binop_impl("not_equal")
+    descr_lt = _binop_impl("less")
+    descr_le = _binop_impl("less_equal")
+    descr_gt = _binop_impl("greater")
+    descr_ge = _binop_impl("greater_equal")
+
+    descr_radd = _binop_right_impl("add")
+    descr_rmul = _binop_right_impl("multiply")
+
+    descr_neg = _unaryop_impl("negative")
+    descr_abs = _unaryop_impl("absolute")
+
+
+class W_BoolBox(W_GenericBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("bool")
+
+class W_NumberBox(W_GenericBox):
+    _attrs_ = ()
+
+class W_IntegerBox(W_NumberBox):
+    pass
+
+class W_SignedIntegerBox(W_IntegerBox):
+    pass
+
+class W_UnsignedIntgerBox(W_IntegerBox):
+    pass
+
+class W_Int8Box(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("int8")
+
+class W_UInt8Box(W_UnsignedIntgerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("uint8")
+
+class W_Int16Box(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("int16")
+
+class W_UInt16Box(W_UnsignedIntgerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("uint16")
+
+class W_Int32Box(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("int32")
+
+class W_UInt32Box(W_UnsignedIntgerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("uint32")
+
+class W_LongBox(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("long")
+
+class W_ULongBox(W_UnsignedIntgerBox, PrimitiveBox):
+    pass
+
+class W_Int64Box(W_SignedIntegerBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("int64")
+
+class W_UInt64Box(W_UnsignedIntgerBox, PrimitiveBox):
+    pass
+
+class W_InexactBox(W_NumberBox):
+    _attrs_ = ()
+
+class W_FloatingBox(W_InexactBox):
+    _attrs_ = ()
+
+class W_Float32Box(W_FloatingBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("float32")
+
+class W_Float64Box(W_FloatingBox, PrimitiveBox):
+    descr__new__, get_dtype = new_dtype_getter("float64")
+
+
+
+W_GenericBox.typedef = TypeDef("generic",
+    __module__ = "numpypy",
+
+    __new__ = interp2app(W_GenericBox.descr__new__.im_func),
+
+    __str__ = interp2app(W_GenericBox.descr_str),
+    __repr__ = interp2app(W_GenericBox.descr_repr),
+    __int__ = interp2app(W_GenericBox.descr_int),
+    __float__ = interp2app(W_GenericBox.descr_float),
+    __nonzero__ = interp2app(W_GenericBox.descr_nonzero),
+
+    __add__ = interp2app(W_GenericBox.descr_add),
+    __sub__ = interp2app(W_GenericBox.descr_sub),
+    __mul__ = interp2app(W_GenericBox.descr_mul),
+    __div__ = interp2app(W_GenericBox.descr_div),
+
+    __radd__ = interp2app(W_GenericBox.descr_add),
+    __rmul__ = interp2app(W_GenericBox.descr_rmul),
+
+    __eq__ = interp2app(W_GenericBox.descr_eq),
+    __ne__ = interp2app(W_GenericBox.descr_ne),
+    __lt__ = interp2app(W_GenericBox.descr_lt),
+    __le__ = interp2app(W_GenericBox.descr_le),
+    __gt__ = interp2app(W_GenericBox.descr_gt),
+    __ge__ = interp2app(W_GenericBox.descr_ge),
+
+    __neg__ = interp2app(W_GenericBox.descr_neg),
+    __abs__ = interp2app(W_GenericBox.descr_abs),
+)
+
+W_BoolBox.typedef = TypeDef("bool_", W_GenericBox.typedef,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_BoolBox.descr__new__.im_func),
+)
+
+W_NumberBox.typedef = TypeDef("number", W_GenericBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_IntegerBox.typedef = TypeDef("integer", W_NumberBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_SignedIntegerBox.typedef = TypeDef("signedinteger", W_IntegerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Int8Box.typedef = TypeDef("int8", W_SignedIntegerBox.typedef,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_Int8Box.descr__new__.im_func),
+)
+
+W_UInt8Box.typedef = TypeDef("uint8", W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Int16Box.typedef = TypeDef("int16", W_SignedIntegerBox.typedef,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_Int16Box.descr__new__.im_func),
+)
+
+W_UInt16Box.typedef = TypeDef("uint16", W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Int32Box.typedef = TypeDef("int32", W_SignedIntegerBox.typedef,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_Int32Box.descr__new__.im_func),
+)
+
+W_UInt32Box.typedef = TypeDef("uint32", W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+if LONG_BIT == 32:
+    long_name = "int32"
+elif LONG_BIT == 64:
+    long_name = "int64"
+W_LongBox.typedef = TypeDef(long_name, (W_SignedIntegerBox.typedef, int_typedef,),
+    __module__ = "numpypy",
+)
+
+W_ULongBox.typedef = TypeDef("u" + long_name, W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Int64Box.typedef = TypeDef("int64", (W_SignedIntegerBox.typedef,) + MIXIN_64,
+    __module__ = "numpypy",
+    __new__ = interp2app(W_Int64Box.descr__new__.im_func),
+)
+
+W_UInt64Box.typedef = TypeDef("uint64", W_UnsignedIntgerBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_InexactBox.typedef = TypeDef("inexact", W_NumberBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_FloatingBox.typedef = TypeDef("floating", W_InexactBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Float32Box.typedef = TypeDef("float32", W_FloatingBox.typedef,
+    __module__ = "numpypy",
+)
+
+W_Float64Box.typedef = TypeDef("float64", (W_FloatingBox.typedef, float_typedef),
+    __module__ = "numpypy",
+
+    __new__ = interp2app(W_Float64Box.descr__new__.im_func),
+)
\ No newline at end of file
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,16 +1,11 @@
-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.interpreter.typedef import (TypeDef, GetSetProperty,
+    interp_attrproperty, interp_attrproperty_w)
+from pypy.module.micronumpy import types, signature, interp_boxes
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import LONG_BIT
 from pypy.rpython.lltypesystem import lltype, rffi
 
 
@@ -19,523 +14,216 @@
 BOOLLTR = "b"
 FLOATINGLTR = "f"
 
+
+VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True, 'render_as_void': True})
+
 class W_Dtype(Wrappable):
-    def __init__(self, space):
-        pass
+    def __init__(self, itemtype, num, kind, name, char, w_box_type, alternate_constructors=[]):
+        self.signature = signature.BaseSignature()
+        self.itemtype = itemtype
+        self.num = num
+        self.kind = kind
+        self.name = name
+        self.char = char
+        self.w_box_type = w_box_type
+        self.alternate_constructors = alternate_constructors
+
+    def malloc(self, length):
+        # XXX find out why test_zjit explodes with tracking of allocations
+        return lltype.malloc(VOID_STORAGE, 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):
+        return self.itemtype.read(storage, self.itemtype.get_element_size(), i, 0)
+
+    def setitem(self, storage, i, box):
+        self.itemtype.store(storage, self.itemtype.get_element_size(), i, 0, box)
+
+    def fill(self, storage, box, start, stop):
+        self.itemtype.fill(storage, self.itemtype.get_element_size(), box, start, stop, 0)
 
     def descr__new__(space, w_subtype, w_dtype):
+        cache = get_dtype_cache(space)
+
         if space.is_w(w_dtype, space.w_None):
-            return space.fromcache(W_Float64Dtype)
+            return cache.w_float64dtype
+        elif space.isinstance_w(w_dtype, w_subtype):
+            return w_dtype
         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)
+            name = space.str_w(w_dtype)
+            for dtype in cache.builtin_dtypes:
+                if dtype.name == name or dtype.char == name:
+                    return dtype
+        else:
+            for dtype in cache.builtin_dtypes:
+                if w_dtype in dtype.alternate_constructors:
+                    return dtype
+                if w_dtype is dtype.w_box_type:
+                    return dtype
         raise OperationError(space.w_TypeError, space.wrap("data type not understood"))
 
+    def descr_str(self, space):
+        return space.wrap(self.name)
+
     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_itemsize(self, space):
+        return space.wrap(self.itemtype.get_element_size())
 
     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):
-    specialize.argtype(1, 2)(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):
-    specialize.argtype(1, 2)(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):
-    specialize.argtype(1)(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):
-        # XXX this won't work after translation, probably requires ovfcheck
-        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)
-    @unaryop
-    def sqrt(self, v):
-        try:
-            return math.sqrt(v)
-        except ValueError:
-            return rfloat.NAN
-
-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
-    @binop
-    def pow(self, v1, v2):
-        res = 1
-        while v2 > 0:
-            if v2 & 1:
-                res *= v1
-            v2 >>= 1
-            if v2 == 0:
-                break
-            v1 *= v1
-        return res
-
-
-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",
+    __module__ = "numpypy",
     __new__ = interp2app(W_Dtype.descr__new__.im_func),
 
+    __str__= interp2app(W_Dtype.descr_str),
     __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),
+    type = interp_attrproperty_w("w_box_type", cls=W_Dtype),
+    itemsize = GetSetProperty(W_Dtype.descr_get_itemsize),
     shape = GetSetProperty(W_Dtype.descr_get_shape),
 )
 W_Dtype.typedef.acceptable_as_base_class = False
+
+class DtypeCache(object):
+    def __init__(self, space):
+        self.w_booldtype = W_Dtype(
+            types.Bool(),
+            num=0,
+            kind=BOOLLTR,
+            name="bool",
+            char="?",
+            w_box_type = space.gettypefor(interp_boxes.W_BoolBox),
+            alternate_constructors=[space.w_bool],
+        )
+        self.w_int8dtype = W_Dtype(
+            types.Int8(),
+            num=1,
+            kind=SIGNEDLTR,
+            name="int8",
+            char="b",
+            w_box_type = space.gettypefor(interp_boxes.W_Int8Box)
+        )
+        self.w_uint8dtype = W_Dtype(
+            types.UInt8(),
+            num=2,
+            kind=UNSIGNEDLTR,
+            name="uint8",
+            char="B",
+            w_box_type = space.gettypefor(interp_boxes.W_UInt8Box),
+        )
+        self.w_int16dtype = W_Dtype(
+            types.Int16(),
+            num=3,
+            kind=SIGNEDLTR,
+            name="int16",
+            char="h",
+            w_box_type = space.gettypefor(interp_boxes.W_Int16Box),
+        )
+        self.w_uint16dtype = W_Dtype(
+            types.UInt16(),
+            num=4,
+            kind=UNSIGNEDLTR,
+            name="uint16",
+            char="H",
+            w_box_type = space.gettypefor(interp_boxes.W_UInt16Box),
+        )
+        self.w_int32dtype = W_Dtype(
+            types.Int32(),
+            num=5,
+            kind=SIGNEDLTR,
+            name="int32",
+            char="i",
+             w_box_type = space.gettypefor(interp_boxes.W_Int32Box),
+       )
+        self.w_uint32dtype = W_Dtype(
+            types.UInt32(),
+            num=6,
+            kind=UNSIGNEDLTR,
+            name="uint32",
+            char="I",
+            w_box_type = space.gettypefor(interp_boxes.W_UInt32Box),
+        )
+        if LONG_BIT == 32:
+            name = "int32"
+        elif LONG_BIT == 64:
+            name = "int64"
+        self.w_longdtype = W_Dtype(
+            types.Long(),
+            num=7,
+            kind=SIGNEDLTR,
+            name=name,
+            char="l",
+            w_box_type = space.gettypefor(interp_boxes.W_LongBox),
+            alternate_constructors=[space.w_int],
+        )
+        self.w_ulongdtype = W_Dtype(
+            types.ULong(),
+            num=8,
+            kind=UNSIGNEDLTR,
+            name="u" + name,
+            char="L",
+            w_box_type = space.gettypefor(interp_boxes.W_ULongBox),
+        )
+        self.w_int64dtype = W_Dtype(
+            types.Int64(),
+            num=9,
+            kind=SIGNEDLTR,
+            name="int64",
+            char="q",
+            w_box_type = space.gettypefor(interp_boxes.W_Int64Box),
+            alternate_constructors=[space.w_long],
+        )
+        self.w_uint64dtype = W_Dtype(
+            types.UInt64(),
+            num=10,
+            kind=UNSIGNEDLTR,
+            name="uint64",
+            char="Q",
+            w_box_type = space.gettypefor(interp_boxes.W_UInt64Box),
+        )
+        self.w_float32dtype = W_Dtype(
+            types.Float32(),
+            num=11,
+            kind=FLOATINGLTR,
+            name="float32",
+            char="f",
+            w_box_type = space.gettypefor(interp_boxes.W_Float32Box),
+        )
+        self.w_float64dtype = W_Dtype(
+            types.Float64(),
+            num=12,
+            kind=FLOATINGLTR,
+            name="float64",
+            char="d",
+            w_box_type = space.gettypefor(interp_boxes.W_Float64Box),
+            alternate_constructors=[space.w_float],
+        )
+
+        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 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
@@ -124,7 +124,7 @@
         for w_elem in elems_w:
             w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_elem,
                                                           w_dtype)
-            if w_dtype is space.fromcache(interp_dtype.W_Float64Dtype):
+            if w_dtype is interp_dtype.get_dtype_cache(space).w_float64dtype:
                 break
     if w_dtype is None:
         w_dtype = space.w_None
@@ -136,7 +136,7 @@
     arr_iter = arr.start_iter(arr.shape)
     for i in range(len(elems_w)):
         w_elem = elems_w[i]
-        dtype.setitem_w(space, arr.storage, arr_iter.offset, w_elem)
+        dtype.setitem(arr.storage, arr_iter.offset, dtype.coerce(space, w_elem))
         arr_iter = arr_iter.next(shapelen)
     return arr
 
@@ -451,8 +451,8 @@
                                               self=self, dtype=dtype,
                                               i=i, result=result, idx=idx,
                                               cur_best=cur_best)
-                new_best = getattr(dtype, op_name)(cur_best, self.eval(i))
-                if dtype.ne(new_best, cur_best):
+                new_best = getattr(dtype.itemtype, op_name)(cur_best, self.eval(i))
+                if dtype.itemtype.ne(new_best, cur_best):
                     result = idx
                     cur_best = new_best
                 i = i.next(shapelen)
@@ -462,8 +462,7 @@
             size = self.find_size()
             if size == 0:
                 raise OperationError(space.w_ValueError,
-                    space.wrap("Can't call %s on zero-size arrays" \
-                            % op_name))
+                    space.wrap("Can't call %s on zero-size arrays" % op_name))
             return space.wrap(loop(self))
         return func_with_new_name(impl, "reduce_arg%s_impl" % op_name)
 
@@ -475,7 +474,7 @@
             all_driver.jit_merge_point(signature=self.signature,
                                        shapelen=shapelen, self=self,
                                        dtype=dtype, i=i)
-            if not dtype.bool(self.eval(i)):
+            if not dtype.itemtype.bool(self.eval(i)):
                 return False
             i = i.next(shapelen)
         return True
@@ -490,7 +489,7 @@
             any_driver.jit_merge_point(signature=self.signature,
                                        shapelen=shapelen, self=self,
                                        dtype=dtype, i=i)
-            if dtype.bool(self.eval(i)):
+            if dtype.itemtype.bool(self.eval(i)):
                 return True
             i = i.next(shapelen)
         return False
@@ -542,8 +541,8 @@
                 res.append(')')
         else:
             concrete.to_str(space, 1, res, indent='       ')
-        if (dtype is not space.fromcache(interp_dtype.W_Float64Dtype) and
-            dtype is not space.fromcache(interp_dtype.W_Int64Dtype)) or \
+        if (dtype is not interp_dtype.get_dtype_cache(space).w_float64dtype and
+            dtype is not interp_dtype.get_dtype_cache(space).w_int64dtype) or \
             not self.find_size():
             res.append(", dtype=" + dtype.name)
         res.append(")")
@@ -612,7 +611,7 @@
                         start = False
                     else:
                         builder.append(spacer)
-                    builder.append(dtype.str_format(self.getitem(item)))
+                    builder.append(dtype.itemtype.str_format(self.getitem(item)))
                     item += self.strides[0]
                 # Add a comma only if comma is False - this prevents adding two
                 # commas
@@ -625,7 +624,7 @@
                     start = False
                 else:
                     builder.append(spacer)
-                builder.append(dtype.str_format(self.getitem(item)))
+                builder.append(dtype.itemtype.str_format(self.getitem(item)))
                 item += self.strides[0]
                 i += 1
         else:
@@ -712,7 +711,7 @@
                 raise OperationError(space.w_IndexError, space.wrap(
                         "0-d arrays can't be indexed"))
             item = concrete._index_of_single_item(space, w_idx)
-            return concrete.getitem(item).wrap(space)
+            return concrete.getitem(item)
         chunks = self._prepare_slice_args(space, w_idx)
         return space.wrap(self.create_slice(space, chunks))
 
@@ -771,14 +770,15 @@
                          shape[:])
 
     def descr_mean(self, space):
-        return space.wrap(space.float_w(self.descr_sum(space)) / self.find_size())
+        return space.div(self.descr_sum(space), space.wrap(self.find_size()))
 
     def descr_nonzero(self, space):
         if self.find_size() > 1:
             raise OperationError(space.w_ValueError, space.wrap(
                 "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"))
-        return space.wrap(space.is_true(self.get_concrete().eval(
-            self.start_iter(self.shape)).wrap(space)))
+        return space.wrap(space.is_true(
+            self.get_concrete().eval(self.start_iter(self.shape))
+        ))
 
     def descr_get_transpose(self, space):
         concrete = self.get_concrete()
@@ -823,8 +823,7 @@
         return scalar_w(space, dtype, w_obj)
 
 def scalar_w(space, dtype, w_obj):
-    assert isinstance(dtype, interp_dtype.W_Dtype)
-    return Scalar(dtype, dtype.unwrap(space, w_obj))
+    return Scalar(dtype, dtype.coerce(space, w_obj))
 
 class Scalar(BaseArray):
     """
@@ -858,7 +857,7 @@
         return ConstantIterator()
 
     def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
-        builder.append(self.dtype.str_format(self.value))
+        builder.append(self.dtype.itemtype.str_format(self.value))
 
     def copy(self):
         return Scalar(self.dtype, self.value)
@@ -1147,9 +1146,9 @@
     def copy(self):
         array = NDimArray(self.size, self.shape[:], self.dtype, self.order)
         rffi.c_memcpy(
-            rffi.cast(rffi.VOIDP, array.storage),
-            rffi.cast(rffi.VOIDP, self.storage),
-            self.size * self.dtype.num_bytes
+            array.storage,
+            self.storage,
+            self.size * self.dtype.itemtype.get_element_size()
         )
         return array
 
@@ -1160,8 +1159,7 @@
             "len() of unsized object"))
 
     def setitem_w(self, space, item, w_value):
-        self.invalidated()
-        self.dtype.setitem_w(space, self.storage, item, w_value)
+        return self.setitem(item, self.dtype.coerce(space, w_value))
 
     def setitem(self, item, value):
         self.invalidated()
@@ -1204,9 +1202,10 @@
     dtype = space.interp_w(interp_dtype.W_Dtype,
         space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
     )
+
     size, shape = _find_size_and_shape(space, w_size)
     arr = NDimArray(size, shape[:], dtype=dtype)
-    one = dtype.adapt_val(1)
+    one = dtype.box(1)
     arr.dtype.fill(arr.storage, one, 0, size)
     return space.wrap(arr)
 
@@ -1308,10 +1307,10 @@
 
     def descr_next(self, space):
         if self.iter.done():
-            raise OperationError(space.w_StopIteration, space.wrap(''))
+            raise OperationError(space.w_StopIteration, space.w_None)
         result = self.eval(self.iter)
         self.iter = self.iter.next(self.shapelen)
-        return result.wrap(space)
+        return result
 
     def descr_iter(self):
         return self
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
--- a/pypy/module/micronumpy/interp_support.py
+++ b/pypy/module/micronumpy/interp_support.py
@@ -1,6 +1,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
 from pypy.rlib.rstruct.runpack import runpack
 from pypy.rpython.lltypesystem import lltype, rffi
 
@@ -18,7 +18,7 @@
         raise OperationError(space.w_ValueError, space.wrap(
             "string length %d not divisable by %d" % (length, FLOAT_SIZE)))
 
-    dtype = space.fromcache(W_Float64Dtype)
+    dtype = get_dtype_cache(space).w_float64dtype
     a = NDimArray(number, [number], dtype=dtype)
 
     start = 0
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, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
-from pypy.module.micronumpy import interp_dtype, signature
+from pypy.module.micronumpy import interp_boxes, 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
@@ -29,7 +29,7 @@
     def descr_get_identity(self, space):
         if self.identity is None:
             return space.w_None
-        return self.identity.wrap(space)
+        return self.identity
 
     def descr_call(self, space, __args__):
         if __args__.keywords or len(__args__.arguments_w) < self.argcount:
@@ -80,8 +80,7 @@
         new_sig = signature.Signature.find_sig([
             self.reduce_signature, obj.signature
         ])
-        return self.reduce_loop(new_sig, shapelen, start, value, obj,
-                           dtype).wrap(space)
+        return self.reduce_loop(new_sig, shapelen, start, value, obj, dtype)
 
     def reduce_loop(self, signature, shapelen, i, value, obj, dtype):
         while not i.done():
@@ -115,7 +114,7 @@
             promote_bools=self.promote_bools,
         )
         if isinstance(w_obj, Scalar):
-            return self.func(res_dtype, w_obj.value.convert_to(res_dtype)).wrap(space)
+            return self.func(res_dtype, w_obj.value.convert_to(res_dtype))
 
         new_sig = signature.Signature.find_sig([self.signature, w_obj.signature])
         w_res = Call1(new_sig, w_obj.shape, res_dtype, w_obj, w_obj.order)
@@ -148,14 +147,14 @@
             promote_bools=self.promote_bools,
         )
         if self.comparison_func:
-            res_dtype = space.fromcache(interp_dtype.W_BoolDtype)
+            res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
         else:
             res_dtype = calc_dtype
         if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar):
             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
@@ -169,7 +168,7 @@
 
 
 W_Ufunc.typedef = TypeDef("ufunc",
-    __module__ = "numpy",
+    __module__ = "numpypy",
 
     __call__ = interp2app(W_Ufunc.descr_call),
     __repr__ = interp2app(W_Ufunc.descr_repr),
@@ -187,7 +186,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.
@@ -197,14 +196,14 @@
     # Everything promotes to float, and bool promotes to everything.
     if dt2.kind == interp_dtype.FLOATINGLTR or dt1.kind == interp_dtype.BOOLLTR:
         # Float32 + 8-bit int = Float64
-        if dt2.num == 11 and dt1.num_bytes >= 4:
-            return space.fromcache(interp_dtype.W_Float64Dtype)
+        if dt2.num == 11 and dt1.itemtype.get_element_size() >= 4:
+            return interp_dtype.get_dtype_cache(space).w_float64dtype
         return dt2
 
     # for now this means mixing signed and unsigned
     if dt2.kind == interp_dtype.SIGNEDLTR:
         # if dt2 has a greater number of bytes, then just go with it
-        if dt1.num_bytes < dt2.num_bytes:
+        if dt1.itemtype.get_element_size() < dt2.itemtype.get_element_size():
             return dt2
         # we need to promote both dtypes
         dtypenum = dt2.num + 2
@@ -214,10 +213,11 @@
         # UInt64 + signed = Float64
         if dt2.num == 10:
             dtypenum += 1
-    newdtype = interp_dtype.ALL_DTYPES[dtypenum]
+    newdtype = interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum]
 
-    if newdtype.num_bytes > dt2.num_bytes or newdtype.kind == interp_dtype.FLOATINGLTR:
-        return space.fromcache(newdtype)
+    if (newdtype.itemtype.get_element_size() > dt2.itemtype.get_element_size() or
+        newdtype.kind == interp_dtype.FLOATINGLTR):
+        return newdtype
     else:
         # we only promoted to long on 32-bit or to longlong on 64-bit
         # this is really for dealing with the Long and Ulong dtypes
@@ -225,35 +225,42 @@
             dtypenum += 2
         else:
             dtypenum += 3
-        return space.fromcache(interp_dtype.ALL_DTYPES[dtypenum])
+        return interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum]
 
 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)
+            return interp_dtype.get_dtype_cache(space).w_float64dtype
         elif dt.kind == interp_dtype.FLOATINGLTR:
-            return space.fromcache(interp_dtype.W_Float64Dtype)
+            return interp_dtype.get_dtype_cache(space).w_float64dtype
         elif dt.kind == interp_dtype.UNSIGNEDLTR:
-            return space.fromcache(interp_dtype.W_UInt64Dtype)
+            return interp_dtype.get_dtype_cache(space).w_uint64dtype
         else:
             assert False
     return dt
 
 def find_dtype_for_scalar(space, w_obj, current_guess=None):
-    bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
-    long_dtype = space.fromcache(interp_dtype.W_LongDtype)
-    int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype)
+    bool_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
+    long_dtype = interp_dtype.get_dtype_cache(space).w_longdtype
+    int64_dtype = interp_dtype.get_dtype_cache(space).w_int64dtype
+
+    if isinstance(w_obj, interp_boxes.W_GenericBox):
+        dtype = w_obj.get_dtype(space)
+        if current_guess is None:
+            return dtype
+        return find_binop_result_dtype(space, dtype, current_guess)
 
     if space.isinstance_w(w_obj, space.w_bool):
         if current_guess is None or current_guess is bool_dtype:
@@ -269,20 +276,19 @@
             current_guess is long_dtype or current_guess is int64_dtype):
             return int64_dtype
         return current_guess
-    return space.fromcache(interp_dtype.W_Float64Dtype)
+    return interp_dtype.get_dtype_cache(space).w_float64dtype
 
 
 def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func):
     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:
+        dtype_cache = interp_dtype.get_dtype_cache(space)
         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)
-                res = booldtype.box(res)
+                return dtype_cache.w_booldtype.box(res)
             return res
     return func_with_new_name(impl, ufunc_name)
 
@@ -338,7 +344,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 NDimArray, 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 = NDimArray(10, [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 = NDimArray(10, [10], dtype=space.fromcache(interp_dtype.W_BoolDtype))
+        bool_ar = NDimArray(10, [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 = NDimArray(10, [10], dtype=space.fromcache(interp_dtype.W_Float64Dtype))
+        float64_dtype = get_dtype_cache(space).w_float64dtype
+
+        ar = NDimArray(10, [10], dtype=float64_dtype)
         v1 = ar.descr_getitem(space, space.wrap(slice(1, 3, 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
diff --git a/pypy/module/micronumpy/test/test_compile.py b/pypy/module/micronumpy/test/test_compile.py
--- a/pypy/module/micronumpy/test/test_compile.py
+++ b/pypy/module/micronumpy/test/test_compile.py
@@ -106,7 +106,7 @@
         c -> 3
         """
         interp = self.run(code)
-        assert interp.results[-1].value.val == 9
+        assert interp.results[-1].value == 9
 
     def test_array_getitem(self):
         code = """
@@ -115,7 +115,7 @@
         a + b -> 3
         """
         interp = self.run(code)
-        assert interp.results[0].value.val == 3 + 6
+        assert interp.results[0].value == 3 + 6
 
     def test_range_getitem(self):
         code = """
@@ -123,7 +123,7 @@
         r -> 3
         """
         interp = self.run(code)
-        assert interp.results[0].value.val == 6
+        assert interp.results[0].value == 6
 
     def test_sum(self):
         code = """
@@ -132,7 +132,7 @@
         r
         """
         interp = self.run(code)
-        assert interp.results[0].value.val == 15
+        assert interp.results[0].value.value == 15
 
     def test_array_write(self):
         code = """
@@ -141,7 +141,7 @@
         a -> 3
         """
         interp = self.run(code)
-        assert interp.results[0].value.val == 15
+        assert interp.results[0].value == 15
 
     def test_min(self):
         interp = self.run("""
@@ -150,7 +150,7 @@
         b = a + a
         min(b)
         """)
-        assert interp.results[0].value.val == -24
+        assert interp.results[0].value.value == -24
 
     def test_max(self):
         interp = self.run("""
@@ -159,7 +159,7 @@
         b = a + a
         max(b)
         """)
-        assert interp.results[0].value.val == 256
+        assert interp.results[0].value.value == 256
 
     def test_slice(self):
         interp = self.run("""
@@ -167,7 +167,7 @@
         b = a -> :
         b -> 3
         """)
-        assert interp.results[0].value.val == 4
+        assert interp.results[0].value == 4
 
     def test_slice_step(self):
         interp = self.run("""
@@ -175,7 +175,7 @@
         b = a -> ::2
         b -> 3
         """)
-        assert interp.results[0].value.val == 6
+        assert interp.results[0].value == 6
 
     def test_setslice(self):
         interp = self.run("""
@@ -185,7 +185,7 @@
         a[::3] = b
         a -> 3
         """)
-        assert interp.results[0].value.val == 5
+        assert interp.results[0].value == 5
 
 
     def test_slice2(self):
@@ -196,14 +196,14 @@
         b = s1 + s2
         b -> 3
         """)
-        assert interp.results[0].value.val == 15
+        assert interp.results[0].value == 15
 
     def test_multidim_getitem(self):
         interp = self.run("""
         a = [[1,2]]
         a -> 0 -> 1
         """)
-        assert interp.results[0].value.val == 2
+        assert interp.results[0].value == 2
 
     def test_multidim_getitem_2(self):
         interp = self.run("""
@@ -211,7 +211,7 @@
         b = a + a
         b -> 1 -> 1
         """)
-        assert interp.results[0].value.val == 8
+        assert interp.results[0].value == 8
 
     def test_set_slice(self):
         interp = self.run("""
@@ -220,7 +220,7 @@
         b[:] = a + a
         b -> 3
         """)
-        assert interp.results[0].value.val == 6
+        assert interp.results[0].value == 6
 
     def test_set_slice2(self):
         interp = self.run("""
@@ -231,4 +231,4 @@
         a[0:30:3] = c
         a -> 3
         """)
-        assert interp.results[0].value.val == 11        
+        assert interp.results[0].value == 11
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -30,7 +30,7 @@
     def test_repr_str(self):
         from numpypy import dtype
 
-        assert repr(dtype) == "<type 'numpy.dtype'>"
+        assert repr(dtype) == "<type 'numpypy.dtype'>"
         d = dtype('?')
         assert repr(d) == "dtype('bool')"
         assert str(d) == "bool"
@@ -44,13 +44,13 @@
             assert a[i] is True_
 
     def test_copy_array_with_dtype(self):
-        from numpypy import array, False_, True_
+        from numpypy import array, False_, True_, int64
 
         a = array([0, 1, 2, 3], dtype=long)
         # int on 64-bit, long in 32-bit
-        assert isinstance(a[0], (int, long))
+        assert isinstance(a[0], int64)
         b = a.copy()
-        assert isinstance(b[0], (int, long))
+        assert isinstance(b[0], int64)
 
         a = array([0, 1, 2, 3], dtype=bool)
         assert a[0] is False_
@@ -72,17 +72,17 @@
             assert a[i] is True_
 
     def test_zeros_long(self):
-        from numpypy import zeros
+        from numpypy import zeros, int64
         a = zeros(10, dtype=long)
         for i in range(10):
-            assert isinstance(a[i], (int, long))
+            assert isinstance(a[i], int64)
             assert a[1] == 0
 
     def test_ones_long(self):
-        from numpypy import ones
+        from numpypy import ones, int64
         a = ones(10, dtype=long)
         for i in range(10):
-            assert isinstance(a[i], (int, long))
+            assert isinstance(a[i], int64)
             assert a[1] == 1
 
     def test_overflow(self):
@@ -165,3 +165,99 @@
 
         # You can't subclass dtype
         raises(TypeError, type, "Foo", (dtype,), {})
+
+class AppTestTypes(BaseNumpyAppTest):
+    def test_abstract_types(self):
+        import numpypy as numpy
+        raises(TypeError, numpy.generic, 0)
+        raises(TypeError, numpy.number, 0)
+        raises(TypeError, numpy.integer, 0)
+        exc = raises(TypeError, numpy.signedinteger, 0)
+        assert str(exc.value) == "cannot create 'numpypy.signedinteger' instances"
+
+        raises(TypeError, numpy.floating, 0)
+        raises(TypeError, numpy.inexact, 0)
+
+    def test_bool(self):
+        import numpypy as numpy
+
+        assert numpy.bool_.mro() == [numpy.bool_, numpy.generic, object]
+        assert numpy.bool_(3) is numpy.True_
+        assert numpy.bool_("") is numpy.False_
+        assert type(numpy.True_) is type(numpy.False_) is numpy.bool_
+
+        class X(numpy.bool_):
+            pass
+
+        assert type(X(True)) is numpy.bool_
+        assert X(True) is numpy.True_
+
+    def test_int8(self):
+        import numpypy as numpy
+
+        assert numpy.int8.mro() == [numpy.int8, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object]
+
+        a = numpy.array([1, 2, 3], numpy.int8)
+        assert type(a[1]) is numpy.int8
+        assert numpy.dtype("int8").type is numpy.int8
+
+        x = numpy.int8(128)
+        assert x == -128
+        assert x != 128
+        assert type(x) is numpy.int8
+        assert repr(x) == "-128"
+
+        assert type(int(x)) is int
+        assert int(x) == -128
+
+    def test_int16(self):
+        import numpypy as numpy
+
+        x = numpy.int16(3)
+        assert x == 3
+
+    def test_int32(self):
+        import numpypy as numpy
+
+        x = numpy.int32(23)
+        assert x == 23
+
+    def test_int_(self):
+        import numpypy as numpy
+
+        assert numpy.int_ is numpy.dtype(int).type
+        assert numpy.int_.mro() == [numpy.int_, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, int, object]
+
+    def test_int64(self):
+        import sys
+        import numpypy as numpy
+
+        if sys.maxint == 2 ** 63 -1:
+            assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, int, object]
+        else:
+            assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object]
+
+        assert numpy.dtype(numpy.int64).type is numpy.int64
+        assert numpy.int64(3) == 3
+
+    def test_float64(self):
+        import numpypy as numpy
+
+        assert numpy.float64.mro() == [numpy.float64, numpy.floating, numpy.inexact, numpy.number, numpy.generic, float, object]
+
+        a = numpy.array([1, 2, 3], numpy.float64)
+        assert type(a[1]) is numpy.float64
+        assert numpy.dtype(float).type is numpy.float64
+
+        assert numpy.float64(2.0) == 2.0
+
+    def test_subclass_type(self):
+        import numpypy as numpy
+
+        class X(numpy.float64):
+            def m(self):
+                return self + 2
+
+        b = X(10)
+        assert type(b) is X
+        assert b.m() == 12
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -709,7 +709,7 @@
             assert b[i] == 2.5 * a[i]
 
     def test_dtype_guessing(self):
-        from numpypy import array, dtype
+        from numpypy import array, dtype, float64, int8, bool_
 
         assert array([True]).dtype is dtype(bool)
         assert array([True, False]).dtype is dtype(bool)
@@ -719,6 +719,10 @@
         assert array([1.2, True]).dtype is dtype(float)
         assert array([1.2, 5]).dtype is dtype(float)
         assert array([]).dtype is dtype(float)
+        assert array([float64(2)]).dtype is dtype(float)
+        assert array([int8(3)]).dtype is dtype("int8")
+        assert array([bool_(True)]).dtype is dtype(bool)
+        assert array([bool_(True), 3.0]).dtype is dtype(float)
 
     def test_comparison(self):
         import operator
@@ -1008,10 +1012,10 @@
         b = a[0].copy()
         assert (b == zeros(10)).all()
 
-class AppTestSupport(object):
+class AppTestSupport(BaseNumpyAppTest):
     def setup_class(cls):
         import struct
-        cls.space = gettestobjspace(usemodules=('micronumpy',))
+        BaseNumpyAppTest.setup_class.im_func(cls)
         cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4))
 
     def test_fromstring(self):
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -8,7 +8,7 @@
 
         assert isinstance(add, ufunc)
         assert repr(add) == "<ufunc 'add'>"
-        assert repr(ufunc) == "<type 'numpy.ufunc'>"
+        assert repr(ufunc) == "<type 'numpypy.ufunc'>"
 
     def test_ufunc_attrs(self):
         from numpypy import add, multiply, sin
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -8,11 +8,11 @@
 from pypy.jit.metainterp import pyjitpl
 from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.jit.metainterp.warmspot import reset_stats
-from pypy.module.micronumpy import interp_ufuncs, signature
+from pypy.module.micronumpy import interp_boxes, interp_ufuncs, signature
 from pypy.module.micronumpy.compile import (numpy_compile, FakeSpace,
     FloatObject, IntObject, BoolObject, Parser, InterpreterState)
-from pypy.module.micronumpy.interp_numarray import NDimArray, NDimSlice,\
-     BaseArray
+from pypy.module.micronumpy.interp_numarray import (NDimArray, NDimSlice,
+     BaseArray)
 from pypy.rlib.nonconst import NonConstant
 from pypy.rpython.annlowlevel import llstr, hlstr
 
@@ -48,17 +48,15 @@
         def f(i):
             interp = InterpreterState(codes[i])
             interp.run(space)
-            res = interp.results[-1]
-            assert isinstance(res, BaseArray)
-            w_res = res.eval(res.start_iter()).wrap(interp.space)
-            if isinstance(w_res, BoolObject):
-                return float(w_res.boolval)
-            elif isinstance(w_res, FloatObject):
-                return w_res.floatval
-            elif isinstance(w_res, IntObject):
-                return w_res.intval
-            else:
-                return -42.
+            w_res = interp.results[-1]
+            if isinstance(w_res, BaseArray):
+                w_res = w_res.eval(w_res.start_iter())
+
+            if isinstance(w_res, interp_boxes.W_Float64Box):
+                return w_res.value
+            elif isinstance(w_res, interp_boxes.W_BoolBox):
+                return float(w_res.value)
+            raise TypeError(w_res)
 
         if self.graph is None:
             interp, graph = self.meta_interp(f, [i],
@@ -80,9 +78,9 @@
 
     def test_add(self):
         result = self.run("add")
-        self.check_simple_loop({'getarrayitem_raw': 2, 'float_add': 1,
-                          'setarrayitem_raw': 1, 'int_add': 3,
-                          'int_ge': 1, 'guard_false': 1, 'jump': 1})
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+                                'setinteriorfield_raw': 1, 'int_add': 3,
+                                'int_ge': 1, 'guard_false': 1, 'jump': 1})
         assert result == 3 + 3
 
     def define_float_add():
@@ -94,9 +92,9 @@
     def test_floatadd(self):
         result = self.run("float_add")
         assert result == 3 + 3
-        self.check_simple_loop({"getarrayitem_raw": 1, "float_add": 1,
-                          "setarrayitem_raw": 1, "int_add": 2,
-                          "int_ge": 1, "guard_false": 1, "jump": 1})
+        self.check_simple_loop({"getinteriorfield_raw": 1, "float_add": 1,
+                                "setinteriorfield_raw": 1, "int_add": 2,
+                                "int_ge": 1, "guard_false": 1, "jump": 1})
 
     def define_sum():
         return """
@@ -108,9 +106,9 @@
     def test_sum(self):
         result = self.run("sum")
         assert result == 2 * sum(range(30))
-        self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 2,
-                          "int_add": 2,
-                          "int_ge": 1, "guard_false": 1, "jump": 1})
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 2,
+                                "int_add": 2, "int_ge": 1, "guard_false": 1,
+                                "jump": 1})
 
     def define_prod():
         return """
@@ -125,9 +123,9 @@
         for i in range(30):
             expected *= i * 2
         assert result == expected
-        self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_mul": 1, "int_add": 2,
-                          "int_ge": 1, "guard_false": 1, "jump": 1})
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+                                "float_mul": 1, "int_add": 2,
+                                "int_ge": 1, "guard_false": 1, "jump": 1})
 
     def test_max(self):
         py.test.skip("broken, investigate")
@@ -138,9 +136,9 @@
         max(b)
         """)
         assert result == 256
-        self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_mul": 1, "int_add": 1,
-                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+                                "float_mul": 1, "int_add": 1,
+                                "int_lt": 1, "guard_true": 1, "jump": 1})
 
     def test_min(self):
         py.test.skip("broken, investigate")
@@ -151,9 +149,9 @@
         min(b)
         """)
         assert result == -24
-        self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_mul": 1, "int_add": 1,
-                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+                                "float_mul": 1, "int_add": 1,
+                                "int_lt": 1, "guard_true": 1, "jump": 1})
 
     def define_any():
         return """
@@ -166,10 +164,10 @@
     def test_any(self):
         result = self.run("any")
         assert result == 1
-        self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_ne": 1, "int_add": 2,
-                          "int_ge": 1, "jump": 1,
-                          "guard_false": 2})
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+                                "float_ne": 1, "int_add": 2,
+                                "int_ge": 1, "jump": 1,
+                                "guard_false": 2})
 
     def define_already_forced():
         return """
@@ -188,10 +186,10 @@
         # sure it was optimized correctly.
         # XXX the comment above is wrong now.  We need preferrably a way to
         # count the two loops separately
-        self.check_resops({'setarrayitem_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 35,
+        self.check_resops({'setinteriorfield_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 41,
                            'guard_class': 22, 'int_add': 8, 'float_mul': 2,
                            'guard_isnull': 2, 'jump': 4, 'int_ge': 4,
-                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
+                           'getinteriorfield_raw': 4, 'float_add': 2, 'guard_false': 4,
                            'guard_value': 2})
 
     def define_ufunc():
@@ -205,10 +203,9 @@
     def test_ufunc(self):
         result = self.run("ufunc")
         assert result == -6
-        self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1, "float_neg": 1,
-                          "setarrayitem_raw": 1, "int_add": 3,
-                          "int_ge": 1, "guard_false": 1, "jump": 1,
-        })
+        self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1, "float_neg": 1,
+                                "setinteriorfield_raw": 1, "int_add": 3,
+                                "int_ge": 1, "guard_false": 1, "jump": 1})
 
     def define_specialization():
         return """
@@ -246,9 +243,9 @@
     def test_slice(self):
         result = self.run("slice")
         assert result == 18
-        self.check_simple_loop({'getarrayitem_raw': 2,
+        self.check_simple_loop({'getinteriorfield_raw': 2,
                                 'float_add': 1,
-                                'setarrayitem_raw': 1,
+                                'setinteriorfield_raw': 1,
                                 'int_add': 3,
                                 'int_ge': 1, 'guard_false': 1,
                                 'jump': 1})
@@ -265,8 +262,8 @@
     def test_slice2(self):
         result = self.run("slice2")
         assert result == 15
-        self.check_simple_loop({'getarrayitem_raw': 2, 'float_add': 1,
-                                'setarrayitem_raw': 1, 'int_add': 3,
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+                                'setinteriorfield_raw': 1, 'int_add': 3,
                                 'int_ge': 1, 'guard_false': 1, 'jump': 1})
 
     def define_multidim():
@@ -279,11 +276,11 @@
     def test_multidim(self):
         result = self.run('multidim')
         assert result == 8
-        self.check_simple_loop({'float_add': 1, 'getarrayitem_raw': 2,
-                          'guard_false': 1, 'int_add': 3, 'int_ge': 1,
-                          'jump': 1, 'setarrayitem_raw': 1})
         # int_add might be 1 here if we try slightly harder with
         # reusing indexes or some optimization
+        self.check_simple_loop({'float_add': 1, 'getinteriorfield_raw': 2,
+                                'guard_false': 1, 'int_add': 3, 'int_ge': 1,
+                                'jump': 1, 'setinteriorfield_raw': 1})
 
     def define_multidim_slice():
         return """
@@ -329,18 +326,18 @@
         result = self.run("setslice")
         assert result == 11.0
         self.check_loop_count(1)
-        self.check_simple_loop({'getarrayitem_raw': 2, 'float_add' : 1,
-                                'setarrayitem_raw': 1, 'int_add': 3,
+        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add' : 1,
+                                'setinteriorfield_raw': 1, 'int_add': 3,
                                 'int_eq': 1, 'guard_false': 1, 'jump': 1})
 
 class TestNumpyOld(LLJitMixin):
     def setup_class(cls):
         py.test.skip("old")
         from pypy.module.micronumpy.compile import FakeSpace
-        from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
+        from pypy.module.micronumpy.interp_dtype import get_dtype_cache
 
         cls.space = FakeSpace()
-        cls.float64_dtype = cls.space.fromcache(W_Float64Dtype)
+        cls.float64_dtype = get_dtype_cache(cls.space).w_float64dtype
 
     def test_int32_sum(self):
         py.test.skip("pypy/jit/backend/llimpl.py needs to be changed to "
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/types.py
@@ -0,0 +1,389 @@
+import functools
+import math
+
+from pypy.module.micronumpy import interp_boxes
+from pypy.objspace.std.floatobject import float2string
+from pypy.rlib import rfloat, libffi, clibffi
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import LONG_BIT, widen
+from pypy.rpython.lltypesystem import lltype, rffi
+
+
+def simple_unary_op(func):
+    specialize.argtype(1)(func)
+    @functools.wraps(func)
+    def dispatcher(self, v):
+        return self.box(
+            func(
+                self,
+                self.for_computation(self.unbox(v))
+            )
+        )
+    return dispatcher
+
+def simple_binary_op(func):
+    specialize.argtype(1, 2)(func)
+    @functools.wraps(func)
+    def dispatcher(self, v1, v2):
+        return self.box(
+            func(
+                self,
+                self.for_computation(self.unbox(v1)),
+                self.for_computation(self.unbox(v2)),
+            )
+        )
+    return dispatcher
+
+def raw_binary_op(func):
+    specialize.argtype(1, 2)(func)
+    @functools.wraps(func)
+    def dispatcher(self, v1, v2):
+        return func(self,
+            self.for_computation(self.unbox(v1)),
+            self.for_computation(self.unbox(v2))
+        )
+    return dispatcher
+
+class BaseType(object):
+    def _unimplemented_ufunc(self, *args):
+        raise NotImplementedError
+    # add = sub = mul = div = mod = pow = eq = ne = lt = le = gt = ge = max = \
+    #     min = copysign = pos = neg = abs = sign = reciprocal = fabs = floor = \
+    #     exp = sin = cos = tan = arcsin = arccos = arctan = arcsinh = \
+    #     arctanh = _unimplemented_ufunc
+
+class Primitive(object):
+    _mixin_ = True
+    def get_element_size(self):
+        return rffi.sizeof(self.T)
+
+    @specialize.argtype(1)
+    def box(self, value):
+        return self.BoxType(rffi.cast(self.T, value))
+
+    def unbox(self, box):
+        assert isinstance(box, self.BoxType)
+        return box.value
+
+    def coerce(self, space, w_item):
+        if isinstance(w_item, self.BoxType):
+            return w_item
+        return self.coerce_subtype(space, space.gettypefor(self.BoxType), w_item)
+
+    def coerce_subtype(self, space, w_subtype, w_item):
+        # XXX: ugly
+        w_obj = space.allocate_instance(self.BoxType, w_subtype)
+        assert isinstance(w_obj, self.BoxType)
+        w_obj.__init__(self._coerce(space, w_item).value)
+        return w_obj
+
+    def _coerce(self, space, w_item):
+        raise NotImplementedError
+
+    def read(self, storage, width, i, offset):
+        return self.box(libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
+            width, storage, i, offset
+        ))
+
+    def store(self, storage, width, i, offset, box):
+        value = self.unbox(box)
+        libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+            width, storage, i, offset, value
+        )
+
+    def fill(self, storage, width, box, start, stop, offset):
+        value = self.unbox(box)
+        for i in xrange(start, stop):
+            libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+                width, storage, i, offset, value
+            )
+
+    @simple_binary_op
+    def add(self, v1, v2):
+        return v1 + v2
+
+    @simple_binary_op
+    def sub(self, v1, v2):
+        return v1 - v2
+
+    @simple_binary_op
+    def mul(self, v1, v2):
+        return v1 * v2
+
+    @simple_unary_op
+    def pos(self, v):
+        return +v
+
+    @simple_unary_op
+    def neg(self, v):
+        return -v
+
+    @simple_unary_op
+    def abs(self, v):
+        return abs(v)
+
+    @raw_binary_op
+    def eq(self, v1, v2):
+        return v1 == v2
+
+    @raw_binary_op
+    def ne(self, v1, v2):
+        return v1 != v2
+
+    @raw_binary_op
+    def lt(self, v1, v2):
+        return v1 < v2
+
+    @raw_binary_op
+    def le(self, v1, v2):
+        return v1 <= v2
+
+    @raw_binary_op
+    def gt(self, v1, v2):
+        return v1 > v2
+
+    @raw_binary_op
+    def ge(self, v1, v2):
+        return v1 >= v2
+
+    def bool(self, v):
+        return bool(self.for_computation(self.unbox(v)))
+
+    @simple_binary_op
+    def max(self, v1, v2):
+        return max(v1, v2)
+
+    @simple_binary_op
+    def min(self, v1, v2):
+        return min(v1, v2)
+
+class Bool(BaseType, Primitive):
+    T = lltype.Bool
+    BoxType = interp_boxes.W_BoolBox
+
+    True = BoxType(True)
+    False = BoxType(False)
+
+    @specialize.argtype(1)
+    def box(self, value):
+        box = Primitive.box(self, value)
+        if box.value:
+            return self.True
+        else:
+            return self.False
+
+    def coerce_subtype(self, space, w_subtype, w_item):
+        # Doesn't return subclasses so it can return the constants.
+        return self._coerce(space, w_item)
+
+    def _coerce(self, space, w_item):
+        return self.box(space.is_true(w_item))
+
+    def str_format(self, box):
+        value = self.unbox(box)
+        return "True" if value else "False"
+
+    def for_computation(self, v):
+        return int(v)
+
+class Integer(Primitive):
+    _mixin_ = True
+
+    def _coerce(self, space, w_item):
+        return self.box(space.int_w(space.int(w_item)))
+
+    def str_format(self, box):
+        value = self.unbox(box)
+        return str(self.for_computation(value))
+
+    def for_computation(self, v):
+        return widen(v)
+
+    @simple_binary_op
+    def div(self, v1, v2):
+        if v2 == 0:
+            return 0
+        return v1 / v2
+
+    @simple_binary_op
+    def mod(self, v1, v2):
+        return v1 % v2
+
+    @simple_binary_op
+    def pow(self, v1, v2):
+        res = 1
+        while v2 > 0:
+            if v2 & 1:
+                res *= v1
+            v2 >>= 1
+            if v2 == 0:
+                break
+            v1 *= v1
+        return res
+
+    @simple_unary_op
+    def sign(self, v):
+        if v > 0:
+            return 1
+        elif v < 0:
+            return -1
+        else:
+            assert v == 0
+            return 0
+
+class Int8(BaseType, Integer):
+    T = rffi.SIGNEDCHAR
+    BoxType = interp_boxes.W_Int8Box
+
+class UInt8(BaseType, Integer):
+    T = rffi.UCHAR
+    BoxType = interp_boxes.W_UInt8Box
+
+class Int16(BaseType, Integer):
+    T = rffi.SHORT
+    BoxType = interp_boxes.W_Int16Box
+
+class UInt16(BaseType, Integer):
+    T = rffi.USHORT
+    BoxType = interp_boxes.W_UInt16Box
+
+class Int32(BaseType, Integer):
+    T = rffi.INT
+    BoxType = interp_boxes.W_Int32Box
+
+class UInt32(BaseType, Integer):
+    T = rffi.UINT
+    BoxType = interp_boxes.W_UInt32Box
+
+class Long(BaseType, Integer):
+    T = rffi.LONG
+    BoxType = interp_boxes.W_LongBox
+
+class ULong(BaseType, Integer):
+    T = rffi.ULONG
+    BoxType = interp_boxes.W_ULongBox
+
+class Int64(BaseType, Integer):
+    T = rffi.LONGLONG
+    BoxType = interp_boxes.W_Int64Box
+
+class UInt64(BaseType, Integer):
+    T = rffi.ULONGLONG
+    BoxType = interp_boxes.W_UInt64Box
+
+class Float(Primitive):
+    _mixin_ = True
+
+    def _coerce(self, space, w_item):
+        return self.box(space.float_w(space.float(w_item)))
+
+    def str_format(self, box):
+        value = self.unbox(box)
+        return float2string(self.for_computation(value), "g", rfloat.DTSF_STR_PRECISION)
+
+    def for_computation(self, v):
+        return float(v)
+
+    @simple_binary_op
+    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)
+
+    @simple_binary_op
+    def mod(self, v1, v2):
+        return math.fmod(v1, v2)
+
+    @simple_binary_op
+    def pow(self, v1, v2):
+        return math.pow(v1, v2)
+
+    @simple_binary_op
+    def copysign(self, v1, v2):
+        return math.copysign(v1, v2)
+
+    @simple_unary_op
+    def sign(self, v):
+        if v == 0.0:
+            return 0.0
+        return rfloat.copysign(1.0, v)
+
+    @simple_unary_op
+    def fabs(self, v):
+        return math.fabs(v)
+
+    @simple_unary_op
+    def reciprocal(self, v):
+        if v == 0.0:
+            return rfloat.copysign(rfloat.INFINITY, v)
+        return 1.0 / v
+
+    @simple_unary_op
+    def floor(self, v):
+        return math.floor(v)
+
+    @simple_unary_op
+    def exp(self, v):
+        try:
+            return math.exp(v)
+        except OverflowError:
+            return rfloat.INFINITY
+
+    @simple_unary_op
+    def sin(self, v):
+        return math.sin(v)
+
+    @simple_unary_op
+    def cos(self, v):
+        return math.cos(v)
+
+    @simple_unary_op
+    def tan(self, v):
+        return math.tan(v)
+
+    @simple_unary_op
+    def arcsin(self, v):
+        if not -1.0 <= v <= 1.0:
+            return rfloat.NAN
+        return math.asin(v)
+
+    @simple_unary_op
+    def arccos(self, v):
+        if not -1.0 <= v <= 1.0:
+            return rfloat.NAN
+        return math.acos(v)
+
+    @simple_unary_op
+    def arctan(self, v):
+        return math.atan(v)
+
+    @simple_unary_op
+    def arcsinh(self, v):
+        return math.asinh(v)
+
+    @simple_unary_op
+    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)
+
+    @simple_unary_op
+    def sqrt(self, v):
+        try:
+            return math.sqrt(v)
+        except ValueError:
+            return rfloat.NAN
+
+
+class Float32(BaseType, Float):
+    T = rffi.FLOAT
+    BoxType = interp_boxes.W_Float32Box
+
+class Float64(BaseType, Float):
+    T = rffi.DOUBLE
+    BoxType = interp_boxes.W_Float64Box
\ No newline at end of file
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -411,6 +411,10 @@
     def getaddressindll(self, name):
         return dlsym(self.lib, name)
 
+# These specialize.call_location's should really be specialize.arg(0), however
+# you can't hash a pointer obj, which the specialize machinery wants to do.
+# Given the present usage of these functions, it's good enough.
+ at specialize.call_location()
 @jit.oopspec("libffi_array_getitem(ffitype, width, addr, index, offset)")
 def array_getitem(ffitype, width, addr, index, offset):
     for TYPE, ffitype2 in clibffi.ffitype_map:
@@ -420,6 +424,7 @@
             return rffi.cast(rffi.CArrayPtr(TYPE), addr)[0]
     assert False
 
+ at specialize.call_location()
 @jit.oopspec("libffi_array_setitem(ffitype, width, addr, index, offset, value)")
 def array_setitem(ffitype, width, addr, index, offset, value):
     for TYPE, ffitype2 in clibffi.ffitype_map:
@@ -428,4 +433,4 @@
             addr = rffi.ptradd(addr, offset)
             rffi.cast(rffi.CArrayPtr(TYPE), addr)[0] = value
             return
-    assert False
\ No newline at end of file
+    assert False
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -91,9 +91,18 @@
 
         return decorated_func
 
+    def call_location(self):
+        """ Specializes the function for each call site.
+        """
+        def decorated_func(func):
+            func._annspecialcase_ = "specialize:call_location"
+            return func
+
+        return decorated_func
+
     def _wrap(self, args):
         return "("+','.join([repr(arg) for arg in args]) +")"
-        
+
 specialize = _Specialize()
 
 def enforceargs(*args):
@@ -125,7 +134,7 @@
 
     def __hash__(self):
         raise TypeError("Symbolics are not hashable!")
-    
+
     def __nonzero__(self):
         raise TypeError("Symbolics are not comparable")
 
@@ -155,7 +164,7 @@
     def lltype(self):
         from pypy.rpython.lltypesystem import lltype
         return lltype.Signed
-    
+
 malloc_zero_filled = CDefinedIntSymbolic('MALLOC_ZERO_FILLED', default=0)
 running_on_llinterp = CDefinedIntSymbolic('RUNNING_ON_LLINTERP', default=1)
 # running_on_llinterp is meant to have the value 0 in all backends
@@ -221,7 +230,7 @@
 
     def compute_result_annotation(self, s_sizehint):
         from pypy.annotation.model import SomeInteger
-        
+
         assert isinstance(s_sizehint, SomeInteger)
         return self.bookkeeper.newlist()
 


More information about the pypy-commit mailing list