numba-cuda 0.0.0__py3-none-any.whl → 0.0.12__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.
- _numba_cuda_redirector.pth +1 -0
- _numba_cuda_redirector.py +74 -0
- numba_cuda/VERSION +1 -0
- numba_cuda/__init__.py +5 -0
- numba_cuda/_version.py +19 -0
- numba_cuda/numba/cuda/__init__.py +22 -0
- numba_cuda/numba/cuda/api.py +526 -0
- numba_cuda/numba/cuda/api_util.py +30 -0
- numba_cuda/numba/cuda/args.py +77 -0
- numba_cuda/numba/cuda/cg.py +62 -0
- numba_cuda/numba/cuda/codegen.py +378 -0
- numba_cuda/numba/cuda/compiler.py +422 -0
- numba_cuda/numba/cuda/cpp_function_wrappers.cu +47 -0
- numba_cuda/numba/cuda/cuda_fp16.h +3631 -0
- numba_cuda/numba/cuda/cuda_fp16.hpp +2465 -0
- numba_cuda/numba/cuda/cuda_paths.py +258 -0
- numba_cuda/numba/cuda/cudadecl.py +806 -0
- numba_cuda/numba/cuda/cudadrv/__init__.py +9 -0
- numba_cuda/numba/cuda/cudadrv/devicearray.py +904 -0
- numba_cuda/numba/cuda/cudadrv/devices.py +248 -0
- numba_cuda/numba/cuda/cudadrv/driver.py +3201 -0
- numba_cuda/numba/cuda/cudadrv/drvapi.py +398 -0
- numba_cuda/numba/cuda/cudadrv/dummyarray.py +452 -0
- numba_cuda/numba/cuda/cudadrv/enums.py +607 -0
- numba_cuda/numba/cuda/cudadrv/error.py +36 -0
- numba_cuda/numba/cuda/cudadrv/libs.py +176 -0
- numba_cuda/numba/cuda/cudadrv/ndarray.py +20 -0
- numba_cuda/numba/cuda/cudadrv/nvrtc.py +260 -0
- numba_cuda/numba/cuda/cudadrv/nvvm.py +707 -0
- numba_cuda/numba/cuda/cudadrv/rtapi.py +10 -0
- numba_cuda/numba/cuda/cudadrv/runtime.py +142 -0
- numba_cuda/numba/cuda/cudaimpl.py +1055 -0
- numba_cuda/numba/cuda/cudamath.py +140 -0
- numba_cuda/numba/cuda/decorators.py +189 -0
- numba_cuda/numba/cuda/descriptor.py +33 -0
- numba_cuda/numba/cuda/device_init.py +89 -0
- numba_cuda/numba/cuda/deviceufunc.py +908 -0
- numba_cuda/numba/cuda/dispatcher.py +1057 -0
- numba_cuda/numba/cuda/errors.py +59 -0
- numba_cuda/numba/cuda/extending.py +7 -0
- numba_cuda/numba/cuda/initialize.py +13 -0
- numba_cuda/numba/cuda/intrinsic_wrapper.py +77 -0
- numba_cuda/numba/cuda/intrinsics.py +198 -0
- numba_cuda/numba/cuda/kernels/__init__.py +0 -0
- numba_cuda/numba/cuda/kernels/reduction.py +262 -0
- numba_cuda/numba/cuda/kernels/transpose.py +65 -0
- numba_cuda/numba/cuda/libdevice.py +3382 -0
- numba_cuda/numba/cuda/libdevicedecl.py +17 -0
- numba_cuda/numba/cuda/libdevicefuncs.py +1057 -0
- numba_cuda/numba/cuda/libdeviceimpl.py +83 -0
- numba_cuda/numba/cuda/mathimpl.py +448 -0
- numba_cuda/numba/cuda/models.py +48 -0
- numba_cuda/numba/cuda/nvvmutils.py +235 -0
- numba_cuda/numba/cuda/printimpl.py +86 -0
- numba_cuda/numba/cuda/random.py +292 -0
- numba_cuda/numba/cuda/simulator/__init__.py +38 -0
- numba_cuda/numba/cuda/simulator/api.py +110 -0
- numba_cuda/numba/cuda/simulator/compiler.py +9 -0
- numba_cuda/numba/cuda/simulator/cudadrv/__init__.py +2 -0
- numba_cuda/numba/cuda/simulator/cudadrv/devicearray.py +432 -0
- numba_cuda/numba/cuda/simulator/cudadrv/devices.py +117 -0
- numba_cuda/numba/cuda/simulator/cudadrv/driver.py +62 -0
- numba_cuda/numba/cuda/simulator/cudadrv/drvapi.py +4 -0
- numba_cuda/numba/cuda/simulator/cudadrv/dummyarray.py +4 -0
- numba_cuda/numba/cuda/simulator/cudadrv/error.py +6 -0
- numba_cuda/numba/cuda/simulator/cudadrv/libs.py +2 -0
- numba_cuda/numba/cuda/simulator/cudadrv/nvvm.py +29 -0
- numba_cuda/numba/cuda/simulator/cudadrv/runtime.py +19 -0
- numba_cuda/numba/cuda/simulator/kernel.py +308 -0
- numba_cuda/numba/cuda/simulator/kernelapi.py +495 -0
- numba_cuda/numba/cuda/simulator/reduction.py +15 -0
- numba_cuda/numba/cuda/simulator/vector_types.py +58 -0
- numba_cuda/numba/cuda/simulator_init.py +17 -0
- numba_cuda/numba/cuda/stubs.py +902 -0
- numba_cuda/numba/cuda/target.py +440 -0
- numba_cuda/numba/cuda/testing.py +202 -0
- numba_cuda/numba/cuda/tests/__init__.py +58 -0
- numba_cuda/numba/cuda/tests/cudadrv/__init__.py +8 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_array_attr.py +145 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_context_stack.py +145 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_array_slicing.py +375 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_auto_context.py +21 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_devicerecord.py +179 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_driver.py +235 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_libraries.py +22 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_memory.py +193 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_ndarray.py +547 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_deallocations.py +249 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_detect.py +81 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_emm_plugins.py +192 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_events.py +38 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_host_alloc.py +65 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_init.py +139 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_inline_ptx.py +37 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_is_fp16.py +12 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_linker.py +317 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_managed_alloc.py +127 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_mvc.py +54 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_nvvm_driver.py +199 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_pinned.py +37 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_profiler.py +20 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_ptds.py +149 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_reset_device.py +36 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_runtime.py +85 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_select_device.py +41 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_streams.py +122 -0
- numba_cuda/numba/cuda/tests/cudapy/__init__.py +8 -0
- numba_cuda/numba/cuda/tests/cudapy/cache_usecases.py +234 -0
- numba_cuda/numba/cuda/tests/cudapy/cache_with_cpu_usecases.py +41 -0
- numba_cuda/numba/cuda/tests/cudapy/extensions_usecases.py +58 -0
- numba_cuda/numba/cuda/tests/cudapy/jitlink.ptx +30 -0
- numba_cuda/numba/cuda/tests/cudapy/recursion_usecases.py +100 -0
- numba_cuda/numba/cuda/tests/cudapy/test_alignment.py +42 -0
- numba_cuda/numba/cuda/tests/cudapy/test_array.py +260 -0
- numba_cuda/numba/cuda/tests/cudapy/test_array_args.py +201 -0
- numba_cuda/numba/cuda/tests/cudapy/test_array_methods.py +35 -0
- numba_cuda/numba/cuda/tests/cudapy/test_atomics.py +1620 -0
- numba_cuda/numba/cuda/tests/cudapy/test_blackscholes.py +120 -0
- numba_cuda/numba/cuda/tests/cudapy/test_boolean.py +24 -0
- numba_cuda/numba/cuda/tests/cudapy/test_caching.py +545 -0
- numba_cuda/numba/cuda/tests/cudapy/test_casting.py +257 -0
- numba_cuda/numba/cuda/tests/cudapy/test_cffi.py +33 -0
- numba_cuda/numba/cuda/tests/cudapy/test_compiler.py +276 -0
- numba_cuda/numba/cuda/tests/cudapy/test_complex.py +296 -0
- numba_cuda/numba/cuda/tests/cudapy/test_complex_kernel.py +20 -0
- numba_cuda/numba/cuda/tests/cudapy/test_const_string.py +129 -0
- numba_cuda/numba/cuda/tests/cudapy/test_constmem.py +176 -0
- numba_cuda/numba/cuda/tests/cudapy/test_cooperative_groups.py +147 -0
- numba_cuda/numba/cuda/tests/cudapy/test_cuda_array_interface.py +435 -0
- numba_cuda/numba/cuda/tests/cudapy/test_cuda_jit_no_types.py +90 -0
- numba_cuda/numba/cuda/tests/cudapy/test_datetime.py +94 -0
- numba_cuda/numba/cuda/tests/cudapy/test_debug.py +101 -0
- numba_cuda/numba/cuda/tests/cudapy/test_debuginfo.py +221 -0
- numba_cuda/numba/cuda/tests/cudapy/test_device_func.py +222 -0
- numba_cuda/numba/cuda/tests/cudapy/test_dispatcher.py +700 -0
- numba_cuda/numba/cuda/tests/cudapy/test_enums.py +121 -0
- numba_cuda/numba/cuda/tests/cudapy/test_errors.py +79 -0
- numba_cuda/numba/cuda/tests/cudapy/test_exception.py +174 -0
- numba_cuda/numba/cuda/tests/cudapy/test_extending.py +155 -0
- numba_cuda/numba/cuda/tests/cudapy/test_fastmath.py +244 -0
- numba_cuda/numba/cuda/tests/cudapy/test_forall.py +52 -0
- numba_cuda/numba/cuda/tests/cudapy/test_freevar.py +29 -0
- numba_cuda/numba/cuda/tests/cudapy/test_frexp_ldexp.py +66 -0
- numba_cuda/numba/cuda/tests/cudapy/test_globals.py +60 -0
- numba_cuda/numba/cuda/tests/cudapy/test_gufunc.py +456 -0
- numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scalar.py +159 -0
- numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scheduling.py +95 -0
- numba_cuda/numba/cuda/tests/cudapy/test_idiv.py +37 -0
- numba_cuda/numba/cuda/tests/cudapy/test_inspect.py +165 -0
- numba_cuda/numba/cuda/tests/cudapy/test_intrinsics.py +1106 -0
- numba_cuda/numba/cuda/tests/cudapy/test_ipc.py +318 -0
- numba_cuda/numba/cuda/tests/cudapy/test_iterators.py +99 -0
- numba_cuda/numba/cuda/tests/cudapy/test_lang.py +64 -0
- numba_cuda/numba/cuda/tests/cudapy/test_laplace.py +119 -0
- numba_cuda/numba/cuda/tests/cudapy/test_libdevice.py +187 -0
- numba_cuda/numba/cuda/tests/cudapy/test_lineinfo.py +199 -0
- numba_cuda/numba/cuda/tests/cudapy/test_localmem.py +164 -0
- numba_cuda/numba/cuda/tests/cudapy/test_mandel.py +37 -0
- numba_cuda/numba/cuda/tests/cudapy/test_math.py +786 -0
- numba_cuda/numba/cuda/tests/cudapy/test_matmul.py +74 -0
- numba_cuda/numba/cuda/tests/cudapy/test_minmax.py +113 -0
- numba_cuda/numba/cuda/tests/cudapy/test_montecarlo.py +22 -0
- numba_cuda/numba/cuda/tests/cudapy/test_multigpu.py +140 -0
- numba_cuda/numba/cuda/tests/cudapy/test_multiprocessing.py +46 -0
- numba_cuda/numba/cuda/tests/cudapy/test_multithreads.py +101 -0
- numba_cuda/numba/cuda/tests/cudapy/test_nondet.py +49 -0
- numba_cuda/numba/cuda/tests/cudapy/test_operator.py +401 -0
- numba_cuda/numba/cuda/tests/cudapy/test_optimization.py +86 -0
- numba_cuda/numba/cuda/tests/cudapy/test_overload.py +335 -0
- numba_cuda/numba/cuda/tests/cudapy/test_powi.py +124 -0
- numba_cuda/numba/cuda/tests/cudapy/test_print.py +128 -0
- numba_cuda/numba/cuda/tests/cudapy/test_py2_div_issue.py +33 -0
- numba_cuda/numba/cuda/tests/cudapy/test_random.py +104 -0
- numba_cuda/numba/cuda/tests/cudapy/test_record_dtype.py +610 -0
- numba_cuda/numba/cuda/tests/cudapy/test_recursion.py +125 -0
- numba_cuda/numba/cuda/tests/cudapy/test_reduction.py +76 -0
- numba_cuda/numba/cuda/tests/cudapy/test_retrieve_autoconverted_arrays.py +83 -0
- numba_cuda/numba/cuda/tests/cudapy/test_serialize.py +85 -0
- numba_cuda/numba/cuda/tests/cudapy/test_slicing.py +37 -0
- numba_cuda/numba/cuda/tests/cudapy/test_sm.py +444 -0
- numba_cuda/numba/cuda/tests/cudapy/test_sm_creation.py +205 -0
- numba_cuda/numba/cuda/tests/cudapy/test_sync.py +271 -0
- numba_cuda/numba/cuda/tests/cudapy/test_transpose.py +80 -0
- numba_cuda/numba/cuda/tests/cudapy/test_ufuncs.py +277 -0
- numba_cuda/numba/cuda/tests/cudapy/test_userexc.py +47 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vector_type.py +307 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize.py +283 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize_complex.py +20 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize_decor.py +69 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize_device.py +36 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize_scalar_arg.py +37 -0
- numba_cuda/numba/cuda/tests/cudapy/test_warning.py +139 -0
- numba_cuda/numba/cuda/tests/cudapy/test_warp_ops.py +276 -0
- numba_cuda/numba/cuda/tests/cudasim/__init__.py +6 -0
- numba_cuda/numba/cuda/tests/cudasim/support.py +6 -0
- numba_cuda/numba/cuda/tests/cudasim/test_cudasim_issues.py +102 -0
- numba_cuda/numba/cuda/tests/data/__init__.py +0 -0
- numba_cuda/numba/cuda/tests/data/cuda_include.cu +5 -0
- numba_cuda/numba/cuda/tests/data/error.cu +7 -0
- numba_cuda/numba/cuda/tests/data/jitlink.cu +23 -0
- numba_cuda/numba/cuda/tests/data/jitlink.ptx +51 -0
- numba_cuda/numba/cuda/tests/data/warn.cu +7 -0
- numba_cuda/numba/cuda/tests/doc_examples/__init__.py +6 -0
- numba_cuda/numba/cuda/tests/doc_examples/ffi/__init__.py +0 -0
- numba_cuda/numba/cuda/tests/doc_examples/ffi/functions.cu +49 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_cg.py +77 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_cpu_gpu_compat.py +76 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_ffi.py +82 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_laplace.py +155 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_matmul.py +173 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_montecarlo.py +109 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_random.py +59 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_reduction.py +76 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_sessionize.py +130 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_ufunc.py +50 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_vecadd.py +73 -0
- numba_cuda/numba/cuda/tests/nocuda/__init__.py +8 -0
- numba_cuda/numba/cuda/tests/nocuda/test_dummyarray.py +359 -0
- numba_cuda/numba/cuda/tests/nocuda/test_function_resolution.py +36 -0
- numba_cuda/numba/cuda/tests/nocuda/test_import.py +49 -0
- numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py +238 -0
- numba_cuda/numba/cuda/tests/nocuda/test_nvvm.py +54 -0
- numba_cuda/numba/cuda/types.py +37 -0
- numba_cuda/numba/cuda/ufuncs.py +662 -0
- numba_cuda/numba/cuda/vector_types.py +209 -0
- numba_cuda/numba/cuda/vectorizers.py +252 -0
- numba_cuda-0.0.12.dist-info/LICENSE +25 -0
- numba_cuda-0.0.12.dist-info/METADATA +68 -0
- numba_cuda-0.0.12.dist-info/RECORD +231 -0
- {numba_cuda-0.0.0.dist-info → numba_cuda-0.0.12.dist-info}/WHEEL +1 -1
- numba_cuda-0.0.0.dist-info/METADATA +0 -6
- numba_cuda-0.0.0.dist-info/RECORD +0 -5
- {numba_cuda-0.0.0.dist-info → numba_cuda-0.0.12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,452 @@
|
|
1
|
+
from collections import namedtuple
|
2
|
+
import itertools
|
3
|
+
import functools
|
4
|
+
import operator
|
5
|
+
import ctypes
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
|
9
|
+
from numba import _helperlib
|
10
|
+
|
11
|
+
Extent = namedtuple("Extent", ["begin", "end"])
|
12
|
+
|
13
|
+
attempt_nocopy_reshape = ctypes.CFUNCTYPE(
|
14
|
+
ctypes.c_int,
|
15
|
+
ctypes.c_long, # nd
|
16
|
+
np.ctypeslib.ndpointer(np.ctypeslib.c_intp, ndim=1), # dims
|
17
|
+
np.ctypeslib.ndpointer(np.ctypeslib.c_intp, ndim=1), # strides
|
18
|
+
ctypes.c_long, # newnd
|
19
|
+
np.ctypeslib.ndpointer(np.ctypeslib.c_intp, ndim=1), # newdims
|
20
|
+
np.ctypeslib.ndpointer(np.ctypeslib.c_intp, ndim=1), # newstrides
|
21
|
+
ctypes.c_long, # itemsize
|
22
|
+
ctypes.c_int, # is_f_order
|
23
|
+
)(_helperlib.c_helpers['attempt_nocopy_reshape'])
|
24
|
+
|
25
|
+
|
26
|
+
class Dim(object):
|
27
|
+
"""A single dimension of the array
|
28
|
+
|
29
|
+
Attributes
|
30
|
+
----------
|
31
|
+
start:
|
32
|
+
start offset
|
33
|
+
stop:
|
34
|
+
stop offset
|
35
|
+
size:
|
36
|
+
number of items
|
37
|
+
stride:
|
38
|
+
item stride
|
39
|
+
"""
|
40
|
+
__slots__ = 'start', 'stop', 'size', 'stride', 'single'
|
41
|
+
|
42
|
+
def __init__(self, start, stop, size, stride, single):
|
43
|
+
self.start = start
|
44
|
+
self.stop = stop
|
45
|
+
self.size = size
|
46
|
+
self.stride = stride
|
47
|
+
self.single = single
|
48
|
+
assert not single or size == 1
|
49
|
+
|
50
|
+
def __getitem__(self, item):
|
51
|
+
if isinstance(item, slice):
|
52
|
+
start, stop, step = item.indices(self.size)
|
53
|
+
stride = step * self.stride
|
54
|
+
start = self.start + start * abs(self.stride)
|
55
|
+
stop = self.start + stop * abs(self.stride)
|
56
|
+
if stride == 0:
|
57
|
+
size = 1
|
58
|
+
else:
|
59
|
+
size = _compute_size(start, stop, stride)
|
60
|
+
ret = Dim(
|
61
|
+
start=start,
|
62
|
+
stop=stop,
|
63
|
+
size=size,
|
64
|
+
stride=stride,
|
65
|
+
single=False
|
66
|
+
)
|
67
|
+
return ret
|
68
|
+
else:
|
69
|
+
sliced = self[item:item + 1] if item != -1 else self[-1:]
|
70
|
+
if sliced.size != 1:
|
71
|
+
raise IndexError
|
72
|
+
return Dim(
|
73
|
+
start=sliced.start,
|
74
|
+
stop=sliced.stop,
|
75
|
+
size=sliced.size,
|
76
|
+
stride=sliced.stride,
|
77
|
+
single=True,
|
78
|
+
)
|
79
|
+
|
80
|
+
def get_offset(self, idx):
|
81
|
+
return self.start + idx * self.stride
|
82
|
+
|
83
|
+
def __repr__(self):
|
84
|
+
strfmt = "Dim(start=%s, stop=%s, size=%s, stride=%s)"
|
85
|
+
return strfmt % (self.start, self.stop, self.size, self.stride)
|
86
|
+
|
87
|
+
def normalize(self, base):
|
88
|
+
return Dim(start=self.start - base, stop=self.stop - base,
|
89
|
+
size=self.size, stride=self.stride, single=self.single)
|
90
|
+
|
91
|
+
def copy(self, start=None, stop=None, size=None, stride=None, single=None):
|
92
|
+
if start is None:
|
93
|
+
start = self.start
|
94
|
+
if stop is None:
|
95
|
+
stop = self.stop
|
96
|
+
if size is None:
|
97
|
+
size = self.size
|
98
|
+
if stride is None:
|
99
|
+
stride = self.stride
|
100
|
+
if single is None:
|
101
|
+
single = self.single
|
102
|
+
return Dim(start, stop, size, stride, single)
|
103
|
+
|
104
|
+
def is_contiguous(self, itemsize):
|
105
|
+
return self.stride == itemsize
|
106
|
+
|
107
|
+
|
108
|
+
def compute_index(indices, dims):
|
109
|
+
return sum(d.get_offset(i) for i, d in zip(indices, dims))
|
110
|
+
|
111
|
+
|
112
|
+
class Element(object):
|
113
|
+
is_array = False
|
114
|
+
|
115
|
+
def __init__(self, extent):
|
116
|
+
self.extent = extent
|
117
|
+
|
118
|
+
def iter_contiguous_extent(self):
|
119
|
+
yield self.extent
|
120
|
+
|
121
|
+
|
122
|
+
class Array(object):
|
123
|
+
"""A dummy numpy array-like object. Consider it an array without the
|
124
|
+
actual data, but offset from the base data pointer.
|
125
|
+
|
126
|
+
Attributes
|
127
|
+
----------
|
128
|
+
dims: tuple of Dim
|
129
|
+
describing each dimension of the array
|
130
|
+
|
131
|
+
ndim: int
|
132
|
+
number of dimension
|
133
|
+
|
134
|
+
shape: tuple of int
|
135
|
+
size of each dimension
|
136
|
+
|
137
|
+
strides: tuple of int
|
138
|
+
stride of each dimension
|
139
|
+
|
140
|
+
itemsize: int
|
141
|
+
itemsize
|
142
|
+
|
143
|
+
extent: (start, end)
|
144
|
+
start and end offset containing the memory region
|
145
|
+
"""
|
146
|
+
is_array = True
|
147
|
+
|
148
|
+
@classmethod
|
149
|
+
def from_desc(cls, offset, shape, strides, itemsize):
|
150
|
+
dims = []
|
151
|
+
for ashape, astride in zip(shape, strides):
|
152
|
+
dim = Dim(offset, offset + ashape * astride, ashape, astride,
|
153
|
+
single=False)
|
154
|
+
dims.append(dim)
|
155
|
+
offset = 0 # offset only applies to first dimension
|
156
|
+
return cls(dims, itemsize)
|
157
|
+
|
158
|
+
def __init__(self, dims, itemsize):
|
159
|
+
self.dims = tuple(dims)
|
160
|
+
self.ndim = len(self.dims)
|
161
|
+
self.shape = tuple(dim.size for dim in self.dims)
|
162
|
+
self.strides = tuple(dim.stride for dim in self.dims)
|
163
|
+
self.itemsize = itemsize
|
164
|
+
self.size = functools.reduce(operator.mul, self.shape, 1)
|
165
|
+
self.extent = self._compute_extent()
|
166
|
+
self.flags = self._compute_layout()
|
167
|
+
|
168
|
+
def _compute_layout(self):
|
169
|
+
# The logic here is based on that in _UpdateContiguousFlags from
|
170
|
+
# numpy/core/src/multiarray/flagsobject.c in NumPy v1.19.1 (commit
|
171
|
+
# 13661ac70).
|
172
|
+
# https://github.com/numpy/numpy/blob/maintenance/1.19.x/numpy/core/src/multiarray/flagsobject.c#L123-L191
|
173
|
+
|
174
|
+
# Records have no dims, and we can treat them as contiguous
|
175
|
+
if not self.dims:
|
176
|
+
return {'C_CONTIGUOUS': True, 'F_CONTIGUOUS': True}
|
177
|
+
|
178
|
+
# If this is a broadcast array then it is not contiguous
|
179
|
+
if any([dim.stride == 0 for dim in self.dims]):
|
180
|
+
return {'C_CONTIGUOUS': False, 'F_CONTIGUOUS': False}
|
181
|
+
|
182
|
+
flags = {'C_CONTIGUOUS': True, 'F_CONTIGUOUS': True}
|
183
|
+
|
184
|
+
# Check C contiguity
|
185
|
+
sd = self.itemsize
|
186
|
+
for dim in reversed(self.dims):
|
187
|
+
if dim.size == 0:
|
188
|
+
# Contiguous by definition
|
189
|
+
return {'C_CONTIGUOUS': True, 'F_CONTIGUOUS': True}
|
190
|
+
if dim.size != 1:
|
191
|
+
if dim.stride != sd:
|
192
|
+
flags['C_CONTIGUOUS'] = False
|
193
|
+
sd *= dim.size
|
194
|
+
|
195
|
+
# Check F contiguity
|
196
|
+
sd = self.itemsize
|
197
|
+
for dim in self.dims:
|
198
|
+
if dim.size != 1:
|
199
|
+
if dim.stride != sd:
|
200
|
+
flags['F_CONTIGUOUS'] = False
|
201
|
+
return flags
|
202
|
+
sd *= dim.size
|
203
|
+
|
204
|
+
return flags
|
205
|
+
|
206
|
+
def _compute_extent(self):
|
207
|
+
firstidx = [0] * self.ndim
|
208
|
+
lastidx = [s - 1 for s in self.shape]
|
209
|
+
start = compute_index(firstidx, self.dims)
|
210
|
+
stop = compute_index(lastidx, self.dims) + self.itemsize
|
211
|
+
stop = max(stop, start) # ensure positive extent
|
212
|
+
return Extent(start, stop)
|
213
|
+
|
214
|
+
def __repr__(self):
|
215
|
+
return '<Array dims=%s itemsize=%s>' % (self.dims, self.itemsize)
|
216
|
+
|
217
|
+
def __getitem__(self, item):
|
218
|
+
if not isinstance(item, tuple):
|
219
|
+
item = [item]
|
220
|
+
else:
|
221
|
+
item = list(item)
|
222
|
+
|
223
|
+
nitem = len(item)
|
224
|
+
ndim = len(self.dims)
|
225
|
+
if nitem > ndim:
|
226
|
+
raise IndexError("%d extra indices given" % (nitem - ndim,))
|
227
|
+
|
228
|
+
# Add empty slices for missing indices
|
229
|
+
while len(item) < ndim:
|
230
|
+
item.append(slice(None, None))
|
231
|
+
|
232
|
+
dims = [dim.__getitem__(it) for dim, it in zip(self.dims, item)]
|
233
|
+
newshape = [d.size for d in dims if not d.single]
|
234
|
+
|
235
|
+
arr = Array(dims, self.itemsize)
|
236
|
+
if newshape:
|
237
|
+
return arr.reshape(*newshape)[0]
|
238
|
+
else:
|
239
|
+
return Element(arr.extent)
|
240
|
+
|
241
|
+
@property
|
242
|
+
def is_c_contig(self):
|
243
|
+
return self.flags['C_CONTIGUOUS']
|
244
|
+
|
245
|
+
@property
|
246
|
+
def is_f_contig(self):
|
247
|
+
return self.flags['F_CONTIGUOUS']
|
248
|
+
|
249
|
+
def iter_contiguous_extent(self):
|
250
|
+
""" Generates extents
|
251
|
+
"""
|
252
|
+
if self.is_c_contig or self.is_f_contig:
|
253
|
+
yield self.extent
|
254
|
+
else:
|
255
|
+
if self.dims[0].stride < self.dims[-1].stride:
|
256
|
+
innerdim = self.dims[0]
|
257
|
+
outerdims = self.dims[1:]
|
258
|
+
outershape = self.shape[1:]
|
259
|
+
else:
|
260
|
+
innerdim = self.dims[-1]
|
261
|
+
outerdims = self.dims[:-1]
|
262
|
+
outershape = self.shape[:-1]
|
263
|
+
|
264
|
+
if innerdim.is_contiguous(self.itemsize):
|
265
|
+
oslen = [range(s) for s in outershape]
|
266
|
+
for indices in itertools.product(*oslen):
|
267
|
+
base = compute_index(indices, outerdims)
|
268
|
+
yield base + innerdim.start, base + innerdim.stop
|
269
|
+
else:
|
270
|
+
oslen = [range(s) for s in self.shape]
|
271
|
+
for indices in itertools.product(*oslen):
|
272
|
+
offset = compute_index(indices, self.dims)
|
273
|
+
yield offset, offset + self.itemsize
|
274
|
+
|
275
|
+
def reshape(self, *newdims, **kws):
|
276
|
+
oldnd = self.ndim
|
277
|
+
newnd = len(newdims)
|
278
|
+
|
279
|
+
if newdims == self.shape:
|
280
|
+
return self, None
|
281
|
+
|
282
|
+
order = kws.pop('order', 'C')
|
283
|
+
if kws:
|
284
|
+
raise TypeError('unknown keyword arguments %s' % kws.keys())
|
285
|
+
if order not in 'CFA':
|
286
|
+
raise ValueError('order not C|F|A')
|
287
|
+
|
288
|
+
# check for exactly one instance of -1 in newdims
|
289
|
+
# https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/core/src/multiarray/shape.c#L470-L515 # noqa: E501
|
290
|
+
unknownidx = -1
|
291
|
+
knownsize = 1
|
292
|
+
for i, dim in enumerate(newdims):
|
293
|
+
if dim < 0:
|
294
|
+
if unknownidx == -1:
|
295
|
+
unknownidx = i
|
296
|
+
else:
|
297
|
+
raise ValueError("can only specify one unknown dimension")
|
298
|
+
else:
|
299
|
+
knownsize *= dim
|
300
|
+
|
301
|
+
# compute the missing dimension
|
302
|
+
if unknownidx >= 0:
|
303
|
+
if knownsize == 0 or self.size % knownsize != 0:
|
304
|
+
raise ValueError("cannot infer valid shape "
|
305
|
+
"for unknown dimension")
|
306
|
+
else:
|
307
|
+
newdims = newdims[0:unknownidx] \
|
308
|
+
+ (self.size // knownsize,) \
|
309
|
+
+ newdims[unknownidx + 1:]
|
310
|
+
|
311
|
+
newsize = functools.reduce(operator.mul, newdims, 1)
|
312
|
+
|
313
|
+
if order == 'A':
|
314
|
+
order = 'F' if self.is_f_contig else 'C'
|
315
|
+
|
316
|
+
if newsize != self.size:
|
317
|
+
raise ValueError("reshape changes the size of the array")
|
318
|
+
|
319
|
+
if self.is_c_contig or self.is_f_contig:
|
320
|
+
if order == 'C':
|
321
|
+
newstrides = list(iter_strides_c_contig(self, newdims))
|
322
|
+
elif order == 'F':
|
323
|
+
newstrides = list(iter_strides_f_contig(self, newdims))
|
324
|
+
else:
|
325
|
+
raise AssertionError("unreachable")
|
326
|
+
else:
|
327
|
+
newstrides = np.empty(newnd, np.ctypeslib.c_intp)
|
328
|
+
|
329
|
+
# need to keep these around in variables, not temporaries, so they
|
330
|
+
# don't get GC'ed before we call into the C code
|
331
|
+
olddims = np.array(self.shape, dtype=np.ctypeslib.c_intp)
|
332
|
+
oldstrides = np.array(self.strides, dtype=np.ctypeslib.c_intp)
|
333
|
+
newdims = np.array(newdims, dtype=np.ctypeslib.c_intp)
|
334
|
+
|
335
|
+
if not attempt_nocopy_reshape(
|
336
|
+
oldnd,
|
337
|
+
olddims,
|
338
|
+
oldstrides,
|
339
|
+
newnd,
|
340
|
+
newdims,
|
341
|
+
newstrides,
|
342
|
+
self.itemsize,
|
343
|
+
order == 'F',
|
344
|
+
):
|
345
|
+
raise NotImplementedError('reshape would require copy')
|
346
|
+
|
347
|
+
ret = self.from_desc(self.extent.begin, shape=newdims,
|
348
|
+
strides=newstrides, itemsize=self.itemsize)
|
349
|
+
|
350
|
+
return ret, list(self.iter_contiguous_extent())
|
351
|
+
|
352
|
+
def squeeze(self, axis=None):
|
353
|
+
newshape, newstrides = [], []
|
354
|
+
if axis is None:
|
355
|
+
for length, stride in zip(self.shape, self.strides):
|
356
|
+
if length != 1:
|
357
|
+
newshape.append(length)
|
358
|
+
newstrides.append(stride)
|
359
|
+
else:
|
360
|
+
if not isinstance(axis, tuple):
|
361
|
+
axis = (axis,)
|
362
|
+
for ax in axis:
|
363
|
+
if self.shape[ax] != 1:
|
364
|
+
raise ValueError(
|
365
|
+
"cannot select an axis to squeeze out which has size "
|
366
|
+
"not equal to one"
|
367
|
+
)
|
368
|
+
for i, (length, stride) in enumerate(zip(self.shape, self.strides)):
|
369
|
+
if i not in axis:
|
370
|
+
newshape.append(length)
|
371
|
+
newstrides.append(stride)
|
372
|
+
newarr = self.from_desc(
|
373
|
+
self.extent.begin,
|
374
|
+
shape=newshape,
|
375
|
+
strides=newstrides,
|
376
|
+
itemsize=self.itemsize,
|
377
|
+
)
|
378
|
+
return newarr, list(self.iter_contiguous_extent())
|
379
|
+
|
380
|
+
def ravel(self, order='C'):
|
381
|
+
if order not in 'CFA':
|
382
|
+
raise ValueError('order not C|F|A')
|
383
|
+
|
384
|
+
if (order in 'CA' and self.is_c_contig
|
385
|
+
or order in 'FA' and self.is_f_contig):
|
386
|
+
newshape = (self.size,)
|
387
|
+
newstrides = (self.itemsize,)
|
388
|
+
arr = self.from_desc(self.extent.begin, newshape, newstrides,
|
389
|
+
self.itemsize)
|
390
|
+
return arr, list(self.iter_contiguous_extent())
|
391
|
+
|
392
|
+
else:
|
393
|
+
raise NotImplementedError("ravel on non-contiguous array")
|
394
|
+
|
395
|
+
|
396
|
+
def iter_strides_f_contig(arr, shape=None):
|
397
|
+
"""yields the f-contiguous strides
|
398
|
+
"""
|
399
|
+
shape = arr.shape if shape is None else shape
|
400
|
+
itemsize = arr.itemsize
|
401
|
+
yield itemsize
|
402
|
+
sum = 1
|
403
|
+
for s in shape[:-1]:
|
404
|
+
sum *= s
|
405
|
+
yield sum * itemsize
|
406
|
+
|
407
|
+
|
408
|
+
def iter_strides_c_contig(arr, shape=None):
|
409
|
+
"""yields the c-contiguous strides
|
410
|
+
"""
|
411
|
+
shape = arr.shape if shape is None else shape
|
412
|
+
itemsize = arr.itemsize
|
413
|
+
|
414
|
+
def gen():
|
415
|
+
yield itemsize
|
416
|
+
sum = 1
|
417
|
+
for s in reversed(shape[1:]):
|
418
|
+
sum *= s
|
419
|
+
yield sum * itemsize
|
420
|
+
|
421
|
+
for i in reversed(list(gen())):
|
422
|
+
yield i
|
423
|
+
|
424
|
+
|
425
|
+
def is_element_indexing(item, ndim):
|
426
|
+
if isinstance(item, slice):
|
427
|
+
return False
|
428
|
+
|
429
|
+
elif isinstance(item, tuple):
|
430
|
+
if len(item) == ndim:
|
431
|
+
if not any(isinstance(it, slice) for it in item):
|
432
|
+
return True
|
433
|
+
|
434
|
+
else:
|
435
|
+
return True
|
436
|
+
|
437
|
+
return False
|
438
|
+
|
439
|
+
|
440
|
+
def _compute_size(start, stop, step):
|
441
|
+
"""Algorithm adapted from cpython rangeobject.c
|
442
|
+
"""
|
443
|
+
if step > 0:
|
444
|
+
lo = start
|
445
|
+
hi = stop
|
446
|
+
else:
|
447
|
+
lo = stop
|
448
|
+
hi = start
|
449
|
+
step = -step
|
450
|
+
if lo >= hi:
|
451
|
+
return 0
|
452
|
+
return (hi - lo - 1) // step + 1
|