pyopencl 2025.2.1__cp310-cp310-macosx_11_0_arm64.whl → 2025.2.2__cp310-cp310-macosx_11_0_arm64.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.
Potentially problematic release.
This version of pyopencl might be problematic. Click here for more details.
- pyopencl/__init__.py +16 -2
- pyopencl/array.py +276 -234
- pyopencl/compyte/.basedpyright/baseline.json +1272 -0
- pyopencl/compyte/array.py +33 -6
- pyopencl/compyte/dtypes.py +39 -13
- pyopencl/compyte/pyproject.toml +15 -0
- pyopencl/reduction.py +55 -28
- pyopencl/typing.py +7 -2
- {pyopencl-2025.2.1.dist-info → pyopencl-2025.2.2.dist-info}/METADATA +1 -1
- {pyopencl-2025.2.1.dist-info → pyopencl-2025.2.2.dist-info}/RECORD +12 -11
- {pyopencl-2025.2.1.dist-info → pyopencl-2025.2.2.dist-info}/WHEEL +0 -0
- {pyopencl-2025.2.1.dist-info → pyopencl-2025.2.2.dist-info}/licenses/LICENSE +0 -0
pyopencl/array.py
CHANGED
|
@@ -34,14 +34,22 @@ import builtins
|
|
|
34
34
|
from dataclasses import dataclass
|
|
35
35
|
from functools import reduce
|
|
36
36
|
from numbers import Number
|
|
37
|
-
from typing import
|
|
37
|
+
from typing import (
|
|
38
|
+
TYPE_CHECKING,
|
|
39
|
+
Any,
|
|
40
|
+
ClassVar,
|
|
41
|
+
Concatenate,
|
|
42
|
+
Literal,
|
|
43
|
+
ParamSpec,
|
|
44
|
+
cast,
|
|
45
|
+
)
|
|
38
46
|
from warnings import warn
|
|
39
47
|
|
|
40
48
|
import numpy as np
|
|
49
|
+
from typing_extensions import Self, override
|
|
41
50
|
|
|
42
51
|
import pyopencl as cl
|
|
43
52
|
import pyopencl.elementwise as elementwise
|
|
44
|
-
import pyopencl.tools as cl_tools
|
|
45
53
|
from pyopencl import cltypes
|
|
46
54
|
from pyopencl.characterize import has_double_support
|
|
47
55
|
from pyopencl.compyte.array import (
|
|
@@ -53,6 +61,14 @@ from pyopencl.compyte.array import (
|
|
|
53
61
|
)
|
|
54
62
|
|
|
55
63
|
|
|
64
|
+
if TYPE_CHECKING:
|
|
65
|
+
from collections.abc import Callable, Hashable
|
|
66
|
+
|
|
67
|
+
from numpy.typing import DTypeLike, NDArray
|
|
68
|
+
|
|
69
|
+
from pyopencl.typing import Allocator
|
|
70
|
+
|
|
71
|
+
|
|
56
72
|
SCALAR_CLASSES = (Number, np.bool_, bool)
|
|
57
73
|
|
|
58
74
|
if cl.get_cl_header_version() >= (2, 0):
|
|
@@ -61,6 +77,10 @@ else:
|
|
|
61
77
|
_SVMPointer_or_nothing = ()
|
|
62
78
|
|
|
63
79
|
|
|
80
|
+
class _NoValue:
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
|
|
64
84
|
# {{{ _get_common_dtype
|
|
65
85
|
|
|
66
86
|
class DoubleDowncastWarning(UserWarning):
|
|
@@ -163,7 +183,11 @@ vec = VecLookupWarner()
|
|
|
163
183
|
|
|
164
184
|
# {{{ helper functionality
|
|
165
185
|
|
|
166
|
-
def _splay(
|
|
186
|
+
def _splay(
|
|
187
|
+
device: cl.Device,
|
|
188
|
+
n: int,
|
|
189
|
+
kernel_specific_max_wg_size: int | None = None,
|
|
190
|
+
):
|
|
167
191
|
max_work_items = builtins.min(128, device.max_work_group_size)
|
|
168
192
|
|
|
169
193
|
if kernel_specific_max_wg_size is not None:
|
|
@@ -198,7 +222,12 @@ def _splay(device, n, kernel_specific_max_wg_size=None):
|
|
|
198
222
|
ARRAY_KERNEL_EXEC_HOOK = None
|
|
199
223
|
|
|
200
224
|
|
|
201
|
-
|
|
225
|
+
P = ParamSpec("P")
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def elwise_kernel_runner(
|
|
229
|
+
kernel_getter: Callable[Concatenate[Array, P], cl.Kernel]
|
|
230
|
+
) -> Callable[Concatenate[Array, P], cl.Event]:
|
|
202
231
|
"""Take a kernel getter of the same signature as the kernel
|
|
203
232
|
and return a function that invokes that kernel.
|
|
204
233
|
|
|
@@ -207,40 +236,31 @@ def elwise_kernel_runner(kernel_getter):
|
|
|
207
236
|
from functools import wraps
|
|
208
237
|
|
|
209
238
|
@wraps(kernel_getter)
|
|
210
|
-
def kernel_runner(out, *args, **kwargs):
|
|
239
|
+
def kernel_runner(out: Array, *args: P.args, **kwargs: P.kwargs) -> cl.Event:
|
|
211
240
|
assert isinstance(out, Array)
|
|
212
241
|
|
|
213
|
-
wait_for = kwargs.pop("wait_for", None)
|
|
214
|
-
queue = kwargs.pop("queue", None)
|
|
242
|
+
wait_for = cast("cl.WaitList", kwargs.pop("wait_for", None))
|
|
243
|
+
queue = cast("cl.CommandQueue | None", kwargs.pop("queue", None))
|
|
215
244
|
if queue is None:
|
|
216
245
|
queue = out.queue
|
|
217
246
|
|
|
218
247
|
assert queue is not None
|
|
219
248
|
|
|
220
249
|
knl = kernel_getter(out, *args, **kwargs)
|
|
221
|
-
work_group_info = knl.get_work_group_info(
|
|
250
|
+
work_group_info = cast("int", knl.get_work_group_info(
|
|
222
251
|
cl.kernel_work_group_info.WORK_GROUP_SIZE,
|
|
223
|
-
queue.device)
|
|
252
|
+
queue.device))
|
|
224
253
|
gs, ls = out._get_sizes(queue, work_group_info)
|
|
225
254
|
|
|
226
|
-
|
|
255
|
+
knl_args = (out, *args, out.size)
|
|
227
256
|
if ARRAY_KERNEL_EXEC_HOOK is not None:
|
|
228
257
|
return ARRAY_KERNEL_EXEC_HOOK( # pylint: disable=not-callable
|
|
229
|
-
knl, queue, gs, ls, *
|
|
258
|
+
knl, queue, gs, ls, *knl_args, wait_for=wait_for)
|
|
230
259
|
else:
|
|
231
|
-
return knl(queue, gs, ls, *
|
|
260
|
+
return knl(queue, gs, ls, *knl_args, wait_for=wait_for)
|
|
232
261
|
|
|
233
262
|
return kernel_runner
|
|
234
263
|
|
|
235
|
-
|
|
236
|
-
class DefaultAllocator(cl_tools.DeferredAllocator):
|
|
237
|
-
def __init__(self, *args, **kwargs):
|
|
238
|
-
warn("pyopencl.array.DefaultAllocator is deprecated. "
|
|
239
|
-
"It will be continue to exist throughout the 2013.x "
|
|
240
|
-
"versions of PyOpenCL.",
|
|
241
|
-
DeprecationWarning, stacklevel=2)
|
|
242
|
-
cl_tools.DeferredAllocator.__init__(self, *args, **kwargs)
|
|
243
|
-
|
|
244
264
|
# }}}
|
|
245
265
|
|
|
246
266
|
|
|
@@ -265,7 +285,8 @@ class _copy_queue: # noqa: N801
|
|
|
265
285
|
pass
|
|
266
286
|
|
|
267
287
|
|
|
268
|
-
_ARRAY_GET_SIZES_CACHE:
|
|
288
|
+
_ARRAY_GET_SIZES_CACHE: \
|
|
289
|
+
dict[Hashable, tuple[tuple[int, ...], tuple[int, ...]]] = {}
|
|
269
290
|
_BOOL_DTYPE = np.dtype(np.int8)
|
|
270
291
|
_NOT_PRESENT = object()
|
|
271
292
|
|
|
@@ -456,15 +477,25 @@ class Array:
|
|
|
456
477
|
.. automethod:: finish
|
|
457
478
|
"""
|
|
458
479
|
|
|
459
|
-
__array_priority__ = 100
|
|
480
|
+
__array_priority__: ClassVar[int] = 100
|
|
481
|
+
|
|
482
|
+
queue: cl.CommandQueue | None
|
|
483
|
+
shape: tuple[int, ...]
|
|
484
|
+
dtype: np.dtype[Any]
|
|
485
|
+
strides: tuple[int, ...]
|
|
486
|
+
events: list[cl.Event]
|
|
487
|
+
nbytes: int
|
|
488
|
+
size: int
|
|
489
|
+
allocator: Allocator | None
|
|
490
|
+
base_data: cl.MemoryObjectHolder | cl.SVMPointer | None
|
|
460
491
|
|
|
461
492
|
def __init__(
|
|
462
493
|
self,
|
|
463
494
|
cq: cl.Context | cl.CommandQueue | None,
|
|
464
495
|
shape: tuple[int, ...] | int,
|
|
465
|
-
dtype:
|
|
496
|
+
dtype: DTypeLike,
|
|
466
497
|
order: str = "C",
|
|
467
|
-
allocator:
|
|
498
|
+
allocator: Allocator | None = None,
|
|
468
499
|
data: Any = None,
|
|
469
500
|
offset: int = 0,
|
|
470
501
|
strides: tuple[int, ...] | None = None,
|
|
@@ -478,7 +509,7 @@ class Array:
|
|
|
478
509
|
_queue: cl.CommandQueue | None = None) -> None:
|
|
479
510
|
if _fast:
|
|
480
511
|
# Assumptions, should be disabled if not testing
|
|
481
|
-
if
|
|
512
|
+
if TYPE_CHECKING:
|
|
482
513
|
assert cq is None
|
|
483
514
|
assert isinstance(_context, cl.Context)
|
|
484
515
|
assert _queue is None or isinstance(_queue, cl.CommandQueue)
|
|
@@ -651,8 +682,15 @@ class Array:
|
|
|
651
682
|
self._flags = f = _ArrayFlags(self)
|
|
652
683
|
return f
|
|
653
684
|
|
|
654
|
-
def _new_with_changes(self,
|
|
655
|
-
|
|
685
|
+
def _new_with_changes(self,
|
|
686
|
+
data: cl.MemoryObjectHolder | cl.SVMPointer | None,
|
|
687
|
+
offset: int | None,
|
|
688
|
+
shape: tuple[int, ...] | None = None,
|
|
689
|
+
dtype: np.dtype[Any] | None = None,
|
|
690
|
+
strides: tuple[int, ...] | None = None,
|
|
691
|
+
queue: cl.CommandQueue | type[_copy_queue] | None = _copy_queue,
|
|
692
|
+
allocator: Allocator | None = None,
|
|
693
|
+
) -> Self:
|
|
656
694
|
"""
|
|
657
695
|
:arg data: *None* means allocate a new array.
|
|
658
696
|
"""
|
|
@@ -672,6 +710,8 @@ class Array:
|
|
|
672
710
|
queue = self.queue
|
|
673
711
|
if allocator is None:
|
|
674
712
|
allocator = self.allocator
|
|
713
|
+
if offset is None:
|
|
714
|
+
offset = self.offset
|
|
675
715
|
|
|
676
716
|
# If we're allocating new data, then there's not likely to be
|
|
677
717
|
# a data dependency. Otherwise, the two arrays should probably
|
|
@@ -687,7 +727,7 @@ class Array:
|
|
|
687
727
|
events=events,
|
|
688
728
|
_fast=fast, _context=self.context, _queue=queue, _size=size)
|
|
689
729
|
|
|
690
|
-
def with_queue(self, queue):
|
|
730
|
+
def with_queue(self, queue: cl.CommandQueue | None):
|
|
691
731
|
"""Return a copy of *self* with the default queue set to *queue*.
|
|
692
732
|
|
|
693
733
|
*None* is allowed as a value for *queue*.
|
|
@@ -701,7 +741,10 @@ class Array:
|
|
|
701
741
|
return self._new_with_changes(self.base_data, self.offset,
|
|
702
742
|
queue=queue)
|
|
703
743
|
|
|
704
|
-
def _get_sizes(self,
|
|
744
|
+
def _get_sizes(self,
|
|
745
|
+
queue: cl.CommandQueue,
|
|
746
|
+
kernel_specific_max_wg_size: int | None = None
|
|
747
|
+
) -> tuple[tuple[int, ...], tuple[int, ...]]:
|
|
705
748
|
if not self.flags.forc:
|
|
706
749
|
raise NotImplementedError("cannot operate on non-contiguous array")
|
|
707
750
|
cache_key = (queue.device.int_ptr, self.size, kernel_specific_max_wg_size)
|
|
@@ -713,7 +756,11 @@ class Array:
|
|
|
713
756
|
_ARRAY_GET_SIZES_CACHE[cache_key] = sizes
|
|
714
757
|
return sizes
|
|
715
758
|
|
|
716
|
-
def set(self,
|
|
759
|
+
def set(self,
|
|
760
|
+
ary: NDArray[Any],
|
|
761
|
+
queue: cl.CommandQueue | None = None,
|
|
762
|
+
async_: bool = False,
|
|
763
|
+
):
|
|
717
764
|
"""Transfer the contents the :class:`numpy.ndarray` object *ary*
|
|
718
765
|
onto the device.
|
|
719
766
|
|
|
@@ -723,32 +770,8 @@ class Array:
|
|
|
723
770
|
*async_* is a Boolean indicating whether the function is allowed
|
|
724
771
|
to return before the transfer completes. To avoid synchronization
|
|
725
772
|
bugs, this defaults to *False*.
|
|
726
|
-
|
|
727
|
-
.. versionchanged:: 2017.2.1
|
|
728
|
-
|
|
729
|
-
Python 3.7 makes ``async`` a reserved keyword. On older Pythons,
|
|
730
|
-
we will continue to accept *async* as a parameter, however this
|
|
731
|
-
should be considered deprecated. *async_* is the new, official
|
|
732
|
-
spelling.
|
|
733
773
|
"""
|
|
734
774
|
|
|
735
|
-
# {{{ handle 'async' deprecation
|
|
736
|
-
|
|
737
|
-
async_arg = kwargs.pop("async", None)
|
|
738
|
-
if async_arg is not None:
|
|
739
|
-
if async_ is not None:
|
|
740
|
-
raise TypeError("may not specify both 'async' and 'async_'")
|
|
741
|
-
async_ = async_arg
|
|
742
|
-
|
|
743
|
-
if async_ is None:
|
|
744
|
-
async_ = False
|
|
745
|
-
|
|
746
|
-
if kwargs:
|
|
747
|
-
raise TypeError("extra keyword arguments specified: %s"
|
|
748
|
-
% ", ".join(kwargs))
|
|
749
|
-
|
|
750
|
-
# }}}
|
|
751
|
-
|
|
752
775
|
assert ary.size == self.size
|
|
753
776
|
assert ary.dtype == self.dtype
|
|
754
777
|
|
|
@@ -756,36 +779,23 @@ class Array:
|
|
|
756
779
|
raise RuntimeError("cannot set from non-contiguous array")
|
|
757
780
|
|
|
758
781
|
if not _equal_strides(ary.strides, self.strides, self.shape):
|
|
759
|
-
|
|
760
|
-
"strides/storage order.
|
|
761
|
-
"in 2013.x.",
|
|
762
|
-
stacklevel=2)
|
|
782
|
+
raise RuntimeError("Setting array from one with different "
|
|
783
|
+
"strides/storage order.")
|
|
763
784
|
|
|
764
785
|
if self.size:
|
|
786
|
+
queue = queue or self.queue
|
|
787
|
+
assert queue is not None
|
|
765
788
|
event1 = cl.enqueue_copy(queue or self.queue, self.base_data, ary,
|
|
766
789
|
dst_offset=self.offset,
|
|
767
790
|
is_blocking=not async_)
|
|
768
791
|
|
|
769
792
|
self.add_event(event1)
|
|
770
793
|
|
|
771
|
-
def _get(self,
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
if async_ is not None:
|
|
777
|
-
raise TypeError("may not specify both 'async' and 'async_'")
|
|
778
|
-
async_ = async_arg
|
|
779
|
-
|
|
780
|
-
if async_ is None:
|
|
781
|
-
async_ = False
|
|
782
|
-
|
|
783
|
-
if kwargs:
|
|
784
|
-
raise TypeError("extra keyword arguments specified: %s"
|
|
785
|
-
% ", ".join(kwargs))
|
|
786
|
-
|
|
787
|
-
# }}}
|
|
788
|
-
|
|
794
|
+
def _get(self,
|
|
795
|
+
queue: cl.CommandQueue | None = None,
|
|
796
|
+
ary: NDArray[Any] | None = None,
|
|
797
|
+
async_: bool = False,
|
|
798
|
+
):
|
|
789
799
|
if ary is None:
|
|
790
800
|
ary = np.empty(self.shape, self.dtype)
|
|
791
801
|
|
|
@@ -812,52 +822,36 @@ class Array:
|
|
|
812
822
|
"to associate one.")
|
|
813
823
|
|
|
814
824
|
if self.size:
|
|
815
|
-
|
|
825
|
+
assert self.base_data is not None
|
|
826
|
+
event1 = cast("cl.Event", cl.enqueue_copy(queue, ary, self.base_data,
|
|
816
827
|
src_offset=self.offset,
|
|
817
|
-
wait_for=self.events, is_blocking=not async_)
|
|
828
|
+
wait_for=self.events, is_blocking=not async_))
|
|
818
829
|
|
|
819
830
|
self.add_event(event1)
|
|
820
831
|
else:
|
|
821
|
-
event1 =
|
|
832
|
+
event1 = cl.enqueue_marker(queue, wait_for=self.events)
|
|
833
|
+
if not async_:
|
|
834
|
+
event1.wait()
|
|
822
835
|
|
|
823
836
|
return ary, event1
|
|
824
837
|
|
|
825
|
-
def get(self,
|
|
838
|
+
def get(self,
|
|
839
|
+
queue: cl.CommandQueue | None = None,
|
|
840
|
+
ary: NDArray[Any] | None = None,
|
|
841
|
+
) -> NDArray[Any]:
|
|
826
842
|
"""Transfer the contents of *self* into *ary* or a newly allocated
|
|
827
843
|
:class:`numpy.ndarray`. If *ary* is given, it must have the same
|
|
828
844
|
shape and dtype.
|
|
829
|
-
|
|
830
|
-
.. versionchanged:: 2019.1.2
|
|
831
|
-
|
|
832
|
-
Calling with ``async_=True`` was deprecated and replaced by
|
|
833
|
-
:meth:`get_async`.
|
|
834
|
-
The event returned by :meth:`pyopencl.enqueue_copy` is now stored into
|
|
835
|
-
:attr:`events` to ensure data is not modified before the copy is
|
|
836
|
-
complete.
|
|
837
|
-
|
|
838
|
-
.. versionchanged:: 2015.2
|
|
839
|
-
|
|
840
|
-
*ary* with different shape was deprecated.
|
|
841
|
-
|
|
842
|
-
.. versionchanged:: 2017.2.1
|
|
843
|
-
|
|
844
|
-
Python 3.7 makes ``async`` a reserved keyword. On older Pythons,
|
|
845
|
-
we will continue to accept *async* as a parameter, however this
|
|
846
|
-
should be considered deprecated. *async_* is the new, official
|
|
847
|
-
spelling.
|
|
848
845
|
"""
|
|
849
846
|
|
|
850
|
-
|
|
851
|
-
warn("calling pyopencl.Array.get with 'async_=True' is deprecated. "
|
|
852
|
-
"Please use pyopencl.Array.get_async for asynchronous "
|
|
853
|
-
"device-to-host transfers",
|
|
854
|
-
DeprecationWarning, stacklevel=2)
|
|
855
|
-
|
|
856
|
-
ary, _event1 = self._get(queue=queue, ary=ary, async_=async_, **kwargs)
|
|
847
|
+
ary, _event1 = self._get(queue=queue, ary=ary)
|
|
857
848
|
|
|
858
849
|
return ary
|
|
859
850
|
|
|
860
|
-
def get_async(self,
|
|
851
|
+
def get_async(self,
|
|
852
|
+
queue: cl.CommandQueue | None = None,
|
|
853
|
+
ary: NDArray[Any] | None = None,
|
|
854
|
+
) -> tuple[NDArray[Any], cl.Event]:
|
|
861
855
|
"""
|
|
862
856
|
Asynchronous version of :meth:`get` which returns a tuple ``(ary, event)``
|
|
863
857
|
containing the host array ``ary``
|
|
@@ -867,9 +861,9 @@ class Array:
|
|
|
867
861
|
.. versionadded:: 2019.1.2
|
|
868
862
|
"""
|
|
869
863
|
|
|
870
|
-
return self._get(queue=queue, ary=ary, async_=True
|
|
864
|
+
return self._get(queue=queue, ary=ary, async_=True)
|
|
871
865
|
|
|
872
|
-
def copy(self, queue=_copy_queue):
|
|
866
|
+
def copy(self, queue: cl.CommandQueue | type[_copy_queue] | None = _copy_queue):
|
|
873
867
|
"""
|
|
874
868
|
:arg queue: The :class:`~pyopencl.CommandQueue` for the returned array.
|
|
875
869
|
|
|
@@ -881,20 +875,24 @@ class Array:
|
|
|
881
875
|
"""
|
|
882
876
|
|
|
883
877
|
if queue is _copy_queue:
|
|
884
|
-
|
|
878
|
+
queue_san = self.queue
|
|
879
|
+
else:
|
|
880
|
+
queue_san = cast("cl.CommandQueue | None", queue)
|
|
885
881
|
|
|
886
|
-
result = self._new_like_me(queue=
|
|
882
|
+
result = self._new_like_me(queue=queue_san)
|
|
887
883
|
|
|
888
884
|
# result.queue won't be the same as queue if queue is None.
|
|
889
885
|
# We force them to be the same here.
|
|
890
886
|
if result.queue is not queue:
|
|
891
|
-
result = result.with_queue(
|
|
887
|
+
result = result.with_queue(queue_san)
|
|
892
888
|
|
|
893
889
|
if not self.flags.forc:
|
|
894
890
|
raise RuntimeError("cannot copy non-contiguous array")
|
|
895
891
|
|
|
896
892
|
if self.nbytes:
|
|
897
|
-
|
|
893
|
+
queue_san = queue_san or self.queue
|
|
894
|
+
assert queue_san is not None
|
|
895
|
+
event1 = cl.enqueue_copy(queue_san,
|
|
898
896
|
result.base_data, self.base_data,
|
|
899
897
|
src_offset=self.offset, byte_count=self.nbytes,
|
|
900
898
|
wait_for=self.events)
|
|
@@ -935,7 +933,7 @@ class Array:
|
|
|
935
933
|
|
|
936
934
|
@staticmethod
|
|
937
935
|
@elwise_kernel_runner
|
|
938
|
-
def _axpbyz(out, afac, a, bfac, b, queue=None):
|
|
936
|
+
def _axpbyz(out, afac, a, bfac, b, queue: cl.CommandQueue | None = None):
|
|
939
937
|
"""Compute ``out = selffac * self + otherfac*other``,
|
|
940
938
|
where *other* is an array."""
|
|
941
939
|
a_shape = a.shape
|
|
@@ -951,7 +949,7 @@ class Array:
|
|
|
951
949
|
|
|
952
950
|
@staticmethod
|
|
953
951
|
@elwise_kernel_runner
|
|
954
|
-
def _axpbz(out, a, x, b, queue=None):
|
|
952
|
+
def _axpbz(out, a, x, b, queue: cl.CommandQueue | None = None):
|
|
955
953
|
"""Compute ``z = a * x + b``, where *b* is a scalar."""
|
|
956
954
|
a = np.array(a)
|
|
957
955
|
b = np.array(b)
|
|
@@ -961,7 +959,7 @@ class Array:
|
|
|
961
959
|
|
|
962
960
|
@staticmethod
|
|
963
961
|
@elwise_kernel_runner
|
|
964
|
-
def _elwise_multiply(out, a, b, queue=None):
|
|
962
|
+
def _elwise_multiply(out, a, b, queue: cl.CommandQueue | None = None):
|
|
965
963
|
a_shape = a.shape
|
|
966
964
|
b_shape = b.shape
|
|
967
965
|
out_shape = out.shape
|
|
@@ -976,7 +974,7 @@ class Array:
|
|
|
976
974
|
|
|
977
975
|
@staticmethod
|
|
978
976
|
@elwise_kernel_runner
|
|
979
|
-
def _rdiv_scalar(out, ary, other, queue=None):
|
|
977
|
+
def _rdiv_scalar(out, ary, other, queue: cl.CommandQueue | None = None):
|
|
980
978
|
other = np.array(other)
|
|
981
979
|
assert out.shape == ary.shape
|
|
982
980
|
return elementwise.get_rdivide_elwise_kernel(
|
|
@@ -984,7 +982,7 @@ class Array:
|
|
|
984
982
|
|
|
985
983
|
@staticmethod
|
|
986
984
|
@elwise_kernel_runner
|
|
987
|
-
def _div(out, self, other, queue=None):
|
|
985
|
+
def _div(out, self, other, queue: cl.CommandQueue | None = None):
|
|
988
986
|
"""Divides an array by another array."""
|
|
989
987
|
assert (self.shape == other.shape == out.shape
|
|
990
988
|
or (self.shape == () and other.shape == out.shape)
|
|
@@ -1074,7 +1072,7 @@ class Array:
|
|
|
1074
1072
|
return elementwise.get_copy_kernel(
|
|
1075
1073
|
dest.context, dest.dtype, src.dtype)
|
|
1076
1074
|
|
|
1077
|
-
def _new_like_me(self, dtype=None, queue=None):
|
|
1075
|
+
def _new_like_me(self, dtype=None, queue: cl.CommandQueue | None = None):
|
|
1078
1076
|
if dtype is None:
|
|
1079
1077
|
dtype = self.dtype
|
|
1080
1078
|
strides = self.strides
|
|
@@ -1098,14 +1096,14 @@ class Array:
|
|
|
1098
1096
|
|
|
1099
1097
|
@staticmethod
|
|
1100
1098
|
@elwise_kernel_runner
|
|
1101
|
-
def _scalar_binop(out, a, b, queue=None, op=None):
|
|
1099
|
+
def _scalar_binop(out, a, b, queue: cl.CommandQueue | None = None, op=None):
|
|
1102
1100
|
return elementwise.get_array_scalar_binop_kernel(
|
|
1103
1101
|
out.context, op, out.dtype, a.dtype,
|
|
1104
1102
|
np.array(b).dtype)
|
|
1105
1103
|
|
|
1106
1104
|
@staticmethod
|
|
1107
1105
|
@elwise_kernel_runner
|
|
1108
|
-
def _array_binop(out, a, b, queue=None, op=None):
|
|
1106
|
+
def _array_binop(out, a, b, queue: cl.CommandQueue | None = None, op=None):
|
|
1109
1107
|
a_shape = a.shape
|
|
1110
1108
|
b_shape = b.shape
|
|
1111
1109
|
out_shape = out.shape
|
|
@@ -1119,7 +1117,7 @@ class Array:
|
|
|
1119
1117
|
|
|
1120
1118
|
@staticmethod
|
|
1121
1119
|
@elwise_kernel_runner
|
|
1122
|
-
def _unop(out, a, queue=None, op=None):
|
|
1120
|
+
def _unop(out, a, queue: cl.CommandQueue | None = None, op=None):
|
|
1123
1121
|
if out.shape != a.shape:
|
|
1124
1122
|
raise ValueError("shapes of arguments do not match")
|
|
1125
1123
|
return elementwise.get_unop_kernel(
|
|
@@ -1129,7 +1127,7 @@ class Array:
|
|
|
1129
1127
|
|
|
1130
1128
|
# {{{ operators
|
|
1131
1129
|
|
|
1132
|
-
def mul_add(self, selffac, other, otherfac, queue=None):
|
|
1130
|
+
def mul_add(self, selffac, other, otherfac, queue: cl.CommandQueue | None = None):
|
|
1133
1131
|
"""Return ``selffac * self + otherfac * other``.
|
|
1134
1132
|
"""
|
|
1135
1133
|
queue = queue or self.queue
|
|
@@ -1152,7 +1150,7 @@ class Array:
|
|
|
1152
1150
|
else:
|
|
1153
1151
|
raise NotImplementedError
|
|
1154
1152
|
|
|
1155
|
-
def __add__(self, other):
|
|
1153
|
+
def __add__(self, other) -> Self:
|
|
1156
1154
|
"""Add an array with an array or an array with a scalar."""
|
|
1157
1155
|
|
|
1158
1156
|
if isinstance(other, Array):
|
|
@@ -1178,7 +1176,7 @@ class Array:
|
|
|
1178
1176
|
|
|
1179
1177
|
__radd__ = __add__
|
|
1180
1178
|
|
|
1181
|
-
def __sub__(self, other):
|
|
1179
|
+
def __sub__(self, other) -> Self:
|
|
1182
1180
|
"""Subtract an array from an array or a scalar from an array."""
|
|
1183
1181
|
|
|
1184
1182
|
if isinstance(other, Array):
|
|
@@ -1201,7 +1199,7 @@ class Array:
|
|
|
1201
1199
|
else:
|
|
1202
1200
|
return NotImplemented
|
|
1203
1201
|
|
|
1204
|
-
def __rsub__(self, other):
|
|
1202
|
+
def __rsub__(self, other) -> Self:
|
|
1205
1203
|
"""Subtracts an array by a scalar or an array::
|
|
1206
1204
|
|
|
1207
1205
|
x = n - self
|
|
@@ -1217,7 +1215,7 @@ class Array:
|
|
|
1217
1215
|
else:
|
|
1218
1216
|
return NotImplemented
|
|
1219
1217
|
|
|
1220
|
-
def __iadd__(self, other):
|
|
1218
|
+
def __iadd__(self, other) -> Self:
|
|
1221
1219
|
if isinstance(other, Array):
|
|
1222
1220
|
if other.shape != self.shape and other.shape != ():
|
|
1223
1221
|
raise NotImplementedError("Broadcasting binary op with shapes:"
|
|
@@ -1235,7 +1233,7 @@ class Array:
|
|
|
1235
1233
|
else:
|
|
1236
1234
|
return NotImplemented
|
|
1237
1235
|
|
|
1238
|
-
def __isub__(self, other):
|
|
1236
|
+
def __isub__(self, other) -> Self:
|
|
1239
1237
|
if isinstance(other, Array):
|
|
1240
1238
|
if other.shape != self.shape and other.shape != ():
|
|
1241
1239
|
raise NotImplementedError("Broadcasting binary op with shapes:"
|
|
@@ -1250,15 +1248,15 @@ class Array:
|
|
|
1250
1248
|
else:
|
|
1251
1249
|
return NotImplemented
|
|
1252
1250
|
|
|
1253
|
-
def __pos__(self):
|
|
1251
|
+
def __pos__(self) -> Self:
|
|
1254
1252
|
return self
|
|
1255
1253
|
|
|
1256
|
-
def __neg__(self):
|
|
1254
|
+
def __neg__(self) -> Self:
|
|
1257
1255
|
result = self._new_like_me()
|
|
1258
1256
|
result.add_event(self._axpbz(result, -1, self, 0))
|
|
1259
1257
|
return result
|
|
1260
1258
|
|
|
1261
|
-
def __mul__(self, other):
|
|
1259
|
+
def __mul__(self, other) -> Self:
|
|
1262
1260
|
if isinstance(other, Array):
|
|
1263
1261
|
result = _get_broadcasted_binary_op_result(self, other, self.queue)
|
|
1264
1262
|
result.add_event(
|
|
@@ -1274,7 +1272,7 @@ class Array:
|
|
|
1274
1272
|
else:
|
|
1275
1273
|
return NotImplemented
|
|
1276
1274
|
|
|
1277
|
-
def __rmul__(self, other):
|
|
1275
|
+
def __rmul__(self, other) -> Self:
|
|
1278
1276
|
if np.isscalar(other):
|
|
1279
1277
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1280
1278
|
result = self._new_like_me(common_dtype)
|
|
@@ -1285,7 +1283,7 @@ class Array:
|
|
|
1285
1283
|
else:
|
|
1286
1284
|
return NotImplemented
|
|
1287
1285
|
|
|
1288
|
-
def __imul__(self, other):
|
|
1286
|
+
def __imul__(self, other) -> Self:
|
|
1289
1287
|
if isinstance(other, Array):
|
|
1290
1288
|
if other.shape != self.shape and other.shape != ():
|
|
1291
1289
|
raise NotImplementedError("Broadcasting binary op with shapes:"
|
|
@@ -1300,7 +1298,7 @@ class Array:
|
|
|
1300
1298
|
else:
|
|
1301
1299
|
return NotImplemented
|
|
1302
1300
|
|
|
1303
|
-
def __div__(self, other):
|
|
1301
|
+
def __div__(self, other) -> Self:
|
|
1304
1302
|
"""Divides an array by an array or a scalar, i.e. ``self / other``.
|
|
1305
1303
|
"""
|
|
1306
1304
|
if isinstance(other, Array):
|
|
@@ -1326,7 +1324,7 @@ class Array:
|
|
|
1326
1324
|
|
|
1327
1325
|
__truediv__ = __div__
|
|
1328
1326
|
|
|
1329
|
-
def __rdiv__(self, other):
|
|
1327
|
+
def __rdiv__(self, other) -> Self:
|
|
1330
1328
|
"""Divides an array by a scalar or an array, i.e. ``other / self``.
|
|
1331
1329
|
"""
|
|
1332
1330
|
common_dtype = _get_truedivide_dtype(self, other, self.queue)
|
|
@@ -1345,7 +1343,7 @@ class Array:
|
|
|
1345
1343
|
|
|
1346
1344
|
__rtruediv__ = __rdiv__
|
|
1347
1345
|
|
|
1348
|
-
def __itruediv__(self, other):
|
|
1346
|
+
def __itruediv__(self, other) -> Self:
|
|
1349
1347
|
# raise an error if the result cannot be cast to self
|
|
1350
1348
|
common_dtype = _get_truedivide_dtype(self, other, self.queue)
|
|
1351
1349
|
if not np.can_cast(common_dtype, self.dtype.type, "same_kind"):
|
|
@@ -1370,7 +1368,7 @@ class Array:
|
|
|
1370
1368
|
else:
|
|
1371
1369
|
return NotImplemented
|
|
1372
1370
|
|
|
1373
|
-
def __and__(self, other):
|
|
1371
|
+
def __and__(self, other) -> Self:
|
|
1374
1372
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1375
1373
|
|
|
1376
1374
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1390,7 +1388,7 @@ class Array:
|
|
|
1390
1388
|
|
|
1391
1389
|
__rand__ = __and__ # commutes
|
|
1392
1390
|
|
|
1393
|
-
def __or__(self, other):
|
|
1391
|
+
def __or__(self, other) -> Self:
|
|
1394
1392
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1395
1393
|
|
|
1396
1394
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1411,7 +1409,7 @@ class Array:
|
|
|
1411
1409
|
|
|
1412
1410
|
__ror__ = __or__ # commutes
|
|
1413
1411
|
|
|
1414
|
-
def __xor__(self, other):
|
|
1412
|
+
def __xor__(self, other) -> Self:
|
|
1415
1413
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1416
1414
|
|
|
1417
1415
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1431,7 +1429,7 @@ class Array:
|
|
|
1431
1429
|
|
|
1432
1430
|
__rxor__ = __xor__ # commutes
|
|
1433
1431
|
|
|
1434
|
-
def __iand__(self, other):
|
|
1432
|
+
def __iand__(self, other) -> Self:
|
|
1435
1433
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1436
1434
|
|
|
1437
1435
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1450,7 +1448,7 @@ class Array:
|
|
|
1450
1448
|
else:
|
|
1451
1449
|
return NotImplemented
|
|
1452
1450
|
|
|
1453
|
-
def __ior__(self, other):
|
|
1451
|
+
def __ior__(self, other) -> Self:
|
|
1454
1452
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1455
1453
|
|
|
1456
1454
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1469,7 +1467,7 @@ class Array:
|
|
|
1469
1467
|
else:
|
|
1470
1468
|
return NotImplemented
|
|
1471
1469
|
|
|
1472
|
-
def __ixor__(self, other):
|
|
1470
|
+
def __ixor__(self, other) -> Self:
|
|
1473
1471
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1474
1472
|
|
|
1475
1473
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1488,7 +1486,9 @@ class Array:
|
|
|
1488
1486
|
else:
|
|
1489
1487
|
return NotImplemented
|
|
1490
1488
|
|
|
1491
|
-
def _zero_fill(self,
|
|
1489
|
+
def _zero_fill(self,
|
|
1490
|
+
queue: cl.CommandQueue | None = None,
|
|
1491
|
+
wait_for: cl.WaitList = None) -> None:
|
|
1492
1492
|
queue = queue or self.queue
|
|
1493
1493
|
|
|
1494
1494
|
if not self.size:
|
|
@@ -1510,7 +1510,10 @@ class Array:
|
|
|
1510
1510
|
zero = np.zeros((), self.dtype)
|
|
1511
1511
|
self.fill(zero, queue=queue)
|
|
1512
1512
|
|
|
1513
|
-
def fill(self,
|
|
1513
|
+
def fill(self,
|
|
1514
|
+
value: object,
|
|
1515
|
+
queue: cl.CommandQueue | None = None,
|
|
1516
|
+
wait_for: cl.WaitList = None) -> Self:
|
|
1514
1517
|
"""Fill the array with *scalar*.
|
|
1515
1518
|
|
|
1516
1519
|
:returns: *self*.
|
|
@@ -1521,14 +1524,14 @@ class Array:
|
|
|
1521
1524
|
|
|
1522
1525
|
return self
|
|
1523
1526
|
|
|
1524
|
-
def __len__(self):
|
|
1527
|
+
def __len__(self) -> int:
|
|
1525
1528
|
"""Returns the size of the leading dimension of *self*."""
|
|
1526
1529
|
if len(self.shape):
|
|
1527
1530
|
return self.shape[0]
|
|
1528
1531
|
else:
|
|
1529
1532
|
return TypeError("len() of unsized object")
|
|
1530
1533
|
|
|
1531
|
-
def __abs__(self):
|
|
1534
|
+
def __abs__(self) -> Self:
|
|
1532
1535
|
"""Return an ``Array`` of the absolute values of the elements
|
|
1533
1536
|
of *self*.
|
|
1534
1537
|
"""
|
|
@@ -1537,7 +1540,7 @@ class Array:
|
|
|
1537
1540
|
result.add_event(self._abs(result, self))
|
|
1538
1541
|
return result
|
|
1539
1542
|
|
|
1540
|
-
def __pow__(self, other):
|
|
1543
|
+
def __pow__(self, other) -> Self:
|
|
1541
1544
|
"""Exponentiation by a scalar or elementwise by another
|
|
1542
1545
|
:class:`Array`.
|
|
1543
1546
|
"""
|
|
@@ -1558,7 +1561,7 @@ class Array:
|
|
|
1558
1561
|
else:
|
|
1559
1562
|
return NotImplemented
|
|
1560
1563
|
|
|
1561
|
-
def __rpow__(self, other):
|
|
1564
|
+
def __rpow__(self, other) -> Self:
|
|
1562
1565
|
if np.isscalar(other):
|
|
1563
1566
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1564
1567
|
result = self._new_like_me(common_dtype)
|
|
@@ -1579,7 +1582,7 @@ class Array:
|
|
|
1579
1582
|
|
|
1580
1583
|
# }}}
|
|
1581
1584
|
|
|
1582
|
-
def reverse(self, queue=None):
|
|
1585
|
+
def reverse(self, queue: cl.CommandQueue | None = None) -> Self:
|
|
1583
1586
|
"""Return this array in reversed order. The array is treated
|
|
1584
1587
|
as one-dimensional.
|
|
1585
1588
|
"""
|
|
@@ -1588,7 +1591,7 @@ class Array:
|
|
|
1588
1591
|
result.add_event(self._reverse(result, self))
|
|
1589
1592
|
return result
|
|
1590
1593
|
|
|
1591
|
-
def astype(self, dtype, queue=None):
|
|
1594
|
+
def astype(self, dtype, queue: cl.CommandQueue | None = None):
|
|
1592
1595
|
"""Return a copy of *self*, cast to *dtype*."""
|
|
1593
1596
|
if dtype == self.dtype:
|
|
1594
1597
|
return self.copy()
|
|
@@ -1599,48 +1602,55 @@ class Array:
|
|
|
1599
1602
|
|
|
1600
1603
|
# {{{ rich comparisons, any, all
|
|
1601
1604
|
|
|
1602
|
-
def __bool__(self):
|
|
1605
|
+
def __bool__(self) -> bool:
|
|
1603
1606
|
if self.shape == ():
|
|
1604
1607
|
return bool(self.get())
|
|
1605
1608
|
else:
|
|
1606
1609
|
raise ValueError("The truth value of an array with "
|
|
1607
1610
|
"more than one element is ambiguous. Use a.any() or a.all()")
|
|
1608
1611
|
|
|
1609
|
-
def any(self,
|
|
1612
|
+
def any(self,
|
|
1613
|
+
queue: cl.CommandQueue | None = None,
|
|
1614
|
+
wait_for: cl.WaitList = None
|
|
1615
|
+
) -> Self:
|
|
1610
1616
|
from pyopencl.reduction import get_any_kernel
|
|
1611
1617
|
krnl = get_any_kernel(self.context, self.dtype)
|
|
1612
1618
|
if wait_for is None:
|
|
1613
1619
|
wait_for = []
|
|
1614
1620
|
result, event1 = krnl(self, queue=queue,
|
|
1615
|
-
wait_for=wait_for
|
|
1621
|
+
wait_for=[*wait_for, *self.events], return_event=True)
|
|
1616
1622
|
result.add_event(event1)
|
|
1617
1623
|
return result
|
|
1618
1624
|
|
|
1619
|
-
def all(self,
|
|
1625
|
+
def all(self,
|
|
1626
|
+
queue: cl.CommandQueue | None = None,
|
|
1627
|
+
wait_for: cl.WaitList = None
|
|
1628
|
+
) -> Self:
|
|
1620
1629
|
from pyopencl.reduction import get_all_kernel
|
|
1621
1630
|
krnl = get_all_kernel(self.context, self.dtype)
|
|
1622
1631
|
if wait_for is None:
|
|
1623
1632
|
wait_for = []
|
|
1624
1633
|
result, event1 = krnl(self, queue=queue,
|
|
1625
|
-
wait_for=wait_for
|
|
1634
|
+
wait_for=[*wait_for, *self.events], return_event=True)
|
|
1626
1635
|
result.add_event(event1)
|
|
1627
1636
|
return result
|
|
1628
1637
|
|
|
1629
1638
|
@staticmethod
|
|
1630
1639
|
@elwise_kernel_runner
|
|
1631
|
-
def _scalar_comparison(out, a, b, queue=None, op=None):
|
|
1640
|
+
def _scalar_comparison(out, a, b, queue: cl.CommandQueue | None = None, op=None):
|
|
1632
1641
|
return elementwise.get_array_scalar_comparison_kernel(
|
|
1633
1642
|
out.context, op, a.dtype)
|
|
1634
1643
|
|
|
1635
1644
|
@staticmethod
|
|
1636
1645
|
@elwise_kernel_runner
|
|
1637
|
-
def _array_comparison(out, a, b, queue=None, op=None):
|
|
1646
|
+
def _array_comparison(out, a, b, queue: cl.CommandQueue | None = None, op=None):
|
|
1638
1647
|
if a.shape != b.shape:
|
|
1639
1648
|
raise ValueError("shapes of comparison arguments do not match")
|
|
1640
1649
|
return elementwise.get_array_comparison_kernel(
|
|
1641
1650
|
out.context, op, a.dtype, b.dtype)
|
|
1642
1651
|
|
|
1643
|
-
|
|
1652
|
+
@override
|
|
1653
|
+
def __eq__(self, other: object) -> Self: # pyright: ignore[reportIncompatibleMethodOverride]
|
|
1644
1654
|
if isinstance(other, Array):
|
|
1645
1655
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1646
1656
|
result.add_event(
|
|
@@ -1654,7 +1664,8 @@ class Array:
|
|
|
1654
1664
|
else:
|
|
1655
1665
|
return NotImplemented
|
|
1656
1666
|
|
|
1657
|
-
|
|
1667
|
+
@override
|
|
1668
|
+
def __ne__(self, other: object) -> Self: # pyright: ignore[reportIncompatibleMethodOverride]
|
|
1658
1669
|
if isinstance(other, Array):
|
|
1659
1670
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1660
1671
|
result.add_event(
|
|
@@ -1668,7 +1679,7 @@ class Array:
|
|
|
1668
1679
|
else:
|
|
1669
1680
|
return NotImplemented
|
|
1670
1681
|
|
|
1671
|
-
def __le__(self, other):
|
|
1682
|
+
def __le__(self, other) -> Self:
|
|
1672
1683
|
if isinstance(other, Array):
|
|
1673
1684
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1674
1685
|
result.add_event(
|
|
@@ -1681,7 +1692,7 @@ class Array:
|
|
|
1681
1692
|
else:
|
|
1682
1693
|
return NotImplemented
|
|
1683
1694
|
|
|
1684
|
-
def __ge__(self, other):
|
|
1695
|
+
def __ge__(self, other) -> Self:
|
|
1685
1696
|
if isinstance(other, Array):
|
|
1686
1697
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1687
1698
|
result.add_event(
|
|
@@ -1695,7 +1706,7 @@ class Array:
|
|
|
1695
1706
|
else:
|
|
1696
1707
|
return NotImplemented
|
|
1697
1708
|
|
|
1698
|
-
def __lt__(self, other):
|
|
1709
|
+
def __lt__(self, other) -> Self:
|
|
1699
1710
|
if isinstance(other, Array):
|
|
1700
1711
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1701
1712
|
result.add_event(
|
|
@@ -1709,7 +1720,7 @@ class Array:
|
|
|
1709
1720
|
else:
|
|
1710
1721
|
return NotImplemented
|
|
1711
1722
|
|
|
1712
|
-
def __gt__(self, other):
|
|
1723
|
+
def __gt__(self, other) -> Self:
|
|
1713
1724
|
if isinstance(other, Array):
|
|
1714
1725
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1715
1726
|
result.add_event(
|
|
@@ -1728,7 +1739,7 @@ class Array:
|
|
|
1728
1739
|
# {{{ complex-valued business
|
|
1729
1740
|
|
|
1730
1741
|
@property
|
|
1731
|
-
def real(self):
|
|
1742
|
+
def real(self) -> Self:
|
|
1732
1743
|
"""
|
|
1733
1744
|
.. versionadded:: 2012.1
|
|
1734
1745
|
"""
|
|
@@ -1741,7 +1752,7 @@ class Array:
|
|
|
1741
1752
|
return self
|
|
1742
1753
|
|
|
1743
1754
|
@property
|
|
1744
|
-
def imag(self):
|
|
1755
|
+
def imag(self) -> Self:
|
|
1745
1756
|
"""
|
|
1746
1757
|
.. versionadded:: 2012.1
|
|
1747
1758
|
"""
|
|
@@ -1753,7 +1764,7 @@ class Array:
|
|
|
1753
1764
|
else:
|
|
1754
1765
|
return zeros_like(self)
|
|
1755
1766
|
|
|
1756
|
-
def conj(self):
|
|
1767
|
+
def conj(self) -> Self:
|
|
1757
1768
|
"""
|
|
1758
1769
|
.. versionadded:: 2012.1
|
|
1759
1770
|
"""
|
|
@@ -1770,7 +1781,7 @@ class Array:
|
|
|
1770
1781
|
|
|
1771
1782
|
# {{{ event management
|
|
1772
1783
|
|
|
1773
|
-
def add_event(self, evt):
|
|
1784
|
+
def add_event(self, evt: cl.Event) -> None:
|
|
1774
1785
|
"""Add *evt* to :attr:`events`. If :attr:`events` is too long, this method
|
|
1775
1786
|
may implicitly wait for a subset of :attr:`events` and clear them from the
|
|
1776
1787
|
list.
|
|
@@ -1784,7 +1795,7 @@ class Array:
|
|
|
1784
1795
|
cl.wait_for_events(wait_events)
|
|
1785
1796
|
del self.events[:n_wait]
|
|
1786
1797
|
|
|
1787
|
-
def finish(self):
|
|
1798
|
+
def finish(self) -> None:
|
|
1788
1799
|
"""Wait for the entire contents of :attr:`events`, clear it."""
|
|
1789
1800
|
|
|
1790
1801
|
if self.events:
|
|
@@ -2022,7 +2033,11 @@ class Array:
|
|
|
2022
2033
|
|
|
2023
2034
|
# }}}
|
|
2024
2035
|
|
|
2025
|
-
def map_to_host(self,
|
|
2036
|
+
def map_to_host(self,
|
|
2037
|
+
queue: cl.CommandQueue | None = None,
|
|
2038
|
+
flags=None,
|
|
2039
|
+
is_blocking: bool = True,
|
|
2040
|
+
wait_for: cl.WaitList = None):
|
|
2026
2041
|
"""If *is_blocking*, return a :class:`numpy.ndarray` corresponding to the
|
|
2027
2042
|
same memory as *self*.
|
|
2028
2043
|
|
|
@@ -2046,7 +2061,7 @@ class Array:
|
|
|
2046
2061
|
ary, evt = cl.enqueue_map_buffer(
|
|
2047
2062
|
queue or self.queue, self.base_data, flags, self.offset,
|
|
2048
2063
|
self.shape, self.dtype, strides=self.strides,
|
|
2049
|
-
wait_for=wait_for
|
|
2064
|
+
wait_for=[*wait_for, *self.events], is_blocking=is_blocking)
|
|
2050
2065
|
|
|
2051
2066
|
if is_blocking:
|
|
2052
2067
|
return ary
|
|
@@ -2153,7 +2168,12 @@ class Array:
|
|
|
2153
2168
|
shape=tuple(new_shape),
|
|
2154
2169
|
strides=tuple(new_strides))
|
|
2155
2170
|
|
|
2156
|
-
def setitem(self,
|
|
2171
|
+
def setitem(self,
|
|
2172
|
+
subscript: Array | slice | int,
|
|
2173
|
+
value: object,
|
|
2174
|
+
queue: cl.CommandQueue | None = None,
|
|
2175
|
+
wait_for: cl.WaitList = None
|
|
2176
|
+
):
|
|
2157
2177
|
"""Like :meth:`__setitem__`, but with the ability to specify
|
|
2158
2178
|
a *queue* and *wait_for*.
|
|
2159
2179
|
|
|
@@ -2164,10 +2184,11 @@ class Array:
|
|
|
2164
2184
|
Added *wait_for*.
|
|
2165
2185
|
"""
|
|
2166
2186
|
|
|
2167
|
-
queue = queue or self.queue
|
|
2187
|
+
queue = queue or self.queue
|
|
2188
|
+
assert queue is not None
|
|
2168
2189
|
if wait_for is None:
|
|
2169
2190
|
wait_for = []
|
|
2170
|
-
wait_for = wait_for
|
|
2191
|
+
wait_for = [*wait_for, *self.events]
|
|
2171
2192
|
|
|
2172
2193
|
if isinstance(subscript, Array):
|
|
2173
2194
|
if subscript.dtype.kind not in ("i", "u"):
|
|
@@ -2193,6 +2214,7 @@ class Array:
|
|
|
2193
2214
|
|
|
2194
2215
|
if isinstance(value, np.ndarray):
|
|
2195
2216
|
if subarray.shape == value.shape and subarray.strides == value.strides:
|
|
2217
|
+
assert subarray.base_data is not None
|
|
2196
2218
|
self.add_event(
|
|
2197
2219
|
cl.enqueue_copy(queue, subarray.base_data,
|
|
2198
2220
|
value, dst_offset=subarray.offset, wait_for=wait_for))
|
|
@@ -2262,8 +2284,13 @@ class _same_as_transfer: # noqa: N801
|
|
|
2262
2284
|
pass
|
|
2263
2285
|
|
|
2264
2286
|
|
|
2265
|
-
def to_device(
|
|
2266
|
-
|
|
2287
|
+
def to_device(
|
|
2288
|
+
queue: cl.CommandQueue,
|
|
2289
|
+
ary: NDArray[Any],
|
|
2290
|
+
allocator: Allocator | None = None,
|
|
2291
|
+
async_: bool = False,
|
|
2292
|
+
array_queue=_same_as_transfer,
|
|
2293
|
+
) -> Array:
|
|
2267
2294
|
"""Return a :class:`Array` that is an exact copy of the
|
|
2268
2295
|
:class:`numpy.ndarray` instance *ary*.
|
|
2269
2296
|
|
|
@@ -2276,32 +2303,8 @@ def to_device(queue, ary, allocator=None, async_=None,
|
|
|
2276
2303
|
|
|
2277
2304
|
.. versionchanged:: 2015.2
|
|
2278
2305
|
*array_queue* argument was added.
|
|
2279
|
-
|
|
2280
|
-
.. versionchanged:: 2017.2.1
|
|
2281
|
-
|
|
2282
|
-
Python 3.7 makes ``async`` a reserved keyword. On older Pythons,
|
|
2283
|
-
we will continue to accept *async* as a parameter, however this
|
|
2284
|
-
should be considered deprecated. *async_* is the new, official
|
|
2285
|
-
spelling.
|
|
2286
2306
|
"""
|
|
2287
2307
|
|
|
2288
|
-
# {{{ handle 'async' deprecation
|
|
2289
|
-
|
|
2290
|
-
async_arg = kwargs.pop("async", None)
|
|
2291
|
-
if async_arg is not None:
|
|
2292
|
-
if async_ is not None:
|
|
2293
|
-
raise TypeError("may not specify both 'async' and 'async_'")
|
|
2294
|
-
async_ = async_arg
|
|
2295
|
-
|
|
2296
|
-
if async_ is None:
|
|
2297
|
-
async_ = False
|
|
2298
|
-
|
|
2299
|
-
if kwargs:
|
|
2300
|
-
raise TypeError("extra keyword arguments specified: %s"
|
|
2301
|
-
% ", ".join(kwargs))
|
|
2302
|
-
|
|
2303
|
-
# }}}
|
|
2304
|
-
|
|
2305
2308
|
if ary.dtype == object:
|
|
2306
2309
|
raise RuntimeError("to_device does not work on object arrays.")
|
|
2307
2310
|
|
|
@@ -2319,7 +2322,13 @@ def to_device(queue, ary, allocator=None, async_=None,
|
|
|
2319
2322
|
empty = Array
|
|
2320
2323
|
|
|
2321
2324
|
|
|
2322
|
-
def zeros(
|
|
2325
|
+
def zeros(
|
|
2326
|
+
queue: cl.CommandQueue,
|
|
2327
|
+
shape: int | tuple[int, ...],
|
|
2328
|
+
dtype: DTypeLike,
|
|
2329
|
+
order: Literal["C"] | Literal["F"] = "C",
|
|
2330
|
+
allocator: Allocator | None = None,
|
|
2331
|
+
) -> Array:
|
|
2323
2332
|
"""Same as :func:`empty`, but the :class:`Array` is zero-initialized before
|
|
2324
2333
|
being returned.
|
|
2325
2334
|
|
|
@@ -2334,7 +2343,11 @@ def zeros(queue, shape, dtype, order="C", allocator=None):
|
|
|
2334
2343
|
return result
|
|
2335
2344
|
|
|
2336
2345
|
|
|
2337
|
-
def empty_like(
|
|
2346
|
+
def empty_like(
|
|
2347
|
+
ary: Array,
|
|
2348
|
+
queue: cl.CommandQueue | type[_copy_queue] | None = _copy_queue,
|
|
2349
|
+
allocator: Allocator | None = None,
|
|
2350
|
+
):
|
|
2338
2351
|
"""Make a new, uninitialized :class:`Array` having the same properties
|
|
2339
2352
|
as *other_ary*.
|
|
2340
2353
|
"""
|
|
@@ -2466,7 +2479,13 @@ def _take(result, ary, indices):
|
|
|
2466
2479
|
result.context, result.dtype, indices.dtype)
|
|
2467
2480
|
|
|
2468
2481
|
|
|
2469
|
-
def take(
|
|
2482
|
+
def take(
|
|
2483
|
+
a: Array,
|
|
2484
|
+
indices: Array,
|
|
2485
|
+
out: Array | None = None,
|
|
2486
|
+
queue: cl.CommandQueue | None = None,
|
|
2487
|
+
wait_for: cl.WaitList = None
|
|
2488
|
+
) -> Array:
|
|
2470
2489
|
"""Return the :class:`Array` ``[a[indices[0]], ..., a[indices[n]]]``.
|
|
2471
2490
|
For the moment, *a* must be a type that can be bound to a texture.
|
|
2472
2491
|
"""
|
|
@@ -2481,7 +2500,7 @@ def take(a, indices, out=None, queue=None, wait_for=None):
|
|
|
2481
2500
|
return out
|
|
2482
2501
|
|
|
2483
2502
|
|
|
2484
|
-
def multi_take(arrays, indices, out=None, queue=None):
|
|
2503
|
+
def multi_take(arrays, indices, out=None, queue: cl.CommandQueue | None = None):
|
|
2485
2504
|
if not len(arrays):
|
|
2486
2505
|
return []
|
|
2487
2506
|
|
|
@@ -2544,7 +2563,7 @@ def multi_take(arrays, indices, out=None, queue=None):
|
|
|
2544
2563
|
|
|
2545
2564
|
|
|
2546
2565
|
def multi_take_put(arrays, dest_indices, src_indices, dest_shape=None,
|
|
2547
|
-
out=None, queue=None, src_offsets=None):
|
|
2566
|
+
out=None, queue: cl.CommandQueue | None = None, src_offsets=None):
|
|
2548
2567
|
if not len(arrays):
|
|
2549
2568
|
return []
|
|
2550
2569
|
|
|
@@ -2626,8 +2645,14 @@ def multi_take_put(arrays, dest_indices, src_indices, dest_shape=None,
|
|
|
2626
2645
|
return out
|
|
2627
2646
|
|
|
2628
2647
|
|
|
2629
|
-
def multi_put(
|
|
2630
|
-
|
|
2648
|
+
def multi_put(
|
|
2649
|
+
arrays,
|
|
2650
|
+
dest_indices: Array,
|
|
2651
|
+
dest_shape=None,
|
|
2652
|
+
out=None,
|
|
2653
|
+
queue: cl.CommandQueue | None = None,
|
|
2654
|
+
wait_for: cl.WaitList = None
|
|
2655
|
+
):
|
|
2631
2656
|
if not len(arrays):
|
|
2632
2657
|
return []
|
|
2633
2658
|
|
|
@@ -2636,9 +2661,10 @@ def multi_put(arrays, dest_indices, dest_shape=None, out=None, queue=None,
|
|
|
2636
2661
|
a_allocator = arrays[0].allocator
|
|
2637
2662
|
context = dest_indices.context
|
|
2638
2663
|
queue = queue or dest_indices.queue
|
|
2664
|
+
assert queue is not None
|
|
2639
2665
|
if wait_for is None:
|
|
2640
2666
|
wait_for = []
|
|
2641
|
-
wait_for = wait_for
|
|
2667
|
+
wait_for = [*wait_for, *dest_indices.events]
|
|
2642
2668
|
|
|
2643
2669
|
vec_count = len(arrays)
|
|
2644
2670
|
|
|
@@ -2705,7 +2731,7 @@ def multi_put(arrays, dest_indices, dest_shape=None, out=None, queue=None,
|
|
|
2705
2731
|
return out
|
|
2706
2732
|
|
|
2707
2733
|
|
|
2708
|
-
def concatenate(arrays, axis=0, queue=None, allocator=None):
|
|
2734
|
+
def concatenate(arrays, axis=0, queue: cl.CommandQueue | None = None, allocator=None):
|
|
2709
2735
|
"""
|
|
2710
2736
|
.. versionadded:: 2013.1
|
|
2711
2737
|
|
|
@@ -2777,7 +2803,7 @@ def _diff(result, array):
|
|
|
2777
2803
|
return elementwise.get_diff_kernel(array.context, array.dtype)
|
|
2778
2804
|
|
|
2779
2805
|
|
|
2780
|
-
def diff(array, queue=None, allocator=None):
|
|
2806
|
+
def diff(array, queue: cl.CommandQueue | None = None, allocator=None):
|
|
2781
2807
|
"""
|
|
2782
2808
|
.. versionadded:: 2013.2
|
|
2783
2809
|
"""
|
|
@@ -2796,7 +2822,7 @@ def diff(array, queue=None, allocator=None):
|
|
|
2796
2822
|
return result
|
|
2797
2823
|
|
|
2798
2824
|
|
|
2799
|
-
def hstack(arrays, queue=None):
|
|
2825
|
+
def hstack(arrays, queue: cl.CommandQueue | None = None):
|
|
2800
2826
|
if len(arrays) == 0:
|
|
2801
2827
|
raise ValueError("need at least one array to hstack")
|
|
2802
2828
|
|
|
@@ -2831,7 +2857,7 @@ def hstack(arrays, queue=None):
|
|
|
2831
2857
|
return result
|
|
2832
2858
|
|
|
2833
2859
|
|
|
2834
|
-
def stack(arrays, axis=0, queue=None):
|
|
2860
|
+
def stack(arrays, axis=0, queue: cl.CommandQueue | None = None):
|
|
2835
2861
|
"""
|
|
2836
2862
|
Join a sequence of arrays along a new axis.
|
|
2837
2863
|
|
|
@@ -2934,7 +2960,12 @@ def _if_positive(result, criterion, then_, else_):
|
|
|
2934
2960
|
)
|
|
2935
2961
|
|
|
2936
2962
|
|
|
2937
|
-
def if_positive(
|
|
2963
|
+
def if_positive(
|
|
2964
|
+
criterion,
|
|
2965
|
+
then_,
|
|
2966
|
+
else_,
|
|
2967
|
+
out=None,
|
|
2968
|
+
queue: cl.CommandQueue | None = None):
|
|
2938
2969
|
"""Return an array like *then_*, which, for the element at index *i*,
|
|
2939
2970
|
contains *then_[i]* if *criterion[i]>0*, else *else_[i]*.
|
|
2940
2971
|
"""
|
|
@@ -3018,7 +3049,7 @@ def _minimum_maximum_backend(out, a, b, minmax):
|
|
|
3018
3049
|
elementwise.get_argument_kind(b))
|
|
3019
3050
|
|
|
3020
3051
|
|
|
3021
|
-
def maximum(a, b, out=None, queue=None):
|
|
3052
|
+
def maximum(a, b, out=None, queue: cl.CommandQueue | None = None):
|
|
3022
3053
|
"""Return the elementwise maximum of *a* and *b*."""
|
|
3023
3054
|
|
|
3024
3055
|
a_is_scalar = np.isscalar(a)
|
|
@@ -3045,7 +3076,7 @@ def maximum(a, b, out=None, queue=None):
|
|
|
3045
3076
|
return out
|
|
3046
3077
|
|
|
3047
3078
|
|
|
3048
|
-
def minimum(a, b, out=None, queue=None):
|
|
3079
|
+
def minimum(a, b, out=None, queue: cl.CommandQueue | None = None):
|
|
3049
3080
|
"""Return the elementwise minimum of *a* and *b*."""
|
|
3050
3081
|
a_is_scalar = np.isscalar(a)
|
|
3051
3082
|
b_is_scalar = np.isscalar(b)
|
|
@@ -3075,7 +3106,7 @@ def minimum(a, b, out=None, queue=None):
|
|
|
3075
3106
|
|
|
3076
3107
|
# {{{ logical ops
|
|
3077
3108
|
|
|
3078
|
-
def _logical_op(x1, x2, out, operator, queue=None):
|
|
3109
|
+
def _logical_op(x1, x2, out, operator, queue: cl.CommandQueue | None = None):
|
|
3079
3110
|
# NOTE: Copied from pycuda.gpuarray
|
|
3080
3111
|
assert operator in ["&&", "||"]
|
|
3081
3112
|
|
|
@@ -3135,21 +3166,21 @@ def _logical_op(x1, x2, out, operator, queue=None):
|
|
|
3135
3166
|
return out
|
|
3136
3167
|
|
|
3137
3168
|
|
|
3138
|
-
def logical_and(x1, x2, /, out=None, queue=None):
|
|
3169
|
+
def logical_and(x1, x2, /, out=None, queue: cl.CommandQueue | None = None):
|
|
3139
3170
|
"""
|
|
3140
3171
|
Returns the element-wise logical AND of *x1* and *x2*.
|
|
3141
3172
|
"""
|
|
3142
3173
|
return _logical_op(x1, x2, out, "&&", queue=queue)
|
|
3143
3174
|
|
|
3144
3175
|
|
|
3145
|
-
def logical_or(x1, x2, /, out=None, queue=None):
|
|
3176
|
+
def logical_or(x1, x2, /, out=None, queue: cl.CommandQueue | None = None):
|
|
3146
3177
|
"""
|
|
3147
3178
|
Returns the element-wise logical OR of *x1* and *x2*.
|
|
3148
3179
|
"""
|
|
3149
3180
|
return _logical_op(x1, x2, out, "||", queue=queue)
|
|
3150
3181
|
|
|
3151
3182
|
|
|
3152
|
-
def logical_not(x, /, out=None, queue=None):
|
|
3183
|
+
def logical_not(x, /, out=None, queue: cl.CommandQueue | None = None):
|
|
3153
3184
|
"""
|
|
3154
3185
|
Returns the element-wise logical NOT of *x*.
|
|
3155
3186
|
"""
|
|
@@ -3171,11 +3202,16 @@ def logical_not(x, /, out=None, queue=None):
|
|
|
3171
3202
|
|
|
3172
3203
|
# {{{ reductions
|
|
3173
3204
|
|
|
3174
|
-
def sum(
|
|
3205
|
+
def sum(
|
|
3206
|
+
a,
|
|
3207
|
+
dtype=None,
|
|
3208
|
+
queue: cl.CommandQueue | None = None,
|
|
3209
|
+
slice=None,
|
|
3210
|
+
initial=_NoValue):
|
|
3175
3211
|
"""
|
|
3176
3212
|
.. versionadded:: 2011.1
|
|
3177
3213
|
"""
|
|
3178
|
-
if initial is not
|
|
3214
|
+
if initial is not _NoValue and not isinstance(initial, SCALAR_CLASSES):
|
|
3179
3215
|
raise ValueError("'initial' is not a scalar")
|
|
3180
3216
|
|
|
3181
3217
|
if dtype is not None:
|
|
@@ -3188,27 +3224,27 @@ def sum(a, dtype=None, queue=None, slice=None, initial=np._NoValue):
|
|
|
3188
3224
|
result.add_event(event1)
|
|
3189
3225
|
|
|
3190
3226
|
# NOTE: neutral element in `get_sum_kernel` is 0 by default
|
|
3191
|
-
if initial is not
|
|
3227
|
+
if initial is not _NoValue:
|
|
3192
3228
|
result += a.dtype.type(initial)
|
|
3193
3229
|
|
|
3194
3230
|
return result
|
|
3195
3231
|
|
|
3196
3232
|
|
|
3197
|
-
def any(a, queue=None, wait_for=None):
|
|
3233
|
+
def any(a, queue: cl.CommandQueue | None = None, wait_for: cl.WaitList = None):
|
|
3198
3234
|
if len(a) == 0:
|
|
3199
3235
|
return _BOOL_DTYPE.type(False)
|
|
3200
3236
|
|
|
3201
3237
|
return a.any(queue=queue, wait_for=wait_for)
|
|
3202
3238
|
|
|
3203
3239
|
|
|
3204
|
-
def all(a, queue=None, wait_for=None):
|
|
3240
|
+
def all(a, queue: cl.CommandQueue | None = None, wait_for: cl.WaitList = None):
|
|
3205
3241
|
if len(a) == 0:
|
|
3206
3242
|
return _BOOL_DTYPE.type(True)
|
|
3207
3243
|
|
|
3208
3244
|
return a.all(queue=queue, wait_for=wait_for)
|
|
3209
3245
|
|
|
3210
3246
|
|
|
3211
|
-
def dot(a, b, dtype=None, queue=None, slice=None):
|
|
3247
|
+
def dot(a, b, dtype=None, queue: cl.CommandQueue | None = None, slice=None):
|
|
3212
3248
|
"""
|
|
3213
3249
|
.. versionadded:: 2011.1
|
|
3214
3250
|
"""
|
|
@@ -3225,7 +3261,7 @@ def dot(a, b, dtype=None, queue=None, slice=None):
|
|
|
3225
3261
|
return result
|
|
3226
3262
|
|
|
3227
3263
|
|
|
3228
|
-
def vdot(a, b, dtype=None, queue=None, slice=None):
|
|
3264
|
+
def vdot(a, b, dtype=None, queue: cl.CommandQueue | None = None, slice=None):
|
|
3229
3265
|
"""Like :func:`numpy.vdot`.
|
|
3230
3266
|
|
|
3231
3267
|
.. versionadded:: 2013.1
|
|
@@ -3244,7 +3280,13 @@ def vdot(a, b, dtype=None, queue=None, slice=None):
|
|
|
3244
3280
|
return result
|
|
3245
3281
|
|
|
3246
3282
|
|
|
3247
|
-
def subset_dot(
|
|
3283
|
+
def subset_dot(
|
|
3284
|
+
subset,
|
|
3285
|
+
a,
|
|
3286
|
+
b,
|
|
3287
|
+
dtype=None,
|
|
3288
|
+
queue: cl.CommandQueue | None = None,
|
|
3289
|
+
slice=None):
|
|
3248
3290
|
"""
|
|
3249
3291
|
.. versionadded:: 2011.1
|
|
3250
3292
|
"""
|
|
@@ -3263,19 +3305,19 @@ def subset_dot(subset, a, b, dtype=None, queue=None, slice=None):
|
|
|
3263
3305
|
|
|
3264
3306
|
|
|
3265
3307
|
def _make_minmax_kernel(what):
|
|
3266
|
-
def f(a, queue=None, initial=
|
|
3308
|
+
def f(a, queue: cl.CommandQueue | None = None, initial=_NoValue):
|
|
3267
3309
|
if isinstance(a, SCALAR_CLASSES):
|
|
3268
3310
|
return np.array(a).dtype.type(a)
|
|
3269
3311
|
|
|
3270
3312
|
if len(a) == 0:
|
|
3271
|
-
if initial is
|
|
3313
|
+
if initial is _NoValue:
|
|
3272
3314
|
raise ValueError(
|
|
3273
3315
|
f"zero-size array to reduction '{what}' "
|
|
3274
3316
|
"which has no identity")
|
|
3275
3317
|
else:
|
|
3276
3318
|
return initial
|
|
3277
3319
|
|
|
3278
|
-
if initial is not
|
|
3320
|
+
if initial is not _NoValue and not isinstance(initial, SCALAR_CLASSES):
|
|
3279
3321
|
raise ValueError("'initial' is not a scalar")
|
|
3280
3322
|
|
|
3281
3323
|
from pyopencl.reduction import get_minmax_kernel
|
|
@@ -3284,7 +3326,7 @@ def _make_minmax_kernel(what):
|
|
|
3284
3326
|
return_event=True)
|
|
3285
3327
|
result.add_event(event1)
|
|
3286
3328
|
|
|
3287
|
-
if initial is not
|
|
3329
|
+
if initial is not _NoValue:
|
|
3288
3330
|
initial = a.dtype.type(initial)
|
|
3289
3331
|
if what == "min":
|
|
3290
3332
|
result = minimum(result, initial, queue=queue)
|
|
@@ -3312,7 +3354,7 @@ max.__doc__ = """
|
|
|
3312
3354
|
|
|
3313
3355
|
|
|
3314
3356
|
def _make_subset_minmax_kernel(what):
|
|
3315
|
-
def f(subset, a, queue=None, slice=None):
|
|
3357
|
+
def f(subset, a, queue: cl.CommandQueue | None = None, slice=None):
|
|
3316
3358
|
from pyopencl.reduction import get_subset_minmax_kernel
|
|
3317
3359
|
krnl = get_subset_minmax_kernel(a.context, what, a.dtype, subset.dtype)
|
|
3318
3360
|
result, event1 = krnl(subset, a, queue=queue, slice=slice,
|
|
@@ -3332,8 +3374,8 @@ subset_max.__doc__ = """.. versionadded:: 2011.1"""
|
|
|
3332
3374
|
|
|
3333
3375
|
# {{{ scans
|
|
3334
3376
|
|
|
3335
|
-
def cumsum(a, output_dtype=None, queue=None,
|
|
3336
|
-
wait_for=None, return_event=False):
|
|
3377
|
+
def cumsum(a, output_dtype=None, queue: cl.CommandQueue | None = None,
|
|
3378
|
+
wait_for: cl.WaitList = None, return_event=False):
|
|
3337
3379
|
# undocumented for now
|
|
3338
3380
|
|
|
3339
3381
|
"""
|