Index: third_party/cython/src/Cython/Utility/MemoryView_C.c |
diff --git a/third_party/cython/src/Cython/Utility/MemoryView_C.c b/third_party/cython/src/Cython/Utility/MemoryView_C.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ec86220fbac0a18e2a8003686c6fd99f66df125b |
--- /dev/null |
+++ b/third_party/cython/src/Cython/Utility/MemoryView_C.c |
@@ -0,0 +1,938 @@ |
+////////// MemviewSliceStruct.proto ////////// |
+ |
+/* memoryview slice struct */ |
+struct {{memview_struct_name}}; |
+ |
+typedef struct { |
+ struct {{memview_struct_name}} *memview; |
+ char *data; |
+ Py_ssize_t shape[{{max_dims}}]; |
+ Py_ssize_t strides[{{max_dims}}]; |
+ Py_ssize_t suboffsets[{{max_dims}}]; |
+} {{memviewslice_name}}; |
+ |
+ |
+/////////// Atomics.proto ///////////// |
+ |
+#include <pythread.h> |
+ |
+#ifndef CYTHON_ATOMICS |
+ #define CYTHON_ATOMICS 1 |
+#endif |
+ |
+#define __pyx_atomic_int_type int |
+// todo: Portland pgcc, maybe OS X's OSAtomicIncrement32, |
+// libatomic + autotools-like distutils support? Such a pain... |
+#if CYTHON_ATOMICS && __GNUC__ >= 4 && (__GNUC_MINOR__ > 1 || \ |
+ (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL >= 2)) && \ |
+ !defined(__i386__) |
+ /* gcc >= 4.1.2 */ |
+ #define __pyx_atomic_incr_aligned(value, lock) __sync_fetch_and_add(value, 1) |
+ #define __pyx_atomic_decr_aligned(value, lock) __sync_fetch_and_sub(value, 1) |
+ |
+ #ifdef __PYX_DEBUG_ATOMICS |
+ #warning "Using GNU atomics" |
+ #endif |
+#elif CYTHON_ATOMICS && MSC_VER |
+ /* msvc */ |
+ #include <Windows.h> |
+ #define __pyx_atomic_int_type LONG |
+ #define __pyx_atomic_incr_aligned(value, lock) InterlockedIncrement(value) |
+ #define __pyx_atomic_decr_aligned(value, lock) InterlockedDecrement(value) |
+ |
+ #ifdef __PYX_DEBUG_ATOMICS |
+ #warning "Using MSVC atomics" |
+ #endif |
+#elif CYTHON_ATOMICS && (defined(__ICC) || defined(__INTEL_COMPILER)) && 0 |
+ #define __pyx_atomic_incr_aligned(value, lock) _InterlockedIncrement(value) |
+ #define __pyx_atomic_decr_aligned(value, lock) _InterlockedDecrement(value) |
+ |
+ #ifdef __PYX_DEBUG_ATOMICS |
+ #warning "Using Intel atomics" |
+ #endif |
+#else |
+ #undef CYTHON_ATOMICS |
+ #define CYTHON_ATOMICS 0 |
+ |
+ #ifdef __PYX_DEBUG_ATOMICS |
+ #warning "Not using atomics" |
+ #endif |
+#endif |
+ |
+typedef volatile __pyx_atomic_int_type __pyx_atomic_int; |
+ |
+#if CYTHON_ATOMICS |
+ #define __pyx_add_acquisition_count(memview) \ |
+ __pyx_atomic_incr_aligned(__pyx_get_slice_count_pointer(memview), memview->lock) |
+ #define __pyx_sub_acquisition_count(memview) \ |
+ __pyx_atomic_decr_aligned(__pyx_get_slice_count_pointer(memview), memview->lock) |
+#else |
+ #define __pyx_add_acquisition_count(memview) \ |
+ __pyx_add_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock) |
+ #define __pyx_sub_acquisition_count(memview) \ |
+ __pyx_sub_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock) |
+#endif |
+ |
+ |
+/////////////// ObjectToMemviewSlice.proto /////////////// |
+ |
+static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *); |
+ |
+ |
+////////// MemviewSliceInit.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_init_memviewslice( |
+ struct __pyx_memoryview_obj *memview, |
+ int ndim, |
+ __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); |
+static CYTHON_INLINE int __pyx_sub_acquisition_count_locked( |
+ __pyx_atomic_int *acquisition_count, PyThread_type_lock lock); |
+ |
+#define __pyx_get_slice_count_pointer(memview) (memview->acquisition_count_aligned_p) |
+#define __pyx_get_slice_count(memview) (*__pyx_get_slice_count_pointer(memview)) |
+#define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__) |
+#define __PYX_XDEC_MEMVIEW(slice, have_gil) __Pyx_XDEC_MEMVIEW(slice, have_gil, __LINE__) |
+static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *, int, int); |
+static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *, int, int); |
+ |
+ |
+/////////////// MemviewSliceIndex.proto /////////////// |
+ |
+static CYTHON_INLINE char *__pyx_memviewslice_index_full( |
+ const char *bufp, Py_ssize_t idx, Py_ssize_t stride, Py_ssize_t suboffset); |
+ |
+ |
+/////////////// ObjectToMemviewSlice /////////////// |
+//@requires: MemviewSliceValidateAndInit |
+ |
+static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *obj) { |
+ {{memviewslice_name}} result = {{memslice_init}}; |
+ __Pyx_BufFmt_StackElem stack[{{struct_nesting_depth}}]; |
+ int axes_specs[] = { {{axes_specs}} }; |
+ int retcode; |
+ |
+ if (obj == Py_None) { |
+ /* We don't bother to refcount None */ |
+ result.memview = (struct __pyx_memoryview_obj *) Py_None; |
+ return 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: |
+ result.memview = NULL; |
+ result.data = NULL; |
+ return result; |
+} |
+ |
+ |
+/////////////// MemviewSliceValidateAndInit.proto /////////////// |
+ |
+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); |
+ |
+/////////////// MemviewSliceValidateAndInit /////////////// |
+//@requires: Buffer.c::TypeInfoCompare |
+ |
+static int |
+__pyx_check_strides(Py_buffer *buf, int dim, int ndim, int spec) |
+{ |
+ if (buf->shape[dim] <= 1) |
+ return 1; |
+ |
+ if (buf->strides) { |
+ if (spec & __Pyx_MEMVIEW_CONTIG) { |
+ if (spec & (__Pyx_MEMVIEW_PTR|__Pyx_MEMVIEW_FULL)) { |
+ if (buf->strides[dim] != sizeof(void *)) { |
+ PyErr_Format(PyExc_ValueError, |
+ "Buffer is not indirectly contiguous " |
+ "in dimension %d.", dim); |
+ goto fail; |
+ } |
+ } else if (buf->strides[dim] != buf->itemsize) { |
+ PyErr_SetString(PyExc_ValueError, |
+ "Buffer and memoryview are not contiguous " |
+ "in the same dimension."); |
+ goto fail; |
+ } |
+ } |
+ |
+ if (spec & __Pyx_MEMVIEW_FOLLOW) { |
+ Py_ssize_t stride = buf->strides[dim]; |
+ if (stride < 0) |
+ stride = -stride; |
+ if (stride < buf->itemsize) { |
+ PyErr_SetString(PyExc_ValueError, |
+ "Buffer and memoryview are not contiguous " |
+ "in the same dimension."); |
+ goto fail; |
+ } |
+ } |
+ } else { |
+ if (spec & __Pyx_MEMVIEW_CONTIG && dim != ndim - 1) { |
+ PyErr_Format(PyExc_ValueError, |
+ "C-contiguous buffer is not contiguous in " |
+ "dimension %d", dim); |
+ goto fail; |
+ } else if (spec & (__Pyx_MEMVIEW_PTR)) { |
+ PyErr_Format(PyExc_ValueError, |
+ "C-contiguous buffer is not indirect in " |
+ "dimension %d", dim); |
+ goto fail; |
+ } else if (buf->suboffsets) { |
+ PyErr_SetString(PyExc_ValueError, |
+ "Buffer exposes suboffsets but no strides"); |
+ goto fail; |
+ } |
+ } |
+ |
+ return 1; |
+fail: |
+ return 0; |
+} |
+ |
+static int |
+__pyx_check_suboffsets(Py_buffer *buf, int dim, CYTHON_UNUSED int ndim, int spec) |
+{ |
+ // Todo: without PyBUF_INDIRECT we may not have suboffset information, i.e., the |
+ // ptr may not be set to NULL but may be uninitialized? |
+ if (spec & __Pyx_MEMVIEW_DIRECT) { |
+ if (buf->suboffsets && buf->suboffsets[dim] >= 0) { |
+ PyErr_Format(PyExc_ValueError, |
+ "Buffer not compatible with direct access " |
+ "in dimension %d.", dim); |
+ goto fail; |
+ } |
+ } |
+ |
+ if (spec & __Pyx_MEMVIEW_PTR) { |
+ if (!buf->suboffsets || (buf->suboffsets && buf->suboffsets[dim] < 0)) { |
+ PyErr_Format(PyExc_ValueError, |
+ "Buffer is not indirectly accessible " |
+ "in dimension %d.", dim); |
+ goto fail; |
+ } |
+ } |
+ |
+ return 1; |
+fail: |
+ return 0; |
+} |
+ |
+static int |
+__pyx_verify_contig(Py_buffer *buf, int ndim, int c_or_f_flag) |
+{ |
+ int i; |
+ |
+ 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] && |
+ buf->shape[i] > 1) |
+ { |
+ PyErr_SetString(PyExc_ValueError, |
+ "Buffer not fortran contiguous."); |
+ goto fail; |
+ } |
+ stride = stride * buf->shape[i]; |
+ } |
+ } else if (c_or_f_flag & __Pyx_IS_C_CONTIG) { |
+ Py_ssize_t stride = 1; |
+ for (i = ndim - 1; i >- 1; i--) { |
+ if (stride * buf->itemsize != buf->strides[i] && |
+ buf->shape[i] > 1) { |
+ PyErr_SetString(PyExc_ValueError, |
+ "Buffer not C contiguous."); |
+ goto fail; |
+ } |
+ stride = stride * buf->shape[i]; |
+ } |
+ } |
+ |
+ return 1; |
+fail: |
+ return 0; |
+} |
+ |
+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) |
+{ |
+ struct __pyx_memoryview_obj *memview, *new_memview; |
+ __Pyx_RefNannyDeclarations |
+ Py_buffer *buf; |
+ int i, spec = 0, retval = -1; |
+ __Pyx_BufFmt_Context ctx; |
+ int from_memoryview = __pyx_memoryview_check(original_obj); |
+ |
+ __Pyx_RefNannySetupContext("ValidateAndInit_memviewslice", 0); |
+ |
+ 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)", |
+ ndim, buf->ndim); |
+ 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, |
+ "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "u byte%s) " |
+ "does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "u byte%s)", |
+ buf->itemsize, |
+ (buf->itemsize > 1) ? "s" : "", |
+ dtype->name, |
+ dtype->size, |
+ (dtype->size > 1) ? "s" : ""); |
+ goto fail; |
+ } |
+ |
+ /* Check axes */ |
+ for (i = 0; i < ndim; i++) { |
+ spec = axes_specs[i]; |
+ if (!__pyx_check_strides(buf, i, ndim, spec)) |
+ goto fail; |
+ if (!__pyx_check_suboffsets(buf, i, ndim, spec)) |
+ goto fail; |
+ } |
+ |
+ /* Check contiguity */ |
+ if (buf->strides && !__pyx_verify_contig(buf, ndim, c_or_f_flag)) |
+ goto fail; |
+ |
+ /* Initialize */ |
+ if (unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice, |
+ new_memview != NULL) == -1)) { |
+ goto fail; |
+ } |
+ |
+ retval = 0; |
+ goto no_fail; |
+ |
+fail: |
+ Py_XDECREF(new_memview); |
+ retval = -1; |
+ |
+no_fail: |
+ __Pyx_RefNannyFinishContext(); |
+ return retval; |
+} |
+ |
+ |
+////////// MemviewSliceInit ////////// |
+ |
+static int |
+__Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview, |
+ int ndim, |
+ {{memviewslice_name}} *memviewslice, |
+ int memview_is_new_reference) |
+{ |
+ __Pyx_RefNannyDeclarations |
+ int i, retval=-1; |
+ Py_buffer *buf = &memview->view; |
+ __Pyx_RefNannySetupContext("init_memviewslice", 0); |
+ |
+ if (!buf) { |
+ PyErr_SetString(PyExc_ValueError, |
+ "buf is NULL."); |
+ goto fail; |
+ } else if (memviewslice->memview || memviewslice->data) { |
+ PyErr_SetString(PyExc_ValueError, |
+ "memviewslice is already initialized!"); |
+ goto fail; |
+ } |
+ |
+ if (buf->strides) { |
+ for (i = 0; i < ndim; i++) { |
+ memviewslice->strides[i] = buf->strides[i]; |
+ } |
+ } else { |
+ Py_ssize_t stride = buf->itemsize; |
+ for (i = ndim - 1; i >= 0; i--) { |
+ memviewslice->strides[i] = stride; |
+ stride *= buf->shape[i]; |
+ } |
+ } |
+ |
+ for (i = 0; i < ndim; i++) { |
+ memviewslice->shape[i] = buf->shape[i]; |
+ if (buf->suboffsets) { |
+ memviewslice->suboffsets[i] = buf->suboffsets[i]; |
+ } else { |
+ memviewslice->suboffsets[i] = -1; |
+ } |
+ } |
+ |
+ memviewslice->memview = memview; |
+ memviewslice->data = (char *)buf->buf; |
+ if (__pyx_add_acquisition_count(memview) == 0 && !memview_is_new_reference) { |
+ Py_INCREF(memview); |
+ } |
+ retval = 0; |
+ goto no_fail; |
+ |
+fail: |
+ /* 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; |
+no_fail: |
+ __Pyx_RefNannyFinishContext(); |
+ return retval; |
+} |
+ |
+ |
+static CYTHON_INLINE void __pyx_fatalerror(const char *fmt, ...) { |
+ va_list vargs; |
+ char msg[200]; |
+ |
+ va_start(vargs, fmt); |
+ |
+#ifdef HAVE_STDARG_PROTOTYPES |
+ va_start(vargs, fmt); |
+#else |
+ va_start(vargs); |
+#endif |
+ |
+ vsnprintf(msg, 200, fmt, vargs); |
+ Py_FatalError(msg); |
+ |
+ va_end(vargs); |
+} |
+ |
+static CYTHON_INLINE int |
+__pyx_add_acquisition_count_locked(__pyx_atomic_int *acquisition_count, |
+ PyThread_type_lock lock) |
+{ |
+ int result; |
+ PyThread_acquire_lock(lock, 1); |
+ result = (*acquisition_count)++; |
+ PyThread_release_lock(lock); |
+ return result; |
+} |
+ |
+static CYTHON_INLINE int |
+__pyx_sub_acquisition_count_locked(__pyx_atomic_int *acquisition_count, |
+ PyThread_type_lock lock) |
+{ |
+ int result; |
+ PyThread_acquire_lock(lock, 1); |
+ result = (*acquisition_count)--; |
+ PyThread_release_lock(lock); |
+ return result; |
+} |
+ |
+ |
+static CYTHON_INLINE void |
+__Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil, int lineno) |
+{ |
+ int first_time; |
+ struct {{memview_struct_name}} *memview = memslice->memview; |
+ if (!memview || (PyObject *) memview == Py_None) |
+ return; /* allow uninitialized memoryview assignment */ |
+ |
+ if (__pyx_get_slice_count(memview) < 0) |
+ __pyx_fatalerror("Acquisition count is %d (line %d)", |
+ __pyx_get_slice_count(memview), lineno); |
+ |
+ first_time = __pyx_add_acquisition_count(memview) == 0; |
+ |
+ if (first_time) { |
+ if (have_gil) { |
+ Py_INCREF((PyObject *) memview); |
+ } else { |
+ PyGILState_STATE _gilstate = PyGILState_Ensure(); |
+ Py_INCREF((PyObject *) memview); |
+ PyGILState_Release(_gilstate); |
+ } |
+ } |
+} |
+ |
+static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice, |
+ int have_gil, int lineno) { |
+ int last_time; |
+ struct {{memview_struct_name}} *memview = memslice->memview; |
+ |
+ if (!memview ) { |
+ return; |
+ } else if ((PyObject *) memview == Py_None) { |
+ memslice->memview = NULL; |
+ return; |
+ } |
+ |
+ if (__pyx_get_slice_count(memview) <= 0) |
+ __pyx_fatalerror("Acquisition count is %d (line %d)", |
+ __pyx_get_slice_count(memview), lineno); |
+ |
+ last_time = __pyx_sub_acquisition_count(memview) == 1; |
+ memslice->data = NULL; |
+ if (last_time) { |
+ if (have_gil) { |
+ Py_CLEAR(memslice->memview); |
+ } else { |
+ PyGILState_STATE _gilstate = PyGILState_Ensure(); |
+ Py_CLEAR(memslice->memview); |
+ PyGILState_Release(_gilstate); |
+ } |
+ } else { |
+ memslice->memview = NULL; |
+ } |
+} |
+ |
+ |
+////////// MemviewSliceCopyTemplate.proto ////////// |
+ |
+static {{memviewslice_name}} |
+__pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs, |
+ const char *mode, int ndim, |
+ size_t sizeof_dtype, int contig_flag, |
+ int dtype_is_object); |
+ |
+ |
+////////// MemviewSliceCopyTemplate ////////// |
+ |
+static {{memviewslice_name}} |
+__pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs, |
+ const char *mode, int ndim, |
+ size_t sizeof_dtype, int contig_flag, |
+ int dtype_is_object) |
+{ |
+ __Pyx_RefNannyDeclarations |
+ int i; |
+ __Pyx_memviewslice new_mvs = {{memslice_init}}; |
+ struct __pyx_memoryview_obj *from_memview = from_mvs->memview; |
+ Py_buffer *buf = &from_memview->view; |
+ PyObject *shape_tuple = NULL; |
+ PyObject *temp_int = NULL; |
+ struct __pyx_array_obj *array_obj = NULL; |
+ struct __pyx_memoryview_obj *memview_obj = NULL; |
+ |
+ __Pyx_RefNannySetupContext("__pyx_memoryview_copy_new_contig", 0); |
+ |
+ for (i = 0; i < ndim; i++) { |
+ if (from_mvs->suboffsets[i] >= 0) { |
+ PyErr_Format(PyExc_ValueError, "Cannot copy memoryview slice with " |
+ "indirect dimensions (axis %d)", i); |
+ goto fail; |
+ } |
+ } |
+ |
+ shape_tuple = PyTuple_New(ndim); |
+ if (unlikely(!shape_tuple)) { |
+ goto fail; |
+ } |
+ __Pyx_GOTREF(shape_tuple); |
+ |
+ |
+ for(i = 0; i < ndim; i++) { |
+ temp_int = PyInt_FromSsize_t(from_mvs->shape[i]); |
+ if(unlikely(!temp_int)) { |
+ goto fail; |
+ } else { |
+ PyTuple_SET_ITEM(shape_tuple, i, temp_int); |
+ temp_int = NULL; |
+ } |
+ } |
+ |
+ array_obj = __pyx_array_new(shape_tuple, sizeof_dtype, buf->format, (char *) mode, NULL); |
+ if (unlikely(!array_obj)) { |
+ goto fail; |
+ } |
+ __Pyx_GOTREF(array_obj); |
+ |
+ memview_obj = (struct __pyx_memoryview_obj *) __pyx_memoryview_new( |
+ (PyObject *) array_obj, contig_flag, |
+ 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, 1) < 0)) |
+ goto fail; |
+ |
+ if (unlikely(__pyx_memoryview_copy_contents(*from_mvs, new_mvs, ndim, ndim, |
+ dtype_is_object) < 0)) |
+ goto fail; |
+ |
+ goto no_fail; |
+ |
+fail: |
+ __Pyx_XDECREF(new_mvs.memview); |
+ new_mvs.memview = NULL; |
+ new_mvs.data = NULL; |
+no_fail: |
+ __Pyx_XDECREF(shape_tuple); |
+ __Pyx_XDECREF(temp_int); |
+ __Pyx_XDECREF(array_obj); |
+ __Pyx_RefNannyFinishContext(); |
+ return new_mvs; |
+} |
+ |
+ |
+////////// CopyContentsUtility.proto ///////// |
+ |
+#define {{func_cname}}(slice) \ |
+ __pyx_memoryview_copy_new_contig(&slice, "{{mode}}", {{ndim}}, \ |
+ sizeof({{dtype_decl}}), {{contig_flag}}, \ |
+ {{dtype_is_object}}) |
+ |
+ |
+////////// OverlappingSlices.proto ////////// |
+ |
+static int __pyx_slices_overlap({{memviewslice_name}} *slice1, |
+ {{memviewslice_name}} *slice2, |
+ int ndim, size_t itemsize); |
+ |
+ |
+////////// OverlappingSlices ////////// |
+ |
+/* Based on numpy's core/src/multiarray/array_assign.c */ |
+ |
+/* Gets a half-open range [start, end) which contains the array data */ |
+static void |
+__pyx_get_array_memory_extents({{memviewslice_name}} *slice, |
+ void **out_start, void **out_end, |
+ int ndim, size_t itemsize) |
+{ |
+ char *start, *end; |
+ int i; |
+ |
+ start = end = slice->data; |
+ |
+ for (i = 0; i < ndim; i++) { |
+ Py_ssize_t stride = slice->strides[i]; |
+ Py_ssize_t extent = slice->shape[i]; |
+ |
+ if (extent == 0) { |
+ *out_start = *out_end = start; |
+ return; |
+ } else { |
+ if (stride > 0) |
+ end += stride * (extent - 1); |
+ else |
+ start += stride * (extent - 1); |
+ } |
+ } |
+ |
+ /* Return a half-open range */ |
+ *out_start = start; |
+ *out_end = end + itemsize; |
+} |
+ |
+/* Returns 1 if the arrays have overlapping data, 0 otherwise */ |
+static int |
+__pyx_slices_overlap({{memviewslice_name}} *slice1, |
+ {{memviewslice_name}} *slice2, |
+ int ndim, size_t itemsize) |
+{ |
+ void *start1, *end1, *start2, *end2; |
+ |
+ __pyx_get_array_memory_extents(slice1, &start1, &end1, ndim, itemsize); |
+ __pyx_get_array_memory_extents(slice2, &start2, &end2, ndim, itemsize); |
+ |
+ return (start1 < end2) && (start2 < end1); |
+} |
+ |
+ |
+////////// MemviewSliceIsCContig.proto ////////// |
+ |
+#define __pyx_memviewslice_is_c_contig{{ndim}}(slice) \ |
+ __pyx_memviewslice_is_contig(&slice, 'C', {{ndim}}) |
+ |
+ |
+////////// MemviewSliceIsFContig.proto ////////// |
+ |
+#define __pyx_memviewslice_is_f_contig{{ndim}}(slice) \ |
+ __pyx_memviewslice_is_contig(&slice, 'F', {{ndim}}) |
+ |
+ |
+////////// MemviewSliceIsContig.proto ////////// |
+ |
+static int __pyx_memviewslice_is_contig(const {{memviewslice_name}} *mvs, |
+ char order, int ndim); |
+ |
+ |
+////////// MemviewSliceIsContig ////////// |
+ |
+static int |
+__pyx_memviewslice_is_contig(const {{memviewslice_name}} *mvs, |
+ char order, int ndim) |
+{ |
+ int i, index, step, start; |
+ Py_ssize_t itemsize = mvs->memview->view.itemsize; |
+ |
+ if (order == 'F') { |
+ step = 1; |
+ start = 0; |
+ } else { |
+ step = -1; |
+ start = ndim - 1; |
+ } |
+ |
+ for (i = 0; i < ndim; i++) { |
+ index = start + step * i; |
+ if (mvs->suboffsets[index] >= 0 || mvs->strides[index] != itemsize) |
+ return 0; |
+ |
+ itemsize *= mvs->shape[index]; |
+ } |
+ |
+ return 1; |
+} |
+ |
+ |
+/////////////// MemviewSliceIndex /////////////// |
+ |
+static CYTHON_INLINE char * |
+__pyx_memviewslice_index_full(const char *bufp, Py_ssize_t idx, |
+ Py_ssize_t stride, Py_ssize_t suboffset) |
+{ |
+ bufp = bufp + idx * stride; |
+ if (suboffset >= 0) { |
+ bufp = *((char **) bufp) + suboffset; |
+ } |
+ return (char *) bufp; |
+} |
+ |
+ |
+/////////////// MemviewDtypeToObject.proto /////////////// |
+ |
+{{if to_py_function}} |
+static PyObject *{{get_function}}(const char *itemp); /* proto */ |
+{{endif}} |
+ |
+{{if from_py_function}} |
+static int {{set_function}}(const char *itemp, PyObject *obj); /* proto */ |
+{{endif}} |
+ |
+/////////////// MemviewDtypeToObject /////////////// |
+ |
+{{#__pyx_memview_<dtype_name>_to_object}} |
+ |
+/* Convert a dtype to or from a Python object */ |
+ |
+{{if to_py_function}} |
+static PyObject *{{get_function}}(const char *itemp) { |
+ return (PyObject *) {{to_py_function}}(*({{dtype}} *) itemp); |
+} |
+{{endif}} |
+ |
+{{if from_py_function}} |
+static int {{set_function}}(const char *itemp, PyObject *obj) { |
+ {{dtype}} value = {{from_py_function}}(obj); |
+ if ({{error_condition}}) |
+ return 0; |
+ *({{dtype}} *) itemp = value; |
+ return 1; |
+} |
+{{endif}} |
+ |
+ |
+/////////////// MemviewObjectToObject.proto /////////////// |
+ |
+/* Function callbacks (for memoryview object) for dtype object */ |
+static PyObject *{{get_function}}(const char *itemp); /* proto */ |
+static int {{set_function}}(const char *itemp, PyObject *obj); /* proto */ |
+ |
+ |
+/////////////// MemviewObjectToObject /////////////// |
+ |
+static PyObject *{{get_function}}(const char *itemp) { |
+ PyObject *result = *(PyObject **) itemp; |
+ Py_INCREF(result); |
+ return result; |
+} |
+ |
+static int {{set_function}}(const char *itemp, PyObject *obj) { |
+ Py_INCREF(obj); |
+ Py_DECREF(*(PyObject **) itemp); |
+ *(PyObject **) itemp = obj; |
+ return 1; |
+} |
+ |
+/////////// ToughSlice ////////// |
+ |
+/* Dimension is indexed with 'start:stop:step' */ |
+ |
+if (unlikely(__pyx_memoryview_slice_memviewslice( |
+ &{{dst}}, |
+ {{src}}.shape[{{dim}}], {{src}}.strides[{{dim}}], {{src}}.suboffsets[{{dim}}], |
+ {{dim}}, |
+ {{new_ndim}}, |
+ &{{suboffset_dim}}, |
+ {{start}}, |
+ {{stop}}, |
+ {{step}}, |
+ {{int(have_start)}}, |
+ {{int(have_stop)}}, |
+ {{int(have_step)}}, |
+ 1) < 0)) |
+{ |
+ {{error_goto}} |
+} |
+ |
+ |
+////////// SimpleSlice ////////// |
+ |
+/* Dimension is indexed with ':' only */ |
+ |
+{{dst}}.shape[{{new_ndim}}] = {{src}}.shape[{{dim}}]; |
+{{dst}}.strides[{{new_ndim}}] = {{src}}.strides[{{dim}}]; |
+ |
+{{if access == 'direct'}} |
+ {{dst}}.suboffsets[{{new_ndim}}] = -1; |
+{{else}} |
+ {{dst}}.suboffsets[{{new_ndim}}] = {{src}}.suboffsets[{{dim}}]; |
+ if ({{src}}.suboffsets[{{dim}}] >= 0) |
+ {{suboffset_dim}} = {{new_ndim}}; |
+{{endif}} |
+ |
+ |
+////////// SliceIndex ////////// |
+ |
+// Dimension is indexed with an integer, we could use the ToughSlice |
+// approach, but this is faster |
+ |
+{ |
+ Py_ssize_t __pyx_tmp_idx = {{idx}}; |
+ Py_ssize_t __pyx_tmp_shape = {{src}}.shape[{{dim}}]; |
+ Py_ssize_t __pyx_tmp_stride = {{src}}.strides[{{dim}}]; |
+ if ({{wraparound}} && (__pyx_tmp_idx < 0)) |
+ __pyx_tmp_idx += __pyx_tmp_shape; |
+ |
+ if ({{boundscheck}} && (__pyx_tmp_idx < 0 || __pyx_tmp_idx >= __pyx_tmp_shape)) { |
+ {{if not have_gil}} |
+ #ifdef WITH_THREAD |
+ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); |
+ #endif |
+ {{endif}} |
+ |
+ PyErr_SetString(PyExc_IndexError, "Index out of bounds (axis {{dim}})"); |
+ |
+ {{if not have_gil}} |
+ #ifdef WITH_THREAD |
+ PyGILState_Release(__pyx_gilstate_save); |
+ #endif |
+ {{endif}} |
+ |
+ {{error_goto}} |
+ } |
+ |
+ {{if all_dimensions_direct}} |
+ {{dst}}.data += __pyx_tmp_idx * __pyx_tmp_stride; |
+ {{else}} |
+ if ({{suboffset_dim}} < 0) { |
+ {{dst}}.data += __pyx_tmp_idx * __pyx_tmp_stride; |
+ |
+ /* This dimension is the first dimension, or is preceded by */ |
+ /* direct or indirect dimensions that are indexed away. */ |
+ /* Hence suboffset_dim must be less than zero, and we can have */ |
+ /* our data pointer refer to another block by dereferencing. */ |
+ /* slice.data -> B -> C becomes slice.data -> C */ |
+ |
+ {{if indirect}} |
+ { |
+ Py_ssize_t __pyx_tmp_suboffset = {{src}}.suboffsets[{{dim}}]; |
+ |
+ {{if generic}} |
+ if (__pyx_tmp_suboffset >= 0) |
+ {{endif}} |
+ |
+ {{dst}}.data = *((char **) {{dst}}.data) + __pyx_tmp_suboffset; |
+ } |
+ {{endif}} |
+ |
+ } else { |
+ {{dst}}.suboffsets[{{suboffset_dim}}] += __pyx_tmp_idx * __pyx_tmp_stride; |
+ |
+ /* Note: dimension can not be indirect, the compiler will have */ |
+ /* issued an error */ |
+ } |
+ |
+ {{endif}} |
+} |
+ |
+ |
+////////// FillStrided1DScalar.proto ////////// |
+ |
+static void |
+__pyx_fill_slice_{{dtype_name}}({{type_decl}} *p, Py_ssize_t extent, Py_ssize_t stride, |
+ size_t itemsize, void *itemp); |
+ |
+////////// FillStrided1DScalar ////////// |
+ |
+/* Fill a slice with a scalar value. The dimension is direct and strided or contiguous */ |
+/* This can be used as a callback for the memoryview object to efficienty assign a scalar */ |
+/* Currently unused */ |
+static void |
+__pyx_fill_slice_{{dtype_name}}({{type_decl}} *p, Py_ssize_t extent, Py_ssize_t stride, |
+ size_t itemsize, void *itemp) |
+{ |
+ Py_ssize_t i; |
+ {{type_decl}} item = *(({{type_decl}} *) itemp); |
+ {{type_decl}} *endp; |
+ |
+ stride /= sizeof({{type_decl}}); |
+ endp = p + stride * extent; |
+ |
+ while (p < endp) { |
+ *p = item; |
+ p += stride; |
+ } |
+} |