diff --git a/CHANGELOG.md b/CHANGELOG.md index fbbd3323993f..ab8d1fd619e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added a new backend routine `syrk` from oneMKL to perform symmetric rank-k update which is used for a specialized matrix multiplication where the result is a symmetric matrix [2509](https://github.com/IntelPython/dpnp/pull/2509) * Added `timeout-minutes` property to GitHub jobs [#2526](https://github.com/IntelPython/dpnp/pull/2526) * Added implementation of `dpnp.ndarray.data` and `dpnp.ndarray.data.ptr` attributes [#2521](https://github.com/IntelPython/dpnp/pull/2521) +* Added `dpnp.ndarray.__contains__` method [#2534](https://github.com/IntelPython/dpnp/pull/2534) ### Changed diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 791b2a8178c4..a70a4e99e668 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -242,7 +242,9 @@ def __bool__(self): def __complex__(self): return self._array_obj.__complex__() - # '__contains__', + def __contains__(self, value, /): + r"""Return :math:`\text{value in self}`.""" + return (self == value).any() def __copy__(self): """ diff --git a/dpnp/tests/test_ndarray.py b/dpnp/tests/test_ndarray.py index eaccf689a795..90b4045f62f9 100644 --- a/dpnp/tests/test_ndarray.py +++ b/dpnp/tests/test_ndarray.py @@ -74,6 +74,39 @@ def test_attributes(self): assert_equal(self.two.itemsize, self.two.dtype.itemsize) +@testing.parameterize(*testing.product({"xp": [dpnp, numpy]})) +class TestContains: + def test_basic(self): + a = self.xp.arange(10).reshape((2, 5)) + assert 4 in a + assert 20 not in a + + def test_broadcast(self): + xp = self.xp + a = xp.arange(6).reshape((2, 3)) + assert 4 in a + assert xp.array([0, 1, 2]) in a + assert xp.array([5, 3, 4]) not in a + + def test_broadcast_error(self): + a = self.xp.arange(10).reshape((2, 5)) + with pytest.raises( + ValueError, + match="operands could not be broadcast together with shapes", + ): + self.xp.array([1, 2]) in a + + def test_strides(self): + xp = self.xp + a = xp.arange(10).reshape((2, 5)) + a = a[:, ::2] + assert 4 in a + assert 8 not in a + assert xp.full(a.shape[-1], fill_value=2) in a + assert xp.full_like(a, fill_value=7) in a + assert xp.full_like(a, fill_value=6) not in a + + class TestView: def test_none_dtype(self): a = numpy.ones((1, 2, 4), dtype=numpy.int32)