Author: Maciej Fijalkowski <[email protected]>
Branch: missing-ndarray-attributes
Changeset: r58528:dd59b7d76e43
Date: 2012-10-28 00:45 +0200
http://bitbucket.org/pypy/pypy/changeset/dd59b7d76e43/

Log:    A very ugly commit :( Implement base. Unfortunately it means slice
        has to carry the original array a bit everywhere

diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py 
b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -44,7 +44,7 @@
     def get_size(self):
         return self.size // self.dtype.itemtype.get_element_size()
 
-    def reshape(self, space, new_shape):
+    def reshape(self, space, orig_array, new_shape):
         # Since we got to here, prod(new_shape) == self.size
         new_strides = None
         if self.size > 0:
@@ -57,7 +57,7 @@
             for nd in range(ndims):
                 new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
             return SliceArray(self.start, new_strides, new_backstrides,
-                              new_shape, self)
+                              new_shape, self, orig_array)
         else:
             return None
 
@@ -168,26 +168,26 @@
                 i += 1
         return Chunks(result)
 
-    def descr_getitem(self, space, w_index):
+    def descr_getitem(self, space, orig_arr, w_index):
         try:
             item = self._single_item_index(space, w_index)
             return self.getitem(item)
         except IndexError:
             # not a single result
             chunks = self._prepare_slice_args(space, w_index)
-            return chunks.apply(self)
+            return chunks.apply(orig_arr)
 
-    def descr_setitem(self, space, w_index, w_value):
+    def descr_setitem(self, space, orig_arr, w_index, w_value):
         try:
             item = self._single_item_index(space, w_index)
             self.setitem(item, self.dtype.coerce(space, w_value))
         except IndexError:
             w_value = convert_to_array(space, w_value)
             chunks = self._prepare_slice_args(space, w_index)
-            view = chunks.apply(self)
+            view = chunks.apply(orig_arr)
             view.implementation.setslice(space, w_value)
 
-    def transpose(self):
+    def transpose(self, orig_array):
         if len(self.shape) < 2:
             return self
         strides = []
@@ -198,7 +198,7 @@
             backstrides.append(self.backstrides[i])
             shape.append(self.shape[i])
         return SliceArray(self.start, strides,
-                          backstrides, shape, self)
+                          backstrides, shape, self, orig_array)
 
     def copy(self):
         strides, backstrides = support.calc_strides(self.shape, self.dtype,
@@ -215,7 +215,7 @@
                                   shape, skip)
         return iter.MultiDimViewIterator(self, self.start, r[0], r[1], shape)
 
-    def swapaxes(self, axis1, axis2):
+    def swapaxes(self, orig_arr, axis1, axis2):
         shape = self.shape[:]
         strides = self.strides[:]
         backstrides = self.backstrides[:]
@@ -223,7 +223,7 @@
         strides[axis1], strides[axis2] = strides[axis2], strides[axis1]
         backstrides[axis1], backstrides[axis2] = backstrides[axis2], 
backstrides[axis1] 
         return W_NDimArray.new_slice(self.start, strides, 
-                                     backstrides, shape, self)
+                                     backstrides, shape, self, orig_arr)
 
     def get_storage_as_int(self, space):
         return rffi.cast(lltype.Signed, self.storage)
@@ -254,10 +254,11 @@
     def __del__(self):
         free_raw_storage(self.storage, track_allocation=False)
 
-    def set_shape(self, space, new_shape):
+    def set_shape(self, space, orig_array, new_shape):
         strides, backstrides = support.calc_strides(new_shape, self.dtype,
                                                     self.order)
-        return SliceArray(0, strides, backstrides, new_shape, self)
+        return SliceArray(0, strides, backstrides, new_shape, self,
+                          orig_array)
 
     def argsort(self, space, w_axis):
         return argsort_array(self, space, w_axis)
@@ -267,8 +268,12 @@
         loop.copy_from_to(self, new_arr.implementation, dtype)
         return new_arr
 
+    def base(self):
+        return None
+
 class SliceArray(BaseConcreteArray):
-    def __init__(self, start, strides, backstrides, shape, parent, dtype=None):
+    def __init__(self, start, strides, backstrides, shape, parent, orig_arr,
+                 dtype=None):
         self.strides = strides
         self.backstrides = backstrides
         self.shape = shape
@@ -282,6 +287,10 @@
         self.dtype = dtype
         self.size = support.product(shape) * 
self.dtype.itemtype.get_element_size()
         self.start = start
+        self.orig_arr = orig_arr
+
+    def base(self):
+        return self.orig_arr
 
     def fill(self, box):
         loop.fill(self, box.convert_to(self.dtype))
@@ -297,7 +306,7 @@
         return iter.MultiDimViewIterator(self.parent, self.start, self.strides,
                                          self.backstrides, self.shape)
 
-    def set_shape(self, space, new_shape):
+    def set_shape(self, space, orig_array, new_shape):
         if len(self.shape) < 2 or self.size == 0:
             # TODO: this code could be refactored into calc_strides
             # but then calc_strides would have to accept a stepping factor
@@ -316,7 +325,7 @@
                 backstrides.reverse()
                 new_shape.reverse()
             return SliceArray(self.start, strides, backstrides, new_shape,
-                              self)
+                              self, orig_array)
         new_strides = calc_new_strides(new_shape, self.shape, self.strides,
                                        self.order)
         if new_strides is None:
@@ -326,4 +335,4 @@
         for nd in range(len(new_shape)):
             new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
         return SliceArray(self.start, new_strides, new_backstrides, new_shape,
-                          self)
+                          self, orig_array)
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py 
b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -51,10 +51,10 @@
     def get_size(self):
         return 1
 
-    def transpose(self):
+    def transpose(self, _):
         return self
 
-    def descr_getitem(self, space, w_idx):
+    def descr_getitem(self, space, _, w_idx):
         raise OperationError(space.w_IndexError,
                              space.wrap("scalars cannot be indexed"))
 
@@ -62,14 +62,14 @@
         raise OperationError(space.w_IndexError,
                              space.wrap("scalars cannot be indexed"))
 
-    def descr_setitem(self, space, w_idx, w_val):
+    def descr_setitem(self, space, _, w_idx, w_val):
         raise OperationError(space.w_IndexError,
                              space.wrap("scalars cannot be indexed"))
         
     def setitem_index(self, space, idx, w_val):
         raise OperationError(space.w_IndexError,
                              space.wrap("scalars cannot be indexed"))
-    def set_shape(self, space, new_shape):
+    def set_shape(self, space, orig_array, new_shape):
         if not new_shape:
             return self
         if support.product(new_shape) == 1:
@@ -80,8 +80,8 @@
         raise OperationError(space.w_ValueError, space.wrap(
             "total size of the array must be unchanged"))
 
-    def reshape(self, space, new_shape):
-        return self.set_shape(space, new_shape)
+    def reshape(self, space, orig_array, new_shape):
+        return self.set_shape(space, orig_array, new_shape)
         
     def create_axis_iter(self, shape, dim):
         raise Exception("axis iter should not happen on scalar")
@@ -101,3 +101,6 @@
 
     def astype(self, space, dtype):
         return W_NDimArray.new_scalar(space, dtype, self.value)
+
+    def base(self):
+        return None
diff --git a/pypy/module/micronumpy/arrayimpl/sort.py 
b/pypy/module/micronumpy/arrayimpl/sort.py
--- a/pypy/module/micronumpy/arrayimpl/sort.py
+++ b/pypy/module/micronumpy/arrayimpl/sort.py
@@ -73,7 +73,9 @@
         raise OperationError(space.w_NotImplementedError,
            space.wrap("sorting of non-numeric types is not implemented"))
     if w_axis is space.w_None:
-        arr = arr.reshape(space, [arr.get_size()])
+        # note that it's fine ot pass None here as we're not going
+        # to pass the result around (None is the link to base in slices)
+        arr = arr.reshape(space, None, [arr.get_size()])
         axis = 0
     elif w_axis is None:
         axis = -1
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
@@ -23,11 +23,12 @@
         return W_NDimArray(impl)
 
     @staticmethod
-    def new_slice(offset, strides, backstrides, shape, parent, dtype=None):
+    def new_slice(offset, strides, backstrides, shape, parent, orig_arr,
+                  dtype=None):
         from pypy.module.micronumpy.arrayimpl import concrete
 
         impl = concrete.SliceArray(offset, strides, backstrides, shape, parent,
-                                   dtype)
+                                   orig_arr, dtype)
         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
@@ -123,7 +123,7 @@
     for arr in args_w:
         chunks[axis] = Chunk(axis_start, axis_start + arr.get_shape()[axis], 1,
                              arr.get_shape()[axis])
-        
Chunks(chunks).apply(res.implementation).implementation.setslice(space, arr)
+        Chunks(chunks).apply(res).implementation.setslice(space, arr)
         axis_start += arr.get_shape()[axis]
     return res
 
@@ -137,7 +137,7 @@
         res = W_NDimArray.from_shape(shape, arr.get_dtype())
         for i in range(repeats):
             Chunks([Chunk(i, shape[0] - repeats + i, repeats,
-                          
orig_size)]).apply(res.implementation).implementation.setslice(space, arr)
+                          
orig_size)]).apply(res).implementation.setslice(space, arr)
     else:
         axis = space.int_w(w_axis)
         shape = arr.get_shape()[:]
@@ -148,7 +148,7 @@
         for i in range(repeats):
             chunks[axis] = Chunk(i, shape[axis] - repeats + i, repeats,
                                  orig_size)
-            
Chunks(chunks).apply(res.implementation).implementation.setslice(space, arr)
+            Chunks(chunks).apply(res).implementation.setslice(space, arr)
     return res
 
 def count_nonzero(space, w_obj):
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
@@ -232,8 +232,6 @@
                 return dtype
             if w_dtype is dtype.w_box_type:
                 return dtype
-    import pdb
-    pdb.set_trace()
     raise OperationError(space.w_TypeError, space.wrap("data type not 
understood"))
 
 W_Dtype.typedef = TypeDef("dtype",
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
@@ -37,7 +37,7 @@
         return self.implementation.get_shape()
 
     def descr_set_shape(self, space, w_new_shape):
-        self.implementation = self.implementation.set_shape(space,
+        self.implementation = self.implementation.set_shape(space, self,
             get_shape_from_iterable(space, self.get_size(), w_new_shape))
 
     def get_dtype(self):
@@ -148,7 +148,7 @@
             w_idx.get_dtype().is_bool_type()):
             return self.getitem_filter(space, w_idx)
         try:
-            return self.implementation.descr_getitem(space, w_idx)
+            return self.implementation.descr_getitem(space, self, w_idx)
         except ArrayArgumentException:
             return self.getitem_array_int(space, w_idx)
         except OperationError:
@@ -166,7 +166,7 @@
             return self.setitem_filter(space, w_idx,
                                        convert_to_array(space, w_value))
         try:
-            self.implementation.descr_setitem(space, w_idx, w_value)
+            self.implementation.descr_setitem(space, self, w_idx, w_value)
         except ArrayArgumentException:
             self.setitem_array_int(space, w_idx, w_value)
 
@@ -254,20 +254,21 @@
         else:
             w_shape = space.newtuple(args_w)
         new_shape = get_shape_from_iterable(space, self.get_size(), w_shape)
-        new_impl = self.implementation.reshape(space, new_shape)
+        new_impl = self.implementation.reshape(space, self, new_shape)
         if new_impl is not None:
             return W_NDimArray(new_impl)
         # Create copy with contiguous data
         arr = self.descr_copy(space)
         if arr.get_size() > 0:
-            arr.implementation = arr.implementation.reshape(space, new_shape)
+            arr.implementation = arr.implementation.reshape(space, self,
+                                                            new_shape)
             assert arr.implementation
         else:
             arr.implementation.shape = new_shape
         return arr
 
     def descr_get_transpose(self, space):
-        return W_NDimArray(self.implementation.transpose())
+        return W_NDimArray(self.implementation.transpose(self))
 
     @unwrap_spec(axis1=int, axis2=int)
     def descr_swapaxes(self, space, axis1, axis2):
@@ -283,7 +284,7 @@
         """
         if self.is_scalar():
             return self
-        return self.implementation.swapaxes(axis1, axis2)
+        return self.implementation.swapaxes(self, axis1, axis2)
 
     def descr_tolist(self, space):
         if len(self.get_shape()) == 0:
@@ -389,9 +390,8 @@
           space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
         return self.implementation.astype(space, dtype)
 
-    def descr_base(self, space):
-        raise OperationError(space.w_NotImplementedError, space.wrap(
-            "base not implemented yet"))
+    def descr_get_base(self, space):
+        return self.implementation.base()
 
     def descr_byteswap(self, space, w_inplace=False):
         raise OperationError(space.w_NotImplementedError, space.wrap(
@@ -790,6 +790,7 @@
 
     argsort = interp2app(W_NDimArray.descr_argsort),
     astype = interp2app(W_NDimArray.descr_astype),
+    base = GetSetProperty(W_NDimArray.descr_get_base),
 
     __array_interface__ = GetSetProperty(W_NDimArray.descr_array_iface),
 )
diff --git a/pypy/module/micronumpy/iter.py b/pypy/module/micronumpy/iter.py
--- a/pypy/module/micronumpy/iter.py
+++ b/pypy/module/micronumpy/iter.py
@@ -57,12 +57,13 @@
     def __init__(self, name):
         self.name = name
 
-    def apply(self, arr):
+    def apply(self, orig_arr):
+        arr = orig_arr.implementation
         ofs, subdtype = arr.dtype.fields[self.name]
         # strides backstrides are identical, ofs only changes start
         return W_NDimArray.new_slice(arr.start + ofs, arr.strides,
                                      arr.backstrides,
-                                     arr.shape, arr, subdtype)
+                                     arr.shape, arr, orig_arr, subdtype)
 
 class Chunks(BaseChunk):
     def __init__(self, l):
@@ -79,13 +80,14 @@
         assert s >= 0
         return shape[:] + old_shape[s:]
 
-    def apply(self, arr):
+    def apply(self, orig_arr):
+        arr = orig_arr.implementation
         shape = self.extend_shape(arr.shape)
         r = calculate_slice_strides(arr.shape, arr.start, arr.strides,
                                     arr.backstrides, self.l)
         _, start, strides, backstrides = r
         return W_NDimArray.new_slice(start, strides[:], backstrides[:],
-                                     shape[:], arr)
+                                     shape[:], arr, orig_arr)
 
 
 class Chunk(BaseChunk):
diff --git a/pypy/module/micronumpy/test/test_iter.py 
b/pypy/module/micronumpy/test/test_iter.py
--- a/pypy/module/micronumpy/test/test_iter.py
+++ b/pypy/module/micronumpy/test/test_iter.py
@@ -1,4 +1,4 @@
-from pypy.module.micronumpy.arrayimpl.concrete import MultiDimViewIterator
+from pypy.module.micronumpy.iter import MultiDimViewIterator
 
 class MockArray(object):
     size = 1
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
@@ -22,7 +22,7 @@
 
 
 def create_slice(a, chunks):
-    return Chunks(chunks).apply(a).implementation
+    return Chunks(chunks).apply(W_NDimArray(a)).implementation
 
 def create_array(*args, **kwargs):
     return W_NDimArray.from_shape(*args, **kwargs).implementation
@@ -1576,6 +1576,14 @@
         assert (b == [1, 2]).all()
         assert b.dtype == 'float'
 
+    def test_base(self):
+        from _numpypy import array
+        assert array(1).base is None
+        assert array([1, 2]).base is None
+        a = array([1, 2, 3, 4])
+        b = a[::2]
+        assert b.base is a
+
 class AppTestMultiDim(BaseNumpyAppTest):
     def test_init(self):
         import _numpypy
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to