[pypy-commit] pypy ndarray-subtype: more w_ corrections, try to be more clever in call2 for subtype compatability with numpy

mattip noreply at buildbot.pypy.org
Sun Jul 7 00:24:07 CEST 2013


Author: Matti Picus <matti.picus at gmail.com>
Branch: ndarray-subtype
Changeset: r65245:2c2324b57f8c
Date: 2013-07-07 01:21 +0300
http://bitbucket.org/pypy/pypy/changeset/2c2324b57f8c/

Log:	more w_ corrections, try to be more clever in call2 for subtype
	compatability with numpy

diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -28,6 +28,7 @@
 
     def __init__(self, implementation):
         assert isinstance(implementation, BaseArrayImplementation)
+        assert isinstance(self, W_NDimArray)
         self.implementation = implementation
 
     @staticmethod
@@ -41,13 +42,13 @@
             impl = concrete.ConcreteArray(shape, dtype.base, order, strides,
                                       backstrides)
         if w_subtype:
-            ret = space.allocate_instance(W_NDimArray, space.type(w_subtype))
-            W_NDimArray.__init__(ret, impl)
-            space.call_function(space.getattr(ret,
+            w_ret = space.allocate_instance(W_NDimArray, space.type(w_subtype))
+            W_NDimArray.__init__(w_ret, impl)
+            assert isinstance(w_ret, W_NDimArray)
+            space.call_function(space.getattr(w_ret,
                                 space.wrap('__array_finalize__')), w_subtype)
-        else:
-            ret = W_NDimArray(impl)
-        return ret
+            return w_ret
+        return W_NDimArray(impl)
 
     @staticmethod
     def from_shape_and_storage(space, shape, storage, dtype, order='C', owning=False, w_subtype=None):
@@ -62,11 +63,11 @@
             impl = concrete.ConcreteArrayNotOwning(shape, dtype, order, strides,
                                                 backstrides, storage)
         if w_subtype:
-            ret = space.allocate_instance(W_NDimArray, space.type(w_subtype))
-            W_NDimArray.__init__(ret, impl)
-            space.call_function(space.getattr(ret,
+            w_ret = space.allocate_instance(W_NDimArray, w_subtype)
+            W_NDimArray.__init__(w_ret, impl)
+            space.call_function(space.getattr(w_ret,
                                 space.wrap('__array_finalize__')), w_subtype)
-            return ret
+            return w_ret
         return W_NDimArray(impl)
 
     @staticmethod
diff --git a/pypy/module/micronumpy/interp_arrayops.py b/pypy/module/micronumpy/interp_arrayops.py
--- a/pypy/module/micronumpy/interp_arrayops.py
+++ b/pypy/module/micronumpy/interp_arrayops.py
@@ -148,24 +148,24 @@
 def repeat(space, w_arr, repeats, w_axis):
     arr = convert_to_array(space, w_arr)
     if space.is_none(w_axis):
-        w_arr = arr.descr_flatten(space)
-        orig_size = w_arr.get_shape()[0]
-        shape = [w_arr.get_shape()[0] * repeats]
-        w_res = W_NDimArray.from_shape(space, shape, arr.get_dtype(), w_subtype=w_arr)
+        arr = arr.descr_flatten(space)
+        orig_size = arr.get_shape()[0]
+        shape = [arr.get_shape()[0] * repeats]
+        w_res = W_NDimArray.from_shape(space, shape, arr.get_dtype(), w_subtype=arr)
         for i in range(repeats):
             Chunks([Chunk(i, shape[0] - repeats + i, repeats,
-                 orig_size)]).apply(space, w_res).implementation.setslice(space, w_arr)
+                 orig_size)]).apply(space, w_res).implementation.setslice(space, arr)
     else:
         axis = space.int_w(w_axis)
-        shape = w_arr.get_shape()[:]
+        shape = arr.get_shape()[:]
         chunks = [Chunk(0, i, 1, i) for i in shape]
         orig_size = shape[axis]
         shape[axis] *= repeats
-        w_res = W_NDimArray.from_shape(space, shape, arr.get_dtype(), w_subtype=w_arr)
+        w_res = W_NDimArray.from_shape(space, shape, arr.get_dtype(), w_subtype=arr)
         for i in range(repeats):
             chunks[axis] = Chunk(i, shape[axis] - repeats + i, repeats,
                                  orig_size)
-            Chunks(chunks).apply(space, w_res).implementation.setslice(space, w_arr)
+            Chunks(chunks).apply(space, w_res).implementation.setslice(space, arr)
     return w_res
 
 def count_nonzero(space, w_obj):
diff --git a/pypy/module/micronumpy/interp_flatiter.py b/pypy/module/micronumpy/interp_flatiter.py
--- a/pypy/module/micronumpy/interp_flatiter.py
+++ b/pypy/module/micronumpy/interp_flatiter.py
@@ -65,7 +65,7 @@
         if length == 1:
             return base_iter.getitem()
         res = W_NDimArray.from_shape(space, [length], base.get_dtype(),
-                                     base.get_order(), subtype=base)
+                                     base.get_order(), w_subtype=base)
         return loop.flatiter_getitem(res, base_iter, step)
 
     def descr_setitem(self, space, w_idx, w_value):
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
@@ -147,11 +147,11 @@
             chunks = self.implementation._prepare_slice_args(space, w_index)
             return chunks.apply(space, self)
         shape = res_shape + self.get_shape()[len(indexes):]
-        res = W_NDimArray.from_shape(space, shape, self.get_dtype(),
-                                     self.get_order(), subtype=self)
-        if not res.get_size():
-            return res
-        return loop.getitem_array_int(space, self, res, iter_shape, indexes,
+        w_res = W_NDimArray.from_shape(space, shape, self.get_dtype(),
+                                     self.get_order(), w_subtype=self)
+        if not w_res.get_size():
+            return w_res
+        return loop.getitem_array_int(space, self, w_res, iter_shape, indexes,
                                       prefix)
 
     def setitem_array_int(self, space, w_index, w_value):
@@ -910,6 +910,8 @@
 @unwrap_spec(offset=int, order=str)
 def descr_new_array(space, w_subtype, w_shape, w_dtype=None, w_buffer=None,
                     offset=0, w_strides=None, order='C'):
+    from pypy.module.micronumpy.arrayimpl.concrete import ConcreteArray
+    from pypy.module.micronumpy.support import calc_strides
     if (offset != 0 or not space.is_none(w_strides) or
         not space.is_none(w_buffer)):
         raise OperationError(space.w_NotImplementedError,
@@ -921,11 +923,17 @@
         return W_NDimArray.new_scalar(space, dtype)
     if space.is_w(w_subtype, space.gettypefor(W_NDimArray)):
         return W_NDimArray.from_shape(space, shape, dtype, order)
-    raise OperationError(space.w_TypeError, space.wrap(
-            "__new__ is not meant to be called except with a ndarray"))
+    strides, backstrides = calc_strides(shape, dtype.base, order)
+    impl = ConcreteArray(shape, dtype.base, order, strides,
+                                  backstrides)
+    w_ret = space.allocate_instance(W_NDimArray, w_subtype)
+    W_NDimArray.__init__(w_ret, impl)
+    space.call_function(space.getattr(w_ret,
+                        space.wrap('__array_finalize__')), w_subtype)
+    return w_ret
 
 @unwrap_spec(addr=int)
-def descr__from_shape_and_storage(space, w_cls, w_shape, addr, w_dtype, w_subclass=None):
+def descr__from_shape_and_storage(space, w_cls, w_shape, addr, w_dtype, w_subtype=None):
     """
     Create an array from an existing buffer, given its address as int.
     PyPy-only implementation detail.
@@ -937,9 +945,12 @@
                      space.call_function(space.gettypefor(interp_dtype.W_Dtype),
                              w_dtype))
     shape = _find_shape(space, w_shape, dtype)
-    if w_subclass:
+    if w_subtype:
+        if not space.isinstance_w(w_subtype, space.w_type):
+            raise OperationError(space.w_ValueError, space.wrap(
+                "subtype must be a subtype of ndarray, not a class instance"))
         return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype,
-                             'C', False, w_subclass)
+                             'C', False, w_subtype)
     else:
         return W_NDimArray.from_shape_and_storage(space, shape, storage, dtype)
 
@@ -1122,12 +1133,12 @@
         dtype = interp_dtype.variable_dtype(space, dtype.char + '1')
     if ndmin > len(shape):
         shape = [1] * (ndmin - len(shape)) + shape
-    arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
-    arr_iter = arr.create_iter()
+    w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
+    arr_iter = w_arr.create_iter()
     for w_elem in elems_w:
         arr_iter.setitem(dtype.coerce(space, w_elem))
         arr_iter.next()
-    return arr
+    return w_arr
 
 @unwrap_spec(order=str)
 def zeros(space, w_shape, w_dtype=None, order='C'):
@@ -1137,7 +1148,7 @@
     shape = _find_shape(space, w_shape, dtype)
     if not shape:
         return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
-    return space.wrap(W_NDimArray.from_shape(space, shape, dtype=dtype, order=order))
+    return W_NDimArray.from_shape(space, shape, dtype=dtype, order=order)
 
 @unwrap_spec(order=str)
 def ones(space, w_shape, w_dtype=None, order='C'):
@@ -1147,10 +1158,10 @@
     shape = _find_shape(space, w_shape, dtype)
     if not shape:
         return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
-    arr = W_NDimArray.from_shape(space, shape, dtype=dtype, order=order)
+    w_arr = W_NDimArray.from_shape(space, shape, dtype=dtype, order=order)
     one = dtype.box(1)
-    arr.fill(one)
-    return space.wrap(arr)
+    w_arr.fill(one)
+    return w_arr
 
 def _reconstruct(space, w_subtype, w_shape, w_dtype):
     return descr_new_array(space, w_subtype, w_shape, w_dtype)
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
@@ -182,7 +182,7 @@
                 if out:
                     dtype = out.get_dtype()
                 temp = W_NDimArray.from_shape(space, temp_shape, dtype,
-                                                subtype=obj)
+                                                w_subtype=obj)
             elif keepdims:
                 shape = obj_shape[:axis] + [1] + obj_shape[axis + 1:]
             else:
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -21,8 +21,33 @@
 
 def call2(space, shape, func, calc_dtype, res_dtype, w_lhs, w_rhs, out):
     # handle array_priority
+    # w_lhs and w_rhs could be of different ndarray subtypes. Numpy does:
+    # 1. if __array_priorities__ are equal and one is an ndarray and the
+    #        other is a subtype,  flip the order
+    # 2. elif rhs.__array_priority__ is higher, flip the order
+    # Now return the subtype of the first one
+
+    w_ndarray = space.gettypefor(W_NDimArray)
+    lhs_type = space.type(w_lhs)
+    rhs_type = space.type(w_rhs)
+    lhs_for_subtype = w_lhs
+    rhs_for_subtype = w_rhs
+    #it may be something like a FlatIter, which is not an ndarray
+    if not lhs_type.issubtype(w_ndarray):
+        lhs_type = space.type(w_lhs.base)
+        lhs_for_subtype = w_lhs.base
+    if not rhs_type.issubtype(w_ndarray):
+        rhs_type = space.gettypefor(w_rhs.base)
+        rhs_for_subtype = w_rhs.base
+    if space.is_w(lhs_type, w_ndarray) and not space.is_w(rhs_type, w_ndarray):
+        w_lhs, w_rhs = w_rhs, w_lhs
+        lhs_for_subtype = rhs_for_subtype
+
+    # TODO handle __array_priorities__ and maybe flip the order
+
     if out is None:
-        out = W_NDimArray.from_shape(space, shape, res_dtype, w_subtype=w_lhs)
+        out = W_NDimArray.from_shape(space, shape, res_dtype,
+                                     w_subtype=lhs_for_subtype)
     left_iter = w_lhs.create_iter(shape)
     right_iter = w_rhs.create_iter(shape)
     out_iter = out.create_iter(shape)
@@ -438,12 +463,12 @@
 def tostring(space, arr):
     builder = StringBuilder()
     iter = arr.create_iter()
-    res_str = W_NDimArray.from_shape(space, [1], arr.get_dtype(), order='C')
+    w_res_str = W_NDimArray.from_shape(space, [1], arr.get_dtype(), order='C')
     itemsize = arr.get_dtype().itemtype.get_element_size()
     res_str_casted = rffi.cast(rffi.CArrayPtr(lltype.Char),
-                               res_str.implementation.get_storage_as_int(space))
+                               w_res_str.implementation.get_storage_as_int(space))
     while not iter.done():
-        res_str.implementation.setitem(0, iter.getitem())
+        w_res_str.implementation.setitem(0, iter.getitem())
         for i in range(itemsize):
             builder.append(res_str_casted[i])
         iter.next()
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
@@ -1477,7 +1477,6 @@
             def __new__(subtype, shape, dtype):
                 self = ndarray.__new__(subtype, shape, dtype)
                 self.id = 'subtype'
-                print 'called new'
                 return self
         a = C([2, 2], int)
         assert isinstance(a, C)
@@ -1485,11 +1484,8 @@
         assert a.shape == (2, 2)
         assert a.dtype is dtype(int)
         assert a.id == 'subtype'
-        print '1'
         a = a.reshape(1, 4)
-        print '2'
         b = a.reshape(4, 1)
-        print '3'
         assert isinstance(b, C)
         #make sure __new__ was not called
         assert not getattr(b, 'id', None)
diff --git a/pypy/module/micronumpy/test/test_subtype.py b/pypy/module/micronumpy/test/test_subtype.py
--- a/pypy/module/micronumpy/test/test_subtype.py
+++ b/pypy/module/micronumpy/test/test_subtype.py
@@ -11,7 +11,7 @@
                 def __new__(cls, subtype):
                     raise ValueError('should not call __new__')
                 def __array_finalize__(self, obj):
-                    
+
                     self.called_finalize = True
             return NoNew ''')
         cls.w_SubType = cls.space.appexec([], '''():
@@ -48,13 +48,11 @@
         assert obj.info is None
         obj = InfoArray(shape=(3,), info='information')
         assert obj.info == 'information'
-        print 'a'
         v = obj[1:]
         assert isinstance(v, InfoArray)
         assert v.base is obj
         assert v.info == 'information'
         arr = np.arange(10)
-        print '1'
         cast_arr = arr.view(InfoArray)
         assert isinstance(cast_arr, InfoArray)
         assert cast_arr.base is arr
@@ -70,7 +68,13 @@
         assert False
 
     def test_sub_flatiter(self):
-        assert False
+        from numpypy import array
+        a = array(range(9)).reshape(3, 3).view(self.NoNew)
+        c = array(range(9)).reshape(3, 3)
+        assert isinstance(a.flat[:] + a.flat[:], self.NoNew)
+        assert isinstance(a.flat[:] + c.flat[:], self.NoNew)
+        assert isinstance(c.flat[:] + a.flat[:], self.NoNew)
+        assert not isinstance(c.flat[:] + c.flat[:], self.NoNew)
 
     def test_sub_getitem_filter(self):
         assert False


More information about the pypy-commit mailing list