Cython 3.1.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. Cython/Build/BuildExecutable.py +169 -0
  2. Cython/Build/Cache.py +199 -0
  3. Cython/Build/Cythonize.py +250 -0
  4. Cython/Build/Dependencies.py +1275 -0
  5. Cython/Build/Distutils.py +1 -0
  6. Cython/Build/Inline.py +342 -0
  7. Cython/Build/IpythonMagic.py +560 -0
  8. Cython/Build/Tests/TestCyCache.py +119 -0
  9. Cython/Build/Tests/TestCythonizeArgsParser.py +481 -0
  10. Cython/Build/Tests/TestDependencies.py +133 -0
  11. Cython/Build/Tests/TestInline.py +112 -0
  12. Cython/Build/Tests/TestIpythonMagic.py +287 -0
  13. Cython/Build/Tests/TestRecythonize.py +212 -0
  14. Cython/Build/Tests/TestStripLiterals.py +155 -0
  15. Cython/Build/Tests/__init__.py +1 -0
  16. Cython/Build/__init__.py +8 -0
  17. Cython/CodeWriter.py +811 -0
  18. Cython/Compiler/AnalysedTreeTransforms.py +97 -0
  19. Cython/Compiler/Annotate.py +326 -0
  20. Cython/Compiler/AutoDocTransforms.py +314 -0
  21. Cython/Compiler/Buffer.py +680 -0
  22. Cython/Compiler/Builtin.py +862 -0
  23. Cython/Compiler/CmdLine.py +243 -0
  24. Cython/Compiler/Code.pxd +145 -0
  25. Cython/Compiler/Code.py +3328 -0
  26. Cython/Compiler/CodeGeneration.py +33 -0
  27. Cython/Compiler/CythonScope.py +179 -0
  28. Cython/Compiler/Dataclass.py +868 -0
  29. Cython/Compiler/DebugFlags.py +21 -0
  30. Cython/Compiler/Errors.py +295 -0
  31. Cython/Compiler/ExprNodes.py +15051 -0
  32. Cython/Compiler/FlowControl.pxd +97 -0
  33. Cython/Compiler/FlowControl.py +1438 -0
  34. Cython/Compiler/FusedNode.py +998 -0
  35. Cython/Compiler/Future.py +16 -0
  36. Cython/Compiler/Interpreter.py +57 -0
  37. Cython/Compiler/Lexicon.py +340 -0
  38. Cython/Compiler/LineTable.py +114 -0
  39. Cython/Compiler/Main.py +779 -0
  40. Cython/Compiler/MatchCaseNodes.py +259 -0
  41. Cython/Compiler/MemoryView.py +860 -0
  42. Cython/Compiler/ModuleNode.py +4065 -0
  43. Cython/Compiler/Naming.py +369 -0
  44. Cython/Compiler/Nodes.py +10557 -0
  45. Cython/Compiler/Optimize.py +5269 -0
  46. Cython/Compiler/Options.py +828 -0
  47. Cython/Compiler/ParseTreeTransforms.pxd +78 -0
  48. Cython/Compiler/ParseTreeTransforms.py +4441 -0
  49. Cython/Compiler/Parsing.pxd +9 -0
  50. Cython/Compiler/Parsing.py +4797 -0
  51. Cython/Compiler/Pipeline.py +425 -0
  52. Cython/Compiler/PyrexTypes.py +5572 -0
  53. Cython/Compiler/Pythran.py +223 -0
  54. Cython/Compiler/Scanning.pxd +40 -0
  55. Cython/Compiler/Scanning.py +574 -0
  56. Cython/Compiler/StringEncoding.py +347 -0
  57. Cython/Compiler/Symtab.py +2998 -0
  58. Cython/Compiler/Tests/TestBuffer.py +105 -0
  59. Cython/Compiler/Tests/TestBuiltin.py +72 -0
  60. Cython/Compiler/Tests/TestCmdLine.py +573 -0
  61. Cython/Compiler/Tests/TestCode.py +86 -0
  62. Cython/Compiler/Tests/TestFlowControl.py +65 -0
  63. Cython/Compiler/Tests/TestGrammar.py +202 -0
  64. Cython/Compiler/Tests/TestMemView.py +71 -0
  65. Cython/Compiler/Tests/TestParseTreeTransforms.py +285 -0
  66. Cython/Compiler/Tests/TestScanning.py +134 -0
  67. Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
  68. Cython/Compiler/Tests/TestStringEncoding.py +33 -0
  69. Cython/Compiler/Tests/TestTreeFragment.py +63 -0
  70. Cython/Compiler/Tests/TestTreePath.py +93 -0
  71. Cython/Compiler/Tests/TestTypes.py +75 -0
  72. Cython/Compiler/Tests/TestUtilityLoad.py +112 -0
  73. Cython/Compiler/Tests/TestVisitor.py +61 -0
  74. Cython/Compiler/Tests/Utils.py +36 -0
  75. Cython/Compiler/Tests/__init__.py +1 -0
  76. Cython/Compiler/TreeFragment.py +278 -0
  77. Cython/Compiler/TreePath.py +290 -0
  78. Cython/Compiler/TypeInference.py +584 -0
  79. Cython/Compiler/TypeSlots.py +1181 -0
  80. Cython/Compiler/UFuncs.py +311 -0
  81. Cython/Compiler/UtilNodes.py +387 -0
  82. Cython/Compiler/UtilityCode.py +274 -0
  83. Cython/Compiler/Version.py +8 -0
  84. Cython/Compiler/Visitor.pxd +53 -0
  85. Cython/Compiler/Visitor.py +861 -0
  86. Cython/Compiler/__init__.py +1 -0
  87. Cython/Coverage.py +443 -0
  88. Cython/Debugger/Cygdb.py +179 -0
  89. Cython/Debugger/DebugWriter.py +82 -0
  90. Cython/Debugger/Tests/TestLibCython.py +275 -0
  91. Cython/Debugger/Tests/__init__.py +1 -0
  92. Cython/Debugger/Tests/cfuncs.c +8 -0
  93. Cython/Debugger/Tests/codefile +49 -0
  94. Cython/Debugger/Tests/test_libcython_in_gdb.py +578 -0
  95. Cython/Debugger/Tests/test_libpython_in_gdb.py +90 -0
  96. Cython/Debugger/__init__.py +1 -0
  97. Cython/Debugger/libcython.py +1549 -0
  98. Cython/Debugger/libpython.py +2821 -0
  99. Cython/Debugging.py +20 -0
  100. Cython/Distutils/__init__.py +2 -0
  101. Cython/Distutils/build_ext.py +137 -0
  102. Cython/Distutils/extension.py +96 -0
  103. Cython/Distutils/old_build_ext.py +351 -0
  104. Cython/Includes/cpython/__init__.pxd +173 -0
  105. Cython/Includes/cpython/array.pxd +174 -0
  106. Cython/Includes/cpython/bool.pxd +37 -0
  107. Cython/Includes/cpython/buffer.pxd +112 -0
  108. Cython/Includes/cpython/bytearray.pxd +33 -0
  109. Cython/Includes/cpython/bytes.pxd +200 -0
  110. Cython/Includes/cpython/cellobject.pxd +35 -0
  111. Cython/Includes/cpython/ceval.pxd +8 -0
  112. Cython/Includes/cpython/codecs.pxd +121 -0
  113. Cython/Includes/cpython/complex.pxd +55 -0
  114. Cython/Includes/cpython/contextvars.pxd +141 -0
  115. Cython/Includes/cpython/conversion.pxd +36 -0
  116. Cython/Includes/cpython/datetime.pxd +384 -0
  117. Cython/Includes/cpython/descr.pxd +26 -0
  118. Cython/Includes/cpython/dict.pxd +187 -0
  119. Cython/Includes/cpython/exc.pxd +263 -0
  120. Cython/Includes/cpython/fileobject.pxd +57 -0
  121. Cython/Includes/cpython/float.pxd +47 -0
  122. Cython/Includes/cpython/function.pxd +65 -0
  123. Cython/Includes/cpython/genobject.pxd +25 -0
  124. Cython/Includes/cpython/getargs.pxd +12 -0
  125. Cython/Includes/cpython/instance.pxd +25 -0
  126. Cython/Includes/cpython/iterator.pxd +36 -0
  127. Cython/Includes/cpython/iterobject.pxd +24 -0
  128. Cython/Includes/cpython/list.pxd +92 -0
  129. Cython/Includes/cpython/long.pxd +149 -0
  130. Cython/Includes/cpython/longintrepr.pxd +19 -0
  131. Cython/Includes/cpython/mapping.pxd +63 -0
  132. Cython/Includes/cpython/marshal.pxd +66 -0
  133. Cython/Includes/cpython/mem.pxd +120 -0
  134. Cython/Includes/cpython/memoryview.pxd +50 -0
  135. Cython/Includes/cpython/method.pxd +49 -0
  136. Cython/Includes/cpython/module.pxd +208 -0
  137. Cython/Includes/cpython/number.pxd +258 -0
  138. Cython/Includes/cpython/object.pxd +433 -0
  139. Cython/Includes/cpython/pycapsule.pxd +143 -0
  140. Cython/Includes/cpython/pylifecycle.pxd +68 -0
  141. Cython/Includes/cpython/pyport.pxd +8 -0
  142. Cython/Includes/cpython/pystate.pxd +95 -0
  143. Cython/Includes/cpython/pythread.pxd +53 -0
  144. Cython/Includes/cpython/ref.pxd +67 -0
  145. Cython/Includes/cpython/sequence.pxd +134 -0
  146. Cython/Includes/cpython/set.pxd +119 -0
  147. Cython/Includes/cpython/slice.pxd +70 -0
  148. Cython/Includes/cpython/time.pxd +129 -0
  149. Cython/Includes/cpython/tuple.pxd +72 -0
  150. Cython/Includes/cpython/type.pxd +53 -0
  151. Cython/Includes/cpython/unicode.pxd +639 -0
  152. Cython/Includes/cpython/version.pxd +32 -0
  153. Cython/Includes/cpython/weakref.pxd +42 -0
  154. Cython/Includes/libc/__init__.pxd +1 -0
  155. Cython/Includes/libc/complex.pxd +35 -0
  156. Cython/Includes/libc/errno.pxd +127 -0
  157. Cython/Includes/libc/float.pxd +43 -0
  158. Cython/Includes/libc/limits.pxd +28 -0
  159. Cython/Includes/libc/locale.pxd +46 -0
  160. Cython/Includes/libc/math.pxd +209 -0
  161. Cython/Includes/libc/setjmp.pxd +10 -0
  162. Cython/Includes/libc/signal.pxd +64 -0
  163. Cython/Includes/libc/stddef.pxd +9 -0
  164. Cython/Includes/libc/stdint.pxd +105 -0
  165. Cython/Includes/libc/stdio.pxd +80 -0
  166. Cython/Includes/libc/stdlib.pxd +72 -0
  167. Cython/Includes/libc/string.pxd +50 -0
  168. Cython/Includes/libc/time.pxd +47 -0
  169. Cython/Includes/libcpp/__init__.pxd +4 -0
  170. Cython/Includes/libcpp/algorithm.pxd +320 -0
  171. Cython/Includes/libcpp/any.pxd +16 -0
  172. Cython/Includes/libcpp/atomic.pxd +59 -0
  173. Cython/Includes/libcpp/bit.pxd +29 -0
  174. Cython/Includes/libcpp/cast.pxd +12 -0
  175. Cython/Includes/libcpp/cmath.pxd +518 -0
  176. Cython/Includes/libcpp/complex.pxd +106 -0
  177. Cython/Includes/libcpp/deque.pxd +165 -0
  178. Cython/Includes/libcpp/execution.pxd +15 -0
  179. Cython/Includes/libcpp/forward_list.pxd +63 -0
  180. Cython/Includes/libcpp/functional.pxd +26 -0
  181. Cython/Includes/libcpp/iterator.pxd +34 -0
  182. Cython/Includes/libcpp/limits.pxd +61 -0
  183. Cython/Includes/libcpp/list.pxd +117 -0
  184. Cython/Includes/libcpp/map.pxd +252 -0
  185. Cython/Includes/libcpp/memory.pxd +115 -0
  186. Cython/Includes/libcpp/numbers.pxd +15 -0
  187. Cython/Includes/libcpp/numeric.pxd +131 -0
  188. Cython/Includes/libcpp/optional.pxd +34 -0
  189. Cython/Includes/libcpp/pair.pxd +1 -0
  190. Cython/Includes/libcpp/queue.pxd +25 -0
  191. Cython/Includes/libcpp/random.pxd +166 -0
  192. Cython/Includes/libcpp/set.pxd +228 -0
  193. Cython/Includes/libcpp/stack.pxd +11 -0
  194. Cython/Includes/libcpp/string.pxd +333 -0
  195. Cython/Includes/libcpp/typeindex.pxd +15 -0
  196. Cython/Includes/libcpp/typeinfo.pxd +10 -0
  197. Cython/Includes/libcpp/unordered_map.pxd +193 -0
  198. Cython/Includes/libcpp/unordered_set.pxd +152 -0
  199. Cython/Includes/libcpp/utility.pxd +30 -0
  200. Cython/Includes/libcpp/vector.pxd +167 -0
  201. Cython/Includes/openmp.pxd +50 -0
  202. Cython/Includes/posix/__init__.pxd +1 -0
  203. Cython/Includes/posix/dlfcn.pxd +14 -0
  204. Cython/Includes/posix/fcntl.pxd +86 -0
  205. Cython/Includes/posix/ioctl.pxd +4 -0
  206. Cython/Includes/posix/mman.pxd +101 -0
  207. Cython/Includes/posix/resource.pxd +57 -0
  208. Cython/Includes/posix/select.pxd +21 -0
  209. Cython/Includes/posix/signal.pxd +73 -0
  210. Cython/Includes/posix/stat.pxd +98 -0
  211. Cython/Includes/posix/stdio.pxd +37 -0
  212. Cython/Includes/posix/stdlib.pxd +29 -0
  213. Cython/Includes/posix/strings.pxd +9 -0
  214. Cython/Includes/posix/time.pxd +71 -0
  215. Cython/Includes/posix/types.pxd +30 -0
  216. Cython/Includes/posix/uio.pxd +26 -0
  217. Cython/Includes/posix/unistd.pxd +271 -0
  218. Cython/Includes/posix/wait.pxd +38 -0
  219. Cython/Plex/Actions.pxd +24 -0
  220. Cython/Plex/Actions.py +119 -0
  221. Cython/Plex/DFA.pxd +14 -0
  222. Cython/Plex/DFA.py +164 -0
  223. Cython/Plex/Errors.py +48 -0
  224. Cython/Plex/Lexicons.py +178 -0
  225. Cython/Plex/Machines.pxd +36 -0
  226. Cython/Plex/Machines.py +238 -0
  227. Cython/Plex/Regexps.py +539 -0
  228. Cython/Plex/Scanners.pxd +47 -0
  229. Cython/Plex/Scanners.py +360 -0
  230. Cython/Plex/Transitions.pxd +14 -0
  231. Cython/Plex/Transitions.py +239 -0
  232. Cython/Plex/__init__.py +34 -0
  233. Cython/Runtime/__init__.py +1 -0
  234. Cython/Runtime/refnanny.pyx +261 -0
  235. Cython/Shadow.py +656 -0
  236. Cython/Shadow.pyi +521 -0
  237. Cython/StringIOTree.py +170 -0
  238. Cython/Tempita/__init__.py +4 -0
  239. Cython/Tempita/_looper.py +154 -0
  240. Cython/Tempita/_tempita.py +1091 -0
  241. Cython/TestUtils.py +417 -0
  242. Cython/Tests/TestCodeWriter.py +128 -0
  243. Cython/Tests/TestCythonUtils.py +202 -0
  244. Cython/Tests/TestJediTyper.py +223 -0
  245. Cython/Tests/TestShadow.py +114 -0
  246. Cython/Tests/TestStringIOTree.py +67 -0
  247. Cython/Tests/TestTestUtils.py +90 -0
  248. Cython/Tests/__init__.py +1 -0
  249. Cython/Tests/xmlrunner.py +390 -0
  250. Cython/Utility/AsyncGen.c +1263 -0
  251. Cython/Utility/Buffer.c +875 -0
  252. Cython/Utility/Builtins.c +660 -0
  253. Cython/Utility/CConvert.pyx +134 -0
  254. Cython/Utility/CMath.c +95 -0
  255. Cython/Utility/CommonStructures.c +139 -0
  256. Cython/Utility/Complex.c +378 -0
  257. Cython/Utility/Coroutine.c +2413 -0
  258. Cython/Utility/CpdefEnums.pyx +108 -0
  259. Cython/Utility/CppConvert.pyx +279 -0
  260. Cython/Utility/CppSupport.cpp +133 -0
  261. Cython/Utility/CythonFunction.c +1851 -0
  262. Cython/Utility/Dataclasses.c +185 -0
  263. Cython/Utility/Dataclasses.py +112 -0
  264. Cython/Utility/Embed.c +125 -0
  265. Cython/Utility/Exceptions.c +1017 -0
  266. Cython/Utility/ExtensionTypes.c +797 -0
  267. Cython/Utility/FunctionArguments.c +573 -0
  268. Cython/Utility/ImportExport.c +912 -0
  269. Cython/Utility/MemoryView.pyx +1478 -0
  270. Cython/Utility/MemoryView_C.c +992 -0
  271. Cython/Utility/ModuleSetupCode.c +2501 -0
  272. Cython/Utility/NumpyImportArray.c +46 -0
  273. Cython/Utility/ObjectHandling.c +3054 -0
  274. Cython/Utility/Optimize.c +1533 -0
  275. Cython/Utility/Overflow.c +404 -0
  276. Cython/Utility/Printing.c +86 -0
  277. Cython/Utility/Profile.c +660 -0
  278. Cython/Utility/StringTools.c +1206 -0
  279. Cython/Utility/TestCyUtilityLoader.pyx +8 -0
  280. Cython/Utility/TestCythonScope.pyx +75 -0
  281. Cython/Utility/TestUtilityLoader.c +12 -0
  282. Cython/Utility/TypeConversion.c +1329 -0
  283. Cython/Utility/UFuncs.pyx +50 -0
  284. Cython/Utility/UFuncs_C.c +89 -0
  285. Cython/Utility/__init__.py +28 -0
  286. Cython/Utility/arrayarray.h +143 -0
  287. Cython/Utils.py +687 -0
  288. Cython/__init__.py +10 -0
  289. Cython/__init__.pyi +7 -0
  290. Cython/py.typed +0 -0
  291. Cython-3.1.0a1.dist-info/COPYING.txt +19 -0
  292. Cython-3.1.0a1.dist-info/LICENSE.txt +176 -0
  293. Cython-3.1.0a1.dist-info/METADATA +67 -0
  294. Cython-3.1.0a1.dist-info/RECORD +301 -0
  295. Cython-3.1.0a1.dist-info/WHEEL +5 -0
  296. Cython-3.1.0a1.dist-info/entry_points.txt +4 -0
  297. Cython-3.1.0a1.dist-info/top_level.txt +3 -0
  298. cython.py +29 -0
  299. pyximport/__init__.py +4 -0
  300. pyximport/pyxbuild.py +160 -0
  301. pyximport/pyximport.py +482 -0
@@ -0,0 +1,1478 @@
1
+ #################### View.MemoryView ####################
2
+
3
+ # cython: language_level=3
4
+ # cython: binding=False
5
+
6
+ # This utility provides cython.array and cython.view.memoryview
7
+
8
+ from __future__ import absolute_import
9
+
10
+ cimport cython
11
+
12
+ # from cpython cimport ...
13
+ cdef extern from "Python.h":
14
+ ctypedef struct PyObject
15
+ int PyIndex_Check(object)
16
+ PyObject *PyExc_IndexError
17
+ PyObject *PyExc_ValueError
18
+
19
+ cdef extern from "pythread.h":
20
+ ctypedef void *PyThread_type_lock
21
+
22
+ PyThread_type_lock PyThread_allocate_lock()
23
+ void PyThread_free_lock(PyThread_type_lock)
24
+
25
+ cdef extern from "<string.h>":
26
+ void *memset(void *b, int c, size_t len)
27
+
28
+ cdef extern from *:
29
+ bint __PYX_CYTHON_ATOMICS_ENABLED()
30
+ int PyObject_GetBuffer(object, Py_buffer *, int) except -1
31
+ void PyBuffer_Release(Py_buffer *)
32
+
33
+ ctypedef struct PyObject
34
+ ctypedef Py_ssize_t Py_intptr_t
35
+ void Py_INCREF(PyObject *)
36
+ void Py_DECREF(PyObject *)
37
+
38
+ void* PyMem_Malloc(size_t n)
39
+ void PyMem_Free(void *p)
40
+ void* PyObject_Malloc(size_t n)
41
+ void PyObject_Free(void *p)
42
+
43
+ cdef struct __pyx_memoryview "__pyx_memoryview_obj":
44
+ Py_buffer view
45
+ PyObject *obj
46
+ __Pyx_TypeInfo *typeinfo
47
+
48
+ ctypedef struct {{memviewslice_name}}:
49
+ __pyx_memoryview *memview
50
+ char *data
51
+ Py_ssize_t shape[{{max_dims}}]
52
+ Py_ssize_t strides[{{max_dims}}]
53
+ Py_ssize_t suboffsets[{{max_dims}}]
54
+
55
+ void __PYX_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
56
+ void __PYX_XCLEAR_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
57
+
58
+ ctypedef struct __pyx_buffer "Py_buffer":
59
+ PyObject *obj
60
+
61
+ PyObject *Py_None
62
+
63
+ cdef enum:
64
+ PyBUF_C_CONTIGUOUS,
65
+ PyBUF_F_CONTIGUOUS,
66
+ PyBUF_ANY_CONTIGUOUS
67
+ PyBUF_FORMAT
68
+ PyBUF_WRITABLE
69
+ PyBUF_STRIDES
70
+ PyBUF_INDIRECT
71
+ PyBUF_ND
72
+ PyBUF_RECORDS
73
+ PyBUF_RECORDS_RO
74
+
75
+ ctypedef struct __Pyx_TypeInfo:
76
+ pass
77
+
78
+ cdef extern from *:
79
+ ctypedef int __pyx_atomic_int_type
80
+ {{memviewslice_name}} slice_copy_contig "__pyx_memoryview_copy_new_contig"(
81
+ __Pyx_memviewslice *from_mvs,
82
+ char *mode, int ndim,
83
+ size_t sizeof_dtype, int contig_flag,
84
+ bint dtype_is_object) except * nogil
85
+ bint slice_is_contig "__pyx_memviewslice_is_contig" (
86
+ {{memviewslice_name}} mvs, char order, int ndim) nogil
87
+ bint slices_overlap "__pyx_slices_overlap" ({{memviewslice_name}} *slice1,
88
+ {{memviewslice_name}} *slice2,
89
+ int ndim, size_t itemsize) nogil
90
+
91
+
92
+ cdef extern from "<stdlib.h>":
93
+ void *malloc(size_t) nogil
94
+ void free(void *) nogil
95
+ void *memcpy(void *dest, void *src, size_t n) nogil
96
+
97
+ # the sequence abstract base class
98
+ cdef object __pyx_collections_abc_Sequence "__pyx_collections_abc_Sequence"
99
+ try:
100
+ __pyx_collections_abc_Sequence = __import__("collections.abc").abc.Sequence
101
+ except:
102
+ # it isn't a big problem if this fails
103
+ __pyx_collections_abc_Sequence = None
104
+
105
+ #
106
+ ### cython.array class
107
+ #
108
+
109
+ @cython.collection_type("sequence")
110
+ @cname("__pyx_array")
111
+ cdef class array:
112
+
113
+ cdef:
114
+ char *data
115
+ Py_ssize_t len
116
+ char *format
117
+ int ndim
118
+ Py_ssize_t *_shape
119
+ Py_ssize_t *_strides
120
+ Py_ssize_t itemsize
121
+ unicode mode # FIXME: this should have been a simple 'char'
122
+ bytes _format
123
+ void (*callback_free_data)(void *data) noexcept
124
+ # cdef object _memview
125
+ cdef bint free_data
126
+ cdef bint dtype_is_object
127
+
128
+ def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None,
129
+ mode="c", bint allocate_buffer=True):
130
+
131
+ cdef int idx
132
+ cdef Py_ssize_t dim
133
+
134
+ self.ndim = <int> len(shape)
135
+ self.itemsize = itemsize
136
+
137
+ if not self.ndim:
138
+ raise ValueError, "Empty shape tuple for cython.array"
139
+
140
+ if itemsize <= 0:
141
+ raise ValueError, "itemsize <= 0 for cython.array"
142
+
143
+ if not isinstance(format, bytes):
144
+ format = format.encode('ASCII')
145
+ self._format = format # keep a reference to the byte string
146
+ self.format = self._format
147
+
148
+ # use single malloc() for both shape and strides
149
+ self._shape = <Py_ssize_t *> PyObject_Malloc(sizeof(Py_ssize_t)*self.ndim*2)
150
+ self._strides = self._shape + self.ndim
151
+
152
+ if not self._shape:
153
+ raise MemoryError, "unable to allocate shape and strides."
154
+
155
+ # cdef Py_ssize_t dim, stride
156
+ for idx, dim in enumerate(shape):
157
+ if dim <= 0:
158
+ raise ValueError, f"Invalid shape in axis {idx}: {dim}."
159
+ self._shape[idx] = dim
160
+
161
+ cdef char order
162
+ if mode == 'c':
163
+ order = b'C'
164
+ self.mode = u'c'
165
+ elif mode == 'fortran':
166
+ order = b'F'
167
+ self.mode = u'fortran'
168
+ else:
169
+ raise ValueError, f"Invalid mode, expected 'c' or 'fortran', got {mode}"
170
+
171
+ self.len = fill_contig_strides_array(self._shape, self._strides, itemsize, self.ndim, order)
172
+
173
+ self.free_data = allocate_buffer
174
+ self.dtype_is_object = format == b'O'
175
+
176
+ if allocate_buffer:
177
+ _allocate_buffer(self)
178
+
179
+ @cname('getbuffer')
180
+ def __getbuffer__(self, Py_buffer *info, int flags):
181
+ cdef int bufmode = -1
182
+ if flags & (PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS):
183
+ if self.mode == u"c":
184
+ bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
185
+ elif self.mode == u"fortran":
186
+ bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS
187
+ if not (flags & bufmode):
188
+ raise ValueError, "Can only create a buffer that is contiguous in memory."
189
+ info.buf = self.data
190
+ info.len = self.len
191
+
192
+ if flags & PyBUF_STRIDES:
193
+ info.ndim = self.ndim
194
+ info.shape = self._shape
195
+ info.strides = self._strides
196
+ else:
197
+ info.ndim = 1
198
+ info.shape = &self.len if flags & PyBUF_ND else NULL
199
+ info.strides = NULL
200
+
201
+ info.suboffsets = NULL
202
+ info.itemsize = self.itemsize
203
+ info.readonly = 0
204
+ info.format = self.format if flags & PyBUF_FORMAT else NULL
205
+ info.obj = self
206
+
207
+ def __dealloc__(array self):
208
+ if self.callback_free_data != NULL:
209
+ self.callback_free_data(self.data)
210
+ elif self.free_data and self.data is not NULL:
211
+ if self.dtype_is_object:
212
+ refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False)
213
+ free(self.data)
214
+ PyObject_Free(self._shape)
215
+
216
+ @property
217
+ def memview(self):
218
+ return self.get_memview()
219
+
220
+ @cname('get_memview')
221
+ cdef get_memview(self):
222
+ flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE
223
+ return memoryview(self, flags, self.dtype_is_object)
224
+
225
+ def __len__(self):
226
+ return self._shape[0]
227
+
228
+ def __getattr__(self, attr):
229
+ return getattr(self.memview, attr)
230
+
231
+ def __getitem__(self, item):
232
+ return self.memview[item]
233
+
234
+ def __setitem__(self, item, value):
235
+ self.memview[item] = value
236
+
237
+ # Sequence methods
238
+ try:
239
+ count = __pyx_collections_abc_Sequence.count
240
+ index = __pyx_collections_abc_Sequence.index
241
+ except:
242
+ pass
243
+
244
+ @cname("__pyx_array_allocate_buffer")
245
+ cdef int _allocate_buffer(array self) except -1:
246
+ # use malloc() for backwards compatibility
247
+ # in case external code wants to change the data pointer
248
+ cdef Py_ssize_t i
249
+ cdef PyObject **p
250
+
251
+ self.free_data = True
252
+ self.data = <char *>malloc(self.len)
253
+ if not self.data:
254
+ raise MemoryError, "unable to allocate array data."
255
+
256
+ if self.dtype_is_object:
257
+ p = <PyObject **> self.data
258
+ for i in range(self.len // self.itemsize):
259
+ p[i] = Py_None
260
+ Py_INCREF(Py_None)
261
+ return 0
262
+
263
+
264
+ @cname("__pyx_array_new")
265
+ cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, const char *c_mode, char *buf):
266
+ cdef array result
267
+ cdef str mode = "fortran" if c_mode[0] == b'f' else "c" # this often comes from a constant C string.
268
+
269
+ if buf is NULL:
270
+ result = array.__new__(array, shape, itemsize, format, mode)
271
+ else:
272
+ result = array.__new__(array, shape, itemsize, format, mode, allocate_buffer=False)
273
+ result.data = buf
274
+
275
+ return result
276
+
277
+
278
+ #
279
+ ### Memoryview constants and cython.view.memoryview class
280
+ #
281
+
282
+ # Disable generic_contiguous, as it makes trouble verifying contiguity:
283
+ # - 'contiguous' or '::1' means the dimension is contiguous with dtype
284
+ # - 'indirect_contiguous' means a contiguous list of pointers
285
+ # - dtype contiguous must be contiguous in the first or last dimension
286
+ # from the start, or from the dimension following the last indirect dimension
287
+ #
288
+ # e.g.
289
+ # int[::indirect_contiguous, ::contiguous, :]
290
+ #
291
+ # is valid (list of pointers to 2d fortran-contiguous array), but
292
+ #
293
+ # int[::generic_contiguous, ::contiguous, :]
294
+ #
295
+ # would mean you'd have assert dimension 0 to be indirect (and pointer contiguous) at runtime.
296
+ # So it doesn't bring any performance benefit, and it's only confusing.
297
+
298
+ @cname('__pyx_MemviewEnum')
299
+ cdef class Enum(object):
300
+ cdef object name
301
+ def __init__(self, name):
302
+ self.name = name
303
+ def __repr__(self):
304
+ return self.name
305
+
306
+ cdef generic = Enum("<strided and direct or indirect>")
307
+ cdef strided = Enum("<strided and direct>") # default
308
+ cdef indirect = Enum("<strided and indirect>")
309
+ # Disable generic_contiguous, as it is a troublemaker
310
+ #cdef generic_contiguous = Enum("<contiguous and direct or indirect>")
311
+ cdef contiguous = Enum("<contiguous and direct>")
312
+ cdef indirect_contiguous = Enum("<contiguous and indirect>")
313
+
314
+ # 'follow' is implied when the first or last axis is ::1
315
+
316
+
317
+ # pre-allocate thread locks for reuse
318
+ ## note that this could be implemented in a more beautiful way in "normal" Cython,
319
+ ## but this code gets merged into the user module and not everything works there.
320
+ cdef int __pyx_memoryview_thread_locks_used = 0
321
+ cdef PyThread_type_lock[{{THREAD_LOCKS_PREALLOCATED}}] __pyx_memoryview_thread_locks = [
322
+ {{for _ in range(THREAD_LOCKS_PREALLOCATED)}}
323
+ PyThread_allocate_lock(),
324
+ {{endfor}}
325
+ ]
326
+
327
+
328
+ @cname('__pyx_memoryview')
329
+ cdef class memoryview:
330
+
331
+ cdef object obj
332
+ cdef object _size
333
+ cdef object _array_interface
334
+ cdef PyThread_type_lock lock
335
+ cdef __pyx_atomic_int_type acquisition_count
336
+ cdef Py_buffer view
337
+ cdef int flags
338
+ cdef bint dtype_is_object
339
+ cdef __Pyx_TypeInfo *typeinfo
340
+
341
+ def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False):
342
+ self.obj = obj
343
+ self.flags = flags
344
+ if type(self) is memoryview or obj is not None:
345
+ PyObject_GetBuffer(obj, &self.view, flags)
346
+ if <PyObject *> self.view.obj == NULL:
347
+ (<__pyx_buffer *> &self.view).obj = Py_None
348
+ Py_INCREF(Py_None)
349
+
350
+ if not __PYX_CYTHON_ATOMICS_ENABLED():
351
+ global __pyx_memoryview_thread_locks_used
352
+ if __pyx_memoryview_thread_locks_used < {{THREAD_LOCKS_PREALLOCATED}}:
353
+ self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]
354
+ __pyx_memoryview_thread_locks_used += 1
355
+ if self.lock is NULL:
356
+ self.lock = PyThread_allocate_lock()
357
+ if self.lock is NULL:
358
+ raise MemoryError
359
+
360
+ if flags & PyBUF_FORMAT:
361
+ self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0')
362
+ else:
363
+ self.dtype_is_object = dtype_is_object
364
+
365
+ assert <Py_intptr_t><void*>(&self.acquisition_count) % sizeof(__pyx_atomic_int_type) == 0
366
+ self.typeinfo = NULL
367
+
368
+ def __dealloc__(memoryview self):
369
+ if self.obj is not None:
370
+ PyBuffer_Release(&self.view)
371
+ elif (<__pyx_buffer *> &self.view).obj == Py_None:
372
+ # Undo the incref in __cinit__() above.
373
+ (<__pyx_buffer *> &self.view).obj = NULL
374
+ Py_DECREF(Py_None)
375
+
376
+ cdef int i
377
+ global __pyx_memoryview_thread_locks_used
378
+ if self.lock != NULL:
379
+ for i in range(__pyx_memoryview_thread_locks_used):
380
+ if __pyx_memoryview_thread_locks[i] is self.lock:
381
+ __pyx_memoryview_thread_locks_used -= 1
382
+ if i != __pyx_memoryview_thread_locks_used:
383
+ __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = (
384
+ __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i])
385
+ break
386
+ else:
387
+ PyThread_free_lock(self.lock)
388
+
389
+ cdef char *get_item_pointer(memoryview self, object index) except NULL:
390
+ cdef Py_ssize_t dim
391
+ cdef char *itemp = <char *> self.view.buf
392
+
393
+ for dim, idx in enumerate(index):
394
+ itemp = pybuffer_index(&self.view, itemp, idx, dim)
395
+
396
+ return itemp
397
+
398
+ #@cname('__pyx_memoryview_getitem')
399
+ def __getitem__(memoryview self, object index):
400
+ if index is Ellipsis:
401
+ return self
402
+
403
+ have_slices, indices = _unellipsify(index, self.view.ndim)
404
+
405
+ cdef char *itemp
406
+ if have_slices:
407
+ return memview_slice(self, indices)
408
+ else:
409
+ itemp = self.get_item_pointer(indices)
410
+ return self.convert_item_to_object(itemp)
411
+
412
+ def __setitem__(memoryview self, object index, object value):
413
+ if self.view.readonly:
414
+ raise TypeError, "Cannot assign to read-only memoryview"
415
+
416
+ have_slices, index = _unellipsify(index, self.view.ndim)
417
+
418
+ if have_slices:
419
+ obj = self.is_slice(value)
420
+ if obj is not None:
421
+ self.setitem_slice_assignment(self[index], obj)
422
+ else:
423
+ self.setitem_slice_assign_scalar(self[index], value)
424
+ else:
425
+ self.setitem_indexed(index, value)
426
+
427
+ cdef is_slice(self, obj):
428
+ if not isinstance(obj, memoryview):
429
+ try:
430
+ obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS,
431
+ self.dtype_is_object)
432
+ except TypeError:
433
+ return None
434
+
435
+ return obj
436
+
437
+ cdef setitem_slice_assignment(self, dst, src):
438
+ cdef {{memviewslice_name}} dst_slice
439
+ cdef {{memviewslice_name}} src_slice
440
+ cdef {{memviewslice_name}} msrc = get_slice_from_memview(src, &src_slice)[0]
441
+ cdef {{memviewslice_name}} mdst = get_slice_from_memview(dst, &dst_slice)[0]
442
+
443
+ memoryview_copy_contents(msrc, mdst, src.ndim, dst.ndim, self.dtype_is_object)
444
+
445
+ cdef setitem_slice_assign_scalar(self, memoryview dst, value):
446
+ cdef int array[128]
447
+ cdef void *tmp = NULL
448
+ cdef void *item
449
+
450
+ cdef {{memviewslice_name}} *dst_slice
451
+ cdef {{memviewslice_name}} tmp_slice
452
+ dst_slice = get_slice_from_memview(dst, &tmp_slice)
453
+
454
+ if <size_t>self.view.itemsize > sizeof(array):
455
+ tmp = PyMem_Malloc(self.view.itemsize)
456
+ if tmp == NULL:
457
+ raise MemoryError
458
+ item = tmp
459
+ else:
460
+ item = <void *> array
461
+
462
+ try:
463
+ if self.dtype_is_object:
464
+ (<PyObject **> item)[0] = <PyObject *> value
465
+ else:
466
+ self.assign_item_from_object(<char *> item, value)
467
+
468
+ # It would be easy to support indirect dimensions, but it's easier
469
+ # to disallow :)
470
+ if self.view.suboffsets != NULL:
471
+ assert_direct_dimensions(self.view.suboffsets, self.view.ndim)
472
+ slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize,
473
+ item, self.dtype_is_object)
474
+ finally:
475
+ PyMem_Free(tmp)
476
+
477
+ cdef setitem_indexed(self, index, value):
478
+ cdef char *itemp = self.get_item_pointer(index)
479
+ self.assign_item_from_object(itemp, value)
480
+
481
+ cdef convert_item_to_object(self, char *itemp):
482
+ """Only used if instantiated manually by the user, or if Cython doesn't
483
+ know how to convert the type"""
484
+ import struct
485
+ cdef bytes bytesitem
486
+ # Do a manual and complete check here instead of this easy hack
487
+ bytesitem = itemp[:self.view.itemsize]
488
+ try:
489
+ result = struct.unpack(self.view.format, bytesitem)
490
+ except struct.error:
491
+ raise ValueError, "Unable to convert item to object"
492
+ else:
493
+ if len(self.view.format) == 1:
494
+ return result[0]
495
+ return result
496
+
497
+ cdef assign_item_from_object(self, char *itemp, object value):
498
+ """Only used if instantiated manually by the user, or if Cython doesn't
499
+ know how to convert the type"""
500
+ import struct
501
+ cdef char c
502
+ cdef bytes bytesvalue
503
+ cdef Py_ssize_t i
504
+
505
+ if isinstance(value, tuple):
506
+ bytesvalue = struct.pack(self.view.format, *value)
507
+ else:
508
+ bytesvalue = struct.pack(self.view.format, value)
509
+
510
+ for i, c in enumerate(bytesvalue):
511
+ itemp[i] = c
512
+
513
+ @cname('getbuffer')
514
+ def __getbuffer__(self, Py_buffer *info, int flags):
515
+ if flags & PyBUF_WRITABLE and self.view.readonly:
516
+ raise ValueError, "Cannot create writable memory view from read-only memoryview"
517
+
518
+ if flags & PyBUF_ND:
519
+ info.shape = self.view.shape
520
+ else:
521
+ info.shape = NULL
522
+
523
+ if flags & PyBUF_STRIDES:
524
+ info.strides = self.view.strides
525
+ else:
526
+ info.strides = NULL
527
+
528
+ if flags & PyBUF_INDIRECT:
529
+ info.suboffsets = self.view.suboffsets
530
+ else:
531
+ info.suboffsets = NULL
532
+
533
+ if flags & PyBUF_FORMAT:
534
+ info.format = self.view.format
535
+ else:
536
+ info.format = NULL
537
+
538
+ info.buf = self.view.buf
539
+ info.ndim = self.view.ndim
540
+ info.itemsize = self.view.itemsize
541
+ info.len = self.view.len
542
+ info.readonly = self.view.readonly
543
+ info.obj = self
544
+
545
+ # Some properties that have the same semantics as in NumPy
546
+ @property
547
+ def T(self):
548
+ cdef _memoryviewslice result = memoryview_copy(self)
549
+ transpose_memslice(&result.from_slice)
550
+ return result
551
+
552
+ @property
553
+ def base(self):
554
+ return self._get_base()
555
+
556
+ cdef _get_base(self):
557
+ return self.obj
558
+
559
+ @property
560
+ def shape(self):
561
+ return tuple([length for length in self.view.shape[:self.view.ndim]])
562
+
563
+ @property
564
+ def strides(self):
565
+ if self.view.strides == NULL:
566
+ # Note: we always ask for strides, so if this is not set it's a bug
567
+ raise ValueError, "Buffer view does not expose strides"
568
+
569
+ return tuple([stride for stride in self.view.strides[:self.view.ndim]])
570
+
571
+ @property
572
+ def suboffsets(self):
573
+ if self.view.suboffsets == NULL:
574
+ return (-1,) * self.view.ndim
575
+
576
+ return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]])
577
+
578
+ @property
579
+ def ndim(self):
580
+ return self.view.ndim
581
+
582
+ @property
583
+ def itemsize(self):
584
+ return self.view.itemsize
585
+
586
+ @property
587
+ def nbytes(self):
588
+ return self.size * self.view.itemsize
589
+
590
+ @property
591
+ def size(self):
592
+ if self._size is None:
593
+ result = 1
594
+
595
+ for length in self.view.shape[:self.view.ndim]:
596
+ result *= length
597
+
598
+ self._size = result
599
+
600
+ return self._size
601
+
602
+ def __len__(self):
603
+ if self.view.ndim >= 1:
604
+ return self.view.shape[0]
605
+
606
+ return 0
607
+
608
+ def __repr__(self):
609
+ return "<MemoryView of %r at 0x%x>" % (self.base.__class__.__name__,
610
+ id(self))
611
+
612
+ def __str__(self):
613
+ return "<MemoryView of %r object>" % (self.base.__class__.__name__,)
614
+
615
+ # Support the same attributes as memoryview slices
616
+ def is_c_contig(self):
617
+ cdef {{memviewslice_name}} *mslice
618
+ cdef {{memviewslice_name}} tmp
619
+ mslice = get_slice_from_memview(self, &tmp)
620
+ return slice_is_contig(mslice[0], 'C', self.view.ndim)
621
+
622
+ def is_f_contig(self):
623
+ cdef {{memviewslice_name}} *mslice
624
+ cdef {{memviewslice_name}} tmp
625
+ mslice = get_slice_from_memview(self, &tmp)
626
+ return slice_is_contig(mslice[0], 'F', self.view.ndim)
627
+
628
+ def copy(self):
629
+ cdef {{memviewslice_name}} mslice
630
+ cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS
631
+
632
+ slice_copy(self, &mslice)
633
+ mslice = slice_copy_contig(&mslice, "c", self.view.ndim,
634
+ self.view.itemsize,
635
+ flags|PyBUF_C_CONTIGUOUS,
636
+ self.dtype_is_object)
637
+
638
+ return memoryview_copy_from_slice(self, &mslice)
639
+
640
+ def copy_fortran(self):
641
+ cdef {{memviewslice_name}} src, dst
642
+ cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS
643
+
644
+ slice_copy(self, &src)
645
+ dst = slice_copy_contig(&src, "fortran", self.view.ndim,
646
+ self.view.itemsize,
647
+ flags|PyBUF_F_CONTIGUOUS,
648
+ self.dtype_is_object)
649
+
650
+ return memoryview_copy_from_slice(self, &dst)
651
+
652
+
653
+ @cname('__pyx_memoryview_new')
654
+ cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo):
655
+ cdef memoryview result = memoryview(o, flags, dtype_is_object)
656
+ result.typeinfo = typeinfo
657
+ return result
658
+
659
+ @cname('__pyx_memoryview_check')
660
+ cdef inline bint memoryview_check(object o) noexcept:
661
+ return isinstance(o, memoryview)
662
+
663
+ cdef tuple _unellipsify(object index, int ndim):
664
+ """
665
+ Replace all ellipses with full slices and fill incomplete indices with
666
+ full slices.
667
+ """
668
+ cdef Py_ssize_t idx
669
+ tup = <tuple>index if isinstance(index, tuple) else (index,)
670
+
671
+ result = [slice(None)] * ndim
672
+ have_slices = False
673
+ seen_ellipsis = False
674
+ idx = 0
675
+ for item in tup:
676
+ if item is Ellipsis:
677
+ if not seen_ellipsis:
678
+ idx += ndim - len(tup)
679
+ seen_ellipsis = True
680
+ have_slices = True
681
+ else:
682
+ if isinstance(item, slice):
683
+ have_slices = True
684
+ elif not PyIndex_Check(item):
685
+ raise TypeError, f"Cannot index with type '{type(item)}'"
686
+ result[idx] = item
687
+ idx += 1
688
+
689
+ nslices = ndim - idx
690
+ return have_slices or nslices, tuple(result)
691
+
692
+ cdef int assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim) except -1:
693
+ for suboffset in suboffsets[:ndim]:
694
+ if suboffset >= 0:
695
+ raise ValueError, "Indirect dimensions not supported"
696
+ return 0 # return type just used as an error flag
697
+
698
+ #
699
+ ### Slicing a memoryview
700
+ #
701
+
702
+ @cname('__pyx_memview_slice')
703
+ cdef memoryview memview_slice(memoryview memview, object indices):
704
+ cdef int new_ndim = 0, suboffset_dim = -1, dim
705
+ cdef bint negative_step
706
+ cdef {{memviewslice_name}} src, dst
707
+ cdef {{memviewslice_name}} *p_src
708
+
709
+ # dst is copied by value in memoryview_fromslice -- initialize it
710
+ # src is never copied
711
+ memset(&dst, 0, sizeof(dst))
712
+
713
+ cdef _memoryviewslice memviewsliceobj
714
+
715
+ assert memview.view.ndim > 0
716
+
717
+ if isinstance(memview, _memoryviewslice):
718
+ memviewsliceobj = memview
719
+ p_src = &memviewsliceobj.from_slice
720
+ else:
721
+ slice_copy(memview, &src)
722
+ p_src = &src
723
+
724
+ # Note: don't use variable src at this point
725
+ # SubNote: we should be able to declare variables in blocks...
726
+
727
+ # memoryview_fromslice() will inc our dst slice
728
+ dst.memview = p_src.memview
729
+ dst.data = p_src.data
730
+
731
+ # Put everything in temps to avoid this bloody warning:
732
+ # "Argument evaluation order in C function call is undefined and
733
+ # may not be as expected"
734
+ cdef {{memviewslice_name}} *p_dst = &dst
735
+ cdef int *p_suboffset_dim = &suboffset_dim
736
+ cdef Py_ssize_t start, stop, step, cindex
737
+ cdef bint have_start, have_stop, have_step
738
+
739
+ for dim, index in enumerate(indices):
740
+ if PyIndex_Check(index):
741
+ cindex = index
742
+ slice_memviewslice(
743
+ p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim],
744
+ dim, new_ndim, p_suboffset_dim,
745
+ cindex, 0, 0, # start, stop, step
746
+ 0, 0, 0, # have_{start,stop,step}
747
+ False)
748
+ elif index is None:
749
+ p_dst.shape[new_ndim] = 1
750
+ p_dst.strides[new_ndim] = 0
751
+ p_dst.suboffsets[new_ndim] = -1
752
+ new_ndim += 1
753
+ else:
754
+ start = index.start or 0
755
+ stop = index.stop or 0
756
+ step = index.step or 0
757
+
758
+ have_start = index.start is not None
759
+ have_stop = index.stop is not None
760
+ have_step = index.step is not None
761
+
762
+ slice_memviewslice(
763
+ p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim],
764
+ dim, new_ndim, p_suboffset_dim,
765
+ start, stop, step,
766
+ have_start, have_stop, have_step,
767
+ True)
768
+ new_ndim += 1
769
+
770
+ if isinstance(memview, _memoryviewslice):
771
+ return memoryview_fromslice(dst, new_ndim,
772
+ memviewsliceobj.to_object_func,
773
+ memviewsliceobj.to_dtype_func,
774
+ memview.dtype_is_object)
775
+ else:
776
+ return memoryview_fromslice(dst, new_ndim, NULL, NULL,
777
+ memview.dtype_is_object)
778
+
779
+
780
+ #
781
+ ### Slicing in a single dimension of a memoryviewslice
782
+ #
783
+
784
+ @cname('__pyx_memoryview_slice_memviewslice')
785
+ cdef int slice_memviewslice(
786
+ {{memviewslice_name}} *dst,
787
+ Py_ssize_t shape, Py_ssize_t stride, Py_ssize_t suboffset,
788
+ int dim, int new_ndim, int *suboffset_dim,
789
+ Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step,
790
+ int have_start, int have_stop, int have_step,
791
+ bint is_slice) except -1 nogil:
792
+ """
793
+ Create a new slice dst given slice src.
794
+
795
+ dim - the current src dimension (indexing will make dimensions
796
+ disappear)
797
+ new_dim - the new dst dimension
798
+ suboffset_dim - pointer to a single int initialized to -1 to keep track of
799
+ where slicing offsets should be added
800
+ """
801
+
802
+ cdef Py_ssize_t new_shape
803
+ cdef bint negative_step
804
+
805
+ if not is_slice:
806
+ # index is a normal integer-like index
807
+ if start < 0:
808
+ start += shape
809
+ if not 0 <= start < shape:
810
+ _err_dim(PyExc_IndexError, "Index out of bounds (axis %d)", dim)
811
+ else:
812
+ # index is a slice
813
+ if have_step:
814
+ negative_step = step < 0
815
+ if step == 0:
816
+ _err_dim(PyExc_ValueError, "Step may not be zero (axis %d)", dim)
817
+ else:
818
+ negative_step = False
819
+ step = 1
820
+
821
+ # check our bounds and set defaults
822
+ if have_start:
823
+ if start < 0:
824
+ start += shape
825
+ if start < 0:
826
+ start = 0
827
+ elif start >= shape:
828
+ if negative_step:
829
+ start = shape - 1
830
+ else:
831
+ start = shape
832
+ else:
833
+ if negative_step:
834
+ start = shape - 1
835
+ else:
836
+ start = 0
837
+
838
+ if have_stop:
839
+ if stop < 0:
840
+ stop += shape
841
+ if stop < 0:
842
+ stop = 0
843
+ elif stop > shape:
844
+ stop = shape
845
+ else:
846
+ if negative_step:
847
+ stop = -1
848
+ else:
849
+ stop = shape
850
+
851
+ # len = ceil( (stop - start) / step )
852
+ with cython.cdivision(True):
853
+ new_shape = (stop - start) // step
854
+
855
+ if (stop - start) - step * new_shape:
856
+ new_shape += 1
857
+
858
+ if new_shape < 0:
859
+ new_shape = 0
860
+
861
+ # shape/strides/suboffsets
862
+ dst.strides[new_ndim] = stride * step
863
+ dst.shape[new_ndim] = new_shape
864
+ dst.suboffsets[new_ndim] = suboffset
865
+
866
+ # Add the slicing or indexing offsets to the right suboffset or base data *
867
+ if suboffset_dim[0] < 0:
868
+ dst.data += start * stride
869
+ else:
870
+ dst.suboffsets[suboffset_dim[0]] += start * stride
871
+
872
+ if suboffset >= 0:
873
+ if not is_slice:
874
+ if new_ndim == 0:
875
+ dst.data = (<char **> dst.data)[0] + suboffset
876
+ else:
877
+ _err_dim(PyExc_IndexError, "All dimensions preceding dimension %d "
878
+ "must be indexed and not sliced", dim)
879
+ else:
880
+ suboffset_dim[0] = new_ndim
881
+
882
+ return 0
883
+
884
+ #
885
+ ### Index a memoryview
886
+ #
887
+ @cname('__pyx_pybuffer_index')
888
+ cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index,
889
+ Py_ssize_t dim) except NULL:
890
+ cdef Py_ssize_t shape, stride, suboffset = -1
891
+ cdef Py_ssize_t itemsize = view.itemsize
892
+ cdef char *resultp
893
+
894
+ if view.ndim == 0:
895
+ shape = view.len // itemsize
896
+ stride = itemsize
897
+ else:
898
+ shape = view.shape[dim]
899
+ stride = view.strides[dim]
900
+ if view.suboffsets != NULL:
901
+ suboffset = view.suboffsets[dim]
902
+
903
+ if index < 0:
904
+ index += view.shape[dim]
905
+ if index < 0:
906
+ raise IndexError, f"Out of bounds on buffer access (axis {dim})"
907
+
908
+ if index >= shape:
909
+ raise IndexError, f"Out of bounds on buffer access (axis {dim})"
910
+
911
+ resultp = bufp + index * stride
912
+ if suboffset >= 0:
913
+ resultp = (<char **> resultp)[0] + suboffset
914
+
915
+ return resultp
916
+
917
+ #
918
+ ### Transposing a memoryviewslice
919
+ #
920
+ @cname('__pyx_memslice_transpose')
921
+ cdef int transpose_memslice({{memviewslice_name}} *memslice) except -1 nogil:
922
+ cdef int ndim = memslice.memview.view.ndim
923
+
924
+ cdef Py_ssize_t *shape = memslice.shape
925
+ cdef Py_ssize_t *strides = memslice.strides
926
+
927
+ # reverse strides and shape
928
+ cdef int i, j
929
+ for i in range(ndim // 2):
930
+ j = ndim - 1 - i
931
+ strides[i], strides[j] = strides[j], strides[i]
932
+ shape[i], shape[j] = shape[j], shape[i]
933
+
934
+ if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0:
935
+ _err(PyExc_ValueError, "Cannot transpose memoryview with indirect dimensions")
936
+
937
+ return 0
938
+
939
+ #
940
+ ### Creating new memoryview objects from slices and memoryviews
941
+ #
942
+ @cython.collection_type("sequence")
943
+ @cname('__pyx_memoryviewslice')
944
+ cdef class _memoryviewslice(memoryview):
945
+ "Internal class for passing memoryview slices to Python"
946
+
947
+ # We need this to keep our shape/strides/suboffset pointers valid
948
+ cdef {{memviewslice_name}} from_slice
949
+ # We need this only to print it's class' name
950
+ cdef object from_object
951
+
952
+ cdef object (*to_object_func)(char *)
953
+ cdef int (*to_dtype_func)(char *, object) except 0
954
+
955
+ def __dealloc__(self):
956
+ __PYX_XCLEAR_MEMVIEW(&self.from_slice, 1)
957
+
958
+ cdef convert_item_to_object(self, char *itemp):
959
+ if self.to_object_func != NULL:
960
+ return self.to_object_func(itemp)
961
+ else:
962
+ return memoryview.convert_item_to_object(self, itemp)
963
+
964
+ cdef assign_item_from_object(self, char *itemp, object value):
965
+ if self.to_dtype_func != NULL:
966
+ self.to_dtype_func(itemp, value)
967
+ else:
968
+ memoryview.assign_item_from_object(self, itemp, value)
969
+
970
+ cdef _get_base(self):
971
+ return self.from_object
972
+
973
+ # Sequence methods
974
+ try:
975
+ count = __pyx_collections_abc_Sequence.count
976
+ index = __pyx_collections_abc_Sequence.index
977
+ except:
978
+ pass
979
+
980
+ try:
981
+ if __pyx_collections_abc_Sequence:
982
+ # The main value of registering _memoryviewslice as a
983
+ # Sequence is that it can be used in structural pattern
984
+ # matching in Python 3.10+
985
+ __pyx_collections_abc_Sequence.register(_memoryviewslice)
986
+ __pyx_collections_abc_Sequence.register(array)
987
+ except:
988
+ pass # ignore failure, it's a minor issue
989
+
990
+ @cname('__pyx_memoryview_fromslice')
991
+ cdef memoryview_fromslice({{memviewslice_name}} memviewslice,
992
+ int ndim,
993
+ object (*to_object_func)(char *),
994
+ int (*to_dtype_func)(char *, object) except 0,
995
+ bint dtype_is_object):
996
+
997
+ cdef _memoryviewslice result
998
+
999
+ if <PyObject *> memviewslice.memview == Py_None:
1000
+ return None
1001
+
1002
+ # assert 0 < ndim <= memviewslice.memview.view.ndim, (
1003
+ # ndim, memviewslice.memview.view.ndim)
1004
+
1005
+ result = _memoryviewslice.__new__(_memoryviewslice, None, 0, dtype_is_object)
1006
+
1007
+ result.from_slice = memviewslice
1008
+ __PYX_INC_MEMVIEW(&memviewslice, 1)
1009
+
1010
+ result.from_object = (<memoryview> memviewslice.memview)._get_base()
1011
+ result.typeinfo = memviewslice.memview.typeinfo
1012
+
1013
+ result.view = memviewslice.memview.view
1014
+ result.view.buf = <void *> memviewslice.data
1015
+ result.view.ndim = ndim
1016
+ (<__pyx_buffer *> &result.view).obj = Py_None
1017
+ Py_INCREF(Py_None)
1018
+
1019
+ if (<memoryview>memviewslice.memview).flags & PyBUF_WRITABLE:
1020
+ result.flags = PyBUF_RECORDS
1021
+ else:
1022
+ result.flags = PyBUF_RECORDS_RO
1023
+
1024
+ result.view.shape = <Py_ssize_t *> result.from_slice.shape
1025
+ result.view.strides = <Py_ssize_t *> result.from_slice.strides
1026
+
1027
+ # only set suboffsets if actually used, otherwise set to NULL to improve compatibility
1028
+ result.view.suboffsets = NULL
1029
+ for suboffset in result.from_slice.suboffsets[:ndim]:
1030
+ if suboffset >= 0:
1031
+ result.view.suboffsets = <Py_ssize_t *> result.from_slice.suboffsets
1032
+ break
1033
+
1034
+ result.view.len = result.view.itemsize
1035
+ for length in result.view.shape[:ndim]:
1036
+ result.view.len *= length
1037
+
1038
+ result.to_object_func = to_object_func
1039
+ result.to_dtype_func = to_dtype_func
1040
+
1041
+ return result
1042
+
1043
+ @cname('__pyx_memoryview_get_slice_from_memoryview')
1044
+ cdef {{memviewslice_name}} *get_slice_from_memview(memoryview memview,
1045
+ {{memviewslice_name}} *mslice) except NULL:
1046
+ cdef _memoryviewslice obj
1047
+ if isinstance(memview, _memoryviewslice):
1048
+ obj = memview
1049
+ return &obj.from_slice
1050
+ else:
1051
+ slice_copy(memview, mslice)
1052
+ return mslice
1053
+
1054
+ @cname('__pyx_memoryview_slice_copy')
1055
+ cdef void slice_copy(memoryview memview, {{memviewslice_name}} *dst) noexcept:
1056
+ cdef int dim
1057
+ cdef (Py_ssize_t*) shape, strides, suboffsets
1058
+
1059
+ shape = memview.view.shape
1060
+ strides = memview.view.strides
1061
+ suboffsets = memview.view.suboffsets
1062
+
1063
+ dst.memview = <__pyx_memoryview *> memview
1064
+ dst.data = <char *> memview.view.buf
1065
+
1066
+ for dim in range(memview.view.ndim):
1067
+ dst.shape[dim] = shape[dim]
1068
+ dst.strides[dim] = strides[dim]
1069
+ dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1
1070
+
1071
+ @cname('__pyx_memoryview_copy_object')
1072
+ cdef memoryview_copy(memoryview memview):
1073
+ "Create a new memoryview object"
1074
+ cdef {{memviewslice_name}} memviewslice
1075
+ slice_copy(memview, &memviewslice)
1076
+ return memoryview_copy_from_slice(memview, &memviewslice)
1077
+
1078
+ @cname('__pyx_memoryview_copy_object_from_slice')
1079
+ cdef memoryview_copy_from_slice(memoryview memview, {{memviewslice_name}} *memviewslice):
1080
+ """
1081
+ Create a new memoryview object from a given memoryview object and slice.
1082
+ """
1083
+ cdef object (*to_object_func)(char *)
1084
+ cdef int (*to_dtype_func)(char *, object) except 0
1085
+
1086
+ if isinstance(memview, _memoryviewslice):
1087
+ to_object_func = (<_memoryviewslice> memview).to_object_func
1088
+ to_dtype_func = (<_memoryviewslice> memview).to_dtype_func
1089
+ else:
1090
+ to_object_func = NULL
1091
+ to_dtype_func = NULL
1092
+
1093
+ return memoryview_fromslice(memviewslice[0], memview.view.ndim,
1094
+ to_object_func, to_dtype_func,
1095
+ memview.dtype_is_object)
1096
+
1097
+
1098
+ #
1099
+ ### Copy the contents of a memoryview slices
1100
+ #
1101
+ cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) noexcept nogil:
1102
+ return -arg if arg < 0 else arg
1103
+
1104
+ @cname('__pyx_get_best_slice_order')
1105
+ cdef char get_best_order({{memviewslice_name}} *mslice, int ndim) noexcept nogil:
1106
+ """
1107
+ Figure out the best memory access order for a given slice.
1108
+ """
1109
+ cdef int i
1110
+ cdef Py_ssize_t c_stride = 0
1111
+ cdef Py_ssize_t f_stride = 0
1112
+
1113
+ for i in range(ndim - 1, -1, -1):
1114
+ if mslice.shape[i] > 1:
1115
+ c_stride = mslice.strides[i]
1116
+ break
1117
+
1118
+ for i in range(ndim):
1119
+ if mslice.shape[i] > 1:
1120
+ f_stride = mslice.strides[i]
1121
+ break
1122
+
1123
+ if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride):
1124
+ return 'C'
1125
+ else:
1126
+ return 'F'
1127
+
1128
+ @cython.cdivision(True)
1129
+ cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides,
1130
+ char *dst_data, Py_ssize_t *dst_strides,
1131
+ Py_ssize_t *src_shape, Py_ssize_t *dst_shape,
1132
+ int ndim, size_t itemsize) noexcept nogil:
1133
+ # Note: src_extent is 1 if we're broadcasting
1134
+ # dst_extent always >= src_extent as we don't do reductions
1135
+ cdef Py_ssize_t i
1136
+ cdef Py_ssize_t src_extent = src_shape[0]
1137
+ cdef Py_ssize_t dst_extent = dst_shape[0]
1138
+ cdef Py_ssize_t src_stride = src_strides[0]
1139
+ cdef Py_ssize_t dst_stride = dst_strides[0]
1140
+
1141
+ if ndim == 1:
1142
+ if (src_stride > 0 and dst_stride > 0 and
1143
+ <size_t> src_stride == itemsize == <size_t> dst_stride):
1144
+ memcpy(dst_data, src_data, itemsize * dst_extent)
1145
+ else:
1146
+ for i in range(dst_extent):
1147
+ memcpy(dst_data, src_data, itemsize)
1148
+ src_data += src_stride
1149
+ dst_data += dst_stride
1150
+ else:
1151
+ for i in range(dst_extent):
1152
+ _copy_strided_to_strided(src_data, src_strides + 1,
1153
+ dst_data, dst_strides + 1,
1154
+ src_shape + 1, dst_shape + 1,
1155
+ ndim - 1, itemsize)
1156
+ src_data += src_stride
1157
+ dst_data += dst_stride
1158
+
1159
+ cdef void copy_strided_to_strided({{memviewslice_name}} *src,
1160
+ {{memviewslice_name}} *dst,
1161
+ int ndim, size_t itemsize) noexcept nogil:
1162
+ _copy_strided_to_strided(src.data, src.strides, dst.data, dst.strides,
1163
+ src.shape, dst.shape, ndim, itemsize)
1164
+
1165
+ @cname('__pyx_memoryview_slice_get_size')
1166
+ cdef Py_ssize_t slice_get_size({{memviewslice_name}} *src, int ndim) noexcept nogil:
1167
+ "Return the size of the memory occupied by the slice in number of bytes"
1168
+ cdef Py_ssize_t shape, size = src.memview.view.itemsize
1169
+
1170
+ for shape in src.shape[:ndim]:
1171
+ size *= shape
1172
+
1173
+ return size
1174
+
1175
+ @cname('__pyx_fill_contig_strides_array')
1176
+ cdef Py_ssize_t fill_contig_strides_array(
1177
+ Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride,
1178
+ int ndim, char order) noexcept nogil:
1179
+ """
1180
+ Fill the strides array for a slice with C or F contiguous strides.
1181
+ This is like PyBuffer_FillContiguousStrides, but compatible with py < 2.6
1182
+ """
1183
+ cdef int idx
1184
+
1185
+ if order == 'F':
1186
+ for idx in range(ndim):
1187
+ strides[idx] = stride
1188
+ stride *= shape[idx]
1189
+ else:
1190
+ for idx in range(ndim - 1, -1, -1):
1191
+ strides[idx] = stride
1192
+ stride *= shape[idx]
1193
+
1194
+ return stride
1195
+
1196
+ @cname('__pyx_memoryview_copy_data_to_temp')
1197
+ cdef void *copy_data_to_temp({{memviewslice_name}} *src,
1198
+ {{memviewslice_name}} *tmpslice,
1199
+ char order,
1200
+ int ndim) except NULL nogil:
1201
+ """
1202
+ Copy a direct slice to temporary contiguous memory. The caller should free
1203
+ the result when done.
1204
+ """
1205
+ cdef int i
1206
+ cdef void *result
1207
+
1208
+ cdef size_t itemsize = src.memview.view.itemsize
1209
+ cdef size_t size = slice_get_size(src, ndim)
1210
+
1211
+ result = malloc(size)
1212
+ if not result:
1213
+ _err_no_memory()
1214
+
1215
+ # tmpslice[0] = src
1216
+ tmpslice.data = <char *> result
1217
+ tmpslice.memview = src.memview
1218
+ for i in range(ndim):
1219
+ tmpslice.shape[i] = src.shape[i]
1220
+ tmpslice.suboffsets[i] = -1
1221
+
1222
+ fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize, ndim, order)
1223
+
1224
+ # We need to broadcast strides again
1225
+ for i in range(ndim):
1226
+ if tmpslice.shape[i] == 1:
1227
+ tmpslice.strides[i] = 0
1228
+
1229
+ if slice_is_contig(src[0], order, ndim):
1230
+ memcpy(result, src.data, size)
1231
+ else:
1232
+ copy_strided_to_strided(src, tmpslice, ndim, itemsize)
1233
+
1234
+ return result
1235
+
1236
+ # Use 'with gil' functions and avoid 'with gil' blocks, as the code within the blocks
1237
+ # has temporaries that need the GIL to clean up
1238
+ @cname('__pyx_memoryview_err_extents')
1239
+ cdef int _err_extents(int i, Py_ssize_t extent1,
1240
+ Py_ssize_t extent2) except -1 with gil:
1241
+ raise ValueError, f"got differing extents in dimension {i} (got {extent1} and {extent2})"
1242
+
1243
+ @cname('__pyx_memoryview_err_dim')
1244
+ cdef int _err_dim(PyObject *error, str msg, int dim) except -1 with gil:
1245
+ raise <object>error, msg % dim
1246
+
1247
+ @cname('__pyx_memoryview_err')
1248
+ cdef int _err(PyObject *error, str msg) except -1 with gil:
1249
+ raise <object>error, msg
1250
+
1251
+ @cname('__pyx_memoryview_err_no_memory')
1252
+ cdef int _err_no_memory() except -1 with gil:
1253
+ raise MemoryError
1254
+
1255
+
1256
+ @cname('__pyx_memoryview_copy_contents')
1257
+ cdef int memoryview_copy_contents({{memviewslice_name}} src,
1258
+ {{memviewslice_name}} dst,
1259
+ int src_ndim, int dst_ndim,
1260
+ bint dtype_is_object) except -1 nogil:
1261
+ """
1262
+ Copy memory from slice src to slice dst.
1263
+ Check for overlapping memory and verify the shapes.
1264
+ """
1265
+ cdef void *tmpdata = NULL
1266
+ cdef size_t itemsize = src.memview.view.itemsize
1267
+ cdef int i
1268
+ cdef char order = get_best_order(&src, src_ndim)
1269
+ cdef bint broadcasting = False
1270
+ cdef bint direct_copy = False
1271
+ cdef {{memviewslice_name}} tmp
1272
+
1273
+ if src_ndim < dst_ndim:
1274
+ broadcast_leading(&src, src_ndim, dst_ndim)
1275
+ elif dst_ndim < src_ndim:
1276
+ broadcast_leading(&dst, dst_ndim, src_ndim)
1277
+
1278
+ cdef int ndim = max(src_ndim, dst_ndim)
1279
+
1280
+ for i in range(ndim):
1281
+ if src.shape[i] != dst.shape[i]:
1282
+ if src.shape[i] == 1:
1283
+ broadcasting = True
1284
+ src.strides[i] = 0
1285
+ else:
1286
+ _err_extents(i, dst.shape[i], src.shape[i])
1287
+
1288
+ if src.suboffsets[i] >= 0:
1289
+ _err_dim(PyExc_ValueError, "Dimension %d is not direct", i)
1290
+
1291
+ if slices_overlap(&src, &dst, ndim, itemsize):
1292
+ # slices overlap, copy to temp, copy temp to dst
1293
+ if not slice_is_contig(src, order, ndim):
1294
+ order = get_best_order(&dst, ndim)
1295
+
1296
+ tmpdata = copy_data_to_temp(&src, &tmp, order, ndim)
1297
+ src = tmp
1298
+
1299
+ if not broadcasting:
1300
+ # See if both slices have equal contiguity, in that case perform a
1301
+ # direct copy. This only works when we are not broadcasting.
1302
+ if slice_is_contig(src, 'C', ndim):
1303
+ direct_copy = slice_is_contig(dst, 'C', ndim)
1304
+ elif slice_is_contig(src, 'F', ndim):
1305
+ direct_copy = slice_is_contig(dst, 'F', ndim)
1306
+
1307
+ if direct_copy:
1308
+ # Contiguous slices with same order
1309
+ refcount_copying(&dst, dtype_is_object, ndim, inc=False)
1310
+ memcpy(dst.data, src.data, slice_get_size(&src, ndim))
1311
+ refcount_copying(&dst, dtype_is_object, ndim, inc=True)
1312
+ free(tmpdata)
1313
+ return 0
1314
+
1315
+ if order == 'F' == get_best_order(&dst, ndim):
1316
+ # see if both slices have Fortran order, transpose them to match our
1317
+ # C-style indexing order
1318
+ transpose_memslice(&src)
1319
+ transpose_memslice(&dst)
1320
+
1321
+ refcount_copying(&dst, dtype_is_object, ndim, inc=False)
1322
+ copy_strided_to_strided(&src, &dst, ndim, itemsize)
1323
+ refcount_copying(&dst, dtype_is_object, ndim, inc=True)
1324
+
1325
+ free(tmpdata)
1326
+ return 0
1327
+
1328
+ @cname('__pyx_memoryview_broadcast_leading')
1329
+ cdef void broadcast_leading({{memviewslice_name}} *mslice,
1330
+ int ndim,
1331
+ int ndim_other) noexcept nogil:
1332
+ cdef int i
1333
+ cdef int offset = ndim_other - ndim
1334
+
1335
+ for i in range(ndim - 1, -1, -1):
1336
+ mslice.shape[i + offset] = mslice.shape[i]
1337
+ mslice.strides[i + offset] = mslice.strides[i]
1338
+ mslice.suboffsets[i + offset] = mslice.suboffsets[i]
1339
+
1340
+ for i in range(offset):
1341
+ mslice.shape[i] = 1
1342
+ mslice.strides[i] = mslice.strides[0]
1343
+ mslice.suboffsets[i] = -1
1344
+
1345
+ #
1346
+ ### Take care of refcounting the objects in slices. Do this separately from any copying,
1347
+ ### to minimize acquiring the GIL
1348
+ #
1349
+
1350
+ @cname('__pyx_memoryview_refcount_copying')
1351
+ cdef void refcount_copying({{memviewslice_name}} *dst, bint dtype_is_object, int ndim, bint inc) noexcept nogil:
1352
+ # incref or decref the objects in the destination slice if the dtype is object
1353
+ if dtype_is_object:
1354
+ refcount_objects_in_slice_with_gil(dst.data, dst.shape, dst.strides, ndim, inc)
1355
+
1356
+ @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil')
1357
+ cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape,
1358
+ Py_ssize_t *strides, int ndim,
1359
+ bint inc) noexcept with gil:
1360
+ refcount_objects_in_slice(data, shape, strides, ndim, inc)
1361
+
1362
+ @cname('__pyx_memoryview_refcount_objects_in_slice')
1363
+ cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape,
1364
+ Py_ssize_t *strides, int ndim, bint inc) noexcept:
1365
+ cdef Py_ssize_t i
1366
+ cdef Py_ssize_t stride = strides[0]
1367
+
1368
+ for i in range(shape[0]):
1369
+ if ndim == 1:
1370
+ if inc:
1371
+ Py_INCREF((<PyObject **> data)[0])
1372
+ else:
1373
+ Py_DECREF((<PyObject **> data)[0])
1374
+ else:
1375
+ refcount_objects_in_slice(data, shape + 1, strides + 1, ndim - 1, inc)
1376
+
1377
+ data += stride
1378
+
1379
+ #
1380
+ ### Scalar to slice assignment
1381
+ #
1382
+ @cname('__pyx_memoryview_slice_assign_scalar')
1383
+ cdef void slice_assign_scalar({{memviewslice_name}} *dst, int ndim,
1384
+ size_t itemsize, void *item,
1385
+ bint dtype_is_object) noexcept nogil:
1386
+ refcount_copying(dst, dtype_is_object, ndim, inc=False)
1387
+ _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, itemsize, item)
1388
+ refcount_copying(dst, dtype_is_object, ndim, inc=True)
1389
+
1390
+
1391
+ @cname('__pyx_memoryview__slice_assign_scalar')
1392
+ cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape,
1393
+ Py_ssize_t *strides, int ndim,
1394
+ size_t itemsize, void *item) noexcept nogil:
1395
+ cdef Py_ssize_t i
1396
+ cdef Py_ssize_t stride = strides[0]
1397
+ cdef Py_ssize_t extent = shape[0]
1398
+
1399
+ if ndim == 1:
1400
+ for i in range(extent):
1401
+ memcpy(data, item, itemsize)
1402
+ data += stride
1403
+ else:
1404
+ for i in range(extent):
1405
+ _slice_assign_scalar(data, shape + 1, strides + 1, ndim - 1, itemsize, item)
1406
+ data += stride
1407
+
1408
+
1409
+ ############### BufferFormatFromTypeInfo ###############
1410
+ cdef extern from *:
1411
+ ctypedef struct __Pyx_StructField
1412
+
1413
+ cdef enum:
1414
+ __PYX_BUF_FLAGS_PACKED_STRUCT
1415
+ __PYX_BUF_FLAGS_INTEGER_COMPLEX
1416
+
1417
+ ctypedef struct __Pyx_TypeInfo:
1418
+ char* name
1419
+ __Pyx_StructField* fields
1420
+ size_t size
1421
+ size_t arraysize[8]
1422
+ int ndim
1423
+ char typegroup
1424
+ char is_unsigned
1425
+ int flags
1426
+
1427
+ ctypedef struct __Pyx_StructField:
1428
+ __Pyx_TypeInfo* type
1429
+ char* name
1430
+ size_t offset
1431
+
1432
+ ctypedef struct __Pyx_BufFmt_StackElem:
1433
+ __Pyx_StructField* field
1434
+ size_t parent_offset
1435
+
1436
+ #ctypedef struct __Pyx_BufFmt_Context:
1437
+ # __Pyx_StructField root
1438
+ __Pyx_BufFmt_StackElem* head
1439
+
1440
+ struct __pyx_typeinfo_string:
1441
+ char string[3]
1442
+
1443
+ __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *)
1444
+
1445
+
1446
+ @cname('__pyx_format_from_typeinfo')
1447
+ cdef bytes format_from_typeinfo(__Pyx_TypeInfo *type):
1448
+ cdef __Pyx_StructField *field
1449
+ cdef __pyx_typeinfo_string fmt
1450
+ cdef bytes part, result
1451
+ cdef Py_ssize_t i
1452
+
1453
+ if type.typegroup == 'S':
1454
+ assert type.fields != NULL
1455
+ assert type.fields.type != NULL
1456
+
1457
+ if type.flags & __PYX_BUF_FLAGS_PACKED_STRUCT:
1458
+ alignment = b'^'
1459
+ else:
1460
+ alignment = b''
1461
+
1462
+ parts = [b"T{"]
1463
+ field = type.fields
1464
+
1465
+ while field.type:
1466
+ part = format_from_typeinfo(field.type)
1467
+ parts.append(part + b':' + field.name + b':')
1468
+ field += 1
1469
+
1470
+ result = alignment.join(parts) + b'}'
1471
+ else:
1472
+ fmt = __Pyx_TypeInfoToFormat(type)
1473
+ result = fmt.string
1474
+ if type.arraysize[0]:
1475
+ extents = [f"{type.arraysize[i]}" for i in range(type.ndim)]
1476
+ result = f"({u','.join(extents)})".encode('ascii') + result
1477
+
1478
+ return result