Author: mattip <[email protected]>
Branch: 
Changeset: r75575:7e9970164f05
Date: 2015-01-29 07:07 +0200
http://bitbucket.org/pypy/pypy/changeset/7e9970164f05/

Log:    test, fix bogus shape,stride,backstride creation in SliceIterator

diff --git a/pypy/module/micronumpy/nditer.py b/pypy/module/micronumpy/nditer.py
--- a/pypy/module/micronumpy/nditer.py
+++ b/pypy/module/micronumpy/nditer.py
@@ -252,10 +252,6 @@
     # Copy logic from npyiter_coalesce_axes, used in ufunc iterators
     # and in nditer's with 'external_loop' flag
     can_coalesce = True
-    if it.order == 'F':
-        fastest = 0
-    else:
-        fastest = -1
     for idim in range(it.ndim - 1):
         for op_it, _ in it.iters:
             if op_it is None:
@@ -275,7 +271,7 @@
         if can_coalesce:
             for i in range(len(it.iters)):
                 new_iter = coalesce_iter(it.iters[i][0], it.op_flags[i], it,
-                                         it.order, fastest)
+                                         it.order)
                 it.iters[i] = (new_iter, new_iter.reset())
             if len(it.shape) > 1:
                 if it.order == 'F':
@@ -289,7 +285,7 @@
             break
     # Always coalesce at least one
     for i in range(len(it.iters)):
-        new_iter = coalesce_iter(it.iters[i][0], it.op_flags[i], it, 'C', -1)
+        new_iter = coalesce_iter(it.iters[i][0], it.op_flags[i], it, 'C')
         it.iters[i] = (new_iter, new_iter.reset())
     if len(it.shape) > 1:
         if it.order == 'F':
@@ -300,12 +296,11 @@
         it.shape = [1]
 
 
-def coalesce_iter(old_iter, op_flags, it, order, fastest=-1, flat=True):
+def coalesce_iter(old_iter, op_flags, it, order, flat=True):
     '''
     We usually iterate through an array one value at a time.
     But after coalesce(), getoperand() will return a slice by removing
-    the fastest varying dimension from the beginning or end of the shape.
-    XXX - what happens on swapaxis arrays?
+    the fastest varying dimension(s) from the beginning or end of the shape.
     If flat is true, then the slice will be 1d, otherwise stack up the shape of
     the fastest varying dimension in the slice, so an iterator of a  'C' array 
     of shape (2,4,3) after two calls to coalesce will iterate 2 times over a 
slice
@@ -319,6 +314,9 @@
         new_strides = strides[1:]
         new_backstrides = backstrides[1:]
         _stride = old_iter.slice_stride + [strides[0]]
+        _shape =  old_iter.slice_shape + [shape[0]]
+        _backstride = old_iter.slice_backstride + [strides[0] * (shape[0] - 1)]
+        fastest = shape[0]
     else:
         new_shape = shape[:-1]
         new_strides = strides[:-1]
@@ -326,14 +324,15 @@
         # use the operand's iterator's rightmost stride,
         # even if it is not the fastest (for 'F' or swapped axis)
         _stride = [strides[-1]] + old_iter.slice_stride
-    _shape = [shape[fastest]]  + old_iter.slice_shape
-    _backstride = [(_shape[fastest] - 1) * _stride[0]] + 
old_iter.slice_backstride
+        _shape = [shape[-1]]  + old_iter.slice_shape
+        _backstride = [(shape[-1] - 1) * strides[-1]] + 
old_iter.slice_backstride
+        fastest = shape[-1]
     if flat:
         _shape = [support.product(_shape)]
         if len(_stride) > 1:
             _stride = [min(_stride[0], _stride[1])]
         _backstride = [(shape[0] - 1) * _stride[0]]
-    return SliceIter(old_iter.array, old_iter.size / shape[fastest],
+    return SliceIter(old_iter.array, old_iter.size / fastest,
                 new_shape, new_strides, new_backstrides,
                 _shape, _stride, _backstride, op_flags, it)
 
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py 
b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -269,6 +269,26 @@
         aout = ufunc_sum(ai)
         assert aout.shape == (3, 3)
 
+    def test_frompyfunc_fortran(self):
+        import numpy as np
+        def tofrom_fortran(in0, out0):
+            out0[:] = in0.T
+
+        def lapack_like_times2(in0, out0):
+            a = np.empty(in0.T.shape, in0.dtype)
+            tofrom_fortran(in0, a)
+            a *= 2
+            tofrom_fortran(a, out0)
+
+        times2 = np.frompyfunc([lapack_like_times2], 1, 1,
+                            signature='(m,n)->(m,n)',
+                            dtypes=[np.dtype(float), np.dtype(float)],
+                            stack_inputs=True,
+                          )
+        in0 = np.arange(3300, dtype=float).reshape(100, 33)
+        out0 = times2(in0)
+        assert out0.shape == in0.shape
+        assert (out0 == in0 * 2).all()
 
     def test_ufunc_kwargs(self):
         from numpy import ufunc, frompyfunc, arange, dtype
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -651,14 +651,10 @@
                           w_op_flags, w_op_dtypes, w_casting, w_op_axes,
                           w_itershape)
             # coalesce each iterators, according to inner_dimensions
-            if nd_it.order == 'F':
-                fastest = 0
-            else:
-                fastest = -1
             for i in range(len(inargs) + len(outargs)):
                 for j in range(self.core_num_dims[i]):
                     new_iter = coalesce_iter(nd_it.iters[i][0], 
nd_it.op_flags[i],
-                                    nd_it, nd_it.order, fastest, flat=False)
+                                    nd_it, nd_it.order, flat=False)
                     nd_it.iters[i] = (new_iter, new_iter.reset())
             # do the iteration
             while not nd_it.done:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to