diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2014-10-26 09:09:31 -0700 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2014-10-26 09:09:31 -0700 |
commit | 256d256b865d42eace7d3b8a7e4cae7745fb9a2e (patch) | |
tree | c648c32404eaf6aeb5b4742a50b66e997f3b0deb /numpy/core | |
parent | fb40fe8618ff472d09ae819fd9734bd94cb9bdc9 (diff) | |
parent | 7d1cb081c8677c5939995b700ab0ee34d5d0e154 (diff) | |
download | numpy-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.c | 29 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 27 |
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): |