diff options
Diffstat (limited to 'numpy/core')
-rw-r--r-- | numpy/core/include/numpy/ndarraytypes.h | 7 | ||||
-rw-r--r-- | numpy/core/numeric.py | 4 | ||||
-rw-r--r-- | numpy/core/src/multiarray/convert.c | 4 | ||||
-rw-r--r-- | numpy/core/src/multiarray/ctors.c | 41 | ||||
-rw-r--r-- | numpy/core/src/multiarray/dtype_transfer.c | 6 | ||||
-rw-r--r-- | numpy/core/src/multiarray/flagsobject.c | 100 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 18 | ||||
-rw-r--r-- | numpy/core/src/multiarray/shape.c | 53 | ||||
-rw-r--r-- | numpy/core/src/private/lowlevel_strided_loops.h | 46 | ||||
-rw-r--r-- | numpy/core/src/umath/reduction.c | 2 | ||||
-rw-r--r-- | numpy/core/tests/test_api.py | 36 | ||||
-rw-r--r-- | numpy/core/tests/test_regression.py | 10 |
12 files changed, 152 insertions, 175 deletions
diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h index 93d561c7c..f7898753b 100644 --- a/numpy/core/include/numpy/ndarraytypes.h +++ b/numpy/core/include/numpy/ndarraytypes.h @@ -756,8 +756,9 @@ typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *); #define NPY_ARRAY_F_CONTIGUOUS 0x0002 /* - * Note: all 0-d arrays are C_CONTIGUOUS and F_CONTIGUOUS. If a - * 1-d array is C_CONTIGUOUS it is also F_CONTIGUOUS + * Note: all 0-d arrays are C_CONTIGUOUS and F_CONTIGUOUS. An N-d + * array that is C_CONTIGUOUS is also F_CONTIGUOUS if only + * one axis has a dimension different from one (ie. a 1x3x1 array). */ /* @@ -1370,7 +1371,7 @@ PyArrayNeighborhoodIter_Next2D(PyArrayNeighborhoodIterObject* iter); PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS)) #define PyArray_ISFORTRAN(m) (PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS) && \ - (PyArray_NDIM(m) > 1)) + (!PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS))) #define PyArray_FORTRAN_IF(m) ((PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS) ? \ NPY_ARRAY_F_CONTIGUOUS : 0)) diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index 5f0474d3e..0d0babbac 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -538,7 +538,7 @@ def require(a, dtype=None, requirements=None): def isfortran(a): """ Returns True if array is arranged in Fortran-order in memory - and dimension > 1. + and not C-order. Parameters ---------- @@ -584,7 +584,7 @@ def isfortran(a): >>> np.isfortran(b) True - 1-D arrays always evaluate as False. + C-ordered arrays evaluate as False even if they are also FORTRAN-ordered. >>> np.isfortran(np.array([1, 2], order='FORTRAN')) False diff --git a/numpy/core/src/multiarray/convert.c b/numpy/core/src/multiarray/convert.c index 8b646e59b..e3dd78b9f 100644 --- a/numpy/core/src/multiarray/convert.c +++ b/numpy/core/src/multiarray/convert.c @@ -265,8 +265,8 @@ PyArray_ToString(PyArrayObject *self, NPY_ORDER order) */ numbytes = PyArray_NBYTES(self); - if ((PyArray_ISCONTIGUOUS(self) && (order == NPY_CORDER)) - || (PyArray_ISFORTRAN(self) && (order == NPY_FORTRANORDER))) { + if ((PyArray_IS_C_CONTIGUOUS(self) && (order == NPY_CORDER)) + || (PyArray_IS_F_CONTIGUOUS(self) && (order == NPY_FORTRANORDER))) { ret = PyBytes_FromStringAndSize(PyArray_DATA(self), (Py_ssize_t) numbytes); } else { diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 934f9198f..ef6c40b46 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -1112,7 +1112,6 @@ PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order, int idim; PyArray_CreateSortedStridePerm(PyArray_NDIM(prototype), - PyArray_SHAPE(prototype), PyArray_STRIDES(prototype), strideperm); @@ -1825,9 +1824,6 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags) } arrflags = PyArray_FLAGS(arr); - if (PyArray_NDIM(arr) <= 1 && (flags & NPY_ARRAY_F_CONTIGUOUS)) { - flags |= NPY_ARRAY_C_CONTIGUOUS; - } /* If a guaranteed copy was requested */ copy = (flags & NPY_ARRAY_ENSURECOPY) || /* If C contiguous was requested, and arr is not */ @@ -1837,9 +1833,8 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags) ((flags & NPY_ARRAY_ALIGNED) && (!(arrflags & NPY_ARRAY_ALIGNED))) || /* If a Fortran contiguous array was requested, and arr is not */ - (PyArray_NDIM(arr) > 1 && - ((flags & NPY_ARRAY_F_CONTIGUOUS) && - (!(arrflags & NPY_ARRAY_F_CONTIGUOUS)))) || + ((flags & NPY_ARRAY_F_CONTIGUOUS) && + (!(arrflags & NPY_ARRAY_F_CONTIGUOUS))) || /* If a writeable array was requested, and arr is not */ ((flags & NPY_ARRAY_WRITEABLE) && (!(arrflags & NPY_ARRAY_WRITEABLE))) || @@ -3570,14 +3565,33 @@ _array_fill_strides(npy_intp *strides, npy_intp *dims, int nd, size_t itemsize, int inflag, int *objflags) { int i; + npy_bool not_cf_contig = 0; + npy_bool nod = 0; /* A dim != 1 was found */ + + /* Check if new array is both F- and C-contiguous */ + for (i = 0; i < nd; i++) { + if (dims[i] != 1) { + if (nod) { + not_cf_contig = 1; + break; + } + nod = 1; + } + } + /* Only make Fortran strides if not contiguous as well */ if ((inflag & (NPY_ARRAY_F_CONTIGUOUS|NPY_ARRAY_C_CONTIGUOUS)) == NPY_ARRAY_F_CONTIGUOUS) { for (i = 0; i < nd; i++) { strides[i] = itemsize; - itemsize *= dims[i] ? dims[i] : 1; + if (dims[i]) { + itemsize *= dims[i]; + } + else { + not_cf_contig = 0; + } } - if (nd > 1) { + if (not_cf_contig) { *objflags = ((*objflags)|NPY_ARRAY_F_CONTIGUOUS) & ~NPY_ARRAY_C_CONTIGUOUS; } @@ -3588,9 +3602,14 @@ _array_fill_strides(npy_intp *strides, npy_intp *dims, int nd, size_t itemsize, else { for (i = nd - 1; i >= 0; i--) { strides[i] = itemsize; - itemsize *= dims[i] ? dims[i] : 1; + if (dims[i]) { + itemsize *= dims[i]; + } + else { + not_cf_contig = 0; + } } - if (nd > 1) { + if (not_cf_contig) { *objflags = ((*objflags)|NPY_ARRAY_C_CONTIGUOUS) & ~NPY_ARRAY_F_CONTIGUOUS; } diff --git a/numpy/core/src/multiarray/dtype_transfer.c b/numpy/core/src/multiarray/dtype_transfer.c index 138275c4c..01cb93562 100644 --- a/numpy/core/src/multiarray/dtype_transfer.c +++ b/numpy/core/src/multiarray/dtype_transfer.c @@ -3921,7 +3921,7 @@ PyArray_PrepareOneRawArrayIter(int ndim, npy_intp *shape, } /* Sort the axes based on the destination strides */ - PyArray_CreateSortedStridePerm(ndim, shape, strides, strideperm); + PyArray_CreateSortedStridePerm(ndim, strides, strideperm); for (i = 0; i < ndim; ++i) { int iperm = strideperm[ndim - i - 1].perm; out_shape[i] = shape[iperm]; @@ -4051,7 +4051,7 @@ PyArray_PrepareTwoRawArrayIter(int ndim, npy_intp *shape, } /* Sort the axes based on the destination strides */ - PyArray_CreateSortedStridePerm(ndim, shape, stridesA, strideperm); + PyArray_CreateSortedStridePerm(ndim, stridesA, strideperm); for (i = 0; i < ndim; ++i) { int iperm = strideperm[ndim - i - 1].perm; out_shape[i] = shape[iperm]; @@ -4185,7 +4185,7 @@ PyArray_PrepareThreeRawArrayIter(int ndim, npy_intp *shape, } /* Sort the axes based on the destination strides */ - PyArray_CreateSortedStridePerm(ndim, shape, stridesA, strideperm); + PyArray_CreateSortedStridePerm(ndim, stridesA, strideperm); for (i = 0; i < ndim; ++i) { int iperm = strideperm[ndim - i - 1].perm; out_shape[i] = shape[iperm]; diff --git a/numpy/core/src/multiarray/flagsobject.c b/numpy/core/src/multiarray/flagsobject.c index faaf264e0..ef04bdb20 100644 --- a/numpy/core/src/multiarray/flagsobject.c +++ b/numpy/core/src/multiarray/flagsobject.c @@ -15,11 +15,8 @@ #include "common.h" -static int -_IsContiguous(PyArrayObject *ap); - -static int -_IsFortranContiguous(PyArrayObject *ap); +static void +_UpdateContiguousFlags(PyArrayObject *ap); /*NUMPY_API * @@ -62,28 +59,9 @@ PyArray_NewFlagsObject(PyObject *obj) NPY_NO_EXPORT void PyArray_UpdateFlags(PyArrayObject *ret, int flagmask) { - - if (flagmask & NPY_ARRAY_F_CONTIGUOUS) { - if (_IsFortranContiguous(ret)) { - PyArray_ENABLEFLAGS(ret, NPY_ARRAY_F_CONTIGUOUS); - if (PyArray_NDIM(ret) > 1) { - PyArray_CLEARFLAGS(ret, NPY_ARRAY_C_CONTIGUOUS); - } - } - else { - PyArray_CLEARFLAGS(ret, NPY_ARRAY_F_CONTIGUOUS); - } - } - if (flagmask & NPY_ARRAY_C_CONTIGUOUS) { - if (_IsContiguous(ret)) { - PyArray_ENABLEFLAGS(ret, NPY_ARRAY_C_CONTIGUOUS); - if (PyArray_NDIM(ret) > 1) { - PyArray_CLEARFLAGS(ret, NPY_ARRAY_F_CONTIGUOUS); - } - } - else { - PyArray_CLEARFLAGS(ret, NPY_ARRAY_C_CONTIGUOUS); - } + /* Always update both, as its not trivial to guess one from the other */ + if (flagmask & (NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_C_CONTIGUOUS)) { + _UpdateContiguousFlags(ret); } if (flagmask & NPY_ARRAY_ALIGNED) { if (_IsAligned(ret)) { @@ -110,66 +88,56 @@ PyArray_UpdateFlags(PyArrayObject *ret, int flagmask) /* * Check whether the given array is stored contiguously - * (row-wise) in memory. + * in memory. And update the passed in ap flags apropriately. * - * 0-strided arrays are not contiguous (even if dimension == 1) + * A dimension == 1 stride is ignored for contiguous flags and a 0-sized array + * is always both C- and F-Contiguous. 0-strided arrays are not contiguous. */ -static int -_IsContiguous(PyArrayObject *ap) +static void +_UpdateContiguousFlags(PyArrayObject *ap) { npy_intp sd; npy_intp dim; int i; + npy_bool is_c_contig = 1; - if (PyArray_NDIM(ap) == 0) { - return 1; - } sd = PyArray_DESCR(ap)->elsize; - if (PyArray_NDIM(ap) == 1) { - return PyArray_DIMS(ap)[0] == 1 || sd == PyArray_STRIDES(ap)[0]; - } for (i = PyArray_NDIM(ap) - 1; i >= 0; --i) { dim = PyArray_DIMS(ap)[i]; /* contiguous by definition */ if (dim == 0) { - return 1; + PyArray_ENABLEFLAGS(ap, NPY_ARRAY_C_CONTIGUOUS); + PyArray_ENABLEFLAGS(ap, NPY_ARRAY_F_CONTIGUOUS); + return; } - if (PyArray_STRIDES(ap)[i] != sd) { - return 0; + if (dim != 1) { + if (PyArray_STRIDES(ap)[i] != sd) { + is_c_contig = 0; + } + sd *= dim; } - sd *= dim; } - return 1; -} - - -/* 0-strided arrays are not contiguous (even if dimension == 1) */ -static int -_IsFortranContiguous(PyArrayObject *ap) -{ - npy_intp sd; - npy_intp dim; - int i; - - if (PyArray_NDIM(ap) == 0) { - return 1; + if (is_c_contig) { + PyArray_ENABLEFLAGS(ap, NPY_ARRAY_C_CONTIGUOUS); } - sd = PyArray_DESCR(ap)->elsize; - if (PyArray_NDIM(ap) == 1) { - return PyArray_DIMS(ap)[0] == 1 || sd == PyArray_STRIDES(ap)[0]; + else { + PyArray_CLEARFLAGS(ap, NPY_ARRAY_C_CONTIGUOUS); } + + /* check if fortran contiguous */ + sd = PyArray_DESCR(ap)->elsize; for (i = 0; i < PyArray_NDIM(ap); ++i) { dim = PyArray_DIMS(ap)[i]; - /* fortran contiguous by definition */ - if (dim == 0) { - return 1; - } - if (PyArray_STRIDES(ap)[i] != sd) { - return 0; + if (dim != 1) { + if (PyArray_STRIDES(ap)[i] != sd) { + PyArray_CLEARFLAGS(ap, NPY_ARRAY_F_CONTIGUOUS); + return; + } + sd *= dim; } - sd *= dim; } - return 1; + PyArray_ENABLEFLAGS(ap, NPY_ARRAY_F_CONTIGUOUS); + return; } static void diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 6ad0eb211..1f455f528 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -1517,26 +1517,18 @@ PyArray_EquivTypenums(int typenum1, int typenum2) /*** END C-API FUNCTIONS **/ static PyObject * -_prepend_ones(PyArrayObject *arr, int nd, int ndmin, NPY_ORDER order) +_prepend_ones(PyArrayObject *arr, int nd, int ndmin) { npy_intp newdims[NPY_MAXDIMS]; npy_intp newstrides[NPY_MAXDIMS]; - npy_intp newstride; int i, k, num; PyArrayObject *ret; PyArray_Descr *dtype; - if (order == NPY_FORTRANORDER || PyArray_ISFORTRAN(arr) || PyArray_NDIM(arr) == 0) { - newstride = PyArray_DESCR(arr)->elsize; - } - else { - newstride = PyArray_STRIDES(arr)[0] * PyArray_DIMS(arr)[0]; - } - num = ndmin - nd; for (i = 0; i < num; i++) { newdims[i] = 1; - newstrides[i] = newstride; + newstrides[i] = PyArray_DESCR(arr)->elsize; } for (i = num; i < ndmin; i++) { k = i - num; @@ -1566,8 +1558,8 @@ _prepend_ones(PyArrayObject *arr, int nd, int ndmin, NPY_ORDER order) #define STRIDING_OK(op, order) \ ((order) == NPY_ANYORDER || \ (order) == NPY_KEEPORDER || \ - ((order) == NPY_CORDER && PyArray_ISCONTIGUOUS(op)) || \ - ((order) == NPY_FORTRANORDER && PyArray_ISFORTRAN(op))) + ((order) == NPY_CORDER && PyArray_IS_C_CONTIGUOUS(op)) || \ + ((order) == NPY_FORTRANORDER && PyArray_IS_F_CONTIGUOUS(op))) static PyObject * _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws) @@ -1677,7 +1669,7 @@ _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws) * create a new array from the same data with ones in the shape * steals a reference to ret */ - return _prepend_ones(ret, nd, ndmin, order); + return _prepend_ones(ret, nd, ndmin); clean_type: Py_XDECREF(type); diff --git a/numpy/core/src/multiarray/shape.c b/numpy/core/src/multiarray/shape.c index 2dcf53d55..6da07e4cd 100644 --- a/numpy/core/src/multiarray/shape.c +++ b/numpy/core/src/multiarray/shape.c @@ -267,32 +267,6 @@ PyArray_Newshape(PyArrayObject *self, PyArray_Dims *newdims, } } } - else if (ndim > 0) { - /* - * replace any 0-valued strides with - * appropriate value to preserve contiguousness - */ - if (order == NPY_FORTRANORDER) { - if (dimensions[0] == 1) { - strides[0] = PyArray_DESCR(self)->elsize; - } - for (i = 1; i < ndim; i++) { - if (dimensions[i] == 1) { - strides[i] = strides[i-1] * dimensions[i-1]; - } - } - } - else { - if (dimensions[ndim-1] == 1) { - strides[ndim-1] = PyArray_DESCR(self)->elsize; - } - for (i = ndim - 2; i > -1; i--) { - if (dimensions[i] == 1) { - strides[i] = strides[i+1] * dimensions[i+1]; - } - } - } - } Py_INCREF(PyArray_DESCR(self)); ret = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(self), @@ -849,7 +823,7 @@ int _npy_stride_sort_item_comparator(const void *a, const void *b) bstride = -bstride; } - if (astride == bstride || astride == 0 || bstride == 0) { + if (astride == bstride) { /* * Make the qsort stable by next comparing the perm order. * (Note that two perm entries will never be equal) @@ -861,9 +835,7 @@ int _npy_stride_sort_item_comparator(const void *a, const void *b) if (astride > bstride) { return -1; } - else { - return 1; - } + return 1; } /*NUMPY_API @@ -874,8 +846,7 @@ int _npy_stride_sort_item_comparator(const void *a, const void *b) * [(2, 12), (0, 4), (1, -2)]. */ NPY_NO_EXPORT void -PyArray_CreateSortedStridePerm(int ndim, npy_intp *shape, - npy_intp *strides, +PyArray_CreateSortedStridePerm(int ndim, npy_intp *strides, npy_stride_sort_item *out_strideperm) { int i; @@ -883,12 +854,7 @@ PyArray_CreateSortedStridePerm(int ndim, npy_intp *shape, /* Set up the strideperm values */ for (i = 0; i < ndim; ++i) { out_strideperm[i].perm = i; - if (shape[i] == 1) { - out_strideperm[i].stride = 0; - } - else { - out_strideperm[i].stride = strides[i]; - } + out_strideperm[i].stride = strides[i]; } /* Sort them */ @@ -1015,10 +981,10 @@ PyArray_Ravel(PyArrayObject *arr, NPY_ORDER order) } } - if (order == NPY_CORDER && PyArray_ISCONTIGUOUS(arr)) { + if (order == NPY_CORDER && PyArray_IS_C_CONTIGUOUS(arr)) { return PyArray_Newshape(arr, &newdim, NPY_CORDER); } - else if (order == NPY_FORTRANORDER && PyArray_ISFORTRAN(arr)) { + 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 */ @@ -1027,7 +993,7 @@ PyArray_Ravel(PyArrayObject *arr, NPY_ORDER order) npy_intp stride; int i, ndim = PyArray_NDIM(arr); - PyArray_CreateSortedStridePerm(PyArray_NDIM(arr), PyArray_SHAPE(arr), + PyArray_CreateSortedStridePerm(PyArray_NDIM(arr), PyArray_STRIDES(arr), strideperm); stride = strideperm[ndim-1].stride; @@ -1164,6 +1130,8 @@ build_shape_string(npy_intp n, npy_intp *vals) * WARNING: If an axis flagged for removal has a shape equal to zero, * the array will point to invalid memory. The caller must * validate this! + * If an axis flagged for removal has a shape larger then one, + * the arrays contiguous flags may require updating. * * For example, this can be used to remove the reduction axes * from a reduction result once its computation is complete. @@ -1186,7 +1154,4 @@ PyArray_RemoveAxesInPlace(PyArrayObject *arr, npy_bool *flags) /* The final number of dimensions */ fa->nd = idim_out; - - /* Update contiguous flags */ - PyArray_UpdateFlags(arr, NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_F_CONTIGUOUS); } diff --git a/numpy/core/src/private/lowlevel_strided_loops.h b/numpy/core/src/private/lowlevel_strided_loops.h index a73dd12cf..94c6a2121 100644 --- a/numpy/core/src/private/lowlevel_strided_loops.h +++ b/numpy/core/src/private/lowlevel_strided_loops.h @@ -552,10 +552,10 @@ PyArray_PrepareThreeRawArrayIter(int ndim, npy_intp *shape, count = PyArray_SIZE(arr), \ data = PyArray_BYTES(arr), \ stride = ((PyArray_NDIM(arr) == 0) ? 0 : \ - (PyArray_CHKFLAGS(arr, NPY_ARRAY_F_CONTIGUOUS) ? \ + ((PyArray_NDIM(arr) == 1) ? \ PyArray_STRIDE(arr, 0) : \ - PyArray_STRIDE(arr, \ - PyArray_NDIM(arr)-1))) + PyArray_ITEMSIZE(arr))) \ + #define PyArray_TRIVIALLY_ITERABLE_PAIR(arr1, arr2) (\ PyArray_TRIVIALLY_ITERABLE(arr1) && \ @@ -575,16 +575,12 @@ PyArray_PrepareThreeRawArrayIter(int ndim, npy_intp *shape, count = ((size1 > size2) || size1 == 0) ? size1 : size2; \ data1 = PyArray_BYTES(arr1); \ data2 = PyArray_BYTES(arr2); \ - stride1 = (size1 == 1 ? 0 : \ - (PyArray_CHKFLAGS(arr1, NPY_ARRAY_F_CONTIGUOUS) ? \ - PyArray_STRIDE(arr1, 0) : \ - PyArray_STRIDE(arr1, \ - PyArray_NDIM(arr1)-1))); \ - stride2 = (size2 == 1 ? 0 : \ - (PyArray_CHKFLAGS(arr2, NPY_ARRAY_F_CONTIGUOUS) ? \ - PyArray_STRIDE(arr2, 0) : \ - PyArray_STRIDE(arr2, \ - PyArray_NDIM(arr2)-1))); \ + stride1 = (size1 == 1 ? 0 : ((PyArray_NDIM(arr1) == 1) ? \ + PyArray_STRIDE(arr1, 0) : \ + PyArray_ITEMSIZE(arr1))); \ + stride2 = (size2 == 1 ? 0 : ((PyArray_NDIM(arr2) == 1) ? \ + PyArray_STRIDE(arr2, 0) : \ + PyArray_ITEMSIZE(arr2))); \ } #define PyArray_TRIVIALLY_ITERABLE_TRIPLE(arr1, arr2, arr3) (\ @@ -620,21 +616,15 @@ PyArray_PrepareThreeRawArrayIter(int ndim, npy_intp *shape, data1 = PyArray_BYTES(arr1); \ data2 = PyArray_BYTES(arr2); \ data3 = PyArray_BYTES(arr3); \ - stride1 = (size1 == 1 ? 0 : \ - (PyArray_CHKFLAGS(arr1, NPY_ARRAY_F_CONTIGUOUS) ? \ - PyArray_STRIDE(arr1, 0) : \ - PyArray_STRIDE(arr1, \ - PyArray_NDIM(arr1)-1))); \ - stride2 = (size2 == 1 ? 0 : \ - (PyArray_CHKFLAGS(arr2, NPY_ARRAY_F_CONTIGUOUS) ? \ - PyArray_STRIDE(arr2, 0) : \ - PyArray_STRIDE(arr2, \ - PyArray_NDIM(arr2)-1))); \ - stride3 = (size3 == 1 ? 0 : \ - (PyArray_CHKFLAGS(arr3, NPY_ARRAY_F_CONTIGUOUS) ? \ - PyArray_STRIDE(arr3, 0) : \ - PyArray_STRIDE(arr3, \ - PyArray_NDIM(arr3)-1))); \ + stride1 = (size1 == 1 ? 0 : ((PyArray_NDIM(arr1) == 1) ? \ + PyArray_STRIDE(arr1, 0) : \ + PyArray_ITEMSIZE(arr1))); \ + stride2 = (size2 == 1 ? 0 : ((PyArray_NDIM(arr2) == 1) ? \ + PyArray_STRIDE(arr2, 0) : \ + PyArray_ITEMSIZE(arr2))); \ + stride3 = (size3 == 1 ? 0 : ((PyArray_NDIM(arr3) == 1) ? \ + PyArray_STRIDE(arr3, 0) : \ + PyArray_ITEMSIZE(arr3))); \ } #endif diff --git a/numpy/core/src/umath/reduction.c b/numpy/core/src/umath/reduction.c index 529d5523a..444682d57 100644 --- a/numpy/core/src/umath/reduction.c +++ b/numpy/core/src/umath/reduction.c @@ -51,7 +51,7 @@ allocate_reduce_result(PyArrayObject *arr, npy_bool *axis_flags, Py_INCREF(dtype); } - PyArray_CreateSortedStridePerm(PyArray_NDIM(arr), PyArray_SHAPE(arr), + PyArray_CreateSortedStridePerm(PyArray_NDIM(arr), PyArray_STRIDES(arr), strideperm); /* Build the new strides and shape */ diff --git a/numpy/core/tests/test_api.py b/numpy/core/tests/test_api.py index 3c365992b..df26dd07a 100644 --- a/numpy/core/tests/test_api.py +++ b/numpy/core/tests/test_api.py @@ -138,9 +138,9 @@ def test_copyto(): assert_raises(TypeError, np.copyto, [1,2,3], [2,3,4]) def test_copy_order(): - a = np.arange(24).reshape(2,3,4) + a = np.arange(24).reshape(2,1,3,4) b = a.copy(order='F') - c = np.arange(24).reshape(2,4,3).swapaxes(1,2) + c = np.arange(24).reshape(2,1,4,3).swapaxes(2,3) def check_copy_result(x, y, ccontig, fcontig, strides=False): assert_(not (x is y)) @@ -202,5 +202,37 @@ def test_copy_order(): res = np.copy(c, order='K') check_copy_result(res, c, ccontig=False, fcontig=False, strides=True) +def test_contiguous_flags(): + a = np.ones((4,4,1))[::2,:,:] + 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) + check_contig(np.empty((2,2,0,2,2)), True, True) + check_contig(np.array([[[1],[2]]], order='F'), True, 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) + + # 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) + + # Test ravel and squeeze. + check_contig(a.ravel(), True, True) + check_contig(np.ones((1,3,1)).squeeze(), True, True) + if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 8056c2cfc..f46a7ddcf 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -61,6 +61,16 @@ class TestRegression(TestCase): np.zeros([3], order='C') np.zeros([3], int, order='C') + def test_asarray_with_order(self,level=rlevel): + """Check that nothing is done when order='F' and array C/F-contiguous""" + a = np.ones(2) + assert_(a is np.asarray(a, order='F')) + + def test_ravel_with_order(self,level=rlevel): + """Check that ravel works when order='F' and array C/F-contiguous""" + a = np.ones(2) + assert_(not a.ravel('F').flags.owndata) + def test_sort_bigendian(self,level=rlevel): """Ticket #47""" a = np.linspace(0, 10, 11) |