pyopencl 2025.1__cp313-cp313-win_amd64.whl → 2025.2.2__cp313-cp313-win_amd64.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 +582 -997
- pyopencl/_cl.cp313-win_amd64.pyd +0 -0
- pyopencl/_cl.pyi +2006 -0
- pyopencl/_cluda.py +3 -0
- pyopencl/_monkeypatch.py +1063 -0
- pyopencl/_mymako.py +3 -0
- pyopencl/algorithm.py +29 -24
- pyopencl/array.py +300 -255
- pyopencl/bitonic_sort.py +5 -2
- pyopencl/bitonic_sort_templates.py +3 -0
- pyopencl/cache.py +5 -5
- pyopencl/capture_call.py +31 -8
- pyopencl/characterize/__init__.py +26 -19
- pyopencl/characterize/performance.py +3 -0
- pyopencl/clmath.py +2 -0
- pyopencl/clrandom.py +3 -0
- pyopencl/cltypes.py +67 -2
- pyopencl/compyte/.basedpyright/baseline.json +1272 -0
- pyopencl/compyte/array.py +36 -9
- pyopencl/compyte/dtypes.py +61 -29
- pyopencl/compyte/pyproject.toml +17 -22
- pyopencl/elementwise.py +13 -10
- pyopencl/invoker.py +13 -17
- pyopencl/ipython_ext.py +2 -0
- pyopencl/py.typed +0 -0
- pyopencl/reduction.py +72 -43
- pyopencl/scan.py +31 -30
- pyopencl/tools.py +128 -90
- pyopencl/typing.py +57 -0
- pyopencl/version.py +2 -0
- {pyopencl-2025.1.dist-info → pyopencl-2025.2.2.dist-info}/METADATA +11 -10
- pyopencl-2025.2.2.dist-info/RECORD +47 -0
- {pyopencl-2025.1.dist-info → pyopencl-2025.2.2.dist-info}/WHEEL +1 -1
- pyopencl-2025.1.dist-info/RECORD +0 -42
- {pyopencl-2025.1.dist-info → pyopencl-2025.2.2.dist-info}/licenses/LICENSE +0 -0
pyopencl/array.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
# NOTE: for elwise_kernel_runner which adds keyword arguments
|
|
4
4
|
# pylint:disable=unexpected-keyword-arg
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
__copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
|
|
7
9
|
|
|
@@ -32,10 +34,19 @@ import builtins
|
|
|
32
34
|
from dataclasses import dataclass
|
|
33
35
|
from functools import reduce
|
|
34
36
|
from numbers import Number
|
|
35
|
-
from typing import
|
|
37
|
+
from typing import (
|
|
38
|
+
TYPE_CHECKING,
|
|
39
|
+
Any,
|
|
40
|
+
ClassVar,
|
|
41
|
+
Concatenate,
|
|
42
|
+
Literal,
|
|
43
|
+
ParamSpec,
|
|
44
|
+
cast,
|
|
45
|
+
)
|
|
36
46
|
from warnings import warn
|
|
37
47
|
|
|
38
48
|
import numpy as np
|
|
49
|
+
from typing_extensions import Self, override
|
|
39
50
|
|
|
40
51
|
import pyopencl as cl
|
|
41
52
|
import pyopencl.elementwise as elementwise
|
|
@@ -50,6 +61,14 @@ from pyopencl.compyte.array import (
|
|
|
50
61
|
)
|
|
51
62
|
|
|
52
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
|
+
|
|
53
72
|
SCALAR_CLASSES = (Number, np.bool_, bool)
|
|
54
73
|
|
|
55
74
|
if cl.get_cl_header_version() >= (2, 0):
|
|
@@ -58,6 +77,10 @@ else:
|
|
|
58
77
|
_SVMPointer_or_nothing = ()
|
|
59
78
|
|
|
60
79
|
|
|
80
|
+
class _NoValue:
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
|
|
61
84
|
# {{{ _get_common_dtype
|
|
62
85
|
|
|
63
86
|
class DoubleDowncastWarning(UserWarning):
|
|
@@ -160,7 +183,11 @@ vec = VecLookupWarner()
|
|
|
160
183
|
|
|
161
184
|
# {{{ helper functionality
|
|
162
185
|
|
|
163
|
-
def _splay(
|
|
186
|
+
def _splay(
|
|
187
|
+
device: cl.Device,
|
|
188
|
+
n: int,
|
|
189
|
+
kernel_specific_max_wg_size: int | None = None,
|
|
190
|
+
):
|
|
164
191
|
max_work_items = builtins.min(128, device.max_work_group_size)
|
|
165
192
|
|
|
166
193
|
if kernel_specific_max_wg_size is not None:
|
|
@@ -195,7 +222,12 @@ def _splay(device, n, kernel_specific_max_wg_size=None):
|
|
|
195
222
|
ARRAY_KERNEL_EXEC_HOOK = None
|
|
196
223
|
|
|
197
224
|
|
|
198
|
-
|
|
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]:
|
|
199
231
|
"""Take a kernel getter of the same signature as the kernel
|
|
200
232
|
and return a function that invokes that kernel.
|
|
201
233
|
|
|
@@ -204,40 +236,31 @@ def elwise_kernel_runner(kernel_getter):
|
|
|
204
236
|
from functools import wraps
|
|
205
237
|
|
|
206
238
|
@wraps(kernel_getter)
|
|
207
|
-
def kernel_runner(out, *args, **kwargs):
|
|
239
|
+
def kernel_runner(out: Array, *args: P.args, **kwargs: P.kwargs) -> cl.Event:
|
|
208
240
|
assert isinstance(out, Array)
|
|
209
241
|
|
|
210
|
-
wait_for = kwargs.pop("wait_for", None)
|
|
211
|
-
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))
|
|
212
244
|
if queue is None:
|
|
213
245
|
queue = out.queue
|
|
214
246
|
|
|
215
247
|
assert queue is not None
|
|
216
248
|
|
|
217
249
|
knl = kernel_getter(out, *args, **kwargs)
|
|
218
|
-
work_group_info = knl.get_work_group_info(
|
|
250
|
+
work_group_info = cast("int", knl.get_work_group_info(
|
|
219
251
|
cl.kernel_work_group_info.WORK_GROUP_SIZE,
|
|
220
|
-
queue.device)
|
|
252
|
+
queue.device))
|
|
221
253
|
gs, ls = out._get_sizes(queue, work_group_info)
|
|
222
254
|
|
|
223
|
-
|
|
255
|
+
knl_args = (out, *args, out.size)
|
|
224
256
|
if ARRAY_KERNEL_EXEC_HOOK is not None:
|
|
225
257
|
return ARRAY_KERNEL_EXEC_HOOK( # pylint: disable=not-callable
|
|
226
|
-
knl, queue, gs, ls, *
|
|
258
|
+
knl, queue, gs, ls, *knl_args, wait_for=wait_for)
|
|
227
259
|
else:
|
|
228
|
-
return knl(queue, gs, ls, *
|
|
260
|
+
return knl(queue, gs, ls, *knl_args, wait_for=wait_for)
|
|
229
261
|
|
|
230
262
|
return kernel_runner
|
|
231
263
|
|
|
232
|
-
|
|
233
|
-
class DefaultAllocator(cl.tools.DeferredAllocator):
|
|
234
|
-
def __init__(self, *args, **kwargs):
|
|
235
|
-
warn("pyopencl.array.DefaultAllocator is deprecated. "
|
|
236
|
-
"It will be continue to exist throughout the 2013.x "
|
|
237
|
-
"versions of PyOpenCL.",
|
|
238
|
-
DeprecationWarning, stacklevel=2)
|
|
239
|
-
cl.tools.DeferredAllocator.__init__(self, *args, **kwargs)
|
|
240
|
-
|
|
241
264
|
# }}}
|
|
242
265
|
|
|
243
266
|
|
|
@@ -262,7 +285,8 @@ class _copy_queue: # noqa: N801
|
|
|
262
285
|
pass
|
|
263
286
|
|
|
264
287
|
|
|
265
|
-
_ARRAY_GET_SIZES_CACHE:
|
|
288
|
+
_ARRAY_GET_SIZES_CACHE: \
|
|
289
|
+
dict[Hashable, tuple[tuple[int, ...], tuple[int, ...]]] = {}
|
|
266
290
|
_BOOL_DTYPE = np.dtype(np.int8)
|
|
267
291
|
_NOT_PRESENT = object()
|
|
268
292
|
|
|
@@ -453,29 +477,39 @@ class Array:
|
|
|
453
477
|
.. automethod:: finish
|
|
454
478
|
"""
|
|
455
479
|
|
|
456
|
-
__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
|
|
457
491
|
|
|
458
492
|
def __init__(
|
|
459
493
|
self,
|
|
460
|
-
cq:
|
|
461
|
-
shape:
|
|
462
|
-
dtype:
|
|
494
|
+
cq: cl.Context | cl.CommandQueue | None,
|
|
495
|
+
shape: tuple[int, ...] | int,
|
|
496
|
+
dtype: DTypeLike,
|
|
463
497
|
order: str = "C",
|
|
464
|
-
allocator:
|
|
498
|
+
allocator: Allocator | None = None,
|
|
465
499
|
data: Any = None,
|
|
466
500
|
offset: int = 0,
|
|
467
|
-
strides:
|
|
468
|
-
events:
|
|
501
|
+
strides: tuple[int, ...] | None = None,
|
|
502
|
+
events: list[cl.Event] | None = None,
|
|
469
503
|
|
|
470
504
|
# NOTE: following args are used for the fast constructor
|
|
471
505
|
_flags: Any = None,
|
|
472
506
|
_fast: bool = False,
|
|
473
|
-
_size:
|
|
474
|
-
_context:
|
|
475
|
-
_queue:
|
|
507
|
+
_size: int | None = None,
|
|
508
|
+
_context: cl.Context | None = None,
|
|
509
|
+
_queue: cl.CommandQueue | None = None) -> None:
|
|
476
510
|
if _fast:
|
|
477
511
|
# Assumptions, should be disabled if not testing
|
|
478
|
-
if
|
|
512
|
+
if TYPE_CHECKING:
|
|
479
513
|
assert cq is None
|
|
480
514
|
assert isinstance(_context, cl.Context)
|
|
481
515
|
assert _queue is None or isinstance(_queue, cl.CommandQueue)
|
|
@@ -648,8 +682,15 @@ class Array:
|
|
|
648
682
|
self._flags = f = _ArrayFlags(self)
|
|
649
683
|
return f
|
|
650
684
|
|
|
651
|
-
def _new_with_changes(self,
|
|
652
|
-
|
|
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:
|
|
653
694
|
"""
|
|
654
695
|
:arg data: *None* means allocate a new array.
|
|
655
696
|
"""
|
|
@@ -669,6 +710,8 @@ class Array:
|
|
|
669
710
|
queue = self.queue
|
|
670
711
|
if allocator is None:
|
|
671
712
|
allocator = self.allocator
|
|
713
|
+
if offset is None:
|
|
714
|
+
offset = self.offset
|
|
672
715
|
|
|
673
716
|
# If we're allocating new data, then there's not likely to be
|
|
674
717
|
# a data dependency. Otherwise, the two arrays should probably
|
|
@@ -684,7 +727,7 @@ class Array:
|
|
|
684
727
|
events=events,
|
|
685
728
|
_fast=fast, _context=self.context, _queue=queue, _size=size)
|
|
686
729
|
|
|
687
|
-
def with_queue(self, queue):
|
|
730
|
+
def with_queue(self, queue: cl.CommandQueue | None):
|
|
688
731
|
"""Return a copy of *self* with the default queue set to *queue*.
|
|
689
732
|
|
|
690
733
|
*None* is allowed as a value for *queue*.
|
|
@@ -698,7 +741,10 @@ class Array:
|
|
|
698
741
|
return self._new_with_changes(self.base_data, self.offset,
|
|
699
742
|
queue=queue)
|
|
700
743
|
|
|
701
|
-
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, ...]]:
|
|
702
748
|
if not self.flags.forc:
|
|
703
749
|
raise NotImplementedError("cannot operate on non-contiguous array")
|
|
704
750
|
cache_key = (queue.device.int_ptr, self.size, kernel_specific_max_wg_size)
|
|
@@ -710,7 +756,11 @@ class Array:
|
|
|
710
756
|
_ARRAY_GET_SIZES_CACHE[cache_key] = sizes
|
|
711
757
|
return sizes
|
|
712
758
|
|
|
713
|
-
def set(self,
|
|
759
|
+
def set(self,
|
|
760
|
+
ary: NDArray[Any],
|
|
761
|
+
queue: cl.CommandQueue | None = None,
|
|
762
|
+
async_: bool = False,
|
|
763
|
+
):
|
|
714
764
|
"""Transfer the contents the :class:`numpy.ndarray` object *ary*
|
|
715
765
|
onto the device.
|
|
716
766
|
|
|
@@ -720,32 +770,8 @@ class Array:
|
|
|
720
770
|
*async_* is a Boolean indicating whether the function is allowed
|
|
721
771
|
to return before the transfer completes. To avoid synchronization
|
|
722
772
|
bugs, this defaults to *False*.
|
|
723
|
-
|
|
724
|
-
.. versionchanged:: 2017.2.1
|
|
725
|
-
|
|
726
|
-
Python 3.7 makes ``async`` a reserved keyword. On older Pythons,
|
|
727
|
-
we will continue to accept *async* as a parameter, however this
|
|
728
|
-
should be considered deprecated. *async_* is the new, official
|
|
729
|
-
spelling.
|
|
730
773
|
"""
|
|
731
774
|
|
|
732
|
-
# {{{ handle 'async' deprecation
|
|
733
|
-
|
|
734
|
-
async_arg = kwargs.pop("async", None)
|
|
735
|
-
if async_arg is not None:
|
|
736
|
-
if async_ is not None:
|
|
737
|
-
raise TypeError("may not specify both 'async' and 'async_'")
|
|
738
|
-
async_ = async_arg
|
|
739
|
-
|
|
740
|
-
if async_ is None:
|
|
741
|
-
async_ = False
|
|
742
|
-
|
|
743
|
-
if kwargs:
|
|
744
|
-
raise TypeError("extra keyword arguments specified: %s"
|
|
745
|
-
% ", ".join(kwargs))
|
|
746
|
-
|
|
747
|
-
# }}}
|
|
748
|
-
|
|
749
775
|
assert ary.size == self.size
|
|
750
776
|
assert ary.dtype == self.dtype
|
|
751
777
|
|
|
@@ -753,36 +779,23 @@ class Array:
|
|
|
753
779
|
raise RuntimeError("cannot set from non-contiguous array")
|
|
754
780
|
|
|
755
781
|
if not _equal_strides(ary.strides, self.strides, self.shape):
|
|
756
|
-
|
|
757
|
-
"strides/storage order.
|
|
758
|
-
"in 2013.x.",
|
|
759
|
-
stacklevel=2)
|
|
782
|
+
raise RuntimeError("Setting array from one with different "
|
|
783
|
+
"strides/storage order.")
|
|
760
784
|
|
|
761
785
|
if self.size:
|
|
786
|
+
queue = queue or self.queue
|
|
787
|
+
assert queue is not None
|
|
762
788
|
event1 = cl.enqueue_copy(queue or self.queue, self.base_data, ary,
|
|
763
789
|
dst_offset=self.offset,
|
|
764
790
|
is_blocking=not async_)
|
|
765
791
|
|
|
766
792
|
self.add_event(event1)
|
|
767
793
|
|
|
768
|
-
def _get(self,
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
if async_ is not None:
|
|
774
|
-
raise TypeError("may not specify both 'async' and 'async_'")
|
|
775
|
-
async_ = async_arg
|
|
776
|
-
|
|
777
|
-
if async_ is None:
|
|
778
|
-
async_ = False
|
|
779
|
-
|
|
780
|
-
if kwargs:
|
|
781
|
-
raise TypeError("extra keyword arguments specified: %s"
|
|
782
|
-
% ", ".join(kwargs))
|
|
783
|
-
|
|
784
|
-
# }}}
|
|
785
|
-
|
|
794
|
+
def _get(self,
|
|
795
|
+
queue: cl.CommandQueue | None = None,
|
|
796
|
+
ary: NDArray[Any] | None = None,
|
|
797
|
+
async_: bool = False,
|
|
798
|
+
):
|
|
786
799
|
if ary is None:
|
|
787
800
|
ary = np.empty(self.shape, self.dtype)
|
|
788
801
|
|
|
@@ -809,52 +822,36 @@ class Array:
|
|
|
809
822
|
"to associate one.")
|
|
810
823
|
|
|
811
824
|
if self.size:
|
|
812
|
-
|
|
825
|
+
assert self.base_data is not None
|
|
826
|
+
event1 = cast("cl.Event", cl.enqueue_copy(queue, ary, self.base_data,
|
|
813
827
|
src_offset=self.offset,
|
|
814
|
-
wait_for=self.events, is_blocking=not async_)
|
|
828
|
+
wait_for=self.events, is_blocking=not async_))
|
|
815
829
|
|
|
816
830
|
self.add_event(event1)
|
|
817
831
|
else:
|
|
818
|
-
event1 =
|
|
832
|
+
event1 = cl.enqueue_marker(queue, wait_for=self.events)
|
|
833
|
+
if not async_:
|
|
834
|
+
event1.wait()
|
|
819
835
|
|
|
820
836
|
return ary, event1
|
|
821
837
|
|
|
822
|
-
def get(self,
|
|
838
|
+
def get(self,
|
|
839
|
+
queue: cl.CommandQueue | None = None,
|
|
840
|
+
ary: NDArray[Any] | None = None,
|
|
841
|
+
) -> NDArray[Any]:
|
|
823
842
|
"""Transfer the contents of *self* into *ary* or a newly allocated
|
|
824
843
|
:class:`numpy.ndarray`. If *ary* is given, it must have the same
|
|
825
844
|
shape and dtype.
|
|
826
|
-
|
|
827
|
-
.. versionchanged:: 2019.1.2
|
|
828
|
-
|
|
829
|
-
Calling with ``async_=True`` was deprecated and replaced by
|
|
830
|
-
:meth:`get_async`.
|
|
831
|
-
The event returned by :meth:`pyopencl.enqueue_copy` is now stored into
|
|
832
|
-
:attr:`events` to ensure data is not modified before the copy is
|
|
833
|
-
complete.
|
|
834
|
-
|
|
835
|
-
.. versionchanged:: 2015.2
|
|
836
|
-
|
|
837
|
-
*ary* with different shape was deprecated.
|
|
838
|
-
|
|
839
|
-
.. versionchanged:: 2017.2.1
|
|
840
|
-
|
|
841
|
-
Python 3.7 makes ``async`` a reserved keyword. On older Pythons,
|
|
842
|
-
we will continue to accept *async* as a parameter, however this
|
|
843
|
-
should be considered deprecated. *async_* is the new, official
|
|
844
|
-
spelling.
|
|
845
845
|
"""
|
|
846
846
|
|
|
847
|
-
|
|
848
|
-
warn("calling pyopencl.Array.get with 'async_=True' is deprecated. "
|
|
849
|
-
"Please use pyopencl.Array.get_async for asynchronous "
|
|
850
|
-
"device-to-host transfers",
|
|
851
|
-
DeprecationWarning, stacklevel=2)
|
|
852
|
-
|
|
853
|
-
ary, _event1 = self._get(queue=queue, ary=ary, async_=async_, **kwargs)
|
|
847
|
+
ary, _event1 = self._get(queue=queue, ary=ary)
|
|
854
848
|
|
|
855
849
|
return ary
|
|
856
850
|
|
|
857
|
-
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]:
|
|
858
855
|
"""
|
|
859
856
|
Asynchronous version of :meth:`get` which returns a tuple ``(ary, event)``
|
|
860
857
|
containing the host array ``ary``
|
|
@@ -864,9 +861,9 @@ class Array:
|
|
|
864
861
|
.. versionadded:: 2019.1.2
|
|
865
862
|
"""
|
|
866
863
|
|
|
867
|
-
return self._get(queue=queue, ary=ary, async_=True
|
|
864
|
+
return self._get(queue=queue, ary=ary, async_=True)
|
|
868
865
|
|
|
869
|
-
def copy(self, queue=_copy_queue):
|
|
866
|
+
def copy(self, queue: cl.CommandQueue | type[_copy_queue] | None = _copy_queue):
|
|
870
867
|
"""
|
|
871
868
|
:arg queue: The :class:`~pyopencl.CommandQueue` for the returned array.
|
|
872
869
|
|
|
@@ -878,20 +875,24 @@ class Array:
|
|
|
878
875
|
"""
|
|
879
876
|
|
|
880
877
|
if queue is _copy_queue:
|
|
881
|
-
|
|
878
|
+
queue_san = self.queue
|
|
879
|
+
else:
|
|
880
|
+
queue_san = cast("cl.CommandQueue | None", queue)
|
|
882
881
|
|
|
883
|
-
result = self._new_like_me(queue=
|
|
882
|
+
result = self._new_like_me(queue=queue_san)
|
|
884
883
|
|
|
885
884
|
# result.queue won't be the same as queue if queue is None.
|
|
886
885
|
# We force them to be the same here.
|
|
887
886
|
if result.queue is not queue:
|
|
888
|
-
result = result.with_queue(
|
|
887
|
+
result = result.with_queue(queue_san)
|
|
889
888
|
|
|
890
889
|
if not self.flags.forc:
|
|
891
890
|
raise RuntimeError("cannot copy non-contiguous array")
|
|
892
891
|
|
|
893
892
|
if self.nbytes:
|
|
894
|
-
|
|
893
|
+
queue_san = queue_san or self.queue
|
|
894
|
+
assert queue_san is not None
|
|
895
|
+
event1 = cl.enqueue_copy(queue_san,
|
|
895
896
|
result.base_data, self.base_data,
|
|
896
897
|
src_offset=self.offset, byte_count=self.nbytes,
|
|
897
898
|
wait_for=self.events)
|
|
@@ -932,7 +933,7 @@ class Array:
|
|
|
932
933
|
|
|
933
934
|
@staticmethod
|
|
934
935
|
@elwise_kernel_runner
|
|
935
|
-
def _axpbyz(out, afac, a, bfac, b, queue=None):
|
|
936
|
+
def _axpbyz(out, afac, a, bfac, b, queue: cl.CommandQueue | None = None):
|
|
936
937
|
"""Compute ``out = selffac * self + otherfac*other``,
|
|
937
938
|
where *other* is an array."""
|
|
938
939
|
a_shape = a.shape
|
|
@@ -948,7 +949,7 @@ class Array:
|
|
|
948
949
|
|
|
949
950
|
@staticmethod
|
|
950
951
|
@elwise_kernel_runner
|
|
951
|
-
def _axpbz(out, a, x, b, queue=None):
|
|
952
|
+
def _axpbz(out, a, x, b, queue: cl.CommandQueue | None = None):
|
|
952
953
|
"""Compute ``z = a * x + b``, where *b* is a scalar."""
|
|
953
954
|
a = np.array(a)
|
|
954
955
|
b = np.array(b)
|
|
@@ -958,7 +959,7 @@ class Array:
|
|
|
958
959
|
|
|
959
960
|
@staticmethod
|
|
960
961
|
@elwise_kernel_runner
|
|
961
|
-
def _elwise_multiply(out, a, b, queue=None):
|
|
962
|
+
def _elwise_multiply(out, a, b, queue: cl.CommandQueue | None = None):
|
|
962
963
|
a_shape = a.shape
|
|
963
964
|
b_shape = b.shape
|
|
964
965
|
out_shape = out.shape
|
|
@@ -973,7 +974,7 @@ class Array:
|
|
|
973
974
|
|
|
974
975
|
@staticmethod
|
|
975
976
|
@elwise_kernel_runner
|
|
976
|
-
def _rdiv_scalar(out, ary, other, queue=None):
|
|
977
|
+
def _rdiv_scalar(out, ary, other, queue: cl.CommandQueue | None = None):
|
|
977
978
|
other = np.array(other)
|
|
978
979
|
assert out.shape == ary.shape
|
|
979
980
|
return elementwise.get_rdivide_elwise_kernel(
|
|
@@ -981,7 +982,7 @@ class Array:
|
|
|
981
982
|
|
|
982
983
|
@staticmethod
|
|
983
984
|
@elwise_kernel_runner
|
|
984
|
-
def _div(out, self, other, queue=None):
|
|
985
|
+
def _div(out, self, other, queue: cl.CommandQueue | None = None):
|
|
985
986
|
"""Divides an array by another array."""
|
|
986
987
|
assert (self.shape == other.shape == out.shape
|
|
987
988
|
or (self.shape == () and other.shape == out.shape)
|
|
@@ -1071,7 +1072,7 @@ class Array:
|
|
|
1071
1072
|
return elementwise.get_copy_kernel(
|
|
1072
1073
|
dest.context, dest.dtype, src.dtype)
|
|
1073
1074
|
|
|
1074
|
-
def _new_like_me(self, dtype=None, queue=None):
|
|
1075
|
+
def _new_like_me(self, dtype=None, queue: cl.CommandQueue | None = None):
|
|
1075
1076
|
if dtype is None:
|
|
1076
1077
|
dtype = self.dtype
|
|
1077
1078
|
strides = self.strides
|
|
@@ -1095,14 +1096,14 @@ class Array:
|
|
|
1095
1096
|
|
|
1096
1097
|
@staticmethod
|
|
1097
1098
|
@elwise_kernel_runner
|
|
1098
|
-
def _scalar_binop(out, a, b, queue=None, op=None):
|
|
1099
|
+
def _scalar_binop(out, a, b, queue: cl.CommandQueue | None = None, op=None):
|
|
1099
1100
|
return elementwise.get_array_scalar_binop_kernel(
|
|
1100
1101
|
out.context, op, out.dtype, a.dtype,
|
|
1101
1102
|
np.array(b).dtype)
|
|
1102
1103
|
|
|
1103
1104
|
@staticmethod
|
|
1104
1105
|
@elwise_kernel_runner
|
|
1105
|
-
def _array_binop(out, a, b, queue=None, op=None):
|
|
1106
|
+
def _array_binop(out, a, b, queue: cl.CommandQueue | None = None, op=None):
|
|
1106
1107
|
a_shape = a.shape
|
|
1107
1108
|
b_shape = b.shape
|
|
1108
1109
|
out_shape = out.shape
|
|
@@ -1116,7 +1117,7 @@ class Array:
|
|
|
1116
1117
|
|
|
1117
1118
|
@staticmethod
|
|
1118
1119
|
@elwise_kernel_runner
|
|
1119
|
-
def _unop(out, a, queue=None, op=None):
|
|
1120
|
+
def _unop(out, a, queue: cl.CommandQueue | None = None, op=None):
|
|
1120
1121
|
if out.shape != a.shape:
|
|
1121
1122
|
raise ValueError("shapes of arguments do not match")
|
|
1122
1123
|
return elementwise.get_unop_kernel(
|
|
@@ -1126,7 +1127,7 @@ class Array:
|
|
|
1126
1127
|
|
|
1127
1128
|
# {{{ operators
|
|
1128
1129
|
|
|
1129
|
-
def mul_add(self, selffac, other, otherfac, queue=None):
|
|
1130
|
+
def mul_add(self, selffac, other, otherfac, queue: cl.CommandQueue | None = None):
|
|
1130
1131
|
"""Return ``selffac * self + otherfac * other``.
|
|
1131
1132
|
"""
|
|
1132
1133
|
queue = queue or self.queue
|
|
@@ -1149,7 +1150,7 @@ class Array:
|
|
|
1149
1150
|
else:
|
|
1150
1151
|
raise NotImplementedError
|
|
1151
1152
|
|
|
1152
|
-
def __add__(self, other):
|
|
1153
|
+
def __add__(self, other) -> Self:
|
|
1153
1154
|
"""Add an array with an array or an array with a scalar."""
|
|
1154
1155
|
|
|
1155
1156
|
if isinstance(other, Array):
|
|
@@ -1175,7 +1176,7 @@ class Array:
|
|
|
1175
1176
|
|
|
1176
1177
|
__radd__ = __add__
|
|
1177
1178
|
|
|
1178
|
-
def __sub__(self, other):
|
|
1179
|
+
def __sub__(self, other) -> Self:
|
|
1179
1180
|
"""Subtract an array from an array or a scalar from an array."""
|
|
1180
1181
|
|
|
1181
1182
|
if isinstance(other, Array):
|
|
@@ -1198,7 +1199,7 @@ class Array:
|
|
|
1198
1199
|
else:
|
|
1199
1200
|
return NotImplemented
|
|
1200
1201
|
|
|
1201
|
-
def __rsub__(self, other):
|
|
1202
|
+
def __rsub__(self, other) -> Self:
|
|
1202
1203
|
"""Subtracts an array by a scalar or an array::
|
|
1203
1204
|
|
|
1204
1205
|
x = n - self
|
|
@@ -1214,7 +1215,7 @@ class Array:
|
|
|
1214
1215
|
else:
|
|
1215
1216
|
return NotImplemented
|
|
1216
1217
|
|
|
1217
|
-
def __iadd__(self, other):
|
|
1218
|
+
def __iadd__(self, other) -> Self:
|
|
1218
1219
|
if isinstance(other, Array):
|
|
1219
1220
|
if other.shape != self.shape and other.shape != ():
|
|
1220
1221
|
raise NotImplementedError("Broadcasting binary op with shapes:"
|
|
@@ -1232,7 +1233,7 @@ class Array:
|
|
|
1232
1233
|
else:
|
|
1233
1234
|
return NotImplemented
|
|
1234
1235
|
|
|
1235
|
-
def __isub__(self, other):
|
|
1236
|
+
def __isub__(self, other) -> Self:
|
|
1236
1237
|
if isinstance(other, Array):
|
|
1237
1238
|
if other.shape != self.shape and other.shape != ():
|
|
1238
1239
|
raise NotImplementedError("Broadcasting binary op with shapes:"
|
|
@@ -1247,15 +1248,15 @@ class Array:
|
|
|
1247
1248
|
else:
|
|
1248
1249
|
return NotImplemented
|
|
1249
1250
|
|
|
1250
|
-
def __pos__(self):
|
|
1251
|
+
def __pos__(self) -> Self:
|
|
1251
1252
|
return self
|
|
1252
1253
|
|
|
1253
|
-
def __neg__(self):
|
|
1254
|
+
def __neg__(self) -> Self:
|
|
1254
1255
|
result = self._new_like_me()
|
|
1255
1256
|
result.add_event(self._axpbz(result, -1, self, 0))
|
|
1256
1257
|
return result
|
|
1257
1258
|
|
|
1258
|
-
def __mul__(self, other):
|
|
1259
|
+
def __mul__(self, other) -> Self:
|
|
1259
1260
|
if isinstance(other, Array):
|
|
1260
1261
|
result = _get_broadcasted_binary_op_result(self, other, self.queue)
|
|
1261
1262
|
result.add_event(
|
|
@@ -1271,7 +1272,7 @@ class Array:
|
|
|
1271
1272
|
else:
|
|
1272
1273
|
return NotImplemented
|
|
1273
1274
|
|
|
1274
|
-
def __rmul__(self, other):
|
|
1275
|
+
def __rmul__(self, other) -> Self:
|
|
1275
1276
|
if np.isscalar(other):
|
|
1276
1277
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1277
1278
|
result = self._new_like_me(common_dtype)
|
|
@@ -1282,7 +1283,7 @@ class Array:
|
|
|
1282
1283
|
else:
|
|
1283
1284
|
return NotImplemented
|
|
1284
1285
|
|
|
1285
|
-
def __imul__(self, other):
|
|
1286
|
+
def __imul__(self, other) -> Self:
|
|
1286
1287
|
if isinstance(other, Array):
|
|
1287
1288
|
if other.shape != self.shape and other.shape != ():
|
|
1288
1289
|
raise NotImplementedError("Broadcasting binary op with shapes:"
|
|
@@ -1297,7 +1298,7 @@ class Array:
|
|
|
1297
1298
|
else:
|
|
1298
1299
|
return NotImplemented
|
|
1299
1300
|
|
|
1300
|
-
def __div__(self, other):
|
|
1301
|
+
def __div__(self, other) -> Self:
|
|
1301
1302
|
"""Divides an array by an array or a scalar, i.e. ``self / other``.
|
|
1302
1303
|
"""
|
|
1303
1304
|
if isinstance(other, Array):
|
|
@@ -1323,7 +1324,7 @@ class Array:
|
|
|
1323
1324
|
|
|
1324
1325
|
__truediv__ = __div__
|
|
1325
1326
|
|
|
1326
|
-
def __rdiv__(self, other):
|
|
1327
|
+
def __rdiv__(self, other) -> Self:
|
|
1327
1328
|
"""Divides an array by a scalar or an array, i.e. ``other / self``.
|
|
1328
1329
|
"""
|
|
1329
1330
|
common_dtype = _get_truedivide_dtype(self, other, self.queue)
|
|
@@ -1342,7 +1343,7 @@ class Array:
|
|
|
1342
1343
|
|
|
1343
1344
|
__rtruediv__ = __rdiv__
|
|
1344
1345
|
|
|
1345
|
-
def __itruediv__(self, other):
|
|
1346
|
+
def __itruediv__(self, other) -> Self:
|
|
1346
1347
|
# raise an error if the result cannot be cast to self
|
|
1347
1348
|
common_dtype = _get_truedivide_dtype(self, other, self.queue)
|
|
1348
1349
|
if not np.can_cast(common_dtype, self.dtype.type, "same_kind"):
|
|
@@ -1367,7 +1368,7 @@ class Array:
|
|
|
1367
1368
|
else:
|
|
1368
1369
|
return NotImplemented
|
|
1369
1370
|
|
|
1370
|
-
def __and__(self, other):
|
|
1371
|
+
def __and__(self, other) -> Self:
|
|
1371
1372
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1372
1373
|
|
|
1373
1374
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1387,7 +1388,7 @@ class Array:
|
|
|
1387
1388
|
|
|
1388
1389
|
__rand__ = __and__ # commutes
|
|
1389
1390
|
|
|
1390
|
-
def __or__(self, other):
|
|
1391
|
+
def __or__(self, other) -> Self:
|
|
1391
1392
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1392
1393
|
|
|
1393
1394
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1408,7 +1409,7 @@ class Array:
|
|
|
1408
1409
|
|
|
1409
1410
|
__ror__ = __or__ # commutes
|
|
1410
1411
|
|
|
1411
|
-
def __xor__(self, other):
|
|
1412
|
+
def __xor__(self, other) -> Self:
|
|
1412
1413
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1413
1414
|
|
|
1414
1415
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1428,7 +1429,7 @@ class Array:
|
|
|
1428
1429
|
|
|
1429
1430
|
__rxor__ = __xor__ # commutes
|
|
1430
1431
|
|
|
1431
|
-
def __iand__(self, other):
|
|
1432
|
+
def __iand__(self, other) -> Self:
|
|
1432
1433
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1433
1434
|
|
|
1434
1435
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1447,7 +1448,7 @@ class Array:
|
|
|
1447
1448
|
else:
|
|
1448
1449
|
return NotImplemented
|
|
1449
1450
|
|
|
1450
|
-
def __ior__(self, other):
|
|
1451
|
+
def __ior__(self, other) -> Self:
|
|
1451
1452
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1452
1453
|
|
|
1453
1454
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1466,7 +1467,7 @@ class Array:
|
|
|
1466
1467
|
else:
|
|
1467
1468
|
return NotImplemented
|
|
1468
1469
|
|
|
1469
|
-
def __ixor__(self, other):
|
|
1470
|
+
def __ixor__(self, other) -> Self:
|
|
1470
1471
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1471
1472
|
|
|
1472
1473
|
if not np.issubdtype(common_dtype, np.integer):
|
|
@@ -1485,7 +1486,9 @@ class Array:
|
|
|
1485
1486
|
else:
|
|
1486
1487
|
return NotImplemented
|
|
1487
1488
|
|
|
1488
|
-
def _zero_fill(self,
|
|
1489
|
+
def _zero_fill(self,
|
|
1490
|
+
queue: cl.CommandQueue | None = None,
|
|
1491
|
+
wait_for: cl.WaitList = None) -> None:
|
|
1489
1492
|
queue = queue or self.queue
|
|
1490
1493
|
|
|
1491
1494
|
if not self.size:
|
|
@@ -1507,7 +1510,10 @@ class Array:
|
|
|
1507
1510
|
zero = np.zeros((), self.dtype)
|
|
1508
1511
|
self.fill(zero, queue=queue)
|
|
1509
1512
|
|
|
1510
|
-
def fill(self,
|
|
1513
|
+
def fill(self,
|
|
1514
|
+
value: object,
|
|
1515
|
+
queue: cl.CommandQueue | None = None,
|
|
1516
|
+
wait_for: cl.WaitList = None) -> Self:
|
|
1511
1517
|
"""Fill the array with *scalar*.
|
|
1512
1518
|
|
|
1513
1519
|
:returns: *self*.
|
|
@@ -1518,14 +1524,14 @@ class Array:
|
|
|
1518
1524
|
|
|
1519
1525
|
return self
|
|
1520
1526
|
|
|
1521
|
-
def __len__(self):
|
|
1527
|
+
def __len__(self) -> int:
|
|
1522
1528
|
"""Returns the size of the leading dimension of *self*."""
|
|
1523
1529
|
if len(self.shape):
|
|
1524
1530
|
return self.shape[0]
|
|
1525
1531
|
else:
|
|
1526
1532
|
return TypeError("len() of unsized object")
|
|
1527
1533
|
|
|
1528
|
-
def __abs__(self):
|
|
1534
|
+
def __abs__(self) -> Self:
|
|
1529
1535
|
"""Return an ``Array`` of the absolute values of the elements
|
|
1530
1536
|
of *self*.
|
|
1531
1537
|
"""
|
|
@@ -1534,7 +1540,7 @@ class Array:
|
|
|
1534
1540
|
result.add_event(self._abs(result, self))
|
|
1535
1541
|
return result
|
|
1536
1542
|
|
|
1537
|
-
def __pow__(self, other):
|
|
1543
|
+
def __pow__(self, other) -> Self:
|
|
1538
1544
|
"""Exponentiation by a scalar or elementwise by another
|
|
1539
1545
|
:class:`Array`.
|
|
1540
1546
|
"""
|
|
@@ -1555,7 +1561,7 @@ class Array:
|
|
|
1555
1561
|
else:
|
|
1556
1562
|
return NotImplemented
|
|
1557
1563
|
|
|
1558
|
-
def __rpow__(self, other):
|
|
1564
|
+
def __rpow__(self, other) -> Self:
|
|
1559
1565
|
if np.isscalar(other):
|
|
1560
1566
|
common_dtype = _get_common_dtype(self, other, self.queue)
|
|
1561
1567
|
result = self._new_like_me(common_dtype)
|
|
@@ -1576,7 +1582,7 @@ class Array:
|
|
|
1576
1582
|
|
|
1577
1583
|
# }}}
|
|
1578
1584
|
|
|
1579
|
-
def reverse(self, queue=None):
|
|
1585
|
+
def reverse(self, queue: cl.CommandQueue | None = None) -> Self:
|
|
1580
1586
|
"""Return this array in reversed order. The array is treated
|
|
1581
1587
|
as one-dimensional.
|
|
1582
1588
|
"""
|
|
@@ -1585,7 +1591,7 @@ class Array:
|
|
|
1585
1591
|
result.add_event(self._reverse(result, self))
|
|
1586
1592
|
return result
|
|
1587
1593
|
|
|
1588
|
-
def astype(self, dtype, queue=None):
|
|
1594
|
+
def astype(self, dtype, queue: cl.CommandQueue | None = None):
|
|
1589
1595
|
"""Return a copy of *self*, cast to *dtype*."""
|
|
1590
1596
|
if dtype == self.dtype:
|
|
1591
1597
|
return self.copy()
|
|
@@ -1596,48 +1602,55 @@ class Array:
|
|
|
1596
1602
|
|
|
1597
1603
|
# {{{ rich comparisons, any, all
|
|
1598
1604
|
|
|
1599
|
-
def __bool__(self):
|
|
1605
|
+
def __bool__(self) -> bool:
|
|
1600
1606
|
if self.shape == ():
|
|
1601
1607
|
return bool(self.get())
|
|
1602
1608
|
else:
|
|
1603
1609
|
raise ValueError("The truth value of an array with "
|
|
1604
1610
|
"more than one element is ambiguous. Use a.any() or a.all()")
|
|
1605
1611
|
|
|
1606
|
-
def any(self,
|
|
1612
|
+
def any(self,
|
|
1613
|
+
queue: cl.CommandQueue | None = None,
|
|
1614
|
+
wait_for: cl.WaitList = None
|
|
1615
|
+
) -> Self:
|
|
1607
1616
|
from pyopencl.reduction import get_any_kernel
|
|
1608
1617
|
krnl = get_any_kernel(self.context, self.dtype)
|
|
1609
1618
|
if wait_for is None:
|
|
1610
1619
|
wait_for = []
|
|
1611
1620
|
result, event1 = krnl(self, queue=queue,
|
|
1612
|
-
wait_for=wait_for
|
|
1621
|
+
wait_for=[*wait_for, *self.events], return_event=True)
|
|
1613
1622
|
result.add_event(event1)
|
|
1614
1623
|
return result
|
|
1615
1624
|
|
|
1616
|
-
def all(self,
|
|
1625
|
+
def all(self,
|
|
1626
|
+
queue: cl.CommandQueue | None = None,
|
|
1627
|
+
wait_for: cl.WaitList = None
|
|
1628
|
+
) -> Self:
|
|
1617
1629
|
from pyopencl.reduction import get_all_kernel
|
|
1618
1630
|
krnl = get_all_kernel(self.context, self.dtype)
|
|
1619
1631
|
if wait_for is None:
|
|
1620
1632
|
wait_for = []
|
|
1621
1633
|
result, event1 = krnl(self, queue=queue,
|
|
1622
|
-
wait_for=wait_for
|
|
1634
|
+
wait_for=[*wait_for, *self.events], return_event=True)
|
|
1623
1635
|
result.add_event(event1)
|
|
1624
1636
|
return result
|
|
1625
1637
|
|
|
1626
1638
|
@staticmethod
|
|
1627
1639
|
@elwise_kernel_runner
|
|
1628
|
-
def _scalar_comparison(out, a, b, queue=None, op=None):
|
|
1640
|
+
def _scalar_comparison(out, a, b, queue: cl.CommandQueue | None = None, op=None):
|
|
1629
1641
|
return elementwise.get_array_scalar_comparison_kernel(
|
|
1630
1642
|
out.context, op, a.dtype)
|
|
1631
1643
|
|
|
1632
1644
|
@staticmethod
|
|
1633
1645
|
@elwise_kernel_runner
|
|
1634
|
-
def _array_comparison(out, a, b, queue=None, op=None):
|
|
1646
|
+
def _array_comparison(out, a, b, queue: cl.CommandQueue | None = None, op=None):
|
|
1635
1647
|
if a.shape != b.shape:
|
|
1636
1648
|
raise ValueError("shapes of comparison arguments do not match")
|
|
1637
1649
|
return elementwise.get_array_comparison_kernel(
|
|
1638
1650
|
out.context, op, a.dtype, b.dtype)
|
|
1639
1651
|
|
|
1640
|
-
|
|
1652
|
+
@override
|
|
1653
|
+
def __eq__(self, other: object) -> Self: # pyright: ignore[reportIncompatibleMethodOverride]
|
|
1641
1654
|
if isinstance(other, Array):
|
|
1642
1655
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1643
1656
|
result.add_event(
|
|
@@ -1651,7 +1664,8 @@ class Array:
|
|
|
1651
1664
|
else:
|
|
1652
1665
|
return NotImplemented
|
|
1653
1666
|
|
|
1654
|
-
|
|
1667
|
+
@override
|
|
1668
|
+
def __ne__(self, other: object) -> Self: # pyright: ignore[reportIncompatibleMethodOverride]
|
|
1655
1669
|
if isinstance(other, Array):
|
|
1656
1670
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1657
1671
|
result.add_event(
|
|
@@ -1665,7 +1679,7 @@ class Array:
|
|
|
1665
1679
|
else:
|
|
1666
1680
|
return NotImplemented
|
|
1667
1681
|
|
|
1668
|
-
def __le__(self, other):
|
|
1682
|
+
def __le__(self, other) -> Self:
|
|
1669
1683
|
if isinstance(other, Array):
|
|
1670
1684
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1671
1685
|
result.add_event(
|
|
@@ -1678,7 +1692,7 @@ class Array:
|
|
|
1678
1692
|
else:
|
|
1679
1693
|
return NotImplemented
|
|
1680
1694
|
|
|
1681
|
-
def __ge__(self, other):
|
|
1695
|
+
def __ge__(self, other) -> Self:
|
|
1682
1696
|
if isinstance(other, Array):
|
|
1683
1697
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1684
1698
|
result.add_event(
|
|
@@ -1692,7 +1706,7 @@ class Array:
|
|
|
1692
1706
|
else:
|
|
1693
1707
|
return NotImplemented
|
|
1694
1708
|
|
|
1695
|
-
def __lt__(self, other):
|
|
1709
|
+
def __lt__(self, other) -> Self:
|
|
1696
1710
|
if isinstance(other, Array):
|
|
1697
1711
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1698
1712
|
result.add_event(
|
|
@@ -1706,7 +1720,7 @@ class Array:
|
|
|
1706
1720
|
else:
|
|
1707
1721
|
return NotImplemented
|
|
1708
1722
|
|
|
1709
|
-
def __gt__(self, other):
|
|
1723
|
+
def __gt__(self, other) -> Self:
|
|
1710
1724
|
if isinstance(other, Array):
|
|
1711
1725
|
result = self._new_like_me(_BOOL_DTYPE)
|
|
1712
1726
|
result.add_event(
|
|
@@ -1725,7 +1739,7 @@ class Array:
|
|
|
1725
1739
|
# {{{ complex-valued business
|
|
1726
1740
|
|
|
1727
1741
|
@property
|
|
1728
|
-
def real(self):
|
|
1742
|
+
def real(self) -> Self:
|
|
1729
1743
|
"""
|
|
1730
1744
|
.. versionadded:: 2012.1
|
|
1731
1745
|
"""
|
|
@@ -1738,7 +1752,7 @@ class Array:
|
|
|
1738
1752
|
return self
|
|
1739
1753
|
|
|
1740
1754
|
@property
|
|
1741
|
-
def imag(self):
|
|
1755
|
+
def imag(self) -> Self:
|
|
1742
1756
|
"""
|
|
1743
1757
|
.. versionadded:: 2012.1
|
|
1744
1758
|
"""
|
|
@@ -1750,7 +1764,7 @@ class Array:
|
|
|
1750
1764
|
else:
|
|
1751
1765
|
return zeros_like(self)
|
|
1752
1766
|
|
|
1753
|
-
def conj(self):
|
|
1767
|
+
def conj(self) -> Self:
|
|
1754
1768
|
"""
|
|
1755
1769
|
.. versionadded:: 2012.1
|
|
1756
1770
|
"""
|
|
@@ -1767,7 +1781,7 @@ class Array:
|
|
|
1767
1781
|
|
|
1768
1782
|
# {{{ event management
|
|
1769
1783
|
|
|
1770
|
-
def add_event(self, evt):
|
|
1784
|
+
def add_event(self, evt: cl.Event) -> None:
|
|
1771
1785
|
"""Add *evt* to :attr:`events`. If :attr:`events` is too long, this method
|
|
1772
1786
|
may implicitly wait for a subset of :attr:`events` and clear them from the
|
|
1773
1787
|
list.
|
|
@@ -1781,7 +1795,7 @@ class Array:
|
|
|
1781
1795
|
cl.wait_for_events(wait_events)
|
|
1782
1796
|
del self.events[:n_wait]
|
|
1783
1797
|
|
|
1784
|
-
def finish(self):
|
|
1798
|
+
def finish(self) -> None:
|
|
1785
1799
|
"""Wait for the entire contents of :attr:`events`, clear it."""
|
|
1786
1800
|
|
|
1787
1801
|
if self.events:
|
|
@@ -1956,13 +1970,13 @@ class Array:
|
|
|
1956
1970
|
raise ValueError("new type not compatible with array")
|
|
1957
1971
|
|
|
1958
1972
|
new_shape = (
|
|
1959
|
-
self.shape[:min_stride_axis]
|
|
1960
|
-
|
|
1961
|
-
|
|
1973
|
+
*self.shape[:min_stride_axis],
|
|
1974
|
+
self.shape[min_stride_axis] * old_itemsize // itemsize,
|
|
1975
|
+
*self.shape[min_stride_axis+1:])
|
|
1962
1976
|
new_strides = (
|
|
1963
|
-
self.strides[:min_stride_axis]
|
|
1964
|
-
|
|
1965
|
-
|
|
1977
|
+
*self.strides[:min_stride_axis],
|
|
1978
|
+
self.strides[min_stride_axis] * itemsize // old_itemsize,
|
|
1979
|
+
*self.strides[min_stride_axis+1:])
|
|
1966
1980
|
|
|
1967
1981
|
return self._new_with_changes(
|
|
1968
1982
|
self.base_data, self.offset,
|
|
@@ -2019,7 +2033,11 @@ class Array:
|
|
|
2019
2033
|
|
|
2020
2034
|
# }}}
|
|
2021
2035
|
|
|
2022
|
-
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):
|
|
2023
2041
|
"""If *is_blocking*, return a :class:`numpy.ndarray` corresponding to the
|
|
2024
2042
|
same memory as *self*.
|
|
2025
2043
|
|
|
@@ -2043,7 +2061,7 @@ class Array:
|
|
|
2043
2061
|
ary, evt = cl.enqueue_map_buffer(
|
|
2044
2062
|
queue or self.queue, self.base_data, flags, self.offset,
|
|
2045
2063
|
self.shape, self.dtype, strides=self.strides,
|
|
2046
|
-
wait_for=wait_for
|
|
2064
|
+
wait_for=[*wait_for, *self.events], is_blocking=is_blocking)
|
|
2047
2065
|
|
|
2048
2066
|
if is_blocking:
|
|
2049
2067
|
return ary
|
|
@@ -2150,7 +2168,12 @@ class Array:
|
|
|
2150
2168
|
shape=tuple(new_shape),
|
|
2151
2169
|
strides=tuple(new_strides))
|
|
2152
2170
|
|
|
2153
|
-
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
|
+
):
|
|
2154
2177
|
"""Like :meth:`__setitem__`, but with the ability to specify
|
|
2155
2178
|
a *queue* and *wait_for*.
|
|
2156
2179
|
|
|
@@ -2161,10 +2184,11 @@ class Array:
|
|
|
2161
2184
|
Added *wait_for*.
|
|
2162
2185
|
"""
|
|
2163
2186
|
|
|
2164
|
-
queue = queue or self.queue
|
|
2187
|
+
queue = queue or self.queue
|
|
2188
|
+
assert queue is not None
|
|
2165
2189
|
if wait_for is None:
|
|
2166
2190
|
wait_for = []
|
|
2167
|
-
wait_for = wait_for
|
|
2191
|
+
wait_for = [*wait_for, *self.events]
|
|
2168
2192
|
|
|
2169
2193
|
if isinstance(subscript, Array):
|
|
2170
2194
|
if subscript.dtype.kind not in ("i", "u"):
|
|
@@ -2190,6 +2214,7 @@ class Array:
|
|
|
2190
2214
|
|
|
2191
2215
|
if isinstance(value, np.ndarray):
|
|
2192
2216
|
if subarray.shape == value.shape and subarray.strides == value.strides:
|
|
2217
|
+
assert subarray.base_data is not None
|
|
2193
2218
|
self.add_event(
|
|
2194
2219
|
cl.enqueue_copy(queue, subarray.base_data,
|
|
2195
2220
|
value, dst_offset=subarray.offset, wait_for=wait_for))
|
|
@@ -2259,8 +2284,13 @@ class _same_as_transfer: # noqa: N801
|
|
|
2259
2284
|
pass
|
|
2260
2285
|
|
|
2261
2286
|
|
|
2262
|
-
def to_device(
|
|
2263
|
-
|
|
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:
|
|
2264
2294
|
"""Return a :class:`Array` that is an exact copy of the
|
|
2265
2295
|
:class:`numpy.ndarray` instance *ary*.
|
|
2266
2296
|
|
|
@@ -2273,32 +2303,8 @@ def to_device(queue, ary, allocator=None, async_=None,
|
|
|
2273
2303
|
|
|
2274
2304
|
.. versionchanged:: 2015.2
|
|
2275
2305
|
*array_queue* argument was added.
|
|
2276
|
-
|
|
2277
|
-
.. versionchanged:: 2017.2.1
|
|
2278
|
-
|
|
2279
|
-
Python 3.7 makes ``async`` a reserved keyword. On older Pythons,
|
|
2280
|
-
we will continue to accept *async* as a parameter, however this
|
|
2281
|
-
should be considered deprecated. *async_* is the new, official
|
|
2282
|
-
spelling.
|
|
2283
2306
|
"""
|
|
2284
2307
|
|
|
2285
|
-
# {{{ handle 'async' deprecation
|
|
2286
|
-
|
|
2287
|
-
async_arg = kwargs.pop("async", None)
|
|
2288
|
-
if async_arg is not None:
|
|
2289
|
-
if async_ is not None:
|
|
2290
|
-
raise TypeError("may not specify both 'async' and 'async_'")
|
|
2291
|
-
async_ = async_arg
|
|
2292
|
-
|
|
2293
|
-
if async_ is None:
|
|
2294
|
-
async_ = False
|
|
2295
|
-
|
|
2296
|
-
if kwargs:
|
|
2297
|
-
raise TypeError("extra keyword arguments specified: %s"
|
|
2298
|
-
% ", ".join(kwargs))
|
|
2299
|
-
|
|
2300
|
-
# }}}
|
|
2301
|
-
|
|
2302
2308
|
if ary.dtype == object:
|
|
2303
2309
|
raise RuntimeError("to_device does not work on object arrays.")
|
|
2304
2310
|
|
|
@@ -2316,7 +2322,13 @@ def to_device(queue, ary, allocator=None, async_=None,
|
|
|
2316
2322
|
empty = Array
|
|
2317
2323
|
|
|
2318
2324
|
|
|
2319
|
-
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:
|
|
2320
2332
|
"""Same as :func:`empty`, but the :class:`Array` is zero-initialized before
|
|
2321
2333
|
being returned.
|
|
2322
2334
|
|
|
@@ -2331,7 +2343,11 @@ def zeros(queue, shape, dtype, order="C", allocator=None):
|
|
|
2331
2343
|
return result
|
|
2332
2344
|
|
|
2333
2345
|
|
|
2334
|
-
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
|
+
):
|
|
2335
2351
|
"""Make a new, uninitialized :class:`Array` having the same properties
|
|
2336
2352
|
as *other_ary*.
|
|
2337
2353
|
"""
|
|
@@ -2352,11 +2368,11 @@ def zeros_like(ary):
|
|
|
2352
2368
|
|
|
2353
2369
|
@dataclass
|
|
2354
2370
|
class _ArangeInfo:
|
|
2355
|
-
start:
|
|
2356
|
-
stop:
|
|
2357
|
-
step:
|
|
2358
|
-
dtype:
|
|
2359
|
-
allocator:
|
|
2371
|
+
start: int | None = None
|
|
2372
|
+
stop: int | None = None
|
|
2373
|
+
step: int | None = None
|
|
2374
|
+
dtype: np.dtype | None = None
|
|
2375
|
+
allocator: Any | None = None
|
|
2360
2376
|
|
|
2361
2377
|
|
|
2362
2378
|
@elwise_kernel_runner
|
|
@@ -2463,7 +2479,13 @@ def _take(result, ary, indices):
|
|
|
2463
2479
|
result.context, result.dtype, indices.dtype)
|
|
2464
2480
|
|
|
2465
2481
|
|
|
2466
|
-
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:
|
|
2467
2489
|
"""Return the :class:`Array` ``[a[indices[0]], ..., a[indices[n]]]``.
|
|
2468
2490
|
For the moment, *a* must be a type that can be bound to a texture.
|
|
2469
2491
|
"""
|
|
@@ -2478,7 +2500,7 @@ def take(a, indices, out=None, queue=None, wait_for=None):
|
|
|
2478
2500
|
return out
|
|
2479
2501
|
|
|
2480
2502
|
|
|
2481
|
-
def multi_take(arrays, indices, out=None, queue=None):
|
|
2503
|
+
def multi_take(arrays, indices, out=None, queue: cl.CommandQueue | None = None):
|
|
2482
2504
|
if not len(arrays):
|
|
2483
2505
|
return []
|
|
2484
2506
|
|
|
@@ -2541,7 +2563,7 @@ def multi_take(arrays, indices, out=None, queue=None):
|
|
|
2541
2563
|
|
|
2542
2564
|
|
|
2543
2565
|
def multi_take_put(arrays, dest_indices, src_indices, dest_shape=None,
|
|
2544
|
-
out=None, queue=None, src_offsets=None):
|
|
2566
|
+
out=None, queue: cl.CommandQueue | None = None, src_offsets=None):
|
|
2545
2567
|
if not len(arrays):
|
|
2546
2568
|
return []
|
|
2547
2569
|
|
|
@@ -2623,8 +2645,14 @@ def multi_take_put(arrays, dest_indices, src_indices, dest_shape=None,
|
|
|
2623
2645
|
return out
|
|
2624
2646
|
|
|
2625
2647
|
|
|
2626
|
-
def multi_put(
|
|
2627
|
-
|
|
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
|
+
):
|
|
2628
2656
|
if not len(arrays):
|
|
2629
2657
|
return []
|
|
2630
2658
|
|
|
@@ -2633,9 +2661,10 @@ def multi_put(arrays, dest_indices, dest_shape=None, out=None, queue=None,
|
|
|
2633
2661
|
a_allocator = arrays[0].allocator
|
|
2634
2662
|
context = dest_indices.context
|
|
2635
2663
|
queue = queue or dest_indices.queue
|
|
2664
|
+
assert queue is not None
|
|
2636
2665
|
if wait_for is None:
|
|
2637
2666
|
wait_for = []
|
|
2638
|
-
wait_for = wait_for
|
|
2667
|
+
wait_for = [*wait_for, *dest_indices.events]
|
|
2639
2668
|
|
|
2640
2669
|
vec_count = len(arrays)
|
|
2641
2670
|
|
|
@@ -2702,7 +2731,7 @@ def multi_put(arrays, dest_indices, dest_shape=None, out=None, queue=None,
|
|
|
2702
2731
|
return out
|
|
2703
2732
|
|
|
2704
2733
|
|
|
2705
|
-
def concatenate(arrays, axis=0, queue=None, allocator=None):
|
|
2734
|
+
def concatenate(arrays, axis=0, queue: cl.CommandQueue | None = None, allocator=None):
|
|
2706
2735
|
"""
|
|
2707
2736
|
.. versionadded:: 2013.1
|
|
2708
2737
|
|
|
@@ -2759,9 +2788,9 @@ def concatenate(arrays, axis=0, queue=None, allocator=None):
|
|
|
2759
2788
|
for ary in arrays:
|
|
2760
2789
|
my_len = ary.shape[axis]
|
|
2761
2790
|
result.setitem(
|
|
2762
|
-
full_slice[:axis]
|
|
2763
|
-
|
|
2764
|
-
|
|
2791
|
+
(*full_slice[:axis],
|
|
2792
|
+
slice(base_idx, base_idx+my_len),
|
|
2793
|
+
*full_slice[axis+1:]),
|
|
2765
2794
|
ary)
|
|
2766
2795
|
|
|
2767
2796
|
base_idx += my_len
|
|
@@ -2774,7 +2803,7 @@ def _diff(result, array):
|
|
|
2774
2803
|
return elementwise.get_diff_kernel(array.context, array.dtype)
|
|
2775
2804
|
|
|
2776
2805
|
|
|
2777
|
-
def diff(array, queue=None, allocator=None):
|
|
2806
|
+
def diff(array, queue: cl.CommandQueue | None = None, allocator=None):
|
|
2778
2807
|
"""
|
|
2779
2808
|
.. versionadded:: 2013.2
|
|
2780
2809
|
"""
|
|
@@ -2793,7 +2822,7 @@ def diff(array, queue=None, allocator=None):
|
|
|
2793
2822
|
return result
|
|
2794
2823
|
|
|
2795
2824
|
|
|
2796
|
-
def hstack(arrays, queue=None):
|
|
2825
|
+
def hstack(arrays, queue: cl.CommandQueue | None = None):
|
|
2797
2826
|
if len(arrays) == 0:
|
|
2798
2827
|
raise ValueError("need at least one array to hstack")
|
|
2799
2828
|
|
|
@@ -2828,7 +2857,7 @@ def hstack(arrays, queue=None):
|
|
|
2828
2857
|
return result
|
|
2829
2858
|
|
|
2830
2859
|
|
|
2831
|
-
def stack(arrays, axis=0, queue=None):
|
|
2860
|
+
def stack(arrays, axis=0, queue: cl.CommandQueue | None = None):
|
|
2832
2861
|
"""
|
|
2833
2862
|
Join a sequence of arrays along a new axis.
|
|
2834
2863
|
|
|
@@ -2867,7 +2896,7 @@ def stack(arrays, axis=0, queue=None):
|
|
|
2867
2896
|
# pyopencl.Array.__setitem__ does not support non-contiguous assignments
|
|
2868
2897
|
raise NotImplementedError
|
|
2869
2898
|
|
|
2870
|
-
result_shape = input_shape[:axis]
|
|
2899
|
+
result_shape = (*input_shape[:axis], len(arrays), *input_shape[axis:])
|
|
2871
2900
|
|
|
2872
2901
|
if __debug__:
|
|
2873
2902
|
if builtins.any(type(ary) != type(arrays[0]) # noqa: E721
|
|
@@ -2931,7 +2960,12 @@ def _if_positive(result, criterion, then_, else_):
|
|
|
2931
2960
|
)
|
|
2932
2961
|
|
|
2933
2962
|
|
|
2934
|
-
def if_positive(
|
|
2963
|
+
def if_positive(
|
|
2964
|
+
criterion,
|
|
2965
|
+
then_,
|
|
2966
|
+
else_,
|
|
2967
|
+
out=None,
|
|
2968
|
+
queue: cl.CommandQueue | None = None):
|
|
2935
2969
|
"""Return an array like *then_*, which, for the element at index *i*,
|
|
2936
2970
|
contains *then_[i]* if *criterion[i]>0*, else *else_[i]*.
|
|
2937
2971
|
"""
|
|
@@ -3015,7 +3049,7 @@ def _minimum_maximum_backend(out, a, b, minmax):
|
|
|
3015
3049
|
elementwise.get_argument_kind(b))
|
|
3016
3050
|
|
|
3017
3051
|
|
|
3018
|
-
def maximum(a, b, out=None, queue=None):
|
|
3052
|
+
def maximum(a, b, out=None, queue: cl.CommandQueue | None = None):
|
|
3019
3053
|
"""Return the elementwise maximum of *a* and *b*."""
|
|
3020
3054
|
|
|
3021
3055
|
a_is_scalar = np.isscalar(a)
|
|
@@ -3042,7 +3076,7 @@ def maximum(a, b, out=None, queue=None):
|
|
|
3042
3076
|
return out
|
|
3043
3077
|
|
|
3044
3078
|
|
|
3045
|
-
def minimum(a, b, out=None, queue=None):
|
|
3079
|
+
def minimum(a, b, out=None, queue: cl.CommandQueue | None = None):
|
|
3046
3080
|
"""Return the elementwise minimum of *a* and *b*."""
|
|
3047
3081
|
a_is_scalar = np.isscalar(a)
|
|
3048
3082
|
b_is_scalar = np.isscalar(b)
|
|
@@ -3072,7 +3106,7 @@ def minimum(a, b, out=None, queue=None):
|
|
|
3072
3106
|
|
|
3073
3107
|
# {{{ logical ops
|
|
3074
3108
|
|
|
3075
|
-
def _logical_op(x1, x2, out, operator, queue=None):
|
|
3109
|
+
def _logical_op(x1, x2, out, operator, queue: cl.CommandQueue | None = None):
|
|
3076
3110
|
# NOTE: Copied from pycuda.gpuarray
|
|
3077
3111
|
assert operator in ["&&", "||"]
|
|
3078
3112
|
|
|
@@ -3132,21 +3166,21 @@ def _logical_op(x1, x2, out, operator, queue=None):
|
|
|
3132
3166
|
return out
|
|
3133
3167
|
|
|
3134
3168
|
|
|
3135
|
-
def logical_and(x1, x2, /, out=None, queue=None):
|
|
3169
|
+
def logical_and(x1, x2, /, out=None, queue: cl.CommandQueue | None = None):
|
|
3136
3170
|
"""
|
|
3137
3171
|
Returns the element-wise logical AND of *x1* and *x2*.
|
|
3138
3172
|
"""
|
|
3139
3173
|
return _logical_op(x1, x2, out, "&&", queue=queue)
|
|
3140
3174
|
|
|
3141
3175
|
|
|
3142
|
-
def logical_or(x1, x2, /, out=None, queue=None):
|
|
3176
|
+
def logical_or(x1, x2, /, out=None, queue: cl.CommandQueue | None = None):
|
|
3143
3177
|
"""
|
|
3144
3178
|
Returns the element-wise logical OR of *x1* and *x2*.
|
|
3145
3179
|
"""
|
|
3146
3180
|
return _logical_op(x1, x2, out, "||", queue=queue)
|
|
3147
3181
|
|
|
3148
3182
|
|
|
3149
|
-
def logical_not(x, /, out=None, queue=None):
|
|
3183
|
+
def logical_not(x, /, out=None, queue: cl.CommandQueue | None = None):
|
|
3150
3184
|
"""
|
|
3151
3185
|
Returns the element-wise logical NOT of *x*.
|
|
3152
3186
|
"""
|
|
@@ -3168,11 +3202,16 @@ def logical_not(x, /, out=None, queue=None):
|
|
|
3168
3202
|
|
|
3169
3203
|
# {{{ reductions
|
|
3170
3204
|
|
|
3171
|
-
def sum(
|
|
3205
|
+
def sum(
|
|
3206
|
+
a,
|
|
3207
|
+
dtype=None,
|
|
3208
|
+
queue: cl.CommandQueue | None = None,
|
|
3209
|
+
slice=None,
|
|
3210
|
+
initial=_NoValue):
|
|
3172
3211
|
"""
|
|
3173
3212
|
.. versionadded:: 2011.1
|
|
3174
3213
|
"""
|
|
3175
|
-
if initial is not
|
|
3214
|
+
if initial is not _NoValue and not isinstance(initial, SCALAR_CLASSES):
|
|
3176
3215
|
raise ValueError("'initial' is not a scalar")
|
|
3177
3216
|
|
|
3178
3217
|
if dtype is not None:
|
|
@@ -3185,27 +3224,27 @@ def sum(a, dtype=None, queue=None, slice=None, initial=np._NoValue):
|
|
|
3185
3224
|
result.add_event(event1)
|
|
3186
3225
|
|
|
3187
3226
|
# NOTE: neutral element in `get_sum_kernel` is 0 by default
|
|
3188
|
-
if initial is not
|
|
3227
|
+
if initial is not _NoValue:
|
|
3189
3228
|
result += a.dtype.type(initial)
|
|
3190
3229
|
|
|
3191
3230
|
return result
|
|
3192
3231
|
|
|
3193
3232
|
|
|
3194
|
-
def any(a, queue=None, wait_for=None):
|
|
3233
|
+
def any(a, queue: cl.CommandQueue | None = None, wait_for: cl.WaitList = None):
|
|
3195
3234
|
if len(a) == 0:
|
|
3196
3235
|
return _BOOL_DTYPE.type(False)
|
|
3197
3236
|
|
|
3198
3237
|
return a.any(queue=queue, wait_for=wait_for)
|
|
3199
3238
|
|
|
3200
3239
|
|
|
3201
|
-
def all(a, queue=None, wait_for=None):
|
|
3240
|
+
def all(a, queue: cl.CommandQueue | None = None, wait_for: cl.WaitList = None):
|
|
3202
3241
|
if len(a) == 0:
|
|
3203
3242
|
return _BOOL_DTYPE.type(True)
|
|
3204
3243
|
|
|
3205
3244
|
return a.all(queue=queue, wait_for=wait_for)
|
|
3206
3245
|
|
|
3207
3246
|
|
|
3208
|
-
def dot(a, b, dtype=None, queue=None, slice=None):
|
|
3247
|
+
def dot(a, b, dtype=None, queue: cl.CommandQueue | None = None, slice=None):
|
|
3209
3248
|
"""
|
|
3210
3249
|
.. versionadded:: 2011.1
|
|
3211
3250
|
"""
|
|
@@ -3222,7 +3261,7 @@ def dot(a, b, dtype=None, queue=None, slice=None):
|
|
|
3222
3261
|
return result
|
|
3223
3262
|
|
|
3224
3263
|
|
|
3225
|
-
def vdot(a, b, dtype=None, queue=None, slice=None):
|
|
3264
|
+
def vdot(a, b, dtype=None, queue: cl.CommandQueue | None = None, slice=None):
|
|
3226
3265
|
"""Like :func:`numpy.vdot`.
|
|
3227
3266
|
|
|
3228
3267
|
.. versionadded:: 2013.1
|
|
@@ -3241,7 +3280,13 @@ def vdot(a, b, dtype=None, queue=None, slice=None):
|
|
|
3241
3280
|
return result
|
|
3242
3281
|
|
|
3243
3282
|
|
|
3244
|
-
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):
|
|
3245
3290
|
"""
|
|
3246
3291
|
.. versionadded:: 2011.1
|
|
3247
3292
|
"""
|
|
@@ -3260,19 +3305,19 @@ def subset_dot(subset, a, b, dtype=None, queue=None, slice=None):
|
|
|
3260
3305
|
|
|
3261
3306
|
|
|
3262
3307
|
def _make_minmax_kernel(what):
|
|
3263
|
-
def f(a, queue=None, initial=
|
|
3308
|
+
def f(a, queue: cl.CommandQueue | None = None, initial=_NoValue):
|
|
3264
3309
|
if isinstance(a, SCALAR_CLASSES):
|
|
3265
3310
|
return np.array(a).dtype.type(a)
|
|
3266
3311
|
|
|
3267
3312
|
if len(a) == 0:
|
|
3268
|
-
if initial is
|
|
3313
|
+
if initial is _NoValue:
|
|
3269
3314
|
raise ValueError(
|
|
3270
3315
|
f"zero-size array to reduction '{what}' "
|
|
3271
3316
|
"which has no identity")
|
|
3272
3317
|
else:
|
|
3273
3318
|
return initial
|
|
3274
3319
|
|
|
3275
|
-
if initial is not
|
|
3320
|
+
if initial is not _NoValue and not isinstance(initial, SCALAR_CLASSES):
|
|
3276
3321
|
raise ValueError("'initial' is not a scalar")
|
|
3277
3322
|
|
|
3278
3323
|
from pyopencl.reduction import get_minmax_kernel
|
|
@@ -3281,7 +3326,7 @@ def _make_minmax_kernel(what):
|
|
|
3281
3326
|
return_event=True)
|
|
3282
3327
|
result.add_event(event1)
|
|
3283
3328
|
|
|
3284
|
-
if initial is not
|
|
3329
|
+
if initial is not _NoValue:
|
|
3285
3330
|
initial = a.dtype.type(initial)
|
|
3286
3331
|
if what == "min":
|
|
3287
3332
|
result = minimum(result, initial, queue=queue)
|
|
@@ -3309,7 +3354,7 @@ max.__doc__ = """
|
|
|
3309
3354
|
|
|
3310
3355
|
|
|
3311
3356
|
def _make_subset_minmax_kernel(what):
|
|
3312
|
-
def f(subset, a, queue=None, slice=None):
|
|
3357
|
+
def f(subset, a, queue: cl.CommandQueue | None = None, slice=None):
|
|
3313
3358
|
from pyopencl.reduction import get_subset_minmax_kernel
|
|
3314
3359
|
krnl = get_subset_minmax_kernel(a.context, what, a.dtype, subset.dtype)
|
|
3315
3360
|
result, event1 = krnl(subset, a, queue=queue, slice=slice,
|
|
@@ -3329,8 +3374,8 @@ subset_max.__doc__ = """.. versionadded:: 2011.1"""
|
|
|
3329
3374
|
|
|
3330
3375
|
# {{{ scans
|
|
3331
3376
|
|
|
3332
|
-
def cumsum(a, output_dtype=None, queue=None,
|
|
3333
|
-
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):
|
|
3334
3379
|
# undocumented for now
|
|
3335
3380
|
|
|
3336
3381
|
"""
|