Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / cython / src / Cython / Utility / MemoryView.pyx
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