Home | History | Annotate | Download | only in Utility
      1 #################### View.MemoryView ####################
      2 
      3 # This utility provides cython.array and cython.view.memoryview
      4 
      5 import cython
      6 
      7 # from cpython cimport ...
      8 cdef extern from "Python.h":
      9     int PyIndex_Check "__Pyx_PyIndex_Check" (object)
     10     object PyLong_FromVoidPtr(void *)
     11 
     12 cdef extern from "pythread.h":
     13     ctypedef void *PyThread_type_lock
     14 
     15     PyThread_type_lock PyThread_allocate_lock()
     16     void PyThread_free_lock(PyThread_type_lock)
     17     int PyThread_acquire_lock(PyThread_type_lock, int mode) nogil
     18     void PyThread_release_lock(PyThread_type_lock) nogil
     19 
     20 cdef extern from "string.h":
     21     void *memset(void *b, int c, size_t len)
     22 
     23 cdef extern from *:
     24     int __Pyx_GetBuffer(object, Py_buffer *, int) except -1
     25     void __Pyx_ReleaseBuffer(Py_buffer *)
     26 
     27     ctypedef struct PyObject
     28     ctypedef Py_ssize_t Py_intptr_t
     29     void Py_INCREF(PyObject *)
     30     void Py_DECREF(PyObject *)
     31 
     32     void* PyMem_Malloc(size_t n)
     33     void PyMem_Free(void *p)
     34 
     35     cdef struct __pyx_memoryview "__pyx_memoryview_obj":
     36         Py_buffer view
     37         PyObject *obj
     38         __Pyx_TypeInfo *typeinfo
     39 
     40     ctypedef struct {{memviewslice_name}}:
     41         __pyx_memoryview *memview
     42         char *data
     43         Py_ssize_t shape[{{max_dims}}]
     44         Py_ssize_t strides[{{max_dims}}]
     45         Py_ssize_t suboffsets[{{max_dims}}]
     46 
     47     void __PYX_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
     48     void __PYX_XDEC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
     49 
     50     ctypedef struct __pyx_buffer "Py_buffer":
     51         PyObject *obj
     52 
     53     PyObject *Py_None
     54 
     55     cdef enum:
     56         PyBUF_C_CONTIGUOUS,
     57         PyBUF_F_CONTIGUOUS,
     58         PyBUF_ANY_CONTIGUOUS
     59         PyBUF_FORMAT
     60         PyBUF_WRITABLE
     61         PyBUF_STRIDES
     62         PyBUF_INDIRECT
     63         PyBUF_RECORDS
     64 
     65     ctypedef struct __Pyx_TypeInfo:
     66         pass
     67 
     68     cdef object capsule "__pyx_capsule_create" (void *p, char *sig)
     69     cdef int __pyx_array_getbuffer(PyObject *obj, Py_buffer view, int flags)
     70     cdef int __pyx_memoryview_getbuffer(PyObject *obj, Py_buffer view, int flags)
     71 
     72 cdef extern from *:
     73     ctypedef int __pyx_atomic_int
     74     {{memviewslice_name}} slice_copy_contig "__pyx_memoryview_copy_new_contig"(
     75                                  __Pyx_memviewslice *from_mvs,
     76                                  char *mode, int ndim,
     77                                  size_t sizeof_dtype, int contig_flag,
     78                                  bint dtype_is_object) nogil except *
     79     bint slice_is_contig "__pyx_memviewslice_is_contig" (
     80                             {{memviewslice_name}} *mvs, char order, int ndim) nogil
     81     bint slices_overlap "__pyx_slices_overlap" ({{memviewslice_name}} *slice1,
     82                                                 {{memviewslice_name}} *slice2,
     83                                                 int ndim, size_t itemsize) nogil
     84 
     85 
     86 cdef extern from "stdlib.h":
     87     void *malloc(size_t) nogil
     88     void free(void *) nogil
     89     void *memcpy(void *dest, void *src, size_t n) nogil
     90 
     91 
     92 
     93 
     94 #
     95 ### cython.array class
     96 #
     97 
     98 @cname("__pyx_array")
     99 cdef class array:
    100 
    101     cdef:
    102         char *data
    103         Py_ssize_t len
    104         char *format
    105         int ndim
    106         Py_ssize_t *_shape
    107         Py_ssize_t *_strides
    108         Py_ssize_t itemsize
    109         unicode mode  # FIXME: this should have been a simple 'char'
    110         bytes _format
    111         void (*callback_free_data)(void *data)
    112         # cdef object _memview
    113         cdef bint free_data
    114         cdef bint dtype_is_object
    115 
    116     def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None,
    117                   mode="c", bint allocate_buffer=True):
    118 
    119         cdef int idx
    120         cdef Py_ssize_t i, dim
    121         cdef PyObject **p
    122 
    123         self.ndim = <int> len(shape)
    124         self.itemsize = itemsize
    125 
    126         if not self.ndim:
    127             raise ValueError("Empty shape tuple for cython.array")
    128 
    129         if itemsize <= 0:
    130             raise ValueError("itemsize <= 0 for cython.array")
    131 
    132         if isinstance(format, unicode):
    133             format = (<unicode>format).encode('ASCII')
    134         self._format = format  # keep a reference to the byte string
    135         self.format = self._format
    136 
    137         # use single malloc() for both shape and strides
    138         self._shape = <Py_ssize_t *> PyMem_Malloc(sizeof(Py_ssize_t)*self.ndim*2)
    139         self._strides = self._shape + self.ndim
    140 
    141         if not self._shape:
    142             raise MemoryError("unable to allocate shape and strides.")
    143 
    144         # cdef Py_ssize_t dim, stride
    145         for idx, dim in enumerate(shape):
    146             if dim <= 0:
    147                 raise ValueError("Invalid shape in axis %d: %d." % (idx, dim))
    148             self._shape[idx] = dim
    149 
    150         cdef char order
    151         if mode == 'fortran':
    152             order = b'F'
    153             self.mode = u'fortran'
    154         elif mode == 'c':
    155             order = b'C'
    156             self.mode = u'c'
    157         else:
    158             raise ValueError("Invalid mode, expected 'c' or 'fortran', got %s" % mode)
    159 
    160         self.len = fill_contig_strides_array(self._shape, self._strides,
    161                                              itemsize, self.ndim, order)
    162 
    163         self.free_data = allocate_buffer
    164         self.dtype_is_object = format == b'O'
    165         if allocate_buffer:
    166             # use malloc() for backwards compatibility
    167             # in case external code wants to change the data pointer
    168             self.data = <char *>malloc(self.len)
    169             if not self.data:
    170                 raise MemoryError("unable to allocate array data.")
    171 
    172             if self.dtype_is_object:
    173                 p = <PyObject **> self.data
    174                 for i in range(self.len / itemsize):
    175                     p[i] = Py_None
    176                     Py_INCREF(Py_None)
    177 
    178     @cname('getbuffer')
    179     def __getbuffer__(self, Py_buffer *info, int flags):
    180         cdef int bufmode = -1
    181         if self.mode == u"c":
    182             bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
    183         elif self.mode == u"fortran":
    184             bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
    185         if not (flags & bufmode):
    186             raise ValueError("Can only create a buffer that is contiguous in memory.")
    187         info.buf = self.data
    188         info.len = self.len
    189         info.ndim = self.ndim
    190         info.shape = self._shape
    191         info.strides = self._strides
    192         info.suboffsets = NULL
    193         info.itemsize = self.itemsize
    194         info.readonly = 0
    195 
    196         if flags & PyBUF_FORMAT:
    197             info.format = self.format
    198         else:
    199             info.format = NULL
    200 
    201         info.obj = self
    202 
    203     __pyx_getbuffer = capsule(<void *> &__pyx_array_getbuffer, "getbuffer(obj, view, flags)")
    204 
    205     def __dealloc__(array self):
    206         if self.callback_free_data != NULL:
    207             self.callback_free_data(self.data)
    208         elif self.free_data:
    209             if self.dtype_is_object:
    210                 refcount_objects_in_slice(self.data, self._shape,
    211                                           self._strides, self.ndim, False)
    212             free(self.data)
    213         PyMem_Free(self._shape)
    214 
    215     property memview:
    216         @cname('get_memview')
    217         def __get__(self):
    218             # Make this a property as 'self.data' may be set after instantiation
    219             flags =  PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE
    220             return  memoryview(self, flags, self.dtype_is_object)
    221 
    222 
    223     def __getattr__(self, attr):
    224         return getattr(self.memview, attr)
    225 
    226     def __getitem__(self, item):
    227         return self.memview[item]
    228 
    229     def __setitem__(self, item, value):
    230         self.memview[item] = value
    231 
    232 
    233 @cname("__pyx_array_new")
    234 cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format,
    235                           char *mode, char *buf):
    236     cdef array result
    237 
    238     if buf == NULL:
    239         result = array(shape, itemsize, format, mode.decode('ASCII'))
    240     else:
    241         result = array(shape, itemsize, format, mode.decode('ASCII'),
    242                        allocate_buffer=False)
    243         result.data = buf
    244 
    245     return result
    246 
    247 
    248 #
    249 ### Memoryview constants and cython.view.memoryview class
    250 #
    251 
    252 # Disable generic_contiguous, as it makes trouble verifying contiguity:
    253 #   - 'contiguous' or '::1' means the dimension is contiguous with dtype
    254 #   - 'indirect_contiguous' means a contiguous list of pointers
    255 #   - dtype contiguous must be contiguous in the first or last dimension
    256 #     from the start, or from the dimension following the last indirect dimension
    257 #
    258 #   e.g.
    259 #           int[::indirect_contiguous, ::contiguous, :]
    260 #
    261 #   is valid (list of pointers to 2d fortran-contiguous array), but
    262 #
    263 #           int[::generic_contiguous, ::contiguous, :]
    264 #
    265 #   would mean you'd have assert dimension 0 to be indirect (and pointer contiguous) at runtime.
    266 #   So it doesn't bring any performance benefit, and it's only confusing.
    267 
    268 @cname('__pyx_MemviewEnum')
    269 cdef class Enum(object):
    270     cdef object name
    271     def __init__(self, name):
    272         self.name = name
    273     def __repr__(self):
    274         return self.name
    275 
    276 cdef generic = Enum("<strided and direct or indirect>")
    277 cdef strided = Enum("<strided and direct>") # default
    278 cdef indirect = Enum("<strided and indirect>")
    279 # Disable generic_contiguous, as it is a troublemaker
    280 #cdef generic_contiguous = Enum("<contiguous and direct or indirect>")
    281 cdef contiguous = Enum("<contiguous and direct>")
    282 cdef indirect_contiguous = Enum("<contiguous and indirect>")
    283 
    284 # 'follow' is implied when the first or last axis is ::1
    285 
    286 
    287 @cname('__pyx_align_pointer')
    288 cdef void *align_pointer(void *memory, size_t alignment) nogil:
    289     "Align pointer memory on a given boundary"
    290     cdef Py_intptr_t aligned_p = <Py_intptr_t> memory
    291     cdef size_t offset
    292 
    293     with cython.cdivision(True):
    294         offset = aligned_p % alignment
    295 
    296     if offset > 0:
    297         aligned_p += alignment - offset
    298 
    299     return <void *> aligned_p
    300 
    301 @cname('__pyx_memoryview')
    302 cdef class memoryview(object):
    303 
    304     cdef object obj
    305     cdef object _size
    306     cdef object _array_interface
    307     cdef PyThread_type_lock lock
    308     # the following array will contain a single __pyx_atomic int with
    309     # suitable alignment
    310     cdef __pyx_atomic_int acquisition_count[2]
    311     cdef __pyx_atomic_int *acquisition_count_aligned_p
    312     cdef Py_buffer view
    313     cdef int flags
    314     cdef bint dtype_is_object
    315     cdef __Pyx_TypeInfo *typeinfo
    316 
    317     def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False):
    318         self.obj = obj
    319         self.flags = flags
    320         if type(self) is memoryview or obj is not None:
    321             __Pyx_GetBuffer(obj, &self.view, flags)
    322             if <PyObject *> self.view.obj == NULL:
    323                 (<__pyx_buffer *> &self.view).obj = Py_None
    324                 Py_INCREF(Py_None)
    325 
    326         self.lock = PyThread_allocate_lock()
    327         if self.lock == NULL:
    328             raise MemoryError
    329 
    330         if flags & PyBUF_FORMAT:
    331             self.dtype_is_object = self.view.format == b'O'
    332         else:
    333             self.dtype_is_object = dtype_is_object
    334 
    335         self.acquisition_count_aligned_p = <__pyx_atomic_int *> align_pointer(
    336                   <void *> &self.acquisition_count[0], sizeof(__pyx_atomic_int))
    337         self.typeinfo = NULL
    338 
    339     def __dealloc__(memoryview self):
    340         if self.obj is not None:
    341             __Pyx_ReleaseBuffer(&self.view)
    342 
    343         if self.lock != NULL:
    344             PyThread_free_lock(self.lock)
    345 
    346     cdef char *get_item_pointer(memoryview self, object index) except NULL:
    347         cdef Py_ssize_t dim
    348         cdef char *itemp = <char *> self.view.buf
    349 
    350         for dim, idx in enumerate(index):
    351             itemp = pybuffer_index(&self.view, itemp, idx, dim)
    352 
    353         return itemp
    354 
    355     #@cname('__pyx_memoryview_getitem')
    356     def __getitem__(memoryview self, object index):
    357         if index is Ellipsis:
    358             return self
    359 
    360         have_slices, indices = _unellipsify(index, self.view.ndim)
    361 
    362         cdef char *itemp
    363         if have_slices:
    364             return memview_slice(self, indices)
    365         else:
    366             itemp = self.get_item_pointer(indices)
    367             return self.convert_item_to_object(itemp)
    368 
    369     def __setitem__(memoryview self, object index, object value):
    370         have_slices, index = _unellipsify(index, self.view.ndim)
    371 
    372         if have_slices:
    373             obj = self.is_slice(value)
    374             if obj:
    375                 self.setitem_slice_assignment(self[index], obj)
    376             else:
    377                 self.setitem_slice_assign_scalar(self[index], value)
    378         else:
    379             self.setitem_indexed(index, value)
    380 
    381     cdef is_slice(self, obj):
    382         if not isinstance(obj, memoryview):
    383             try:
    384                 obj = memoryview(obj, self.flags|PyBUF_ANY_CONTIGUOUS,
    385                                  self.dtype_is_object)
    386             except TypeError:
    387                 return None
    388 
    389         return obj
    390 
    391     cdef setitem_slice_assignment(self, dst, src):
    392         cdef {{memviewslice_name}} dst_slice
    393         cdef {{memviewslice_name}} src_slice
    394 
    395         memoryview_copy_contents(get_slice_from_memview(src, &src_slice)[0],
    396                                  get_slice_from_memview(dst, &dst_slice)[0],
    397                                  src.ndim, dst.ndim, self.dtype_is_object)
    398 
    399     cdef setitem_slice_assign_scalar(self, memoryview dst, value):
    400         cdef int array[128]
    401         cdef void *tmp = NULL
    402         cdef void *item
    403 
    404         cdef {{memviewslice_name}} *dst_slice
    405         cdef {{memviewslice_name}} tmp_slice
    406         dst_slice = get_slice_from_memview(dst, &tmp_slice)
    407 
    408         if <size_t>self.view.itemsize > sizeof(array):
    409             tmp = PyMem_Malloc(self.view.itemsize)
    410             if tmp == NULL:
    411                 raise MemoryError
    412             item = tmp
    413         else:
    414             item = <void *> array
    415 
    416         try:
    417             if self.dtype_is_object:
    418                 (<PyObject **> item)[0] = <PyObject *> value
    419             else:
    420                 self.assign_item_from_object(<char *> item, value)
    421 
    422             # It would be easy to support indirect dimensions, but it's easier
    423             # to disallow :)
    424             if self.view.suboffsets != NULL:
    425                 assert_direct_dimensions(self.view.suboffsets, self.view.ndim)
    426             slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize,
    427                                 item, self.dtype_is_object)
    428         finally:
    429             PyMem_Free(tmp)
    430 
    431     cdef setitem_indexed(self, index, value):
    432         cdef char *itemp = self.get_item_pointer(index)
    433         self.assign_item_from_object(itemp, value)
    434 
    435     cdef convert_item_to_object(self, char *itemp):
    436         """Only used if instantiated manually by the user, or if Cython doesn't
    437         know how to convert the type"""
    438         import struct
    439         cdef bytes bytesitem
    440         # Do a manual and complete check here instead of this easy hack
    441         bytesitem = itemp[:self.view.itemsize]
    442         try:
    443             result = struct.unpack(self.view.format, bytesitem)
    444         except struct.error:
    445             raise ValueError("Unable to convert item to object")
    446         else:
    447             if len(self.view.format) == 1:
    448                 return result[0]
    449             return result
    450 
    451     cdef assign_item_from_object(self, char *itemp, object value):
    452         """Only used if instantiated manually by the user, or if Cython doesn't
    453         know how to convert the type"""
    454         import struct
    455         cdef char c
    456         cdef bytes bytesvalue
    457         cdef Py_ssize_t i
    458 
    459         if isinstance(value, tuple):
    460             bytesvalue = struct.pack(self.view.format, *value)
    461         else:
    462             bytesvalue = struct.pack(self.view.format, value)
    463 
    464         for i, c in enumerate(bytesvalue):
    465             itemp[i] = c
    466 
    467     @cname('getbuffer')
    468     def __getbuffer__(self, Py_buffer *info, int flags):
    469         if flags & PyBUF_STRIDES:
    470             info.shape = self.view.shape
    471         else:
    472             info.shape = NULL
    473 
    474         if flags & PyBUF_STRIDES:
    475             info.strides = self.view.strides
    476         else:
    477             info.strides = NULL
    478 
    479         if flags & PyBUF_INDIRECT:
    480             info.suboffsets = self.view.suboffsets
    481         else:
    482             info.suboffsets = NULL
    483 
    484         if flags & PyBUF_FORMAT:
    485             info.format = self.view.format
    486         else:
    487             info.format = NULL
    488 
    489         info.buf = self.view.buf
    490         info.ndim = self.view.ndim
    491         info.itemsize = self.view.itemsize
    492         info.len = self.view.len
    493         info.readonly = 0
    494         info.obj = self
    495 
    496     __pyx_getbuffer = capsule(<void *> &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)")
    497 
    498     # Some properties that have the same sematics as in NumPy
    499     property T:
    500         @cname('__pyx_memoryview_transpose')
    501         def __get__(self):
    502             cdef _memoryviewslice result = memoryview_copy(self)
    503             transpose_memslice(&result.from_slice)
    504             return result
    505 
    506     property base:
    507         @cname('__pyx_memoryview__get__base')
    508         def __get__(self):
    509             return self.obj
    510 
    511     property shape:
    512         @cname('__pyx_memoryview_get_shape')
    513         def __get__(self):
    514             return tuple([self.view.shape[i] for i in xrange(self.view.ndim)])
    515 
    516     property strides:
    517         @cname('__pyx_memoryview_get_strides')
    518         def __get__(self):
    519             if self.view.strides == NULL:
    520                 # Note: we always ask for strides, so if this is not set it's a bug
    521                 raise ValueError("Buffer view does not expose strides")
    522 
    523             return tuple([self.view.strides[i] for i in xrange(self.view.ndim)])
    524 
    525     property suboffsets:
    526         @cname('__pyx_memoryview_get_suboffsets')
    527         def __get__(self):
    528             if self.view.suboffsets == NULL:
    529                 return [-1] * self.view.ndim
    530 
    531             return tuple([self.view.suboffsets[i] for i in xrange(self.view.ndim)])
    532 
    533     property ndim:
    534         @cname('__pyx_memoryview_get_ndim')
    535         def __get__(self):
    536             return self.view.ndim
    537 
    538     property itemsize:
    539         @cname('__pyx_memoryview_get_itemsize')
    540         def __get__(self):
    541             return self.view.itemsize
    542 
    543     property nbytes:
    544         @cname('__pyx_memoryview_get_nbytes')
    545         def __get__(self):
    546             return self.size * self.view.itemsize
    547 
    548     property size:
    549         @cname('__pyx_memoryview_get_size')
    550         def __get__(self):
    551             if self._size is None:
    552                 result = 1
    553 
    554                 for length in self.shape:
    555                     result *= length
    556 
    557                 self._size = result
    558 
    559             return self._size
    560 
    561     def __len__(self):
    562         if self.view.ndim >= 1:
    563             return self.view.shape[0]
    564 
    565         return 0
    566 
    567     def __repr__(self):
    568         return "<MemoryView of %r at 0x%x>" % (self.base.__class__.__name__,
    569                                                id(self))
    570 
    571     def __str__(self):
    572         return "<MemoryView of %r object>" % (self.base.__class__.__name__,)
    573 
    574     # Support the same attributes as memoryview slices
    575     def is_c_contig(self):
    576         cdef {{memviewslice_name}} *mslice
    577         cdef {{memviewslice_name}} tmp
    578         mslice = get_slice_from_memview(self, &tmp)
    579         return slice_is_contig(mslice, 'C', self.view.ndim)
    580 
    581     def is_f_contig(self):
    582         cdef {{memviewslice_name}} *mslice
    583         cdef {{memviewslice_name}} tmp
    584         mslice = get_slice_from_memview(self, &tmp)
    585         return slice_is_contig(mslice, 'F', self.view.ndim)
    586 
    587     def copy(self):
    588         cdef {{memviewslice_name}} mslice
    589         cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS
    590 
    591         slice_copy(self, &mslice)
    592         mslice = slice_copy_contig(&mslice, "c", self.view.ndim,
    593                                    self.view.itemsize,
    594                                    flags|PyBUF_C_CONTIGUOUS,
    595                                    self.dtype_is_object)
    596 
    597         return memoryview_copy_from_slice(self, &mslice)
    598 
    599     def copy_fortran(self):
    600         cdef {{memviewslice_name}} src, dst
    601         cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS
    602 
    603         slice_copy(self, &src)
    604         dst = slice_copy_contig(&src, "fortran", self.view.ndim,
    605                                 self.view.itemsize,
    606                                 flags|PyBUF_F_CONTIGUOUS,
    607                                 self.dtype_is_object)
    608 
    609         return memoryview_copy_from_slice(self, &dst)
    610 
    611 
    612 @cname('__pyx_memoryview_new')
    613 cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo):
    614     cdef memoryview result = memoryview(o, flags, dtype_is_object)
    615     result.typeinfo = typeinfo
    616     return result
    617 
    618 @cname('__pyx_memoryview_check')
    619 cdef inline bint memoryview_check(object o):
    620     return isinstance(o, memoryview)
    621 
    622 cdef tuple _unellipsify(object index, int ndim):
    623     """
    624     Replace all ellipses with full slices and fill incomplete indices with
    625     full slices.
    626     """
    627     if not isinstance(index, tuple):
    628         tup = (index,)
    629     else:
    630         tup = index
    631 
    632     result = []
    633     have_slices = False
    634     seen_ellipsis = False
    635     for idx, item in enumerate(tup):
    636         if item is Ellipsis:
    637             if not seen_ellipsis:
    638                 result.extend([slice(None)] * (ndim - len(tup) + 1))
    639                 seen_ellipsis = True
    640             else:
    641                 result.append(slice(None))
    642             have_slices = True
    643         else:
    644             if not isinstance(item, slice) and not PyIndex_Check(item):
    645                 raise TypeError("Cannot index with type '%s'" % type(item))
    646 
    647             have_slices = have_slices or isinstance(item, slice)
    648             result.append(item)
    649 
    650     nslices = ndim - len(result)
    651     if nslices:
    652         result.extend([slice(None)] * nslices)
    653 
    654     return have_slices or nslices, tuple(result)
    655 
    656 cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim):
    657     cdef int i
    658     for i in range(ndim):
    659         if suboffsets[i] >= 0:
    660             raise ValueError("Indirect dimensions not supported")
    661 
    662 #
    663 ### Slicing a memoryview
    664 #
    665 
    666 @cname('__pyx_memview_slice')
    667 cdef memoryview memview_slice(memoryview memview, object indices):
    668     cdef int new_ndim = 0, suboffset_dim = -1, dim
    669     cdef bint negative_step
    670     cdef {{memviewslice_name}} src, dst
    671     cdef {{memviewslice_name}} *p_src
    672 
    673     # dst is copied by value in memoryview_fromslice -- initialize it
    674     # src is never copied
    675     memset(&dst, 0, sizeof(dst))
    676 
    677     cdef _memoryviewslice memviewsliceobj
    678 
    679     assert memview.view.ndim > 0
    680 
    681     if isinstance(memview, _memoryviewslice):
    682         memviewsliceobj = memview
    683         p_src = &memviewsliceobj.from_slice
    684     else:
    685         slice_copy(memview, &src)
    686         p_src = &src
    687 
    688     # Note: don't use variable src at this point
    689     # SubNote: we should be able to declare variables in blocks...
    690 
    691     # memoryview_fromslice() will inc our dst slice
    692     dst.memview = p_src.memview
    693     dst.data = p_src.data
    694 
    695     # Put everything in temps to avoid this bloody warning:
    696     # "Argument evaluation order in C function call is undefined and
    697     #  may not be as expected"
    698     cdef {{memviewslice_name}} *p_dst = &dst
    699     cdef int *p_suboffset_dim = &suboffset_dim
    700     cdef Py_ssize_t start, stop, step
    701     cdef bint have_start, have_stop, have_step
    702 
    703     for dim, index in enumerate(indices):
    704         if PyIndex_Check(index):
    705             slice_memviewslice(
    706                 p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim],
    707                 dim, new_ndim, p_suboffset_dim,
    708                 index, 0, 0, # start, stop, step
    709                 0, 0, 0, # have_{start,stop,step}
    710                 False)
    711         elif index is None:
    712             p_dst.shape[new_ndim] = 1
    713             p_dst.strides[new_ndim] = 0
    714             p_dst.suboffsets[new_ndim] = -1
    715             new_ndim += 1
    716         else:
    717             start = index.start or 0
    718             stop = index.stop or 0
    719             step = index.step or 0
    720 
    721             have_start = index.start is not None
    722             have_stop = index.stop is not None
    723             have_step = index.step is not None
    724 
    725             slice_memviewslice(
    726                 p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim],
    727                 dim, new_ndim, p_suboffset_dim,
    728                 start, stop, step,
    729                 have_start, have_stop, have_step,
    730                 True)
    731             new_ndim += 1
    732 
    733     if isinstance(memview, _memoryviewslice):
    734         return memoryview_fromslice(dst, new_ndim,
    735                                     memviewsliceobj.to_object_func,
    736                                     memviewsliceobj.to_dtype_func,
    737                                     memview.dtype_is_object)
    738     else:
    739         return memoryview_fromslice(dst, new_ndim, NULL, NULL,
    740                                     memview.dtype_is_object)
    741 
    742 
    743 #
    744 ### Slicing in a single dimension of a memoryviewslice
    745 #
    746 
    747 cdef extern from "stdlib.h":
    748     void abort() nogil
    749     void printf(char *s, ...) nogil
    750 
    751 cdef extern from "stdio.h":
    752     ctypedef struct FILE
    753     FILE *stderr
    754     int fputs(char *s, FILE *stream)
    755 
    756 cdef extern from "pystate.h":
    757     void PyThreadState_Get() nogil
    758 
    759     # These are not actually nogil, but we check for the GIL before calling them
    760     void PyErr_SetString(PyObject *type, char *msg) nogil
    761     PyObject *PyErr_Format(PyObject *exc, char *msg, ...) nogil
    762 
    763 @cname('__pyx_memoryview_slice_memviewslice')
    764 cdef int slice_memviewslice(
    765         {{memviewslice_name}} *dst,
    766         Py_ssize_t shape, Py_ssize_t stride, Py_ssize_t suboffset,
    767         int dim, int new_ndim, int *suboffset_dim,
    768         Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step,
    769         int have_start, int have_stop, int have_step,
    770         bint is_slice) nogil except -1:
    771     """
    772     Create a new slice dst given slice src.
    773 
    774     dim             - the current src dimension (indexing will make dimensions
    775                                                  disappear)
    776     new_dim         - the new dst dimension
    777     suboffset_dim   - pointer to a single int initialized to -1 to keep track of
    778                       where slicing offsets should be added
    779     """
    780 
    781     cdef Py_ssize_t new_shape
    782     cdef bint negative_step
    783 
    784     if not is_slice:
    785         # index is a normal integer-like index
    786         if start < 0:
    787             start += shape
    788         if not 0 <= start < shape:
    789             _err_dim(IndexError, "Index out of bounds (axis %d)", dim)
    790     else:
    791         # index is a slice
    792         negative_step = have_step != 0 and step < 0
    793 
    794         if have_step and step == 0:
    795             _err_dim(ValueError, "Step may not be zero (axis %d)", dim)
    796 
    797         # check our bounds and set defaults
    798         if have_start:
    799             if start < 0:
    800                 start += shape
    801                 if start < 0:
    802                     start = 0
    803             elif start >= shape:
    804                 if negative_step:
    805                     start = shape - 1
    806                 else:
    807                     start = shape
    808         else:
    809             if negative_step:
    810                 start = shape - 1
    811             else:
    812                 start = 0
    813 
    814         if have_stop:
    815             if stop < 0:
    816                 stop += shape
    817                 if stop < 0:
    818                     stop = 0
    819             elif stop > shape:
    820                 stop = shape
    821         else:
    822             if negative_step:
    823                 stop = -1
    824             else:
    825                 stop = shape
    826 
    827         if not have_step:
    828             step = 1
    829 
    830         # len = ceil( (stop - start) / step )
    831         with cython.cdivision(True):
    832             new_shape = (stop - start) // step
    833 
    834             if (stop - start) - step * new_shape:
    835                 new_shape += 1
    836 
    837         if new_shape < 0:
    838             new_shape = 0
    839 
    840         # shape/strides/suboffsets
    841         dst.strides[new_ndim] = stride * step
    842         dst.shape[new_ndim] = new_shape
    843         dst.suboffsets[new_ndim] = suboffset
    844 
    845     # Add the slicing or idexing offsets to the right suboffset or base data *
    846     if suboffset_dim[0] < 0:
    847         dst.data += start * stride
    848     else:
    849         dst.suboffsets[suboffset_dim[0]] += start * stride
    850 
    851     if suboffset >= 0:
    852         if not is_slice:
    853             if new_ndim == 0:
    854                 dst.data = (<char **> dst.data)[0] + suboffset
    855             else:
    856                 _err_dim(IndexError, "All dimensions preceding dimension %d "
    857                                      "must be indexed and not sliced", dim)
    858         else:
    859             suboffset_dim[0] = new_ndim
    860 
    861     return 0
    862 
    863 #
    864 ### Index a memoryview
    865 #
    866 @cname('__pyx_pybuffer_index')
    867 cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index,
    868                           Py_ssize_t dim) except NULL:
    869     cdef Py_ssize_t shape, stride, suboffset = -1
    870     cdef Py_ssize_t itemsize = view.itemsize
    871     cdef char *resultp
    872 
    873     if view.ndim == 0:
    874         shape = view.len / itemsize
    875         stride = itemsize
    876     else:
    877         shape = view.shape[dim]
    878         stride = view.strides[dim]
    879         if view.suboffsets != NULL:
    880             suboffset = view.suboffsets[dim]
    881 
    882     if index < 0:
    883         index += view.shape[dim]
    884         if index < 0:
    885             raise IndexError("Out of bounds on buffer access (axis %d)" % dim)
    886 
    887     if index >= shape:
    888         raise IndexError("Out of bounds on buffer access (axis %d)" % dim)
    889 
    890     resultp = bufp + index * stride
    891     if suboffset >= 0:
    892         resultp = (<char **> resultp)[0] + suboffset
    893 
    894     return resultp
    895 
    896 #
    897 ### Transposing a memoryviewslice
    898 #
    899 @cname('__pyx_memslice_transpose')
    900 cdef int transpose_memslice({{memviewslice_name}} *memslice) nogil except 0:
    901     cdef int ndim = memslice.memview.view.ndim
    902 
    903     cdef Py_ssize_t *shape = memslice.shape
    904     cdef Py_ssize_t *strides = memslice.strides
    905 
    906     # reverse strides and shape
    907     cdef int i, j
    908     for i in range(ndim / 2):
    909         j = ndim - 1 - i
    910         strides[i], strides[j] = strides[j], strides[i]
    911         shape[i], shape[j] = shape[j], shape[i]
    912 
    913         if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0:
    914             _err(ValueError, "Cannot transpose memoryview with indirect dimensions")
    915 
    916     return 1
    917 
    918 #
    919 ### Creating new memoryview objects from slices and memoryviews
    920 #
    921 @cname('__pyx_memoryviewslice')
    922 cdef class _memoryviewslice(memoryview):
    923     "Internal class for passing memoryview slices to Python"
    924 
    925     # We need this to keep our shape/strides/suboffset pointers valid
    926     cdef {{memviewslice_name}} from_slice
    927     # We need this only to print it's class' name
    928     cdef object from_object
    929 
    930     cdef object (*to_object_func)(char *)
    931     cdef int (*to_dtype_func)(char *, object) except 0
    932 
    933     def __dealloc__(self):
    934         __PYX_XDEC_MEMVIEW(&self.from_slice, 1)
    935 
    936     cdef convert_item_to_object(self, char *itemp):
    937         if self.to_object_func != NULL:
    938             return self.to_object_func(itemp)
    939         else:
    940             return memoryview.convert_item_to_object(self, itemp)
    941 
    942     cdef assign_item_from_object(self, char *itemp, object value):
    943         if self.to_dtype_func != NULL:
    944             self.to_dtype_func(itemp, value)
    945         else:
    946             memoryview.assign_item_from_object(self, itemp, value)
    947 
    948     property base:
    949         @cname('__pyx_memoryviewslice__get__base')
    950         def __get__(self):
    951             return self.from_object
    952 
    953     __pyx_getbuffer = capsule(<void *> &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)")
    954 
    955 
    956 @cname('__pyx_memoryview_fromslice')
    957 cdef memoryview_fromslice({{memviewslice_name}} memviewslice,
    958                           int ndim,
    959                           object (*to_object_func)(char *),
    960                           int (*to_dtype_func)(char *, object) except 0,
    961                           bint dtype_is_object):
    962 
    963     cdef _memoryviewslice result
    964     cdef int i
    965 
    966     if <PyObject *> memviewslice.memview == Py_None:
    967         return None
    968 
    969     # assert 0 < ndim <= memviewslice.memview.view.ndim, (
    970     #                 ndim, memviewslice.memview.view.ndim)
    971 
    972     result = _memoryviewslice(None, 0, dtype_is_object)
    973 
    974     result.from_slice = memviewslice
    975     __PYX_INC_MEMVIEW(&memviewslice, 1)
    976 
    977     result.from_object = (<memoryview> memviewslice.memview).base
    978     result.typeinfo = memviewslice.memview.typeinfo
    979 
    980     result.view = memviewslice.memview.view
    981     result.view.buf = <void *> memviewslice.data
    982     result.view.ndim = ndim
    983     (<__pyx_buffer *> &result.view).obj = Py_None
    984     Py_INCREF(Py_None)
    985 
    986     result.flags = PyBUF_RECORDS
    987 
    988     result.view.shape = <Py_ssize_t *> result.from_slice.shape
    989     result.view.strides = <Py_ssize_t *> result.from_slice.strides
    990     result.view.suboffsets = <Py_ssize_t *> result.from_slice.suboffsets
    991 
    992     result.view.len = result.view.itemsize
    993     for i in range(ndim):
    994         result.view.len *= result.view.shape[i]
    995 
    996     result.to_object_func = to_object_func
    997     result.to_dtype_func = to_dtype_func
    998 
    999     return result
   1000 
   1001 @cname('__pyx_memoryview_get_slice_from_memoryview')
   1002 cdef {{memviewslice_name}} *get_slice_from_memview(memoryview memview,
   1003                                                    {{memviewslice_name}} *mslice):
   1004     cdef _memoryviewslice obj
   1005     if isinstance(memview, _memoryviewslice):
   1006         obj = memview
   1007         return &obj.from_slice
   1008     else:
   1009         slice_copy(memview, mslice)
   1010         return mslice
   1011 
   1012 @cname('__pyx_memoryview_slice_copy')
   1013 cdef void slice_copy(memoryview memview, {{memviewslice_name}} *dst):
   1014     cdef int dim
   1015     cdef (Py_ssize_t*) shape, strides, suboffsets
   1016 
   1017     shape = memview.view.shape
   1018     strides = memview.view.strides
   1019     suboffsets = memview.view.suboffsets
   1020 
   1021     dst.memview = <__pyx_memoryview *> memview
   1022     dst.data = <char *> memview.view.buf
   1023 
   1024     for dim in range(memview.view.ndim):
   1025         dst.shape[dim] = shape[dim]
   1026         dst.strides[dim] = strides[dim]
   1027         if suboffsets == NULL:
   1028             dst.suboffsets[dim] = -1
   1029         else:
   1030             dst.suboffsets[dim] = suboffsets[dim]
   1031 
   1032 @cname('__pyx_memoryview_copy_object')
   1033 cdef memoryview_copy(memoryview memview):
   1034     "Create a new memoryview object"
   1035     cdef {{memviewslice_name}} memviewslice
   1036     slice_copy(memview, &memviewslice)
   1037     return memoryview_copy_from_slice(memview, &memviewslice)
   1038 
   1039 @cname('__pyx_memoryview_copy_object_from_slice')
   1040 cdef memoryview_copy_from_slice(memoryview memview, {{memviewslice_name}} *memviewslice):
   1041     """
   1042     Create a new memoryview object from a given memoryview object and slice.
   1043     """
   1044     cdef object (*to_object_func)(char *)
   1045     cdef int (*to_dtype_func)(char *, object) except 0
   1046 
   1047     if isinstance(memview, _memoryviewslice):
   1048         to_object_func = (<_memoryviewslice> memview).to_object_func
   1049         to_dtype_func = (<_memoryviewslice> memview).to_dtype_func
   1050     else:
   1051         to_object_func = NULL
   1052         to_dtype_func = NULL
   1053 
   1054     return memoryview_fromslice(memviewslice[0], memview.view.ndim,
   1055                                 to_object_func, to_dtype_func,
   1056                                 memview.dtype_is_object)
   1057 
   1058 
   1059 #
   1060 ### Copy the contents of a memoryview slices
   1061 #
   1062 cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil:
   1063     if arg < 0:
   1064         return -arg
   1065     else:
   1066         return arg
   1067 
   1068 @cname('__pyx_get_best_slice_order')
   1069 cdef char get_best_order({{memviewslice_name}} *mslice, int ndim) nogil:
   1070     """
   1071     Figure out the best memory access order for a given slice.
   1072     """
   1073     cdef int i
   1074     cdef Py_ssize_t c_stride = 0
   1075     cdef Py_ssize_t f_stride = 0
   1076 
   1077     for i in range(ndim - 1, -1, -1):
   1078         if mslice.shape[i] > 1:
   1079             c_stride = mslice.strides[i]
   1080             break
   1081 
   1082     for i in range(ndim):
   1083         if mslice.shape[i] > 1:
   1084             f_stride = mslice.strides[i]
   1085             break
   1086 
   1087     if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride):
   1088         return 'C'
   1089     else:
   1090         return 'F'
   1091 
   1092 @cython.cdivision(True)
   1093 cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides,
   1094                                    char *dst_data, Py_ssize_t *dst_strides,
   1095                                    Py_ssize_t *src_shape, Py_ssize_t *dst_shape,
   1096                                    int ndim, size_t itemsize) nogil:
   1097     # Note: src_extent is 1 if we're broadcasting
   1098     # dst_extent always >= src_extent as we don't do reductions
   1099     cdef Py_ssize_t i
   1100     cdef Py_ssize_t src_extent = src_shape[0]
   1101     cdef Py_ssize_t dst_extent = dst_shape[0]
   1102     cdef Py_ssize_t src_stride = src_strides[0]
   1103     cdef Py_ssize_t dst_stride = dst_strides[0]
   1104 
   1105     if ndim == 1:
   1106        if (src_stride > 0 and dst_stride > 0 and
   1107            <size_t> src_stride == itemsize == <size_t> dst_stride):
   1108            memcpy(dst_data, src_data, itemsize * dst_extent)
   1109        else:
   1110            for i in range(dst_extent):
   1111                memcpy(dst_data, src_data, itemsize)
   1112                src_data += src_stride
   1113                dst_data += dst_stride
   1114     else:
   1115         for i in range(dst_extent):
   1116             _copy_strided_to_strided(src_data, src_strides + 1,
   1117                                      dst_data, dst_strides + 1,
   1118                                      src_shape + 1, dst_shape + 1,
   1119                                      ndim - 1, itemsize)
   1120             src_data += src_stride
   1121             dst_data += dst_stride
   1122 
   1123 cdef void copy_strided_to_strided({{memviewslice_name}} *src,
   1124                                   {{memviewslice_name}} *dst,
   1125                                   int ndim, size_t itemsize) nogil:
   1126     _copy_strided_to_strided(src.data, src.strides, dst.data, dst.strides,
   1127                              src.shape, dst.shape, ndim, itemsize)
   1128 
   1129 @cname('__pyx_memoryview_slice_get_size')
   1130 cdef Py_ssize_t slice_get_size({{memviewslice_name}} *src, int ndim) nogil:
   1131     "Return the size of the memory occupied by the slice in number of bytes"
   1132     cdef int i
   1133     cdef Py_ssize_t size = src.memview.view.itemsize
   1134 
   1135     for i in range(ndim):
   1136         size *= src.shape[i]
   1137 
   1138     return size
   1139 
   1140 @cname('__pyx_fill_contig_strides_array')
   1141 cdef Py_ssize_t fill_contig_strides_array(
   1142                 Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride,
   1143                 int ndim, char order) nogil:
   1144     """
   1145     Fill the strides array for a slice with C or F contiguous strides.
   1146     This is like PyBuffer_FillContiguousStrides, but compatible with py < 2.6
   1147     """
   1148     cdef int idx
   1149 
   1150     if order == 'F':
   1151         for idx in range(ndim):
   1152             strides[idx] = stride
   1153             stride = stride * shape[idx]
   1154     else:
   1155         for idx in range(ndim - 1, -1, -1):
   1156             strides[idx] = stride
   1157             stride = stride * shape[idx]
   1158 
   1159     return stride
   1160 
   1161 @cname('__pyx_memoryview_copy_data_to_temp')
   1162 cdef void *copy_data_to_temp({{memviewslice_name}} *src,
   1163                              {{memviewslice_name}} *tmpslice,
   1164                              char order,
   1165                              int ndim) nogil except NULL:
   1166     """
   1167     Copy a direct slice to temporary contiguous memory. The caller should free
   1168     the result when done.
   1169     """
   1170     cdef int i
   1171     cdef void *result
   1172 
   1173     cdef size_t itemsize = src.memview.view.itemsize
   1174     cdef size_t size = slice_get_size(src, ndim)
   1175 
   1176     result = malloc(size)
   1177     if not result:
   1178         _err(MemoryError, NULL)
   1179 
   1180     # tmpslice[0] = src
   1181     tmpslice.data = <char *> result
   1182     tmpslice.memview = src.memview
   1183     for i in range(ndim):
   1184         tmpslice.shape[i] = src.shape[i]
   1185         tmpslice.suboffsets[i] = -1
   1186 
   1187     fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize,
   1188                               ndim, order)
   1189 
   1190     # We need to broadcast strides again
   1191     for i in range(ndim):
   1192         if tmpslice.shape[i] == 1:
   1193             tmpslice.strides[i] = 0
   1194 
   1195     if slice_is_contig(src, order, ndim):
   1196         memcpy(result, src.data, size)
   1197     else:
   1198         copy_strided_to_strided(src, tmpslice, ndim, itemsize)
   1199 
   1200     return result
   1201 
   1202 # Use 'with gil' functions and avoid 'with gil' blocks, as the code within the blocks
   1203 # has temporaries that need the GIL to clean up
   1204 @cname('__pyx_memoryview_err_extents')
   1205 cdef int _err_extents(int i, Py_ssize_t extent1,
   1206                              Py_ssize_t extent2) except -1 with gil:
   1207     raise ValueError("got differing extents in dimension %d (got %d and %d)" %
   1208                                                         (i, extent1, extent2))
   1209 
   1210 @cname('__pyx_memoryview_err_dim')
   1211 cdef int _err_dim(object error, char *msg, int dim) except -1 with gil:
   1212     raise error(msg.decode('ascii') % dim)
   1213 
   1214 @cname('__pyx_memoryview_err')
   1215 cdef int _err(object error, char *msg) except -1 with gil:
   1216     if msg != NULL:
   1217         raise error(msg.decode('ascii'))
   1218     else:
   1219         raise error
   1220 
   1221 @cname('__pyx_memoryview_copy_contents')
   1222 cdef int memoryview_copy_contents({{memviewslice_name}} src,
   1223                                   {{memviewslice_name}} dst,
   1224                                   int src_ndim, int dst_ndim,
   1225                                   bint dtype_is_object) nogil except -1:
   1226     """
   1227     Copy memory from slice src to slice dst.
   1228     Check for overlapping memory and verify the shapes.
   1229     """
   1230     cdef void *tmpdata = NULL
   1231     cdef size_t itemsize = src.memview.view.itemsize
   1232     cdef int i
   1233     cdef char order = get_best_order(&src, src_ndim)
   1234     cdef bint broadcasting = False
   1235     cdef bint direct_copy = False
   1236     cdef {{memviewslice_name}} tmp
   1237 
   1238     if src_ndim < dst_ndim:
   1239         broadcast_leading(&src, src_ndim, dst_ndim)
   1240     elif dst_ndim < src_ndim:
   1241         broadcast_leading(&dst, dst_ndim, src_ndim)
   1242 
   1243     cdef int ndim = max(src_ndim, dst_ndim)
   1244 
   1245     for i in range(ndim):
   1246         if src.shape[i] != dst.shape[i]:
   1247             if src.shape[i] == 1:
   1248                 broadcasting = True
   1249                 src.strides[i] = 0
   1250             else:
   1251                 _err_extents(i, dst.shape[i], src.shape[i])
   1252 
   1253         if src.suboffsets[i] >= 0:
   1254             _err_dim(ValueError, "Dimension %d is not direct", i)
   1255 
   1256     if slices_overlap(&src, &dst, ndim, itemsize):
   1257         # slices overlap, copy to temp, copy temp to dst
   1258         if not slice_is_contig(&src, order, ndim):
   1259             order = get_best_order(&dst, ndim)
   1260 
   1261         tmpdata = copy_data_to_temp(&src, &tmp, order, ndim)
   1262         src = tmp
   1263 
   1264     if not broadcasting:
   1265         # See if both slices have equal contiguity, in that case perform a
   1266         # direct copy. This only works when we are not broadcasting.
   1267         if slice_is_contig(&src, 'C', ndim):
   1268             direct_copy = slice_is_contig(&dst, 'C', ndim)
   1269         elif slice_is_contig(&src, 'F', ndim):
   1270             direct_copy = slice_is_contig(&dst, 'F', ndim)
   1271 
   1272         if direct_copy:
   1273             # Contiguous slices with same order
   1274             refcount_copying(&dst, dtype_is_object, ndim, False)
   1275             memcpy(dst.data, src.data, slice_get_size(&src, ndim))
   1276             refcount_copying(&dst, dtype_is_object, ndim, True)
   1277             free(tmpdata)
   1278             return 0
   1279 
   1280     if order == 'F' == get_best_order(&dst, ndim):
   1281         # see if both slices have Fortran order, transpose them to match our
   1282         # C-style indexing order
   1283         transpose_memslice(&src)
   1284         transpose_memslice(&dst)
   1285 
   1286     refcount_copying(&dst, dtype_is_object, ndim, False)
   1287     copy_strided_to_strided(&src, &dst, ndim, itemsize)
   1288     refcount_copying(&dst, dtype_is_object, ndim, True)
   1289 
   1290     free(tmpdata)
   1291     return 0
   1292 
   1293 @cname('__pyx_memoryview_broadcast_leading')
   1294 cdef void broadcast_leading({{memviewslice_name}} *slice,
   1295                             int ndim,
   1296                             int ndim_other) nogil:
   1297     cdef int i
   1298     cdef int offset = ndim_other - ndim
   1299 
   1300     for i in range(ndim - 1, -1, -1):
   1301         slice.shape[i + offset] = slice.shape[i]
   1302         slice.strides[i + offset] = slice.strides[i]
   1303         slice.suboffsets[i + offset] = slice.suboffsets[i]
   1304 
   1305     for i in range(offset):
   1306         slice.shape[i] = 1
   1307         slice.strides[i] = slice.strides[0]
   1308         slice.suboffsets[i] = -1
   1309 
   1310 #
   1311 ### Take care of refcounting the objects in slices. Do this seperately from any copying,
   1312 ### to minimize acquiring the GIL
   1313 #
   1314 
   1315 @cname('__pyx_memoryview_refcount_copying')
   1316 cdef void refcount_copying({{memviewslice_name}} *dst, bint dtype_is_object,
   1317                            int ndim, bint inc) nogil:
   1318     # incref or decref the objects in the destination slice if the dtype is
   1319     # object
   1320     if dtype_is_object:
   1321         refcount_objects_in_slice_with_gil(dst.data, dst.shape,
   1322                                            dst.strides, ndim, inc)
   1323 
   1324 @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil')
   1325 cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape,
   1326                                              Py_ssize_t *strides, int ndim,
   1327                                              bint inc) with gil:
   1328     refcount_objects_in_slice(data, shape, strides, ndim, inc)
   1329 
   1330 @cname('__pyx_memoryview_refcount_objects_in_slice')
   1331 cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape,
   1332                                     Py_ssize_t *strides, int ndim, bint inc):
   1333     cdef Py_ssize_t i
   1334 
   1335     for i in range(shape[0]):
   1336         if ndim == 1:
   1337             if inc:
   1338                 Py_INCREF((<PyObject **> data)[0])
   1339             else:
   1340                 Py_DECREF((<PyObject **> data)[0])
   1341         else:
   1342             refcount_objects_in_slice(data, shape + 1, strides + 1,
   1343                                       ndim - 1, inc)
   1344 
   1345         data += strides[0]
   1346 
   1347 #
   1348 ### Scalar to slice assignment
   1349 #
   1350 @cname('__pyx_memoryview_slice_assign_scalar')
   1351 cdef void slice_assign_scalar({{memviewslice_name}} *dst, int ndim,
   1352                               size_t itemsize, void *item,
   1353                               bint dtype_is_object) nogil:
   1354     refcount_copying(dst, dtype_is_object, ndim, False)
   1355     _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim,
   1356                          itemsize, item)
   1357     refcount_copying(dst, dtype_is_object, ndim, True)
   1358 
   1359 
   1360 @cname('__pyx_memoryview__slice_assign_scalar')
   1361 cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape,
   1362                               Py_ssize_t *strides, int ndim,
   1363                               size_t itemsize, void *item) nogil:
   1364     cdef Py_ssize_t i
   1365     cdef Py_ssize_t stride = strides[0]
   1366     cdef Py_ssize_t extent = shape[0]
   1367 
   1368     if ndim == 1:
   1369         for i in range(extent):
   1370             memcpy(data, item, itemsize)
   1371             data += stride
   1372     else:
   1373         for i in range(extent):
   1374             _slice_assign_scalar(data, shape + 1, strides + 1,
   1375                                 ndim - 1, itemsize, item)
   1376             data += stride
   1377 
   1378 
   1379 ############### BufferFormatFromTypeInfo ###############
   1380 cdef extern from *:
   1381     ctypedef struct __Pyx_StructField
   1382 
   1383     cdef enum:
   1384         __PYX_BUF_FLAGS_PACKED_STRUCT
   1385         __PYX_BUF_FLAGS_INTEGER_COMPLEX
   1386 
   1387     ctypedef struct __Pyx_TypeInfo:
   1388       char* name
   1389       __Pyx_StructField* fields
   1390       size_t size
   1391       size_t arraysize[8]
   1392       int ndim
   1393       char typegroup
   1394       char is_unsigned
   1395       int flags
   1396 
   1397     ctypedef struct __Pyx_StructField:
   1398       __Pyx_TypeInfo* type
   1399       char* name
   1400       size_t offset
   1401 
   1402     ctypedef struct __Pyx_BufFmt_StackElem:
   1403       __Pyx_StructField* field
   1404       size_t parent_offset
   1405 
   1406     #ctypedef struct __Pyx_BufFmt_Context:
   1407     #  __Pyx_StructField root
   1408       __Pyx_BufFmt_StackElem* head
   1409 
   1410     struct __pyx_typeinfo_string:
   1411         char string[3]
   1412 
   1413     __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *)
   1414 
   1415 
   1416 @cname('__pyx_format_from_typeinfo')
   1417 cdef bytes format_from_typeinfo(__Pyx_TypeInfo *type):
   1418     cdef __Pyx_StructField *field
   1419     cdef __pyx_typeinfo_string fmt
   1420     cdef bytes part, result
   1421 
   1422     if type.typegroup == 'S':
   1423         assert type.fields != NULL and type.fields.type != NULL
   1424 
   1425         if type.flags & __PYX_BUF_FLAGS_PACKED_STRUCT:
   1426             alignment = b'^'
   1427         else:
   1428             alignment = b''
   1429 
   1430         parts = [b"T{"]
   1431         field = type.fields
   1432 
   1433         while field.type:
   1434             part = format_from_typeinfo(field.type)
   1435             parts.append(part + b':' + field.name + b':')
   1436             field += 1
   1437 
   1438         result = alignment.join(parts) + b'}'
   1439     else:
   1440         fmt = __Pyx_TypeInfoToFormat(type)
   1441         if type.arraysize[0]:
   1442             extents = [unicode(type.arraysize[i]) for i in range(type.ndim)]
   1443             result = (u"(%s)" % u','.join(extents)).encode('ascii') + fmt.string
   1444         else:
   1445             result = fmt.string
   1446 
   1447     return result
   1448