Cython 3.2.0__cp39-abi3-win32.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.
- Cython/Build/BuildExecutable.py +169 -0
- Cython/Build/Cache.py +199 -0
- Cython/Build/Cythonize.py +350 -0
- Cython/Build/Dependencies.py +1314 -0
- Cython/Build/Distutils.py +1 -0
- Cython/Build/Inline.py +463 -0
- Cython/Build/IpythonMagic.py +560 -0
- Cython/Build/SharedModule.py +94 -0
- Cython/Build/Tests/TestCyCache.py +194 -0
- Cython/Build/Tests/TestCythonizeArgsParser.py +481 -0
- Cython/Build/Tests/TestDependencies.py +133 -0
- Cython/Build/Tests/TestInline.py +177 -0
- Cython/Build/Tests/TestIpythonMagic.py +287 -0
- Cython/Build/Tests/TestRecythonize.py +212 -0
- Cython/Build/Tests/TestStripLiterals.py +155 -0
- Cython/Build/Tests/__init__.py +1 -0
- Cython/Build/__init__.py +11 -0
- Cython/CodeWriter.py +815 -0
- Cython/Compiler/AnalysedTreeTransforms.py +97 -0
- Cython/Compiler/Annotate.py +328 -0
- Cython/Compiler/AutoDocTransforms.py +320 -0
- Cython/Compiler/Buffer.py +680 -0
- Cython/Compiler/Builtin.py +984 -0
- Cython/Compiler/CmdLine.py +263 -0
- Cython/Compiler/Code.pxd +149 -0
- Cython/Compiler/Code.py +3746 -0
- Cython/Compiler/Code.pyd +0 -0
- Cython/Compiler/CodeGeneration.py +33 -0
- Cython/Compiler/CythonScope.py +191 -0
- Cython/Compiler/Dataclass.py +864 -0
- Cython/Compiler/DebugFlags.py +24 -0
- Cython/Compiler/Errors.py +297 -0
- Cython/Compiler/ExprNodes.py +15562 -0
- Cython/Compiler/FlowControl.pxd +97 -0
- Cython/Compiler/FlowControl.py +1451 -0
- Cython/Compiler/FlowControl.pyd +0 -0
- Cython/Compiler/FusedNode.py +971 -0
- Cython/Compiler/FusedNode.pyd +0 -0
- Cython/Compiler/Future.py +16 -0
- Cython/Compiler/Interpreter.py +57 -0
- Cython/Compiler/Lexicon.py +421 -0
- Cython/Compiler/LineTable.py +114 -0
- Cython/Compiler/LineTable.pyd +0 -0
- Cython/Compiler/Main.py +857 -0
- Cython/Compiler/MatchCaseNodes.py +259 -0
- Cython/Compiler/MemoryView.py +905 -0
- Cython/Compiler/ModuleNode.py +4235 -0
- Cython/Compiler/Naming.py +363 -0
- Cython/Compiler/Nodes.py +10831 -0
- Cython/Compiler/Optimize.py +5288 -0
- Cython/Compiler/Options.py +843 -0
- Cython/Compiler/ParseTreeTransforms.pxd +78 -0
- Cython/Compiler/ParseTreeTransforms.py +4638 -0
- Cython/Compiler/Parsing.pxd +9 -0
- Cython/Compiler/Parsing.py +4775 -0
- Cython/Compiler/Parsing.pyd +0 -0
- Cython/Compiler/Pipeline.py +439 -0
- Cython/Compiler/PyrexTypes.py +5870 -0
- Cython/Compiler/Pythran.py +232 -0
- Cython/Compiler/Scanning.pxd +48 -0
- Cython/Compiler/Scanning.py +701 -0
- Cython/Compiler/Scanning.pyd +0 -0
- Cython/Compiler/StringEncoding.py +298 -0
- Cython/Compiler/Symtab.py +3073 -0
- Cython/Compiler/Tests/TestBuffer.py +105 -0
- Cython/Compiler/Tests/TestBuiltin.py +72 -0
- Cython/Compiler/Tests/TestCmdLine.py +586 -0
- Cython/Compiler/Tests/TestCode.py +144 -0
- Cython/Compiler/Tests/TestFlowControl.py +65 -0
- Cython/Compiler/Tests/TestGrammar.py +202 -0
- Cython/Compiler/Tests/TestMemView.py +71 -0
- Cython/Compiler/Tests/TestParseTreeTransforms.py +285 -0
- Cython/Compiler/Tests/TestScanning.py +134 -0
- Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
- Cython/Compiler/Tests/TestStringEncoding.py +21 -0
- Cython/Compiler/Tests/TestTreeFragment.py +63 -0
- Cython/Compiler/Tests/TestTreePath.py +103 -0
- Cython/Compiler/Tests/TestTypes.py +75 -0
- Cython/Compiler/Tests/TestUtilityLoad.py +112 -0
- Cython/Compiler/Tests/TestVisitor.py +61 -0
- Cython/Compiler/Tests/Utils.py +36 -0
- Cython/Compiler/Tests/__init__.py +1 -0
- Cython/Compiler/TreeFragment.py +278 -0
- Cython/Compiler/TreePath.py +303 -0
- Cython/Compiler/TypeInference.py +591 -0
- Cython/Compiler/TypeSlots.py +1174 -0
- Cython/Compiler/UFuncs.py +311 -0
- Cython/Compiler/UtilNodes.py +389 -0
- Cython/Compiler/UtilityCode.py +344 -0
- Cython/Compiler/Version.py +8 -0
- Cython/Compiler/Visitor.pxd +53 -0
- Cython/Compiler/Visitor.py +861 -0
- Cython/Compiler/Visitor.pyd +0 -0
- Cython/Compiler/__init__.py +1 -0
- Cython/Coverage.py +448 -0
- Cython/Debugger/Cygdb.py +177 -0
- Cython/Debugger/DebugWriter.py +82 -0
- Cython/Debugger/Tests/TestLibCython.py +275 -0
- Cython/Debugger/Tests/__init__.py +1 -0
- Cython/Debugger/Tests/cfuncs.c +8 -0
- Cython/Debugger/Tests/codefile +49 -0
- Cython/Debugger/Tests/test_libcython_in_gdb.py +578 -0
- Cython/Debugger/Tests/test_libpython_in_gdb.py +90 -0
- Cython/Debugger/__init__.py +1 -0
- Cython/Debugger/libcython.py +1548 -0
- Cython/Debugger/libpython.py +2821 -0
- Cython/Debugging.py +20 -0
- Cython/Distutils/__init__.py +2 -0
- Cython/Distutils/build_ext.py +139 -0
- Cython/Distutils/extension.py +96 -0
- Cython/Distutils/old_build_ext.py +351 -0
- Cython/Includes/cpython/__init__.pxd +173 -0
- Cython/Includes/cpython/array.pxd +178 -0
- Cython/Includes/cpython/bool.pxd +37 -0
- Cython/Includes/cpython/buffer.pxd +112 -0
- Cython/Includes/cpython/bytearray.pxd +33 -0
- Cython/Includes/cpython/bytes.pxd +200 -0
- Cython/Includes/cpython/cellobject.pxd +35 -0
- Cython/Includes/cpython/ceval.pxd +8 -0
- Cython/Includes/cpython/codecs.pxd +121 -0
- Cython/Includes/cpython/complex.pxd +60 -0
- Cython/Includes/cpython/contextvars.pxd +145 -0
- Cython/Includes/cpython/conversion.pxd +36 -0
- Cython/Includes/cpython/datetime.pxd +395 -0
- Cython/Includes/cpython/descr.pxd +26 -0
- Cython/Includes/cpython/dict.pxd +187 -0
- Cython/Includes/cpython/exc.pxd +263 -0
- Cython/Includes/cpython/fileobject.pxd +57 -0
- Cython/Includes/cpython/float.pxd +47 -0
- Cython/Includes/cpython/function.pxd +65 -0
- Cython/Includes/cpython/genobject.pxd +25 -0
- Cython/Includes/cpython/getargs.pxd +12 -0
- Cython/Includes/cpython/instance.pxd +25 -0
- Cython/Includes/cpython/iterator.pxd +36 -0
- Cython/Includes/cpython/iterobject.pxd +24 -0
- Cython/Includes/cpython/list.pxd +92 -0
- Cython/Includes/cpython/long.pxd +149 -0
- Cython/Includes/cpython/longintrepr.pxd +14 -0
- Cython/Includes/cpython/mapping.pxd +63 -0
- Cython/Includes/cpython/marshal.pxd +66 -0
- Cython/Includes/cpython/mem.pxd +120 -0
- Cython/Includes/cpython/memoryview.pxd +50 -0
- Cython/Includes/cpython/method.pxd +49 -0
- Cython/Includes/cpython/module.pxd +208 -0
- Cython/Includes/cpython/number.pxd +258 -0
- Cython/Includes/cpython/object.pxd +433 -0
- Cython/Includes/cpython/pycapsule.pxd +143 -0
- Cython/Includes/cpython/pylifecycle.pxd +68 -0
- Cython/Includes/cpython/pyport.pxd +8 -0
- Cython/Includes/cpython/pystate.pxd +95 -0
- Cython/Includes/cpython/pythread.pxd +53 -0
- Cython/Includes/cpython/ref.pxd +141 -0
- Cython/Includes/cpython/sequence.pxd +134 -0
- Cython/Includes/cpython/set.pxd +119 -0
- Cython/Includes/cpython/slice.pxd +70 -0
- Cython/Includes/cpython/time.pxd +129 -0
- Cython/Includes/cpython/tuple.pxd +72 -0
- Cython/Includes/cpython/type.pxd +53 -0
- Cython/Includes/cpython/unicode.pxd +639 -0
- Cython/Includes/cpython/version.pxd +32 -0
- Cython/Includes/cpython/weakref.pxd +78 -0
- Cython/Includes/libc/__init__.pxd +1 -0
- Cython/Includes/libc/complex.pxd +35 -0
- Cython/Includes/libc/errno.pxd +127 -0
- Cython/Includes/libc/float.pxd +43 -0
- Cython/Includes/libc/limits.pxd +28 -0
- Cython/Includes/libc/locale.pxd +46 -0
- Cython/Includes/libc/math.pxd +209 -0
- Cython/Includes/libc/setjmp.pxd +10 -0
- Cython/Includes/libc/signal.pxd +64 -0
- Cython/Includes/libc/stddef.pxd +9 -0
- Cython/Includes/libc/stdint.pxd +105 -0
- Cython/Includes/libc/stdio.pxd +80 -0
- Cython/Includes/libc/stdlib.pxd +72 -0
- Cython/Includes/libc/string.pxd +50 -0
- Cython/Includes/libc/threads.pxd +234 -0
- Cython/Includes/libc/time.pxd +52 -0
- Cython/Includes/libcpp/__init__.pxd +4 -0
- Cython/Includes/libcpp/algorithm.pxd +320 -0
- Cython/Includes/libcpp/any.pxd +16 -0
- Cython/Includes/libcpp/atomic.pxd +59 -0
- Cython/Includes/libcpp/barrier.pxd +22 -0
- Cython/Includes/libcpp/bit.pxd +29 -0
- Cython/Includes/libcpp/cast.pxd +12 -0
- Cython/Includes/libcpp/cmath.pxd +518 -0
- Cython/Includes/libcpp/complex.pxd +106 -0
- Cython/Includes/libcpp/condition_variable.pxd +322 -0
- Cython/Includes/libcpp/deque.pxd +165 -0
- Cython/Includes/libcpp/exception.pxd +86 -0
- Cython/Includes/libcpp/execution.pxd +15 -0
- Cython/Includes/libcpp/forward_list.pxd +63 -0
- Cython/Includes/libcpp/functional.pxd +26 -0
- Cython/Includes/libcpp/future.pxd +103 -0
- Cython/Includes/libcpp/iterator.pxd +34 -0
- Cython/Includes/libcpp/latch.pxd +17 -0
- Cython/Includes/libcpp/limits.pxd +61 -0
- Cython/Includes/libcpp/list.pxd +117 -0
- Cython/Includes/libcpp/map.pxd +252 -0
- Cython/Includes/libcpp/memory.pxd +115 -0
- Cython/Includes/libcpp/mutex.pxd +387 -0
- Cython/Includes/libcpp/numbers.pxd +15 -0
- Cython/Includes/libcpp/numeric.pxd +131 -0
- Cython/Includes/libcpp/optional.pxd +34 -0
- Cython/Includes/libcpp/pair.pxd +1 -0
- Cython/Includes/libcpp/queue.pxd +25 -0
- Cython/Includes/libcpp/random.pxd +166 -0
- Cython/Includes/libcpp/semaphore.pxd +43 -0
- Cython/Includes/libcpp/set.pxd +228 -0
- Cython/Includes/libcpp/shared_mutex.pxd +96 -0
- Cython/Includes/libcpp/span.pxd +87 -0
- Cython/Includes/libcpp/stack.pxd +11 -0
- Cython/Includes/libcpp/stop_token.pxd +117 -0
- Cython/Includes/libcpp/string.pxd +355 -0
- Cython/Includes/libcpp/string_view.pxd +183 -0
- Cython/Includes/libcpp/typeindex.pxd +15 -0
- Cython/Includes/libcpp/typeinfo.pxd +10 -0
- Cython/Includes/libcpp/unordered_map.pxd +193 -0
- Cython/Includes/libcpp/unordered_set.pxd +152 -0
- Cython/Includes/libcpp/utility.pxd +30 -0
- Cython/Includes/libcpp/vector.pxd +186 -0
- Cython/Includes/numpy/math.pxd +150 -0
- Cython/Includes/openmp.pxd +50 -0
- Cython/Includes/posix/__init__.pxd +1 -0
- Cython/Includes/posix/dlfcn.pxd +14 -0
- Cython/Includes/posix/fcntl.pxd +86 -0
- Cython/Includes/posix/ioctl.pxd +4 -0
- Cython/Includes/posix/mman.pxd +101 -0
- Cython/Includes/posix/resource.pxd +57 -0
- Cython/Includes/posix/select.pxd +21 -0
- Cython/Includes/posix/signal.pxd +73 -0
- Cython/Includes/posix/stat.pxd +98 -0
- Cython/Includes/posix/stdio.pxd +37 -0
- Cython/Includes/posix/stdlib.pxd +29 -0
- Cython/Includes/posix/strings.pxd +9 -0
- Cython/Includes/posix/time.pxd +71 -0
- Cython/Includes/posix/types.pxd +30 -0
- Cython/Includes/posix/uio.pxd +26 -0
- Cython/Includes/posix/unistd.pxd +271 -0
- Cython/Includes/posix/wait.pxd +38 -0
- Cython/Plex/Actions.pxd +24 -0
- Cython/Plex/Actions.py +119 -0
- Cython/Plex/Actions.pyd +0 -0
- Cython/Plex/DFA.pxd +14 -0
- Cython/Plex/DFA.py +164 -0
- Cython/Plex/DFA.pyd +0 -0
- Cython/Plex/Errors.py +48 -0
- Cython/Plex/Lexicons.py +178 -0
- Cython/Plex/Machines.pxd +36 -0
- Cython/Plex/Machines.py +238 -0
- Cython/Plex/Machines.pyd +0 -0
- Cython/Plex/Regexps.py +535 -0
- Cython/Plex/Scanners.pxd +45 -0
- Cython/Plex/Scanners.py +328 -0
- Cython/Plex/Scanners.pyd +0 -0
- Cython/Plex/Transitions.pxd +14 -0
- Cython/Plex/Transitions.py +239 -0
- Cython/Plex/Transitions.pyd +0 -0
- Cython/Plex/__init__.py +34 -0
- Cython/Runtime/__init__.py +1 -0
- Cython/Runtime/refnanny.pyd +0 -0
- Cython/Runtime/refnanny.pyx +237 -0
- Cython/Shadow.py +690 -0
- Cython/Shadow.pyi +521 -0
- Cython/StringIOTree.py +170 -0
- Cython/StringIOTree.pyd +0 -0
- Cython/Tempita/__init__.py +4 -0
- Cython/Tempita/_looper.py +154 -0
- Cython/Tempita/_tempita.py +1091 -0
- Cython/Tempita/_tempita.pyd +0 -0
- Cython/TestUtils.py +422 -0
- Cython/Tests/TestCodeWriter.py +128 -0
- Cython/Tests/TestCythonUtils.py +202 -0
- Cython/Tests/TestJediTyper.py +223 -0
- Cython/Tests/TestShadow.py +114 -0
- Cython/Tests/TestStringIOTree.py +67 -0
- Cython/Tests/TestTestUtils.py +90 -0
- Cython/Tests/__init__.py +1 -0
- Cython/Tests/xmlrunner.py +390 -0
- Cython/Utility/AsyncGen.c +1031 -0
- Cython/Utility/Buffer.c +865 -0
- Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
- Cython/Utility/Builtins.c +810 -0
- Cython/Utility/CConvert.pyx +134 -0
- Cython/Utility/CMath.c +104 -0
- Cython/Utility/CommonStructures.c +226 -0
- Cython/Utility/Complex.c +378 -0
- Cython/Utility/Coroutine.c +2300 -0
- Cython/Utility/CpdefEnums.pyx +103 -0
- Cython/Utility/CppConvert.pyx +282 -0
- Cython/Utility/CppSupport.cpp +151 -0
- Cython/Utility/CythonFunction.c +1832 -0
- Cython/Utility/Dataclasses.c +101 -0
- Cython/Utility/Embed.c +121 -0
- Cython/Utility/Exceptions.c +1016 -0
- Cython/Utility/ExtensionTypes.c +996 -0
- Cython/Utility/FunctionArguments.c +1043 -0
- Cython/Utility/FusedFunction.pyx +44 -0
- Cython/Utility/ImportExport.c +907 -0
- Cython/Utility/MemoryView.pxd +188 -0
- Cython/Utility/MemoryView.pyx +1482 -0
- Cython/Utility/MemoryView_C.c +927 -0
- Cython/Utility/ModuleSetupCode.c +3203 -0
- Cython/Utility/NumpyImportArray.c +46 -0
- Cython/Utility/ObjectHandling.c +3273 -0
- Cython/Utility/Optimize.c +1603 -0
- Cython/Utility/Overflow.c +384 -0
- Cython/Utility/Printing.c +86 -0
- Cython/Utility/Profile.c +732 -0
- Cython/Utility/StringTools.c +1379 -0
- Cython/Utility/Synchronization.c +399 -0
- Cython/Utility/TString.c +356 -0
- Cython/Utility/TestCyUtilityLoader.pyx +8 -0
- Cython/Utility/TestCythonScope.pyx +75 -0
- Cython/Utility/TestUtilityLoader.c +12 -0
- Cython/Utility/TypeConversion.c +1385 -0
- Cython/Utility/UFuncs.pyx +50 -0
- Cython/Utility/UFuncs_C.c +89 -0
- Cython/Utility/__init__.py +28 -0
- Cython/Utility/arrayarray.h +167 -0
- Cython/Utils.py +687 -0
- Cython/Utils.pyd +0 -0
- Cython/__init__.py +10 -0
- Cython/__init__.pyi +7 -0
- Cython/py.typed +0 -0
- cython-3.2.0.dist-info/METADATA +85 -0
- cython-3.2.0.dist-info/RECORD +333 -0
- cython-3.2.0.dist-info/WHEEL +5 -0
- cython-3.2.0.dist-info/entry_points.txt +4 -0
- cython-3.2.0.dist-info/top_level.txt +3 -0
- cython.py +29 -0
- pyximport/__init__.py +4 -0
- pyximport/pyxbuild.py +160 -0
- pyximport/pyximport.py +482 -0
|
@@ -0,0 +1,905 @@
|
|
|
1
|
+
from .Errors import CompileError, error
|
|
2
|
+
from . import ExprNodes
|
|
3
|
+
from .ExprNodes import IntNode, NameNode, AttributeNode
|
|
4
|
+
from . import Options
|
|
5
|
+
from .. import Utils
|
|
6
|
+
from .Code import UtilityCode, TempitaUtilityCode
|
|
7
|
+
from .UtilityCode import CythonUtilityCode, CythonSharedUtilityCode
|
|
8
|
+
from . import Buffer
|
|
9
|
+
from . import Naming
|
|
10
|
+
from . import PyrexTypes
|
|
11
|
+
|
|
12
|
+
START_ERR = "Start must not be given."
|
|
13
|
+
STOP_ERR = "Axis specification only allowed in the 'step' slot."
|
|
14
|
+
STEP_ERR = "Step must be omitted, 1, or a valid specifier."
|
|
15
|
+
BOTH_CF_ERR = "Cannot specify an array that is both C and Fortran contiguous."
|
|
16
|
+
INVALID_ERR = "Invalid axis specification."
|
|
17
|
+
NOT_CIMPORTED_ERR = "Variable was not cimported from cython.view"
|
|
18
|
+
EXPR_ERR = "no expressions allowed in axis spec, only names and literals."
|
|
19
|
+
CF_ERR = "Invalid axis specification for a C/Fortran contiguous array."
|
|
20
|
+
ERR_UNINITIALIZED = ("Cannot check if memoryview %s is initialized without the "
|
|
21
|
+
"GIL, consider using initializedcheck(False)")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
format_flag = "PyBUF_FORMAT"
|
|
25
|
+
|
|
26
|
+
memview_c_contiguous = "(PyBUF_C_CONTIGUOUS | PyBUF_FORMAT)"
|
|
27
|
+
memview_f_contiguous = "(PyBUF_F_CONTIGUOUS | PyBUF_FORMAT)"
|
|
28
|
+
memview_any_contiguous = "(PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT)"
|
|
29
|
+
memview_full_access = "PyBUF_FULL_RO"
|
|
30
|
+
memview_strided_access = "PyBUF_RECORDS_RO"
|
|
31
|
+
|
|
32
|
+
MEMVIEW_DIRECT = '__Pyx_MEMVIEW_DIRECT'
|
|
33
|
+
MEMVIEW_PTR = '__Pyx_MEMVIEW_PTR'
|
|
34
|
+
MEMVIEW_FULL = '__Pyx_MEMVIEW_FULL'
|
|
35
|
+
MEMVIEW_CONTIG = '__Pyx_MEMVIEW_CONTIG'
|
|
36
|
+
MEMVIEW_STRIDED= '__Pyx_MEMVIEW_STRIDED'
|
|
37
|
+
MEMVIEW_FOLLOW = '__Pyx_MEMVIEW_FOLLOW'
|
|
38
|
+
|
|
39
|
+
_spec_to_const = {
|
|
40
|
+
'direct' : MEMVIEW_DIRECT,
|
|
41
|
+
'ptr' : MEMVIEW_PTR,
|
|
42
|
+
'full' : MEMVIEW_FULL,
|
|
43
|
+
'contig' : MEMVIEW_CONTIG,
|
|
44
|
+
'strided': MEMVIEW_STRIDED,
|
|
45
|
+
'follow' : MEMVIEW_FOLLOW,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
_spec_to_abbrev = {
|
|
49
|
+
'direct' : 'd',
|
|
50
|
+
'ptr' : 'p',
|
|
51
|
+
'full' : 'f',
|
|
52
|
+
'contig' : 'c',
|
|
53
|
+
'strided' : 's',
|
|
54
|
+
'follow' : '_',
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def put_init_entry(mv_cname, code):
|
|
59
|
+
code.putln("%s.data = NULL;" % mv_cname)
|
|
60
|
+
code.putln("%s.memview = NULL;" % mv_cname)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
#def axes_to_str(axes):
|
|
64
|
+
# return "".join([access[0].upper()+packing[0] for (access, packing) in axes])
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def put_acquire_memoryviewslice(lhs_cname, lhs_type, lhs_pos, rhs, code,
|
|
68
|
+
have_gil=False, first_assignment=True):
|
|
69
|
+
"We can avoid decreffing the lhs if we know it is the first assignment"
|
|
70
|
+
assert rhs.type.is_memoryviewslice
|
|
71
|
+
|
|
72
|
+
pretty_rhs = rhs.result_in_temp() or rhs.is_simple()
|
|
73
|
+
if pretty_rhs:
|
|
74
|
+
rhstmp = rhs.result()
|
|
75
|
+
else:
|
|
76
|
+
rhstmp = code.funcstate.allocate_temp(lhs_type, manage_ref=False)
|
|
77
|
+
code.putln("%s = %s;" % (rhstmp, rhs.result_as(lhs_type)))
|
|
78
|
+
|
|
79
|
+
# Allow uninitialized assignment
|
|
80
|
+
#code.putln(code.put_error_if_unbound(lhs_pos, rhs.entry))
|
|
81
|
+
put_assign_to_memviewslice(lhs_cname, rhs, rhstmp, lhs_type, code,
|
|
82
|
+
have_gil=have_gil, first_assignment=first_assignment)
|
|
83
|
+
|
|
84
|
+
if not pretty_rhs:
|
|
85
|
+
code.funcstate.release_temp(rhstmp)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def put_assign_to_memviewslice(lhs_cname, rhs, rhs_cname, memviewslicetype, code,
|
|
89
|
+
have_gil=False, first_assignment=False):
|
|
90
|
+
if lhs_cname == rhs_cname:
|
|
91
|
+
# self assignment is tricky because memoryview xdecref clears the memoryview
|
|
92
|
+
# thus invalidating both sides of the assignment. Therefore make it actually do nothing
|
|
93
|
+
code.putln("/* memoryview self assignment no-op */")
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
if not first_assignment:
|
|
97
|
+
code.put_xdecref(lhs_cname, memviewslicetype,
|
|
98
|
+
have_gil=have_gil)
|
|
99
|
+
|
|
100
|
+
if not rhs.result_in_temp():
|
|
101
|
+
rhs.make_owned_memoryviewslice(code)
|
|
102
|
+
|
|
103
|
+
code.putln("%s = %s;" % (lhs_cname, rhs_cname))
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def get_buf_flags(specs):
|
|
107
|
+
is_c_contig, is_f_contig = is_cf_contig(specs)
|
|
108
|
+
|
|
109
|
+
if is_c_contig:
|
|
110
|
+
return memview_c_contiguous
|
|
111
|
+
elif is_f_contig:
|
|
112
|
+
return memview_f_contiguous
|
|
113
|
+
|
|
114
|
+
access, packing = zip(*specs)
|
|
115
|
+
|
|
116
|
+
if 'full' in access or 'ptr' in access:
|
|
117
|
+
return memview_full_access
|
|
118
|
+
else:
|
|
119
|
+
return memview_strided_access
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def insert_newaxes(memoryviewtype, n):
|
|
123
|
+
axes = [('direct', 'strided')] * n
|
|
124
|
+
axes.extend(memoryviewtype.axes)
|
|
125
|
+
return PyrexTypes.MemoryViewSliceType(memoryviewtype.dtype, axes)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def broadcast_types(src, dst):
|
|
129
|
+
n = abs(src.ndim - dst.ndim)
|
|
130
|
+
if src.ndim < dst.ndim:
|
|
131
|
+
return insert_newaxes(src, n), dst
|
|
132
|
+
else:
|
|
133
|
+
return src, insert_newaxes(dst, n)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def valid_memslice_dtype(dtype, i=0):
|
|
137
|
+
"""
|
|
138
|
+
Return whether type dtype can be used as the base type of a
|
|
139
|
+
memoryview slice.
|
|
140
|
+
|
|
141
|
+
We support structs, numeric types and objects
|
|
142
|
+
"""
|
|
143
|
+
if dtype.is_complex and dtype.real_type.is_int:
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
if dtype is PyrexTypes.c_bint_type:
|
|
147
|
+
return False
|
|
148
|
+
|
|
149
|
+
if dtype.is_struct and dtype.kind == 'struct':
|
|
150
|
+
for member in dtype.scope.var_entries:
|
|
151
|
+
if not valid_memslice_dtype(member.type):
|
|
152
|
+
return False
|
|
153
|
+
|
|
154
|
+
return True
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
dtype.is_error or
|
|
158
|
+
# Pointers are not valid (yet)
|
|
159
|
+
# (dtype.is_ptr and valid_memslice_dtype(dtype.base_type)) or
|
|
160
|
+
(dtype.is_array and i < 8 and
|
|
161
|
+
valid_memslice_dtype(dtype.base_type, i + 1)) or
|
|
162
|
+
dtype.is_numeric or
|
|
163
|
+
dtype.is_pyobject or
|
|
164
|
+
dtype.is_fused or # accept this as it will be replaced by specializations later
|
|
165
|
+
(dtype.is_typedef and valid_memslice_dtype(dtype.typedef_base_type))
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
|
|
170
|
+
"""
|
|
171
|
+
May be used during code generation time to be queried for
|
|
172
|
+
shape/strides/suboffsets attributes, or to perform indexing or slicing.
|
|
173
|
+
"""
|
|
174
|
+
def __init__(self, entry):
|
|
175
|
+
self.entry = entry
|
|
176
|
+
self.type = entry.type
|
|
177
|
+
self.cname = entry.cname
|
|
178
|
+
|
|
179
|
+
self.buf_ptr = "%s.data" % self.cname
|
|
180
|
+
|
|
181
|
+
dtype = self.entry.type.dtype
|
|
182
|
+
self.buf_ptr_type = PyrexTypes.CPtrType(dtype)
|
|
183
|
+
self.init_attributes()
|
|
184
|
+
|
|
185
|
+
def get_buf_suboffsetvars(self):
|
|
186
|
+
return self._for_all_ndim("%s.suboffsets[%d]")
|
|
187
|
+
|
|
188
|
+
def get_buf_stridevars(self):
|
|
189
|
+
return self._for_all_ndim("%s.strides[%d]")
|
|
190
|
+
|
|
191
|
+
def get_buf_shapevars(self):
|
|
192
|
+
return self._for_all_ndim("%s.shape[%d]")
|
|
193
|
+
|
|
194
|
+
def generate_buffer_lookup_code(self, code, index_cnames):
|
|
195
|
+
axes = [(dim, index_cnames[dim], access, packing)
|
|
196
|
+
for dim, (access, packing) in enumerate(self.type.axes)]
|
|
197
|
+
return self._generate_buffer_lookup_code(code, axes)
|
|
198
|
+
|
|
199
|
+
def _generate_buffer_lookup_code(self, code, axes, cast_result=True):
|
|
200
|
+
"""
|
|
201
|
+
Generate a single expression that indexes the memory view slice
|
|
202
|
+
in each dimension.
|
|
203
|
+
"""
|
|
204
|
+
bufp = self.buf_ptr
|
|
205
|
+
type_decl = self.type.dtype.empty_declaration_code()
|
|
206
|
+
|
|
207
|
+
for dim, index, access, packing in axes:
|
|
208
|
+
shape = "%s.shape[%d]" % (self.cname, dim)
|
|
209
|
+
stride = "%s.strides[%d]" % (self.cname, dim)
|
|
210
|
+
suboffset = "%s.suboffsets[%d]" % (self.cname, dim)
|
|
211
|
+
|
|
212
|
+
flag = get_memoryview_flag(access, packing)
|
|
213
|
+
|
|
214
|
+
if flag in ("generic", "generic_contiguous"):
|
|
215
|
+
# Note: we cannot do cast tricks to avoid stride multiplication
|
|
216
|
+
# for generic_contiguous, as we may have to do (dtype *)
|
|
217
|
+
# or (dtype **) arithmetic, we won't know which unless
|
|
218
|
+
# we check suboffsets
|
|
219
|
+
code.globalstate.use_utility_code(memviewslice_index_helpers)
|
|
220
|
+
bufp = ('__pyx_memviewslice_index_full(%s, %s, %s, %s)' %
|
|
221
|
+
(bufp, index, stride, suboffset))
|
|
222
|
+
|
|
223
|
+
elif flag == "indirect":
|
|
224
|
+
bufp = "(%s + %s * %s)" % (bufp, index, stride)
|
|
225
|
+
bufp = ("(*((char **) %s) + %s)" % (bufp, suboffset))
|
|
226
|
+
|
|
227
|
+
elif flag == "indirect_contiguous":
|
|
228
|
+
# Note: we do char ** arithmetic
|
|
229
|
+
bufp = "(*((char **) %s + %s) + %s)" % (bufp, index, suboffset)
|
|
230
|
+
|
|
231
|
+
elif flag == "strided":
|
|
232
|
+
bufp = "(%s + %s * %s)" % (bufp, index, stride)
|
|
233
|
+
|
|
234
|
+
else:
|
|
235
|
+
assert flag == 'contiguous', flag
|
|
236
|
+
bufp = '((char *) (((%s *) %s) + %s))' % (type_decl, bufp, index)
|
|
237
|
+
|
|
238
|
+
bufp = '( /* dim=%d */ %s )' % (dim, bufp)
|
|
239
|
+
|
|
240
|
+
if cast_result:
|
|
241
|
+
return "((%s *) %s)" % (type_decl, bufp)
|
|
242
|
+
|
|
243
|
+
return bufp
|
|
244
|
+
|
|
245
|
+
def generate_buffer_slice_code(self, code, indices, dst, dst_type, have_gil,
|
|
246
|
+
have_slices, directives):
|
|
247
|
+
"""
|
|
248
|
+
Slice a memoryviewslice.
|
|
249
|
+
|
|
250
|
+
indices - list of index nodes. If not a SliceNode, or NoneNode,
|
|
251
|
+
then it must be coercible to Py_ssize_t
|
|
252
|
+
|
|
253
|
+
Simply call __pyx_memoryview_slice_memviewslice with the right
|
|
254
|
+
arguments, unless the dimension is omitted or a bare ':', in which
|
|
255
|
+
case we copy over the shape/strides/suboffsets attributes directly
|
|
256
|
+
for that dimension.
|
|
257
|
+
"""
|
|
258
|
+
src = self.cname
|
|
259
|
+
|
|
260
|
+
code.putln("%(dst)s.data = %(src)s.data;" % locals())
|
|
261
|
+
code.putln("%(dst)s.memview = %(src)s.memview;" % locals())
|
|
262
|
+
code.put_incref_memoryviewslice(dst, dst_type, have_gil=have_gil)
|
|
263
|
+
|
|
264
|
+
all_dimensions_direct = all(access == 'direct' for access, packing in self.type.axes)
|
|
265
|
+
suboffset_dim_temp = []
|
|
266
|
+
|
|
267
|
+
def get_suboffset_dim():
|
|
268
|
+
# create global temp variable at request
|
|
269
|
+
if not suboffset_dim_temp:
|
|
270
|
+
suboffset_dim = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
|
|
271
|
+
code.putln("%s = -1;" % suboffset_dim)
|
|
272
|
+
suboffset_dim_temp.append(suboffset_dim)
|
|
273
|
+
return suboffset_dim_temp[0]
|
|
274
|
+
|
|
275
|
+
dim = -1
|
|
276
|
+
new_ndim = 0
|
|
277
|
+
for index in indices:
|
|
278
|
+
if index.is_none:
|
|
279
|
+
# newaxis
|
|
280
|
+
for attrib, value in [('shape', 1), ('strides', 0), ('suboffsets', -1)]:
|
|
281
|
+
code.putln("%s.%s[%d] = %d;" % (dst, attrib, new_ndim, value))
|
|
282
|
+
|
|
283
|
+
new_ndim += 1
|
|
284
|
+
continue
|
|
285
|
+
|
|
286
|
+
dim += 1
|
|
287
|
+
access, packing = self.type.axes[dim]
|
|
288
|
+
|
|
289
|
+
if index.is_slice:
|
|
290
|
+
# slice, unspecified dimension, or part of ellipsis
|
|
291
|
+
d = dict(locals())
|
|
292
|
+
for s in "start stop step".split():
|
|
293
|
+
idx = getattr(index, s)
|
|
294
|
+
have_idx = d['have_' + s] = not idx.is_none
|
|
295
|
+
d[s] = idx.result() if have_idx else "0"
|
|
296
|
+
|
|
297
|
+
if not (d['have_start'] or d['have_stop'] or d['have_step']):
|
|
298
|
+
# full slice (:), simply copy over the extent, stride
|
|
299
|
+
# and suboffset. Also update suboffset_dim if needed
|
|
300
|
+
d['access'] = access
|
|
301
|
+
util_name = "SimpleSlice"
|
|
302
|
+
else:
|
|
303
|
+
util_name = "ToughSlice"
|
|
304
|
+
d['error_goto'] = code.error_goto(index.pos)
|
|
305
|
+
|
|
306
|
+
new_ndim += 1
|
|
307
|
+
else:
|
|
308
|
+
# normal index
|
|
309
|
+
idx = index.result()
|
|
310
|
+
|
|
311
|
+
indirect = access != 'direct'
|
|
312
|
+
if indirect:
|
|
313
|
+
generic = access == 'full'
|
|
314
|
+
if new_ndim != 0:
|
|
315
|
+
return error(index.pos,
|
|
316
|
+
"All preceding dimensions must be "
|
|
317
|
+
"indexed and not sliced")
|
|
318
|
+
|
|
319
|
+
d = dict(
|
|
320
|
+
locals(),
|
|
321
|
+
wraparound=int(directives['wraparound']),
|
|
322
|
+
boundscheck=int(directives['boundscheck']),
|
|
323
|
+
)
|
|
324
|
+
if d['boundscheck']:
|
|
325
|
+
d['error_goto'] = code.error_goto(index.pos)
|
|
326
|
+
util_name = "SliceIndex"
|
|
327
|
+
|
|
328
|
+
_, impl = TempitaUtilityCode.load_as_string(util_name, "MemoryView_C.c", context=d)
|
|
329
|
+
code.put(impl)
|
|
330
|
+
|
|
331
|
+
if suboffset_dim_temp:
|
|
332
|
+
code.funcstate.release_temp(suboffset_dim_temp[0])
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def empty_slice(pos):
|
|
336
|
+
none = ExprNodes.NoneNode(pos)
|
|
337
|
+
return ExprNodes.SliceNode(pos, start=none,
|
|
338
|
+
stop=none, step=none)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def unellipsify(indices, ndim):
|
|
342
|
+
result = []
|
|
343
|
+
seen_ellipsis = False
|
|
344
|
+
have_slices = False
|
|
345
|
+
|
|
346
|
+
newaxes = [newaxis for newaxis in indices if newaxis.is_none]
|
|
347
|
+
n_indices = len(indices) - len(newaxes)
|
|
348
|
+
|
|
349
|
+
for index in indices:
|
|
350
|
+
if isinstance(index, ExprNodes.EllipsisNode):
|
|
351
|
+
have_slices = True
|
|
352
|
+
full_slice = empty_slice(index.pos)
|
|
353
|
+
|
|
354
|
+
if seen_ellipsis:
|
|
355
|
+
result.append(full_slice)
|
|
356
|
+
else:
|
|
357
|
+
nslices = ndim - n_indices + 1
|
|
358
|
+
result.extend([full_slice] * nslices)
|
|
359
|
+
seen_ellipsis = True
|
|
360
|
+
else:
|
|
361
|
+
have_slices = have_slices or index.is_slice or index.is_none
|
|
362
|
+
result.append(index)
|
|
363
|
+
|
|
364
|
+
result_length = len(result) - len(newaxes)
|
|
365
|
+
if result_length < ndim:
|
|
366
|
+
have_slices = True
|
|
367
|
+
nslices = ndim - result_length
|
|
368
|
+
result.extend([empty_slice(indices[-1].pos)] * nslices)
|
|
369
|
+
|
|
370
|
+
return have_slices, result, newaxes
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def get_memoryview_flag(access, packing):
|
|
374
|
+
if access == 'full' and packing in ('strided', 'follow'):
|
|
375
|
+
return 'generic'
|
|
376
|
+
elif access == 'full' and packing == 'contig':
|
|
377
|
+
return 'generic_contiguous'
|
|
378
|
+
elif access == 'ptr' and packing in ('strided', 'follow'):
|
|
379
|
+
return 'indirect'
|
|
380
|
+
elif access == 'ptr' and packing == 'contig':
|
|
381
|
+
return 'indirect_contiguous'
|
|
382
|
+
elif access == 'direct' and packing in ('strided', 'follow'):
|
|
383
|
+
return 'strided'
|
|
384
|
+
else:
|
|
385
|
+
assert (access, packing) == ('direct', 'contig'), (access, packing)
|
|
386
|
+
return 'contiguous'
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def get_is_contig_func_name(contig_type, ndim):
|
|
390
|
+
assert contig_type in ('C', 'F')
|
|
391
|
+
return "__pyx_memviewslice_is_contig_%s%d" % (contig_type, ndim)
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def get_is_contig_utility(contig_type, ndim):
|
|
395
|
+
assert contig_type in ('C', 'F')
|
|
396
|
+
C = dict(template_context, ndim=ndim, contig_type=contig_type)
|
|
397
|
+
utility = load_memview_c_utility("MemviewSliceCheckContig", context=C,
|
|
398
|
+
requires=[is_contig_utility])
|
|
399
|
+
return utility
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def slice_iter(slice_type, slice_result, ndim, code, force_strided=False):
|
|
403
|
+
if (slice_type.is_c_contig or slice_type.is_f_contig) and not force_strided:
|
|
404
|
+
return ContigSliceIter(slice_type, slice_result, ndim, code)
|
|
405
|
+
else:
|
|
406
|
+
return StridedSliceIter(slice_type, slice_result, ndim, code)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
class SliceIter:
|
|
410
|
+
def __init__(self, slice_type, slice_result, ndim, code):
|
|
411
|
+
self.slice_type = slice_type
|
|
412
|
+
self.slice_result = slice_result
|
|
413
|
+
self.code = code
|
|
414
|
+
self.ndim = ndim
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
class ContigSliceIter(SliceIter):
|
|
418
|
+
def start_loops(self):
|
|
419
|
+
code = self.code
|
|
420
|
+
code.begin_block()
|
|
421
|
+
|
|
422
|
+
type_decl = self.slice_type.dtype.empty_declaration_code()
|
|
423
|
+
|
|
424
|
+
total_size = ' * '.join("%s.shape[%d]" % (self.slice_result, i)
|
|
425
|
+
for i in range(self.ndim))
|
|
426
|
+
code.putln("Py_ssize_t __pyx_temp_extent = %s;" % total_size)
|
|
427
|
+
code.putln("Py_ssize_t __pyx_temp_idx;")
|
|
428
|
+
code.putln("%s *__pyx_temp_pointer = (%s *) %s.data;" % (
|
|
429
|
+
type_decl, type_decl, self.slice_result))
|
|
430
|
+
code.putln("for (__pyx_temp_idx = 0; "
|
|
431
|
+
"__pyx_temp_idx < __pyx_temp_extent; "
|
|
432
|
+
"__pyx_temp_idx++) {")
|
|
433
|
+
|
|
434
|
+
return "__pyx_temp_pointer"
|
|
435
|
+
|
|
436
|
+
def end_loops(self):
|
|
437
|
+
self.code.putln("__pyx_temp_pointer += 1;")
|
|
438
|
+
self.code.putln("}")
|
|
439
|
+
self.code.end_block()
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
class StridedSliceIter(SliceIter):
|
|
443
|
+
def start_loops(self):
|
|
444
|
+
code = self.code
|
|
445
|
+
code.begin_block()
|
|
446
|
+
|
|
447
|
+
for i in range(self.ndim):
|
|
448
|
+
t = i, self.slice_result, i
|
|
449
|
+
code.putln("Py_ssize_t __pyx_temp_extent_%d = %s.shape[%d];" % t)
|
|
450
|
+
code.putln("Py_ssize_t __pyx_temp_stride_%d = %s.strides[%d];" % t)
|
|
451
|
+
code.putln("char *__pyx_temp_pointer_%d;" % i)
|
|
452
|
+
code.putln("Py_ssize_t __pyx_temp_idx_%d;" % i)
|
|
453
|
+
|
|
454
|
+
code.putln("__pyx_temp_pointer_0 = %s.data;" % self.slice_result)
|
|
455
|
+
|
|
456
|
+
for i in range(self.ndim):
|
|
457
|
+
if i > 0:
|
|
458
|
+
code.putln("__pyx_temp_pointer_%d = __pyx_temp_pointer_%d;" % (i, i - 1))
|
|
459
|
+
|
|
460
|
+
code.putln("for (__pyx_temp_idx_%d = 0; "
|
|
461
|
+
"__pyx_temp_idx_%d < __pyx_temp_extent_%d; "
|
|
462
|
+
"__pyx_temp_idx_%d++) {" % (i, i, i, i))
|
|
463
|
+
|
|
464
|
+
return "__pyx_temp_pointer_%d" % (self.ndim - 1)
|
|
465
|
+
|
|
466
|
+
def end_loops(self):
|
|
467
|
+
code = self.code
|
|
468
|
+
for i in range(self.ndim - 1, -1, -1):
|
|
469
|
+
code.putln("__pyx_temp_pointer_%d += __pyx_temp_stride_%d;" % (i, i))
|
|
470
|
+
code.putln("}")
|
|
471
|
+
|
|
472
|
+
code.end_block()
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def copy_c_or_fortran_cname(memview):
|
|
476
|
+
if memview.is_c_contig:
|
|
477
|
+
c_or_f = 'c'
|
|
478
|
+
else:
|
|
479
|
+
c_or_f = 'f'
|
|
480
|
+
|
|
481
|
+
return "__pyx_memoryview_copy_slice_%s_%s" % (
|
|
482
|
+
memview.specialization_suffix(), c_or_f)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def get_copy_new_utility(pos, from_memview, to_memview):
|
|
486
|
+
if (from_memview.dtype != to_memview.dtype and
|
|
487
|
+
not (from_memview.dtype.is_cv_qualified and from_memview.dtype.cv_base_type == to_memview.dtype)):
|
|
488
|
+
error(pos, "dtypes must be the same!")
|
|
489
|
+
return
|
|
490
|
+
if len(from_memview.axes) != len(to_memview.axes):
|
|
491
|
+
error(pos, "number of dimensions must be same")
|
|
492
|
+
return
|
|
493
|
+
if not (to_memview.is_c_contig or to_memview.is_f_contig):
|
|
494
|
+
error(pos, "to_memview must be c or f contiguous.")
|
|
495
|
+
return
|
|
496
|
+
|
|
497
|
+
for (access, packing) in from_memview.axes:
|
|
498
|
+
if access != 'direct':
|
|
499
|
+
error(pos, "cannot handle 'full' or 'ptr' access at this time.")
|
|
500
|
+
return
|
|
501
|
+
|
|
502
|
+
if to_memview.is_c_contig:
|
|
503
|
+
mode = 'c'
|
|
504
|
+
contig_flag = memview_c_contiguous
|
|
505
|
+
else:
|
|
506
|
+
assert to_memview.is_f_contig
|
|
507
|
+
mode = 'fortran'
|
|
508
|
+
contig_flag = memview_f_contiguous
|
|
509
|
+
|
|
510
|
+
return load_memview_c_utility(
|
|
511
|
+
"CopyContentsUtility",
|
|
512
|
+
context=dict(
|
|
513
|
+
template_context,
|
|
514
|
+
mode=mode,
|
|
515
|
+
dtype_decl=to_memview.dtype.empty_declaration_code(),
|
|
516
|
+
contig_flag=contig_flag,
|
|
517
|
+
ndim=to_memview.ndim,
|
|
518
|
+
func_cname=copy_c_or_fortran_cname(to_memview),
|
|
519
|
+
dtype_is_object=int(to_memview.dtype.is_pyobject),
|
|
520
|
+
),
|
|
521
|
+
requires=[copy_contents_new_utility],
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def get_axes_specs(env, axes):
|
|
526
|
+
'''
|
|
527
|
+
get_axes_specs(env, axes) -> list of (access, packing) specs for each axis.
|
|
528
|
+
access is one of 'full', 'ptr' or 'direct'
|
|
529
|
+
packing is one of 'contig', 'strided' or 'follow'
|
|
530
|
+
'''
|
|
531
|
+
|
|
532
|
+
cythonscope = env.context.cython_scope
|
|
533
|
+
cythonscope.load_cythonscope()
|
|
534
|
+
viewscope = cythonscope.viewscope
|
|
535
|
+
|
|
536
|
+
access_specs = tuple([viewscope.lookup(name)
|
|
537
|
+
for name in ('full', 'direct', 'ptr')])
|
|
538
|
+
packing_specs = tuple([viewscope.lookup(name)
|
|
539
|
+
for name in ('contig', 'strided', 'follow')])
|
|
540
|
+
|
|
541
|
+
is_f_contig, is_c_contig = False, False
|
|
542
|
+
default_access, default_packing = 'direct', 'strided'
|
|
543
|
+
cf_access, cf_packing = default_access, 'follow'
|
|
544
|
+
|
|
545
|
+
axes_specs = []
|
|
546
|
+
# analyse all axes.
|
|
547
|
+
for idx, axis in enumerate(axes):
|
|
548
|
+
if not axis.start.is_none:
|
|
549
|
+
raise CompileError(axis.start.pos, START_ERR)
|
|
550
|
+
|
|
551
|
+
if not axis.stop.is_none:
|
|
552
|
+
raise CompileError(axis.stop.pos, STOP_ERR)
|
|
553
|
+
|
|
554
|
+
if axis.step.is_none:
|
|
555
|
+
axes_specs.append((default_access, default_packing))
|
|
556
|
+
|
|
557
|
+
elif isinstance(axis.step, IntNode):
|
|
558
|
+
# the packing for the ::1 axis is contiguous,
|
|
559
|
+
# all others are cf_packing.
|
|
560
|
+
if axis.step.compile_time_value(env) != 1:
|
|
561
|
+
raise CompileError(axis.step.pos, STEP_ERR)
|
|
562
|
+
|
|
563
|
+
axes_specs.append((cf_access, 'cfcontig'))
|
|
564
|
+
|
|
565
|
+
elif isinstance(axis.step, (NameNode, AttributeNode)):
|
|
566
|
+
entry = _get_resolved_spec(env, axis.step)
|
|
567
|
+
if entry.name in view_constant_to_access_packing:
|
|
568
|
+
axes_specs.append(view_constant_to_access_packing[entry.name])
|
|
569
|
+
else:
|
|
570
|
+
raise CompileError(axis.step.pos, INVALID_ERR)
|
|
571
|
+
|
|
572
|
+
else:
|
|
573
|
+
raise CompileError(axis.step.pos, INVALID_ERR)
|
|
574
|
+
|
|
575
|
+
# First, find out if we have a ::1 somewhere
|
|
576
|
+
contig_dim = 0
|
|
577
|
+
is_contig = False
|
|
578
|
+
for idx, (access, packing) in enumerate(axes_specs):
|
|
579
|
+
if packing == 'cfcontig':
|
|
580
|
+
if is_contig:
|
|
581
|
+
raise CompileError(axis.step.pos, BOTH_CF_ERR)
|
|
582
|
+
|
|
583
|
+
contig_dim = idx
|
|
584
|
+
axes_specs[idx] = (access, 'contig')
|
|
585
|
+
is_contig = True
|
|
586
|
+
|
|
587
|
+
if is_contig:
|
|
588
|
+
# We have a ::1 somewhere, see if we're C or Fortran contiguous
|
|
589
|
+
if contig_dim == len(axes) - 1:
|
|
590
|
+
is_c_contig = True
|
|
591
|
+
else:
|
|
592
|
+
is_f_contig = True
|
|
593
|
+
|
|
594
|
+
if contig_dim and not axes_specs[contig_dim - 1][0] in ('full', 'ptr'):
|
|
595
|
+
raise CompileError(axes[contig_dim].pos,
|
|
596
|
+
"Fortran contiguous specifier must follow an indirect dimension")
|
|
597
|
+
|
|
598
|
+
if is_c_contig:
|
|
599
|
+
# Contiguous in the last dimension, find the last indirect dimension
|
|
600
|
+
contig_dim = -1
|
|
601
|
+
for idx, (access, packing) in enumerate(reversed(axes_specs)):
|
|
602
|
+
if access in ('ptr', 'full'):
|
|
603
|
+
contig_dim = len(axes) - idx - 1
|
|
604
|
+
|
|
605
|
+
# Replace 'strided' with 'follow' for any dimension following the last
|
|
606
|
+
# indirect dimension, the first dimension or the dimension following
|
|
607
|
+
# the ::1.
|
|
608
|
+
# int[::indirect, ::1, :, :]
|
|
609
|
+
# ^ ^
|
|
610
|
+
# int[::indirect, :, :, ::1]
|
|
611
|
+
# ^ ^
|
|
612
|
+
start = contig_dim + 1
|
|
613
|
+
stop = len(axes) - is_c_contig
|
|
614
|
+
for idx, (access, packing) in enumerate(axes_specs[start:stop]):
|
|
615
|
+
idx = contig_dim + 1 + idx
|
|
616
|
+
if access != 'direct':
|
|
617
|
+
raise CompileError(axes[idx].pos,
|
|
618
|
+
"Indirect dimension may not follow "
|
|
619
|
+
"Fortran contiguous dimension")
|
|
620
|
+
if packing == 'contig':
|
|
621
|
+
raise CompileError(axes[idx].pos,
|
|
622
|
+
"Dimension may not be contiguous")
|
|
623
|
+
axes_specs[idx] = (access, cf_packing)
|
|
624
|
+
|
|
625
|
+
if is_c_contig:
|
|
626
|
+
# For C contiguity, we need to fix the 'contig' dimension
|
|
627
|
+
# after the loop
|
|
628
|
+
a, p = axes_specs[-1]
|
|
629
|
+
axes_specs[-1] = a, 'contig'
|
|
630
|
+
|
|
631
|
+
validate_axes_specs([axis.start.pos for axis in axes],
|
|
632
|
+
axes_specs,
|
|
633
|
+
is_c_contig,
|
|
634
|
+
is_f_contig)
|
|
635
|
+
|
|
636
|
+
return axes_specs
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
def validate_axes(pos, axes):
|
|
640
|
+
if len(axes) >= Options.buffer_max_dims:
|
|
641
|
+
error(pos, "More dimensions than the maximum number"
|
|
642
|
+
" of buffer dimensions were used.")
|
|
643
|
+
return False
|
|
644
|
+
|
|
645
|
+
return True
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
def is_cf_contig(specs):
|
|
649
|
+
is_c_contig = is_f_contig = False
|
|
650
|
+
|
|
651
|
+
if len(specs) == 1 and specs == [('direct', 'contig')]:
|
|
652
|
+
is_c_contig = True
|
|
653
|
+
|
|
654
|
+
elif (specs[-1] == ('direct','contig') and
|
|
655
|
+
all(axis == ('direct','follow') for axis in specs[:-1])):
|
|
656
|
+
# c_contiguous: 'follow', 'follow', ..., 'follow', 'contig'
|
|
657
|
+
is_c_contig = True
|
|
658
|
+
|
|
659
|
+
elif (len(specs) > 1 and
|
|
660
|
+
specs[0] == ('direct','contig') and
|
|
661
|
+
all(axis == ('direct','follow') for axis in specs[1:])):
|
|
662
|
+
# f_contiguous: 'contig', 'follow', 'follow', ..., 'follow'
|
|
663
|
+
is_f_contig = True
|
|
664
|
+
|
|
665
|
+
return is_c_contig, is_f_contig
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
def get_mode(specs):
|
|
669
|
+
is_c_contig, is_f_contig = is_cf_contig(specs)
|
|
670
|
+
|
|
671
|
+
if is_c_contig:
|
|
672
|
+
return 'c'
|
|
673
|
+
elif is_f_contig:
|
|
674
|
+
return 'fortran'
|
|
675
|
+
|
|
676
|
+
for access, packing in specs:
|
|
677
|
+
if access in ('ptr', 'full'):
|
|
678
|
+
return 'full'
|
|
679
|
+
|
|
680
|
+
return 'strided'
|
|
681
|
+
|
|
682
|
+
view_constant_to_access_packing = {
|
|
683
|
+
'generic': ('full', 'strided'),
|
|
684
|
+
'strided': ('direct', 'strided'),
|
|
685
|
+
'indirect': ('ptr', 'strided'),
|
|
686
|
+
'generic_contiguous': ('full', 'contig'),
|
|
687
|
+
'contiguous': ('direct', 'contig'),
|
|
688
|
+
'indirect_contiguous': ('ptr', 'contig'),
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
def validate_axes_specs(positions, specs, is_c_contig, is_f_contig):
|
|
692
|
+
|
|
693
|
+
packing_specs = ('contig', 'strided', 'follow')
|
|
694
|
+
access_specs = ('direct', 'ptr', 'full')
|
|
695
|
+
|
|
696
|
+
# is_c_contig, is_f_contig = is_cf_contig(specs)
|
|
697
|
+
|
|
698
|
+
has_contig = has_follow = has_strided = has_generic_contig = False
|
|
699
|
+
|
|
700
|
+
last_indirect_dimension = -1
|
|
701
|
+
for idx, (access, packing) in enumerate(specs):
|
|
702
|
+
if access == 'ptr':
|
|
703
|
+
last_indirect_dimension = idx
|
|
704
|
+
|
|
705
|
+
for idx, (pos, (access, packing)) in enumerate(zip(positions, specs)):
|
|
706
|
+
|
|
707
|
+
if not (access in access_specs and
|
|
708
|
+
packing in packing_specs):
|
|
709
|
+
raise CompileError(pos, "Invalid axes specification.")
|
|
710
|
+
|
|
711
|
+
if packing == 'strided':
|
|
712
|
+
has_strided = True
|
|
713
|
+
elif packing == 'contig':
|
|
714
|
+
if has_contig:
|
|
715
|
+
raise CompileError(pos, "Only one direct contiguous "
|
|
716
|
+
"axis may be specified.")
|
|
717
|
+
|
|
718
|
+
valid_contig_dims = last_indirect_dimension + 1, len(specs) - 1
|
|
719
|
+
if idx not in valid_contig_dims and access != 'ptr':
|
|
720
|
+
if last_indirect_dimension + 1 != len(specs) - 1:
|
|
721
|
+
dims = "dimensions %d and %d" % valid_contig_dims
|
|
722
|
+
else:
|
|
723
|
+
dims = "dimension %d" % valid_contig_dims[0]
|
|
724
|
+
|
|
725
|
+
raise CompileError(pos, "Only %s may be contiguous and direct" % dims)
|
|
726
|
+
|
|
727
|
+
has_contig = access != 'ptr'
|
|
728
|
+
elif packing == 'follow':
|
|
729
|
+
if has_strided:
|
|
730
|
+
raise CompileError(pos, "A memoryview cannot have both follow and strided axis specifiers.")
|
|
731
|
+
if not (is_c_contig or is_f_contig):
|
|
732
|
+
raise CompileError(pos, "Invalid use of the follow specifier.")
|
|
733
|
+
|
|
734
|
+
if access in ('ptr', 'full'):
|
|
735
|
+
has_strided = False
|
|
736
|
+
|
|
737
|
+
def _get_resolved_spec(env, spec):
|
|
738
|
+
# spec must be a NameNode or an AttributeNode
|
|
739
|
+
if isinstance(spec, NameNode):
|
|
740
|
+
return _resolve_NameNode(env, spec)
|
|
741
|
+
elif isinstance(spec, AttributeNode):
|
|
742
|
+
return _resolve_AttributeNode(env, spec)
|
|
743
|
+
else:
|
|
744
|
+
raise CompileError(spec.pos, INVALID_ERR)
|
|
745
|
+
|
|
746
|
+
def _resolve_NameNode(env, node):
|
|
747
|
+
try:
|
|
748
|
+
resolved_name = env.lookup(node.name).name
|
|
749
|
+
except AttributeError:
|
|
750
|
+
raise CompileError(node.pos, INVALID_ERR)
|
|
751
|
+
|
|
752
|
+
viewscope = env.context.cython_scope.viewscope
|
|
753
|
+
entry = viewscope.lookup(resolved_name)
|
|
754
|
+
if entry is None:
|
|
755
|
+
raise CompileError(node.pos, NOT_CIMPORTED_ERR)
|
|
756
|
+
|
|
757
|
+
return entry
|
|
758
|
+
|
|
759
|
+
def _resolve_AttributeNode(env, node):
|
|
760
|
+
path = []
|
|
761
|
+
while isinstance(node, AttributeNode):
|
|
762
|
+
path.insert(0, node.attribute)
|
|
763
|
+
node = node.obj
|
|
764
|
+
if isinstance(node, NameNode):
|
|
765
|
+
path.insert(0, node.name)
|
|
766
|
+
else:
|
|
767
|
+
raise CompileError(node.pos, EXPR_ERR)
|
|
768
|
+
modnames = path[:-1]
|
|
769
|
+
# must be at least 1 module name, o/w not an AttributeNode.
|
|
770
|
+
assert modnames
|
|
771
|
+
|
|
772
|
+
scope = env
|
|
773
|
+
for modname in modnames:
|
|
774
|
+
mod = scope.lookup(modname)
|
|
775
|
+
if not mod or not mod.as_module:
|
|
776
|
+
raise CompileError(
|
|
777
|
+
node.pos, "undeclared name not builtin: %s" % modname)
|
|
778
|
+
scope = mod.as_module
|
|
779
|
+
|
|
780
|
+
entry = scope.lookup(path[-1])
|
|
781
|
+
if not entry:
|
|
782
|
+
raise CompileError(node.pos, "No such attribute '%s'" % path[-1])
|
|
783
|
+
|
|
784
|
+
return entry
|
|
785
|
+
|
|
786
|
+
#
|
|
787
|
+
### Utility loading
|
|
788
|
+
#
|
|
789
|
+
|
|
790
|
+
def load_memview_cy_utility(util_code_name, context=None, **kwargs):
|
|
791
|
+
return CythonUtilityCode.load(util_code_name, "MemoryView.pyx",
|
|
792
|
+
context=context, **kwargs)
|
|
793
|
+
|
|
794
|
+
def load_memview_c_utility(
|
|
795
|
+
util_code_name, util_code_filename="MemoryView_C.c",
|
|
796
|
+
*,
|
|
797
|
+
context=None, **kwargs):
|
|
798
|
+
if context is None:
|
|
799
|
+
return UtilityCode.load(util_code_name, util_code_filename, **kwargs)
|
|
800
|
+
else:
|
|
801
|
+
return TempitaUtilityCode.load(util_code_name, util_code_filename,
|
|
802
|
+
context=context, **kwargs)
|
|
803
|
+
|
|
804
|
+
def use_cython_array_utility_code(env):
|
|
805
|
+
if env.context.shared_utility_qualified_name:
|
|
806
|
+
return
|
|
807
|
+
cython_scope = env.context.cython_scope
|
|
808
|
+
cython_scope.load_cythonscope()
|
|
809
|
+
cython_scope.viewscope.lookup('array_cwrapper').used = True
|
|
810
|
+
|
|
811
|
+
template_context = {
|
|
812
|
+
'max_dims': Options.buffer_max_dims,
|
|
813
|
+
'memviewslice_name': Naming.memviewslice_cname,
|
|
814
|
+
'memslice_init': PyrexTypes.MemoryViewSliceType.default_value,
|
|
815
|
+
'THREAD_LOCKS_PREALLOCATED': 8,
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
def _get_memviewslice_declare_code():
|
|
819
|
+
memviewslice_declare_code = load_memview_c_utility(
|
|
820
|
+
"MemviewSliceStruct",
|
|
821
|
+
context=template_context,
|
|
822
|
+
requires=[])
|
|
823
|
+
return memviewslice_declare_code
|
|
824
|
+
|
|
825
|
+
atomic_utility = load_memview_c_utility(
|
|
826
|
+
"Atomics", util_code_filename="Synchronization.c", context=template_context)
|
|
827
|
+
|
|
828
|
+
memviewslice_index_helpers = load_memview_c_utility("MemviewSliceIndex")
|
|
829
|
+
|
|
830
|
+
def _get_typeinfo_to_format_code():
|
|
831
|
+
return load_memview_cy_utility(
|
|
832
|
+
"BufferFormatFromTypeInfo", requires=[Buffer._typeinfo_to_format_code])
|
|
833
|
+
|
|
834
|
+
def get_typeinfo_to_format_code(shared_utility_qualified_name):
|
|
835
|
+
if shared_utility_qualified_name:
|
|
836
|
+
return CythonSharedUtilityCode(
|
|
837
|
+
'BufferFormatFromTypeInfo.pxd',
|
|
838
|
+
shared_utility_qualified_name,
|
|
839
|
+
template_context=template_context,
|
|
840
|
+
requires=[])
|
|
841
|
+
else:
|
|
842
|
+
return _get_typeinfo_to_format_code()
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
is_contig_utility = load_memview_c_utility("MemviewSliceIsContig")
|
|
846
|
+
overlapping_utility = load_memview_c_utility("OverlappingSlices")
|
|
847
|
+
refcount_utility = load_memview_c_utility("MemviewRefcount")
|
|
848
|
+
slice_init_utility = load_memview_c_utility("MemviewSliceInit")
|
|
849
|
+
memviewslice_declare_code = load_memview_c_utility("MemviewSliceStruct", context=template_context)
|
|
850
|
+
|
|
851
|
+
copy_contents_new_utility = load_memview_c_utility(
|
|
852
|
+
"MemviewSliceCopyTemplate",
|
|
853
|
+
context=template_context,
|
|
854
|
+
# Requires general memoryview code - dependency is added below.
|
|
855
|
+
)
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
@Utils.cached_function
|
|
859
|
+
def _get_memoryview_utility_code():
|
|
860
|
+
memoryview_utility_code = load_memview_cy_utility(
|
|
861
|
+
"View.MemoryView",
|
|
862
|
+
context=template_context,
|
|
863
|
+
requires=[
|
|
864
|
+
Buffer.buffer_struct_declare_code,
|
|
865
|
+
Buffer.buffer_formats_declare_code,
|
|
866
|
+
memviewslice_declare_code,
|
|
867
|
+
refcount_utility,
|
|
868
|
+
atomic_utility,
|
|
869
|
+
is_contig_utility,
|
|
870
|
+
overlapping_utility,
|
|
871
|
+
copy_contents_new_utility,
|
|
872
|
+
],
|
|
873
|
+
)
|
|
874
|
+
|
|
875
|
+
return memoryview_utility_code
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
@Utils.cached_function
|
|
879
|
+
def _get_memoryview_shared_utility_code(shared_utility_qualified_name):
|
|
880
|
+
shared_utility_code = CythonSharedUtilityCode(
|
|
881
|
+
'MemoryView.pxd',
|
|
882
|
+
shared_utility_qualified_name,
|
|
883
|
+
template_context=template_context,
|
|
884
|
+
requires=[
|
|
885
|
+
Buffer.buffer_struct_declare_code,
|
|
886
|
+
Buffer.buffer_formats_declare_code,
|
|
887
|
+
memviewslice_declare_code,
|
|
888
|
+
refcount_utility,
|
|
889
|
+
atomic_utility,
|
|
890
|
+
copy_contents_new_utility,
|
|
891
|
+
],
|
|
892
|
+
)
|
|
893
|
+
|
|
894
|
+
return shared_utility_code
|
|
895
|
+
|
|
896
|
+
def get_view_utility_code(shared_utility_qualified_name):
|
|
897
|
+
if shared_utility_qualified_name:
|
|
898
|
+
return _get_memoryview_shared_utility_code(shared_utility_qualified_name)
|
|
899
|
+
else:
|
|
900
|
+
return _get_memoryview_utility_code()
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
view_utility_allowlist = ('array', 'memoryview', 'array_cwrapper',
|
|
904
|
+
'generic', 'strided', 'indirect', 'contiguous',
|
|
905
|
+
'indirect_contiguous')
|