aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/cython/Cython/Utility/MemoryView.pyx
diff options
context:
space:
mode:
authorAnton Samokhvalov <pg83@yandex.ru>2022-02-10 16:45:17 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:17 +0300
commitd3a398281c6fd1d3672036cb2d63f842d2cb28c5 (patch)
treedd4bd3ca0f36b817e96812825ffaf10d645803f2 /contrib/tools/cython/Cython/Utility/MemoryView.pyx
parent72cb13b4aff9bc9cf22e49251bc8fd143f82538f (diff)
downloadydb-d3a398281c6fd1d3672036cb2d63f842d2cb28c5.tar.gz
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/tools/cython/Cython/Utility/MemoryView.pyx')
-rw-r--r--contrib/tools/cython/Cython/Utility/MemoryView.pyx2668
1 files changed, 1334 insertions, 1334 deletions
diff --git a/contrib/tools/cython/Cython/Utility/MemoryView.pyx b/contrib/tools/cython/Cython/Utility/MemoryView.pyx
index 0b4386360d..6ca5fab9ba 100644
--- a/contrib/tools/cython/Cython/Utility/MemoryView.pyx
+++ b/contrib/tools/cython/Cython/Utility/MemoryView.pyx
@@ -1,313 +1,313 @@
-#################### View.MemoryView ####################
-
-# This utility provides cython.array and cython.view.memoryview
-
+#################### View.MemoryView ####################
+
+# This utility provides cython.array and cython.view.memoryview
+
from __future__ import absolute_import
-
+
cimport cython
-# from cpython cimport ...
-cdef extern from "Python.h":
- int PyIndex_Check(object)
- object PyLong_FromVoidPtr(void *)
-
-cdef extern from "pythread.h":
- ctypedef void *PyThread_type_lock
-
- PyThread_type_lock PyThread_allocate_lock()
- void PyThread_free_lock(PyThread_type_lock)
- int PyThread_acquire_lock(PyThread_type_lock, int mode) nogil
- void PyThread_release_lock(PyThread_type_lock) nogil
-
+# from cpython cimport ...
+cdef extern from "Python.h":
+ int PyIndex_Check(object)
+ object PyLong_FromVoidPtr(void *)
+
+cdef extern from "pythread.h":
+ ctypedef void *PyThread_type_lock
+
+ PyThread_type_lock PyThread_allocate_lock()
+ void PyThread_free_lock(PyThread_type_lock)
+ int PyThread_acquire_lock(PyThread_type_lock, int mode) nogil
+ void PyThread_release_lock(PyThread_type_lock) nogil
+
cdef extern from "<string.h>":
- void *memset(void *b, int c, size_t len)
-
-cdef extern from *:
- int __Pyx_GetBuffer(object, Py_buffer *, int) except -1
- void __Pyx_ReleaseBuffer(Py_buffer *)
-
- ctypedef struct PyObject
- ctypedef Py_ssize_t Py_intptr_t
- void Py_INCREF(PyObject *)
- void Py_DECREF(PyObject *)
-
- void* PyMem_Malloc(size_t n)
- void PyMem_Free(void *p)
+ void *memset(void *b, int c, size_t len)
+
+cdef extern from *:
+ int __Pyx_GetBuffer(object, Py_buffer *, int) except -1
+ void __Pyx_ReleaseBuffer(Py_buffer *)
+
+ ctypedef struct PyObject
+ ctypedef Py_ssize_t Py_intptr_t
+ void Py_INCREF(PyObject *)
+ void Py_DECREF(PyObject *)
+
+ void* PyMem_Malloc(size_t n)
+ void PyMem_Free(void *p)
void* PyObject_Malloc(size_t n)
void PyObject_Free(void *p)
-
- cdef struct __pyx_memoryview "__pyx_memoryview_obj":
- Py_buffer view
- PyObject *obj
- __Pyx_TypeInfo *typeinfo
-
- ctypedef struct {{memviewslice_name}}:
- __pyx_memoryview *memview
- char *data
- Py_ssize_t shape[{{max_dims}}]
- Py_ssize_t strides[{{max_dims}}]
- Py_ssize_t suboffsets[{{max_dims}}]
-
- void __PYX_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
- void __PYX_XDEC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
-
- ctypedef struct __pyx_buffer "Py_buffer":
- PyObject *obj
-
- PyObject *Py_None
-
- cdef enum:
- PyBUF_C_CONTIGUOUS,
- PyBUF_F_CONTIGUOUS,
- PyBUF_ANY_CONTIGUOUS
- PyBUF_FORMAT
- PyBUF_WRITABLE
- PyBUF_STRIDES
- PyBUF_INDIRECT
+
+ cdef struct __pyx_memoryview "__pyx_memoryview_obj":
+ Py_buffer view
+ PyObject *obj
+ __Pyx_TypeInfo *typeinfo
+
+ ctypedef struct {{memviewslice_name}}:
+ __pyx_memoryview *memview
+ char *data
+ Py_ssize_t shape[{{max_dims}}]
+ Py_ssize_t strides[{{max_dims}}]
+ Py_ssize_t suboffsets[{{max_dims}}]
+
+ void __PYX_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
+ void __PYX_XDEC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
+
+ ctypedef struct __pyx_buffer "Py_buffer":
+ PyObject *obj
+
+ PyObject *Py_None
+
+ cdef enum:
+ PyBUF_C_CONTIGUOUS,
+ PyBUF_F_CONTIGUOUS,
+ PyBUF_ANY_CONTIGUOUS
+ PyBUF_FORMAT
+ PyBUF_WRITABLE
+ PyBUF_STRIDES
+ PyBUF_INDIRECT
PyBUF_ND
- PyBUF_RECORDS
+ PyBUF_RECORDS
PyBUF_RECORDS_RO
-
- ctypedef struct __Pyx_TypeInfo:
- pass
-
- cdef object capsule "__pyx_capsule_create" (void *p, char *sig)
- cdef int __pyx_array_getbuffer(PyObject *obj, Py_buffer view, int flags)
- cdef int __pyx_memoryview_getbuffer(PyObject *obj, Py_buffer view, int flags)
-
-cdef extern from *:
- ctypedef int __pyx_atomic_int
- {{memviewslice_name}} slice_copy_contig "__pyx_memoryview_copy_new_contig"(
- __Pyx_memviewslice *from_mvs,
- char *mode, int ndim,
- size_t sizeof_dtype, int contig_flag,
- bint dtype_is_object) nogil except *
- bint slice_is_contig "__pyx_memviewslice_is_contig" (
+
+ ctypedef struct __Pyx_TypeInfo:
+ pass
+
+ cdef object capsule "__pyx_capsule_create" (void *p, char *sig)
+ cdef int __pyx_array_getbuffer(PyObject *obj, Py_buffer view, int flags)
+ cdef int __pyx_memoryview_getbuffer(PyObject *obj, Py_buffer view, int flags)
+
+cdef extern from *:
+ ctypedef int __pyx_atomic_int
+ {{memviewslice_name}} slice_copy_contig "__pyx_memoryview_copy_new_contig"(
+ __Pyx_memviewslice *from_mvs,
+ char *mode, int ndim,
+ size_t sizeof_dtype, int contig_flag,
+ bint dtype_is_object) nogil except *
+ bint slice_is_contig "__pyx_memviewslice_is_contig" (
{{memviewslice_name}} mvs, char order, int ndim) nogil
- bint slices_overlap "__pyx_slices_overlap" ({{memviewslice_name}} *slice1,
- {{memviewslice_name}} *slice2,
- int ndim, size_t itemsize) nogil
-
-
+ bint slices_overlap "__pyx_slices_overlap" ({{memviewslice_name}} *slice1,
+ {{memviewslice_name}} *slice2,
+ int ndim, size_t itemsize) nogil
+
+
cdef extern from "<stdlib.h>":
- void *malloc(size_t) nogil
- void free(void *) nogil
- void *memcpy(void *dest, void *src, size_t n) nogil
-
-
-
-
-#
-### cython.array class
-#
-
-@cname("__pyx_array")
-cdef class array:
-
- cdef:
- char *data
- Py_ssize_t len
- char *format
- int ndim
- Py_ssize_t *_shape
- Py_ssize_t *_strides
- Py_ssize_t itemsize
- unicode mode # FIXME: this should have been a simple 'char'
- bytes _format
- void (*callback_free_data)(void *data)
- # cdef object _memview
- cdef bint free_data
- cdef bint dtype_is_object
-
- def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None,
- mode="c", bint allocate_buffer=True):
-
- cdef int idx
- cdef Py_ssize_t i, dim
- cdef PyObject **p
-
- self.ndim = <int> len(shape)
- self.itemsize = itemsize
-
- if not self.ndim:
- raise ValueError("Empty shape tuple for cython.array")
-
- if itemsize <= 0:
- raise ValueError("itemsize <= 0 for cython.array")
-
+ void *malloc(size_t) nogil
+ void free(void *) nogil
+ void *memcpy(void *dest, void *src, size_t n) nogil
+
+
+
+
+#
+### cython.array class
+#
+
+@cname("__pyx_array")
+cdef class array:
+
+ cdef:
+ char *data
+ Py_ssize_t len
+ char *format
+ int ndim
+ Py_ssize_t *_shape
+ Py_ssize_t *_strides
+ Py_ssize_t itemsize
+ unicode mode # FIXME: this should have been a simple 'char'
+ bytes _format
+ void (*callback_free_data)(void *data)
+ # cdef object _memview
+ cdef bint free_data
+ cdef bint dtype_is_object
+
+ def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None,
+ mode="c", bint allocate_buffer=True):
+
+ cdef int idx
+ cdef Py_ssize_t i, dim
+ cdef PyObject **p
+
+ self.ndim = <int> len(shape)
+ self.itemsize = itemsize
+
+ if not self.ndim:
+ raise ValueError("Empty shape tuple for cython.array")
+
+ if itemsize <= 0:
+ raise ValueError("itemsize <= 0 for cython.array")
+
if not isinstance(format, bytes):
format = format.encode('ASCII')
- self._format = format # keep a reference to the byte string
- self.format = self._format
-
- # use single malloc() for both shape and strides
+ self._format = format # keep a reference to the byte string
+ self.format = self._format
+
+ # use single malloc() for both shape and strides
self._shape = <Py_ssize_t *> PyObject_Malloc(sizeof(Py_ssize_t)*self.ndim*2)
- self._strides = self._shape + self.ndim
-
- if not self._shape:
- raise MemoryError("unable to allocate shape and strides.")
-
- # cdef Py_ssize_t dim, stride
- for idx, dim in enumerate(shape):
- if dim <= 0:
- raise ValueError("Invalid shape in axis %d: %d." % (idx, dim))
- self._shape[idx] = dim
-
- cdef char order
- if mode == 'fortran':
- order = b'F'
- self.mode = u'fortran'
- elif mode == 'c':
- order = b'C'
- self.mode = u'c'
- else:
- raise ValueError("Invalid mode, expected 'c' or 'fortran', got %s" % mode)
-
- self.len = fill_contig_strides_array(self._shape, self._strides,
- itemsize, self.ndim, order)
-
- self.free_data = allocate_buffer
- self.dtype_is_object = format == b'O'
- if allocate_buffer:
- # use malloc() for backwards compatibility
- # in case external code wants to change the data pointer
- self.data = <char *>malloc(self.len)
- if not self.data:
- raise MemoryError("unable to allocate array data.")
-
- if self.dtype_is_object:
- p = <PyObject **> self.data
- for i in range(self.len / itemsize):
- p[i] = Py_None
- Py_INCREF(Py_None)
-
- @cname('getbuffer')
- def __getbuffer__(self, Py_buffer *info, int flags):
- cdef int bufmode = -1
- if self.mode == u"c":
- bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
- elif self.mode == u"fortran":
- bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
- if not (flags & bufmode):
- raise ValueError("Can only create a buffer that is contiguous in memory.")
- info.buf = self.data
- info.len = self.len
- info.ndim = self.ndim
- info.shape = self._shape
- info.strides = self._strides
- info.suboffsets = NULL
- info.itemsize = self.itemsize
- info.readonly = 0
-
- if flags & PyBUF_FORMAT:
- info.format = self.format
- else:
- info.format = NULL
-
- info.obj = self
-
- __pyx_getbuffer = capsule(<void *> &__pyx_array_getbuffer, "getbuffer(obj, view, flags)")
-
- def __dealloc__(array self):
- if self.callback_free_data != NULL:
- self.callback_free_data(self.data)
- elif self.free_data:
- if self.dtype_is_object:
- refcount_objects_in_slice(self.data, self._shape,
- self._strides, self.ndim, False)
- free(self.data)
+ self._strides = self._shape + self.ndim
+
+ if not self._shape:
+ raise MemoryError("unable to allocate shape and strides.")
+
+ # cdef Py_ssize_t dim, stride
+ for idx, dim in enumerate(shape):
+ if dim <= 0:
+ raise ValueError("Invalid shape in axis %d: %d." % (idx, dim))
+ self._shape[idx] = dim
+
+ cdef char order
+ if mode == 'fortran':
+ order = b'F'
+ self.mode = u'fortran'
+ elif mode == 'c':
+ order = b'C'
+ self.mode = u'c'
+ else:
+ raise ValueError("Invalid mode, expected 'c' or 'fortran', got %s" % mode)
+
+ self.len = fill_contig_strides_array(self._shape, self._strides,
+ itemsize, self.ndim, order)
+
+ self.free_data = allocate_buffer
+ self.dtype_is_object = format == b'O'
+ if allocate_buffer:
+ # use malloc() for backwards compatibility
+ # in case external code wants to change the data pointer
+ self.data = <char *>malloc(self.len)
+ if not self.data:
+ raise MemoryError("unable to allocate array data.")
+
+ if self.dtype_is_object:
+ p = <PyObject **> self.data
+ for i in range(self.len / itemsize):
+ p[i] = Py_None
+ Py_INCREF(Py_None)
+
+ @cname('getbuffer')
+ def __getbuffer__(self, Py_buffer *info, int flags):
+ cdef int bufmode = -1
+ if self.mode == u"c":
+ bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
+ elif self.mode == u"fortran":
+ bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
+ if not (flags & bufmode):
+ raise ValueError("Can only create a buffer that is contiguous in memory.")
+ info.buf = self.data
+ info.len = self.len
+ info.ndim = self.ndim
+ info.shape = self._shape
+ info.strides = self._strides
+ info.suboffsets = NULL
+ info.itemsize = self.itemsize
+ info.readonly = 0
+
+ if flags & PyBUF_FORMAT:
+ info.format = self.format
+ else:
+ info.format = NULL
+
+ info.obj = self
+
+ __pyx_getbuffer = capsule(<void *> &__pyx_array_getbuffer, "getbuffer(obj, view, flags)")
+
+ def __dealloc__(array self):
+ if self.callback_free_data != NULL:
+ self.callback_free_data(self.data)
+ elif self.free_data:
+ if self.dtype_is_object:
+ refcount_objects_in_slice(self.data, self._shape,
+ self._strides, self.ndim, False)
+ free(self.data)
PyObject_Free(self._shape)
-
+
@property
def memview(self):
return self.get_memview()
-
+
@cname('get_memview')
cdef get_memview(self):
flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE
return memoryview(self, flags, self.dtype_is_object)
-
+
def __len__(self):
return self._shape[0]
- def __getattr__(self, attr):
- return getattr(self.memview, attr)
-
- def __getitem__(self, item):
- return self.memview[item]
-
- def __setitem__(self, item, value):
- self.memview[item] = value
-
-
-@cname("__pyx_array_new")
-cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format,
- char *mode, char *buf):
- cdef array result
-
- if buf == NULL:
- result = array(shape, itemsize, format, mode.decode('ASCII'))
- else:
- result = array(shape, itemsize, format, mode.decode('ASCII'),
- allocate_buffer=False)
- result.data = buf
-
- return result
-
-
-#
-### Memoryview constants and cython.view.memoryview class
-#
-
-# Disable generic_contiguous, as it makes trouble verifying contiguity:
-# - 'contiguous' or '::1' means the dimension is contiguous with dtype
-# - 'indirect_contiguous' means a contiguous list of pointers
-# - dtype contiguous must be contiguous in the first or last dimension
-# from the start, or from the dimension following the last indirect dimension
-#
-# e.g.
-# int[::indirect_contiguous, ::contiguous, :]
-#
-# is valid (list of pointers to 2d fortran-contiguous array), but
-#
-# int[::generic_contiguous, ::contiguous, :]
-#
-# would mean you'd have assert dimension 0 to be indirect (and pointer contiguous) at runtime.
-# So it doesn't bring any performance benefit, and it's only confusing.
-
-@cname('__pyx_MemviewEnum')
-cdef class Enum(object):
- cdef object name
- def __init__(self, name):
- self.name = name
- def __repr__(self):
- return self.name
-
-cdef generic = Enum("<strided and direct or indirect>")
-cdef strided = Enum("<strided and direct>") # default
-cdef indirect = Enum("<strided and indirect>")
-# Disable generic_contiguous, as it is a troublemaker
-#cdef generic_contiguous = Enum("<contiguous and direct or indirect>")
-cdef contiguous = Enum("<contiguous and direct>")
-cdef indirect_contiguous = Enum("<contiguous and indirect>")
-
-# 'follow' is implied when the first or last axis is ::1
-
-
-@cname('__pyx_align_pointer')
-cdef void *align_pointer(void *memory, size_t alignment) nogil:
- "Align pointer memory on a given boundary"
- cdef Py_intptr_t aligned_p = <Py_intptr_t> memory
- cdef size_t offset
-
- with cython.cdivision(True):
- offset = aligned_p % alignment
-
- if offset > 0:
- aligned_p += alignment - offset
-
- return <void *> aligned_p
-
+ def __getattr__(self, attr):
+ return getattr(self.memview, attr)
+
+ def __getitem__(self, item):
+ return self.memview[item]
+
+ def __setitem__(self, item, value):
+ self.memview[item] = value
+
+
+@cname("__pyx_array_new")
+cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format,
+ char *mode, char *buf):
+ cdef array result
+
+ if buf == NULL:
+ result = array(shape, itemsize, format, mode.decode('ASCII'))
+ else:
+ result = array(shape, itemsize, format, mode.decode('ASCII'),
+ allocate_buffer=False)
+ result.data = buf
+
+ return result
+
+
+#
+### Memoryview constants and cython.view.memoryview class
+#
+
+# Disable generic_contiguous, as it makes trouble verifying contiguity:
+# - 'contiguous' or '::1' means the dimension is contiguous with dtype
+# - 'indirect_contiguous' means a contiguous list of pointers
+# - dtype contiguous must be contiguous in the first or last dimension
+# from the start, or from the dimension following the last indirect dimension
+#
+# e.g.
+# int[::indirect_contiguous, ::contiguous, :]
+#
+# is valid (list of pointers to 2d fortran-contiguous array), but
+#
+# int[::generic_contiguous, ::contiguous, :]
+#
+# would mean you'd have assert dimension 0 to be indirect (and pointer contiguous) at runtime.
+# So it doesn't bring any performance benefit, and it's only confusing.
+
+@cname('__pyx_MemviewEnum')
+cdef class Enum(object):
+ cdef object name
+ def __init__(self, name):
+ self.name = name
+ def __repr__(self):
+ return self.name
+
+cdef generic = Enum("<strided and direct or indirect>")
+cdef strided = Enum("<strided and direct>") # default
+cdef indirect = Enum("<strided and indirect>")
+# Disable generic_contiguous, as it is a troublemaker
+#cdef generic_contiguous = Enum("<contiguous and direct or indirect>")
+cdef contiguous = Enum("<contiguous and direct>")
+cdef indirect_contiguous = Enum("<contiguous and indirect>")
+
+# 'follow' is implied when the first or last axis is ::1
+
+
+@cname('__pyx_align_pointer')
+cdef void *align_pointer(void *memory, size_t alignment) nogil:
+ "Align pointer memory on a given boundary"
+ cdef Py_intptr_t aligned_p = <Py_intptr_t> memory
+ cdef size_t offset
+
+ with cython.cdivision(True):
+ offset = aligned_p % alignment
+
+ if offset > 0:
+ aligned_p += alignment - offset
+
+ return <void *> aligned_p
+
# pre-allocate thread locks for reuse
## note that this could be implemented in a more beautiful way in "normal" Cython,
@@ -326,31 +326,31 @@ cdef PyThread_type_lock[THREAD_LOCKS_PREALLOCATED] __pyx_memoryview_thread_locks
]
-@cname('__pyx_memoryview')
-cdef class memoryview(object):
-
- cdef object obj
- cdef object _size
- cdef object _array_interface
- cdef PyThread_type_lock lock
- # the following array will contain a single __pyx_atomic int with
- # suitable alignment
- cdef __pyx_atomic_int acquisition_count[2]
- cdef __pyx_atomic_int *acquisition_count_aligned_p
- 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
- self.flags = flags
- if type(self) is memoryview or obj is not None:
- __Pyx_GetBuffer(obj, &self.view, flags)
- if <PyObject *> self.view.obj == NULL:
- (<__pyx_buffer *> &self.view).obj = Py_None
- Py_INCREF(Py_None)
-
+@cname('__pyx_memoryview')
+cdef class memoryview(object):
+
+ cdef object obj
+ cdef object _size
+ cdef object _array_interface
+ cdef PyThread_type_lock lock
+ # the following array will contain a single __pyx_atomic int with
+ # suitable alignment
+ cdef __pyx_atomic_int acquisition_count[2]
+ cdef __pyx_atomic_int *acquisition_count_aligned_p
+ 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
+ self.flags = flags
+ if type(self) is memoryview or obj is not None:
+ __Pyx_GetBuffer(obj, &self.view, flags)
+ if <PyObject *> self.view.obj == NULL:
+ (<__pyx_buffer *> &self.view).obj = Py_None
+ Py_INCREF(Py_None)
+
global __pyx_memoryview_thread_locks_used
if __pyx_memoryview_thread_locks_used < THREAD_LOCKS_PREALLOCATED:
self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]
@@ -359,27 +359,27 @@ cdef class memoryview(object):
self.lock = PyThread_allocate_lock()
if self.lock is NULL:
raise MemoryError
-
- if flags & PyBUF_FORMAT:
+
+ if flags & PyBUF_FORMAT:
self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0')
- else:
- self.dtype_is_object = dtype_is_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:
- __Pyx_ReleaseBuffer(&self.view)
+ else:
+ self.dtype_is_object = dtype_is_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:
+ __Pyx_ReleaseBuffer(&self.view)
elif (<__pyx_buffer *> &self.view).obj == Py_None:
# Undo the incref in __cinit__() above.
(<__pyx_buffer *> &self.view).obj = NULL
Py_DECREF(Py_None)
-
+
cdef int i
global __pyx_memoryview_thread_locks_used
- if self.lock != NULL:
+ if self.lock != NULL:
for i in range(__pyx_memoryview_thread_locks_used):
if __pyx_memoryview_thread_locks[i] is self.lock:
__pyx_memoryview_thread_locks_used -= 1
@@ -389,649 +389,649 @@ cdef class memoryview(object):
break
else:
PyThread_free_lock(self.lock)
-
- cdef char *get_item_pointer(memoryview self, object index) except NULL:
- cdef Py_ssize_t dim
- cdef char *itemp = <char *> self.view.buf
-
- for dim, idx in enumerate(index):
- itemp = pybuffer_index(&self.view, itemp, idx, dim)
-
- return itemp
-
- #@cname('__pyx_memoryview_getitem')
- def __getitem__(memoryview self, object index):
- if index is Ellipsis:
- return self
-
- have_slices, indices = _unellipsify(index, self.view.ndim)
-
- cdef char *itemp
- if have_slices:
- return memview_slice(self, indices)
- else:
- itemp = self.get_item_pointer(indices)
- return self.convert_item_to_object(itemp)
-
- def __setitem__(memoryview self, object index, object value):
+
+ cdef char *get_item_pointer(memoryview self, object index) except NULL:
+ cdef Py_ssize_t dim
+ cdef char *itemp = <char *> self.view.buf
+
+ for dim, idx in enumerate(index):
+ itemp = pybuffer_index(&self.view, itemp, idx, dim)
+
+ return itemp
+
+ #@cname('__pyx_memoryview_getitem')
+ def __getitem__(memoryview self, object index):
+ if index is Ellipsis:
+ return self
+
+ have_slices, indices = _unellipsify(index, self.view.ndim)
+
+ cdef char *itemp
+ if have_slices:
+ return memview_slice(self, indices)
+ else:
+ itemp = self.get_item_pointer(indices)
+ return self.convert_item_to_object(itemp)
+
+ def __setitem__(memoryview self, object index, object value):
if self.view.readonly:
raise TypeError("Cannot assign to read-only memoryview")
- have_slices, index = _unellipsify(index, self.view.ndim)
-
- if have_slices:
- obj = self.is_slice(value)
- if obj:
- self.setitem_slice_assignment(self[index], obj)
- else:
- self.setitem_slice_assign_scalar(self[index], value)
- else:
- self.setitem_indexed(index, value)
-
- cdef is_slice(self, obj):
- if not isinstance(obj, memoryview):
- try:
+ have_slices, index = _unellipsify(index, self.view.ndim)
+
+ if have_slices:
+ obj = self.is_slice(value)
+ if obj:
+ self.setitem_slice_assignment(self[index], obj)
+ else:
+ self.setitem_slice_assign_scalar(self[index], value)
+ else:
+ self.setitem_indexed(index, value)
+
+ cdef is_slice(self, obj):
+ if not isinstance(obj, memoryview):
+ try:
obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS,
- self.dtype_is_object)
- except TypeError:
- return None
-
- return obj
-
- cdef setitem_slice_assignment(self, dst, src):
- cdef {{memviewslice_name}} dst_slice
- cdef {{memviewslice_name}} src_slice
-
- memoryview_copy_contents(get_slice_from_memview(src, &src_slice)[0],
- get_slice_from_memview(dst, &dst_slice)[0],
- src.ndim, dst.ndim, self.dtype_is_object)
-
- cdef setitem_slice_assign_scalar(self, memoryview dst, value):
- cdef int array[128]
- cdef void *tmp = NULL
- cdef void *item
-
- cdef {{memviewslice_name}} *dst_slice
- cdef {{memviewslice_name}} tmp_slice
- dst_slice = get_slice_from_memview(dst, &tmp_slice)
-
- if <size_t>self.view.itemsize > sizeof(array):
- tmp = PyMem_Malloc(self.view.itemsize)
- if tmp == NULL:
- raise MemoryError
- item = tmp
- else:
- item = <void *> array
-
- try:
- if self.dtype_is_object:
- (<PyObject **> item)[0] = <PyObject *> value
- else:
- self.assign_item_from_object(<char *> item, value)
-
- # It would be easy to support indirect dimensions, but it's easier
- # to disallow :)
- if self.view.suboffsets != NULL:
- assert_direct_dimensions(self.view.suboffsets, self.view.ndim)
- slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize,
- item, self.dtype_is_object)
- finally:
- PyMem_Free(tmp)
-
- cdef setitem_indexed(self, index, value):
- cdef char *itemp = self.get_item_pointer(index)
- self.assign_item_from_object(itemp, value)
-
- cdef convert_item_to_object(self, char *itemp):
- """Only used if instantiated manually by the user, or if Cython doesn't
- know how to convert the type"""
- import struct
- cdef bytes bytesitem
- # Do a manual and complete check here instead of this easy hack
- bytesitem = itemp[:self.view.itemsize]
- try:
- result = struct.unpack(self.view.format, bytesitem)
- except struct.error:
- raise ValueError("Unable to convert item to object")
- else:
- if len(self.view.format) == 1:
- return result[0]
- return result
-
- cdef assign_item_from_object(self, char *itemp, object value):
- """Only used if instantiated manually by the user, or if Cython doesn't
- know how to convert the type"""
- import struct
- cdef char c
- cdef bytes bytesvalue
- cdef Py_ssize_t i
-
- if isinstance(value, tuple):
- bytesvalue = struct.pack(self.view.format, *value)
- else:
- bytesvalue = struct.pack(self.view.format, value)
-
- for i, c in enumerate(bytesvalue):
- itemp[i] = c
-
- @cname('getbuffer')
- def __getbuffer__(self, Py_buffer *info, int flags):
+ self.dtype_is_object)
+ except TypeError:
+ return None
+
+ return obj
+
+ cdef setitem_slice_assignment(self, dst, src):
+ cdef {{memviewslice_name}} dst_slice
+ cdef {{memviewslice_name}} src_slice
+
+ memoryview_copy_contents(get_slice_from_memview(src, &src_slice)[0],
+ get_slice_from_memview(dst, &dst_slice)[0],
+ src.ndim, dst.ndim, self.dtype_is_object)
+
+ cdef setitem_slice_assign_scalar(self, memoryview dst, value):
+ cdef int array[128]
+ cdef void *tmp = NULL
+ cdef void *item
+
+ cdef {{memviewslice_name}} *dst_slice
+ cdef {{memviewslice_name}} tmp_slice
+ dst_slice = get_slice_from_memview(dst, &tmp_slice)
+
+ if <size_t>self.view.itemsize > sizeof(array):
+ tmp = PyMem_Malloc(self.view.itemsize)
+ if tmp == NULL:
+ raise MemoryError
+ item = tmp
+ else:
+ item = <void *> array
+
+ try:
+ if self.dtype_is_object:
+ (<PyObject **> item)[0] = <PyObject *> value
+ else:
+ self.assign_item_from_object(<char *> item, value)
+
+ # It would be easy to support indirect dimensions, but it's easier
+ # to disallow :)
+ if self.view.suboffsets != NULL:
+ assert_direct_dimensions(self.view.suboffsets, self.view.ndim)
+ slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize,
+ item, self.dtype_is_object)
+ finally:
+ PyMem_Free(tmp)
+
+ cdef setitem_indexed(self, index, value):
+ cdef char *itemp = self.get_item_pointer(index)
+ self.assign_item_from_object(itemp, value)
+
+ cdef convert_item_to_object(self, char *itemp):
+ """Only used if instantiated manually by the user, or if Cython doesn't
+ know how to convert the type"""
+ import struct
+ cdef bytes bytesitem
+ # Do a manual and complete check here instead of this easy hack
+ bytesitem = itemp[:self.view.itemsize]
+ try:
+ result = struct.unpack(self.view.format, bytesitem)
+ except struct.error:
+ raise ValueError("Unable to convert item to object")
+ else:
+ if len(self.view.format) == 1:
+ return result[0]
+ return result
+
+ cdef assign_item_from_object(self, char *itemp, object value):
+ """Only used if instantiated manually by the user, or if Cython doesn't
+ know how to convert the type"""
+ import struct
+ cdef char c
+ cdef bytes bytesvalue
+ cdef Py_ssize_t i
+
+ if isinstance(value, tuple):
+ bytesvalue = struct.pack(self.view.format, *value)
+ else:
+ bytesvalue = struct.pack(self.view.format, value)
+
+ for i, c in enumerate(bytesvalue):
+ itemp[i] = c
+
+ @cname('getbuffer')
+ def __getbuffer__(self, Py_buffer *info, int flags):
if flags & PyBUF_WRITABLE and self.view.readonly:
raise ValueError("Cannot create writable memory view from read-only memoryview")
if flags & PyBUF_ND:
- info.shape = self.view.shape
- else:
- info.shape = NULL
-
- if flags & PyBUF_STRIDES:
- info.strides = self.view.strides
- else:
- info.strides = NULL
-
- if flags & PyBUF_INDIRECT:
- info.suboffsets = self.view.suboffsets
- else:
- info.suboffsets = NULL
-
- if flags & PyBUF_FORMAT:
- info.format = self.view.format
- else:
- info.format = NULL
-
- info.buf = self.view.buf
- info.ndim = self.view.ndim
- info.itemsize = self.view.itemsize
- info.len = self.view.len
+ info.shape = self.view.shape
+ else:
+ info.shape = NULL
+
+ if flags & PyBUF_STRIDES:
+ info.strides = self.view.strides
+ else:
+ info.strides = NULL
+
+ if flags & PyBUF_INDIRECT:
+ info.suboffsets = self.view.suboffsets
+ else:
+ info.suboffsets = NULL
+
+ if flags & PyBUF_FORMAT:
+ info.format = self.view.format
+ else:
+ info.format = NULL
+
+ info.buf = self.view.buf
+ info.ndim = self.view.ndim
+ info.itemsize = self.view.itemsize
+ info.len = self.view.len
info.readonly = self.view.readonly
- info.obj = self
-
- __pyx_getbuffer = capsule(<void *> &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)")
-
+ info.obj = self
+
+ __pyx_getbuffer = capsule(<void *> &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)")
+
# Some properties that have the same semantics as in NumPy
@property
def T(self):
cdef _memoryviewslice result = memoryview_copy(self)
transpose_memslice(&result.from_slice)
return result
-
+
@property
def base(self):
return self.obj
-
+
@property
def shape(self):
return tuple([length for length in self.view.shape[:self.view.ndim]])
-
+
@property
def strides(self):
if self.view.strides == NULL:
# Note: we always ask for strides, so if this is not set it's a bug
raise ValueError("Buffer view does not expose strides")
-
+
return tuple([stride for stride in self.view.strides[:self.view.ndim]])
-
+
@property
def suboffsets(self):
if self.view.suboffsets == NULL:
return (-1,) * self.view.ndim
-
+
return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]])
-
+
@property
def ndim(self):
return self.view.ndim
-
+
@property
def itemsize(self):
return self.view.itemsize
-
+
@property
def nbytes(self):
return self.size * self.view.itemsize
-
+
@property
def size(self):
if self._size is None:
result = 1
-
+
for length in self.view.shape[:self.view.ndim]:
result *= length
-
+
self._size = result
-
+
return self._size
-
- def __len__(self):
- if self.view.ndim >= 1:
- return self.view.shape[0]
-
- return 0
-
- def __repr__(self):
- return "<MemoryView of %r at 0x%x>" % (self.base.__class__.__name__,
- id(self))
-
- def __str__(self):
- return "<MemoryView of %r object>" % (self.base.__class__.__name__,)
-
- # Support the same attributes as memoryview slices
- def is_c_contig(self):
- cdef {{memviewslice_name}} *mslice
- cdef {{memviewslice_name}} tmp
- mslice = get_slice_from_memview(self, &tmp)
+
+ def __len__(self):
+ if self.view.ndim >= 1:
+ return self.view.shape[0]
+
+ return 0
+
+ def __repr__(self):
+ return "<MemoryView of %r at 0x%x>" % (self.base.__class__.__name__,
+ id(self))
+
+ def __str__(self):
+ return "<MemoryView of %r object>" % (self.base.__class__.__name__,)
+
+ # Support the same attributes as memoryview slices
+ def is_c_contig(self):
+ cdef {{memviewslice_name}} *mslice
+ cdef {{memviewslice_name}} tmp
+ mslice = get_slice_from_memview(self, &tmp)
return slice_is_contig(mslice[0], 'C', self.view.ndim)
-
- def is_f_contig(self):
- cdef {{memviewslice_name}} *mslice
- cdef {{memviewslice_name}} tmp
- mslice = get_slice_from_memview(self, &tmp)
+
+ def is_f_contig(self):
+ cdef {{memviewslice_name}} *mslice
+ cdef {{memviewslice_name}} tmp
+ mslice = get_slice_from_memview(self, &tmp)
return slice_is_contig(mslice[0], 'F', self.view.ndim)
-
- def copy(self):
- cdef {{memviewslice_name}} mslice
- cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS
-
- slice_copy(self, &mslice)
- mslice = slice_copy_contig(&mslice, "c", self.view.ndim,
- self.view.itemsize,
- flags|PyBUF_C_CONTIGUOUS,
- self.dtype_is_object)
-
- return memoryview_copy_from_slice(self, &mslice)
-
- def copy_fortran(self):
- cdef {{memviewslice_name}} src, dst
- cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS
-
- slice_copy(self, &src)
- dst = slice_copy_contig(&src, "fortran", self.view.ndim,
- self.view.itemsize,
- flags|PyBUF_F_CONTIGUOUS,
- self.dtype_is_object)
-
- return memoryview_copy_from_slice(self, &dst)
-
-
-@cname('__pyx_memoryview_new')
-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 inline bint memoryview_check(object o):
- return isinstance(o, memoryview)
-
-cdef tuple _unellipsify(object index, int ndim):
- """
- Replace all ellipses with full slices and fill incomplete indices with
- full slices.
- """
- if not isinstance(index, tuple):
- tup = (index,)
- else:
- tup = index
-
- result = []
- have_slices = False
- seen_ellipsis = False
- for idx, item in enumerate(tup):
- if item is Ellipsis:
- if not seen_ellipsis:
- result.extend([slice(None)] * (ndim - len(tup) + 1))
- seen_ellipsis = True
- else:
- result.append(slice(None))
- have_slices = True
- else:
- if not isinstance(item, slice) and not PyIndex_Check(item):
- raise TypeError("Cannot index with type '%s'" % type(item))
-
- have_slices = have_slices or isinstance(item, slice)
- result.append(item)
-
- nslices = ndim - len(result)
- if nslices:
- result.extend([slice(None)] * nslices)
-
- return have_slices or nslices, tuple(result)
-
-cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim):
+
+ def copy(self):
+ cdef {{memviewslice_name}} mslice
+ cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS
+
+ slice_copy(self, &mslice)
+ mslice = slice_copy_contig(&mslice, "c", self.view.ndim,
+ self.view.itemsize,
+ flags|PyBUF_C_CONTIGUOUS,
+ self.dtype_is_object)
+
+ return memoryview_copy_from_slice(self, &mslice)
+
+ def copy_fortran(self):
+ cdef {{memviewslice_name}} src, dst
+ cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS
+
+ slice_copy(self, &src)
+ dst = slice_copy_contig(&src, "fortran", self.view.ndim,
+ self.view.itemsize,
+ flags|PyBUF_F_CONTIGUOUS,
+ self.dtype_is_object)
+
+ return memoryview_copy_from_slice(self, &dst)
+
+
+@cname('__pyx_memoryview_new')
+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 inline bint memoryview_check(object o):
+ return isinstance(o, memoryview)
+
+cdef tuple _unellipsify(object index, int ndim):
+ """
+ Replace all ellipses with full slices and fill incomplete indices with
+ full slices.
+ """
+ if not isinstance(index, tuple):
+ tup = (index,)
+ else:
+ tup = index
+
+ result = []
+ have_slices = False
+ seen_ellipsis = False
+ for idx, item in enumerate(tup):
+ if item is Ellipsis:
+ if not seen_ellipsis:
+ result.extend([slice(None)] * (ndim - len(tup) + 1))
+ seen_ellipsis = True
+ else:
+ result.append(slice(None))
+ have_slices = True
+ else:
+ if not isinstance(item, slice) and not PyIndex_Check(item):
+ raise TypeError("Cannot index with type '%s'" % type(item))
+
+ have_slices = have_slices or isinstance(item, slice)
+ result.append(item)
+
+ nslices = ndim - len(result)
+ if nslices:
+ result.extend([slice(None)] * nslices)
+
+ return have_slices or nslices, tuple(result)
+
+cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim):
for suboffset in suboffsets[:ndim]:
if suboffset >= 0:
- raise ValueError("Indirect dimensions not supported")
-
-#
-### Slicing a memoryview
-#
-
-@cname('__pyx_memview_slice')
-cdef memoryview memview_slice(memoryview memview, object indices):
- cdef int new_ndim = 0, suboffset_dim = -1, dim
- cdef bint negative_step
- cdef {{memviewslice_name}} src, dst
- cdef {{memviewslice_name}} *p_src
-
- # dst is copied by value in memoryview_fromslice -- initialize it
- # src is never copied
- memset(&dst, 0, sizeof(dst))
-
- cdef _memoryviewslice memviewsliceobj
-
- assert memview.view.ndim > 0
-
- if isinstance(memview, _memoryviewslice):
- memviewsliceobj = memview
- p_src = &memviewsliceobj.from_slice
- else:
- slice_copy(memview, &src)
- p_src = &src
-
- # Note: don't use variable src at this point
- # SubNote: we should be able to declare variables in blocks...
-
- # memoryview_fromslice() will inc our dst slice
- dst.memview = p_src.memview
- dst.data = p_src.data
-
- # Put everything in temps to avoid this bloody warning:
- # "Argument evaluation order in C function call is undefined and
- # may not be as expected"
- cdef {{memviewslice_name}} *p_dst = &dst
- cdef int *p_suboffset_dim = &suboffset_dim
- cdef Py_ssize_t start, stop, step
- cdef bint have_start, have_stop, have_step
-
- for dim, index in enumerate(indices):
- if PyIndex_Check(index):
- slice_memviewslice(
- p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim],
- dim, new_ndim, p_suboffset_dim,
- index, 0, 0, # start, stop, step
- 0, 0, 0, # have_{start,stop,step}
- False)
- elif index is None:
- p_dst.shape[new_ndim] = 1
- p_dst.strides[new_ndim] = 0
- p_dst.suboffsets[new_ndim] = -1
- new_ndim += 1
- else:
- start = index.start or 0
- stop = index.stop or 0
- step = index.step or 0
-
- have_start = index.start is not None
- have_stop = index.stop is not None
- have_step = index.step is not None
-
- slice_memviewslice(
- p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim],
- dim, new_ndim, p_suboffset_dim,
- start, stop, step,
- have_start, have_stop, have_step,
- True)
- new_ndim += 1
-
- if isinstance(memview, _memoryviewslice):
- return memoryview_fromslice(dst, new_ndim,
- memviewsliceobj.to_object_func,
- memviewsliceobj.to_dtype_func,
- memview.dtype_is_object)
- else:
- return memoryview_fromslice(dst, new_ndim, NULL, NULL,
- memview.dtype_is_object)
-
-
-#
-### Slicing in a single dimension of a memoryviewslice
-#
-
+ raise ValueError("Indirect dimensions not supported")
+
+#
+### Slicing a memoryview
+#
+
+@cname('__pyx_memview_slice')
+cdef memoryview memview_slice(memoryview memview, object indices):
+ cdef int new_ndim = 0, suboffset_dim = -1, dim
+ cdef bint negative_step
+ cdef {{memviewslice_name}} src, dst
+ cdef {{memviewslice_name}} *p_src
+
+ # dst is copied by value in memoryview_fromslice -- initialize it
+ # src is never copied
+ memset(&dst, 0, sizeof(dst))
+
+ cdef _memoryviewslice memviewsliceobj
+
+ assert memview.view.ndim > 0
+
+ if isinstance(memview, _memoryviewslice):
+ memviewsliceobj = memview
+ p_src = &memviewsliceobj.from_slice
+ else:
+ slice_copy(memview, &src)
+ p_src = &src
+
+ # Note: don't use variable src at this point
+ # SubNote: we should be able to declare variables in blocks...
+
+ # memoryview_fromslice() will inc our dst slice
+ dst.memview = p_src.memview
+ dst.data = p_src.data
+
+ # Put everything in temps to avoid this bloody warning:
+ # "Argument evaluation order in C function call is undefined and
+ # may not be as expected"
+ cdef {{memviewslice_name}} *p_dst = &dst
+ cdef int *p_suboffset_dim = &suboffset_dim
+ cdef Py_ssize_t start, stop, step
+ cdef bint have_start, have_stop, have_step
+
+ for dim, index in enumerate(indices):
+ if PyIndex_Check(index):
+ slice_memviewslice(
+ p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim],
+ dim, new_ndim, p_suboffset_dim,
+ index, 0, 0, # start, stop, step
+ 0, 0, 0, # have_{start,stop,step}
+ False)
+ elif index is None:
+ p_dst.shape[new_ndim] = 1
+ p_dst.strides[new_ndim] = 0
+ p_dst.suboffsets[new_ndim] = -1
+ new_ndim += 1
+ else:
+ start = index.start or 0
+ stop = index.stop or 0
+ step = index.step or 0
+
+ have_start = index.start is not None
+ have_stop = index.stop is not None
+ have_step = index.step is not None
+
+ slice_memviewslice(
+ p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim],
+ dim, new_ndim, p_suboffset_dim,
+ start, stop, step,
+ have_start, have_stop, have_step,
+ True)
+ new_ndim += 1
+
+ if isinstance(memview, _memoryviewslice):
+ return memoryview_fromslice(dst, new_ndim,
+ memviewsliceobj.to_object_func,
+ memviewsliceobj.to_dtype_func,
+ memview.dtype_is_object)
+ else:
+ return memoryview_fromslice(dst, new_ndim, NULL, NULL,
+ memview.dtype_is_object)
+
+
+#
+### Slicing in a single dimension of a memoryviewslice
+#
+
cdef extern from "<stdlib.h>":
- void abort() nogil
- void printf(char *s, ...) nogil
-
+ void abort() nogil
+ void printf(char *s, ...) nogil
+
cdef extern from "<stdio.h>":
- ctypedef struct FILE
- FILE *stderr
- int fputs(char *s, FILE *stream)
-
-cdef extern from "pystate.h":
- void PyThreadState_Get() nogil
-
- # These are not actually nogil, but we check for the GIL before calling them
- void PyErr_SetString(PyObject *type, char *msg) nogil
- PyObject *PyErr_Format(PyObject *exc, char *msg, ...) nogil
-
-@cname('__pyx_memoryview_slice_memviewslice')
-cdef int slice_memviewslice(
- {{memviewslice_name}} *dst,
- Py_ssize_t shape, Py_ssize_t stride, Py_ssize_t suboffset,
- int dim, int new_ndim, int *suboffset_dim,
- Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step,
- int have_start, int have_stop, int have_step,
- bint is_slice) nogil except -1:
- """
- Create a new slice dst given slice src.
-
- dim - the current src dimension (indexing will make dimensions
- disappear)
- new_dim - the new dst dimension
- suboffset_dim - pointer to a single int initialized to -1 to keep track of
- where slicing offsets should be added
- """
-
- cdef Py_ssize_t new_shape
- cdef bint negative_step
-
- if not is_slice:
- # index is a normal integer-like index
- if start < 0:
- start += shape
- if not 0 <= start < shape:
- _err_dim(IndexError, "Index out of bounds (axis %d)", dim)
- else:
- # index is a slice
- negative_step = have_step != 0 and step < 0
-
- if have_step and step == 0:
- _err_dim(ValueError, "Step may not be zero (axis %d)", dim)
-
- # check our bounds and set defaults
- if have_start:
- if start < 0:
- start += shape
- if start < 0:
- start = 0
- elif start >= shape:
- if negative_step:
- start = shape - 1
- else:
- start = shape
- else:
- if negative_step:
- start = shape - 1
- else:
- start = 0
-
- if have_stop:
- if stop < 0:
- stop += shape
- if stop < 0:
- stop = 0
- elif stop > shape:
- stop = shape
- else:
- if negative_step:
- stop = -1
- else:
- stop = shape
-
- if not have_step:
- step = 1
-
- # len = ceil( (stop - start) / step )
- with cython.cdivision(True):
- new_shape = (stop - start) // step
-
- if (stop - start) - step * new_shape:
- new_shape += 1
-
- if new_shape < 0:
- new_shape = 0
-
- # shape/strides/suboffsets
- dst.strides[new_ndim] = stride * step
- dst.shape[new_ndim] = new_shape
- dst.suboffsets[new_ndim] = suboffset
-
- # Add the slicing or idexing offsets to the right suboffset or base data *
- if suboffset_dim[0] < 0:
- dst.data += start * stride
- else:
- dst.suboffsets[suboffset_dim[0]] += start * stride
-
- if suboffset >= 0:
- if not is_slice:
- if new_ndim == 0:
- dst.data = (<char **> dst.data)[0] + suboffset
- else:
- _err_dim(IndexError, "All dimensions preceding dimension %d "
- "must be indexed and not sliced", dim)
- else:
- suboffset_dim[0] = new_ndim
-
- return 0
-
-#
-### Index a memoryview
-#
-@cname('__pyx_pybuffer_index')
-cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index,
- Py_ssize_t dim) except NULL:
- cdef Py_ssize_t shape, stride, suboffset = -1
- cdef Py_ssize_t itemsize = view.itemsize
- cdef char *resultp
-
- if view.ndim == 0:
- shape = view.len / itemsize
- stride = itemsize
- else:
- shape = view.shape[dim]
- stride = view.strides[dim]
- if view.suboffsets != NULL:
- suboffset = view.suboffsets[dim]
-
- if index < 0:
- index += view.shape[dim]
- if index < 0:
- raise IndexError("Out of bounds on buffer access (axis %d)" % dim)
-
- if index >= shape:
- raise IndexError("Out of bounds on buffer access (axis %d)" % dim)
-
- resultp = bufp + index * stride
- if suboffset >= 0:
- resultp = (<char **> resultp)[0] + suboffset
-
- return resultp
-
-#
-### Transposing a memoryviewslice
-#
-@cname('__pyx_memslice_transpose')
-cdef int transpose_memslice({{memviewslice_name}} *memslice) nogil except 0:
- cdef int ndim = memslice.memview.view.ndim
-
- cdef Py_ssize_t *shape = memslice.shape
- cdef Py_ssize_t *strides = memslice.strides
-
- # reverse strides and shape
- cdef int i, j
- for i in range(ndim / 2):
- j = ndim - 1 - i
- strides[i], strides[j] = strides[j], strides[i]
- shape[i], shape[j] = shape[j], shape[i]
-
- if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0:
- _err(ValueError, "Cannot transpose memoryview with indirect dimensions")
-
- return 1
-
-#
-### Creating new memoryview objects from slices and memoryviews
-#
-@cname('__pyx_memoryviewslice')
-cdef class _memoryviewslice(memoryview):
- "Internal class for passing memoryview slices to Python"
-
- # We need this to keep our shape/strides/suboffset pointers valid
- cdef {{memviewslice_name}} from_slice
- # We need this only to print it's class' name
- cdef object from_object
-
- cdef object (*to_object_func)(char *)
- cdef int (*to_dtype_func)(char *, object) except 0
-
- def __dealloc__(self):
- __PYX_XDEC_MEMVIEW(&self.from_slice, 1)
-
- cdef convert_item_to_object(self, char *itemp):
- if self.to_object_func != NULL:
- return self.to_object_func(itemp)
- else:
- return memoryview.convert_item_to_object(self, itemp)
-
- cdef assign_item_from_object(self, char *itemp, object value):
- if self.to_dtype_func != NULL:
- self.to_dtype_func(itemp, value)
- else:
- memoryview.assign_item_from_object(self, itemp, value)
-
+ ctypedef struct FILE
+ FILE *stderr
+ int fputs(char *s, FILE *stream)
+
+cdef extern from "pystate.h":
+ void PyThreadState_Get() nogil
+
+ # These are not actually nogil, but we check for the GIL before calling them
+ void PyErr_SetString(PyObject *type, char *msg) nogil
+ PyObject *PyErr_Format(PyObject *exc, char *msg, ...) nogil
+
+@cname('__pyx_memoryview_slice_memviewslice')
+cdef int slice_memviewslice(
+ {{memviewslice_name}} *dst,
+ Py_ssize_t shape, Py_ssize_t stride, Py_ssize_t suboffset,
+ int dim, int new_ndim, int *suboffset_dim,
+ Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step,
+ int have_start, int have_stop, int have_step,
+ bint is_slice) nogil except -1:
+ """
+ Create a new slice dst given slice src.
+
+ dim - the current src dimension (indexing will make dimensions
+ disappear)
+ new_dim - the new dst dimension
+ suboffset_dim - pointer to a single int initialized to -1 to keep track of
+ where slicing offsets should be added
+ """
+
+ cdef Py_ssize_t new_shape
+ cdef bint negative_step
+
+ if not is_slice:
+ # index is a normal integer-like index
+ if start < 0:
+ start += shape
+ if not 0 <= start < shape:
+ _err_dim(IndexError, "Index out of bounds (axis %d)", dim)
+ else:
+ # index is a slice
+ negative_step = have_step != 0 and step < 0
+
+ if have_step and step == 0:
+ _err_dim(ValueError, "Step may not be zero (axis %d)", dim)
+
+ # check our bounds and set defaults
+ if have_start:
+ if start < 0:
+ start += shape
+ if start < 0:
+ start = 0
+ elif start >= shape:
+ if negative_step:
+ start = shape - 1
+ else:
+ start = shape
+ else:
+ if negative_step:
+ start = shape - 1
+ else:
+ start = 0
+
+ if have_stop:
+ if stop < 0:
+ stop += shape
+ if stop < 0:
+ stop = 0
+ elif stop > shape:
+ stop = shape
+ else:
+ if negative_step:
+ stop = -1
+ else:
+ stop = shape
+
+ if not have_step:
+ step = 1
+
+ # len = ceil( (stop - start) / step )
+ with cython.cdivision(True):
+ new_shape = (stop - start) // step
+
+ if (stop - start) - step * new_shape:
+ new_shape += 1
+
+ if new_shape < 0:
+ new_shape = 0
+
+ # shape/strides/suboffsets
+ dst.strides[new_ndim] = stride * step
+ dst.shape[new_ndim] = new_shape
+ dst.suboffsets[new_ndim] = suboffset
+
+ # Add the slicing or idexing offsets to the right suboffset or base data *
+ if suboffset_dim[0] < 0:
+ dst.data += start * stride
+ else:
+ dst.suboffsets[suboffset_dim[0]] += start * stride
+
+ if suboffset >= 0:
+ if not is_slice:
+ if new_ndim == 0:
+ dst.data = (<char **> dst.data)[0] + suboffset
+ else:
+ _err_dim(IndexError, "All dimensions preceding dimension %d "
+ "must be indexed and not sliced", dim)
+ else:
+ suboffset_dim[0] = new_ndim
+
+ return 0
+
+#
+### Index a memoryview
+#
+@cname('__pyx_pybuffer_index')
+cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index,
+ Py_ssize_t dim) except NULL:
+ cdef Py_ssize_t shape, stride, suboffset = -1
+ cdef Py_ssize_t itemsize = view.itemsize
+ cdef char *resultp
+
+ if view.ndim == 0:
+ shape = view.len / itemsize
+ stride = itemsize
+ else:
+ shape = view.shape[dim]
+ stride = view.strides[dim]
+ if view.suboffsets != NULL:
+ suboffset = view.suboffsets[dim]
+
+ if index < 0:
+ index += view.shape[dim]
+ if index < 0:
+ raise IndexError("Out of bounds on buffer access (axis %d)" % dim)
+
+ if index >= shape:
+ raise IndexError("Out of bounds on buffer access (axis %d)" % dim)
+
+ resultp = bufp + index * stride
+ if suboffset >= 0:
+ resultp = (<char **> resultp)[0] + suboffset
+
+ return resultp
+
+#
+### Transposing a memoryviewslice
+#
+@cname('__pyx_memslice_transpose')
+cdef int transpose_memslice({{memviewslice_name}} *memslice) nogil except 0:
+ cdef int ndim = memslice.memview.view.ndim
+
+ cdef Py_ssize_t *shape = memslice.shape
+ cdef Py_ssize_t *strides = memslice.strides
+
+ # reverse strides and shape
+ cdef int i, j
+ for i in range(ndim / 2):
+ j = ndim - 1 - i
+ strides[i], strides[j] = strides[j], strides[i]
+ shape[i], shape[j] = shape[j], shape[i]
+
+ if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0:
+ _err(ValueError, "Cannot transpose memoryview with indirect dimensions")
+
+ return 1
+
+#
+### Creating new memoryview objects from slices and memoryviews
+#
+@cname('__pyx_memoryviewslice')
+cdef class _memoryviewslice(memoryview):
+ "Internal class for passing memoryview slices to Python"
+
+ # We need this to keep our shape/strides/suboffset pointers valid
+ cdef {{memviewslice_name}} from_slice
+ # We need this only to print it's class' name
+ cdef object from_object
+
+ cdef object (*to_object_func)(char *)
+ cdef int (*to_dtype_func)(char *, object) except 0
+
+ def __dealloc__(self):
+ __PYX_XDEC_MEMVIEW(&self.from_slice, 1)
+
+ cdef convert_item_to_object(self, char *itemp):
+ if self.to_object_func != NULL:
+ return self.to_object_func(itemp)
+ else:
+ return memoryview.convert_item_to_object(self, itemp)
+
+ cdef assign_item_from_object(self, char *itemp, object value):
+ if self.to_dtype_func != NULL:
+ self.to_dtype_func(itemp, value)
+ else:
+ memoryview.assign_item_from_object(self, itemp, value)
+
@property
def base(self):
return self.from_object
-
- __pyx_getbuffer = capsule(<void *> &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)")
-
-
-@cname('__pyx_memoryview_fromslice')
-cdef memoryview_fromslice({{memviewslice_name}} memviewslice,
- int ndim,
- object (*to_object_func)(char *),
- int (*to_dtype_func)(char *, object) except 0,
- bint dtype_is_object):
-
- cdef _memoryviewslice result
-
- if <PyObject *> memviewslice.memview == Py_None:
- return None
-
- # assert 0 < ndim <= memviewslice.memview.view.ndim, (
- # ndim, memviewslice.memview.view.ndim)
-
- result = _memoryviewslice(None, 0, dtype_is_object)
-
- result.from_slice = memviewslice
- __PYX_INC_MEMVIEW(&memviewslice, 1)
-
- result.from_object = (<memoryview> memviewslice.memview).base
- result.typeinfo = memviewslice.memview.typeinfo
-
- result.view = memviewslice.memview.view
- result.view.buf = <void *> memviewslice.data
- result.view.ndim = ndim
- (<__pyx_buffer *> &result.view).obj = Py_None
- Py_INCREF(Py_None)
-
+
+ __pyx_getbuffer = capsule(<void *> &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)")
+
+
+@cname('__pyx_memoryview_fromslice')
+cdef memoryview_fromslice({{memviewslice_name}} memviewslice,
+ int ndim,
+ object (*to_object_func)(char *),
+ int (*to_dtype_func)(char *, object) except 0,
+ bint dtype_is_object):
+
+ cdef _memoryviewslice result
+
+ if <PyObject *> memviewslice.memview == Py_None:
+ return None
+
+ # assert 0 < ndim <= memviewslice.memview.view.ndim, (
+ # ndim, memviewslice.memview.view.ndim)
+
+ result = _memoryviewslice(None, 0, dtype_is_object)
+
+ result.from_slice = memviewslice
+ __PYX_INC_MEMVIEW(&memviewslice, 1)
+
+ result.from_object = (<memoryview> memviewslice.memview).base
+ result.typeinfo = memviewslice.memview.typeinfo
+
+ result.view = memviewslice.memview.view
+ result.view.buf = <void *> memviewslice.data
+ result.view.ndim = ndim
+ (<__pyx_buffer *> &result.view).obj = Py_None
+ Py_INCREF(Py_None)
+
if (<memoryview>memviewslice.memview).flags & PyBUF_WRITABLE:
result.flags = PyBUF_RECORDS
else:
result.flags = PyBUF_RECORDS_RO
-
- result.view.shape = <Py_ssize_t *> result.from_slice.shape
- result.view.strides = <Py_ssize_t *> result.from_slice.strides
-
+
+ result.view.shape = <Py_ssize_t *> result.from_slice.shape
+ result.view.strides = <Py_ssize_t *> result.from_slice.strides
+
# only set suboffsets if actually used, otherwise set to NULL to improve compatibility
result.view.suboffsets = NULL
for suboffset in result.from_slice.suboffsets[:ndim]:
@@ -1039,456 +1039,456 @@ cdef memoryview_fromslice({{memviewslice_name}} memviewslice,
result.view.suboffsets = <Py_ssize_t *> result.from_slice.suboffsets
break
- result.view.len = result.view.itemsize
+ result.view.len = result.view.itemsize
for length in result.view.shape[:ndim]:
result.view.len *= length
-
- result.to_object_func = to_object_func
- result.to_dtype_func = to_dtype_func
-
- return result
-
-@cname('__pyx_memoryview_get_slice_from_memoryview')
-cdef {{memviewslice_name}} *get_slice_from_memview(memoryview memview,
+
+ result.to_object_func = to_object_func
+ result.to_dtype_func = to_dtype_func
+
+ return result
+
+@cname('__pyx_memoryview_get_slice_from_memoryview')
+cdef {{memviewslice_name}} *get_slice_from_memview(memoryview memview,
{{memviewslice_name}} *mslice) except NULL:
- cdef _memoryviewslice obj
- if isinstance(memview, _memoryviewslice):
- obj = memview
- return &obj.from_slice
- else:
- slice_copy(memview, mslice)
- return mslice
-
-@cname('__pyx_memoryview_slice_copy')
-cdef void slice_copy(memoryview memview, {{memviewslice_name}} *dst):
- cdef int dim
- cdef (Py_ssize_t*) shape, strides, suboffsets
-
- shape = memview.view.shape
- strides = memview.view.strides
- suboffsets = memview.view.suboffsets
-
- dst.memview = <__pyx_memoryview *> memview
- dst.data = <char *> memview.view.buf
-
- for dim in range(memview.view.ndim):
- dst.shape[dim] = shape[dim]
- dst.strides[dim] = strides[dim]
+ cdef _memoryviewslice obj
+ if isinstance(memview, _memoryviewslice):
+ obj = memview
+ return &obj.from_slice
+ else:
+ slice_copy(memview, mslice)
+ return mslice
+
+@cname('__pyx_memoryview_slice_copy')
+cdef void slice_copy(memoryview memview, {{memviewslice_name}} *dst):
+ cdef int dim
+ cdef (Py_ssize_t*) shape, strides, suboffsets
+
+ shape = memview.view.shape
+ strides = memview.view.strides
+ suboffsets = memview.view.suboffsets
+
+ dst.memview = <__pyx_memoryview *> memview
+ dst.data = <char *> memview.view.buf
+
+ for dim in range(memview.view.ndim):
+ dst.shape[dim] = shape[dim]
+ dst.strides[dim] = strides[dim]
dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1
-
-@cname('__pyx_memoryview_copy_object')
-cdef memoryview_copy(memoryview memview):
- "Create a new memoryview object"
- cdef {{memviewslice_name}} memviewslice
- slice_copy(memview, &memviewslice)
- return memoryview_copy_from_slice(memview, &memviewslice)
-
-@cname('__pyx_memoryview_copy_object_from_slice')
-cdef memoryview_copy_from_slice(memoryview memview, {{memviewslice_name}} *memviewslice):
- """
- Create a new memoryview object from a given memoryview object and slice.
- """
- cdef object (*to_object_func)(char *)
- cdef int (*to_dtype_func)(char *, object) except 0
-
- if isinstance(memview, _memoryviewslice):
- to_object_func = (<_memoryviewslice> memview).to_object_func
- to_dtype_func = (<_memoryviewslice> memview).to_dtype_func
- else:
- to_object_func = NULL
- to_dtype_func = NULL
-
- return memoryview_fromslice(memviewslice[0], memview.view.ndim,
- to_object_func, to_dtype_func,
- memview.dtype_is_object)
-
-
-#
-### Copy the contents of a memoryview slices
-#
-cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil:
- if arg < 0:
- return -arg
- else:
- return arg
-
-@cname('__pyx_get_best_slice_order')
-cdef char get_best_order({{memviewslice_name}} *mslice, int ndim) nogil:
- """
- Figure out the best memory access order for a given slice.
- """
- cdef int i
- cdef Py_ssize_t c_stride = 0
- cdef Py_ssize_t f_stride = 0
-
- for i in range(ndim - 1, -1, -1):
- if mslice.shape[i] > 1:
- c_stride = mslice.strides[i]
- break
-
- for i in range(ndim):
- if mslice.shape[i] > 1:
- f_stride = mslice.strides[i]
- break
-
- if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride):
- return 'C'
- else:
- return 'F'
-
-@cython.cdivision(True)
-cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides,
- char *dst_data, Py_ssize_t *dst_strides,
- Py_ssize_t *src_shape, Py_ssize_t *dst_shape,
- int ndim, size_t itemsize) nogil:
- # Note: src_extent is 1 if we're broadcasting
- # dst_extent always >= src_extent as we don't do reductions
- cdef Py_ssize_t i
- cdef Py_ssize_t src_extent = src_shape[0]
- cdef Py_ssize_t dst_extent = dst_shape[0]
- cdef Py_ssize_t src_stride = src_strides[0]
- cdef Py_ssize_t dst_stride = dst_strides[0]
-
- if ndim == 1:
- if (src_stride > 0 and dst_stride > 0 and
- <size_t> src_stride == itemsize == <size_t> dst_stride):
- memcpy(dst_data, src_data, itemsize * dst_extent)
- else:
- for i in range(dst_extent):
- memcpy(dst_data, src_data, itemsize)
- src_data += src_stride
- dst_data += dst_stride
- else:
- for i in range(dst_extent):
- _copy_strided_to_strided(src_data, src_strides + 1,
- dst_data, dst_strides + 1,
- src_shape + 1, dst_shape + 1,
- ndim - 1, itemsize)
- src_data += src_stride
- dst_data += dst_stride
-
-cdef void copy_strided_to_strided({{memviewslice_name}} *src,
- {{memviewslice_name}} *dst,
- int ndim, size_t itemsize) nogil:
- _copy_strided_to_strided(src.data, src.strides, dst.data, dst.strides,
- src.shape, dst.shape, ndim, itemsize)
-
-@cname('__pyx_memoryview_slice_get_size')
-cdef Py_ssize_t slice_get_size({{memviewslice_name}} *src, int ndim) nogil:
- "Return the size of the memory occupied by the slice in number of bytes"
+
+@cname('__pyx_memoryview_copy_object')
+cdef memoryview_copy(memoryview memview):
+ "Create a new memoryview object"
+ cdef {{memviewslice_name}} memviewslice
+ slice_copy(memview, &memviewslice)
+ return memoryview_copy_from_slice(memview, &memviewslice)
+
+@cname('__pyx_memoryview_copy_object_from_slice')
+cdef memoryview_copy_from_slice(memoryview memview, {{memviewslice_name}} *memviewslice):
+ """
+ Create a new memoryview object from a given memoryview object and slice.
+ """
+ cdef object (*to_object_func)(char *)
+ cdef int (*to_dtype_func)(char *, object) except 0
+
+ if isinstance(memview, _memoryviewslice):
+ to_object_func = (<_memoryviewslice> memview).to_object_func
+ to_dtype_func = (<_memoryviewslice> memview).to_dtype_func
+ else:
+ to_object_func = NULL
+ to_dtype_func = NULL
+
+ return memoryview_fromslice(memviewslice[0], memview.view.ndim,
+ to_object_func, to_dtype_func,
+ memview.dtype_is_object)
+
+
+#
+### Copy the contents of a memoryview slices
+#
+cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil:
+ if arg < 0:
+ return -arg
+ else:
+ return arg
+
+@cname('__pyx_get_best_slice_order')
+cdef char get_best_order({{memviewslice_name}} *mslice, int ndim) nogil:
+ """
+ Figure out the best memory access order for a given slice.
+ """
+ cdef int i
+ cdef Py_ssize_t c_stride = 0
+ cdef Py_ssize_t f_stride = 0
+
+ for i in range(ndim - 1, -1, -1):
+ if mslice.shape[i] > 1:
+ c_stride = mslice.strides[i]
+ break
+
+ for i in range(ndim):
+ if mslice.shape[i] > 1:
+ f_stride = mslice.strides[i]
+ break
+
+ if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride):
+ return 'C'
+ else:
+ return 'F'
+
+@cython.cdivision(True)
+cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides,
+ char *dst_data, Py_ssize_t *dst_strides,
+ Py_ssize_t *src_shape, Py_ssize_t *dst_shape,
+ int ndim, size_t itemsize) nogil:
+ # Note: src_extent is 1 if we're broadcasting
+ # dst_extent always >= src_extent as we don't do reductions
+ cdef Py_ssize_t i
+ cdef Py_ssize_t src_extent = src_shape[0]
+ cdef Py_ssize_t dst_extent = dst_shape[0]
+ cdef Py_ssize_t src_stride = src_strides[0]
+ cdef Py_ssize_t dst_stride = dst_strides[0]
+
+ if ndim == 1:
+ if (src_stride > 0 and dst_stride > 0 and
+ <size_t> src_stride == itemsize == <size_t> dst_stride):
+ memcpy(dst_data, src_data, itemsize * dst_extent)
+ else:
+ for i in range(dst_extent):
+ memcpy(dst_data, src_data, itemsize)
+ src_data += src_stride
+ dst_data += dst_stride
+ else:
+ for i in range(dst_extent):
+ _copy_strided_to_strided(src_data, src_strides + 1,
+ dst_data, dst_strides + 1,
+ src_shape + 1, dst_shape + 1,
+ ndim - 1, itemsize)
+ src_data += src_stride
+ dst_data += dst_stride
+
+cdef void copy_strided_to_strided({{memviewslice_name}} *src,
+ {{memviewslice_name}} *dst,
+ int ndim, size_t itemsize) nogil:
+ _copy_strided_to_strided(src.data, src.strides, dst.data, dst.strides,
+ src.shape, dst.shape, ndim, itemsize)
+
+@cname('__pyx_memoryview_slice_get_size')
+cdef Py_ssize_t slice_get_size({{memviewslice_name}} *src, int ndim) nogil:
+ "Return the size of the memory occupied by the slice in number of bytes"
cdef Py_ssize_t shape, size = src.memview.view.itemsize
-
+
for shape in src.shape[:ndim]:
size *= shape
-
- return size
-
-@cname('__pyx_fill_contig_strides_array')
-cdef Py_ssize_t fill_contig_strides_array(
- Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride,
- int ndim, char order) nogil:
- """
- Fill the strides array for a slice with C or F contiguous strides.
- This is like PyBuffer_FillContiguousStrides, but compatible with py < 2.6
- """
- cdef int idx
-
- if order == 'F':
- for idx in range(ndim):
- strides[idx] = stride
+
+ return size
+
+@cname('__pyx_fill_contig_strides_array')
+cdef Py_ssize_t fill_contig_strides_array(
+ Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride,
+ int ndim, char order) nogil:
+ """
+ Fill the strides array for a slice with C or F contiguous strides.
+ This is like PyBuffer_FillContiguousStrides, but compatible with py < 2.6
+ """
+ cdef int idx
+
+ if order == 'F':
+ for idx in range(ndim):
+ strides[idx] = stride
stride *= shape[idx]
- else:
- for idx in range(ndim - 1, -1, -1):
- strides[idx] = stride
+ else:
+ for idx in range(ndim - 1, -1, -1):
+ strides[idx] = stride
stride *= shape[idx]
-
- return stride
-
-@cname('__pyx_memoryview_copy_data_to_temp')
-cdef void *copy_data_to_temp({{memviewslice_name}} *src,
- {{memviewslice_name}} *tmpslice,
- char order,
- int ndim) nogil except NULL:
- """
- Copy a direct slice to temporary contiguous memory. The caller should free
- the result when done.
- """
- cdef int i
- cdef void *result
-
- cdef size_t itemsize = src.memview.view.itemsize
- cdef size_t size = slice_get_size(src, ndim)
-
- result = malloc(size)
- if not result:
- _err(MemoryError, NULL)
-
- # tmpslice[0] = src
- tmpslice.data = <char *> result
- tmpslice.memview = src.memview
- for i in range(ndim):
- tmpslice.shape[i] = src.shape[i]
- tmpslice.suboffsets[i] = -1
-
- fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize,
- ndim, order)
-
- # We need to broadcast strides again
- for i in range(ndim):
- if tmpslice.shape[i] == 1:
- tmpslice.strides[i] = 0
-
+
+ return stride
+
+@cname('__pyx_memoryview_copy_data_to_temp')
+cdef void *copy_data_to_temp({{memviewslice_name}} *src,
+ {{memviewslice_name}} *tmpslice,
+ char order,
+ int ndim) nogil except NULL:
+ """
+ Copy a direct slice to temporary contiguous memory. The caller should free
+ the result when done.
+ """
+ cdef int i
+ cdef void *result
+
+ cdef size_t itemsize = src.memview.view.itemsize
+ cdef size_t size = slice_get_size(src, ndim)
+
+ result = malloc(size)
+ if not result:
+ _err(MemoryError, NULL)
+
+ # tmpslice[0] = src
+ tmpslice.data = <char *> result
+ tmpslice.memview = src.memview
+ for i in range(ndim):
+ tmpslice.shape[i] = src.shape[i]
+ tmpslice.suboffsets[i] = -1
+
+ fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize,
+ ndim, order)
+
+ # We need to broadcast strides again
+ for i in range(ndim):
+ if tmpslice.shape[i] == 1:
+ tmpslice.strides[i] = 0
+
if slice_is_contig(src[0], order, ndim):
- memcpy(result, src.data, size)
- else:
- copy_strided_to_strided(src, tmpslice, ndim, itemsize)
-
- return result
-
-# Use 'with gil' functions and avoid 'with gil' blocks, as the code within the blocks
-# has temporaries that need the GIL to clean up
-@cname('__pyx_memoryview_err_extents')
-cdef int _err_extents(int i, Py_ssize_t extent1,
- Py_ssize_t extent2) except -1 with gil:
- raise ValueError("got differing extents in dimension %d (got %d and %d)" %
- (i, extent1, extent2))
-
-@cname('__pyx_memoryview_err_dim')
-cdef int _err_dim(object error, char *msg, int dim) except -1 with gil:
- raise error(msg.decode('ascii') % dim)
-
-@cname('__pyx_memoryview_err')
-cdef int _err(object error, char *msg) except -1 with gil:
- if msg != NULL:
- raise error(msg.decode('ascii'))
- else:
- raise error
-
-@cname('__pyx_memoryview_copy_contents')
-cdef int memoryview_copy_contents({{memviewslice_name}} src,
- {{memviewslice_name}} dst,
- int src_ndim, int dst_ndim,
- bint dtype_is_object) nogil except -1:
- """
- Copy memory from slice src to slice dst.
- Check for overlapping memory and verify the shapes.
- """
- cdef void *tmpdata = NULL
- cdef size_t itemsize = src.memview.view.itemsize
- cdef int i
- cdef char order = get_best_order(&src, src_ndim)
- cdef bint broadcasting = False
- cdef bint direct_copy = False
- cdef {{memviewslice_name}} tmp
-
- if src_ndim < dst_ndim:
- broadcast_leading(&src, src_ndim, dst_ndim)
- elif dst_ndim < src_ndim:
- broadcast_leading(&dst, dst_ndim, src_ndim)
-
- cdef int ndim = max(src_ndim, dst_ndim)
-
- for i in range(ndim):
- if src.shape[i] != dst.shape[i]:
- if src.shape[i] == 1:
- broadcasting = True
- src.strides[i] = 0
- else:
- _err_extents(i, dst.shape[i], src.shape[i])
-
- if src.suboffsets[i] >= 0:
- _err_dim(ValueError, "Dimension %d is not direct", i)
-
- if slices_overlap(&src, &dst, ndim, itemsize):
- # slices overlap, copy to temp, copy temp to dst
+ memcpy(result, src.data, size)
+ else:
+ copy_strided_to_strided(src, tmpslice, ndim, itemsize)
+
+ return result
+
+# Use 'with gil' functions and avoid 'with gil' blocks, as the code within the blocks
+# has temporaries that need the GIL to clean up
+@cname('__pyx_memoryview_err_extents')
+cdef int _err_extents(int i, Py_ssize_t extent1,
+ Py_ssize_t extent2) except -1 with gil:
+ raise ValueError("got differing extents in dimension %d (got %d and %d)" %
+ (i, extent1, extent2))
+
+@cname('__pyx_memoryview_err_dim')
+cdef int _err_dim(object error, char *msg, int dim) except -1 with gil:
+ raise error(msg.decode('ascii') % dim)
+
+@cname('__pyx_memoryview_err')
+cdef int _err(object error, char *msg) except -1 with gil:
+ if msg != NULL:
+ raise error(msg.decode('ascii'))
+ else:
+ raise error
+
+@cname('__pyx_memoryview_copy_contents')
+cdef int memoryview_copy_contents({{memviewslice_name}} src,
+ {{memviewslice_name}} dst,
+ int src_ndim, int dst_ndim,
+ bint dtype_is_object) nogil except -1:
+ """
+ Copy memory from slice src to slice dst.
+ Check for overlapping memory and verify the shapes.
+ """
+ cdef void *tmpdata = NULL
+ cdef size_t itemsize = src.memview.view.itemsize
+ cdef int i
+ cdef char order = get_best_order(&src, src_ndim)
+ cdef bint broadcasting = False
+ cdef bint direct_copy = False
+ cdef {{memviewslice_name}} tmp
+
+ if src_ndim < dst_ndim:
+ broadcast_leading(&src, src_ndim, dst_ndim)
+ elif dst_ndim < src_ndim:
+ broadcast_leading(&dst, dst_ndim, src_ndim)
+
+ cdef int ndim = max(src_ndim, dst_ndim)
+
+ for i in range(ndim):
+ if src.shape[i] != dst.shape[i]:
+ if src.shape[i] == 1:
+ broadcasting = True
+ src.strides[i] = 0
+ else:
+ _err_extents(i, dst.shape[i], src.shape[i])
+
+ if src.suboffsets[i] >= 0:
+ _err_dim(ValueError, "Dimension %d is not direct", i)
+
+ if slices_overlap(&src, &dst, ndim, itemsize):
+ # slices overlap, copy to temp, copy temp to dst
if not slice_is_contig(src, order, ndim):
- order = get_best_order(&dst, ndim)
-
- tmpdata = copy_data_to_temp(&src, &tmp, order, ndim)
- src = tmp
-
- if not broadcasting:
- # See if both slices have equal contiguity, in that case perform a
- # direct copy. This only works when we are not broadcasting.
+ order = get_best_order(&dst, ndim)
+
+ tmpdata = copy_data_to_temp(&src, &tmp, order, ndim)
+ src = tmp
+
+ if not broadcasting:
+ # See if both slices have equal contiguity, in that case perform a
+ # direct copy. This only works when we are not broadcasting.
if slice_is_contig(src, 'C', ndim):
direct_copy = slice_is_contig(dst, 'C', ndim)
elif slice_is_contig(src, 'F', ndim):
direct_copy = slice_is_contig(dst, 'F', ndim)
-
- if direct_copy:
- # Contiguous slices with same order
- refcount_copying(&dst, dtype_is_object, ndim, False)
- memcpy(dst.data, src.data, slice_get_size(&src, ndim))
- refcount_copying(&dst, dtype_is_object, ndim, True)
- free(tmpdata)
- return 0
-
- if order == 'F' == get_best_order(&dst, ndim):
- # see if both slices have Fortran order, transpose them to match our
- # C-style indexing order
- transpose_memslice(&src)
- transpose_memslice(&dst)
-
- refcount_copying(&dst, dtype_is_object, ndim, False)
- copy_strided_to_strided(&src, &dst, ndim, itemsize)
- refcount_copying(&dst, dtype_is_object, ndim, True)
-
- free(tmpdata)
- return 0
-
-@cname('__pyx_memoryview_broadcast_leading')
+
+ if direct_copy:
+ # Contiguous slices with same order
+ refcount_copying(&dst, dtype_is_object, ndim, False)
+ memcpy(dst.data, src.data, slice_get_size(&src, ndim))
+ refcount_copying(&dst, dtype_is_object, ndim, True)
+ free(tmpdata)
+ return 0
+
+ if order == 'F' == get_best_order(&dst, ndim):
+ # see if both slices have Fortran order, transpose them to match our
+ # C-style indexing order
+ transpose_memslice(&src)
+ transpose_memslice(&dst)
+
+ refcount_copying(&dst, dtype_is_object, ndim, False)
+ copy_strided_to_strided(&src, &dst, ndim, itemsize)
+ refcount_copying(&dst, dtype_is_object, ndim, True)
+
+ free(tmpdata)
+ return 0
+
+@cname('__pyx_memoryview_broadcast_leading')
cdef void broadcast_leading({{memviewslice_name}} *mslice,
- int ndim,
- int ndim_other) nogil:
- cdef int i
- cdef int offset = ndim_other - ndim
-
- for i in range(ndim - 1, -1, -1):
+ int ndim,
+ int ndim_other) nogil:
+ cdef int i
+ cdef int offset = ndim_other - ndim
+
+ for i in range(ndim - 1, -1, -1):
mslice.shape[i + offset] = mslice.shape[i]
mslice.strides[i + offset] = mslice.strides[i]
mslice.suboffsets[i + offset] = mslice.suboffsets[i]
-
- for i in range(offset):
+
+ for i in range(offset):
mslice.shape[i] = 1
mslice.strides[i] = mslice.strides[0]
mslice.suboffsets[i] = -1
-
-#
+
+#
### Take care of refcounting the objects in slices. Do this separately from any copying,
-### to minimize acquiring the GIL
-#
-
-@cname('__pyx_memoryview_refcount_copying')
-cdef void refcount_copying({{memviewslice_name}} *dst, bint dtype_is_object,
- int ndim, bint inc) nogil:
- # incref or decref the objects in the destination slice if the dtype is
- # object
- if dtype_is_object:
- refcount_objects_in_slice_with_gil(dst.data, dst.shape,
- dst.strides, ndim, inc)
-
-@cname('__pyx_memoryview_refcount_objects_in_slice_with_gil')
-cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape,
- Py_ssize_t *strides, int ndim,
- bint inc) with gil:
- refcount_objects_in_slice(data, shape, strides, ndim, inc)
-
-@cname('__pyx_memoryview_refcount_objects_in_slice')
-cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape,
- Py_ssize_t *strides, int ndim, bint inc):
- cdef Py_ssize_t i
-
- for i in range(shape[0]):
- if ndim == 1:
- if inc:
- Py_INCREF((<PyObject **> data)[0])
- else:
- Py_DECREF((<PyObject **> data)[0])
- else:
- refcount_objects_in_slice(data, shape + 1, strides + 1,
- ndim - 1, inc)
-
- data += strides[0]
-
-#
-### Scalar to slice assignment
-#
-@cname('__pyx_memoryview_slice_assign_scalar')
-cdef void slice_assign_scalar({{memviewslice_name}} *dst, int ndim,
- size_t itemsize, void *item,
- bint dtype_is_object) nogil:
- refcount_copying(dst, dtype_is_object, ndim, False)
- _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim,
- itemsize, item)
- refcount_copying(dst, dtype_is_object, ndim, True)
-
-
-@cname('__pyx_memoryview__slice_assign_scalar')
-cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape,
- Py_ssize_t *strides, int ndim,
- size_t itemsize, void *item) nogil:
- cdef Py_ssize_t i
- cdef Py_ssize_t stride = strides[0]
- cdef Py_ssize_t extent = shape[0]
-
- if ndim == 1:
- for i in range(extent):
- memcpy(data, item, itemsize)
- data += stride
- else:
- for i in range(extent):
- _slice_assign_scalar(data, shape + 1, strides + 1,
- ndim - 1, itemsize, item)
- data += stride
-
-
-############### BufferFormatFromTypeInfo ###############
-cdef extern from *:
- ctypedef struct __Pyx_StructField
-
- cdef enum:
- __PYX_BUF_FLAGS_PACKED_STRUCT
- __PYX_BUF_FLAGS_INTEGER_COMPLEX
-
- ctypedef struct __Pyx_TypeInfo:
- char* name
- __Pyx_StructField* fields
- size_t size
- size_t arraysize[8]
- int ndim
- char typegroup
- char is_unsigned
- int flags
-
- ctypedef struct __Pyx_StructField:
- __Pyx_TypeInfo* type
- char* name
- size_t offset
-
- ctypedef struct __Pyx_BufFmt_StackElem:
- __Pyx_StructField* field
- size_t parent_offset
-
- #ctypedef struct __Pyx_BufFmt_Context:
- # __Pyx_StructField root
- __Pyx_BufFmt_StackElem* head
-
- struct __pyx_typeinfo_string:
- char string[3]
-
- __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *)
-
-
-@cname('__pyx_format_from_typeinfo')
-cdef bytes format_from_typeinfo(__Pyx_TypeInfo *type):
- cdef __Pyx_StructField *field
- cdef __pyx_typeinfo_string fmt
- cdef bytes part, result
-
- if type.typegroup == 'S':
+### to minimize acquiring the GIL
+#
+
+@cname('__pyx_memoryview_refcount_copying')
+cdef void refcount_copying({{memviewslice_name}} *dst, bint dtype_is_object,
+ int ndim, bint inc) nogil:
+ # incref or decref the objects in the destination slice if the dtype is
+ # object
+ if dtype_is_object:
+ refcount_objects_in_slice_with_gil(dst.data, dst.shape,
+ dst.strides, ndim, inc)
+
+@cname('__pyx_memoryview_refcount_objects_in_slice_with_gil')
+cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape,
+ Py_ssize_t *strides, int ndim,
+ bint inc) with gil:
+ refcount_objects_in_slice(data, shape, strides, ndim, inc)
+
+@cname('__pyx_memoryview_refcount_objects_in_slice')
+cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape,
+ Py_ssize_t *strides, int ndim, bint inc):
+ cdef Py_ssize_t i
+
+ for i in range(shape[0]):
+ if ndim == 1:
+ if inc:
+ Py_INCREF((<PyObject **> data)[0])
+ else:
+ Py_DECREF((<PyObject **> data)[0])
+ else:
+ refcount_objects_in_slice(data, shape + 1, strides + 1,
+ ndim - 1, inc)
+
+ data += strides[0]
+
+#
+### Scalar to slice assignment
+#
+@cname('__pyx_memoryview_slice_assign_scalar')
+cdef void slice_assign_scalar({{memviewslice_name}} *dst, int ndim,
+ size_t itemsize, void *item,
+ bint dtype_is_object) nogil:
+ refcount_copying(dst, dtype_is_object, ndim, False)
+ _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim,
+ itemsize, item)
+ refcount_copying(dst, dtype_is_object, ndim, True)
+
+
+@cname('__pyx_memoryview__slice_assign_scalar')
+cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape,
+ Py_ssize_t *strides, int ndim,
+ size_t itemsize, void *item) nogil:
+ cdef Py_ssize_t i
+ cdef Py_ssize_t stride = strides[0]
+ cdef Py_ssize_t extent = shape[0]
+
+ if ndim == 1:
+ for i in range(extent):
+ memcpy(data, item, itemsize)
+ data += stride
+ else:
+ for i in range(extent):
+ _slice_assign_scalar(data, shape + 1, strides + 1,
+ ndim - 1, itemsize, item)
+ data += stride
+
+
+############### BufferFormatFromTypeInfo ###############
+cdef extern from *:
+ ctypedef struct __Pyx_StructField
+
+ cdef enum:
+ __PYX_BUF_FLAGS_PACKED_STRUCT
+ __PYX_BUF_FLAGS_INTEGER_COMPLEX
+
+ ctypedef struct __Pyx_TypeInfo:
+ char* name
+ __Pyx_StructField* fields
+ size_t size
+ size_t arraysize[8]
+ int ndim
+ char typegroup
+ char is_unsigned
+ int flags
+
+ ctypedef struct __Pyx_StructField:
+ __Pyx_TypeInfo* type
+ char* name
+ size_t offset
+
+ ctypedef struct __Pyx_BufFmt_StackElem:
+ __Pyx_StructField* field
+ size_t parent_offset
+
+ #ctypedef struct __Pyx_BufFmt_Context:
+ # __Pyx_StructField root
+ __Pyx_BufFmt_StackElem* head
+
+ struct __pyx_typeinfo_string:
+ char string[3]
+
+ __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *)
+
+
+@cname('__pyx_format_from_typeinfo')
+cdef bytes format_from_typeinfo(__Pyx_TypeInfo *type):
+ cdef __Pyx_StructField *field
+ cdef __pyx_typeinfo_string fmt
+ cdef bytes part, result
+
+ if type.typegroup == 'S':
assert type.fields != NULL
assert type.fields.type != NULL
-
- if type.flags & __PYX_BUF_FLAGS_PACKED_STRUCT:
- alignment = b'^'
- else:
- alignment = b''
-
- parts = [b"T{"]
- field = type.fields
-
- while field.type:
- part = format_from_typeinfo(field.type)
- parts.append(part + b':' + field.name + b':')
- field += 1
-
- result = alignment.join(parts) + b'}'
- else:
- fmt = __Pyx_TypeInfoToFormat(type)
- if type.arraysize[0]:
- extents = [unicode(type.arraysize[i]) for i in range(type.ndim)]
- result = (u"(%s)" % u','.join(extents)).encode('ascii') + fmt.string
- else:
- result = fmt.string
-
- return result
+
+ if type.flags & __PYX_BUF_FLAGS_PACKED_STRUCT:
+ alignment = b'^'
+ else:
+ alignment = b''
+
+ parts = [b"T{"]
+ field = type.fields
+
+ while field.type:
+ part = format_from_typeinfo(field.type)
+ parts.append(part + b':' + field.name + b':')
+ field += 1
+
+ result = alignment.join(parts) + b'}'
+ else:
+ fmt = __Pyx_TypeInfoToFormat(type)
+ if type.arraysize[0]:
+ extents = [unicode(type.arraysize[i]) for i in range(type.ndim)]
+ result = (u"(%s)" % u','.join(extents)).encode('ascii') + fmt.string
+ else:
+ result = fmt.string
+
+ return result