diff --git a/CHANGELOG.md b/CHANGELOG.md index db62a8b6347..172e6f6ecee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,7 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Updated `pre-commit` GitHub workflow to pass `no-commit-to-branch` check [#2501](https://github.com/IntelPython/dpnp/pull/2501) * Updated the math formulas in summary of `dpnp.matvec` and `dpnp.vecmat` to correct a typo [#2503](https://github.com/IntelPython/dpnp/pull/2503) * Avoided negating unsigned integers in ceil division used in `dpnp.resize` implementation [#2508](https://github.com/IntelPython/dpnp/pull/2508) -* Fixed `dpnp.unique` with 1d input array and `axis=0`, `equal_nan=True` keywords passed where the produced result doesn't collapse the NaNs [#2530](https://github.com/IntelPython/dpnp/pull/2530) +* Fixed `dpnp.unique` with 1d input array and `axis=0`, `equal_nan=True` keywords passed where the produced result doesn't collapse the NaNs [#2530](https://github.com/IntelPython/dpnp/pull/2530), [#2587](https://github.com/IntelPython/dpnp/pull/2587) * Resolved issue when `dpnp.ndarray` constructor is called with `dpnp.ndarray.data` as `buffer` keyword [#2533](https://github.com/IntelPython/dpnp/pull/2533) * Fixed `dpnp.linalg.cond` to always return a real dtype [#2547](https://github.com/IntelPython/dpnp/pull/2547) * Resolved the issue in `dpnp.random` functions to allow any value of `size` where each element is castable to `Py_ssize_t` type [#2578](https://github.com/IntelPython/dpnp/pull/2578) diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index 2a9c958c3a4..b994819fa39 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -4270,7 +4270,13 @@ def unique( """ - if axis is None or (axis == 0 and ar.ndim == 1): + dpnp.check_supported_arrays_type(ar) + nd = ar.ndim + + if axis is None or nd == 1: + if axis is not None: + normalize_axis_index(axis, nd) + return _unique_1d( ar, return_index, return_inverse, return_counts, equal_nan ) @@ -4280,7 +4286,7 @@ def unique( ar = dpnp.moveaxis(ar, axis, 0) except AxisError: # this removes the "axis1" or "axis2" prefix from the error message - raise AxisError(axis, ar.ndim) from None + raise AxisError(axis, nd) from None # reshape input array into a contiguous 2D array orig_sh = ar.shape diff --git a/dpnp/tests/test_manipulation.py b/dpnp/tests/test_manipulation.py index 0b3d6eb12dc..25ac9445aaf 100644 --- a/dpnp/tests/test_manipulation.py +++ b/dpnp/tests/test_manipulation.py @@ -1852,17 +1852,28 @@ def test_equal_nan(self, eq_nan_kwd): # TODO: uncomment once numpy 2.4.0 release is published # @testing.with_requires("numpy>=2.4.0") - def test_1d_equal_nan_axis0(self): + @pytest.mark.parametrize("axis", [0, -1]) + def test_1d_equal_nan_axis(self, axis): a = numpy.array([numpy.nan, 0, 0, numpy.nan]) ia = dpnp.array(a) - result = dpnp.unique(ia, axis=0, equal_nan=True) - expected = numpy.unique(a, axis=0, equal_nan=True) + result = dpnp.unique(ia, axis=axis, equal_nan=True) + expected = numpy.unique(a, axis=axis, equal_nan=True) # TODO: remove when numpy#29372 is released if numpy_version() < "2.4.0": expected = numpy.array([0.0, numpy.nan]) assert_array_equal(result, expected) + # TODO: uncomment once numpy 2.4.0 release is published + # @testing.with_requires("numpy>=2.4.0") + @pytest.mark.parametrize("equal_nan", [True, False]) + # @pytest.mark.parametrize("xp", [numpy, dpnp]) + @pytest.mark.parametrize("xp", [dpnp]) + def test_1d_axis_float_raises_typeerror(self, xp, equal_nan): + a = xp.array([xp.nan, 0, 0, xp.nan]) + with pytest.raises(TypeError, match="integer argument expected"): + xp.unique(a, axis=0.0, equal_nan=equal_nan) + @testing.with_requires("numpy>=2.0.1") @pytest.mark.parametrize("dt", get_float_complex_dtypes()) @pytest.mark.parametrize(