diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/shape.c | 36 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 56 |
2 files changed, 50 insertions, 42 deletions
diff --git a/numpy/core/src/multiarray/shape.c b/numpy/core/src/multiarray/shape.c index b679d6d5d..f46f820ca 100644 --- a/numpy/core/src/multiarray/shape.c +++ b/numpy/core/src/multiarray/shape.c @@ -940,55 +940,51 @@ PyArray_Ravel(PyArrayObject *arr, NPY_ORDER order) order = NPY_FORTRANORDER; } } + else if (order == NPY_ANYORDER) { + order = PyArray_ISFORTRAN(arr) ? NPY_FORTRANORDER : NPY_CORDER; + } - if (order != NPY_KEEPORDER) { - return PyArray_Newshape(arr, &newdim, order); + if (order == NPY_CORDER && PyArray_IS_C_CONTIGUOUS(arr)) { + return PyArray_Newshape(arr, &newdim, NPY_CORDER); + } + else if (order == NPY_FORTRANORDER && PyArray_IS_F_CONTIGUOUS(arr)) { + return PyArray_Newshape(arr, &newdim, NPY_FORTRANORDER); } /* For KEEPORDER, check if we can make a flattened view */ - else { + else if (order == NPY_KEEPORDER) { npy_stride_sort_item strideperm[NPY_MAXDIMS]; - npy_intp stride = 0, base_stride = NPY_MIN_INTP; + npy_intp stride; int i, ndim = PyArray_NDIM(arr); PyArray_CreateSortedStridePerm(PyArray_NDIM(arr), PyArray_STRIDES(arr), strideperm); + /* The output array must be contiguous, so the first stride is fixed */ + stride = PyArray_ITEMSIZE(arr); + for (i = ndim-1; i >= 0; --i) { if (PyArray_DIM(arr, strideperm[i].perm) == 1) { /* A size one dimension does not matter */ continue; } - if (base_stride == NPY_MIN_INTP) { - stride = strideperm[i].stride; - base_stride = stride; - } - else if (strideperm[i].stride != stride) { + if (strideperm[i].stride != stride) { break; } stride *= PyArray_DIM(arr, strideperm[i].perm); } -#if NPY_RELAXED_STRIDES_CHECKING == 0 - /* - * For tidyness, cannot be reached with relaxed strides checking - * since the array is guaranteed contiguous (without, not sure...) - */ - if (base_stride == NPY_MIN_INTP) { - base_stride = PyArray_ITEMSIZE(arr); - } -#endif - /* If all the strides matched a contiguous layout, return a view */ if (i < 0) { PyArrayObject *ret; + stride = PyArray_ITEMSIZE(arr); val[0] = PyArray_SIZE(arr); Py_INCREF(PyArray_DESCR(arr)); ret = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(arr), PyArray_DESCR(arr), 1, val, - &base_stride, + &stride, PyArray_BYTES(arr), PyArray_FLAGS(arr), (PyObject *)arr); diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index a2667172c..5a73aa935 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -2075,41 +2075,37 @@ class TestMethods(TestCase): assert_equal(a.ravel(order='K'), [2, 3, 0, 1]) assert_(a.ravel(order='K').flags.owndata) + # Test simple 1-d copy behaviour: + a = np.arange(10)[::2] + assert_(a.ravel('K').flags.owndata) + assert_(a.ravel('C').flags.owndata) + assert_(a.ravel('F').flags.owndata) + # Not contiguous and 1-sized axis with non matching stride a = np.arange(2**3 * 2)[::2] a = a.reshape(2, 1, 2, 2).swapaxes(-1, -2) strides = list(a.strides) strides[1] = 123 a.strides = strides - assert_(np.may_share_memory(a.ravel(order='K'), a)) + assert_(a.ravel(order='K').flags.owndata) assert_equal(a.ravel('K'), np.arange(0, 15, 2)) - # General case of possible ravel that is not contiguous but - # works and includes a 1-sized axis with non matching stride - a = a.swapaxes(-1, -2) # swap back to C-order - assert_(np.may_share_memory(a.ravel(order='C'), a)) - assert_(np.may_share_memory(a.ravel(order='K'), a)) - - a = a.T # swap all to Fortran order - assert_(np.may_share_memory(a.ravel(order='F'), a)) + # contiguous and 1-sized axis with non matching stride works: + a = np.arange(2**3) + a = a.reshape(2, 1, 2, 2).swapaxes(-1, -2) + strides = list(a.strides) + strides[1] = 123 + a.strides = strides assert_(np.may_share_memory(a.ravel(order='K'), a)) + assert_equal(a.ravel(order='K'), np.arange(2**3)) - # Test negative strides: + # Test negative strides (not very interesting since non-contiguous): a = np.arange(4)[::-1].reshape(2, 2) - assert_(np.may_share_memory(a.ravel(order='C'), a)) - assert_(np.may_share_memory(a.ravel(order='K'), a)) + assert_(a.ravel(order='C').flags.owndata) + assert_(a.ravel(order='K').flags.owndata) assert_equal(a.ravel('C'), [3, 2, 1, 0]) assert_equal(a.ravel('K'), [3, 2, 1, 0]) - # Test keeporder with weirdly strided 1-sized dims (1-d first stride) - a = np.arange(8)[::2].reshape(1, 2, 2, 1) # neither C, nor F order - strides = list(a.strides) - strides[0] = -12 - strides[-1] = 0 - a.strides = strides - assert_(np.may_share_memory(a.ravel(order='K'), a)) - assert_equal(a.ravel('K'), a.ravel('C')) - # 1-element tidy strides test (NPY_RELAXED_STRIDES_CHECKING): a = np.array([[1]]) a.strides = (123, 432) @@ -2125,7 +2121,7 @@ class TestMethods(TestCase): assert_equal(a.ravel(order), [0]) assert_(np.may_share_memory(a.ravel(order), a)) - #Test that certain non-inplace ravels work right (mostly) for 'K': + # Test that certain non-inplace ravels work right (mostly) for 'K': b = np.arange(2**4 * 2)[::2].reshape(2, 2, 2, 2) a = b[..., ::2] assert_equal(a.ravel('K'), [0, 4, 8, 12, 16, 20, 24, 28]) @@ -2139,6 +2135,22 @@ class TestMethods(TestCase): assert_equal(a.ravel('A'), [0, 2, 4, 6, 8, 10, 12, 14]) assert_equal(a.ravel('F'), [0, 8, 4, 12, 2, 10, 6, 14]) + def test_ravel_subclass(self): + class ArraySubclass(np.ndarray): + pass + + a = np.arange(10).view(ArraySubclass) + assert_(isinstance(a.ravel('C'), ArraySubclass)) + assert_(isinstance(a.ravel('F'), ArraySubclass)) + assert_(isinstance(a.ravel('A'), ArraySubclass)) + assert_(isinstance(a.ravel('K'), ArraySubclass)) + + a = np.arange(10)[::2].view(ArraySubclass) + assert_(isinstance(a.ravel('C'), ArraySubclass)) + assert_(isinstance(a.ravel('F'), ArraySubclass)) + assert_(isinstance(a.ravel('A'), ArraySubclass)) + assert_(isinstance(a.ravel('K'), ArraySubclass)) + def test_swapaxes(self): a = np.arange(1*2*3*4).reshape(1, 2, 3, 4).copy() idx = np.indices(a.shape) |