Commit b5009ce5 authored by Mark Florisson's avatar Mark Florisson

Compare memoryview type pointers directly when coercing from memoryview to memoryview slice

parent 721f6ecd
......@@ -784,11 +784,14 @@ impl = """
""")
raise_buffer_fallback_code = load_buffer_utility("BufferFallbackError")
buffer_structs_code = load_buffer_utility("BufferFormatStructs")
buffer_structs_code = load_buffer_utility(
"BufferFormatStructs", proto_block='utility_code_proto_before_types')
acquire_utility_code = load_buffer_utility("BufferFormatCheck",
context=context,
requires=[buffer_structs_code])
# See utility code BufferFormatFromTypeInfo
_typeinfo_to_format_code = load_buffer_utility(
"TypeInfoToFormat", context={}, requires=[buffer_structs_code])
_typeinfo_to_format_code = load_buffer_utility("TypeInfoToFormat", context={},
requires=[buffer_structs_code])
typeinfo_compare_code = load_buffer_utility("TypeInfoCompare", context={},
requires=[buffer_structs_code])
\ No newline at end of file
......@@ -897,7 +897,8 @@ memviewslice_init_code = load_memview_c_utility(
context=dict(context, BUF_MAX_NDIMS=Options.buffer_max_dims),
requires=[memviewslice_declare_code,
Buffer.acquire_utility_code,
atomic_utility],
atomic_utility,
Buffer.typeinfo_compare_code],
)
memviewslice_index_helpers = load_memview_c_utility("MemviewSliceIndex")
......
......@@ -710,6 +710,63 @@ static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
__Pyx_ReleaseBuffer(info);
}
/////////////// TypeInfoCompare.proto ///////////////
static int __pyx_typeinfo_cmp(__Pyx_TypeInfo *a, __Pyx_TypeInfo *b);
/////////////// TypeInfoCompare ///////////////
/* See if two dtypes are equal */
static int
__pyx_typeinfo_cmp(__Pyx_TypeInfo *a, __Pyx_TypeInfo *b)
{
int i;
if (!a || !b)
return 0;
if (a == b)
return 1;
if (a->size != b->size || a->typegroup != b->typegroup ||
a->is_unsigned != b->is_unsigned || a->ndim != b->ndim)
return 0;
if (a->ndim) {
/* Verify multidimensional C arrays */
for (i = 0; i < a->ndim; i++)
if (a->arraysize[i] != b->arraysize[i])
return 0;
}
if (a->typegroup == 'S') {
/* Check for packed struct */
if (a->flags != b->flags)
return 0;
/* compare all struct fields */
if (a->fields || b->fields) {
/* Check if both have fields */
if (!(a->fields && b->fields))
return 0;
/* compare */
for (i = 0; a->fields[i].type && b->fields[i].type; i++) {
__Pyx_StructField *field_a = a->fields + i;
__Pyx_StructField *field_b = b->fields + i;
if (field_a->offset != field_b->offset ||
!__pyx_typeinfo_cmp(field_a->type, field_b->type))
return 0;
}
/* If all fields are processed, we have a match */
return !a->fields[i].type && !b->fields[i].type;
}
}
return 1;
}
/////////////// TypeInfoToFormat.proto ///////////////
struct __pyx_typeinfo_string {
......
......@@ -32,6 +32,7 @@ cdef extern from *:
cdef struct __pyx_memoryview "__pyx_memoryview_obj":
Py_buffer view
PyObject *obj
__Pyx_TypeInfo *typeinfo
ctypedef struct {{memviewslice_name}}:
__pyx_memoryview *memview
......@@ -58,6 +59,10 @@ cdef extern from *:
PyBUF_INDIRECT
PyBUF_RECORDS
ctypedef struct __Pyx_TypeInfo:
pass
cdef extern from *:
ctypedef int __pyx_atomic_int
{{memviewslice_name}} slice_copy_contig "__pyx_memoryview_copy_new_contig"(
......@@ -307,6 +312,7 @@ cdef class memoryview(object):
cdef Py_buffer view
cdef int flags
cdef bint dtype_is_object
cdef __Pyx_TypeInfo *typeinfo
def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False):
self.obj = obj
......@@ -328,7 +334,7 @@ cdef class memoryview(object):
self.acquisition_count_aligned_p = <__pyx_atomic_int *> align_pointer(
<void *> &self.acquisition_count[0], sizeof(__pyx_atomic_int))
self.typeinfo = NULL
def __dealloc__(memoryview self):
if self.obj is not None:
......@@ -601,8 +607,14 @@ cdef class memoryview(object):
@cname('__pyx_memoryview_new')
cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object):
return memoryview(o, flags, dtype_is_object)
cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo):
cdef memoryview result = memoryview(o, flags, dtype_is_object)
result.typeinfo = typeinfo
return result
@cname('__pyx_memoryview_check')
cdef bint memoryview_check(object o):
return isinstance(o, memoryview)
cdef tuple _unellipsify(object index, int ndim):
"""
......@@ -956,6 +968,7 @@ cdef memoryview_fromslice({{memviewslice_name}} *memviewslice,
__PYX_INC_MEMVIEW(memviewslice, 1)
result.from_object = <object> memviewslice.memview.obj
result.typeinfo = memviewslice.memview.typeinfo
result.view = memviewslice.memview.view
result.view.buf = <void *> memviewslice.data
......
......@@ -89,14 +89,21 @@ static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *);
#define __Pyx_IS_C_CONTIG 1
#define __Pyx_IS_F_CONTIG 2
static int __Pyx_ValidateAndInit_memviewslice(struct __pyx_memoryview_obj *memview,
int *axes_specs, int c_or_f_flag, int ndim, __Pyx_TypeInfo *dtype,
__Pyx_BufFmt_StackElem stack[], __Pyx_memviewslice *memviewslice);
static int __Pyx_ValidateAndInit_memviewslice(
int *axes_specs,
int c_or_f_flag,
int buf_flags,
int ndim,
__Pyx_TypeInfo *dtype,
__Pyx_BufFmt_StackElem stack[],
__Pyx_memviewslice *memviewslice,
PyObject *original_obj);
static int __Pyx_init_memviewslice(
struct __pyx_memoryview_obj *memview,
int ndim,
__Pyx_memviewslice *memviewslice);
__Pyx_memviewslice *memviewslice,
int memview_is_new_reference);
static CYTHON_INLINE int __pyx_add_acquisition_count_locked(__pyx_atomic_int *acquisition_count,
PyThread_type_lock lock);
......@@ -116,7 +123,6 @@ static CYTHON_INLINE char *__pyx_memviewslice_index_full(const char *bufp, Py_ss
static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *obj) {
{{memviewslice_name}} result = {{memslice_init}};
struct __pyx_memoryview_obj *memview;
__Pyx_BufFmt_StackElem stack[{{struct_nesting_depth}}];
int axes_specs[] = { {{axes_specs}} };
int retcode;
......@@ -127,19 +133,16 @@ static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *obj) {
return result;
}
memview = (struct __pyx_memoryview_obj *) __pyx_memoryview_new(obj, {{buf_flag}}, 0);
if (unlikely(!memview))
goto __pyx_fail;
retcode = __Pyx_ValidateAndInit_memviewslice(memview, axes_specs,
{{c_or_f_flag}}, {{ndim}}, &{{dtype_typeinfo}}, stack, &result);
retcode = __Pyx_ValidateAndInit_memviewslice(axes_specs, {{c_or_f_flag}},
{{buf_flag}}, {{ndim}},
&{{dtype_typeinfo}}, stack,
&result, obj);
if (unlikely(retcode == -1))
goto __pyx_fail;
return result;
__pyx_fail:
Py_XDECREF(memview);
result.memview = NULL;
result.data = NULL;
return result;
......@@ -148,29 +151,38 @@ __pyx_fail:
////////// MemviewSliceInit //////////
static int __Pyx_ValidateAndInit_memviewslice(
struct __pyx_memoryview_obj *memview,
int *axes_specs,
int c_or_f_flag,
int buf_flags,
int ndim,
__Pyx_TypeInfo *dtype,
__Pyx_BufFmt_StackElem stack[],
__Pyx_memviewslice *memviewslice) {
__Pyx_memviewslice *memviewslice,
PyObject *original_obj)
{
struct __pyx_memoryview_obj *memview, *new_memview;
__Pyx_RefNannyDeclarations
Py_buffer *buf = &memview->view;
Py_buffer *buf;
int stride, i, spec = 0, retval = -1;
__Pyx_BufFmt_Context ctx;
int from_memoryview = __pyx_memoryview_check(original_obj);
__Pyx_RefNannySetupContext("ValidateAndInit_memviewslice");
if (!buf) goto fail;
if(memviewslice->data || memviewslice->memview) {
PyErr_SetString(PyExc_ValueError,
"memoryviewslice struct must be initialized to NULL.");
goto fail;
if (from_memoryview && __pyx_typeinfo_cmp(dtype, ((struct __pyx_memoryview_obj *)
original_obj)->typeinfo)) {
/* We have a matching dtype, skip format parsing */
memview = (struct __pyx_memoryview_obj *) original_obj;
new_memview = NULL;
} else {
memview = (struct __pyx_memoryview_obj *) __pyx_memoryview_new(
original_obj, buf_flags, 0, dtype);
new_memview = memview;
if (unlikely(!memview))
goto fail;
}
buf = &memview->view;
if (buf->ndim != ndim) {
PyErr_Format(PyExc_ValueError,
"Buffer has wrong number of dimensions (expected %d, got %d)",
......@@ -178,8 +190,10 @@ static int __Pyx_ValidateAndInit_memviewslice(
goto fail;
}
__Pyx_BufFmt_Init(&ctx, stack, dtype);
if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail;
if (new_memview) {
__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,
......@@ -267,16 +281,16 @@ static int __Pyx_ValidateAndInit_memviewslice(
}
}
if(unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice) == -1)) {
if (unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice,
new_memview != NULL) == -1)) {
goto fail;
}
retval = 0;
goto no_fail;
fail:
__Pyx_XDECREF(memviewslice->memview);
memviewslice->memview = 0;
memviewslice->data = 0;
Py_XDECREF(new_memview);
retval = -1;
no_fail:
......@@ -287,14 +301,15 @@ no_fail:
static int
__Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview,
int ndim,
{{memviewslice_name}} *memviewslice)
{{memviewslice_name}} *memviewslice,
int memview_is_new_reference)
{
__Pyx_RefNannyDeclarations
int i, retval=-1;
Py_buffer *buf = &memview->view;
__Pyx_RefNannySetupContext("init_memviewslice");
if(!buf) {
if (!buf) {
PyErr_SetString(PyExc_ValueError,
"buf is NULL.");
goto fail;
......@@ -316,12 +331,15 @@ __Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview,
memviewslice->memview = memview;
memviewslice->data = (char *)buf->buf;
__pyx_add_acquisition_count(memview);
if (__pyx_add_acquisition_count(memview) == 0 && !memview_is_new_reference) {
Py_INCREF(memview);
}
retval = 0;
goto no_fail;
fail:
__Pyx_XDECREF(memviewslice->memview);
/* Don't decref, the memoryview may be borrowed. Let the caller do the cleanup */
/* __Pyx_XDECREF(memviewslice->memview); */
memviewslice->memview = 0;
memviewslice->data = 0;
retval = -1;
......@@ -486,12 +504,13 @@ __pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs,
memview_obj = (struct __pyx_memoryview_obj *) __pyx_memoryview_new(
(PyObject *) array_obj, contig_flag,
dtype_is_object);
dtype_is_object,
from_mvs->memview->typeinfo);
if (unlikely(!memview_obj))
goto fail;
/* initialize new_mvs */
if (unlikely(__Pyx_init_memviewslice(memview_obj, ndim, &new_mvs) < 0))
if (unlikely(__Pyx_init_memviewslice(memview_obj, ndim, &new_mvs, 1) < 0))
goto fail;
if (unlikely(__pyx_memoryview_copy_contents(*from_mvs, new_mvs, ndim, ndim,
......
PYTHON setup.py build_ext --inplace
PYTHON -c "import test_compare_type_pointers"
######## setup.py ########
from Cython.Build import cythonize
from distutils.core import setup
setup(
ext_modules = cythonize("*.pyx"),
)
######## test_compare_type_pointers.pyx ########
include "types.pxi"
import other_module
def test_foo_view(Foo[:] m):
return m[0].f
assert test_foo_view(other_module.fooview_obj) == 5.0
def test_double_view(double[:] m):
return m[0]
assert test_double_view(other_module.doubleview_obj) == 6.0
######## other_module.pyx ########
include "types.pxi"
cdef Foo[10] fooarray
cdef Foo[:] fooview = fooarray
fooview_obj = fooview
fooview[0].f = 5.0
cdef double[10] doublearray
cdef double[:] doubleview = doublearray
doubleview_obj = doubleview
doubleview[0] = 6.0
######## types.pxi ########
ctypedef packed struct Baz:
double d
ctypedef struct Bar:
int i
ctypedef struct Foo:
float f
double complex dc
char c
int i
Bar b
char s[20]
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