[pypy-commit] pypy default: optimize and test ndarray flatiter get/set

bdkearns noreply at buildbot.pypy.org
Thu Oct 9 05:59:47 CEST 2014


Author: Brian Kearns <bdkearns at gmail.com>
Branch: 
Changeset: r73849:7842e64c5847
Date: 2014-10-08 13:23 -0400
http://bitbucket.org/pypy/pypy/changeset/7842e64c5847/

Log:	optimize and test ndarray flatiter get/set

diff --git a/pypy/module/micronumpy/flatiter.py b/pypy/module/micronumpy/flatiter.py
--- a/pypy/module/micronumpy/flatiter.py
+++ b/pypy/module/micronumpy/flatiter.py
@@ -27,12 +27,9 @@
 class W_FlatIterator(W_NDimArray):
     def __init__(self, arr):
         self.base = arr
+        self.iter, self.state = arr.create_iter()
         # this is needed to support W_NDimArray interface
         self.implementation = FakeArrayImplementation(self.base)
-        self.reset()
-
-    def reset(self):
-        self.iter, self.state = self.base.create_iter()
 
     def descr_len(self, space):
         return space.wrap(self.iter.size)
@@ -54,25 +51,39 @@
         if not (space.isinstance_w(w_idx, space.w_int) or
                 space.isinstance_w(w_idx, space.w_slice)):
             raise oefmt(space.w_IndexError, 'unsupported iterator index')
-        self.reset()
-        base = self.base
-        start, stop, step, length = space.decode_index4(w_idx, base.get_size())
-        base_iter, base_state = base.create_iter()
-        base_state = base_iter.next_skip_x(base_state, start)
-        if length == 1:
-            return base_iter.getitem(base_state)
-        res = W_NDimArray.from_shape(space, [length], base.get_dtype(),
-                                     base.get_order(), w_instance=base)
-        return loop.flatiter_getitem(res, base_iter, base_state, step)
+        self.state = self.iter.reset(self.state)
+        start, stop, step, length = space.decode_index4(w_idx, self.iter.size)
+        self.state = self.iter.next_skip_x(self.state, start)
+        try:
+            if length == 1:
+                return self.iter.getitem(self.state)
+            base = self.base
+            res = W_NDimArray.from_shape(space, [length], base.get_dtype(),
+                                         base.get_order(), w_instance=base)
+            return loop.flatiter_getitem(res, self.iter, self.state, step)
+        finally:
+            self.state = self.iter.reset(self.state)
 
     def descr_setitem(self, space, w_idx, w_value):
         if not (space.isinstance_w(w_idx, space.w_int) or
                 space.isinstance_w(w_idx, space.w_slice)):
             raise oefmt(space.w_IndexError, 'unsupported iterator index')
-        base = self.base
-        start, stop, step, length = space.decode_index4(w_idx, base.get_size())
-        arr = convert_to_array(space, w_value)
-        loop.flatiter_setitem(space, self.base, arr, start, step, length)
+        start, stop, step, length = space.decode_index4(w_idx, self.iter.size)
+        self.state = self.iter.reset(self.state)
+        self.state = self.iter.next_skip_x(self.state, start)
+        try:
+            dtype = self.base.get_dtype()
+            if length == 1:
+                try:
+                    val = dtype.coerce(space, w_value)
+                except OperationError:
+                    raise oefmt(space.w_ValueError, "Error setting single item of array.")
+                self.iter.setitem(self.state, val)
+                return
+            arr = convert_to_array(space, w_value)
+            loop.flatiter_setitem(space, dtype, arr, self.iter, self.state, step, length)
+        finally:
+            self.state = self.iter.reset(self.state)
 
     def descr_iter(self):
         return self
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
@@ -443,11 +443,8 @@
                                         greens = ['dtype'],
                                         reds = 'auto')
 
-def flatiter_setitem(space, arr, val, start, step, length):
-    dtype = arr.get_dtype()
-    arr_iter, arr_state = arr.create_iter()
+def flatiter_setitem(space, dtype, val, arr_iter, arr_state, step, length):
     val_iter, val_state = val.create_iter()
-    arr_state = arr_iter.next_skip_x(arr_state, start)
     while length > 0:
         flatiter_setitem_driver.jit_merge_point(dtype=dtype)
         val = val_iter.getitem(val_state)
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -475,8 +475,10 @@
         return repeat(space, self, repeats, w_axis)
 
     def descr_set_flatiter(self, space, w_obj):
+        iter, state = self.create_iter()
+        dtype = self.get_dtype()
         arr = convert_to_array(space, w_obj)
-        loop.flatiter_setitem(space, self, arr, 0, 1, self.get_size())
+        loop.flatiter_setitem(space, dtype, arr, iter, state, 1, iter.size)
 
     def descr_get_flatiter(self, space):
         return space.wrap(W_FlatIterator(self))
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -2727,15 +2727,35 @@
         b.next()
         assert b.index == 3
         assert b.coords == (0, 3)
+        b.next()
         assert b[3] == 3
-        assert (b[::3] == [0, 3, 6, 9]).all()
-        assert (b[2::5] == [2, 7]).all()
-        assert b[-2] == 8
-        raises(IndexError, "b[11]")
-        raises(IndexError, "b[-11]")
-        raises(IndexError, 'b[0, 1]')
         assert b.index == 0
         assert b.coords == (0, 0)
+        b.next()
+        assert (b[::3] == [0, 3, 6, 9]).all()
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        assert (b[2::5] == [2, 7]).all()
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        assert b[-2] == 8
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        raises(IndexError, "b[11]")
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        raises(IndexError, "b[-11]")
+        assert b.index == 0
+        assert b.coords == (0, 0)
+        b.next()
+        exc = raises(IndexError, 'b[0, 1]')
+        assert str(exc.value) == "unsupported iterator index"
+        assert b.index == 1
+        assert b.coords == (0, 1)
 
     def test_flatiter_setitem(self):
         from numpypy import arange, array
@@ -2743,9 +2763,25 @@
         b = a.T.flat
         b[6::2] = [-1, -2]
         assert (a == [[0, 1, -1, 3], [4, 5, 6, -1], [8, 9, -2, 11]]).all()
+        assert b[2] == 8
+        assert b.index == 0
+        b.next()
+        b[6::2] = [-21, -42]
+        assert (a == [[0, 1, -21, 3], [4, 5, 6, -21], [8, 9, -42, 11]]).all()
         b[0:2] = [[[100]]]
         assert(a[0,0] == 100)
         assert(a[1,0] == 100)
+        b.next()
+        assert b.index == 1
+        exc = raises(ValueError, "b[0] = [1, 2]")
+        assert str(exc.value) == "Error setting single item of array."
+        assert b.index == 0
+        b.next()
+        raises(IndexError, "b[100] = 42")
+        assert b.index == 1
+        exc = raises(IndexError, "b[0, 1] = 42")
+        assert str(exc.value) == "unsupported iterator index"
+        assert b.index == 1
 
     def test_flatiter_ops(self):
         from numpypy import arange, array
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -77,3 +77,119 @@
             --TICK--
             jump(p0, p1, p3, p6, p7, p12, p14, f86, p18, i87, i62, p41, i58, p47, i40, i64, i70, descr=...)
         """)
+
+    def test_array_flatiter_getitem_single(self):
+        def main():
+            import _numpypy.multiarray as np
+            arr = np.zeros((1024, 16)) + 42
+            ai = arr.flat
+            i = 0
+            while i < arr.size:
+                a = ai[i]
+                i += 1
+            return a
+        log = self.run(main, [])
+        assert log.result == 42.0
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i123 = int_lt(i112, i44)
+            guard_true(i123, descr=...)
+            p124 = getfield_gc_pure(p121, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices 16>)
+            setarrayitem_gc(p124, 1, 0, descr=<ArrayS 8>)
+            setarrayitem_gc(p124, 0, 0, descr=<ArrayS 8>)
+            i126 = int_lt(i112, i65)
+            guard_true(i126, descr=...)
+            i127 = int_sub(i75, i112)
+            i128 = int_lt(0, i127)
+            guard_false(i128, descr=...)
+            i129 = int_floordiv(i112, i75)
+            i130 = int_mul(i129, i75)
+            i131 = int_sub(i112, i130)
+            i132 = int_rshift(i131, 63)
+            i133 = int_add(i129, i132)
+            i134 = int_mul(i133, i75)
+            i135 = int_sub(i112, i134)
+            i136 = int_mul(i91, i135)
+            i137 = int_add(i64, i136)
+            i138 = int_sub(i98, i133)
+            setarrayitem_gc(p124, 1, i135, descr=<ArrayS 8>)
+            i139 = int_lt(0, i138)
+            guard_true(i139, descr=...)
+            i140 = int_mul(i102, i133)
+            i141 = int_add(i137, i140)
+            f142 = raw_load(i108, i141, descr=<ArrayF 8>)
+            i143 = int_add(i112, 1)
+            setarrayitem_gc(p124, 1, 0, descr=<ArrayS 8>)
+            guard_not_invalidated(descr=...)
+            i144 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value 0>)
+            i145 = int_lt(i144, 0)
+            guard_false(i145, descr=...)
+            p146 = new_with_vtable(...)
+            setfield_gc(p146, p49, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_iterator 24>)
+            setfield_gc(p146, p124, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices 16>)
+            setfield_gc(p146, i64, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_offset 32>)
+            setfield_gc(p146, 0, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_index 8>)
+            setfield_gc(p16, p146, descr=<FieldP pypy.module.micronumpy.flatiter.W_FlatIterator.inst_state 56>)
+            i147 = arraylen_gc(p72, descr=<ArrayS 8>)
+            i148 = arraylen_gc(p90, descr=<ArrayS 8>)
+            jump(p0, p1, p3, p6, p7, p12, p14, p16, i143, f142, p26, i44, p146, i65, p49, i64, i75, i91, i98, i102, i108, p72, p90, descr=...)
+        """)
+
+    def test_array_flatiter_setitem_single(self):
+        def main():
+            import _numpypy.multiarray as np
+            arr = np.empty((1024, 16))
+            ai = arr.flat
+            i = 0
+            while i < arr.size:
+                ai[i] = 42.0
+                i += 1
+            return ai[-1]
+        log = self.run(main, [])
+        assert log.result == 42.0
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i126 = int_lt(i115, i42)
+            guard_true(i126, descr=...)
+            i127 = int_lt(i115, i48)
+            guard_true(i127, descr=...)
+            p128 = getfield_gc_pure(p124, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices 16>)
+            i129 = int_sub(i73, i115)
+            setarrayitem_gc(p128, 1, 0, descr=<ArrayS 8>)
+            setarrayitem_gc(p128, 0, 0, descr=<ArrayS 8>)
+            i131 = int_lt(0, i129)
+            guard_false(i131, descr=...)
+            i132 = int_floordiv(i115, i73)
+            i133 = int_mul(i132, i73)
+            i134 = int_sub(i115, i133)
+            i135 = int_rshift(i134, 63)
+            i136 = int_add(i132, i135)
+            i137 = int_mul(i136, i73)
+            i138 = int_sub(i115, i137)
+            i139 = int_mul(i89, i138)
+            i140 = int_add(i66, i139)
+            i141 = int_sub(i96, i136)
+            setarrayitem_gc(p128, 1, i138, descr=<ArrayS 8>)
+            i142 = int_lt(0, i141)
+            guard_true(i142, descr=...)
+            i143 = int_mul(i100, i136)
+            i144 = int_add(i140, i143)
+            setarrayitem_gc(p128, 0, i136, descr=<ArrayS 8>)
+            guard_not_invalidated(descr=...)
+            raw_store(i111, i144, 42.000000, descr=<ArrayF 8>)
+            i146 = int_add(i115, 1)
+            i147 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value 0>)
+            setarrayitem_gc(p128, 1, 0, descr=<ArrayS 8>)
+            setarrayitem_gc(p128, 0, 0, descr=<ArrayS 8>)
+            i149 = int_lt(i147, 0)
+            guard_false(i149, descr=...)
+            p150 = new_with_vtable(...)
+            setfield_gc(p150, p47, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_iterator 24>)
+            setfield_gc(p150, p128, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices 16>)
+            setfield_gc(p150, i66, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_offset 32>)
+            setfield_gc(p150, 0, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_index 8>)
+            setfield_gc(p16, p150, descr=<FieldP pypy.module.micronumpy.flatiter.W_FlatIterator.inst_state 56>)
+            i151 = arraylen_gc(p70, descr=<ArrayS 8>)
+            i152 = arraylen_gc(p88, descr=<ArrayS 8>)
+            jump(p0, p1, p3, p6, p7, p12, p14, p16, i146, i42, i48, p150, i73, i66, p47, i89, i96, i100, i111, p70, p88, descr=...)
+        """)


More information about the pypy-commit mailing list