Commit 8bda5665 authored by Kurt Smith's avatar Kurt Smith Committed by Mark Florisson

moved memoryview initialization function from CythonUtilCode to pure C

parent 6343a2fb
......@@ -257,12 +257,6 @@ cdef full = Enum("<full axis access mode>")
cdef extern from *:
int __Pyx_GetBuffer(object, Py_buffer *, int)
void __Pyx_ReleaseBuffer(Py_buffer *)
void __Pyx_XDECREF(object)
void __Pyx_DECREF(object)
void __Pyx_GIVEREF(object)
void __Pyx_INCREF(object)
void __Pyx_GOTREF(object)
cdef class memoryview(object):
......@@ -277,145 +271,7 @@ cdef class memoryview(object):
cdef memoryview memoryview_cwrapper(object o, int flags):
return memoryview(o, flags)
# XXX: put in #defines...
DEF BUF_MAX_NDIMS = %d
DEF __Pyx_MEMVIEW_DIRECT = 1
DEF __Pyx_MEMVIEW_PTR = 2
DEF __Pyx_MEMVIEW_FULL = 4
DEF __Pyx_MEMVIEW_CONTIG = 8
DEF __Pyx_MEMVIEW_STRIDED = 16
DEF __Pyx_MEMVIEW_FOLLOW = 32
cdef extern from *:
struct __pyx_obj_memoryview:
Py_buffer view
ctypedef struct __Pyx_mv_DimInfo:
Py_ssize_t shape, strides, suboffsets
ctypedef struct __Pyx_memviewslice:
__pyx_obj_memoryview *memview
char *data
__Pyx_mv_DimInfo diminfo[BUF_MAX_NDIMS]
cdef is_cf_contig(int *specs, int ndim):
is_c_contig = is_f_contig = False
# c_contiguous: 'follow', 'follow', ..., 'follow', 'contig'
if specs[ndim-1] & __Pyx_MEMVIEW_CONTIG:
for i in range(0, ndim-1):
if not (specs[i] & __Pyx_MEMVIEW_FOLLOW):
break
else:
is_c_contig = True
# f_contiguous: 'contig', 'follow', 'follow', ..., 'follow'
elif ndim > 1 and (specs[0] & __Pyx_MEMVIEW_CONTIG):
for i in range(1, ndim):
if not (specs[i] & __Pyx_MEMVIEW_FOLLOW):
break
else:
is_f_contig = True
return is_c_contig, is_f_contig
cdef bint DEBUG = 0
cdef object init_memviewslice_from_memview(
memoryview memview,
int *axes_specs,
int ndim,
Py_ssize_t itemsize,
char *format,
__Pyx_memviewslice *memviewslice):
if memviewslice.data or memviewslice.memview:
raise ValueError("memviewslice must be empty and initialized to NULL.")
cdef int i
if ndim > BUF_MAX_NDIMS:
raise ValueError("number of dimensions exceed maximum of" + str(BUF_MAX_NDIMS))
cdef Py_buffer pybuf = memview.view
if pybuf.ndim != ndim:
raise ValueError("incompatible number of dimensions.")
if DEBUG: print pybuf.ndim
cdef str pyx_format = pybuf.format
cdef str view_format = format
if pyx_format != view_format:
raise ValueError("Buffer and memoryview datatype formats do not match.")
if DEBUG: print pybuf.format
if itemsize != pybuf.itemsize:
raise ValueError("Buffer and memoryview itemsize do not match.")
if DEBUG: print pybuf.itemsize
if not pybuf.strides:
raise ValueError("no stride information provided.")
has_suboffsets = True
if not pybuf.suboffsets:
has_suboffsets = False
is_c_contig, is_f_contig = is_cf_contig(axes_specs, ndim)
cdef int spec = 0
for i in range(ndim):
istr = str(i)
spec = axes_specs[i]
if spec & __Pyx_MEMVIEW_CONTIG:
if pybuf.strides[i] != 1:
raise ValueError("Dimension "+istr+" in axes specification is incompatible with buffer.")
if spec & (__Pyx_MEMVIEW_STRIDED | __Pyx_MEMVIEW_FOLLOW):
if pybuf.strides[i] <= 1:
raise ValueError("Dimension "+istr+" in axes specification is incompatible with buffer.")
if spec & __Pyx_MEMVIEW_DIRECT:
if has_suboffsets and pybuf.suboffsets[i] >= 0:
raise ValueError("Dimension "+istr+" in axes specification is incompatible with buffer.")
if spec & (__Pyx_MEMVIEW_PTR | __Pyx_MEMVIEW_FULL):
if not has_suboffsets:
raise ValueError("Buffer object does not provide suboffsets.")
if spec & __Pyx_MEMVIEW_PTR:
if pybuf.suboffsets[i] < 0:
raise ValueError("Buffer object suboffset in dimension "+istr+"must be >= 0.")
if is_f_contig:
idx = 0; stride = 1
for i in range(ndim):
if stride != pybuf.strides[i]:
raise ValueError("Buffer object not fortran contiguous.")
stride = stride * pybuf.shape[i]
elif is_c_contig:
idx = ndim-1; stride = 1
for i in range(ndim-1,-1,-1):
if stride != pybuf.strides[i]:
raise ValueError("Buffer object not C contiguous.")
stride = stride * pybuf.shape[i]
if DEBUG: print "pybuf.len", pybuf.len
for i in range(ndim):
memviewslice.diminfo[i].strides = pybuf.strides[i]
memviewslice.diminfo[i].shape = pybuf.shape[i]
if DEBUG: print 'pybuf.shape', pybuf.shape[i]
if DEBUG: print 'pybuf.strides', pybuf.strides[i]
if has_suboffsets:
if DEBUG: print 'pybuf.suboffsets', pybuf.suboffsets[i]
memviewslice.diminfo[i].suboffsets = pybuf.suboffsets[i]
__Pyx_INCREF(<object>memview)
__Pyx_GIVEREF(<object>memview)
memviewslice.memview = <__pyx_obj_memoryview*>memview
memviewslice.data = <char *>pybuf.buf
""" % Options.buffer_max_dims, name="foobar", prefix="__pyx_viewaxis_")
""", name="view_code", prefix="__pyx_viewaxis_")
cyarray_prefix = u'__pyx_cythonarray_'
cython_array_utility_code = CythonUtilityCode(u'''
......
......@@ -7597,12 +7597,13 @@ class CoerceToMemViewSliceNode(CoercionNode):
self.is_temp = 1
def generate_result_code(self, code):
import MemoryView
import MemoryView, Buffer
memviewobj = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
buf_flag = MemoryView.get_buf_flag(self.type.axes)
code.putln("%s = (PyObject *)"
"__pyx_viewaxis_memoryview_cwrapper(%s, %s);" %\
(memviewobj, self.arg.py_result(), buf_flag))
code.putln(code.error_goto_if_null(memviewobj, self.pos))
ndim = len(self.type.axes)
spec_int_arr = code.funcstate.allocate_temp(
PyrexTypes.c_array_type(PyrexTypes.c_int_type, ndim),
......@@ -7611,12 +7612,29 @@ class CoerceToMemViewSliceNode(CoercionNode):
for idx, cspec in enumerate(specs_code):
code.putln("%s[%d] = %s;" % (spec_int_arr, idx, cspec))
itemsize = self.type.dtype.sign_and_name()
format = MemoryView.format_from_type(self.type.dtype)
code.globalstate.use_utility_code(Buffer.acquire_utility_code)
code.globalstate.use_utility_code(MemoryView.memviewslice_init_code)
dtype_typeinfo = Buffer.get_type_information_cname(code, self.type.dtype)
MemoryView.put_init_entry(self.result(), code)
code.putln("__pyx_viewaxis_init_memviewslice_from_memview"
"((struct __pyx_obj_memoryview *)%s, %s, %d, sizeof(%s), \"%s\", &%s);" %\
(memviewobj, spec_int_arr, ndim, itemsize, format, self.result()))
code.put_gotref(code.as_pyobject("%s.memview" % self.result(), cython_memoryview_ptr_type))
code.putln("{")
code.putln("__Pyx_BufFmt_StackElem __pyx_stack[%d];" %
self.type.dtype.struct_nesting_depth())
result = self.result()
if self.type.is_c_contig:
c_or_f_flag = "__Pyx_IS_C_CONTIG"
elif self.type.is_f_contig:
c_or_f_flag = "__Pyx_IS_F_CONTIG"
else:
c_or_f_flag = "0"
code.putln(code.error_goto_if("-1 == __Pyx_ValidateAndInit_memviewslice("
"(struct __pyx_obj_memoryview *) %(memviewobj)s,"
" %(spec_int_arr)s, %(c_or_f_flag)s, %(ndim)d,"
" &%(dtype_typeinfo)s, __pyx_stack, &%(result)s)" % locals(), self.pos))
code.putln("}")
code.put_gotref(
code.as_pyobject("%s.memview" % self.result(), cython_memoryview_ptr_type))
code.funcstate.release_temp(memviewobj)
code.funcstate.release_temp(spec_int_arr)
......
......@@ -434,3 +434,197 @@ typedef struct {
Options.buffer_max_dims,
memviewslice_cname)
)
memviewslice_init_code = UtilityCode(proto="""\
#define __Pyx_BUF_MAX_NDIMS %(BUF_MAX_NDIMS)d
#define __Pyx_MEMVIEW_DIRECT 1
#define __Pyx_MEMVIEW_PTR 2
#define __Pyx_MEMVIEW_FULL 4
#define __Pyx_MEMVIEW_CONTIG 8
#define __Pyx_MEMVIEW_STRIDED 16
#define __Pyx_MEMVIEW_FOLLOW 32
#define __Pyx_IS_C_CONTIG 1
#define __Pyx_IS_F_CONTIG 2
static int __Pyx_ValidateAndInit_memviewslice(struct __pyx_obj_memoryview *memview,
int *axes_specs, int c_or_f_flag, int ndim, __Pyx_TypeInfo *dtype,
__Pyx_BufFmt_StackElem stack[], __Pyx_memviewslice *memviewslice);
static int __Pyx_init_memviewslice(
struct __pyx_obj_memoryview *memview,
int ndim,
__Pyx_memviewslice *memviewslice);
""" % {'BUF_MAX_NDIMS' :Options.buffer_max_dims},
impl = """\
static int __Pyx_ValidateAndInit_memviewslice(
struct __pyx_obj_memoryview *memview,
int *axes_specs,
int c_or_f_flag,
int ndim,
__Pyx_TypeInfo *dtype,
__Pyx_BufFmt_StackElem stack[],
__Pyx_memviewslice *memviewslice) {
__Pyx_SetupRefcountContext("ValidateAndInit_memviewslice");
Py_buffer *buf = &memview->view;
int stride, i, spec = 0, retval = -1;
if (!buf) goto fail;
if(memviewslice->data || memviewslice->memview) {
PyErr_SetString(PyExc_ValueError,
"memoryviewslice struct must be initialized to NULL.");
goto fail;
}
if (buf->ndim != ndim) {
PyErr_Format(PyExc_ValueError,
"Buffer has wrong number of dimensions (expected %d, got %d)",
ndim, buf->ndim);
goto fail;
}
__Pyx_BufFmt_Context ctx;
__Pyx_BufFmt_Init(&ctx, stack, dtype);
if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail;
if ((unsigned)buf->itemsize != dtype->size) {
PyErr_Format(PyExc_ValueError,
"Item size of buffer (%"PY_FORMAT_SIZE_T"d byte%s) does not match size of '%s' (%"PY_FORMAT_SIZE_T"d byte%s)",
buf->itemsize, (buf->itemsize > 1) ? "s" : "",
dtype->name,
dtype->size, (dtype->size > 1) ? "s" : "");
goto fail;
}
if (!buf->strides) {
PyErr_SetString(PyExc_ValueError,
"buffer does not supply strides necessary for memoryview.");
goto fail;
}
for(i=0; i<ndim; i++) {
spec = axes_specs[i];
if (spec & __Pyx_MEMVIEW_CONTIG) {
if (buf->strides[i] != buf->itemsize) {
PyErr_SetString(PyExc_ValueError,
"Buffer and memoryview are not contiguous in the same dimension.");
goto fail;
}
}
if (spec & (__Pyx_MEMVIEW_STRIDED | __Pyx_MEMVIEW_FOLLOW)) {
if (buf->strides[i] <= buf->itemsize) {
PyErr_SetString(PyExc_ValueError,
"Buffer and memoryview are not contiguous in the same dimension.");
goto fail;
}
}
if (spec & __Pyx_MEMVIEW_DIRECT) {
if (buf->suboffsets && buf->suboffsets[i] >= 0) {
PyErr_SetString(PyExc_ValueError,
"Buffer not compatible with direct access.");
goto fail;
}
}
if (spec & (__Pyx_MEMVIEW_PTR | __Pyx_MEMVIEW_FULL)) {
if (!buf->suboffsets) {
PyErr_SetString(PyExc_ValueError,
"Buffer not able to be indirectly accessed.");
goto fail;
}
}
if (spec & __Pyx_MEMVIEW_PTR) {
if (buf->suboffsets[i] < 0) {
PyErr_Format(PyExc_ValueError,
"Buffer not indirectly accessed in %d dimension, although memoryview is.", i);
goto fail;
}
}
}
if (c_or_f_flag & __Pyx_IS_F_CONTIG) {
stride = 1;
for(i=0; i<ndim; i++) {
if(stride * buf->itemsize != buf->strides[i]) {
PyErr_SetString(PyExc_ValueError,
"Buffer not fortran contiguous.");
goto fail;
}
stride = stride * buf->shape[i];
}
} else if (c_or_f_flag & __Pyx_IS_F_CONTIG) {
for(i=ndim-1; i>-1; i--) {
if(stride * buf->itemsize != buf->strides[i]) {
PyErr_SetString(PyExc_ValueError,
"Buffer not C contiguous.");
goto fail;
}
stride = stride * buf->shape[i];
}
}
if(unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice) == -1)) {
goto fail;
}
retval = 0;
goto no_fail;
fail:
__Pyx_XDECREF(memviewslice->memview);
memviewslice->memview = 0;
memviewslice->data = 0;
retval = -1;
no_fail:
__Pyx_FinishRefcountContext();
return retval;
}
static int __Pyx_init_memviewslice(
struct __pyx_obj_memoryview *memview,
int ndim,
__Pyx_memviewslice *memviewslice) {
__Pyx_SetupRefcountContext("init_memviewslice");
int i, retval=-1;
Py_buffer *buf = &memview->view;
if(!buf || memviewslice->memview || memviewslice->data) {
goto fail;
}
for(i=0; i<ndim; i++) {
memviewslice->diminfo[i].strides = buf->strides[i];
memviewslice->diminfo[i].shape = buf->shape[i];
if(buf->suboffsets) {
memviewslice->diminfo[i].suboffsets = buf->suboffsets[i];
}
}
__Pyx_INCREF((PyObject *)memview);
__Pyx_GIVEREF((PyObject *)memview);
memviewslice->memview = memview;
memviewslice->data = (char *)buf->buf;
retval = 0;
goto no_fail;
fail:
__Pyx_XDECREF(memviewslice->memview);
memviewslice->memview = 0;
memviewslice->data = 0;
retval = -1;
no_fail:
__Pyx_FinishRefcountContext();
return retval;
}
""")
memviewslice_init_code.requires = [memviewslice_declare_code]
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