array-api-strict 2.3__py3-none-any.whl → 2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- array_api_strict/__init__.py +11 -5
- array_api_strict/_array_object.py +226 -200
- array_api_strict/_constants.py +1 -1
- array_api_strict/_creation_functions.py +97 -119
- array_api_strict/_data_type_functions.py +73 -64
- array_api_strict/_dtypes.py +35 -24
- array_api_strict/_elementwise_functions.py +138 -482
- array_api_strict/_fft.py +28 -32
- array_api_strict/_flags.py +65 -26
- array_api_strict/_helpers.py +23 -14
- array_api_strict/_indexing_functions.py +3 -8
- array_api_strict/_info.py +64 -69
- array_api_strict/_linalg.py +57 -53
- array_api_strict/_linear_algebra_functions.py +11 -9
- array_api_strict/_manipulation_functions.py +30 -30
- array_api_strict/_searching_functions.py +22 -33
- array_api_strict/_set_functions.py +4 -6
- array_api_strict/_sorting_functions.py +6 -6
- array_api_strict/_statistical_functions.py +57 -64
- array_api_strict/_typing.py +30 -50
- array_api_strict/_utility_functions.py +11 -13
- array_api_strict/_version.py +2 -2
- array_api_strict/py.typed +0 -0
- array_api_strict/tests/test_array_object.py +163 -56
- array_api_strict/tests/test_creation_functions.py +14 -12
- array_api_strict/tests/test_data_type_functions.py +40 -6
- array_api_strict/tests/test_elementwise_functions.py +94 -45
- array_api_strict/tests/test_searching_functions.py +79 -1
- array_api_strict/tests/test_validation.py +1 -3
- {array_api_strict-2.3.dist-info → array_api_strict-2.4.dist-info}/METADATA +5 -4
- array_api_strict-2.4.dist-info/RECORD +44 -0
- {array_api_strict-2.3.dist-info → array_api_strict-2.4.dist-info}/WHEEL +1 -1
- array_api_strict-2.3.dist-info/RECORD +0 -43
- {array_api_strict-2.3.dist-info → array_api_strict-2.4.dist-info}/LICENSE +0 -0
- {array_api_strict-2.3.dist-info → array_api_strict-2.4.dist-info}/top_level.txt +0 -0
array_api_strict/_fft.py
CHANGED
|
@@ -1,31 +1,27 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from typing import Literal
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if TYPE_CHECKING:
|
|
6
|
-
from typing import Union, Optional, Literal
|
|
7
|
-
from ._typing import Device, Dtype as DType
|
|
8
|
-
from collections.abc import Sequence
|
|
4
|
+
import numpy as np
|
|
9
5
|
|
|
6
|
+
from ._array_object import ALL_DEVICES, Array, Device
|
|
7
|
+
from ._data_type_functions import astype
|
|
10
8
|
from ._dtypes import (
|
|
9
|
+
DType,
|
|
10
|
+
_complex_floating_dtypes,
|
|
11
11
|
_floating_dtypes,
|
|
12
12
|
_real_floating_dtypes,
|
|
13
|
-
_complex_floating_dtypes,
|
|
14
|
-
float32,
|
|
15
13
|
complex64,
|
|
14
|
+
float32,
|
|
16
15
|
)
|
|
17
|
-
from ._array_object import Array, ALL_DEVICES
|
|
18
|
-
from ._data_type_functions import astype
|
|
19
16
|
from ._flags import requires_extension
|
|
20
17
|
|
|
21
|
-
import numpy as np
|
|
22
18
|
|
|
23
19
|
@requires_extension('fft')
|
|
24
20
|
def fft(
|
|
25
21
|
x: Array,
|
|
26
22
|
/,
|
|
27
23
|
*,
|
|
28
|
-
n:
|
|
24
|
+
n: int | None = None,
|
|
29
25
|
axis: int = -1,
|
|
30
26
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
31
27
|
) -> Array:
|
|
@@ -48,7 +44,7 @@ def ifft(
|
|
|
48
44
|
x: Array,
|
|
49
45
|
/,
|
|
50
46
|
*,
|
|
51
|
-
n:
|
|
47
|
+
n: int | None = None,
|
|
52
48
|
axis: int = -1,
|
|
53
49
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
54
50
|
) -> Array:
|
|
@@ -71,8 +67,8 @@ def fftn(
|
|
|
71
67
|
x: Array,
|
|
72
68
|
/,
|
|
73
69
|
*,
|
|
74
|
-
s: Sequence[int] = None,
|
|
75
|
-
axes: Sequence[int] = None,
|
|
70
|
+
s: Sequence[int] | None = None,
|
|
71
|
+
axes: Sequence[int] | None = None,
|
|
76
72
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
77
73
|
) -> Array:
|
|
78
74
|
"""
|
|
@@ -94,8 +90,8 @@ def ifftn(
|
|
|
94
90
|
x: Array,
|
|
95
91
|
/,
|
|
96
92
|
*,
|
|
97
|
-
s: Sequence[int] = None,
|
|
98
|
-
axes: Sequence[int] = None,
|
|
93
|
+
s: Sequence[int] | None = None,
|
|
94
|
+
axes: Sequence[int] | None = None,
|
|
99
95
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
100
96
|
) -> Array:
|
|
101
97
|
"""
|
|
@@ -117,7 +113,7 @@ def rfft(
|
|
|
117
113
|
x: Array,
|
|
118
114
|
/,
|
|
119
115
|
*,
|
|
120
|
-
n:
|
|
116
|
+
n: int | None = None,
|
|
121
117
|
axis: int = -1,
|
|
122
118
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
123
119
|
) -> Array:
|
|
@@ -140,7 +136,7 @@ def irfft(
|
|
|
140
136
|
x: Array,
|
|
141
137
|
/,
|
|
142
138
|
*,
|
|
143
|
-
n:
|
|
139
|
+
n: int | None = None,
|
|
144
140
|
axis: int = -1,
|
|
145
141
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
146
142
|
) -> Array:
|
|
@@ -163,8 +159,8 @@ def rfftn(
|
|
|
163
159
|
x: Array,
|
|
164
160
|
/,
|
|
165
161
|
*,
|
|
166
|
-
s: Sequence[int] = None,
|
|
167
|
-
axes: Sequence[int] = None,
|
|
162
|
+
s: Sequence[int] | None = None,
|
|
163
|
+
axes: Sequence[int] | None = None,
|
|
168
164
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
169
165
|
) -> Array:
|
|
170
166
|
"""
|
|
@@ -186,8 +182,8 @@ def irfftn(
|
|
|
186
182
|
x: Array,
|
|
187
183
|
/,
|
|
188
184
|
*,
|
|
189
|
-
s: Sequence[int] = None,
|
|
190
|
-
axes: Sequence[int] = None,
|
|
185
|
+
s: Sequence[int] | None = None,
|
|
186
|
+
axes: Sequence[int] | None = None,
|
|
191
187
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
192
188
|
) -> Array:
|
|
193
189
|
"""
|
|
@@ -209,7 +205,7 @@ def hfft(
|
|
|
209
205
|
x: Array,
|
|
210
206
|
/,
|
|
211
207
|
*,
|
|
212
|
-
n:
|
|
208
|
+
n: int | None = None,
|
|
213
209
|
axis: int = -1,
|
|
214
210
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
215
211
|
) -> Array:
|
|
@@ -232,7 +228,7 @@ def ihfft(
|
|
|
232
228
|
x: Array,
|
|
233
229
|
/,
|
|
234
230
|
*,
|
|
235
|
-
n:
|
|
231
|
+
n: int | None = None,
|
|
236
232
|
axis: int = -1,
|
|
237
233
|
norm: Literal["backward", "ortho", "forward"] = "backward",
|
|
238
234
|
) -> Array:
|
|
@@ -256,8 +252,8 @@ def fftfreq(
|
|
|
256
252
|
/,
|
|
257
253
|
*,
|
|
258
254
|
d: float = 1.0,
|
|
259
|
-
dtype:
|
|
260
|
-
device:
|
|
255
|
+
dtype: DType | None = None,
|
|
256
|
+
device: Device | None = None
|
|
261
257
|
) -> Array:
|
|
262
258
|
"""
|
|
263
259
|
Array API compatible wrapper for :py:func:`np.fft.fftfreq <numpy.fft.fftfreq>`.
|
|
@@ -280,8 +276,8 @@ def rfftfreq(
|
|
|
280
276
|
/,
|
|
281
277
|
*,
|
|
282
278
|
d: float = 1.0,
|
|
283
|
-
dtype:
|
|
284
|
-
device:
|
|
279
|
+
dtype: DType | None = None,
|
|
280
|
+
device: Device | None = None
|
|
285
281
|
) -> Array:
|
|
286
282
|
"""
|
|
287
283
|
Array API compatible wrapper for :py:func:`np.fft.rfftfreq <numpy.fft.rfftfreq>`.
|
|
@@ -299,7 +295,7 @@ def rfftfreq(
|
|
|
299
295
|
return Array._new(np_result, device=device)
|
|
300
296
|
|
|
301
297
|
@requires_extension('fft')
|
|
302
|
-
def fftshift(x: Array, /, *, axes:
|
|
298
|
+
def fftshift(x: Array, /, *, axes: int | Sequence[int] | None = None) -> Array:
|
|
303
299
|
"""
|
|
304
300
|
Array API compatible wrapper for :py:func:`np.fft.fftshift <numpy.fft.fftshift>`.
|
|
305
301
|
|
|
@@ -310,7 +306,7 @@ def fftshift(x: Array, /, *, axes: Union[int, Sequence[int]] = None) -> Array:
|
|
|
310
306
|
return Array._new(np.fft.fftshift(x._array, axes=axes), device=x.device)
|
|
311
307
|
|
|
312
308
|
@requires_extension('fft')
|
|
313
|
-
def ifftshift(x: Array, /, *, axes:
|
|
309
|
+
def ifftshift(x: Array, /, *, axes: int | Sequence[int] | None = None) -> Array:
|
|
314
310
|
"""
|
|
315
311
|
Array API compatible wrapper for :py:func:`np.fft.ifftshift <numpy.fft.ifftshift>`.
|
|
316
312
|
|
array_api_strict/_flags.py
CHANGED
|
@@ -11,18 +11,25 @@ None of these functions are part of the standard itself. A typical array API
|
|
|
11
11
|
library will only support one particular configuration of these flags.
|
|
12
12
|
|
|
13
13
|
"""
|
|
14
|
-
|
|
15
14
|
import functools
|
|
16
15
|
import os
|
|
17
16
|
import warnings
|
|
17
|
+
from collections.abc import Callable
|
|
18
|
+
from types import TracebackType
|
|
19
|
+
from typing import Any, Collection, ParamSpec, TypeVar, cast
|
|
18
20
|
|
|
19
21
|
import array_api_strict
|
|
20
22
|
|
|
23
|
+
P = ParamSpec("P")
|
|
24
|
+
T = TypeVar("T")
|
|
25
|
+
_CallableT = TypeVar("_CallableT", bound=Callable[..., object])
|
|
26
|
+
|
|
27
|
+
|
|
21
28
|
supported_versions = (
|
|
22
29
|
"2021.12",
|
|
23
30
|
"2022.12",
|
|
24
31
|
"2023.12",
|
|
25
|
-
"2024.12"
|
|
32
|
+
"2024.12",
|
|
26
33
|
)
|
|
27
34
|
|
|
28
35
|
draft_version = "2025.12"
|
|
@@ -43,19 +50,23 @@ extension_versions = {
|
|
|
43
50
|
"fft": "2022.12",
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
|
|
53
|
+
default_extensions: tuple[str, ...] = (
|
|
47
54
|
"linalg",
|
|
48
55
|
"fft",
|
|
49
56
|
)
|
|
57
|
+
ENABLED_EXTENSIONS = default_extensions
|
|
58
|
+
|
|
59
|
+
|
|
50
60
|
# Public functions
|
|
51
61
|
|
|
62
|
+
|
|
52
63
|
def set_array_api_strict_flags(
|
|
53
64
|
*,
|
|
54
|
-
api_version=None,
|
|
55
|
-
boolean_indexing=None,
|
|
56
|
-
data_dependent_shapes=None,
|
|
57
|
-
enabled_extensions=None,
|
|
58
|
-
):
|
|
65
|
+
api_version: str | None = None,
|
|
66
|
+
boolean_indexing: bool | None = None,
|
|
67
|
+
data_dependent_shapes: bool | None = None,
|
|
68
|
+
enabled_extensions: Collection[str] | None = None,
|
|
69
|
+
) -> None:
|
|
59
70
|
"""
|
|
60
71
|
Set the array-api-strict flags to the specified values.
|
|
61
72
|
|
|
@@ -178,7 +189,8 @@ if set_array_api_strict_flags.__doc__ is not None:
|
|
|
178
189
|
draft_version=draft_version,
|
|
179
190
|
)
|
|
180
191
|
|
|
181
|
-
|
|
192
|
+
|
|
193
|
+
def get_array_api_strict_flags() -> dict[str, Any]:
|
|
182
194
|
"""
|
|
183
195
|
Get the current array-api-strict flags.
|
|
184
196
|
|
|
@@ -228,7 +240,7 @@ def get_array_api_strict_flags():
|
|
|
228
240
|
}
|
|
229
241
|
|
|
230
242
|
|
|
231
|
-
def reset_array_api_strict_flags():
|
|
243
|
+
def reset_array_api_strict_flags() -> None:
|
|
232
244
|
"""
|
|
233
245
|
Reset the array-api-strict flags to their default values.
|
|
234
246
|
|
|
@@ -300,8 +312,19 @@ class ArrayAPIStrictFlags:
|
|
|
300
312
|
reset_array_api_strict_flags: Reset the flags to their default values.
|
|
301
313
|
|
|
302
314
|
"""
|
|
303
|
-
|
|
304
|
-
|
|
315
|
+
|
|
316
|
+
kwargs: dict[str, Any]
|
|
317
|
+
old_flags: dict[str, Any]
|
|
318
|
+
__slots__ = ("kwargs", "old_flags")
|
|
319
|
+
|
|
320
|
+
def __init__(
|
|
321
|
+
self,
|
|
322
|
+
*,
|
|
323
|
+
api_version: str | None = None,
|
|
324
|
+
boolean_indexing: bool | None = None,
|
|
325
|
+
data_dependent_shapes: bool | None = None,
|
|
326
|
+
enabled_extensions: Collection[str] | None = None,
|
|
327
|
+
):
|
|
305
328
|
self.kwargs = {
|
|
306
329
|
"api_version": api_version,
|
|
307
330
|
"boolean_indexing": boolean_indexing,
|
|
@@ -310,12 +333,19 @@ class ArrayAPIStrictFlags:
|
|
|
310
333
|
}
|
|
311
334
|
self.old_flags = get_array_api_strict_flags()
|
|
312
335
|
|
|
313
|
-
def __enter__(self):
|
|
336
|
+
def __enter__(self) -> None:
|
|
314
337
|
set_array_api_strict_flags(**self.kwargs)
|
|
315
338
|
|
|
316
|
-
def __exit__(
|
|
339
|
+
def __exit__(
|
|
340
|
+
self,
|
|
341
|
+
exc_type: type[BaseException] | None,
|
|
342
|
+
exc_value: BaseException | None,
|
|
343
|
+
traceback: TracebackType | None,
|
|
344
|
+
/,
|
|
345
|
+
) -> None:
|
|
317
346
|
set_array_api_strict_flags(**self.old_flags)
|
|
318
347
|
|
|
348
|
+
|
|
319
349
|
# Private functions
|
|
320
350
|
|
|
321
351
|
ENVIRONMENT_VARIABLES = [
|
|
@@ -325,8 +355,9 @@ ENVIRONMENT_VARIABLES = [
|
|
|
325
355
|
"ARRAY_API_STRICT_ENABLED_EXTENSIONS",
|
|
326
356
|
]
|
|
327
357
|
|
|
328
|
-
|
|
329
|
-
|
|
358
|
+
|
|
359
|
+
def set_flags_from_environment() -> None:
|
|
360
|
+
kwargs: dict[str, Any] = {}
|
|
330
361
|
if "ARRAY_API_STRICT_API_VERSION" in os.environ:
|
|
331
362
|
kwargs["api_version"] = os.environ["ARRAY_API_STRICT_API_VERSION"]
|
|
332
363
|
|
|
@@ -346,35 +377,41 @@ def set_flags_from_environment():
|
|
|
346
377
|
# linalg and fft to __all__
|
|
347
378
|
set_array_api_strict_flags(**kwargs)
|
|
348
379
|
|
|
380
|
+
|
|
349
381
|
set_flags_from_environment()
|
|
350
382
|
|
|
351
383
|
# Decorators
|
|
352
384
|
|
|
353
|
-
|
|
354
|
-
|
|
385
|
+
|
|
386
|
+
def requires_api_version(version: str) -> Callable[[_CallableT], _CallableT]:
|
|
387
|
+
def decorator(func: Callable[P, T]) -> Callable[P, T]:
|
|
355
388
|
@functools.wraps(func)
|
|
356
|
-
def wrapper(*args, **kwargs):
|
|
389
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
357
390
|
if version > API_VERSION:
|
|
358
391
|
raise RuntimeError(
|
|
359
392
|
f"The function {func.__name__} requires API version {version} or later, "
|
|
360
393
|
f"but the current API version for array-api-strict is {API_VERSION}"
|
|
361
394
|
)
|
|
362
395
|
return func(*args, **kwargs)
|
|
396
|
+
|
|
363
397
|
return wrapper
|
|
364
|
-
return decorator
|
|
365
398
|
|
|
366
|
-
|
|
399
|
+
return cast(Callable[[_CallableT], _CallableT], decorator)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def requires_data_dependent_shapes(func: Callable[P, T]) -> Callable[P, T]:
|
|
367
403
|
@functools.wraps(func)
|
|
368
|
-
def wrapper(*args, **kwargs):
|
|
404
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
369
405
|
if not DATA_DEPENDENT_SHAPES:
|
|
370
406
|
raise RuntimeError(f"The function {func.__name__} requires data-dependent shapes, but the data_dependent_shapes flag has been disabled for array-api-strict")
|
|
371
407
|
return func(*args, **kwargs)
|
|
372
408
|
return wrapper
|
|
373
409
|
|
|
374
|
-
|
|
375
|
-
|
|
410
|
+
|
|
411
|
+
def requires_extension(extension: str) -> Callable[[_CallableT], _CallableT]:
|
|
412
|
+
def decorator(func: Callable[P, T]) -> Callable[P, T]:
|
|
376
413
|
@functools.wraps(func)
|
|
377
|
-
def wrapper(*args, **kwargs):
|
|
414
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
378
415
|
if extension not in ENABLED_EXTENSIONS:
|
|
379
416
|
if extension == 'linalg' \
|
|
380
417
|
and func.__name__ in ['matmul', 'tensordot',
|
|
@@ -382,5 +419,7 @@ def requires_extension(extension):
|
|
|
382
419
|
raise RuntimeError(f"The linalg extension has been disabled for array-api-strict. However, {func.__name__} is also present in the main array_api_strict namespace and may be used from there.")
|
|
383
420
|
raise RuntimeError(f"The function {func.__name__} requires the {extension} extension, but it has been disabled for array-api-strict")
|
|
384
421
|
return func(*args, **kwargs)
|
|
422
|
+
|
|
385
423
|
return wrapper
|
|
386
|
-
|
|
424
|
+
|
|
425
|
+
return cast(Callable[[_CallableT], _CallableT], decorator)
|
array_api_strict/_helpers.py
CHANGED
|
@@ -1,37 +1,46 @@
|
|
|
1
|
-
"""Private helper routines.
|
|
2
|
-
"""
|
|
1
|
+
"""Private helper routines."""
|
|
3
2
|
|
|
4
|
-
from .
|
|
3
|
+
from ._array_object import Array
|
|
5
4
|
from ._dtypes import _dtype_categories
|
|
5
|
+
from ._flags import get_array_api_strict_flags
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
_PY_SCALARS = (bool, int, float, complex)
|
|
9
8
|
|
|
10
|
-
def _maybe_normalize_py_scalars(x1, x2, dtype_category, func_name):
|
|
11
9
|
|
|
10
|
+
def _maybe_normalize_py_scalars(
|
|
11
|
+
x1: Array | complex,
|
|
12
|
+
x2: Array | complex,
|
|
13
|
+
dtype_category: str,
|
|
14
|
+
func_name: str,
|
|
15
|
+
) -> tuple[Array, Array]:
|
|
12
16
|
flags = get_array_api_strict_flags()
|
|
13
17
|
if flags["api_version"] < "2024.12":
|
|
14
18
|
# scalars will fail at the call site
|
|
15
|
-
return x1, x2
|
|
19
|
+
return x1, x2 # type: ignore[return-value]
|
|
16
20
|
|
|
17
21
|
_allowed_dtypes = _dtype_categories[dtype_category]
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
# Disallow subclasses, e.g. np.float64 and np.complex128
|
|
24
|
+
if type(x1) in _PY_SCALARS:
|
|
25
|
+
if type(x2) in _PY_SCALARS:
|
|
21
26
|
raise TypeError(f"Two scalars not allowed, got {type(x1) = } and {type(x2) =}")
|
|
22
|
-
|
|
27
|
+
if not isinstance(x2, Array):
|
|
28
|
+
raise TypeError(f"Argument is neither an Array nor a Python scalar: {type(x2)=} ")
|
|
23
29
|
if x2.dtype not in _allowed_dtypes:
|
|
24
30
|
raise TypeError(f"Only {dtype_category} dtypes are allowed {func_name}. Got {x2.dtype}.")
|
|
25
31
|
x1 = x2._promote_scalar(x1)
|
|
26
32
|
|
|
27
|
-
elif
|
|
28
|
-
|
|
33
|
+
elif type(x2) in _PY_SCALARS:
|
|
34
|
+
if not isinstance(x1, Array):
|
|
35
|
+
raise TypeError(f"Argument is neither an Array nor a Python scalar: {type(x2)=} ")
|
|
29
36
|
if x1.dtype not in _allowed_dtypes:
|
|
30
37
|
raise TypeError(f"Only {dtype_category} dtypes are allowed {func_name}. Got {x1.dtype}.")
|
|
31
38
|
x2 = x1._promote_scalar(x2)
|
|
32
39
|
else:
|
|
40
|
+
if not isinstance(x1, Array) or not isinstance(x2, Array):
|
|
41
|
+
raise TypeError(f"Argument(s) are neither Array nor Python scalars: {type(x1)=} and {type(x2)=}")
|
|
42
|
+
|
|
33
43
|
if x1.dtype not in _allowed_dtypes or x2.dtype not in _allowed_dtypes:
|
|
34
|
-
raise TypeError(f"Only {dtype_category} dtypes are allowed {func_name}. "
|
|
44
|
+
raise TypeError(f"Only {dtype_category} dtypes are allowed in {func_name}(...). "
|
|
35
45
|
f"Got {x1.dtype} and {x2.dtype}.")
|
|
36
46
|
return x1, x2
|
|
37
|
-
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import numpy as np
|
|
2
2
|
|
|
3
3
|
from ._array_object import Array
|
|
4
4
|
from ._dtypes import _integer_dtypes
|
|
5
5
|
from ._flags import requires_api_version
|
|
6
6
|
|
|
7
|
-
from typing import TYPE_CHECKING
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from typing import Optional
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def take(x: Array, indices: Array, /, *, axis: Optional[int] = None) -> Array:
|
|
8
|
+
def take(x: Array, indices: Array, /, *, axis: int | None = None) -> Array:
|
|
15
9
|
"""
|
|
16
10
|
Array API compatible wrapper for :py:func:`np.take <numpy.take>`.
|
|
17
11
|
|
|
@@ -27,6 +21,7 @@ def take(x: Array, indices: Array, /, *, axis: Optional[int] = None) -> Array:
|
|
|
27
21
|
raise ValueError(f"Arrays from two different devices ({x.device} and {indices.device}) can not be combined.")
|
|
28
22
|
return Array._new(np.take(x._array, indices._array, axis=axis), device=x.device)
|
|
29
23
|
|
|
24
|
+
|
|
30
25
|
@requires_api_version('2024.12')
|
|
31
26
|
def take_along_axis(x: Array, indices: Array, /, *, axis: int = -1) -> Array:
|
|
32
27
|
"""
|
array_api_strict/_info.py
CHANGED
|
@@ -1,25 +1,20 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
1
|
import numpy as np
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
from ._typing import device, DefaultDataTypes, DataTypes, Capabilities
|
|
10
|
-
|
|
11
|
-
from ._array_object import ALL_DEVICES, CPU_DEVICE
|
|
3
|
+
from . import _dtypes as dt
|
|
4
|
+
from ._array_object import ALL_DEVICES, CPU_DEVICE, Device
|
|
12
5
|
from ._flags import get_array_api_strict_flags, requires_api_version
|
|
13
|
-
from .
|
|
6
|
+
from ._typing import Capabilities, DataTypes, DefaultDataTypes
|
|
7
|
+
|
|
14
8
|
|
|
15
9
|
@requires_api_version('2023.12')
|
|
16
10
|
class __array_namespace_info__:
|
|
17
11
|
@requires_api_version('2023.12')
|
|
18
12
|
def capabilities(self) -> Capabilities:
|
|
19
13
|
flags = get_array_api_strict_flags()
|
|
20
|
-
res = {
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
res: Capabilities = { # type: ignore[typeddict-item]
|
|
15
|
+
"boolean indexing": flags['boolean_indexing'],
|
|
16
|
+
"data-dependent shapes": flags['data_dependent_shapes'],
|
|
17
|
+
}
|
|
23
18
|
if flags['api_version'] >= '2024.12':
|
|
24
19
|
# maxdims is 32 for NumPy 1.x and 64 for NumPy 2.0. Eventually we will
|
|
25
20
|
# drop support for NumPy 1 but for now, just compute the number
|
|
@@ -36,104 +31,104 @@ class __array_namespace_info__:
|
|
|
36
31
|
return res
|
|
37
32
|
|
|
38
33
|
@requires_api_version('2023.12')
|
|
39
|
-
def default_device(self) ->
|
|
34
|
+
def default_device(self) -> Device:
|
|
40
35
|
return CPU_DEVICE
|
|
41
36
|
|
|
42
37
|
@requires_api_version('2023.12')
|
|
43
38
|
def default_dtypes(
|
|
44
39
|
self,
|
|
45
40
|
*,
|
|
46
|
-
device:
|
|
41
|
+
device: Device | None = None,
|
|
47
42
|
) -> DefaultDataTypes:
|
|
48
43
|
return {
|
|
49
|
-
"real floating": float64,
|
|
50
|
-
"complex floating": complex128,
|
|
51
|
-
"integral": int64,
|
|
52
|
-
"indexing": int64,
|
|
44
|
+
"real floating": dt.float64,
|
|
45
|
+
"complex floating": dt.complex128,
|
|
46
|
+
"integral": dt.int64,
|
|
47
|
+
"indexing": dt.int64,
|
|
53
48
|
}
|
|
54
49
|
|
|
55
50
|
@requires_api_version('2023.12')
|
|
56
51
|
def dtypes(
|
|
57
52
|
self,
|
|
58
53
|
*,
|
|
59
|
-
device:
|
|
60
|
-
kind:
|
|
54
|
+
device: Device | None = None,
|
|
55
|
+
kind: str | tuple[str, ...] | None = None,
|
|
61
56
|
) -> DataTypes:
|
|
62
57
|
if kind is None:
|
|
63
58
|
return {
|
|
64
|
-
"bool": bool,
|
|
65
|
-
"int8": int8,
|
|
66
|
-
"int16": int16,
|
|
67
|
-
"int32": int32,
|
|
68
|
-
"int64": int64,
|
|
69
|
-
"uint8": uint8,
|
|
70
|
-
"uint16": uint16,
|
|
71
|
-
"uint32": uint32,
|
|
72
|
-
"uint64": uint64,
|
|
73
|
-
"float32": float32,
|
|
74
|
-
"float64": float64,
|
|
75
|
-
"complex64": complex64,
|
|
76
|
-
"complex128": complex128,
|
|
59
|
+
"bool": dt.bool,
|
|
60
|
+
"int8": dt.int8,
|
|
61
|
+
"int16": dt.int16,
|
|
62
|
+
"int32": dt.int32,
|
|
63
|
+
"int64": dt.int64,
|
|
64
|
+
"uint8": dt.uint8,
|
|
65
|
+
"uint16": dt.uint16,
|
|
66
|
+
"uint32": dt.uint32,
|
|
67
|
+
"uint64": dt.uint64,
|
|
68
|
+
"float32": dt.float32,
|
|
69
|
+
"float64": dt.float64,
|
|
70
|
+
"complex64": dt.complex64,
|
|
71
|
+
"complex128": dt.complex128,
|
|
77
72
|
}
|
|
78
73
|
if kind == "bool":
|
|
79
|
-
return {"bool": bool}
|
|
74
|
+
return {"bool": dt.bool}
|
|
80
75
|
if kind == "signed integer":
|
|
81
76
|
return {
|
|
82
|
-
"int8": int8,
|
|
83
|
-
"int16": int16,
|
|
84
|
-
"int32": int32,
|
|
85
|
-
"int64": int64,
|
|
77
|
+
"int8": dt.int8,
|
|
78
|
+
"int16": dt.int16,
|
|
79
|
+
"int32": dt.int32,
|
|
80
|
+
"int64": dt.int64,
|
|
86
81
|
}
|
|
87
82
|
if kind == "unsigned integer":
|
|
88
83
|
return {
|
|
89
|
-
"uint8": uint8,
|
|
90
|
-
"uint16": uint16,
|
|
91
|
-
"uint32": uint32,
|
|
92
|
-
"uint64": uint64,
|
|
84
|
+
"uint8": dt.uint8,
|
|
85
|
+
"uint16": dt.uint16,
|
|
86
|
+
"uint32": dt.uint32,
|
|
87
|
+
"uint64": dt.uint64,
|
|
93
88
|
}
|
|
94
89
|
if kind == "integral":
|
|
95
90
|
return {
|
|
96
|
-
"int8": int8,
|
|
97
|
-
"int16": int16,
|
|
98
|
-
"int32": int32,
|
|
99
|
-
"int64": int64,
|
|
100
|
-
"uint8": uint8,
|
|
101
|
-
"uint16": uint16,
|
|
102
|
-
"uint32": uint32,
|
|
103
|
-
"uint64": uint64,
|
|
91
|
+
"int8": dt.int8,
|
|
92
|
+
"int16": dt.int16,
|
|
93
|
+
"int32": dt.int32,
|
|
94
|
+
"int64": dt.int64,
|
|
95
|
+
"uint8": dt.uint8,
|
|
96
|
+
"uint16": dt.uint16,
|
|
97
|
+
"uint32": dt.uint32,
|
|
98
|
+
"uint64": dt.uint64,
|
|
104
99
|
}
|
|
105
100
|
if kind == "real floating":
|
|
106
101
|
return {
|
|
107
|
-
"float32": float32,
|
|
108
|
-
"float64": float64,
|
|
102
|
+
"float32": dt.float32,
|
|
103
|
+
"float64": dt.float64,
|
|
109
104
|
}
|
|
110
105
|
if kind == "complex floating":
|
|
111
106
|
return {
|
|
112
|
-
"complex64": complex64,
|
|
113
|
-
"complex128": complex128,
|
|
107
|
+
"complex64": dt.complex64,
|
|
108
|
+
"complex128": dt.complex128,
|
|
114
109
|
}
|
|
115
110
|
if kind == "numeric":
|
|
116
111
|
return {
|
|
117
|
-
"int8": int8,
|
|
118
|
-
"int16": int16,
|
|
119
|
-
"int32": int32,
|
|
120
|
-
"int64": int64,
|
|
121
|
-
"uint8": uint8,
|
|
122
|
-
"uint16": uint16,
|
|
123
|
-
"uint32": uint32,
|
|
124
|
-
"uint64": uint64,
|
|
125
|
-
"float32": float32,
|
|
126
|
-
"float64": float64,
|
|
127
|
-
"complex64": complex64,
|
|
128
|
-
"complex128": complex128,
|
|
112
|
+
"int8": dt.int8,
|
|
113
|
+
"int16": dt.int16,
|
|
114
|
+
"int32": dt.int32,
|
|
115
|
+
"int64": dt.int64,
|
|
116
|
+
"uint8": dt.uint8,
|
|
117
|
+
"uint16": dt.uint16,
|
|
118
|
+
"uint32": dt.uint32,
|
|
119
|
+
"uint64": dt.uint64,
|
|
120
|
+
"float32": dt.float32,
|
|
121
|
+
"float64": dt.float64,
|
|
122
|
+
"complex64": dt.complex64,
|
|
123
|
+
"complex128": dt.complex128,
|
|
129
124
|
}
|
|
130
125
|
if isinstance(kind, tuple):
|
|
131
|
-
res = {}
|
|
126
|
+
res: DataTypes = {}
|
|
132
127
|
for k in kind:
|
|
133
128
|
res.update(self.dtypes(kind=k))
|
|
134
129
|
return res
|
|
135
130
|
raise ValueError(f"unsupported kind: {kind!r}")
|
|
136
131
|
|
|
137
132
|
@requires_api_version('2023.12')
|
|
138
|
-
def devices(self) ->
|
|
133
|
+
def devices(self) -> list[Device]:
|
|
139
134
|
return list(ALL_DEVICES)
|