Author: mattip <[email protected]>
Branch: 
Changeset: r80476:393569a1c0ba
Date: 2015-10-29 16:58 +1100
http://bitbucket.org/pypy/pypy/changeset/393569a1c0ba/

Log:    test, tweak handling of 'order' in various ndarray creation methods

diff --git a/pypy/module/micronumpy/concrete.py 
b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -23,11 +23,14 @@
     ''' 
     argsort (return the indices to sort) a list of strides
     '''
-    def __init__(self, rangelist, strides):
+    def __init__(self, rangelist, strides, order):
         self.strides = strides
+        self.order = order
         TimSort.__init__(self, rangelist)
 
     def lt(self, a, b):
+        if self.order == NPY.CORDER:
+            return self.strides[a] <= self.strides[b]
         return self.strides[a] < self.strides[b]
 
 
@@ -311,12 +314,9 @@
                           backstrides, shape, self, orig_array)
 
     def copy(self, space, order=NPY.ANYORDER):
-        order = support.get_order_as_CF(self.order, order)
-        strides, backstrides = calc_strides(self.get_shape(), self.dtype,
-                                                    order)
-        impl = ConcreteArray(self.get_shape(), self.dtype, order, strides,
-                             backstrides)
-        return loop.setslice(space, self.get_shape(), impl, self)
+        if order == NPY.ANYORDER:
+            order = NPY.KEEPORDER
+        return self.astype(space, self.dtype, order, copy=True)
 
     def create_iter(self, shape=None, backward_broadcast=False):
         if shape is not None and \
@@ -363,7 +363,7 @@
     def get_buffer(self, space, readonly):
         return ArrayBuffer(self, readonly)
 
-    def astype(self, space, dtype, order):
+    def astype(self, space, dtype, order, copy=True):
         # copy the general pattern of the strides
         # but make the array storage contiguous in memory
         shape = self.get_shape()
@@ -377,18 +377,21 @@
             t_strides, backstrides = calc_strides(shape, dtype, order)
         else:
             indx_array = range(len(strides))
-            list_sorter = StrideSort(indx_array, strides)
+            list_sorter = StrideSort(indx_array, strides, self.order)
             list_sorter.sort()
             t_elsize = dtype.elsize
             t_strides = strides[:]
             base = dtype.elsize
+            print 'start strides, shape, indx_array', strides, shape, 
indx_array
             for i in indx_array:
                 t_strides[i] = base
                 base *= shape[i]
+            print 'final strides', t_strides
             backstrides = calc_backstrides(t_strides, shape)
         order = support.get_order_as_CF(self.order, order)
         impl = ConcreteArray(shape, dtype, order, t_strides, backstrides)
-        loop.setslice(space, impl.get_shape(), impl, self)
+        if copy:
+            loop.setslice(space, impl.get_shape(), impl, self)
         return impl
 
 OBJECTSTORE = lltype.GcStruct('ObjectStore',
diff --git a/pypy/module/micronumpy/ctors.py b/pypy/module/micronumpy/ctors.py
--- a/pypy/module/micronumpy/ctors.py
+++ b/pypy/module/micronumpy/ctors.py
@@ -103,15 +103,18 @@
             copy = False
     dtype = descriptor.decode_w_dtype(space, w_dtype)
 
-    if space.is_none(w_order):
-        w_order = space.wrap('C')
-    npy_order = order_converter(space, w_order, NPY.CORDER)
 
     if isinstance(w_object, W_NDimArray):
-        if (dtype is None or w_object.get_dtype() is dtype):
-            if copy and (subok or type(w_object) is W_NDimArray):
-                return w_object.descr_copy(space, w_order)
-            elif not copy and (subok or type(w_object) is W_NDimArray):
+        npy_order = order_converter(space, w_order, NPY.ANYORDER)
+        if (dtype is None or w_object.get_dtype() is dtype) and (subok or
+                type(w_object) is W_NDimArray):
+            flags = w_object.get_flags()
+            must_copy = copy
+            must_copy |= (npy_order == NPY.CORDER and not flags & 
NPY.ARRAY_C_CONTIGUOUS)
+            must_copy |= (npy_order == NPY.FORTRANORDER and not flags & 
NPY.ARRAY_F_CONTIGUOUS)
+            if must_copy:
+                return w_object.descr_copy(space, space.wrap(npy_order))
+            else:
                 return w_object
         if subok and not type(w_object) is W_NDimArray:
             raise oefmt(space.w_NotImplementedError,
@@ -124,7 +127,8 @@
             copy = True
         if copy:
             shape = w_object.get_shape()
-            w_arr = W_NDimArray.from_shape(space, shape, dtype, 
order=npy_order)
+            order = support.get_order_as_CF(w_object.get_order(), npy_order)
+            w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
             if support.product(shape) == 1:
                 w_arr.set_scalar_value(dtype.coerce(space,
                         w_object.implementation.getitem(0)))
@@ -148,6 +152,7 @@
                     w_base=w_base, strides=imp.strides, start=imp.start)
     else:
         # not an array
+        npy_order = order_converter(space, w_order, NPY.CORDER)
         shape, elems_w = find_shape_and_elems(space, w_object, dtype)
     if dtype is None and space.isinstance_w(w_object, space.w_buffer):
         dtype = descriptor.get_dtype_cache(space).w_uint8dtype
@@ -271,6 +276,7 @@
 
 
 def _zeros_or_empty(space, w_shape, w_dtype, w_order, zero):
+    # w_order can be None, str, or boolean
     order = order_converter(space, w_order, NPY.CORDER)
     dtype = space.interp_w(descriptor.W_Dtype,
         space.call_function(space.gettypefor(descriptor.W_Dtype), w_dtype))
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
@@ -16,6 +16,7 @@
         self.dtype = base.get_dtype()
         self.shape = [base.get_size()]
         self.storage = self._base.implementation.storage
+        self.order = base.get_order()
 
     def base(self):
         return self._base
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
@@ -370,11 +370,11 @@
 
     def descr_copy(self, space, w_order=None):
         if w_order is None:
-            order = NPY.KEEPORDER
+            order = NPY.CORDER
         elif space.isinstance_w(w_order, space.w_int):
             order = space.int_w(w_order)
         else:
-            order = order_converter(space, w_order, NPY.KEEPORDER)
+            order = order_converter(space, w_order, NPY.CORDER)
         copy = self.implementation.copy(space, order)
         w_subtype = space.type(self)
         return wrap_impl(space, w_subtype, self, copy)
diff --git a/pypy/module/micronumpy/test/test_flagsobj.py 
b/pypy/module/micronumpy/test/test_flagsobj.py
--- a/pypy/module/micronumpy/test/test_flagsobj.py
+++ b/pypy/module/micronumpy/test/test_flagsobj.py
@@ -47,3 +47,104 @@
         b = np.array([4,5,6,7])
         assert a.flags == b.flags
         assert not a.flags != b.flags
+
+    def test_copy_order(self):
+        import numpy as np
+        tst = np.ones((10, 1), order='C').flags.f_contiguous
+        NPY_RELAXED_STRIDES_CHECKING = tst
+        a = np.arange(24).reshape(2, 1, 3, 4)
+        b = a.copy(order='F')
+        c = np.arange(24).reshape(2, 1, 4, 3).swapaxes(2, 3)
+
+        def check_copy_result(x, y, ccontig, fcontig, strides=False):
+            assert x is not y
+            assert (x == y).all()
+            assert res.flags.c_contiguous == ccontig
+            assert res.flags.f_contiguous == fcontig
+            # This check is impossible only because
+            # NPY_RELAXED_STRIDES_CHECKING changes the strides actively
+            if not NPY_RELAXED_STRIDES_CHECKING:
+                if strides:
+                    assert x.strides == y.strides
+                else:
+                    assert x.strides != y.strides
+
+        # Validate the initial state of a, b, and c
+        assert a.flags.c_contiguous
+        assert not a.flags.f_contiguous
+        assert not b.flags.c_contiguous
+        assert b.flags.f_contiguous
+        assert not c.flags.c_contiguous
+        assert not c.flags.f_contiguous
+
+        # Copy with order='C'
+        res = a.copy(order='C')
+        check_copy_result(res, a, ccontig=True, fcontig=False, strides=True)
+        res = b.copy(order='C')
+        check_copy_result(res, b, ccontig=True, fcontig=False, strides=False)
+        res = c.copy(order='C')
+        check_copy_result(res, c, ccontig=True, fcontig=False, strides=False)
+
+        # Copy with order='F'
+        res = a.copy(order='F')
+        check_copy_result(res, a, ccontig=False, fcontig=True, strides=False)
+        res = b.copy(order='F')
+        check_copy_result(res, b, ccontig=False, fcontig=True, strides=True)
+        res = c.copy(order='F')
+        check_copy_result(res, c, ccontig=False, fcontig=True, strides=False)
+
+        # Copy with order='K'
+        res = a.copy(order='K')
+        check_copy_result(res, a, ccontig=True, fcontig=False, strides=True)
+        res = b.copy(order='K')
+        check_copy_result(res, b, ccontig=False, fcontig=True, strides=True)
+        res = c.copy(order='K')
+        check_copy_result(res, c, ccontig=False, fcontig=False, strides=True)
+
+    def test_contiguous_flags(self):
+        import numpy as np
+        tst = np.ones((10, 1), order='C').flags.f_contiguous
+        NPY_RELAXED_STRIDES_CHECKING = tst
+        a = np.ones((4, 4, 1))[::2,:,:]
+        if NPY_RELAXED_STRIDES_CHECKING:
+            a.strides = a.strides[:2] + (-123,)
+        b = np.ones((2, 2, 1, 2, 2)).swapaxes(3, 4)
+
+        def check_contig(a, ccontig, fcontig):
+            assert a.flags.c_contiguous == ccontig
+            assert a.flags.f_contiguous == fcontig
+
+        # Check if new arrays are correct:
+        check_contig(a, False, False)
+        check_contig(b, False, False)
+        if NPY_RELAXED_STRIDES_CHECKING:
+            check_contig(np.empty((2, 2, 0, 2, 2)), True, True)
+            check_contig(np.array([[[1], [2]]], order='F'), True, True)
+        else:
+            check_contig(np.empty((2, 2, 0, 2, 2)), True, False)
+            check_contig(np.array([[[1], [2]]], order='F'), False, True)
+        check_contig(np.empty((2, 2)), True, False)
+        check_contig(np.empty((2, 2), order='F'), False, True)
+
+        # Check that np.array creates correct contiguous flags:
+        check_contig(np.array(a, copy=False), False, False)
+        check_contig(np.array(a, copy=False, order='C'), True, False)
+        check_contig(np.array(a, ndmin=4, copy=False, order='F'), False, True)
+
+        if NPY_RELAXED_STRIDES_CHECKING:
+            # Check slicing update of flags and :
+            check_contig(a[0], True, True)
+            check_contig(a[None, ::4, ..., None], True, True)
+            check_contig(b[0, 0, ...], False, True)
+            check_contig(b[:,:, 0:0,:,:], True, True)
+        else:
+            # Check slicing update of flags:
+            check_contig(a[0], True, False)
+            # Would be nice if this was C-Contiguous:
+            check_contig(a[None, 0, ..., None], False, False)
+            check_contig(b[0, 0, 0, ...], False, True)
+
+        # Test ravel and squeeze.
+        check_contig(a.ravel(), True, True)
+        check_contig(np.ones((1, 3, 1)).squeeze(), True, True)
+ 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to