From 36152fa882d87ce4adf7bb9cc3a1e937576ec09b Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 17 Jun 2024 13:33:48 +0200 Subject: [PATCH 01/12] Implement dpnp.isneginf() --- dpnp/dpnp_iface_logic.py | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/dpnp/dpnp_iface_logic.py b/dpnp/dpnp_iface_logic.py index d780cf578bf..5245007013a 100644 --- a/dpnp/dpnp_iface_logic.py +++ b/dpnp/dpnp_iface_logic.py @@ -66,6 +66,7 @@ "isfinite", "isinf", "isnan", + "isneginf", "less", "less_equal", "logical_and", @@ -710,6 +711,70 @@ def isclose(x1, x2, rtol=1e-05, atol=1e-08, equal_nan=False): ) +def isneginf(x, out=None): + """ + Test element-wise for negative infinity, return result as bool array. + + For full documentation refer to :obj:`numpy.isneginf`. + + Parameters + ---------- + x : {dpnp.ndarray, usm_ndarray} + Input array. + out : {None, dpnp.ndarray, usm_ndarray}, optional + A location into which the result is stored. If provided, it must have a + shape that the input broadcasts to and a boolean data type. + If not provided or None, a freshly-allocated boolean array is returned + + Returns + ------- + out : dpnp.ndarray + Boolean array of same shape as ``x``. + + See Also + -------- + :obj:`dpnp.isinf` : Test element-wise for positive or negative infinity. + :obj:`dpnp.isposinf` : Test element-wise for positive infinity, + return result as bool array. + :obj:`dpnp.isnan` : Test element-wise for NaN and + return result as a boolean array. + :obj:`dpnp.isfinite` : Test element-wise for finiteness. + + Examples + -------- + >>> import dpnp as np + >>> x = np.array(np.inf) + >>> np.isneginf(-x) + array(True) + >>> np.isneginf(x) + array(False) + + >>> x = np.array([-np.inf, 0., np.inf]) + >>> np.isneginf(x) + array([ True, False, False]) + + >>> x = np.array([-np.inf, 0., np.inf]) + >>> y = np.zeros(x.shape, dtype='bool') + >>> np.isneginf(x, y) + array([ True, False, False]) + >>> y + array([ True, False, False]) + + """ + + is_inf = dpnp.isinf(x) + try: + signbit = dpnp.signbit(x) + except ValueError as e: + dtype = x.dtype + raise TypeError( + f"This operation is not supported for {dtype} values " + "because it would be ambiguous." + ) from e + + return dpnp.logical_and(is_inf, signbit, out) + + _LESS_DOCSTRING = """ Computes the less-than test results for each element `x1_i` of the input array `x1` with the respective element `x2_i` of the input array `x2`. From 070286f13bdc0c73448ff838fd6b70fb1598169c Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 17 Jun 2024 13:44:10 +0200 Subject: [PATCH 02/12] Add tests for dpnp.isneginf() --- tests/test_logic.py | 30 ++++++++++++++++++- .../cupy/logic_tests/test_content.py | 13 ++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/test_logic.py b/tests/test_logic.py index 1b8e34a6fe8..0f3433012f5 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -7,7 +7,6 @@ from .helper import ( get_all_dtypes, get_float_complex_dtypes, - has_support_aspect64, ) @@ -394,3 +393,32 @@ def test_finite(op, data, dtype): dpnp_res = getattr(dpnp, op)(x, out=dp_out) assert dp_out is dpnp_res assert_equal(dpnp_res, np_res) + + +@pytest.mark.parametrize("func", ["isneginf"], ids=["isneginf"]) +@pytest.mark.parametrize( + "data", + [ + [dpnp.inf, -1, 0, 1, dpnp.nan, -dpnp.inf], + [[dpnp.inf, dpnp.nan], [dpnp.nan, 0], [1, -dpnp.inf]], + ], + ids=[ + "[dpnp.inf, -1, 0, 1, dpnp.nan, -dpnp.inf]", + "[[dpnp.inf, dpnp.nan], [dpnp.nan, 0], [1, -dpnp.inf]]", + ], +) +@pytest.mark.parametrize("dtype", get_float_complex_dtypes()) +def test_infinity_sign(func, data, dtype): + x = dpnp.asarray(data, dtype=dtype) + if dpnp.issubdtype(dtype, dpnp.complexfloating): + with pytest.raises(TypeError): + dpnp_res = getattr(dpnp, func)(x) + else: + np_res = getattr(numpy, func)(x.asnumpy()) + dpnp_res = getattr(dpnp, func)(x) + assert_equal(dpnp_res, np_res) + + dp_out = dpnp.empty(np_res.shape, dtype=dpnp.bool) + dpnp_res = getattr(dpnp, func)(x, out=dp_out) + assert dp_out is dpnp_res + assert_equal(dpnp_res, np_res) diff --git a/tests/third_party/cupy/logic_tests/test_content.py b/tests/third_party/cupy/logic_tests/test_content.py index fe2446d68b2..6987d2951a5 100644 --- a/tests/third_party/cupy/logic_tests/test_content.py +++ b/tests/third_party/cupy/logic_tests/test_content.py @@ -29,3 +29,16 @@ def test_isinf(self): def test_isnan(self): self.check_unary_nan("isnan") + + +class TestUfuncLike(unittest.TestCase): + @testing.numpy_cupy_array_equal() + def check_unary(self, name, xp): + a = xp.array([-3, xp.inf, -1, -xp.inf, 0, 1, 2, xp.nan]) + return getattr(xp, name)(a) + + def test_isneginf(self): + self.check_unary("isneginf") + + # def test_isposinf(self): + # self.check_unary("isposinf") From 8455c101c4cade82771d990f873cc850acf5043d Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 17 Jun 2024 13:54:42 +0200 Subject: [PATCH 03/12] Implement dpnp.isposinf() --- dpnp/dpnp_iface_logic.py | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/dpnp/dpnp_iface_logic.py b/dpnp/dpnp_iface_logic.py index 5245007013a..b1a2768bad7 100644 --- a/dpnp/dpnp_iface_logic.py +++ b/dpnp/dpnp_iface_logic.py @@ -67,6 +67,7 @@ "isinf", "isnan", "isneginf", + "isposinf", "less", "less_equal", "logical_and", @@ -775,6 +776,70 @@ def isneginf(x, out=None): return dpnp.logical_and(is_inf, signbit, out) +def isposinf(x, out=None): + """ + Test element-wise for positive infinity, return result as bool array. + + For full documentation refer to :obj:`numpy.isposinf`. + + Parameters + ---------- + x : {dpnp.ndarray, usm_ndarray} + Input array. + out : {None, dpnp.ndarray, usm_ndarray}, optional + A location into which the result is stored. If provided, it must have a + shape that the input broadcasts to and a boolean data type. + If not provided or None, a freshly-allocated boolean array is returned + + Returns + ------- + out : dpnp.ndarray + Boolean array of same shape as ``x``. + + See Also + -------- + :obj:`dpnp.isinf` : Test element-wise for positive or negative infinity. + :obj:`dpnp.isneginf` : Test element-wise for negative infinity, + return result as bool array. + :obj:`dpnp.isnan` : Test element-wise for NaN and + return result as a boolean array. + :obj:`dpnp.isfinite` : Test element-wise for finiteness. + + Examples + -------- + >>> import dpnp as np + >>> x = np.array(np.inf) + >>> np.isposinf(x) + array(True) + >>> np.isposinf(-x) + array(False) + + >>> x = np.array([-np.inf, 0., np.inf]) + >>> np.isposinf(x) + array([False, False, True]) + + >>> x = np.array([-np.inf, 0., np.inf]) + >>> y = np.zeros(x.shape, dtype='bool') + >>> np.isposinf(x, y) + array([False, False, True]) + >>> y + array([False, False, True]) + + """ + + is_inf = dpnp.isinf(x) + try: + signbit = ~dpnp.signbit(x) + except ValueError as e: + dtype = x.dtype + raise TypeError( + f"This operation is not supported for {dtype} values " + "because it would be ambiguous." + ) from e + + return dpnp.logical_and(is_inf, signbit, out) + + _LESS_DOCSTRING = """ Computes the less-than test results for each element `x1_i` of the input array `x1` with the respective element `x2_i` of the input array `x2`. From 18bc6b49313d3af9bdede1e7914175be11a12307 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 17 Jun 2024 13:55:02 +0200 Subject: [PATCH 04/12] Add tests for dpnp.isposinf() --- tests/test_logic.py | 6 +++--- tests/third_party/cupy/logic_tests/test_content.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_logic.py b/tests/test_logic.py index 0f3433012f5..10ea3708b0f 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -395,7 +395,7 @@ def test_finite(op, data, dtype): assert_equal(dpnp_res, np_res) -@pytest.mark.parametrize("func", ["isneginf"], ids=["isneginf"]) +@pytest.mark.parametrize("func", ["isneginf", "isposinf"]) @pytest.mark.parametrize( "data", [ @@ -403,8 +403,8 @@ def test_finite(op, data, dtype): [[dpnp.inf, dpnp.nan], [dpnp.nan, 0], [1, -dpnp.inf]], ], ids=[ - "[dpnp.inf, -1, 0, 1, dpnp.nan, -dpnp.inf]", - "[[dpnp.inf, dpnp.nan], [dpnp.nan, 0], [1, -dpnp.inf]]", + "1D array", + "2D array", ], ) @pytest.mark.parametrize("dtype", get_float_complex_dtypes()) diff --git a/tests/third_party/cupy/logic_tests/test_content.py b/tests/third_party/cupy/logic_tests/test_content.py index 6987d2951a5..3f0a88c6781 100644 --- a/tests/third_party/cupy/logic_tests/test_content.py +++ b/tests/third_party/cupy/logic_tests/test_content.py @@ -40,5 +40,5 @@ def check_unary(self, name, xp): def test_isneginf(self): self.check_unary("isneginf") - # def test_isposinf(self): - # self.check_unary("isposinf") + def test_isposinf(self): + self.check_unary("isposinf") From 3eb9dbdb27024dff0eaedc6a2f6d9641f72ff45d Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 17 Jun 2024 16:39:23 +0200 Subject: [PATCH 05/12] Add new functions to gen docs --- doc/reference/logic.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/reference/logic.rst b/doc/reference/logic.rst index f5b3e646e66..57133259c71 100644 --- a/doc/reference/logic.rst +++ b/doc/reference/logic.rst @@ -26,6 +26,8 @@ Infinities and NaNs dpnp.isfinite dpnp.isinf dpnp.isnan + dpnp.isneginf + dpnp.isposinf Array type testing From d3c8545a58a162dc0dca2180f2a551ab96bb0412 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 17 Jun 2024 16:48:35 +0200 Subject: [PATCH 06/12] Add additional checks --- dpnp/dpnp_iface_logic.py | 60 ++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/dpnp/dpnp_iface_logic.py b/dpnp/dpnp_iface_logic.py index b1a2768bad7..5f36bfe44c6 100644 --- a/dpnp/dpnp_iface_logic.py +++ b/dpnp/dpnp_iface_logic.py @@ -725,7 +725,9 @@ def isneginf(x, out=None): out : {None, dpnp.ndarray, usm_ndarray}, optional A location into which the result is stored. If provided, it must have a shape that the input broadcasts to and a boolean data type. - If not provided or None, a freshly-allocated boolean array is returned + If not provided or ``None``, a freshly-allocated boolean array + is returned. + Default: ``None``. Returns ------- @@ -763,17 +765,27 @@ def isneginf(x, out=None): """ - is_inf = dpnp.isinf(x) - try: - signbit = dpnp.signbit(x) - except ValueError as e: - dtype = x.dtype + dpnp.check_supported_arrays_type(x) + + if out is not None: + dpnp.check_supported_arrays_type(out) + out_dtype = out.dtype + if not dpnp.issubdtype(out_dtype, dpnp.bool): + raise TypeError( + f"Output array data type must be boolean, got {out.dtype}" + ) + + x_dtype = x.dtype + if dpnp.issubdtype(x_dtype, dpnp.complexfloating): raise TypeError( - f"This operation is not supported for {dtype} values " + f"This operation is not supported for {x_dtype} values " "because it would be ambiguous." - ) from e + ) + + is_inf = dpnp.isinf(x) + signbit = dpnp.signbit(x) - return dpnp.logical_and(is_inf, signbit, out) + return dpnp.logical_and(is_inf, signbit, out=out) def isposinf(x, out=None): @@ -789,7 +801,9 @@ def isposinf(x, out=None): out : {None, dpnp.ndarray, usm_ndarray}, optional A location into which the result is stored. If provided, it must have a shape that the input broadcasts to and a boolean data type. - If not provided or None, a freshly-allocated boolean array is returned + If not provided or ``None``, a freshly-allocated boolean array + is returned. + Default: ``None``. Returns ------- @@ -827,17 +841,27 @@ def isposinf(x, out=None): """ - is_inf = dpnp.isinf(x) - try: - signbit = ~dpnp.signbit(x) - except ValueError as e: - dtype = x.dtype + dpnp.check_supported_arrays_type(x) + + if out is not None: + dpnp.check_supported_arrays_type(out) + out_dtype = out.dtype + if not dpnp.issubdtype(out_dtype, dpnp.bool): + raise TypeError( + f"Output array data type must be boolean, got {out.dtype}" + ) + + x_dtype = x.dtype + if dpnp.issubdtype(x_dtype, dpnp.complexfloating): raise TypeError( - f"This operation is not supported for {dtype} values " + f"This operation is not supported for {x_dtype} values " "because it would be ambiguous." - ) from e + ) + + is_inf = dpnp.isinf(x) + signbit = ~dpnp.signbit(x) - return dpnp.logical_and(is_inf, signbit, out) + return dpnp.logical_and(is_inf, signbit, out=out) _LESS_DOCSTRING = """ From 3fbe307248145647996780151091a0bc5f3c9c6a Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 17 Jun 2024 20:50:28 +0200 Subject: [PATCH 07/12] Add test_infinity_sign_errors --- tests/test_logic.py | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/tests/test_logic.py b/tests/test_logic.py index 10ea3708b0f..88315848c1e 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -7,6 +7,7 @@ from .helper import ( get_all_dtypes, get_float_complex_dtypes, + get_float_dtypes, ) @@ -407,18 +408,37 @@ def test_finite(op, data, dtype): "2D array", ], ) -@pytest.mark.parametrize("dtype", get_float_complex_dtypes()) +@pytest.mark.parametrize("dtype", get_float_dtypes()) def test_infinity_sign(func, data, dtype): x = dpnp.asarray(data, dtype=dtype) - if dpnp.issubdtype(dtype, dpnp.complexfloating): - with pytest.raises(TypeError): - dpnp_res = getattr(dpnp, func)(x) - else: - np_res = getattr(numpy, func)(x.asnumpy()) - dpnp_res = getattr(dpnp, func)(x) - assert_equal(dpnp_res, np_res) + np_res = getattr(numpy, func)(x.asnumpy()) + dpnp_res = getattr(dpnp, func)(x) + assert_equal(dpnp_res, np_res) - dp_out = dpnp.empty(np_res.shape, dtype=dpnp.bool) - dpnp_res = getattr(dpnp, func)(x, out=dp_out) - assert dp_out is dpnp_res - assert_equal(dpnp_res, np_res) + dp_out = dpnp.empty(np_res.shape, dtype=dpnp.bool) + dpnp_res = getattr(dpnp, func)(x, out=dp_out) + assert dp_out is dpnp_res + assert_equal(dpnp_res, np_res) + + +@pytest.mark.parametrize("func", ["isneginf", "isposinf"]) +def test_infinity_sign_errors(func): + data = [dpnp.inf, 0, -dpnp.inf] + + # unsupported data type + x = dpnp.asarray(data, dtype="c8") + x_np = dpnp.asnumpy(x) + with pytest.raises(TypeError): + getattr(dpnp, func)(x) + getattr(numpy, func)(x_np) + + # unsupported type + with pytest.raises(TypeError): + getattr(dpnp, func)(data) # list + getattr(dpnp, func)(x_np) # numpy array + + # unsupported `out` data type + x = dpnp.asarray(data, dtype=dpnp.default_float_type()) + out = dpnp.empty_like(x, dtype="int32") + with pytest.raises(TypeError): + getattr(dpnp, func)(x, out=out) From 24115537d731d1c0ca9b1a03950d17a55816fa7e Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 17 Jun 2024 20:51:35 +0200 Subject: [PATCH 08/12] Add sycl_queue/usm tests for logic functions --- tests/test_sycl_queue.py | 65 ++++++++++++++++++++++++++++++++++++++++ tests/test_usm_type.py | 33 +++++++++++++++++++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index 99334cfabfc..a778ec3f1a3 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -478,6 +478,15 @@ def test_meshgrid(device_x, device_y): pytest.param("trapz", [[0.0, 1.0, 2.0], [3.0, 4.0, 5.0]]), pytest.param("trunc", [-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]), pytest.param("var", [1.0, 2.0, 4.0, 7.0]), + # logic functions + pytest.param("all", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), + pytest.param("any", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), + pytest.param("isfinite", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), + pytest.param("isinf", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), + pytest.param("isnan", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), + pytest.param("isneginf", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), + pytest.param("isposinf", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), + pytest.param("logical_not", [-dpnp.inf, -1.0, 0.0, dpnp.inf, dpnp.nan]), ], ) @pytest.mark.parametrize( @@ -681,6 +690,62 @@ def test_reduce_hypot(device): pytest.param("vdot", [3.0, 4.0, 5.0], [1.0, 2.0, 3.0]), pytest.param("vdot", [3, 4, 5], [1, 2, 3]), pytest.param("vdot", [3 + 2j, 4 + 1j, 5], [1, 2 + 3j, 3]), + # logic functions + pytest.param( + "allclose", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], + ), + pytest.param( + "equal", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], + ), + pytest.param( + "greater", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf], + ), + pytest.param( + "greater_equal", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf], + ), + # TODO: unblock when dpnp.isclose() is updated + # pytest.param("isclose", + # [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], + # [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan] + # ), + pytest.param( + "less", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf], + ), + pytest.param( + "less_equal", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf], + ), + pytest.param( + "logical_and", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], + ), + pytest.param( + "logical_or", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], + ), + pytest.param( + "logical_xor", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], + ), + pytest.param( + "not_equal", + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], + ), ], ) @pytest.mark.parametrize( diff --git a/tests/test_usm_type.py b/tests/test_usm_type.py index 4f7314ff2db..55f252c216a 100644 --- a/tests/test_usm_type.py +++ b/tests/test_usm_type.py @@ -354,6 +354,37 @@ def test_tril_triu(func, usm_type): assert x.usm_type == usm_type +@pytest.mark.parametrize( + "op", + [ + "all", + "any", + "isfinite", + "isinf", + "isnan", + "isneginf", + "isposinf", + "logical_not", + ], + ids=[ + "all", + "any", + "isfinite", + "isinf", + "isnan", + "isneginf", + "isposinf", + "logical_not", + ], +) +@pytest.mark.parametrize("usm_type_x", list_of_usm_types, ids=list_of_usm_types) +def test_coerced_usm_types_logic_op_1in(op, usm_type_x): + x = dp.arange(-10, 10, usm_type=usm_type_x) + res = getattr(dp, op)(x) + + assert x.usm_type == res.usm_type == usm_type_x + + @pytest.mark.parametrize( "op", [ @@ -381,7 +412,7 @@ def test_tril_triu(func, usm_type): ) @pytest.mark.parametrize("usm_type_x", list_of_usm_types, ids=list_of_usm_types) @pytest.mark.parametrize("usm_type_y", list_of_usm_types, ids=list_of_usm_types) -def test_coerced_usm_types_logic_op(op, usm_type_x, usm_type_y): +def test_coerced_usm_types_logic_op_2in(op, usm_type_x, usm_type_y): x = dp.arange(100, usm_type=usm_type_x) y = dp.arange(100, usm_type=usm_type_y)[::-1] From 37eb8fd7d6b07f7a6f5138eb0f286abb7d9ac0d3 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Wed, 19 Jun 2024 15:30:54 +0200 Subject: [PATCH 09/12] Update tests --- tests/test_logic.py | 14 ++-- tests/test_sycl_queue.py | 147 ++++++++++++++++++++++----------------- tests/test_usm_type.py | 23 +----- 3 files changed, 90 insertions(+), 94 deletions(-) diff --git a/tests/test_logic.py b/tests/test_logic.py index 88315848c1e..f7a8e37f321 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -1,6 +1,6 @@ import numpy import pytest -from numpy.testing import assert_allclose, assert_equal +from numpy.testing import assert_allclose, assert_equal, assert_raises import dpnp @@ -428,17 +428,15 @@ def test_infinity_sign_errors(func): # unsupported data type x = dpnp.asarray(data, dtype="c8") x_np = dpnp.asnumpy(x) - with pytest.raises(TypeError): - getattr(dpnp, func)(x) - getattr(numpy, func)(x_np) + assert_raises(TypeError, getattr(dpnp, func), x) + assert_raises(TypeError, getattr(numpy, func), x_np) # unsupported type - with pytest.raises(TypeError): - getattr(dpnp, func)(data) # list - getattr(dpnp, func)(x_np) # numpy array + assert_raises(TypeError, getattr(dpnp, func), data) + assert_raises(TypeError, getattr(dpnp, func), x_np) # unsupported `out` data type x = dpnp.asarray(data, dtype=dpnp.default_float_type()) out = dpnp.empty_like(x, dtype="int32") - with pytest.raises(TypeError): + with pytest.raises(ValueError): getattr(dpnp, func)(x, out=out) diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index a778ec3f1a3..e88df40b688 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -478,15 +478,6 @@ def test_meshgrid(device_x, device_y): pytest.param("trapz", [[0.0, 1.0, 2.0], [3.0, 4.0, 5.0]]), pytest.param("trunc", [-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]), pytest.param("var", [1.0, 2.0, 4.0, 7.0]), - # logic functions - pytest.param("all", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), - pytest.param("any", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), - pytest.param("isfinite", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), - pytest.param("isinf", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), - pytest.param("isnan", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), - pytest.param("isneginf", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), - pytest.param("isposinf", [-dpnp.inf, -1.0, 1.0, dpnp.inf, dpnp.nan]), - pytest.param("logical_not", [-dpnp.inf, -1.0, 0.0, dpnp.inf, dpnp.nan]), ], ) @pytest.mark.parametrize( @@ -508,6 +499,40 @@ def test_1in_1out(func, data, device): assert_sycl_queue_equal(result_queue, expected_queue) +@pytest.mark.parametrize( + "op", + [ + "all", + "any", + "isfinite", + "isinf", + "isnan", + "isneginf", + "isposinf", + "logical_not", + ], +) +@pytest.mark.parametrize( + "device", + valid_devices, + ids=[device.filter_string for device in valid_devices], +) +def test_logic_op_1in(op, device): + x = dpnp.array( + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], device=device + ) + result = getattr(dpnp, op)(x) + + x_orig = dpnp.asnumpy(x) + expected = getattr(numpy, op)(x_orig) + assert_dtype_allclose(result, expected) + + expected_queue = x.get_array().sycl_queue + result_queue = result.get_array().sycl_queue + + assert_sycl_queue_equal(result_queue, expected_queue) + + @pytest.mark.parametrize( "device", valid_devices, @@ -690,62 +715,6 @@ def test_reduce_hypot(device): pytest.param("vdot", [3.0, 4.0, 5.0], [1.0, 2.0, 3.0]), pytest.param("vdot", [3, 4, 5], [1, 2, 3]), pytest.param("vdot", [3 + 2j, 4 + 1j, 5], [1, 2 + 3j, 3]), - # logic functions - pytest.param( - "allclose", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], - ), - pytest.param( - "equal", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], - ), - pytest.param( - "greater", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf], - ), - pytest.param( - "greater_equal", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf], - ), - # TODO: unblock when dpnp.isclose() is updated - # pytest.param("isclose", - # [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], - # [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan] - # ), - pytest.param( - "less", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf], - ), - pytest.param( - "less_equal", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf], - ), - pytest.param( - "logical_and", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], - ), - pytest.param( - "logical_or", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], - ), - pytest.param( - "logical_xor", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], - ), - pytest.param( - "not_equal", - [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], - [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], - ), ], ) @pytest.mark.parametrize( @@ -768,6 +737,54 @@ def test_2in_1out(func, data1, data2, device): assert_sycl_queue_equal(result.sycl_queue, x2.sycl_queue) +@pytest.mark.parametrize( + "op", + [ + "equal", + "greater", + "greater_equal", + # TODO: unblock when dpnp.isclose() is updated + # "isclose", + "less", + "less_equal", + "logical_and", + "logical_or", + "logical_xor", + "not_equal", + ], +) +@pytest.mark.parametrize( + "device", + valid_devices, + ids=[device.filter_string for device in valid_devices], +) +def test_logic_op_2in(op, device): + x1 = dpnp.array( + [-dpnp.inf, -1.0, 0.0, 1.0, dpnp.inf, dpnp.nan], device=device + ) + x2 = dpnp.array( + [dpnp.inf, 1.0, 0.0, -1.0, -dpnp.inf, dpnp.nan], device=device + ) + # Remove NaN value from input arrays because numpy raises RuntimeWarning + if op in [ + "greater", + "greater_equal", + "less", + "less_equal", + ]: + x1 = x1[:-1] + result = getattr(dpnp, op)(x1, x2) + + x1_orig = numpy.asnumpy(x1) + x2_orig = numpy.asnumpy(x2) + expected = getattr(numpy, op)(x1_orig, x2_orig) + + assert_dtype_allclose(result, expected) + + assert_sycl_queue_equal(result.sycl_queue, x1.sycl_queue) + assert_sycl_queue_equal(result.sycl_queue, x2.sycl_queue) + + @pytest.mark.parametrize( "func, data, scalar", [ diff --git a/tests/test_usm_type.py b/tests/test_usm_type.py index 55f252c216a..6d81c0848d5 100644 --- a/tests/test_usm_type.py +++ b/tests/test_usm_type.py @@ -366,16 +366,6 @@ def test_tril_triu(func, usm_type): "isposinf", "logical_not", ], - ids=[ - "all", - "any", - "isfinite", - "isinf", - "isnan", - "isneginf", - "isposinf", - "logical_not", - ], ) @pytest.mark.parametrize("usm_type_x", list_of_usm_types, ids=list_of_usm_types) def test_coerced_usm_types_logic_op_1in(op, usm_type_x): @@ -391,17 +381,8 @@ def test_coerced_usm_types_logic_op_1in(op, usm_type_x): "equal", "greater", "greater_equal", - "less", - "less_equal", - "logical_and", - "logical_or", - "logical_xor", - "not_equal", - ], - ids=[ - "equal", - "greater", - "greater_equal", + # TODO: unblock when dpnp.isclose() is updated + # "isclose", "less", "less_equal", "logical_and", From 510904f9d17b420d8a40ca206f8baa41bf6de74d Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Wed, 19 Jun 2024 15:32:05 +0200 Subject: [PATCH 10/12] Remove out dtype check --- dpnp/dpnp_iface_logic.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/dpnp/dpnp_iface_logic.py b/dpnp/dpnp_iface_logic.py index 5f36bfe44c6..1d316d1e8a5 100644 --- a/dpnp/dpnp_iface_logic.py +++ b/dpnp/dpnp_iface_logic.py @@ -769,11 +769,6 @@ def isneginf(x, out=None): if out is not None: dpnp.check_supported_arrays_type(out) - out_dtype = out.dtype - if not dpnp.issubdtype(out_dtype, dpnp.bool): - raise TypeError( - f"Output array data type must be boolean, got {out.dtype}" - ) x_dtype = x.dtype if dpnp.issubdtype(x_dtype, dpnp.complexfloating): @@ -845,11 +840,6 @@ def isposinf(x, out=None): if out is not None: dpnp.check_supported_arrays_type(out) - out_dtype = out.dtype - if not dpnp.issubdtype(out_dtype, dpnp.bool): - raise TypeError( - f"Output array data type must be boolean, got {out.dtype}" - ) x_dtype = x.dtype if dpnp.issubdtype(x_dtype, dpnp.complexfloating): From 580f35fc246a3a2b03dad65f6501d88e6af68e14 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Tue, 25 Jun 2024 12:04:02 +0200 Subject: [PATCH 11/12] Add TODO with support different out dtype --- dpnp/dpnp_iface_logic.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dpnp/dpnp_iface_logic.py b/dpnp/dpnp_iface_logic.py index 1d316d1e8a5..f359862842a 100644 --- a/dpnp/dpnp_iface_logic.py +++ b/dpnp/dpnp_iface_logic.py @@ -780,6 +780,7 @@ def isneginf(x, out=None): is_inf = dpnp.isinf(x) signbit = dpnp.signbit(x) + # TODO: support different out dtype #1717(dpctl) return dpnp.logical_and(is_inf, signbit, out=out) @@ -851,6 +852,7 @@ def isposinf(x, out=None): is_inf = dpnp.isinf(x) signbit = ~dpnp.signbit(x) + # TODO: support different out dtype #1717(dpctl) return dpnp.logical_and(is_inf, signbit, out=out) From 9164caf3b7b1c077e123c1ab65f088a7a03181d8 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Wed, 26 Jun 2024 18:18:31 +0200 Subject: [PATCH 12/12] Update test_logic_op_2in --- tests/test_sycl_queue.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index b2494e6b625..378ecaf9b19 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -775,10 +775,11 @@ def test_logic_op_2in(op, device): "less_equal", ]: x1 = x1[:-1] + x2 = x2[:-1] result = getattr(dpnp, op)(x1, x2) - x1_orig = numpy.asnumpy(x1) - x2_orig = numpy.asnumpy(x2) + x1_orig = dpnp.asnumpy(x1) + x2_orig = dpnp.asnumpy(x2) expected = getattr(numpy, op)(x1_orig, x2_orig) assert_dtype_allclose(result, expected)