MemoryView.pyx 49 KB

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