MemoryView.pyx 48 KB

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