dask-array 0.1.0__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.
- dask_array/__init__.py +228 -0
- dask_array/_backends.py +76 -0
- dask_array/_backends_array.py +99 -0
- dask_array/_blockwise.py +1410 -0
- dask_array/_broadcast.py +272 -0
- dask_array/_chunk.py +445 -0
- dask_array/_chunk_types.py +54 -0
- dask_array/_collection.py +1644 -0
- dask_array/_concatenate.py +331 -0
- dask_array/_core_utils.py +1365 -0
- dask_array/_dispatch.py +141 -0
- dask_array/_einsum.py +277 -0
- dask_array/_expr.py +544 -0
- dask_array/_expr_flow.py +586 -0
- dask_array/_gufunc.py +805 -0
- dask_array/_histogram.py +617 -0
- dask_array/_map_blocks.py +652 -0
- dask_array/_new_collection.py +10 -0
- dask_array/_numpy_compat.py +135 -0
- dask_array/_overlap.py +1159 -0
- dask_array/_rechunk.py +1050 -0
- dask_array/_reshape.py +710 -0
- dask_array/_routines.py +102 -0
- dask_array/_shuffle.py +448 -0
- dask_array/_stack.py +264 -0
- dask_array/_svg.py +291 -0
- dask_array/_templates.py +29 -0
- dask_array/_test_utils.py +257 -0
- dask_array/_ufunc.py +385 -0
- dask_array/_utils.py +349 -0
- dask_array/_visualize.py +223 -0
- dask_array/_xarray.py +337 -0
- dask_array/core/__init__.py +34 -0
- dask_array/core/_blockwise_funcs.py +312 -0
- dask_array/core/_conversion.py +422 -0
- dask_array/core/_from_graph.py +97 -0
- dask_array/creation/__init__.py +71 -0
- dask_array/creation/_arange.py +121 -0
- dask_array/creation/_diag.py +116 -0
- dask_array/creation/_diagonal.py +241 -0
- dask_array/creation/_eye.py +103 -0
- dask_array/creation/_linspace.py +102 -0
- dask_array/creation/_mesh.py +134 -0
- dask_array/creation/_ones_zeros.py +454 -0
- dask_array/creation/_pad.py +270 -0
- dask_array/creation/_repeat.py +55 -0
- dask_array/creation/_tile.py +36 -0
- dask_array/creation/_tri.py +28 -0
- dask_array/creation/_utils.py +296 -0
- dask_array/fft.py +320 -0
- dask_array/io/__init__.py +39 -0
- dask_array/io/_base.py +10 -0
- dask_array/io/_from_array.py +257 -0
- dask_array/io/_from_delayed.py +95 -0
- dask_array/io/_from_graph.py +54 -0
- dask_array/io/_from_npy_stack.py +67 -0
- dask_array/io/_store.py +336 -0
- dask_array/io/_tiledb.py +159 -0
- dask_array/io/_to_npy_stack.py +65 -0
- dask_array/io/_zarr.py +449 -0
- dask_array/linalg/__init__.py +39 -0
- dask_array/linalg/_cholesky.py +234 -0
- dask_array/linalg/_lu.py +300 -0
- dask_array/linalg/_norm.py +94 -0
- dask_array/linalg/_qr.py +601 -0
- dask_array/linalg/_solve.py +349 -0
- dask_array/linalg/_svd.py +394 -0
- dask_array/linalg/_tensordot.py +334 -0
- dask_array/linalg/_utils.py +74 -0
- dask_array/manipulation/__init__.py +45 -0
- dask_array/manipulation/_expand.py +321 -0
- dask_array/manipulation/_flip.py +92 -0
- dask_array/manipulation/_roll.py +78 -0
- dask_array/manipulation/_transpose.py +309 -0
- dask_array/random/__init__.py +125 -0
- dask_array/random/_choice.py +181 -0
- dask_array/random/_expr.py +256 -0
- dask_array/random/_generator.py +441 -0
- dask_array/random/_random_state.py +259 -0
- dask_array/random/_utils.py +84 -0
- dask_array/reductions/__init__.py +84 -0
- dask_array/reductions/_arg_reduction.py +130 -0
- dask_array/reductions/_common.py +1082 -0
- dask_array/reductions/_cumulative.py +522 -0
- dask_array/reductions/_percentile.py +261 -0
- dask_array/reductions/_reduction.py +725 -0
- dask_array/reductions/_trace.py +56 -0
- dask_array/routines/__init__.py +133 -0
- dask_array/routines/_apply.py +84 -0
- dask_array/routines/_bincount.py +112 -0
- dask_array/routines/_broadcast.py +111 -0
- dask_array/routines/_coarsen.py +115 -0
- dask_array/routines/_diff.py +79 -0
- dask_array/routines/_gradient.py +158 -0
- dask_array/routines/_indexing.py +65 -0
- dask_array/routines/_insert_delete.py +132 -0
- dask_array/routines/_misc.py +122 -0
- dask_array/routines/_nonzero.py +72 -0
- dask_array/routines/_search.py +123 -0
- dask_array/routines/_select.py +113 -0
- dask_array/routines/_statistics.py +171 -0
- dask_array/routines/_topk.py +82 -0
- dask_array/routines/_triangular.py +74 -0
- dask_array/routines/_unique.py +232 -0
- dask_array/routines/_where.py +62 -0
- dask_array/slicing/__init__.py +67 -0
- dask_array/slicing/_basic.py +550 -0
- dask_array/slicing/_blocks.py +138 -0
- dask_array/slicing/_bool_index.py +145 -0
- dask_array/slicing/_setitem.py +329 -0
- dask_array/slicing/_squeeze.py +101 -0
- dask_array/slicing/_utils.py +1133 -0
- dask_array/slicing/_vindex.py +282 -0
- dask_array/stacking/__init__.py +15 -0
- dask_array/stacking/_block.py +83 -0
- dask_array/stacking/_simple.py +58 -0
- dask_array/templates/array.html.j2 +48 -0
- dask_array/tests/__init__.py +0 -0
- dask_array/tests/conftest.py +22 -0
- dask_array/tests/test_api.py +40 -0
- dask_array/tests/test_binary_op_chunks.py +107 -0
- dask_array/tests/test_coarse_slice_through_blockwise.py +362 -0
- dask_array/tests/test_collection.py +799 -0
- dask_array/tests/test_creation.py +1102 -0
- dask_array/tests/test_expr_flow.py +143 -0
- dask_array/tests/test_linalg.py +1130 -0
- dask_array/tests/test_map_blocks_multi_output.py +104 -0
- dask_array/tests/test_rechunk_pushdown.py +214 -0
- dask_array/tests/test_reductions.py +1091 -0
- dask_array/tests/test_routines.py +2853 -0
- dask_array/tests/test_shuffle_chunks.py +67 -0
- dask_array/tests/test_slice_pushdown.py +968 -0
- dask_array/tests/test_slice_through_blockwise.py +678 -0
- dask_array/tests/test_slice_through_overlap.py +366 -0
- dask_array/tests/test_slice_through_reshape.py +272 -0
- dask_array/tests/test_slicing.py +839 -0
- dask_array/tests/test_transpose_slice_pushdown.py +208 -0
- dask_array/tests/test_visualize.py +94 -0
- dask_array/tests/test_xarray.py +193 -0
- dask_array-0.1.0.dist-info/METADATA +48 -0
- dask_array-0.1.0.dist-info/RECORD +144 -0
- dask_array-0.1.0.dist-info/WHEEL +4 -0
- dask_array-0.1.0.dist-info/entry_points.txt +2 -0
- dask_array-0.1.0.dist-info/licenses/LICENSE +29 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import operator
|
|
5
|
+
from functools import partial
|
|
6
|
+
from itertools import product
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from dask_array._new_collection import new_collection
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Local implementations of merge/scan functions (copied from dask.array.reductions)
|
|
14
|
+
def _cumsum_merge(a, b):
|
|
15
|
+
if isinstance(a, np.ma.masked_array) or isinstance(b, np.ma.masked_array):
|
|
16
|
+
values = np.ma.getdata(a) + np.ma.getdata(b)
|
|
17
|
+
return np.ma.masked_array(values, mask=np.ma.getmaskarray(b))
|
|
18
|
+
return a + b
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _cumprod_merge(a, b):
|
|
22
|
+
if isinstance(a, np.ma.masked_array) or isinstance(b, np.ma.masked_array):
|
|
23
|
+
values = np.ma.getdata(a) * np.ma.getdata(b)
|
|
24
|
+
return np.ma.masked_array(values, mask=np.ma.getmaskarray(b))
|
|
25
|
+
return a * b
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _prefixscan_first(func, x, axis, dtype):
|
|
29
|
+
"""Compute the prefix scan (e.g., cumsum) on the first block."""
|
|
30
|
+
return func(x, axis=axis, dtype=dtype)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _prefixscan_combine(func, binop, pre, x, axis, dtype):
|
|
34
|
+
"""Combine results of a parallel prefix scan such as cumsum.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
func : callable
|
|
39
|
+
Cumulative function (e.g. ``np.cumsum``)
|
|
40
|
+
binop : callable
|
|
41
|
+
Associative function (e.g. ``add``)
|
|
42
|
+
pre : np.array
|
|
43
|
+
The value calculated in parallel from ``preop``.
|
|
44
|
+
For example, the sum of all the previous blocks.
|
|
45
|
+
x : np.array
|
|
46
|
+
Current block
|
|
47
|
+
axis : int
|
|
48
|
+
dtype : dtype
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
np.array
|
|
53
|
+
"""
|
|
54
|
+
return binop(pre, func(x, axis=axis, dtype=dtype))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
from dask_array._expr import ArrayExpr
|
|
58
|
+
from dask_array._utils import validate_axis
|
|
59
|
+
from dask.tokenize import _tokenize_deterministic
|
|
60
|
+
from dask.utils import cached_property, funcname
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _prepare_cumulative(x, axis):
|
|
64
|
+
"""Prepare array for cumulative reduction.
|
|
65
|
+
|
|
66
|
+
When axis=None, flatten and rechunk the array to a 1D array with
|
|
67
|
+
npartitions chunks, then set axis=0.
|
|
68
|
+
|
|
69
|
+
Returns (array, axis) tuple.
|
|
70
|
+
"""
|
|
71
|
+
from dask_array._collection import Array
|
|
72
|
+
|
|
73
|
+
if not isinstance(x, Array):
|
|
74
|
+
from dask_array.core._conversion import asarray
|
|
75
|
+
|
|
76
|
+
x = asarray(x)
|
|
77
|
+
|
|
78
|
+
if axis is None:
|
|
79
|
+
if x.ndim > 1:
|
|
80
|
+
x = x.flatten().rechunk(chunks=x.npartitions)
|
|
81
|
+
axis = 0
|
|
82
|
+
|
|
83
|
+
return x, axis
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class CumReduction(ArrayExpr):
|
|
87
|
+
"""Expression for cumulative reductions (cumsum, cumprod, etc.).
|
|
88
|
+
|
|
89
|
+
Uses the sequential algorithm: apply the cumulative function to each block,
|
|
90
|
+
then combine blocks by adding the last element of previous blocks.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
_parameters = ["array", "func", "binop", "ident", "axis", "_dtype"]
|
|
94
|
+
_defaults = {"_dtype": None}
|
|
95
|
+
|
|
96
|
+
@cached_property
|
|
97
|
+
def _name(self):
|
|
98
|
+
return f"{funcname(self.func)}-{_tokenize_deterministic(*self.operands)}"
|
|
99
|
+
|
|
100
|
+
@cached_property
|
|
101
|
+
def dtype(self):
|
|
102
|
+
if self._dtype is not None:
|
|
103
|
+
return np.dtype(self._dtype)
|
|
104
|
+
# Infer dtype from the function
|
|
105
|
+
return getattr(self.func(np.ones((0,), dtype=self.array.dtype)), "dtype", object)
|
|
106
|
+
|
|
107
|
+
@cached_property
|
|
108
|
+
def _meta(self):
|
|
109
|
+
# Return meta with the correct dtype
|
|
110
|
+
meta = self.array._meta
|
|
111
|
+
if hasattr(meta, "dtype") and meta.dtype != self.dtype:
|
|
112
|
+
return meta.astype(self.dtype)
|
|
113
|
+
return meta
|
|
114
|
+
|
|
115
|
+
@cached_property
|
|
116
|
+
def chunks(self):
|
|
117
|
+
return self.array.chunks
|
|
118
|
+
|
|
119
|
+
def _layer(self):
|
|
120
|
+
from functools import partial
|
|
121
|
+
|
|
122
|
+
from dask.utils import apply
|
|
123
|
+
|
|
124
|
+
x = self.array
|
|
125
|
+
axis = self.axis
|
|
126
|
+
func = self.func
|
|
127
|
+
binop = self.binop
|
|
128
|
+
ident = self.ident
|
|
129
|
+
dtype = self.dtype
|
|
130
|
+
|
|
131
|
+
# Apply cumulative function to each block
|
|
132
|
+
# We'll use a two-phase approach:
|
|
133
|
+
# 1. First, apply the cumulative function to each block (via map_blocks expression)
|
|
134
|
+
# 2. Then, build the correction tasks that add previous block totals
|
|
135
|
+
|
|
136
|
+
dsk = {}
|
|
137
|
+
|
|
138
|
+
# Phase 1: Apply cumulative function per block
|
|
139
|
+
# We create intermediate keys for the per-block cumulative results
|
|
140
|
+
per_block_name = self._name + "-chunk"
|
|
141
|
+
|
|
142
|
+
# Determine if we need to pass dtype to the function
|
|
143
|
+
use_dtype = False
|
|
144
|
+
try:
|
|
145
|
+
import inspect
|
|
146
|
+
|
|
147
|
+
func_params = inspect.signature(func).parameters
|
|
148
|
+
use_dtype = "dtype" in func_params
|
|
149
|
+
except ValueError:
|
|
150
|
+
try:
|
|
151
|
+
# Workaround for numpy ufunc.accumulate
|
|
152
|
+
if isinstance(func.__self__, np.ufunc) and func.__name__ == "accumulate":
|
|
153
|
+
use_dtype = True
|
|
154
|
+
except AttributeError:
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
# Create per-block cumulative tasks
|
|
158
|
+
for key in product(*map(range, x.numblocks)):
|
|
159
|
+
if use_dtype:
|
|
160
|
+
dsk[(per_block_name,) + key] = (
|
|
161
|
+
partial(func, axis=axis, dtype=dtype),
|
|
162
|
+
(x.name,) + key,
|
|
163
|
+
)
|
|
164
|
+
else:
|
|
165
|
+
dsk[(per_block_name,) + key] = (
|
|
166
|
+
partial(func, axis=axis),
|
|
167
|
+
(x.name,) + key,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Phase 2: Build the sequential combination
|
|
171
|
+
n = x.numblocks[axis]
|
|
172
|
+
full = slice(None, None, None)
|
|
173
|
+
slc = (full,) * axis + (slice(-1, None),) + (full,) * (x.ndim - axis - 1)
|
|
174
|
+
|
|
175
|
+
# For each position along the axis, we need to track the cumulative
|
|
176
|
+
# last values from all previous blocks
|
|
177
|
+
indices = list(product(*[range(nb) if i != axis else [0] for i, nb in enumerate(x.numblocks)]))
|
|
178
|
+
|
|
179
|
+
# Initialize "extra" values (cumulative sums of previous blocks) to identity
|
|
180
|
+
for ind in indices:
|
|
181
|
+
shape = tuple(x.chunks[i][ii] if i != axis else 1 for i, ii in enumerate(ind))
|
|
182
|
+
dsk[(self._name, "extra") + ind] = (
|
|
183
|
+
apply,
|
|
184
|
+
np.full_like,
|
|
185
|
+
(x._meta, ident, dtype),
|
|
186
|
+
{"shape": shape},
|
|
187
|
+
)
|
|
188
|
+
# First block along axis: just use per-block result
|
|
189
|
+
dsk[(self._name,) + ind] = (per_block_name,) + ind
|
|
190
|
+
|
|
191
|
+
# For subsequent blocks, add the cumulative total from previous blocks
|
|
192
|
+
for i in range(1, n):
|
|
193
|
+
last_indices = indices
|
|
194
|
+
indices = list(product(*[range(nb) if ii != axis else [i] for ii, nb in enumerate(x.numblocks)]))
|
|
195
|
+
for old, ind in zip(last_indices, indices):
|
|
196
|
+
this_extra = (self._name, "extra") + ind
|
|
197
|
+
# Combine previous extra with the last element of the previous block
|
|
198
|
+
dsk[this_extra] = (
|
|
199
|
+
binop,
|
|
200
|
+
(self._name, "extra") + old,
|
|
201
|
+
(operator.getitem, (per_block_name,) + old, slc),
|
|
202
|
+
)
|
|
203
|
+
# Add the extra to this block's result
|
|
204
|
+
dsk[(self._name,) + ind] = (
|
|
205
|
+
binop,
|
|
206
|
+
this_extra,
|
|
207
|
+
(per_block_name,) + ind,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return dsk
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class CumReductionBlelloch(ArrayExpr):
|
|
214
|
+
"""Expression for parallel cumulative reductions using Blelloch's algorithm.
|
|
215
|
+
|
|
216
|
+
This is a work-efficient parallel scan that uses O(log n) parallel steps.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
_parameters = ["array", "func", "preop", "binop", "axis", "_dtype"]
|
|
220
|
+
_defaults = {"_dtype": None}
|
|
221
|
+
|
|
222
|
+
@cached_property
|
|
223
|
+
def _name(self):
|
|
224
|
+
return f"{funcname(self.func)}-{_tokenize_deterministic(*self.operands)}"
|
|
225
|
+
|
|
226
|
+
@cached_property
|
|
227
|
+
def dtype(self):
|
|
228
|
+
if self._dtype is not None:
|
|
229
|
+
return np.dtype(self._dtype)
|
|
230
|
+
return getattr(self.func(np.ones((0,), dtype=self.array.dtype)), "dtype", object)
|
|
231
|
+
|
|
232
|
+
@cached_property
|
|
233
|
+
def _meta(self):
|
|
234
|
+
# Return meta with the correct dtype
|
|
235
|
+
meta = self.array._meta
|
|
236
|
+
if hasattr(meta, "dtype") and meta.dtype != self.dtype:
|
|
237
|
+
return meta.astype(self.dtype)
|
|
238
|
+
return meta
|
|
239
|
+
|
|
240
|
+
@cached_property
|
|
241
|
+
def chunks(self):
|
|
242
|
+
return self.array.chunks
|
|
243
|
+
|
|
244
|
+
def _layer(self):
|
|
245
|
+
import builtins as py_builtins
|
|
246
|
+
|
|
247
|
+
x = self.array
|
|
248
|
+
axis = self.axis
|
|
249
|
+
func = self.func
|
|
250
|
+
preop = self.preop
|
|
251
|
+
binop = self.binop
|
|
252
|
+
dtype = self.dtype
|
|
253
|
+
base_key = (self._name,)
|
|
254
|
+
|
|
255
|
+
dsk = {}
|
|
256
|
+
|
|
257
|
+
# Phase 1: Compute prefix values (sum/product of each block)
|
|
258
|
+
batches_name = self._name + "-batch"
|
|
259
|
+
for key in product(*map(range, x.numblocks)):
|
|
260
|
+
dsk[(batches_name,) + key] = (
|
|
261
|
+
partial(preop, axis=axis, keepdims=True),
|
|
262
|
+
(x.name,) + key,
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Build indices for each position along the axis
|
|
266
|
+
full_indices = [
|
|
267
|
+
list(product(*[range(nb) if j != axis else [i] for j, nb in enumerate(x.numblocks)]))
|
|
268
|
+
for i in range(x.numblocks[axis])
|
|
269
|
+
]
|
|
270
|
+
|
|
271
|
+
if not full_indices:
|
|
272
|
+
return dsk
|
|
273
|
+
|
|
274
|
+
*indices, last_index = full_indices
|
|
275
|
+
prefix_vals = [[(batches_name,) + index for index in vals] for vals in indices]
|
|
276
|
+
|
|
277
|
+
n_vals = len(prefix_vals)
|
|
278
|
+
level = 0
|
|
279
|
+
|
|
280
|
+
if n_vals >= 2:
|
|
281
|
+
# Upsweep
|
|
282
|
+
stride = 1
|
|
283
|
+
stride2 = 2
|
|
284
|
+
while stride2 <= n_vals:
|
|
285
|
+
for i in range(stride2 - 1, n_vals, stride2):
|
|
286
|
+
new_vals = []
|
|
287
|
+
for index, left_val, right_val in zip(indices[i], prefix_vals[i - stride], prefix_vals[i]):
|
|
288
|
+
key = base_key + index + (level, i)
|
|
289
|
+
dsk[key] = (binop, left_val, right_val)
|
|
290
|
+
new_vals.append(key)
|
|
291
|
+
prefix_vals[i] = new_vals
|
|
292
|
+
stride = stride2
|
|
293
|
+
stride2 *= 2
|
|
294
|
+
level += 1
|
|
295
|
+
|
|
296
|
+
# Downsweep
|
|
297
|
+
stride2 = py_builtins.max(2, 2 ** math.ceil(math.log2(n_vals // 2)))
|
|
298
|
+
stride = stride2 // 2
|
|
299
|
+
while stride > 0:
|
|
300
|
+
for i in range(stride2 + stride - 1, n_vals, stride2):
|
|
301
|
+
new_vals = []
|
|
302
|
+
for index, left_val, right_val in zip(indices[i], prefix_vals[i - stride], prefix_vals[i]):
|
|
303
|
+
key = base_key + index + (level, i)
|
|
304
|
+
dsk[key] = (binop, left_val, right_val)
|
|
305
|
+
new_vals.append(key)
|
|
306
|
+
prefix_vals[i] = new_vals
|
|
307
|
+
stride2 = stride
|
|
308
|
+
stride //= 2
|
|
309
|
+
level += 1
|
|
310
|
+
|
|
311
|
+
# Phase 2: Apply cumulative function and combine with prefix sums
|
|
312
|
+
# First blocks: just apply the cumulative function
|
|
313
|
+
for index in full_indices[0]:
|
|
314
|
+
dsk[base_key + index] = (
|
|
315
|
+
_prefixscan_first,
|
|
316
|
+
func,
|
|
317
|
+
(x.name,) + index,
|
|
318
|
+
axis,
|
|
319
|
+
dtype,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
# Remaining blocks: apply cumulative function and add prefix sum
|
|
323
|
+
for indexes, vals in zip(full_indices[1:], prefix_vals):
|
|
324
|
+
for index, val in zip(indexes, vals):
|
|
325
|
+
dsk[base_key + index] = (
|
|
326
|
+
_prefixscan_combine,
|
|
327
|
+
func,
|
|
328
|
+
binop,
|
|
329
|
+
val,
|
|
330
|
+
(x.name,) + index,
|
|
331
|
+
axis,
|
|
332
|
+
dtype,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
return dsk
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _cumreduction_expr(func, binop, ident, x, axis, dtype, out, method, preop):
|
|
339
|
+
"""Create cumulative reduction expression."""
|
|
340
|
+
from dask_array._collection import Array
|
|
341
|
+
from dask_array.core._blockwise_funcs import _handle_out
|
|
342
|
+
|
|
343
|
+
if not isinstance(x, Array):
|
|
344
|
+
from dask_array.core._conversion import asarray
|
|
345
|
+
|
|
346
|
+
x = asarray(x)
|
|
347
|
+
|
|
348
|
+
x, axis = _prepare_cumulative(x, axis)
|
|
349
|
+
axis = validate_axis(axis, x.ndim)
|
|
350
|
+
|
|
351
|
+
if method == "blelloch":
|
|
352
|
+
if preop is None:
|
|
353
|
+
raise TypeError('cumreduction with "blelloch" method requires `preop=` argument')
|
|
354
|
+
expr = CumReductionBlelloch(x.expr, func, preop, binop, axis, dtype)
|
|
355
|
+
elif method == "sequential":
|
|
356
|
+
expr = CumReduction(x.expr, func, binop, ident, axis, dtype)
|
|
357
|
+
else:
|
|
358
|
+
raise ValueError(f'Invalid method for cumreduction. Expected "sequential" or "blelloch". Got: {method!r}')
|
|
359
|
+
|
|
360
|
+
result = new_collection(expr)
|
|
361
|
+
return _handle_out(out, result)
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def cumsum(x, axis=None, dtype=None, out=None, method="sequential"):
|
|
365
|
+
"""Return the cumulative sum of the elements along a given axis.
|
|
366
|
+
|
|
367
|
+
Parameters
|
|
368
|
+
----------
|
|
369
|
+
x : array_like
|
|
370
|
+
Input array.
|
|
371
|
+
axis : int, optional
|
|
372
|
+
Axis along which the cumulative sum is computed. The default
|
|
373
|
+
(None) is to compute the cumsum over the flattened array.
|
|
374
|
+
dtype : dtype, optional
|
|
375
|
+
Type of the returned array and of the accumulator in which the
|
|
376
|
+
elements are summed.
|
|
377
|
+
out : ndarray, optional
|
|
378
|
+
Not implemented for Dask arrays.
|
|
379
|
+
method : {'sequential', 'blelloch'}, optional
|
|
380
|
+
Algorithm to use for the cumulative sum. Default is 'sequential'.
|
|
381
|
+
|
|
382
|
+
Returns
|
|
383
|
+
-------
|
|
384
|
+
cumsum_along_axis : dask array
|
|
385
|
+
A new array holding the result.
|
|
386
|
+
"""
|
|
387
|
+
return _cumreduction_expr(
|
|
388
|
+
np.cumsum,
|
|
389
|
+
_cumsum_merge,
|
|
390
|
+
0,
|
|
391
|
+
x,
|
|
392
|
+
axis,
|
|
393
|
+
dtype,
|
|
394
|
+
out=out,
|
|
395
|
+
method=method,
|
|
396
|
+
preop=np.sum,
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def cumprod(x, axis=None, dtype=None, out=None, method="sequential"):
|
|
401
|
+
"""Return the cumulative product of elements along a given axis.
|
|
402
|
+
|
|
403
|
+
Parameters
|
|
404
|
+
----------
|
|
405
|
+
x : array_like
|
|
406
|
+
Input array.
|
|
407
|
+
axis : int, optional
|
|
408
|
+
Axis along which the cumulative product is computed. The default
|
|
409
|
+
(None) is to compute the cumprod over the flattened array.
|
|
410
|
+
dtype : dtype, optional
|
|
411
|
+
Type of the returned array and of the accumulator in which the
|
|
412
|
+
elements are multiplied.
|
|
413
|
+
out : ndarray, optional
|
|
414
|
+
Not implemented for Dask arrays.
|
|
415
|
+
method : {'sequential', 'blelloch'}, optional
|
|
416
|
+
Algorithm to use for the cumulative product. Default is 'sequential'.
|
|
417
|
+
|
|
418
|
+
Returns
|
|
419
|
+
-------
|
|
420
|
+
cumprod_along_axis : dask array
|
|
421
|
+
A new array holding the result.
|
|
422
|
+
"""
|
|
423
|
+
return _cumreduction_expr(
|
|
424
|
+
np.cumprod,
|
|
425
|
+
_cumprod_merge,
|
|
426
|
+
1,
|
|
427
|
+
x,
|
|
428
|
+
axis,
|
|
429
|
+
dtype,
|
|
430
|
+
out=out,
|
|
431
|
+
method=method,
|
|
432
|
+
preop=np.prod,
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
def nancumsum(x, axis, dtype=None, out=None, *, method="sequential"):
|
|
437
|
+
"""Return the cumulative sum of array elements treating NaNs as zero.
|
|
438
|
+
|
|
439
|
+
Parameters
|
|
440
|
+
----------
|
|
441
|
+
x : array_like
|
|
442
|
+
Input array.
|
|
443
|
+
axis : int
|
|
444
|
+
Axis along which the cumulative sum is computed.
|
|
445
|
+
dtype : dtype, optional
|
|
446
|
+
Type of the returned array and of the accumulator in which the
|
|
447
|
+
elements are summed.
|
|
448
|
+
out : ndarray, optional
|
|
449
|
+
Not implemented for Dask arrays.
|
|
450
|
+
method : {'sequential', 'blelloch'}, optional
|
|
451
|
+
Algorithm to use for the cumulative sum. Default is 'sequential'.
|
|
452
|
+
|
|
453
|
+
Returns
|
|
454
|
+
-------
|
|
455
|
+
nancumsum_along_axis : dask array
|
|
456
|
+
A new array holding the result.
|
|
457
|
+
"""
|
|
458
|
+
from dask_array import _chunk as chunk_module
|
|
459
|
+
|
|
460
|
+
return _cumreduction_expr(
|
|
461
|
+
chunk_module.nancumsum,
|
|
462
|
+
operator.add,
|
|
463
|
+
0,
|
|
464
|
+
x,
|
|
465
|
+
axis,
|
|
466
|
+
dtype,
|
|
467
|
+
out=out,
|
|
468
|
+
method=method,
|
|
469
|
+
preop=np.nansum,
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def nancumprod(x, axis, dtype=None, out=None, *, method="sequential"):
|
|
474
|
+
"""Return the cumulative product of array elements treating NaNs as one.
|
|
475
|
+
|
|
476
|
+
Parameters
|
|
477
|
+
----------
|
|
478
|
+
x : array_like
|
|
479
|
+
Input array.
|
|
480
|
+
axis : int
|
|
481
|
+
Axis along which the cumulative product is computed.
|
|
482
|
+
dtype : dtype, optional
|
|
483
|
+
Type of the returned array and of the accumulator in which the
|
|
484
|
+
elements are multiplied.
|
|
485
|
+
out : ndarray, optional
|
|
486
|
+
Not implemented for Dask arrays.
|
|
487
|
+
method : {'sequential', 'blelloch'}, optional
|
|
488
|
+
Algorithm to use for the cumulative product. Default is 'sequential'.
|
|
489
|
+
|
|
490
|
+
Returns
|
|
491
|
+
-------
|
|
492
|
+
nancumprod_along_axis : dask array
|
|
493
|
+
A new array holding the result.
|
|
494
|
+
"""
|
|
495
|
+
from dask_array import _chunk as chunk_module
|
|
496
|
+
|
|
497
|
+
return _cumreduction_expr(
|
|
498
|
+
chunk_module.nancumprod,
|
|
499
|
+
operator.mul,
|
|
500
|
+
1,
|
|
501
|
+
x,
|
|
502
|
+
axis,
|
|
503
|
+
dtype,
|
|
504
|
+
out=out,
|
|
505
|
+
method=method,
|
|
506
|
+
preop=np.nanprod,
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def cumreduction(
|
|
511
|
+
func,
|
|
512
|
+
binop,
|
|
513
|
+
ident,
|
|
514
|
+
x,
|
|
515
|
+
axis=None,
|
|
516
|
+
dtype=None,
|
|
517
|
+
out=None,
|
|
518
|
+
method="sequential",
|
|
519
|
+
preop=None,
|
|
520
|
+
):
|
|
521
|
+
"""Generic cumulative reduction. See dask.array.reductions.cumreduction."""
|
|
522
|
+
return _cumreduction_expr(func, binop, ident, x, axis, dtype, out=out, method=method, preop=preop)
|