Commit 6d41b480 authored by Mark Florisson's avatar Mark Florisson

Error checking for NULL strides + tests

parent a6610e7a
......@@ -207,9 +207,10 @@ static int __Pyx_ValidateAndInit_memviewslice(
goto fail;
}
for(i=0; i<ndim; i++) {
for (i = 0; i < ndim; i++) {
spec = axes_specs[i];
if (buf->strides) {
if (spec & __Pyx_MEMVIEW_CONTIG) {
if (spec & (__Pyx_MEMVIEW_PTR|__Pyx_MEMVIEW_FULL)) {
if (buf->strides[i] != sizeof(void *)) {
......@@ -234,6 +235,23 @@ static int __Pyx_ValidateAndInit_memviewslice(
goto fail;
}
}
} else {
if (spec & __Pyx_MEMVIEW_CONTIG && i != ndim - 1) {
PyErr_Format(PyExc_ValueError,
"C-contiguous buffer is not contiguous in "
"dimension %d", i);
goto fail;
} else if (spec & (__Pyx_MEMVIEW_PTR)) {
PyErr_Format(PyExc_ValueError,
"C-contiguous buffer is not indirect in "
"dimension %d", i);
goto fail;
} else if (buf->suboffsets) {
PyErr_SetString(PyExc_ValueError,
"Buffer exposes suboffsets but no strides");
goto fail;
}
}
/* Todo: without PyBUF_INDIRECT we may not have suboffset information, i.e., the
ptr may not be set to NULL but may be uninitialized? */
......@@ -254,10 +272,11 @@ static int __Pyx_ValidateAndInit_memviewslice(
}
}
if (buf->strides) {
if (c_or_f_flag & __Pyx_IS_F_CONTIG) {
Py_ssize_t stride = 1;
for(i=0; i<ndim; i++) {
if(stride * buf->itemsize != buf->strides[i]) {
for (i=0; i<ndim; i++) {
if (stride * buf->itemsize != buf->strides[i]) {
PyErr_SetString(PyExc_ValueError,
"Buffer not fortran contiguous.");
goto fail;
......@@ -266,7 +285,7 @@ static int __Pyx_ValidateAndInit_memviewslice(
}
} else if (c_or_f_flag & __Pyx_IS_C_CONTIG) {
Py_ssize_t stride = 1;
for(i=ndim-1; i>-1; i--) {
for (i = ndim-1; i>-1; i--) {
if(stride * buf->itemsize != buf->strides[i]) {
PyErr_SetString(PyExc_ValueError,
"Buffer not C contiguous.");
......@@ -275,6 +294,7 @@ static int __Pyx_ValidateAndInit_memviewslice(
stride = stride * buf->shape[i];
}
}
}
if (unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice,
new_memview != NULL) == -1)) {
......
......@@ -10,6 +10,7 @@ import sys
cimport numpy as np
import numpy as np
cimport cython
from cython cimport view
include "cythonarrayutil.pxi"
include "../buffers/mockbuffers.pxi"
......@@ -568,3 +569,102 @@ def test_struct_attributes():
print array[0]['attrib1']
print array[0]['attrib2']
print chr(array[0]['attrib3']['c'][0][0])
#
### Test for NULL strides (C contiguous buffers)
#
cdef getbuffer(Buffer self, Py_buffer *info):
info.buf = &self.m[0, 0]
info.len = 10 * 20
info.ndim = 2
info.shape = self._shape
info.strides = NULL
info.suboffsets = NULL
info.itemsize = 4
info.readonly = 0
self.format = b"f"
info.format = self.format
cdef class Buffer(object):
cdef Py_ssize_t _shape[2]
cdef bytes format
cdef float[:, :] m
cdef object shape, strides
def __init__(self):
a = np.arange(200, dtype=np.float32).reshape(10, 20)
self.m = a
self.shape = a.shape
self.strides = a.strides
self._shape[0] = 10
self._shape[1] = 20
def __getbuffer__(self, Py_buffer *info, int flags):
getbuffer(self, info)
cdef class SuboffsetsNoStridesBuffer(Buffer):
def __getbuffer__(self, Py_buffer *info, int flags):
getbuffer(self, info)
info.suboffsets = self._shape
@testcase
def test_null_strides(Buffer buffer_obj):
"""
>>> test_null_strides(Buffer())
"""
cdef float[:, :] m1 = buffer_obj
cdef float[:, ::1] m2 = buffer_obj
cdef float[:, ::view.contiguous] m3 = buffer_obj
assert (<object> m1).strides == buffer_obj.strides
assert (<object> m2).strides == buffer_obj.strides, ((<object> m2).strides, buffer_obj.strides)
assert (<object> m3).strides == buffer_obj.strides
cdef int i, j
for i in range(m1.shape[0]):
for j in range(m1.shape[1]):
assert m1[i, j] == buffer_obj.m[i, j]
assert m2[i, j] == buffer_obj.m[i, j], (i, j, m2[i, j], buffer_obj.m[i, j])
assert m3[i, j] == buffer_obj.m[i, j]
@testcase
def test_null_strides_error(buffer_obj):
"""
>>> test_null_strides_error(Buffer())
C-contiguous buffer is not indirect in dimension 1
C-contiguous buffer is not indirect in dimension 0
C-contiguous buffer is not contiguous in dimension 0
C-contiguous buffer is not contiguous in dimension 0
>>> test_null_strides_error(SuboffsetsNoStridesBuffer())
Traceback (most recent call last):
...
ValueError: Buffer exposes suboffsets but no strides
"""
# valid
cdef float[::view.generic, ::view.generic] full_buf = buffer_obj
# invalid
cdef float[:, ::view.indirect] indirect_buf1
cdef float[::view.indirect, :] indirect_buf2
cdef float[::1, :] fortran_buf1
cdef float[::view.contiguous, :] fortran_buf2
try:
indirect_buf1 = buffer_obj
except ValueError, e:
print e
try:
indirect_buf2 = buffer_obj
except ValueError, e:
print e
try:
fortran_buf1 = buffer_obj
except ValueError, e:
print e
try:
fortran_buf2 = buffer_obj
except ValueError, e:
print e
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment