From 25155e0550a156a3257b718db1efa550268ab8b0 Mon Sep 17 00:00:00 2001 From: Joseph Thomas Guman Date: Wed, 7 Feb 2024 15:15:54 -0800 Subject: [PATCH 1/4] Adding functionality for logical_and.reduce() with appropriate modifications in tests \n\n Joseph Guman --- cunumeric/_ufunc/comparison.py | 1 + cunumeric/_ufunc/ufunc.py | 7 +++++++ tests/integration/test_fallback.py | 4 ++-- tests/integration/test_logical_reduction.py | 20 ++++++++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/integration/test_logical_reduction.py diff --git a/cunumeric/_ufunc/comparison.py b/cunumeric/_ufunc/comparison.py index d1df4e8de..b6f5739a3 100644 --- a/cunumeric/_ufunc/comparison.py +++ b/cunumeric/_ufunc/comparison.py @@ -73,6 +73,7 @@ "logical_and", BinaryOpCode.LOGICAL_AND, relation_types_of(all_dtypes), + red_code=UnaryRedCode.PROD, ) logical_or = create_binary_ufunc( diff --git a/cunumeric/_ufunc/ufunc.py b/cunumeric/_ufunc/ufunc.py index 3bba6b8ad..7b6c4b84b 100644 --- a/cunumeric/_ufunc/ufunc.py +++ b/cunumeric/_ufunc/ufunc.py @@ -753,6 +753,13 @@ def reduce( f"reduction for {self} is not yet implemented" ) + if self._op_code in [ + BinaryOpCode.LOGICAL_AND, + BinaryOpCode.LOGICAL_OR, + BinaryOpCode.LOGICAL_XOR, + ]: + array = array._astype(bool, temporary=True) + # NumPy seems to be using None as the default axis value for scalars if array.ndim == 0 and axis == 0: axis = None diff --git a/tests/integration/test_fallback.py b/tests/integration/test_fallback.py index 4e312d0bb..e910fa706 100644 --- a/tests/integration/test_fallback.py +++ b/tests/integration/test_fallback.py @@ -28,8 +28,8 @@ def test_ufunc(): in_num = num.array([0, 1, 2, 3]) in_np = in_num.__array__() - out_num = np.logical_and.reduce(in_num) - out_np = np.logical_and.reduce(in_np) + out_num = np.logical_or.reduce(in_num) + out_np = np.logical_or.reduce(in_np) assert np.array_equal(out_num, out_np) diff --git a/tests/integration/test_logical_reduction.py b/tests/integration/test_logical_reduction.py new file mode 100644 index 000000000..9ba93a68e --- /dev/null +++ b/tests/integration/test_logical_reduction.py @@ -0,0 +1,20 @@ +import numpy as np +import pytest +from utils.comparisons import allclose + +import cunumeric as num + +def test_logical_and_reduce(): + input = [[[12,0,1,2],[9,0,0,1]],[[0,0,0,5],[1,1,1,1]]] + in_num = num.array(input) + in_np = np.array(input) + + axes = [None, 0, 1, 2, (0,1,2)] + for axis in axes: + out_num = num.logical_and.reduce(in_num, axis=axis) + out_np = np.logical_and.reduce(in_np, axis=axis) + assert(allclose(out_num, out_np, check_dtype=True)) + +if __name__ == "__main__": + import sys + sys.exit(pytest.main(sys.argv)) From a7ad064043f04161c48786f9ba77a5177977478e Mon Sep 17 00:00:00 2001 From: Joseph Thomas Guman Date: Wed, 7 Feb 2024 15:47:33 -0800 Subject: [PATCH 2/4] Minor style change to test for logical_and.reduce() \n\nSigned-off-by: Joseph Guman --- tests/integration/test_logical_reduction.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_logical_reduction.py b/tests/integration/test_logical_reduction.py index 9ba93a68e..3bcc75fd1 100644 --- a/tests/integration/test_logical_reduction.py +++ b/tests/integration/test_logical_reduction.py @@ -4,17 +4,20 @@ import cunumeric as num + def test_logical_and_reduce(): - input = [[[12,0,1,2],[9,0,0,1]],[[0,0,0,5],[1,1,1,1]]] + input = [[[12, 0, 1, 2], [9, 0, 0, 1]], [[0, 0, 0, 5], [1, 1, 1, 1]]] in_num = num.array(input) in_np = np.array(input) - axes = [None, 0, 1, 2, (0,1,2)] + axes = [None, 0, 1, 2, (0, 1, 2)] for axis in axes: out_num = num.logical_and.reduce(in_num, axis=axis) out_np = np.logical_and.reduce(in_np, axis=axis) - assert(allclose(out_num, out_np, check_dtype=True)) + assert allclose(out_num, out_np, check_dtype=True) + if __name__ == "__main__": import sys + sys.exit(pytest.main(sys.argv)) From 4c887fdc0115a64173d85e9825e970d53c4f0ea9 Mon Sep 17 00:00:00 2001 From: Joseph Thomas Guman Date: Tue, 13 Feb 2024 15:28:22 -0800 Subject: [PATCH 3/4] Style changes and adding logical_or.reduce() functionality with UnaryRedCode.ANY Signed-off-by: Joseph Guman --- cunumeric/_ufunc/comparison.py | 3 ++- cunumeric/_ufunc/ufunc.py | 8 ++++++-- tests/integration/test_fallback.py | 11 +++++++++-- tests/integration/test_logical_reduction.py | 16 +++++++++------- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/cunumeric/_ufunc/comparison.py b/cunumeric/_ufunc/comparison.py index b6f5739a3..726936166 100644 --- a/cunumeric/_ufunc/comparison.py +++ b/cunumeric/_ufunc/comparison.py @@ -73,7 +73,7 @@ "logical_and", BinaryOpCode.LOGICAL_AND, relation_types_of(all_dtypes), - red_code=UnaryRedCode.PROD, + red_code=UnaryRedCode.ALL, ) logical_or = create_binary_ufunc( @@ -81,6 +81,7 @@ "logical_or", BinaryOpCode.LOGICAL_OR, relation_types_of(all_dtypes), + red_code=UnaryRedCode.ANY, ) logical_xor = create_binary_ufunc( diff --git a/cunumeric/_ufunc/ufunc.py b/cunumeric/_ufunc/ufunc.py index 7b6c4b84b..011ef13d1 100644 --- a/cunumeric/_ufunc/ufunc.py +++ b/cunumeric/_ufunc/ufunc.py @@ -756,9 +756,12 @@ def reduce( if self._op_code in [ BinaryOpCode.LOGICAL_AND, BinaryOpCode.LOGICAL_OR, - BinaryOpCode.LOGICAL_XOR, ]: - array = array._astype(bool, temporary=True) + res_dtype = bool + if dtype is not None: + raise TypeError("Cannot set dtype on a logical reduction") + else: + res_dtype = None # NumPy seems to be using None as the default axis value for scalars if array.ndim == 0 and axis == 0: @@ -774,6 +777,7 @@ def reduce( keepdims=keepdims, initial=initial, where=where, + res_dtype=res_dtype, ) diff --git a/tests/integration/test_fallback.py b/tests/integration/test_fallback.py index e910fa706..545f1513d 100644 --- a/tests/integration/test_fallback.py +++ b/tests/integration/test_fallback.py @@ -28,8 +28,15 @@ def test_ufunc(): in_num = num.array([0, 1, 2, 3]) in_np = in_num.__array__() - out_num = np.logical_or.reduce(in_num) - out_np = np.logical_or.reduce(in_np) + # This test uses logical_xor.reduce because it is currently unimplemented, + # and we want to verify a behaviour of unimplemented ufunc methods. If + # logical_xor.reduce becomes implemented in the future, this assertion will + # start to fail, and a new (unimplemented) ufunc method should be found to + # replace it + assert not num.logical_and.accumulate._cunumeric.implemented + + out_num = np.logical_and.accumulate(in_num) + out_np = np.logical_and.accumulate(in_np) assert np.array_equal(out_num, out_np) diff --git a/tests/integration/test_logical_reduction.py b/tests/integration/test_logical_reduction.py index 3bcc75fd1..023c2526c 100644 --- a/tests/integration/test_logical_reduction.py +++ b/tests/integration/test_logical_reduction.py @@ -1,20 +1,22 @@ import numpy as np import pytest -from utils.comparisons import allclose import cunumeric as num -def test_logical_and_reduce(): +@pytest.mark.parametrize("axis", [None, 0, 1, 2, (0, 1, 2)]) +def test_logical_reductions(axis): input = [[[12, 0, 1, 2], [9, 0, 0, 1]], [[0, 0, 0, 5], [1, 1, 1, 1]]] in_num = num.array(input) in_np = np.array(input) - axes = [None, 0, 1, 2, (0, 1, 2)] - for axis in axes: - out_num = num.logical_and.reduce(in_num, axis=axis) - out_np = np.logical_and.reduce(in_np, axis=axis) - assert allclose(out_num, out_np, check_dtype=True) + out_num = num.logical_and.reduce(in_num, axis=axis) + out_np = np.logical_and.reduce(in_np, axis=axis) + assert num.array_equal(out_num, out_np) + + out_num = num.logical_or.reduce(in_num, axis=axis) + out_np = np.logical_or.reduce(in_np, axis=axis) + assert num.array_equal(out_num, out_np) if __name__ == "__main__": From 03e52a7c140e664e4f7df1aac82def5a82bc1d63 Mon Sep 17 00:00:00 2001 From: Manolis Papadakis Date: Fri, 8 Mar 2024 17:14:32 -0800 Subject: [PATCH 4/4] Minor fixes --- tests/integration/test_fallback.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/integration/test_fallback.py b/tests/integration/test_fallback.py index 545f1513d..3d93f5e91 100644 --- a/tests/integration/test_fallback.py +++ b/tests/integration/test_fallback.py @@ -28,14 +28,14 @@ def test_ufunc(): in_num = num.array([0, 1, 2, 3]) in_np = in_num.__array__() - # This test uses logical_xor.reduce because it is currently unimplemented, - # and we want to verify a behaviour of unimplemented ufunc methods. If - # logical_xor.reduce becomes implemented in the future, this assertion will - # start to fail, and a new (unimplemented) ufunc method should be found to - # replace it + # This test uses logical_and.accumulate because it is currently + # unimplemented, and we want to verify a behaviour of unimplemented ufunc + # methods. If logical_and.accumulate becomes implemented in the future, + # this assertion will start to fail, and a new (unimplemented) ufunc method + # should be found to replace it assert not num.logical_and.accumulate._cunumeric.implemented - out_num = np.logical_and.accumulate(in_num) + out_num = num.logical_and.accumulate(in_num) out_np = np.logical_and.accumulate(in_np) assert np.array_equal(out_num, out_np)