[pypy-commit] pypy default: Added sum, prod, max, mul, all, any, and dot to micronumpy

justinpeel noreply at buildbot.pypy.org
Tue Jul 12 00:47:06 CEST 2011


Author: Justin Peel <notmuchtotell at gmail.com>
Branch: 
Changeset: r45480:f3254e205395
Date: 2011-07-10 16:31 -0600
http://bitbucket.org/pypy/pypy/changeset/f3254e205395/

Log:	Added sum, prod, max, mul, all, any, and dot to micronumpy

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
@@ -1,5 +1,5 @@
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
-from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.error import operationerrfmt, OperationError
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.rlib import jit
@@ -49,6 +49,14 @@
     return math.pow(v1, v2)
 def mod(v1, v2):
     return math.fmod(v1, v2)
+def maximum(v1, v2):
+    return max(v1, v2)
+def minimum(v1, v2):
+    return min(v1, v2)
+def and_bool(v1, v2):
+    return v1 and bool(v2)
+def or_bool(v1, v2):
+    return v1 or bool(v2)
 
 class BaseArray(Wrappable):
     def __init__(self):
@@ -110,6 +118,90 @@
     descr_pow = _binop_impl(pow)
     descr_mod = _binop_impl(mod)
 
+    def _reduce_sum_prod_impl(function, init):
+        reduce_driver = jit.JitDriver(greens=['signature'],
+                         reds = ['i', 'size', 'self', 'result'])
+
+        def loop(self, result, size):
+            i = 0
+            while i < size:
+                reduce_driver.jit_merge_point(signature=self.signature,
+                                              self=self, size=size, i=i,
+                                              result=result)
+                result = function(result, self.eval(i))
+                i += 1
+            return result
+
+        def impl(self, space):
+            return space.wrap(loop(self, init, self.find_size()))
+        return func_with_new_name(impl, "reduce_%s_impl" % function.__name__)
+
+    def _reduce_max_min_impl(function):
+        reduce_driver = jit.JitDriver(greens=['signature'],
+                         reds = ['i', 'size', 'self', 'result'])    
+        def loop(self, result, size):
+            i = 1
+            while i < size:
+                reduce_driver.jit_merge_point(signature=self.signature,
+                                              self=self, size=size, i=i,
+                                              result=result)
+                result = function(result, self.eval(i))
+                i += 1
+            return result
+        
+        def impl(self, space):
+            size = self.find_size()
+            if size == 0:
+                raise OperationError(space.w_ValueError,
+                    space.wrap("Can't call %s on zero-size arrays" \
+                            % function.__name__))
+            return space.wrap(loop(self, self.eval(0), size))
+        return func_with_new_name(impl, "reduce_%s_impl" % function.__name__)
+
+    def _reduce_any_all_impl(function, init, cond):
+        reduce_driver = jit.JitDriver(greens=['signature'],
+                         reds = ['i', 'size', 'result', 'self'])
+        def loop(self, result, size):
+            i = 0
+            if cond:
+                while i < size:
+                    reduce_driver.jit_merge_point(signature=self.signature,
+                                                  self=self, size=size, i=i,
+                                                  result=result)
+                    result = function(result, self.eval(i))
+                    if result:
+                        break
+                    i += 1
+            else:
+                while i < size:
+                    reduce_driver.jit_merge_point(signature=self.signature,
+                                                  self=self, size=size, i=i,
+                                                  result=result)
+                    result = function(result, self.eval(i))
+                    if not result:
+                        break
+                    i += 1
+            return result
+
+        def impl(self, space):
+            size = self.find_size()
+            return space.wrap(loop(self, init, size))
+        return func_with_new_name(impl, "reduce_%s_impl" % function.__name__)
+
+    descr_sum = _reduce_sum_prod_impl(add, 0.0)
+    descr_prod = _reduce_sum_prod_impl(mul, 1.0)
+    descr_max = _reduce_max_min_impl(maximum)
+    descr_min = _reduce_max_min_impl(minimum)
+    descr_all = _reduce_any_all_impl(and_bool, True, False)
+    descr_any = _reduce_any_all_impl(or_bool, False, True)
+
+    def descr_dot(self, space, w_other):
+        if isinstance(w_other, BaseArray):
+            return self.descr_mul(space, w_other).descr_sum(space)
+        else:
+            w_other = FloatWrapper(space.float_w(w_other))
+            return self.descr_mul(space, w_other)
+
     def get_concrete(self):
         raise NotImplementedError
 
@@ -391,4 +483,11 @@
     __mod__ = interp2app(BaseArray.descr_mod),
 
     mean = interp2app(BaseArray.descr_mean),
+    sum = interp2app(BaseArray.descr_sum),
+    prod = interp2app(BaseArray.descr_prod),
+    max = interp2app(BaseArray.descr_max),
+    min = interp2app(BaseArray.descr_min),
+    all = interp2app(BaseArray.descr_all),
+    any = interp2app(BaseArray.descr_any),
+    dot = interp2app(BaseArray.descr_dot),
 )
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
@@ -282,12 +282,74 @@
         assert a.mean() == 2.0
         assert a[:4].mean() == 1.5
 
+    def test_sum(self):
+        from numpy import array
+        a = array(range(5))
+        assert a.sum() == 10.0
+        assert a[:4].sum() == 6.0
+
+    def test_prod(self):
+        from numpy import array
+        a = array(range(1,6))
+        assert a.prod() == 120.0
+        assert a[:4].prod() == 24.0
+
+    def test_max(self):
+        from numpy import array
+        a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
+        assert a.max() == 5.7
+        b = array([])
+        raises(ValueError, "b.max()")
+
+    def test_max_add(self):
+        from numpy import array
+        a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
+        assert (a+a).max() == 11.4
+
+    def test_min(self):
+        from numpy import array
+        a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
+        assert a.min() == -3.0
+        b = array([])
+        raises(ValueError, "b.min()")
+
+    def test_all(self):
+        from numpy import array
+        a = array(range(5))
+        assert a.all() == False
+        a[0] = 3.0
+        assert a.all() == True
+        b = array([])
+        assert b.all() == True
+
+    def test_any(self):
+        from numpy import array, zeros
+        a = array(range(5))
+        assert a.any() == True
+        b = zeros(5)
+        assert b.any() == False
+        c = array([])
+        assert c.any() == False
+
+    def test_dot(self):
+        from numpy import array
+        a = array(range(5))
+        assert a.dot(a) == 30.0
+
+    def test_dot_constant(self):
+        from numpy import array
+        a = array(range(5))
+        b = a.dot(2.5)
+        for i in xrange(5):
+            assert b[i] == 2.5*a[i]
+
+
 class AppTestSupport(object):
     def setup_class(cls):
         import struct
         cls.space = gettestobjspace(usemodules=('micronumpy',))
         cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4))
-    
+
     def test_fromstring(self):
         from numpy import fromstring
         a = fromstring(self.data)
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
@@ -4,9 +4,13 @@
     FloatWrapper, Call2, SingleDimSlice, add, mul, neg, Call1)
 from pypy.module.micronumpy.interp_ufuncs import negative
 from pypy.module.micronumpy.compile import numpy_compile
+from pypy.rlib.objectmodel import specialize
 
 class FakeSpace(object):
-    pass
+    w_ValueError = None
+    @specialize.argtype(1)
+    def wrap(self, v):
+        return v
 
 class TestNumpyJIt(LLJitMixin):
     def setup_class(cls):
@@ -51,6 +55,93 @@
 
         assert result == f(5)
 
+    def test_sum(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            return ar.descr_add(space, ar).descr_sum(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 2,
+                          "int_add": 1,
+                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        assert result == f(5)
+
+    def test_prod(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            return ar.descr_add(space, ar).descr_prod(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                          "float_mul": 1, "int_add": 1,
+                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        assert result == f(5)
+
+    def test_max(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            j = 0
+            while j < i:
+                ar.get_concrete().storage[j] = float(j)
+                j += 1
+            return ar.descr_add(space, ar).descr_max(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                          "float_gt": 1, "int_add": 1,
+                          "int_lt": 1, "guard_true": 1, 
+                          "guard_false": 1, "jump": 1})
+
+    def test_min(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            j = 0
+            while j < i:
+                ar.get_concrete().storage[j] = float(j)
+                j += 1
+            return ar.descr_add(space, ar).descr_min(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                           "float_lt": 1, "int_add": 1,
+                           "int_lt": 1, "guard_true": 2,
+                           "jump": 1})
+
+    def test_all(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            j = 0
+            while j < i:
+                ar.get_concrete().storage[j] = 1.0
+                j += 1
+            return ar.descr_add(space, ar).descr_all(space)
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                          "int_add": 1, "float_ne": 1,
+                          "int_lt": 1, "guard_true": 2, "jump": 1})
+
+    def test_any(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            return ar.descr_add(space, ar).descr_any(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                          "int_add": 1, "float_ne": 1, "guard_false": 1,
+                          "int_lt": 1, "guard_true": 1, "jump": 1})
+
     def test_already_forecd(self):
         def f(i):
             ar = SingleDimArray(i)


More information about the pypy-commit mailing list