Skip to content

Commit 9988853

Browse files
authored
Increase support of array API standard. (#873)
1 parent 79c1a17 commit 9988853

File tree

10 files changed

+76
-68
lines changed

10 files changed

+76
-68
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ repos:
1818
exclude: ".ipynb"
1919

2020
- repo: https://github.com/astral-sh/ruff-pre-commit
21-
rev: v0.11.5
21+
rev: v0.11.10
2222
hooks:
23-
- id: ruff
23+
- id: ruff-check
2424
args: ["--fix"]
2525
types_or: [ python, pyi, jupyter ]
2626
- id: ruff-format

ci/Numba-array-api-skips.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
array_api_tests/test_operators_and_elementwise_functions.py::test_floor

ci/Numba-array-api-xfails.txt

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ array_api_tests/test_creation_functions.py::test_arange
55
array_api_tests/test_creation_functions.py::test_linspace
66
array_api_tests/test_creation_functions.py::test_meshgrid
77
array_api_tests/test_data_type_functions.py::test_finfo[float32]
8-
array_api_tests/test_data_type_functions.py::test_isdtype
98
array_api_tests/test_has_names.py::test_has_names[linalg-cholesky]
109
array_api_tests/test_has_names.py::test_has_names[linalg-cross]
1110
array_api_tests/test_has_names.py::test_has_names[linalg-det]
@@ -36,7 +35,6 @@ array_api_tests/test_has_names.py::test_has_names[creation-from_dlpack]
3635
array_api_tests/test_has_names.py::test_has_names[creation-linspace]
3736
array_api_tests/test_has_names.py::test_has_names[creation-meshgrid]
3837
array_api_tests/test_has_names.py::test_has_names[sorting-argsort]
39-
array_api_tests/test_has_names.py::test_has_names[data_type-isdtype]
4038
array_api_tests/test_has_names.py::test_has_names[array_method-__dlpack__]
4139
array_api_tests/test_has_names.py::test_has_names[array_method-__dlpack_device__]
4240
array_api_tests/test_has_names.py::test_has_names[array_method-__setitem__]
@@ -50,7 +48,6 @@ array_api_tests/test_signatures.py::test_func_signature[from_dlpack]
5048
array_api_tests/test_signatures.py::test_func_signature[linspace]
5149
array_api_tests/test_signatures.py::test_func_signature[meshgrid]
5250
array_api_tests/test_signatures.py::test_func_signature[argsort]
53-
array_api_tests/test_signatures.py::test_func_signature[isdtype]
5451
array_api_tests/test_signatures.py::test_array_method_signature[__dlpack__]
5552
array_api_tests/test_signatures.py::test_array_method_signature[__dlpack_device__]
5653
array_api_tests/test_signatures.py::test_array_method_signature[__setitem__]
@@ -74,71 +71,28 @@ array_api_tests/test_data_type_functions.py::test_finfo[complex64]
7471
array_api_tests/test_manipulation_functions.py::test_squeeze
7572
array_api_tests/test_has_names.py::test_has_names[utility-diff]
7673
array_api_tests/test_has_names.py::test_has_names[manipulation-repeat]
77-
array_api_tests/test_has_names.py::test_has_names[elementwise-copysign]
7874
array_api_tests/test_has_names.py::test_has_names[manipulation-tile]
7975
array_api_tests/test_has_names.py::test_has_names[manipulation-unstack]
80-
array_api_tests/test_has_names.py::test_has_names[elementwise-hypot]
81-
array_api_tests/test_has_names.py::test_has_names[elementwise-maximum]
82-
array_api_tests/test_has_names.py::test_has_names[elementwise-minimum]
83-
array_api_tests/test_has_names.py::test_has_names[elementwise-nextafter]
84-
array_api_tests/test_has_names.py::test_has_names[elementwise-reciprocal]
85-
array_api_tests/test_has_names.py::test_has_names[elementwise-signbit]
8676
array_api_tests/test_has_names.py::test_has_names[statistical-cumulative_sum]
8777
array_api_tests/test_has_names.py::test_has_names[statistical-cumulative_prod]
8878
array_api_tests/test_has_names.py::test_has_names[indexing-take_along_axis]
89-
array_api_tests/test_has_names.py::test_has_names[info-__array_namespace_info__]
9079
array_api_tests/test_has_names.py::test_has_names[searching-count_nonzero]
9180
array_api_tests/test_has_names.py::test_has_names[searching-searchsorted]
92-
array_api_tests/test_inspection_functions.py::test_array_namespace_info
93-
array_api_tests/test_inspection_functions.py::test_array_namespace_info_dtypes
9481
array_api_tests/test_signatures.py::test_func_signature[diff]
9582
array_api_tests/test_signatures.py::test_func_signature[repeat]
9683
array_api_tests/test_signatures.py::test_func_signature[tile]
9784
array_api_tests/test_signatures.py::test_func_signature[unstack]
98-
array_api_tests/test_signatures.py::test_func_signature[astype]
99-
array_api_tests/test_signatures.py::test_func_signature[copysign]
100-
array_api_tests/test_signatures.py::test_func_signature[hypot]
101-
array_api_tests/test_signatures.py::test_func_signature[maximum]
102-
array_api_tests/test_signatures.py::test_func_signature[minimum]
103-
array_api_tests/test_signatures.py::test_func_signature[nextafter]
104-
array_api_tests/test_signatures.py::test_func_signature[reciprocal]
105-
array_api_tests/test_signatures.py::test_func_signature[signbit]
10685
array_api_tests/test_signatures.py::test_func_signature[take_along_axis]
107-
array_api_tests/test_signatures.py::test_func_signature[__array_namespace_info__]
108-
array_api_tests/test_signatures.py::test_info_func_signature[capabilities]
109-
array_api_tests/test_signatures.py::test_info_func_signature[default_device]
110-
array_api_tests/test_signatures.py::test_info_func_signature[default_dtypes]
111-
array_api_tests/test_signatures.py::test_info_func_signature[devices]
112-
array_api_tests/test_signatures.py::test_info_func_signature[dtypes]
113-
array_api_tests/test_special_cases.py::test_unary[clip(x_i is NaN) -> NaN]
114-
array_api_tests/test_special_cases.py::test_unary[signbit(x_i is +0) -> False]
115-
array_api_tests/test_special_cases.py::test_unary[signbit(x_i is -0) -> True]
116-
array_api_tests/test_special_cases.py::test_unary[signbit(x_i is +infinity) -> False]
117-
array_api_tests/test_special_cases.py::test_unary[signbit(x_i is -infinity) -> True]
118-
array_api_tests/test_special_cases.py::test_unary[signbit(isfinite(x_i) and x_i > 0) -> False]
119-
array_api_tests/test_special_cases.py::test_unary[signbit(isfinite(x_i) and x_i < 0) -> True]
120-
array_api_tests/test_special_cases.py::test_unary[signbit(x_i is +NaN) -> False]
121-
array_api_tests/test_special_cases.py::test_unary[signbit(x_i is -NaN) -> True]
122-
array_api_tests/test_special_cases.py::test_binary[copysign(x1_i is NaN and x2_i < 0) -> NaN]
123-
array_api_tests/test_special_cases.py::test_binary[copysign(x1_i is NaN and x2_i is -0) -> NaN]
124-
array_api_tests/test_special_cases.py::test_binary[copysign(x1_i is NaN and x2_i is +0) -> NaN]
125-
array_api_tests/test_special_cases.py::test_binary[copysign(x1_i is NaN and x2_i > 0) -> NaN]
12686
array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is +infinity and isfinite(x2_i) and x2_i > 0) -> +infinity]
12787
array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is +infinity and isfinite(x2_i) and x2_i < 0) -> -infinity]
12888
array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is -infinity and isfinite(x2_i) and x2_i > 0) -> -infinity]
12989
array_api_tests/test_special_cases.py::test_binary[floor_divide(x1_i is -infinity and isfinite(x2_i) and x2_i < 0) -> +infinity]
13090
array_api_tests/test_special_cases.py::test_binary[floor_divide(isfinite(x1_i) and x1_i > 0 and x2_i is -infinity) -> -0]
131-
array_api_tests/test_operators_and_elementwise_functions.py::test_nextafter
13291
array_api_tests/test_special_cases.py::test_binary[__floordiv__(x1_i is +infinity and isfinite(x2_i) and x2_i > 0) -> +infinity]
13392
array_api_tests/test_special_cases.py::test_binary[floor_divide(isfinite(x1_i) and x1_i < 0 and x2_i is +infinity) -> -0]
13493
array_api_tests/test_special_cases.py::test_binary[__floordiv__(x1_i is +infinity and isfinite(x2_i) and x2_i < 0) -> -infinity]
135-
array_api_tests/test_special_cases.py::test_binary[maximum(x1_i is NaN or x2_i is NaN) -> NaN]
13694
array_api_tests/test_special_cases.py::test_binary[__floordiv__(x1_i is -infinity and isfinite(x2_i) and x2_i > 0) -> -infinity]
137-
array_api_tests/test_special_cases.py::test_binary[minimum(x1_i is NaN or x2_i is NaN) -> NaN]
13895
array_api_tests/test_special_cases.py::test_binary[__floordiv__(x1_i is -infinity and isfinite(x2_i) and x2_i < 0) -> +infinity]
139-
array_api_tests/test_special_cases.py::test_binary[nextafter(x1_i is NaN or x2_i is NaN) -> NaN]
140-
array_api_tests/test_special_cases.py::test_binary[nextafter(x1_i is -0 and x2_i is +0) -> +0]
141-
array_api_tests/test_special_cases.py::test_binary[nextafter(x1_i is +0 and x2_i is -0) -> -0]
14296
array_api_tests/test_special_cases.py::test_binary[__floordiv__(isfinite(x1_i) and x1_i > 0 and x2_i is -infinity) -> -0]
14397
array_api_tests/test_special_cases.py::test_binary[__floordiv__(isfinite(x1_i) and x1_i < 0 and x2_i is +infinity) -> -0]
14498
array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(x1_i is +infinity and isfinite(x2_i) and x2_i > 0) -> +infinity]
@@ -147,30 +101,18 @@ array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(x1_i is +infinity
147101
array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(isfinite(x1_i) and x1_i > 0 and x2_i is -infinity) -> -0]
148102
array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(x1_i is -infinity and isfinite(x2_i) and x2_i > 0) -> -infinity]
149103
array_api_tests/test_special_cases.py::test_iop[__ifloordiv__(isfinite(x1_i) and x1_i < 0 and x2_i is +infinity) -> -0]
150-
array_api_tests/test_operators_and_elementwise_functions.py::test_reciprocal
151104
array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_1[1]
152105
array_api_tests/test_statistical_functions.py::test_cumulative_prod
153106
array_api_tests/test_statistical_functions.py::test_cumulative_sum
154107
array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_1[None]
155-
array_api_tests/test_operators_and_elementwise_functions.py::test_signbit
156108
array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_2[1]
157109
array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_2[None]
158110
array_api_tests/test_manipulation_functions.py::test_repeat
159111
array_api_tests/test_searching_functions.py::test_count_nonzero
160-
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
161-
array_api_tests/test_operators_and_elementwise_functions.py::test_maximum
162112
array_api_tests/test_searching_functions.py::test_searchsorted
163113
array_api_tests/test_manipulation_functions.py::test_tile
164114
array_api_tests/test_signatures.py::test_func_signature[cumulative_sum]
165115
array_api_tests/test_signatures.py::test_func_signature[cumulative_prod]
166116
array_api_tests/test_manipulation_functions.py::test_unstack
167-
array_api_tests/test_operators_and_elementwise_functions.py::test_minimum
168-
array_api_tests/test_operators_and_elementwise_functions.py::test_hypot
169-
array_api_tests/test_operators_and_elementwise_functions.py::test_clip
170117
array_api_tests/test_signatures.py::test_func_signature[count_nonzero]
171118
array_api_tests/test_signatures.py::test_func_signature[searchsorted]
172-
array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_real[copysign]
173-
array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_real[hypot]
174-
array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_real[nextafter]
175-
array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_real[maximum]
176-
array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_real[minimum]

sparse/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class SparseFutureWarning(FutureWarning):
4848
from sparse.numba_backend import * # noqa: F403
4949
from sparse.numba_backend import ( # noqa: F401
5050
__all__,
51+
__array_namespace_info__,
5152
_common,
5253
_compressed,
5354
_coo,

sparse/numba_backend/__init__.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
complex64,
99
complex128,
1010
conj,
11+
copysign,
1112
cos,
1213
cosh,
1314
divide,
@@ -22,6 +23,7 @@
2223
floor_divide,
2324
greater,
2425
greater_equal,
26+
hypot,
2527
iinfo,
2628
inf,
2729
int8,
@@ -40,15 +42,20 @@
4042
logical_not,
4143
logical_or,
4244
logical_xor,
45+
maximum,
46+
minimum,
4347
multiply,
4448
nan,
4549
negative,
4650
newaxis,
51+
nextafter,
4752
not_equal,
4853
pi,
4954
positive,
55+
reciprocal,
5056
remainder,
5157
sign,
58+
signbit,
5259
sin,
5360
sinh,
5461
sqrt,
@@ -158,6 +165,8 @@
158165
)
159166
from ._dok import DOK
160167
from ._io import load_npz, save_npz
168+
from ._settings import IS_NUMPY2 as _IS_NUMPY2
169+
from ._settings import __array_namespace_info__ # noqa: F401
161170
from ._umath import elemwise
162171
from ._utils import random
163172

@@ -203,6 +212,7 @@
203212
"concat",
204213
"concatenate",
205214
"conj",
215+
"copysign",
206216
"cos",
207217
"cosh",
208218
"diagonal",
@@ -230,6 +240,7 @@
230240
"full_like",
231241
"greater",
232242
"greater_equal",
243+
"hypot",
233244
"iinfo",
234245
"imag",
235246
"inf",
@@ -258,8 +269,10 @@
258269
"matmul",
259270
"matrix_transpose",
260271
"max",
272+
"maximum",
261273
"mean",
262274
"min",
275+
"minimum",
263276
"moveaxis",
264277
"multiply",
265278
"nan",
@@ -271,6 +284,7 @@
271284
"nansum",
272285
"negative",
273286
"newaxis",
287+
"nextafter",
274288
"nonzero",
275289
"not_equal",
276290
"ones",
@@ -284,13 +298,15 @@
284298
"prod",
285299
"random",
286300
"real",
301+
"reciprocal",
287302
"remainder",
288303
"reshape",
289304
"result_type",
290305
"roll",
291306
"round",
292307
"save_npz",
293308
"sign",
309+
"signbit",
294310
"sin",
295311
"sinh",
296312
"sort",
@@ -320,3 +336,13 @@
320336
"zeros",
321337
"zeros_like",
322338
]
339+
340+
341+
if _IS_NUMPY2:
342+
from numpy import isdtype
343+
344+
__all__ += [
345+
"isdtype",
346+
]
347+
348+
__all__.sort()

sparse/numba_backend/_common.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2726,7 +2726,8 @@ def reshape(x, /, shape, *, copy=None):
27262726
return x.reshape(shape=shape)
27272727

27282728

2729-
def astype(x, dtype, /, *, copy=True):
2729+
@_check_device
2730+
def astype(x, dtype, /, *, copy=True, device=None):
27302731
"""
27312732
Copies an array to a specified data type irrespective of type-promotion rules.
27322733

sparse/numba_backend/_settings.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
AUTO_DENSIFY = bool(int(os.environ.get("SPARSE_AUTO_DENSIFY", "0")))
66
WARN_ON_TOO_DENSE = bool(int(os.environ.get("SPARSE_WARN_ON_TOO_DENSE", "0")))
7+
IS_NUMPY2 = np.lib.NumpyVersion(np.__version__) >= "2.0.0a1"
78

89

910
def _is_nep18_enabled():
@@ -18,3 +19,32 @@ def __array_function__(self, *args, **kwargs):
1819

1920

2021
NEP18_ENABLED = _is_nep18_enabled()
22+
23+
24+
class ArrayNamespaceInfo:
25+
def __init__(self):
26+
self.np_info = np.__array_namespace_info__()
27+
28+
def capabilities(self):
29+
np_capabilities = self.np_info.capabilities()
30+
return {
31+
"boolean indexing": True,
32+
"data-dependent shapes": True,
33+
"max dimensions": np_capabilities.get("max dimensions", 64) - 1,
34+
}
35+
36+
def default_device(self):
37+
return self.np_info.default_device()
38+
39+
def default_dtypes(self, *, device=None):
40+
return self.np_info.default_dtypes(device=device)
41+
42+
def devices(self):
43+
return self.np_info.devices()
44+
45+
def dtypes(self, *, device=None, kind=None):
46+
return self.np_info.dtypes(device=device, kind=kind)
47+
48+
49+
def __array_namespace_info__() -> ArrayNamespaceInfo:
50+
return ArrayNamespaceInfo()

sparse/numba_backend/_sparse_array.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,6 @@ def clip(self, min=None, max=None, out=None):
609609
- [sparse.clip][] : For full documentation and more details.
610610
- [`numpy.clip`][] : Equivalent NumPy function.
611611
"""
612-
if min is None and max is None:
613-
raise ValueError("One of max or min must be given.")
614612
if out is not None and not isinstance(out, tuple):
615613
out = (out,)
616614
return self.__array_ufunc__(np.clip, "__call__", self, a_min=min, a_max=max, out=out)

sparse/numba_backend/tests/test_coo.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,9 +1130,6 @@ def test_clip():
11301130

11311131
assert_eq(np.clip(s, 1, 3), np.clip(x, 1, 3))
11321132

1133-
with pytest.raises(ValueError):
1134-
s.clip()
1135-
11361133
out = sparse.COO.from_numpy(np.zeros_like(x))
11371134
out2 = s.clip(min=1, max=3, out=out)
11381135
assert out is out2

0 commit comments

Comments
 (0)