[pypy-commit] pypy numpy-multidim: Work on casting. Seems to fly

fijal noreply at buildbot.pypy.org
Thu Oct 27 16:14:42 CEST 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: numpy-multidim
Changeset: r48505:301f1937556a
Date: 2011-10-27 16:13 +0200
http://bitbucket.org/pypy/pypy/changeset/301f1937556a/

Log:	Work on casting. Seems to fly

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
@@ -211,7 +211,8 @@
     def descr_repr(self, space):
         # Simple implementation so that we can see the array. Needs work.
         concrete = self.get_concrete()
-        res = "array([" + ", ".join(concrete._getnums(False)) + "]"
+        #res = "array([" + ", ".join(concrete._getnums(False)) + "]"
+        res = 'array()'
         dtype = concrete.find_dtype()
         if (dtype is not space.fromcache(interp_dtype.W_Float64Dtype) and
             dtype is not space.fromcache(interp_dtype.W_Int64Dtype)) or not self.find_size():
@@ -240,20 +241,29 @@
             item += index[i]
         return item
 
+    def len_of_shape(self):
+        return len(self.shape)
+
+    def get_root_shape(self):
+        return self.shape
+
     def _single_item_result(self, space, w_idx):
         """ The result of getitem/setitem is a single item if w_idx
         is a list of scalars that match the size of shape
         """
-        if len(self.shape) == 1:
-            if (space.isinstance_w(w_idx, space.w_slice) or
-                space.isinstance_w(w_idx, space.w_int)):
+        shape_len = self.len_of_shape()
+        if shape_len == 1:
+            if space.isinstance_w(w_idx, space.w_int):
                 return True
             return False
+        if (space.isinstance_w(w_idx, space.w_slice) or
+            space.isinstance_w(w_idx, space.w_int)):
+            return False
         lgt = space.len_w(w_idx)
-        if lgt > len(self.shape):
+        if lgt > shape_len:
             raise OperationError(space.w_IndexError,
                                  space.wrap("invalid index"))
-        if lgt < len(self.shape):
+        if lgt < shape_len:
             return False
         for w_item in space.fixedview(w_idx):
             if space.isinstance_w(w_item, space.w_slice):
@@ -266,12 +276,25 @@
         ])
         if (space.isinstance_w(w_idx, space.w_int) or
             space.isinstance_w(w_idx, space.w_slice)):
-            chunks = [space.decode_index4(w_idx, self.shape[0])]
+            start, stop, step, lgt = space.decode_index4(w_idx, self.shape[0])
+            if lgt == 1:
+                shape = self.shape[1:]
+            else:
+                shape = self.shape
+            chunks = [(start, stop, step, lgt)]
         else:
             chunks = []
+            shape = self.shape[:]
             for i, w_item in enumerate(space.fixedview(w_idx)):
-                chunks.append(space.decode_index4(w_item, self.shape[i]))
-        return NDimSlice(self, new_sig, chunks)
+                start, stop, step, lgt = space.decode_index4(w_item,
+                                                             self.shape[i])
+                chunks.append((start, stop, step, lgt))
+                if lgt == 1:
+                    shape[i] = -1
+                else:
+                    shape[i] = lgt
+            shape = [i for i in shape if i != -1]
+        return NDimSlice(self, new_sig, chunks, shape)
 
     def descr_getitem(self, space, w_idx):
         if self._single_item_result(space, w_idx):
@@ -481,10 +504,13 @@
     Class for representing views of arrays, they will reflect changes of parent
     arrays. Example: slices
     """
-    def __init__(self, parent, signature):
-        BaseArray.__init__(self)
+    def __init__(self, parent, signature, shape):
+        BaseArray.__init__(self, shape)
         self.signature = signature
         self.parent = parent
+        self.size = 1
+        for elem in shape:
+            self.size *= elem
         self.invalidates = parent.invalidates
 
     def get_concrete(self):
@@ -506,9 +532,7 @@
         raise NotImplementedError
 
     def descr_len(self, space):
-        xxx
-        # XXX find shape first
-        return space.wrap(self.find_size())
+        return space.wrap(self.shape[0])
 
     def calc_index(self, item):
         raise NotImplementedError
@@ -516,11 +540,13 @@
 class NDimSlice(ViewArray):
     signature = signature.BaseSignature()
 
-    def __init__(self, parent, signature, chunks):
-        ViewArray.__init__(self, parent, signature)
+    def __init__(self, parent, signature, chunks, shape):
+        ViewArray.__init__(self, parent, signature, shape)
         self.chunks = chunks
-        xxxx
-        self.size = slice_length
+        self.shape_reduction = 0
+        for chunk in chunks:
+            if chunk[-1] == 1:
+                self.shape_reduction += 1
 
     def get_root_storage(self):
         return self.parent.get_concrete().get_root_storage()
@@ -532,14 +558,53 @@
         return self.parent.find_dtype()
 
     def setslice(self, space, start, stop, step, slice_length, arr):
+        xxx
         start = self.calc_index(start)
         if stop != -1:
             stop = self.calc_index(stop)
         step = self.step * step
         self._sliceloop(start, stop, step, arr, self.parent)
 
+    def len_of_shape(self):
+        return self.parent.len_of_shape() - self.shape_reduction
+
+    def get_root_shape(self):
+        return self.parent.get_root_shape()
+
+    # XXX we might want to provide a custom finder of where we look for
+    #     a particular item, right now we'll do the calculations again
+
     def calc_index(self, item):
-        return (self.start + item * self.step)
+        index = []
+        _item = item
+        for i in range(len(self.shape) -1, 0, -1):
+            s = self.shape[i]
+            index.append(_item % s)
+            _item //= s
+        index.append(_item)
+        index.reverse()
+        i = 0
+        item = 0
+        k = 0
+        shape = self.parent.shape
+        for chunk in self.chunks:
+            if k != 0:
+                item *= shape[k]
+            k += 1
+            start, stop, step, lgt = chunk
+            if lgt == 1:
+                # we don't consume an index
+                item += start
+            else:
+                item += start + step * index[i]
+                i += 1
+        while k < len(shape):
+            if k != 0:
+                item *= shape[k]
+            k += 1
+            item += index[i]
+            i += 1
+        return item
 
 
 class NDimArray(BaseArray):
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
@@ -630,7 +630,30 @@
         raises(IndexError, a.__getitem__, (4,))
         raises(IndexError, a.__getitem__, (3, 3))
         raises(IndexError, a.__getitem__, (slice(None), 3))
-        
+        a[0,1,1] = 13
+        a[1,2,1] = 15
+        b = a[0]
+        assert len(b) == 3
+        assert b.shape == (3, 2)
+        assert b[1,1] == 13
+        b = a[1]
+        assert b.shape == (3, 2)
+        assert b[2,1] == 15
+        b = a[:,1]
+        assert b.shape == (4, 2)
+        assert b[0,1] == 13
+        b = a[:,1,:]
+        assert b.shape == (4, 2)
+        assert b[0,1] == 13
+        b = a[1, 2]
+        assert b[1] == 15
+        b = a[:]
+        assert b.shape == (4, 3, 2)
+        assert b[1,2,1] == 15
+        assert b[0,1,1] == 13
+        b = a[:][:,1][:]
+        assert b[2,1] == 0.0
+        assert b[0,1] == 13
 
 class AppTestSupport(object):
     def setup_class(cls):


More information about the pypy-commit mailing list