summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/include/numpy/ndarraytypes.h7
-rw-r--r--numpy/core/numeric.py4
-rw-r--r--numpy/core/src/multiarray/convert.c4
-rw-r--r--numpy/core/src/multiarray/ctors.c41
-rw-r--r--numpy/core/src/multiarray/dtype_transfer.c6
-rw-r--r--numpy/core/src/multiarray/flagsobject.c100
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c18
-rw-r--r--numpy/core/src/multiarray/shape.c53
-rw-r--r--numpy/core/src/private/lowlevel_strided_loops.h46
-rw-r--r--numpy/core/src/umath/reduction.c2
-rw-r--r--numpy/core/tests/test_api.py36
-rw-r--r--numpy/core/tests/test_regression.py10
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)