MemoryView_C.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. ////////// MemviewSliceStruct.proto //////////
  2. //@proto_block: utility_code_proto_before_types
  3. /* memoryview slice struct */
  4. struct {{memview_struct_name}};
  5. typedef struct {
  6. struct {{memview_struct_name}} *memview;
  7. char *data;
  8. Py_ssize_t shape[{{max_dims}}];
  9. Py_ssize_t strides[{{max_dims}}];
  10. Py_ssize_t suboffsets[{{max_dims}}];
  11. } {{memviewslice_name}};
  12. // used for "len(memviewslice)"
  13. #define __Pyx_MemoryView_Len(m) (m.shape[0])
  14. /////////// Atomics.proto /////////////
  15. //@proto_block: utility_code_proto_before_types
  16. #include <pythread.h>
  17. #ifndef CYTHON_ATOMICS
  18. #define CYTHON_ATOMICS 1
  19. #endif
  20. #define __pyx_atomic_int_type int
  21. // todo: Portland pgcc, maybe OS X's OSAtomicIncrement32,
  22. // libatomic + autotools-like distutils support? Such a pain...
  23. #if CYTHON_ATOMICS && __GNUC__ >= 4 && (__GNUC_MINOR__ > 1 || \
  24. (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL >= 2)) && \
  25. !defined(__i386__)
  26. /* gcc >= 4.1.2 */
  27. #define __pyx_atomic_incr_aligned(value, lock) __sync_fetch_and_add(value, 1)
  28. #define __pyx_atomic_decr_aligned(value, lock) __sync_fetch_and_sub(value, 1)
  29. #ifdef __PYX_DEBUG_ATOMICS
  30. #warning "Using GNU atomics"
  31. #endif
  32. #elif CYTHON_ATOMICS && defined(_MSC_VER) && 0
  33. /* msvc */
  34. #include <Windows.h>
  35. #undef __pyx_atomic_int_type
  36. #define __pyx_atomic_int_type LONG
  37. #define __pyx_atomic_incr_aligned(value, lock) InterlockedIncrement(value)
  38. #define __pyx_atomic_decr_aligned(value, lock) InterlockedDecrement(value)
  39. #ifdef __PYX_DEBUG_ATOMICS
  40. #pragma message ("Using MSVC atomics")
  41. #endif
  42. #elif CYTHON_ATOMICS && (defined(__ICC) || defined(__INTEL_COMPILER)) && 0
  43. #define __pyx_atomic_incr_aligned(value, lock) _InterlockedIncrement(value)
  44. #define __pyx_atomic_decr_aligned(value, lock) _InterlockedDecrement(value)
  45. #ifdef __PYX_DEBUG_ATOMICS
  46. #warning "Using Intel atomics"
  47. #endif
  48. #else
  49. #undef CYTHON_ATOMICS
  50. #define CYTHON_ATOMICS 0
  51. #ifdef __PYX_DEBUG_ATOMICS
  52. #warning "Not using atomics"
  53. #endif
  54. #endif
  55. typedef volatile __pyx_atomic_int_type __pyx_atomic_int;
  56. #if CYTHON_ATOMICS
  57. #define __pyx_add_acquisition_count(memview) \
  58. __pyx_atomic_incr_aligned(__pyx_get_slice_count_pointer(memview), memview->lock)
  59. #define __pyx_sub_acquisition_count(memview) \
  60. __pyx_atomic_decr_aligned(__pyx_get_slice_count_pointer(memview), memview->lock)
  61. #else
  62. #define __pyx_add_acquisition_count(memview) \
  63. __pyx_add_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock)
  64. #define __pyx_sub_acquisition_count(memview) \
  65. __pyx_sub_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock)
  66. #endif
  67. /////////////// ObjectToMemviewSlice.proto ///////////////
  68. static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *, int writable_flag);
  69. ////////// MemviewSliceInit.proto //////////
  70. #define __Pyx_BUF_MAX_NDIMS %(BUF_MAX_NDIMS)d
  71. #define __Pyx_MEMVIEW_DIRECT 1
  72. #define __Pyx_MEMVIEW_PTR 2
  73. #define __Pyx_MEMVIEW_FULL 4
  74. #define __Pyx_MEMVIEW_CONTIG 8
  75. #define __Pyx_MEMVIEW_STRIDED 16
  76. #define __Pyx_MEMVIEW_FOLLOW 32
  77. #define __Pyx_IS_C_CONTIG 1
  78. #define __Pyx_IS_F_CONTIG 2
  79. static int __Pyx_init_memviewslice(
  80. struct __pyx_memoryview_obj *memview,
  81. int ndim,
  82. __Pyx_memviewslice *memviewslice,
  83. int memview_is_new_reference);
  84. static CYTHON_INLINE int __pyx_add_acquisition_count_locked(
  85. __pyx_atomic_int *acquisition_count, PyThread_type_lock lock);
  86. static CYTHON_INLINE int __pyx_sub_acquisition_count_locked(
  87. __pyx_atomic_int *acquisition_count, PyThread_type_lock lock);
  88. #define __pyx_get_slice_count_pointer(memview) (memview->acquisition_count_aligned_p)
  89. #define __pyx_get_slice_count(memview) (*__pyx_get_slice_count_pointer(memview))
  90. #define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__)
  91. #define __PYX_XDEC_MEMVIEW(slice, have_gil) __Pyx_XDEC_MEMVIEW(slice, have_gil, __LINE__)
  92. static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *, int, int);
  93. static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *, int, int);
  94. /////////////// MemviewSliceIndex.proto ///////////////
  95. static CYTHON_INLINE char *__pyx_memviewslice_index_full(
  96. const char *bufp, Py_ssize_t idx, Py_ssize_t stride, Py_ssize_t suboffset);
  97. /////////////// ObjectToMemviewSlice ///////////////
  98. //@requires: MemviewSliceValidateAndInit
  99. static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *obj, int writable_flag) {
  100. {{memviewslice_name}} result = {{memslice_init}};
  101. __Pyx_BufFmt_StackElem stack[{{struct_nesting_depth}}];
  102. int axes_specs[] = { {{axes_specs}} };
  103. int retcode;
  104. if (obj == Py_None) {
  105. /* We don't bother to refcount None */
  106. result.memview = (struct __pyx_memoryview_obj *) Py_None;
  107. return result;
  108. }
  109. retcode = __Pyx_ValidateAndInit_memviewslice(axes_specs, {{c_or_f_flag}},
  110. {{buf_flag}} | writable_flag, {{ndim}},
  111. &{{dtype_typeinfo}}, stack,
  112. &result, obj);
  113. if (unlikely(retcode == -1))
  114. goto __pyx_fail;
  115. return result;
  116. __pyx_fail:
  117. result.memview = NULL;
  118. result.data = NULL;
  119. return result;
  120. }
  121. /////////////// MemviewSliceValidateAndInit.proto ///////////////
  122. static int __Pyx_ValidateAndInit_memviewslice(
  123. int *axes_specs,
  124. int c_or_f_flag,
  125. int buf_flags,
  126. int ndim,
  127. __Pyx_TypeInfo *dtype,
  128. __Pyx_BufFmt_StackElem stack[],
  129. __Pyx_memviewslice *memviewslice,
  130. PyObject *original_obj);
  131. /////////////// MemviewSliceValidateAndInit ///////////////
  132. //@requires: Buffer.c::TypeInfoCompare
  133. //@requires: Buffer.c::BufferFormatStructs
  134. //@requires: Buffer.c::BufferFormatCheck
  135. static int
  136. __pyx_check_strides(Py_buffer *buf, int dim, int ndim, int spec)
  137. {
  138. if (buf->shape[dim] <= 1)
  139. return 1;
  140. if (buf->strides) {
  141. if (spec & __Pyx_MEMVIEW_CONTIG) {
  142. if (spec & (__Pyx_MEMVIEW_PTR|__Pyx_MEMVIEW_FULL)) {
  143. if (buf->strides[dim] != sizeof(void *)) {
  144. PyErr_Format(PyExc_ValueError,
  145. "Buffer is not indirectly contiguous "
  146. "in dimension %d.", dim);
  147. goto fail;
  148. }
  149. } else if (buf->strides[dim] != buf->itemsize) {
  150. PyErr_SetString(PyExc_ValueError,
  151. "Buffer and memoryview are not contiguous "
  152. "in the same dimension.");
  153. goto fail;
  154. }
  155. }
  156. if (spec & __Pyx_MEMVIEW_FOLLOW) {
  157. Py_ssize_t stride = buf->strides[dim];
  158. if (stride < 0)
  159. stride = -stride;
  160. if (stride < buf->itemsize) {
  161. PyErr_SetString(PyExc_ValueError,
  162. "Buffer and memoryview are not contiguous "
  163. "in the same dimension.");
  164. goto fail;
  165. }
  166. }
  167. } else {
  168. if (spec & __Pyx_MEMVIEW_CONTIG && dim != ndim - 1) {
  169. PyErr_Format(PyExc_ValueError,
  170. "C-contiguous buffer is not contiguous in "
  171. "dimension %d", dim);
  172. goto fail;
  173. } else if (spec & (__Pyx_MEMVIEW_PTR)) {
  174. PyErr_Format(PyExc_ValueError,
  175. "C-contiguous buffer is not indirect in "
  176. "dimension %d", dim);
  177. goto fail;
  178. } else if (buf->suboffsets) {
  179. PyErr_SetString(PyExc_ValueError,
  180. "Buffer exposes suboffsets but no strides");
  181. goto fail;
  182. }
  183. }
  184. return 1;
  185. fail:
  186. return 0;
  187. }
  188. static int
  189. __pyx_check_suboffsets(Py_buffer *buf, int dim, CYTHON_UNUSED int ndim, int spec)
  190. {
  191. // Todo: without PyBUF_INDIRECT we may not have suboffset information, i.e., the
  192. // ptr may not be set to NULL but may be uninitialized?
  193. if (spec & __Pyx_MEMVIEW_DIRECT) {
  194. if (buf->suboffsets && buf->suboffsets[dim] >= 0) {
  195. PyErr_Format(PyExc_ValueError,
  196. "Buffer not compatible with direct access "
  197. "in dimension %d.", dim);
  198. goto fail;
  199. }
  200. }
  201. if (spec & __Pyx_MEMVIEW_PTR) {
  202. if (!buf->suboffsets || (buf->suboffsets && buf->suboffsets[dim] < 0)) {
  203. PyErr_Format(PyExc_ValueError,
  204. "Buffer is not indirectly accessible "
  205. "in dimension %d.", dim);
  206. goto fail;
  207. }
  208. }
  209. return 1;
  210. fail:
  211. return 0;
  212. }
  213. static int
  214. __pyx_verify_contig(Py_buffer *buf, int ndim, int c_or_f_flag)
  215. {
  216. int i;
  217. if (c_or_f_flag & __Pyx_IS_F_CONTIG) {
  218. Py_ssize_t stride = 1;
  219. for (i = 0; i < ndim; i++) {
  220. if (stride * buf->itemsize != buf->strides[i] &&
  221. buf->shape[i] > 1)
  222. {
  223. PyErr_SetString(PyExc_ValueError,
  224. "Buffer not fortran contiguous.");
  225. goto fail;
  226. }
  227. stride = stride * buf->shape[i];
  228. }
  229. } else if (c_or_f_flag & __Pyx_IS_C_CONTIG) {
  230. Py_ssize_t stride = 1;
  231. for (i = ndim - 1; i >- 1; i--) {
  232. if (stride * buf->itemsize != buf->strides[i] &&
  233. buf->shape[i] > 1) {
  234. PyErr_SetString(PyExc_ValueError,
  235. "Buffer not C contiguous.");
  236. goto fail;
  237. }
  238. stride = stride * buf->shape[i];
  239. }
  240. }
  241. return 1;
  242. fail:
  243. return 0;
  244. }
  245. static int __Pyx_ValidateAndInit_memviewslice(
  246. int *axes_specs,
  247. int c_or_f_flag,
  248. int buf_flags,
  249. int ndim,
  250. __Pyx_TypeInfo *dtype,
  251. __Pyx_BufFmt_StackElem stack[],
  252. __Pyx_memviewslice *memviewslice,
  253. PyObject *original_obj)
  254. {
  255. struct __pyx_memoryview_obj *memview, *new_memview;
  256. __Pyx_RefNannyDeclarations
  257. Py_buffer *buf;
  258. int i, spec = 0, retval = -1;
  259. __Pyx_BufFmt_Context ctx;
  260. int from_memoryview = __pyx_memoryview_check(original_obj);
  261. __Pyx_RefNannySetupContext("ValidateAndInit_memviewslice", 0);
  262. if (from_memoryview && __pyx_typeinfo_cmp(dtype, ((struct __pyx_memoryview_obj *)
  263. original_obj)->typeinfo)) {
  264. /* We have a matching dtype, skip format parsing */
  265. memview = (struct __pyx_memoryview_obj *) original_obj;
  266. new_memview = NULL;
  267. } else {
  268. memview = (struct __pyx_memoryview_obj *) __pyx_memoryview_new(
  269. original_obj, buf_flags, 0, dtype);
  270. new_memview = memview;
  271. if (unlikely(!memview))
  272. goto fail;
  273. }
  274. buf = &memview->view;
  275. if (buf->ndim != ndim) {
  276. PyErr_Format(PyExc_ValueError,
  277. "Buffer has wrong number of dimensions (expected %d, got %d)",
  278. ndim, buf->ndim);
  279. goto fail;
  280. }
  281. if (new_memview) {
  282. __Pyx_BufFmt_Init(&ctx, stack, dtype);
  283. if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail;
  284. }
  285. if ((unsigned) buf->itemsize != dtype->size) {
  286. PyErr_Format(PyExc_ValueError,
  287. "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "u byte%s) "
  288. "does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "u byte%s)",
  289. buf->itemsize,
  290. (buf->itemsize > 1) ? "s" : "",
  291. dtype->name,
  292. dtype->size,
  293. (dtype->size > 1) ? "s" : "");
  294. goto fail;
  295. }
  296. /* Check axes */
  297. for (i = 0; i < ndim; i++) {
  298. spec = axes_specs[i];
  299. if (!__pyx_check_strides(buf, i, ndim, spec))
  300. goto fail;
  301. if (!__pyx_check_suboffsets(buf, i, ndim, spec))
  302. goto fail;
  303. }
  304. /* Check contiguity */
  305. if (buf->strides && !__pyx_verify_contig(buf, ndim, c_or_f_flag))
  306. goto fail;
  307. /* Initialize */
  308. if (unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice,
  309. new_memview != NULL) == -1)) {
  310. goto fail;
  311. }
  312. retval = 0;
  313. goto no_fail;
  314. fail:
  315. Py_XDECREF(new_memview);
  316. retval = -1;
  317. no_fail:
  318. __Pyx_RefNannyFinishContext();
  319. return retval;
  320. }
  321. ////////// MemviewSliceInit //////////
  322. static int
  323. __Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview,
  324. int ndim,
  325. {{memviewslice_name}} *memviewslice,
  326. int memview_is_new_reference)
  327. {
  328. __Pyx_RefNannyDeclarations
  329. int i, retval=-1;
  330. Py_buffer *buf = &memview->view;
  331. __Pyx_RefNannySetupContext("init_memviewslice", 0);
  332. if (!buf) {
  333. PyErr_SetString(PyExc_ValueError,
  334. "buf is NULL.");
  335. goto fail;
  336. } else if (memviewslice->memview || memviewslice->data) {
  337. PyErr_SetString(PyExc_ValueError,
  338. "memviewslice is already initialized!");
  339. goto fail;
  340. }
  341. if (buf->strides) {
  342. for (i = 0; i < ndim; i++) {
  343. memviewslice->strides[i] = buf->strides[i];
  344. }
  345. } else {
  346. Py_ssize_t stride = buf->itemsize;
  347. for (i = ndim - 1; i >= 0; i--) {
  348. memviewslice->strides[i] = stride;
  349. stride *= buf->shape[i];
  350. }
  351. }
  352. for (i = 0; i < ndim; i++) {
  353. memviewslice->shape[i] = buf->shape[i];
  354. if (buf->suboffsets) {
  355. memviewslice->suboffsets[i] = buf->suboffsets[i];
  356. } else {
  357. memviewslice->suboffsets[i] = -1;
  358. }
  359. }
  360. memviewslice->memview = memview;
  361. memviewslice->data = (char *)buf->buf;
  362. if (__pyx_add_acquisition_count(memview) == 0 && !memview_is_new_reference) {
  363. Py_INCREF(memview);
  364. }
  365. retval = 0;
  366. goto no_fail;
  367. fail:
  368. /* Don't decref, the memoryview may be borrowed. Let the caller do the cleanup */
  369. /* __Pyx_XDECREF(memviewslice->memview); */
  370. memviewslice->memview = 0;
  371. memviewslice->data = 0;
  372. retval = -1;
  373. no_fail:
  374. __Pyx_RefNannyFinishContext();
  375. return retval;
  376. }
  377. #ifndef Py_NO_RETURN
  378. // available since Py3.3
  379. #define Py_NO_RETURN
  380. #endif
  381. static void __pyx_fatalerror(const char *fmt, ...) Py_NO_RETURN {
  382. va_list vargs;
  383. char msg[200];
  384. #ifdef HAVE_STDARG_PROTOTYPES
  385. va_start(vargs, fmt);
  386. #else
  387. va_start(vargs);
  388. #endif
  389. vsnprintf(msg, 200, fmt, vargs);
  390. va_end(vargs);
  391. Py_FatalError(msg);
  392. }
  393. static CYTHON_INLINE int
  394. __pyx_add_acquisition_count_locked(__pyx_atomic_int *acquisition_count,
  395. PyThread_type_lock lock)
  396. {
  397. int result;
  398. PyThread_acquire_lock(lock, 1);
  399. result = (*acquisition_count)++;
  400. PyThread_release_lock(lock);
  401. return result;
  402. }
  403. static CYTHON_INLINE int
  404. __pyx_sub_acquisition_count_locked(__pyx_atomic_int *acquisition_count,
  405. PyThread_type_lock lock)
  406. {
  407. int result;
  408. PyThread_acquire_lock(lock, 1);
  409. result = (*acquisition_count)--;
  410. PyThread_release_lock(lock);
  411. return result;
  412. }
  413. static CYTHON_INLINE void
  414. __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil, int lineno)
  415. {
  416. int first_time;
  417. struct {{memview_struct_name}} *memview = memslice->memview;
  418. if (!memview || (PyObject *) memview == Py_None)
  419. return; /* allow uninitialized memoryview assignment */
  420. if (__pyx_get_slice_count(memview) < 0)
  421. __pyx_fatalerror("Acquisition count is %d (line %d)",
  422. __pyx_get_slice_count(memview), lineno);
  423. first_time = __pyx_add_acquisition_count(memview) == 0;
  424. if (first_time) {
  425. if (have_gil) {
  426. Py_INCREF((PyObject *) memview);
  427. } else {
  428. PyGILState_STATE _gilstate = PyGILState_Ensure();
  429. Py_INCREF((PyObject *) memview);
  430. PyGILState_Release(_gilstate);
  431. }
  432. }
  433. }
  434. static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
  435. int have_gil, int lineno) {
  436. int last_time;
  437. struct {{memview_struct_name}} *memview = memslice->memview;
  438. if (!memview ) {
  439. return;
  440. } else if ((PyObject *) memview == Py_None) {
  441. memslice->memview = NULL;
  442. return;
  443. }
  444. if (__pyx_get_slice_count(memview) <= 0)
  445. __pyx_fatalerror("Acquisition count is %d (line %d)",
  446. __pyx_get_slice_count(memview), lineno);
  447. last_time = __pyx_sub_acquisition_count(memview) == 1;
  448. memslice->data = NULL;
  449. if (last_time) {
  450. if (have_gil) {
  451. Py_CLEAR(memslice->memview);
  452. } else {
  453. PyGILState_STATE _gilstate = PyGILState_Ensure();
  454. Py_CLEAR(memslice->memview);
  455. PyGILState_Release(_gilstate);
  456. }
  457. } else {
  458. memslice->memview = NULL;
  459. }
  460. }
  461. ////////// MemviewSliceCopyTemplate.proto //////////
  462. static {{memviewslice_name}}
  463. __pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs,
  464. const char *mode, int ndim,
  465. size_t sizeof_dtype, int contig_flag,
  466. int dtype_is_object);
  467. ////////// MemviewSliceCopyTemplate //////////
  468. static {{memviewslice_name}}
  469. __pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs,
  470. const char *mode, int ndim,
  471. size_t sizeof_dtype, int contig_flag,
  472. int dtype_is_object)
  473. {
  474. __Pyx_RefNannyDeclarations
  475. int i;
  476. __Pyx_memviewslice new_mvs = {{memslice_init}};
  477. struct __pyx_memoryview_obj *from_memview = from_mvs->memview;
  478. Py_buffer *buf = &from_memview->view;
  479. PyObject *shape_tuple = NULL;
  480. PyObject *temp_int = NULL;
  481. struct __pyx_array_obj *array_obj = NULL;
  482. struct __pyx_memoryview_obj *memview_obj = NULL;
  483. __Pyx_RefNannySetupContext("__pyx_memoryview_copy_new_contig", 0);
  484. for (i = 0; i < ndim; i++) {
  485. if (from_mvs->suboffsets[i] >= 0) {
  486. PyErr_Format(PyExc_ValueError, "Cannot copy memoryview slice with "
  487. "indirect dimensions (axis %d)", i);
  488. goto fail;
  489. }
  490. }
  491. shape_tuple = PyTuple_New(ndim);
  492. if (unlikely(!shape_tuple)) {
  493. goto fail;
  494. }
  495. __Pyx_GOTREF(shape_tuple);
  496. for(i = 0; i < ndim; i++) {
  497. temp_int = PyInt_FromSsize_t(from_mvs->shape[i]);
  498. if(unlikely(!temp_int)) {
  499. goto fail;
  500. } else {
  501. PyTuple_SET_ITEM(shape_tuple, i, temp_int);
  502. temp_int = NULL;
  503. }
  504. }
  505. array_obj = __pyx_array_new(shape_tuple, sizeof_dtype, buf->format, (char *) mode, NULL);
  506. if (unlikely(!array_obj)) {
  507. goto fail;
  508. }
  509. __Pyx_GOTREF(array_obj);
  510. memview_obj = (struct __pyx_memoryview_obj *) __pyx_memoryview_new(
  511. (PyObject *) array_obj, contig_flag,
  512. dtype_is_object,
  513. from_mvs->memview->typeinfo);
  514. if (unlikely(!memview_obj))
  515. goto fail;
  516. /* initialize new_mvs */
  517. if (unlikely(__Pyx_init_memviewslice(memview_obj, ndim, &new_mvs, 1) < 0))
  518. goto fail;
  519. if (unlikely(__pyx_memoryview_copy_contents(*from_mvs, new_mvs, ndim, ndim,
  520. dtype_is_object) < 0))
  521. goto fail;
  522. goto no_fail;
  523. fail:
  524. __Pyx_XDECREF(new_mvs.memview);
  525. new_mvs.memview = NULL;
  526. new_mvs.data = NULL;
  527. no_fail:
  528. __Pyx_XDECREF(shape_tuple);
  529. __Pyx_XDECREF(temp_int);
  530. __Pyx_XDECREF(array_obj);
  531. __Pyx_RefNannyFinishContext();
  532. return new_mvs;
  533. }
  534. ////////// CopyContentsUtility.proto /////////
  535. #define {{func_cname}}(slice) \
  536. __pyx_memoryview_copy_new_contig(&slice, "{{mode}}", {{ndim}}, \
  537. sizeof({{dtype_decl}}), {{contig_flag}}, \
  538. {{dtype_is_object}})
  539. ////////// OverlappingSlices.proto //////////
  540. static int __pyx_slices_overlap({{memviewslice_name}} *slice1,
  541. {{memviewslice_name}} *slice2,
  542. int ndim, size_t itemsize);
  543. ////////// OverlappingSlices //////////
  544. /* Based on numpy's core/src/multiarray/array_assign.c */
  545. /* Gets a half-open range [start, end) which contains the array data */
  546. static void
  547. __pyx_get_array_memory_extents({{memviewslice_name}} *slice,
  548. void **out_start, void **out_end,
  549. int ndim, size_t itemsize)
  550. {
  551. char *start, *end;
  552. int i;
  553. start = end = slice->data;
  554. for (i = 0; i < ndim; i++) {
  555. Py_ssize_t stride = slice->strides[i];
  556. Py_ssize_t extent = slice->shape[i];
  557. if (extent == 0) {
  558. *out_start = *out_end = start;
  559. return;
  560. } else {
  561. if (stride > 0)
  562. end += stride * (extent - 1);
  563. else
  564. start += stride * (extent - 1);
  565. }
  566. }
  567. /* Return a half-open range */
  568. *out_start = start;
  569. *out_end = end + itemsize;
  570. }
  571. /* Returns 1 if the arrays have overlapping data, 0 otherwise */
  572. static int
  573. __pyx_slices_overlap({{memviewslice_name}} *slice1,
  574. {{memviewslice_name}} *slice2,
  575. int ndim, size_t itemsize)
  576. {
  577. void *start1, *end1, *start2, *end2;
  578. __pyx_get_array_memory_extents(slice1, &start1, &end1, ndim, itemsize);
  579. __pyx_get_array_memory_extents(slice2, &start2, &end2, ndim, itemsize);
  580. return (start1 < end2) && (start2 < end1);
  581. }
  582. ////////// MemviewSliceCheckContig.proto //////////
  583. #define __pyx_memviewslice_is_contig_{{contig_type}}{{ndim}}(slice) \
  584. __pyx_memviewslice_is_contig(slice, '{{contig_type}}', {{ndim}})
  585. ////////// MemviewSliceIsContig.proto //////////
  586. static int __pyx_memviewslice_is_contig(const {{memviewslice_name}} mvs, char order, int ndim);/*proto*/
  587. ////////// MemviewSliceIsContig //////////
  588. static int
  589. __pyx_memviewslice_is_contig(const {{memviewslice_name}} mvs, char order, int ndim)
  590. {
  591. int i, index, step, start;
  592. Py_ssize_t itemsize = mvs.memview->view.itemsize;
  593. if (order == 'F') {
  594. step = 1;
  595. start = 0;
  596. } else {
  597. step = -1;
  598. start = ndim - 1;
  599. }
  600. for (i = 0; i < ndim; i++) {
  601. index = start + step * i;
  602. if (mvs.suboffsets[index] >= 0 || mvs.strides[index] != itemsize)
  603. return 0;
  604. itemsize *= mvs.shape[index];
  605. }
  606. return 1;
  607. }
  608. /////////////// MemviewSliceIndex ///////////////
  609. static CYTHON_INLINE char *
  610. __pyx_memviewslice_index_full(const char *bufp, Py_ssize_t idx,
  611. Py_ssize_t stride, Py_ssize_t suboffset)
  612. {
  613. bufp = bufp + idx * stride;
  614. if (suboffset >= 0) {
  615. bufp = *((char **) bufp) + suboffset;
  616. }
  617. return (char *) bufp;
  618. }
  619. /////////////// MemviewDtypeToObject.proto ///////////////
  620. {{if to_py_function}}
  621. static CYTHON_INLINE PyObject *{{get_function}}(const char *itemp); /* proto */
  622. {{endif}}
  623. {{if from_py_function}}
  624. static CYTHON_INLINE int {{set_function}}(const char *itemp, PyObject *obj); /* proto */
  625. {{endif}}
  626. /////////////// MemviewDtypeToObject ///////////////
  627. {{#__pyx_memview_<dtype_name>_to_object}}
  628. /* Convert a dtype to or from a Python object */
  629. {{if to_py_function}}
  630. static CYTHON_INLINE PyObject *{{get_function}}(const char *itemp) {
  631. return (PyObject *) {{to_py_function}}(*({{dtype}} *) itemp);
  632. }
  633. {{endif}}
  634. {{if from_py_function}}
  635. static CYTHON_INLINE int {{set_function}}(const char *itemp, PyObject *obj) {
  636. {{dtype}} value = {{from_py_function}}(obj);
  637. if ({{error_condition}})
  638. return 0;
  639. *({{dtype}} *) itemp = value;
  640. return 1;
  641. }
  642. {{endif}}
  643. /////////////// MemviewObjectToObject.proto ///////////////
  644. /* Function callbacks (for memoryview object) for dtype object */
  645. static PyObject *{{get_function}}(const char *itemp); /* proto */
  646. static int {{set_function}}(const char *itemp, PyObject *obj); /* proto */
  647. /////////////// MemviewObjectToObject ///////////////
  648. static PyObject *{{get_function}}(const char *itemp) {
  649. PyObject *result = *(PyObject **) itemp;
  650. Py_INCREF(result);
  651. return result;
  652. }
  653. static int {{set_function}}(const char *itemp, PyObject *obj) {
  654. Py_INCREF(obj);
  655. Py_DECREF(*(PyObject **) itemp);
  656. *(PyObject **) itemp = obj;
  657. return 1;
  658. }
  659. /////////// ToughSlice //////////
  660. /* Dimension is indexed with 'start:stop:step' */
  661. if (unlikely(__pyx_memoryview_slice_memviewslice(
  662. &{{dst}},
  663. {{src}}.shape[{{dim}}], {{src}}.strides[{{dim}}], {{src}}.suboffsets[{{dim}}],
  664. {{dim}},
  665. {{new_ndim}},
  666. &{{get_suboffset_dim()}},
  667. {{start}},
  668. {{stop}},
  669. {{step}},
  670. {{int(have_start)}},
  671. {{int(have_stop)}},
  672. {{int(have_step)}},
  673. 1) < 0))
  674. {
  675. {{error_goto}}
  676. }
  677. ////////// SimpleSlice //////////
  678. /* Dimension is indexed with ':' only */
  679. {{dst}}.shape[{{new_ndim}}] = {{src}}.shape[{{dim}}];
  680. {{dst}}.strides[{{new_ndim}}] = {{src}}.strides[{{dim}}];
  681. {{if access == 'direct'}}
  682. {{dst}}.suboffsets[{{new_ndim}}] = -1;
  683. {{else}}
  684. {{dst}}.suboffsets[{{new_ndim}}] = {{src}}.suboffsets[{{dim}}];
  685. if ({{src}}.suboffsets[{{dim}}] >= 0)
  686. {{get_suboffset_dim()}} = {{new_ndim}};
  687. {{endif}}
  688. ////////// SliceIndex //////////
  689. // Dimension is indexed with an integer, we could use the ToughSlice
  690. // approach, but this is faster
  691. {
  692. Py_ssize_t __pyx_tmp_idx = {{idx}};
  693. Py_ssize_t __pyx_tmp_shape = {{src}}.shape[{{dim}}];
  694. Py_ssize_t __pyx_tmp_stride = {{src}}.strides[{{dim}}];
  695. if ({{wraparound}} && (__pyx_tmp_idx < 0))
  696. __pyx_tmp_idx += __pyx_tmp_shape;
  697. if ({{boundscheck}} && (__pyx_tmp_idx < 0 || __pyx_tmp_idx >= __pyx_tmp_shape)) {
  698. {{if not have_gil}}
  699. #ifdef WITH_THREAD
  700. PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();
  701. #endif
  702. {{endif}}
  703. PyErr_SetString(PyExc_IndexError, "Index out of bounds (axis {{dim}})");
  704. {{if not have_gil}}
  705. #ifdef WITH_THREAD
  706. PyGILState_Release(__pyx_gilstate_save);
  707. #endif
  708. {{endif}}
  709. {{error_goto}}
  710. }
  711. {{if all_dimensions_direct}}
  712. {{dst}}.data += __pyx_tmp_idx * __pyx_tmp_stride;
  713. {{else}}
  714. if ({{get_suboffset_dim()}} < 0) {
  715. {{dst}}.data += __pyx_tmp_idx * __pyx_tmp_stride;
  716. /* This dimension is the first dimension, or is preceded by */
  717. /* direct or indirect dimensions that are indexed away. */
  718. /* Hence suboffset_dim must be less than zero, and we can have */
  719. /* our data pointer refer to another block by dereferencing. */
  720. /* slice.data -> B -> C becomes slice.data -> C */
  721. {{if indirect}}
  722. {
  723. Py_ssize_t __pyx_tmp_suboffset = {{src}}.suboffsets[{{dim}}];
  724. {{if generic}}
  725. if (__pyx_tmp_suboffset >= 0)
  726. {{endif}}
  727. {{dst}}.data = *((char **) {{dst}}.data) + __pyx_tmp_suboffset;
  728. }
  729. {{endif}}
  730. } else {
  731. {{dst}}.suboffsets[{{get_suboffset_dim()}}] += __pyx_tmp_idx * __pyx_tmp_stride;
  732. /* Note: dimension can not be indirect, the compiler will have */
  733. /* issued an error */
  734. }
  735. {{endif}}
  736. }
  737. ////////// FillStrided1DScalar.proto //////////
  738. static void
  739. __pyx_fill_slice_{{dtype_name}}({{type_decl}} *p, Py_ssize_t extent, Py_ssize_t stride,
  740. size_t itemsize, void *itemp);
  741. ////////// FillStrided1DScalar //////////
  742. /* Fill a slice with a scalar value. The dimension is direct and strided or contiguous */
  743. /* This can be used as a callback for the memoryview object to efficienty assign a scalar */
  744. /* Currently unused */
  745. static void
  746. __pyx_fill_slice_{{dtype_name}}({{type_decl}} *p, Py_ssize_t extent, Py_ssize_t stride,
  747. size_t itemsize, void *itemp)
  748. {
  749. Py_ssize_t i;
  750. {{type_decl}} item = *(({{type_decl}} *) itemp);
  751. {{type_decl}} *endp;
  752. stride /= sizeof({{type_decl}});
  753. endp = p + stride * extent;
  754. while (p < endp) {
  755. *p = item;
  756. p += stride;
  757. }
  758. }