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.
Files changed (35) hide show
  1. array_api_strict/__init__.py +11 -5
  2. array_api_strict/_array_object.py +226 -200
  3. array_api_strict/_constants.py +1 -1
  4. array_api_strict/_creation_functions.py +97 -119
  5. array_api_strict/_data_type_functions.py +73 -64
  6. array_api_strict/_dtypes.py +35 -24
  7. array_api_strict/_elementwise_functions.py +138 -482
  8. array_api_strict/_fft.py +28 -32
  9. array_api_strict/_flags.py +65 -26
  10. array_api_strict/_helpers.py +23 -14
  11. array_api_strict/_indexing_functions.py +3 -8
  12. array_api_strict/_info.py +64 -69
  13. array_api_strict/_linalg.py +57 -53
  14. array_api_strict/_linear_algebra_functions.py +11 -9
  15. array_api_strict/_manipulation_functions.py +30 -30
  16. array_api_strict/_searching_functions.py +22 -33
  17. array_api_strict/_set_functions.py +4 -6
  18. array_api_strict/_sorting_functions.py +6 -6
  19. array_api_strict/_statistical_functions.py +57 -64
  20. array_api_strict/_typing.py +30 -50
  21. array_api_strict/_utility_functions.py +11 -13
  22. array_api_strict/_version.py +2 -2
  23. array_api_strict/py.typed +0 -0
  24. array_api_strict/tests/test_array_object.py +163 -56
  25. array_api_strict/tests/test_creation_functions.py +14 -12
  26. array_api_strict/tests/test_data_type_functions.py +40 -6
  27. array_api_strict/tests/test_elementwise_functions.py +94 -45
  28. array_api_strict/tests/test_searching_functions.py +79 -1
  29. array_api_strict/tests/test_validation.py +1 -3
  30. {array_api_strict-2.3.dist-info → array_api_strict-2.4.dist-info}/METADATA +5 -4
  31. array_api_strict-2.4.dist-info/RECORD +44 -0
  32. {array_api_strict-2.3.dist-info → array_api_strict-2.4.dist-info}/WHEEL +1 -1
  33. array_api_strict-2.3.dist-info/RECORD +0 -43
  34. {array_api_strict-2.3.dist-info → array_api_strict-2.4.dist-info}/LICENSE +0 -0
  35. {array_api_strict-2.3.dist-info → array_api_strict-2.4.dist-info}/top_level.txt +0 -0
@@ -1,38 +1,34 @@
1
- from __future__ import annotations
1
+ from typing import Any
2
2
 
3
+ import numpy as np
4
+
5
+ from ._array_object import Array
6
+ from ._creation_functions import ones, zeros
3
7
  from ._dtypes import (
4
- _real_floating_dtypes,
5
- _real_numeric_dtypes,
8
+ DType,
6
9
  _floating_dtypes,
10
+ _np_dtype,
7
11
  _numeric_dtypes,
12
+ _real_floating_dtypes,
13
+ _real_numeric_dtypes,
14
+ complex64,
15
+ float32,
8
16
  )
9
- from ._array_object import Array
10
- from ._dtypes import float32, complex64
11
- from ._flags import requires_api_version, get_array_api_strict_flags
12
- from ._creation_functions import zeros, ones
17
+ from ._flags import get_array_api_strict_flags, requires_api_version
13
18
  from ._manipulation_functions import concat
14
19
 
15
- from typing import TYPE_CHECKING
16
-
17
- if TYPE_CHECKING:
18
- from typing import Optional, Tuple, Union
19
- from ._typing import Dtype
20
-
21
- import numpy as np
22
20
 
23
21
  @requires_api_version('2023.12')
24
22
  def cumulative_sum(
25
23
  x: Array,
26
24
  /,
27
25
  *,
28
- axis: Optional[int] = None,
29
- dtype: Optional[Dtype] = None,
26
+ axis: int | None = None,
27
+ dtype: DType | None = None,
30
28
  include_initial: bool = False,
31
29
  ) -> Array:
32
30
  if x.dtype not in _numeric_dtypes:
33
31
  raise TypeError("Only numeric dtypes are allowed in cumulative_sum")
34
- if dtype is not None:
35
- dtype = dtype._np_dtype
36
32
 
37
33
  # TODO: The standard is not clear about what should happen when x.ndim == 0.
38
34
  if axis is None:
@@ -44,7 +40,7 @@ def cumulative_sum(
44
40
  if axis < 0:
45
41
  axis += x.ndim
46
42
  x = concat([zeros(x.shape[:axis] + (1,) + x.shape[axis + 1:], dtype=x.dtype), x], axis=axis)
47
- return Array._new(np.cumsum(x._array, axis=axis, dtype=dtype), device=x.device)
43
+ return Array._new(np.cumsum(x._array, axis=axis, dtype=_np_dtype(dtype)), device=x.device)
48
44
 
49
45
 
50
46
  @requires_api_version('2024.12')
@@ -52,8 +48,8 @@ def cumulative_prod(
52
48
  x: Array,
53
49
  /,
54
50
  *,
55
- axis: Optional[int] = None,
56
- dtype: Optional[Dtype] = None,
51
+ axis: int | None = None,
52
+ dtype: DType | None = None,
57
53
  include_initial: bool = False,
58
54
  ) -> Array:
59
55
  if x.dtype not in _numeric_dtypes:
@@ -61,9 +57,6 @@ def cumulative_prod(
61
57
  if x.ndim == 0:
62
58
  raise ValueError("Only ndim >= 1 arrays are allowed in cumulative_prod")
63
59
 
64
- if dtype is not None:
65
- dtype = dtype._np_dtype
66
-
67
60
  if axis is None:
68
61
  if x.ndim > 1:
69
62
  raise ValueError("axis must be specified in cumulative_prod for more than one dimension")
@@ -74,14 +67,14 @@ def cumulative_prod(
74
67
  if axis < 0:
75
68
  axis += x.ndim
76
69
  x = concat([ones(x.shape[:axis] + (1,) + x.shape[axis + 1:], dtype=x.dtype), x], axis=axis)
77
- return Array._new(np.cumprod(x._array, axis=axis, dtype=dtype), device=x.device)
70
+ return Array._new(np.cumprod(x._array, axis=axis, dtype=_np_dtype(dtype)), device=x.device)
78
71
 
79
72
 
80
73
  def max(
81
74
  x: Array,
82
75
  /,
83
76
  *,
84
- axis: Optional[Union[int, Tuple[int, ...]]] = None,
77
+ axis: int | tuple[int, ...] | None = None,
85
78
  keepdims: bool = False,
86
79
  ) -> Array:
87
80
  if x.dtype not in _real_numeric_dtypes:
@@ -93,14 +86,15 @@ def mean(
93
86
  x: Array,
94
87
  /,
95
88
  *,
96
- axis: Optional[Union[int, Tuple[int, ...]]] = None,
89
+ axis: int | tuple[int, ...] | None = None,
97
90
  keepdims: bool = False,
98
91
  ) -> Array:
99
92
 
100
- if get_array_api_strict_flags()['api_version'] > '2023.12':
101
- allowed_dtypes = _floating_dtypes
102
- else:
103
- allowed_dtypes = _real_floating_dtypes
93
+ allowed_dtypes = (
94
+ _floating_dtypes
95
+ if get_array_api_strict_flags()['api_version'] > '2023.12'
96
+ else _real_floating_dtypes
97
+ )
104
98
 
105
99
  if x.dtype not in allowed_dtypes:
106
100
  raise TypeError("Only floating-point dtypes are allowed in mean")
@@ -111,7 +105,7 @@ def min(
111
105
  x: Array,
112
106
  /,
113
107
  *,
114
- axis: Optional[Union[int, Tuple[int, ...]]] = None,
108
+ axis: int | tuple[int, ...] | None = None,
115
109
  keepdims: bool = False,
116
110
  ) -> Array:
117
111
  if x.dtype not in _real_numeric_dtypes:
@@ -119,37 +113,43 @@ def min(
119
113
  return Array._new(np.min(x._array, axis=axis, keepdims=keepdims), device=x.device)
120
114
 
121
115
 
116
+ def _np_dtype_sumprod(x: Array, dtype: DType | None) -> np.dtype[Any] | None:
117
+ """In versions prior to 2023.12, sum() and prod() upcast for all
118
+ dtypes when dtype=None. For 2023.12, the behavior is the same as in
119
+ NumPy (only upcast for integral dtypes).
120
+ """
121
+ if dtype is None and get_array_api_strict_flags()['api_version'] < '2023.12':
122
+ if x.dtype == float32:
123
+ return np.float64 # type: ignore[return-value]
124
+ elif x.dtype == complex64:
125
+ return np.complex128 # type: ignore[return-value]
126
+ return _np_dtype(dtype)
127
+
128
+
122
129
  def prod(
123
130
  x: Array,
124
131
  /,
125
132
  *,
126
- axis: Optional[Union[int, Tuple[int, ...]]] = None,
127
- dtype: Optional[Dtype] = None,
133
+ axis: int | tuple[int, ...] | None = None,
134
+ dtype: DType | None = None,
128
135
  keepdims: bool = False,
129
136
  ) -> Array:
130
137
  if x.dtype not in _numeric_dtypes:
131
138
  raise TypeError("Only numeric dtypes are allowed in prod")
132
139
 
133
- if dtype is None:
134
- # Note: In versions prior to 2023.12, sum() and prod() upcast for all
135
- # dtypes when dtype=None. For 2023.12, the behavior is the same as in
136
- # NumPy (only upcast for integral dtypes).
137
- if get_array_api_strict_flags()['api_version'] < '2023.12':
138
- if x.dtype == float32:
139
- dtype = np.float64
140
- elif x.dtype == complex64:
141
- dtype = np.complex128
142
- else:
143
- dtype = dtype._np_dtype
144
- return Array._new(np.prod(x._array, dtype=dtype, axis=axis, keepdims=keepdims), device=x.device)
140
+ np_dtype = _np_dtype_sumprod(x, dtype)
141
+ return Array._new(
142
+ np.prod(x._array, dtype=np_dtype, axis=axis, keepdims=keepdims),
143
+ device=x.device,
144
+ )
145
145
 
146
146
 
147
147
  def std(
148
148
  x: Array,
149
149
  /,
150
150
  *,
151
- axis: Optional[Union[int, Tuple[int, ...]]] = None,
152
- correction: Union[int, float] = 0.0,
151
+ axis: int | tuple[int, ...] | None = None,
152
+ correction: float = 0.0,
153
153
  keepdims: bool = False,
154
154
  ) -> Array:
155
155
  # Note: the keyword argument correction is different here
@@ -162,33 +162,26 @@ def sum(
162
162
  x: Array,
163
163
  /,
164
164
  *,
165
- axis: Optional[Union[int, Tuple[int, ...]]] = None,
166
- dtype: Optional[Dtype] = None,
165
+ axis: int | tuple[int, ...] | None = None,
166
+ dtype: DType | None = None,
167
167
  keepdims: bool = False,
168
168
  ) -> Array:
169
169
  if x.dtype not in _numeric_dtypes:
170
170
  raise TypeError("Only numeric dtypes are allowed in sum")
171
171
 
172
- if dtype is None:
173
- # Note: In versions prior to 2023.12, sum() and prod() upcast for all
174
- # dtypes when dtype=None. For 2023.12, the behavior is the same as in
175
- # NumPy (only upcast for integral dtypes).
176
- if get_array_api_strict_flags()['api_version'] < '2023.12':
177
- if x.dtype == float32:
178
- dtype = np.float64
179
- elif x.dtype == complex64:
180
- dtype = np.complex128
181
- else:
182
- dtype = dtype._np_dtype
183
- return Array._new(np.sum(x._array, axis=axis, dtype=dtype, keepdims=keepdims), device=x.device)
172
+ np_dtype = _np_dtype_sumprod(x, dtype)
173
+ return Array._new(
174
+ np.sum(x._array, axis=axis, dtype=np_dtype, keepdims=keepdims),
175
+ device=x.device,
176
+ )
184
177
 
185
178
 
186
179
  def var(
187
180
  x: Array,
188
181
  /,
189
182
  *,
190
- axis: Optional[Union[int, Tuple[int, ...]]] = None,
191
- correction: Union[int, float] = 0.0,
183
+ axis: int | tuple[int, ...] | None = None,
184
+ correction: float = 0.0,
192
185
  keepdims: bool = False,
193
186
  ) -> Array:
194
187
  # Note: the keyword argument correction is different here
@@ -8,41 +8,19 @@ valid for inputs that match the given type annotations.
8
8
 
9
9
  from __future__ import annotations
10
10
 
11
- __all__ = [
12
- "Array",
13
- "Device",
14
- "Dtype",
15
- "SupportsDLPack",
16
- "SupportsBufferProtocol",
17
- "PyCapsule",
18
- ]
19
-
20
11
  import sys
12
+ from typing import Any, Protocol, TypedDict, TypeVar
21
13
 
22
- from typing import (
23
- Any,
24
- TypedDict,
25
- TypeVar,
26
- Protocol,
27
- )
28
-
29
- from ._array_object import Array, _device
30
- from ._dtypes import _DType
31
- from ._info import __array_namespace_info__
14
+ from ._dtypes import DType
32
15
 
33
16
  _T_co = TypeVar("_T_co", covariant=True)
34
17
 
18
+
35
19
  class NestedSequence(Protocol[_T_co]):
36
20
  def __getitem__(self, key: int, /) -> _T_co | NestedSequence[_T_co]: ...
37
21
  def __len__(self, /) -> int: ...
38
22
 
39
23
 
40
- Device = _device
41
-
42
- Dtype = _DType
43
-
44
- Info = __array_namespace_info__
45
-
46
24
  if sys.version_info >= (3, 12):
47
25
  from collections.abc import Buffer as SupportsBufferProtocol
48
26
  else:
@@ -50,40 +28,42 @@ else:
50
28
 
51
29
  PyCapsule = Any
52
30
 
31
+
53
32
  class SupportsDLPack(Protocol):
54
33
  def __dlpack__(self, /, *, stream: None = ...) -> PyCapsule: ...
55
34
 
35
+
56
36
  Capabilities = TypedDict(
57
- "Capabilities", {"boolean indexing": bool, "data-dependent shapes": bool,
58
- "max dimensions": int}
37
+ "Capabilities",
38
+ {
39
+ "boolean indexing": bool,
40
+ "data-dependent shapes": bool,
41
+ "max dimensions": int,
42
+ },
59
43
  )
60
44
 
61
45
  DefaultDataTypes = TypedDict(
62
46
  "DefaultDataTypes",
63
47
  {
64
- "real floating": Dtype,
65
- "complex floating": Dtype,
66
- "integral": Dtype,
67
- "indexing": Dtype,
48
+ "real floating": DType,
49
+ "complex floating": DType,
50
+ "integral": DType,
51
+ "indexing": DType,
68
52
  },
69
53
  )
70
54
 
71
- DataTypes = TypedDict(
72
- "DataTypes",
73
- {
74
- "bool": Dtype,
75
- "float32": Dtype,
76
- "float64": Dtype,
77
- "complex64": Dtype,
78
- "complex128": Dtype,
79
- "int8": Dtype,
80
- "int16": Dtype,
81
- "int32": Dtype,
82
- "int64": Dtype,
83
- "uint8": Dtype,
84
- "uint16": Dtype,
85
- "uint32": Dtype,
86
- "uint64": Dtype,
87
- },
88
- total=False,
89
- )
55
+
56
+ class DataTypes(TypedDict, total=False):
57
+ bool: DType
58
+ float32: DType
59
+ float64: DType
60
+ complex64: DType
61
+ complex128: DType
62
+ int8: DType
63
+ int16: DType
64
+ int32: DType
65
+ int64: DType
66
+ uint8: DType
67
+ uint16: DType
68
+ uint32: DType
69
+ uint64: DType
@@ -1,21 +1,18 @@
1
- from __future__ import annotations
1
+ from typing import Any
2
+
3
+ import numpy as np
4
+ import numpy.typing as npt
2
5
 
3
6
  from ._array_object import Array
4
- from ._flags import requires_api_version
5
7
  from ._dtypes import _numeric_dtypes
6
-
7
- from typing import TYPE_CHECKING
8
- if TYPE_CHECKING:
9
- from typing import Optional, Tuple, Union
10
-
11
- import numpy as np
8
+ from ._flags import requires_api_version
12
9
 
13
10
 
14
11
  def all(
15
12
  x: Array,
16
13
  /,
17
14
  *,
18
- axis: Optional[Union[int, Tuple[int, ...]]] = None,
15
+ axis: int | tuple[int, ...] | None = None,
19
16
  keepdims: bool = False,
20
17
  ) -> Array:
21
18
  """
@@ -30,7 +27,7 @@ def any(
30
27
  x: Array,
31
28
  /,
32
29
  *,
33
- axis: Optional[Union[int, Tuple[int, ...]]] = None,
30
+ axis: int | tuple[int, ...] | None = None,
34
31
  keepdims: bool = False,
35
32
  ) -> Array:
36
33
  """
@@ -40,6 +37,7 @@ def any(
40
37
  """
41
38
  return Array._new(np.asarray(np.any(x._array, axis=axis, keepdims=keepdims)), device=x.device)
42
39
 
40
+
43
41
  @requires_api_version('2024.12')
44
42
  def diff(
45
43
  x: Array,
@@ -47,8 +45,8 @@ def diff(
47
45
  *,
48
46
  axis: int = -1,
49
47
  n: int = 1,
50
- prepend: Optional[Array] = None,
51
- append: Optional[Array] = None,
48
+ prepend: Array | None = None,
49
+ append: Array | None = None,
52
50
  ) -> Array:
53
51
  if x.dtype not in _numeric_dtypes:
54
52
  raise TypeError("Only numeric dtypes are allowed in diff")
@@ -57,7 +55,7 @@ def diff(
57
55
  # currently specified.
58
56
 
59
57
  # NumPy does not support prepend=None or append=None
60
- kwargs = dict(axis=axis, n=n)
58
+ kwargs: dict[str, int | npt.NDArray[Any]] = {"axis": axis, "n": n}
61
59
  if prepend is not None:
62
60
  if prepend.device != x.device:
63
61
  raise ValueError(f"Arrays from two different devices ({prepend.device} and {x.device}) can not be combined.")
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '2.3'
21
- __version_tuple__ = version_tuple = (2, 3)
20
+ __version__ = version = '2.4'
21
+ __version_tuple__ = version_tuple = (2, 4)
File without changes