summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2014-10-26 09:09:31 -0700
committerCharles Harris <charlesr.harris@gmail.com>2014-10-26 09:09:31 -0700
commit256d256b865d42eace7d3b8a7e4cae7745fb9a2e (patch)
treec648c32404eaf6aeb5b4742a50b66e997f3b0deb /numpy/core
parentfb40fe8618ff472d09ae819fd9734bd94cb9bdc9 (diff)
parent7d1cb081c8677c5939995b700ab0ee34d5d0e154 (diff)
downloadnumpy-256d256b865d42eace7d3b8a7e4cae7745fb9a2e.tar.gz
Merge pull request #5086 from mdboom/stride-fix
Fix how strides is set on Py_buffer object when the array is C-contiguous
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/src/multiarray/buffer.c29
-rw-r--r--numpy/core/tests/test_multiarray.py27
2 files changed, 54 insertions, 2 deletions
diff --git a/numpy/core/src/multiarray/buffer.c b/numpy/core/src/multiarray/buffer.c
index 6ba98d1cd..7f7607e1f 100644
--- a/numpy/core/src/multiarray/buffer.c
+++ b/numpy/core/src/multiarray/buffer.c
@@ -629,6 +629,8 @@ array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
{
PyArrayObject *self;
_buffer_info_t *info = NULL;
+ int i;
+ Py_ssize_t sd;
self = (PyArrayObject*)obj;
@@ -703,6 +705,31 @@ array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
}
if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
view->strides = info->strides;
+
+#ifdef NPY_RELAXED_STRIDES_CHECKING
+ /*
+ * If NPY_RELAXED_STRIDES_CHECKING is on, the array may be
+ * contiguous, but it won't look that way to Python when it
+ * tries to determine contiguity by looking at the strides
+ * (since one of the elements may be -1). In that case, just
+ * regenerate strides from shape.
+ */
+ if (PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS) &&
+ !((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)) {
+ sd = view->itemsize;
+ for (i = view->ndim-1; i >= 0; --i) {
+ view->strides[i] = sd;
+ sd *= view->shape[i];
+ }
+ }
+ else if (PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) {
+ sd = view->itemsize;
+ for (i = 0; i < view->ndim; ++i) {
+ view->strides[i] = sd;
+ sd *= view->shape[i];
+ }
+ }
+#endif
}
else {
view->strides = NULL;
@@ -922,7 +949,7 @@ _descriptor_from_pep3118_format_fast(char *s, PyObject **result)
*result = (PyObject*)PyArray_DescrNewByteorder(descr, byte_order);
Py_DECREF(descr);
}
-
+
return 1;
}
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 6cbe36f03..d6f98e0b7 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -1921,7 +1921,7 @@ class TestMethods(TestCase):
a = np.array([1-1j, 1, 2.0, 'f'], object)
assert_raises(AttributeError, lambda: a.conj())
- assert_raises(AttributeError, lambda: a.conjugate())
+ assert_raises(AttributeError, lambda: a.conjugate())
class TestBinop(object):
@@ -4316,6 +4316,31 @@ class TestNewBufferProtocol(object):
x3 = np.arange(dt3.itemsize, dtype=np.int8).view(dt3)
self._check_roundtrip(x3)
+ def test_relaxed_strides(self):
+ # Test that relaxed strides are converted to non-relaxed
+ c = np.ones((1, 10, 10), dtype='i8')
+
+ # Check for NPY_RELAXED_STRIDES_CHECKING:
+ if np.ones((10, 1), order="C").flags.f_contiguous:
+ c.strides = (-1, 80, 8)
+
+ assert memoryview(c).strides == (800, 80, 8)
+
+ # Writing C-contiguous data to a BytesIO buffer should work
+ fd = io.BytesIO()
+ fd.write(c.data)
+
+ fortran = c.T
+ assert memoryview(fortran).strides == (8, 80, 800)
+
+ arr = np.ones((1, 10))
+ if arr.flags.f_contiguous:
+ shape, strides = get_buffer_info(arr, ['F_CONTIGUOUS'])
+ assert_(strides[0] == 8)
+ arr = np.ones((10, 1), order='F')
+ shape, strides = get_buffer_info(arr, ['C_CONTIGUOUS'])
+ assert_(strides[-1] == 8)
+
class TestArrayAttributeDeletion(object):