Skip to content

Commit 9edbbeb

Browse files
authored
Merge branch 'master' into improve-coverage-manipulaiton
2 parents 9081800 + f56a43f commit 9edbbeb

File tree

13 files changed

+265
-37
lines changed

13 files changed

+265
-37
lines changed

.github/workflows/array-api-skips.txt

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,5 @@
11
# array API tests to be skipped
22

3-
# missing unique-like functions
4-
array_api_tests/test_has_names.py::test_has_names[set-unique_all]
5-
array_api_tests/test_has_names.py::test_has_names[set-unique_counts]
6-
array_api_tests/test_has_names.py::test_has_names[set-unique_inverse]
7-
array_api_tests/test_has_names.py::test_has_names[set-unique_values]
8-
array_api_tests/test_set_functions.py::test_unique_all
9-
array_api_tests/test_set_functions.py::test_unique_counts
10-
array_api_tests/test_set_functions.py::test_unique_inverse
11-
array_api_tests/test_set_functions.py::test_unique_values
12-
array_api_tests/test_signatures.py::test_func_signature[unique_all]
13-
array_api_tests/test_signatures.py::test_func_signature[unique_counts]
14-
array_api_tests/test_signatures.py::test_func_signature[unique_inverse]
15-
array_api_tests/test_signatures.py::test_func_signature[unique_values]
16-
173
# hypothesis found failures
184
array_api_tests/test_operators_and_elementwise_functions.py::test_clip
195

doc/reference/creation.rst renamed to doc/reference/array-creation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.. _routines.creation:
1+
.. _routines.array-creation:
22

33
Array creation routines
44
=======================

doc/reference/manipulation.rst renamed to doc/reference/array-manipulation.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ Adding and removing elements
135135
dpnp.append
136136
dpnp.resize
137137
dpnp.trim_zeros
138-
dpnp.unique
139138
dpnp.pad
140139

141140

File renamed without changes.

doc/reference/misc.rst renamed to doc/reference/other.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ Utility
1010
:toctree: generated/
1111
:nosignatures:
1212

13-
dpnp.broadcast_shapes
1413
dpnp.byte_bounds
1514
dpnp.get_include
1615
dpnp.show_config
1716
dpnp.show_runtime
17+
dpnp.broadcast_shapes

doc/reference/routines.rst

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,19 @@ These functions cover a subset of
1111
.. toctree::
1212
:maxdepth: 2
1313

14-
creation
15-
manipulation
16-
binary
14+
array-creation
15+
array-manipulation
16+
bitwise
1717
dtype
1818
fft
1919
functional
2020
indexing
2121
linalg
2222
logic
2323
math
24+
other
2425
.. polynomials
2526
random
26-
sorting
27+
set
28+
sort
2729
statistics

doc/reference/set.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Set routines
2+
============
3+
4+
.. https://numpy.org/doc/stable/reference/routines.set.html
5+
6+
Making proper sets
7+
------------------
8+
.. autosummary::
9+
:toctree: generated/
10+
:nosignatures:
11+
12+
dpnp.unique
13+
dpnp.unique_all
14+
dpnp.unique_counts
15+
dpnp.unique_inverse
16+
dpnp.unique_values
17+
18+
Boolean operations
19+
------------------
20+
.. autosummary::
21+
:toctree: generated/
22+
:nosignatures:
23+
24+
dpnp.in1d
25+
dpnp.intersect1d
26+
dpnp.isin
27+
dpnp.setdiff1d
28+
dpnp.setxor1d
29+
dpnp.union1d
File renamed without changes.

dpnp/dpnp_iface_manipulation.py

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,24 @@ class InsertDeleteParams(NamedTuple):
7171
usm_type: str
7272

7373

74+
# pylint:disable=missing-class-docstring
75+
class UniqueAllResult(NamedTuple):
76+
values: dpnp.ndarray
77+
indices: dpnp.ndarray
78+
inverse_indices: dpnp.ndarray
79+
counts: dpnp.ndarray
80+
81+
82+
class UniqueCountsResult(NamedTuple):
83+
values: dpnp.ndarray
84+
counts: dpnp.ndarray
85+
86+
87+
class UniqueInverseResult(NamedTuple):
88+
values: dpnp.ndarray
89+
inverse_indices: dpnp.ndarray
90+
91+
7492
__all__ = [
7593
"append",
7694
"array_split",
@@ -122,6 +140,10 @@ class InsertDeleteParams(NamedTuple):
122140
"transpose",
123141
"trim_zeros",
124142
"unique",
143+
"unique_all",
144+
"unique_counts",
145+
"unique_inverse",
146+
"unique_values",
125147
"unstack",
126148
"vsplit",
127149
"vstack",
@@ -4275,6 +4297,189 @@ def unique(
42754297
return _unpack_tuple(result)
42764298

42774299

4300+
def unique_all(x, /):
4301+
"""
4302+
Find the unique elements of an array, and counts, inverse, and indices.
4303+
4304+
For full documentation refer to :obj:`numpy.unique_all`.
4305+
4306+
Parameters
4307+
----------
4308+
x : {dpnp.ndarray, usm_ndarray}
4309+
Input array. It will be flattened if it is not already 1-D.
4310+
4311+
Returns
4312+
-------
4313+
A namedtuple with the following attributes:
4314+
4315+
values : dpnp.ndarray
4316+
The unique elements of an input array.
4317+
indices : dpnp.ndarray
4318+
The first occurring indices for each unique element.
4319+
inverse_indices : dpnp.ndarray
4320+
The indices from the set of unique elements that reconstruct `x`.
4321+
counts : dpnp.ndarray
4322+
The corresponding counts for each unique element.
4323+
4324+
See Also
4325+
--------
4326+
:obj:`dpnp.unique` : Find the unique elements of an array.
4327+
4328+
Examples
4329+
--------
4330+
>>> import dpnp as np
4331+
>>> x = np.array([1, 1, 2])
4332+
>>> uniq = np.unique_all(x)
4333+
>>> uniq.values
4334+
array([1, 2])
4335+
>>> uniq.indices
4336+
array([0, 2])
4337+
>>> uniq.inverse_indices
4338+
array([0, 0, 1])
4339+
>>> uniq.counts
4340+
array([2, 1])
4341+
4342+
"""
4343+
4344+
result = dpnp.unique(
4345+
x,
4346+
return_index=True,
4347+
return_inverse=True,
4348+
return_counts=True,
4349+
equal_nan=False,
4350+
)
4351+
return UniqueAllResult(*result)
4352+
4353+
4354+
def unique_counts(x, /):
4355+
"""
4356+
Find the unique elements and counts of an input array `x`.
4357+
4358+
For full documentation refer to :obj:`numpy.unique_counts`.
4359+
4360+
Parameters
4361+
----------
4362+
x : {dpnp.ndarray, usm_ndarray}
4363+
Input array. It will be flattened if it is not already 1-D.
4364+
4365+
Returns
4366+
-------
4367+
A namedtuple with the following attributes:
4368+
4369+
values : dpnp.ndarray
4370+
The unique elements of an input array.
4371+
counts : dpnp.ndarray
4372+
The corresponding counts for each unique element.
4373+
4374+
See Also
4375+
--------
4376+
:obj:`dpnp.unique` : Find the unique elements of an array.
4377+
4378+
Examples
4379+
--------
4380+
>>> import dpnp as np
4381+
>>> x = np.array([1, 1, 2])
4382+
>>> uniq = np.unique_counts(x)
4383+
>>> uniq.values
4384+
array([1, 2])
4385+
>>> uniq.counts
4386+
array([2, 1])
4387+
4388+
"""
4389+
4390+
result = dpnp.unique(
4391+
x,
4392+
return_index=False,
4393+
return_inverse=False,
4394+
return_counts=True,
4395+
equal_nan=False,
4396+
)
4397+
return UniqueCountsResult(*result)
4398+
4399+
4400+
def unique_inverse(x, /):
4401+
"""
4402+
Find the unique elements of `x` and indices to reconstruct `x`.
4403+
4404+
For full documentation refer to :obj:`numpy.unique_inverse`.
4405+
4406+
Parameters
4407+
----------
4408+
x : {dpnp.ndarray, usm_ndarray}
4409+
Input array. It will be flattened if it is not already 1-D.
4410+
4411+
Returns
4412+
-------
4413+
A namedtuple with the following attributes:
4414+
4415+
values : dpnp.ndarray
4416+
The unique elements of an input array.
4417+
inverse_indices : dpnp.ndarray
4418+
The indices from the set of unique elements that reconstruct `x`.
4419+
4420+
See Also
4421+
--------
4422+
:obj:`dpnp.unique` : Find the unique elements of an array.
4423+
4424+
Examples
4425+
--------
4426+
>>> import dpnp as np
4427+
>>> x = np.array([1, 1, 2])
4428+
>>> uniq = np.unique_inverse(x)
4429+
>>> uniq.values
4430+
array([1, 2])
4431+
>>> uniq.inverse_indices
4432+
array([0, 0, 1])
4433+
4434+
"""
4435+
4436+
result = dpnp.unique(
4437+
x,
4438+
return_index=False,
4439+
return_inverse=True,
4440+
return_counts=False,
4441+
equal_nan=False,
4442+
)
4443+
return UniqueInverseResult(*result)
4444+
4445+
4446+
def unique_values(x, /):
4447+
"""
4448+
Returns the unique elements of an input array `x`.
4449+
4450+
For full documentation refer to :obj:`numpy.unique_values`.
4451+
4452+
Parameters
4453+
----------
4454+
x : {dpnp.ndarray, usm_ndarray}
4455+
Input array. It will be flattened if it is not already 1-D.
4456+
4457+
Returns
4458+
-------
4459+
out : dpnp.ndarray
4460+
The unique elements of an input array.
4461+
4462+
See Also
4463+
--------
4464+
:obj:`dpnp.unique` : Find the unique elements of an array.
4465+
4466+
Examples
4467+
--------
4468+
>>> import dpnp as np
4469+
>>> np.unique_values(np.array([1, 1, 2]))
4470+
array([1, 2])
4471+
4472+
"""
4473+
4474+
return dpnp.unique(
4475+
x,
4476+
return_index=False,
4477+
return_inverse=False,
4478+
return_counts=False,
4479+
equal_nan=False,
4480+
)
4481+
4482+
42784483
def unstack(x, /, *, axis=0):
42794484
"""
42804485
Split an array into a sequence of arrays along the given axis.

dpnp/tests/test_manipulation.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
get_float_dtypes,
2222
get_integer_dtypes,
2323
has_support_aspect64,
24+
numpy_version,
2425
)
2526
from .third_party.cupy import testing
2627

@@ -1152,7 +1153,7 @@ def test_ndarray(self):
11521153
result = ia.reshape((2, 5))
11531154
assert_array_equal(result, expected)
11541155

1155-
@testing.with_requires("numpy>=2.0")
1156+
@testing.with_requires("numpy>=2.1")
11561157
def test_copy(self):
11571158
a = numpy.arange(10).reshape(2, 5)
11581159
ia = dpnp.array(a)
@@ -1870,10 +1871,7 @@ def test_2d_axis_nans(self, dt, axis_kwd, return_kwds, row):
18701871
if len(return_kwds) == 0:
18711872
assert_array_equal(result, expected)
18721873
else:
1873-
if (
1874-
len(axis_kwd) == 0
1875-
and numpy.lib.NumpyVersion(numpy.__version__) < "2.0.1"
1876-
):
1874+
if len(axis_kwd) == 0 and numpy_version() < "2.0.1":
18771875
# gh-26961: numpy.unique(..., return_inverse=True, axis=None)
18781876
# returned flatten unique_inverse till 2.0.1 version
18791877
expected = (
@@ -1884,6 +1882,20 @@ def test_2d_axis_nans(self, dt, axis_kwd, return_kwds, row):
18841882
for iv, v in zip(result, expected):
18851883
assert_array_equal(iv, v)
18861884

1885+
@testing.with_requires("numpy>=2.0")
1886+
@pytest.mark.parametrize(
1887+
"func",
1888+
["unique_all", "unique_counts", "unique_inverse", "unique_values"],
1889+
)
1890+
def test_array_api_functions(self, func):
1891+
a = numpy.array([numpy.nan, 1, 4, 1, 3, 4, 5, 5, 1])
1892+
ia = dpnp.array(a)
1893+
1894+
result = getattr(dpnp, func)(ia)
1895+
expected = getattr(numpy, func)(a)
1896+
for iv, v in zip(result, expected):
1897+
assert_array_equal(iv, v)
1898+
18871899

18881900
class TestVsplit:
18891901
@pytest.mark.parametrize("xp", [numpy, dpnp])

dpnp/tests/test_mathematical.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,10 +2445,10 @@ def test_out(self, func_params, dtype):
24452445

24462446
assert result is dp_out
24472447
# numpy.ceil, numpy.floor, numpy.trunc always return float dtype for
2448-
# NumPy < 2.0.0 while output has the dtype of input for NumPy >= 2.0.0
2448+
# NumPy < 2.1.0 while output has the dtype of input for NumPy >= 2.1.0
24492449
# (dpnp follows the latter behavior except for boolean dtype where it
24502450
# returns int8)
2451-
if numpy_version() < "2.0.0" or dtype == numpy.bool:
2451+
if numpy_version() < "2.1.0" or dtype == numpy.bool:
24522452
check_type = False
24532453
else:
24542454
check_type = True

0 commit comments

Comments
 (0)