MemoryView.pyx 48 KB

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