[pypy-commit] pypy numpy-refactor: axis reduce, not working yet

fijal noreply at buildbot.pypy.org
Wed Sep 5 12:53:23 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: numpy-refactor
Changeset: r57143:e6845da36040
Date: 2012-09-05 12:52 +0200
http://bitbucket.org/pypy/pypy/changeset/e6845da36040/

Log:	axis reduce, not working yet

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
@@ -74,6 +74,47 @@
     def done(self):
         return self._done
 
+class AxisIterator(base.BaseArrayIterator):
+    def __init__(self, array, shape, dim):
+        self.shape = shape
+        strides = array.strides
+        backstrides = array.backstrides
+        if len(shape) == len(strides):
+            # keepdims = True
+            self.strides = strides[:dim] + [0] + strides[dim + 1:]
+            self.backstrides = backstrides[:dim] + [0] + backstrides[dim + 1:]
+        else:
+            self.strides = strides[:dim] + [0] + strides[dim:]
+            self.backstrides = backstrides[:dim] + [0] + backstrides[dim:]
+        self.first_line = True
+        self.indices = [0] * len(shape)
+        self._done = False
+        self.offset = array.start
+        self.dim = dim
+        self.array = array
+        
+    def setitem(self, elem):
+        self.array.setitem(self.offset, elem)
+
+    def getitem(self):
+        return self.array.getitem(self.offset)
+
+    @jit.unroll_safe
+    def next(self):
+        for i in range(len(self.shape) - 1, -1, -1):
+            if self.indices[i] < self.shape[i] - 1:
+                if i == self.dim:
+                    self.first_line = False
+                self.indices[i] += 1
+                self.offset += self.strides[i]
+                break
+            else:
+                if i == self.dim:
+                    self.first_line = True
+                self.indices[i] = 0
+                self.offset -= self.backstrides[i]
+        else:
+            self._done = True
 
 def int_w(space, w_obj):
     # a special version that respects both __index__ and __int__
@@ -238,6 +279,9 @@
                              backstrides)
         return loop.setslice(self.shape, impl, self)
 
+    def create_axis_iter(self, shape, dim):
+        return AxisIterator(self, shape, dim)
+
 class ConcreteArray(BaseConcreteArray):
     def __init__(self, shape, dtype, order, strides, backstrides):
         self.shape = shape
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
@@ -70,3 +70,5 @@
     def reshape(self, space, new_shape):
         return self.set_shape(space, new_shape)
         
+    def create_axis_iter(self, shape, dim):
+        raise Exception("axis iter should not happen on scalar")
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
@@ -90,6 +90,9 @@
     def create_iter(self, shape):
         return self.implementation.create_iter(shape)
 
+    def create_axis_iter(self, shape, dim):
+        return self.implementation.create_axis_iter(shape, dim)
+
     def is_scalar(self):
         return self.implementation.is_scalar()
 
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
@@ -171,7 +171,9 @@
             else:
                 shape = obj_shape[:axis] + obj_shape[axis + 1:]
             if out:
-                #Test for shape agreement
+                # Test for shape agreement
+                # XXX maybe we need to do broadcasting here, although I must
+                #     say I don't understand the details for axis reduce
                 if len(out.get_shape()) > len(shape):
                     raise operationerrfmt(space.w_ValueError,
                         'output parameter for reduction operation %s' +
@@ -187,14 +189,11 @@
                         ",".join([str(x) for x in shape]),
                         ",".join([str(x) for x in out.get_shape()]),
                         )
-                #Test for dtype agreement, perhaps create an itermediate
-                #if out.dtype != dtype:
-                #    raise OperationError(space.w_TypeError, space.wrap(
-                #        "mismatched  dtypes"))
-                return self.do_axis_reduce(obj, out.find_dtype(), axis, out)
+                dtype = out.get_dtype()
             else:
-                result = W_NDimArray.from_shape(shape, dtype)
-                return self.do_axis_reduce(obj, dtype, axis, result)
+                out = W_NDimArray.from_shape(shape, dtype)
+            return loop.do_axis_reduce(shape, self.func, obj, dtype, axis, out,
+                                       self.identity)
         if out:
             if len(out.get_shape())>0:
                 raise operationerrfmt(space.w_ValueError, "output parameter "
@@ -208,14 +207,6 @@
             return out
         return res
 
-    def do_axis_reduce(self, obj, dtype, axis, result):
-        xxx
-        from pypy.module.micronumpy.interp_numarray import AxisReduce
-        arr = AxisReduce(self.func, self.name, self.identity, obj.shape, dtype,
-                         result, obj, axis)
-        loop.compute(arr)
-        return arr.left
-
 class W_Ufunc1(W_Ufunc):
     argcount = 1
 
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,7 +21,7 @@
         out_iter.next()
     return out
 
-def call1(shape, func, name , calc_dtype, res_dtype, w_obj, out):
+def call1(shape, func, name, calc_dtype, res_dtype, w_obj, out):
     if out is None:
         out = W_NDimArray.from_shape(shape, res_dtype)
     obj_iter = w_obj.create_iter(shape)
@@ -82,3 +82,23 @@
         x_iter.next()
         y_iter.next()
     return out
+
+def do_axis_reduce(shape, func, arr, dtype, axis, out, identity):
+    import pdb
+    pdb.set_trace()
+    out_iter = out.create_iter(shape)
+    arr_iter = arr.create_axis_iter(shape, axis)
+    if identity is not None:
+        identity = identity.convert_to(dtype)
+    while not out_iter.done():
+        w_val = arr_iter.getitem().convert_to(dtype)
+        if arr_iter.first_line:
+            if identity is not None:
+                w_val = func(dtype, identity, w_val)
+        else:
+            cur = out_iter.getitem()
+            w_val = func(dtype, cur, w_val)
+        out_iter.setitem(w_val)
+        arr_iter.next()
+        out_iter.next()
+    return out
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
@@ -2,7 +2,6 @@
 import py, sys
 
 from pypy.conftest import option
-from pypy.interpreter.error import OperationError
 from pypy.module.micronumpy.appbridge import get_appbridge_cache
 from pypy.module.micronumpy.iter import Chunk, Chunks
 from pypy.module.micronumpy.interp_numarray import W_NDimArray
@@ -1083,7 +1082,7 @@
         assert a[:4].mean() == 1.5
         a = array(range(105)).reshape(3, 5, 7)
         b = a.mean(axis=0)
-        b[0, 0]==35.
+        assert b[0, 0] == 35.
         assert a.mean(axis=0)[0, 0] == 35
         assert (b == array(range(35, 70), dtype=float).reshape(5, 7)).all()
         assert (a.mean(2) == array(range(0, 15), dtype=float).reshape(3, 5) * 7 + 3).all()


More information about the pypy-commit mailing list