diff --git a/dpnp/backend/include/dpnp_iface_fptr.hpp b/dpnp/backend/include/dpnp_iface_fptr.hpp index 61c1c9838ad6..70a2d860910b 100644 --- a/dpnp/backend/include/dpnp_iface_fptr.hpp +++ b/dpnp/backend/include/dpnp_iface_fptr.hpp @@ -370,9 +370,7 @@ enum class DPNPFuncName : size_t DPNP_FN_TRI, /**< Used in numpy.tri() impl */ DPNP_FN_TRI_EXT, /**< Used in numpy.tri() impl, requires extra parameters */ DPNP_FN_TRIL, /**< Used in numpy.tril() impl */ - DPNP_FN_TRIL_EXT, /**< Used in numpy.tril() impl, requires extra parameters */ DPNP_FN_TRIU, /**< Used in numpy.triu() impl */ - DPNP_FN_TRIU_EXT, /**< Used in numpy.triu() impl, requires extra parameters */ DPNP_FN_TRUNC, /**< Used in numpy.trunc() impl */ DPNP_FN_TRUNC_EXT, /**< Used in numpy.trunc() impl, requires extra parameters */ DPNP_FN_VANDER, /**< Used in numpy.vander() impl */ diff --git a/dpnp/backend/kernels/dpnp_krnl_arraycreation.cpp b/dpnp/backend/kernels/dpnp_krnl_arraycreation.cpp index 8727e37fafc2..a29fcca0975b 100644 --- a/dpnp/backend/kernels/dpnp_krnl_arraycreation.cpp +++ b/dpnp/backend/kernels/dpnp_krnl_arraycreation.cpp @@ -1055,17 +1055,6 @@ void (*dpnp_tril_default_c)(void*, const size_t, const size_t) = dpnp_tril_c<_DataType>; -template -DPCTLSyclEventRef (*dpnp_tril_ext_c)(DPCTLSyclQueueRef, - void*, - void*, - const int, - shape_elem_type*, - shape_elem_type*, - const size_t, - const size_t, - const DPCTLEventVectorRef) = dpnp_tril_c<_DataType>; - template DPCTLSyclEventRef dpnp_triu_c(DPCTLSyclQueueRef q_ref, void* array_in, @@ -1218,17 +1207,6 @@ void (*dpnp_triu_default_c)(void*, const size_t, const size_t) = dpnp_triu_c<_DataType>; -template -DPCTLSyclEventRef (*dpnp_triu_ext_c)(DPCTLSyclQueueRef, - void*, - void*, - const int, - shape_elem_type*, - shape_elem_type*, - const size_t, - const size_t, - const DPCTLEventVectorRef) = dpnp_triu_c<_DataType>; - template DPCTLSyclEventRef dpnp_zeros_c(DPCTLSyclQueueRef q_ref, void* result, @@ -1439,21 +1417,11 @@ void func_map_init_arraycreation(func_map_t& fmap) fmap[DPNPFuncName::DPNP_FN_TRIL][eft_FLT][eft_FLT] = {eft_FLT, (void*)dpnp_tril_default_c}; fmap[DPNPFuncName::DPNP_FN_TRIL][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_tril_default_c}; - fmap[DPNPFuncName::DPNP_FN_TRIL_EXT][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_tril_ext_c}; - fmap[DPNPFuncName::DPNP_FN_TRIL_EXT][eft_LNG][eft_LNG] = {eft_LNG, (void*)dpnp_tril_ext_c}; - fmap[DPNPFuncName::DPNP_FN_TRIL_EXT][eft_FLT][eft_FLT] = {eft_FLT, (void*)dpnp_tril_ext_c}; - fmap[DPNPFuncName::DPNP_FN_TRIL_EXT][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_tril_ext_c}; - fmap[DPNPFuncName::DPNP_FN_TRIU][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_triu_default_c}; fmap[DPNPFuncName::DPNP_FN_TRIU][eft_LNG][eft_LNG] = {eft_LNG, (void*)dpnp_triu_default_c}; fmap[DPNPFuncName::DPNP_FN_TRIU][eft_FLT][eft_FLT] = {eft_FLT, (void*)dpnp_triu_default_c}; fmap[DPNPFuncName::DPNP_FN_TRIU][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_triu_default_c}; - fmap[DPNPFuncName::DPNP_FN_TRIU_EXT][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_triu_ext_c}; - fmap[DPNPFuncName::DPNP_FN_TRIU_EXT][eft_LNG][eft_LNG] = {eft_LNG, (void*)dpnp_triu_ext_c}; - fmap[DPNPFuncName::DPNP_FN_TRIU_EXT][eft_FLT][eft_FLT] = {eft_FLT, (void*)dpnp_triu_ext_c}; - fmap[DPNPFuncName::DPNP_FN_TRIU_EXT][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_triu_ext_c}; - fmap[DPNPFuncName::DPNP_FN_ZEROS][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_zeros_default_c}; fmap[DPNPFuncName::DPNP_FN_ZEROS][eft_LNG][eft_LNG] = {eft_LNG, (void*)dpnp_zeros_default_c}; fmap[DPNPFuncName::DPNP_FN_ZEROS][eft_FLT][eft_FLT] = {eft_FLT, (void*)dpnp_zeros_default_c}; diff --git a/dpnp/dpnp_algo/dpnp_algo_arraycreation.pyx b/dpnp/dpnp_algo/dpnp_algo_arraycreation.pyx index 6986bf0ec702..cb44a08db598 100644 --- a/dpnp/dpnp_algo/dpnp_algo_arraycreation.pyx +++ b/dpnp/dpnp_algo/dpnp_algo_arraycreation.pyx @@ -45,8 +45,6 @@ __all__ += [ "dpnp_ptp", "dpnp_trace", "dpnp_tri", - "dpnp_tril", - "dpnp_triu", "dpnp_vander", ] @@ -426,94 +424,6 @@ cpdef utils.dpnp_descriptor dpnp_tri(N, M=None, k=0, dtype=dpnp.float): return result -cpdef utils.dpnp_descriptor dpnp_tril(utils.dpnp_descriptor m, int k): - cdef shape_type_c input_shape = m.shape - cdef shape_type_c result_shape - - if m.ndim == 1: - result_shape = (m.shape[0], m.shape[0]) - else: - result_shape = m.shape - - cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(m.dtype) - cdef DPNPFuncData kernel_data = get_dpnp_function_ptr(DPNP_FN_TRIL_EXT, param1_type, param1_type) - - m_obj = m.get_array() - - # ceate result array with type given by FPTR data - cdef utils.dpnp_descriptor result = utils.create_output_descriptor(result_shape, - kernel_data.return_type, - None, - device=m_obj.sycl_device, - usm_type=m_obj.usm_type, - sycl_queue=m_obj.sycl_queue) - - result_sycl_queue = result.get_array().sycl_queue - - cdef c_dpctl.SyclQueue q = result_sycl_queue - cdef c_dpctl.DPCTLSyclQueueRef q_ref = q.get_queue_ref() - - cdef custom_1in_1out_func_ptr_t func = kernel_data.ptr - cdef c_dpctl.DPCTLSyclEventRef event_ref = func(q_ref, - m.get_data(), - result.get_data(), - k, - input_shape.data(), - result_shape.data(), - m.ndim, - result.ndim, - NULL) # dep_events_ref - - with nogil: c_dpctl.DPCTLEvent_WaitAndThrow(event_ref) - c_dpctl.DPCTLEvent_Delete(event_ref) - - return result - - -cpdef utils.dpnp_descriptor dpnp_triu(utils.dpnp_descriptor m, int k): - cdef shape_type_c input_shape = m.shape - cdef shape_type_c result_shape - - if m.ndim == 1: - result_shape = (m.shape[0], m.shape[0]) - else: - result_shape = m.shape - - cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(m.dtype) - cdef DPNPFuncData kernel_data = get_dpnp_function_ptr(DPNP_FN_TRIU_EXT, param1_type, param1_type) - - m_obj = m.get_array() - - # ceate result array with type given by FPTR data - cdef utils.dpnp_descriptor result = utils.create_output_descriptor(result_shape, - kernel_data.return_type, - None, - device=m_obj.sycl_device, - usm_type=m_obj.usm_type, - sycl_queue=m_obj.sycl_queue) - - result_sycl_queue = result.get_array().sycl_queue - - cdef c_dpctl.SyclQueue q = result_sycl_queue - cdef c_dpctl.DPCTLSyclQueueRef q_ref = q.get_queue_ref() - - cdef custom_1in_1out_func_ptr_t func = kernel_data.ptr - cdef c_dpctl.DPCTLSyclEventRef event_ref = func(q_ref, - m.get_data(), - result.get_data(), - k, - input_shape.data(), - result_shape.data(), - m.ndim, - result.ndim, - NULL) # dep_events_ref - - with nogil: c_dpctl.DPCTLEvent_WaitAndThrow(event_ref) - c_dpctl.DPCTLEvent_Delete(event_ref) - - return result - - cpdef utils.dpnp_descriptor dpnp_vander(utils.dpnp_descriptor x1, int N, int increasing): cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(x1.dtype) cdef DPNPFuncData kernel_data = get_dpnp_function_ptr(DPNP_FN_VANDER_EXT, param1_type, DPNP_FT_NONE) diff --git a/dpnp/dpnp_container.py b/dpnp/dpnp_container.py index 7065e497652d..75e20f8a0cb6 100644 --- a/dpnp/dpnp_container.py +++ b/dpnp/dpnp_container.py @@ -48,6 +48,8 @@ "eye", "full", "ones" + "tril", + "triu", "zeros", ] @@ -200,6 +202,18 @@ def ones(shape, return dpnp_array(array_obj.shape, buffer=array_obj, order=order) +def tril(x1, /, *, k=0): + """"Creates `dpnp_array` as lower triangular part of an input array.""" + array_obj = dpt.tril(x1.get_array() if isinstance(x1, dpnp_array) else x1, k) + return dpnp_array(array_obj.shape, buffer=array_obj, order="K") + + +def triu(x1, /, *, k=0): + """"Creates `dpnp_array` as upper triangular part of an input array.""" + array_obj = dpt.triu(x1.get_array() if isinstance(x1, dpnp_array) else x1, k) + return dpnp_array(array_obj.shape, buffer=array_obj, order="K") + + def zeros(shape, *, dtype=None, diff --git a/dpnp/dpnp_iface_arraycreation.py b/dpnp/dpnp_iface_arraycreation.py index 1740b1d6001a..5b062a346b97 100644 --- a/dpnp/dpnp_iface_arraycreation.py +++ b/dpnp/dpnp_iface_arraycreation.py @@ -42,6 +42,7 @@ import numpy import dpnp +import operator import dpnp.config as config from dpnp.dpnp_algo import * @@ -1332,7 +1333,7 @@ def tri(N, M=None, k=0, dtype=dpnp.float, **kwargs): return call_origin(numpy.tri, N, M, k, dtype, **kwargs) -def tril(x1, k=0): +def tril(x1, /, *, k=0): """ Lower triangle of an array. @@ -1340,6 +1341,12 @@ def tril(x1, k=0): For full documentation refer to :obj:`numpy.tril`. + Limitations + ----------- + Parameter `x1` is supported as :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray` with two or more dimensions. + Parameter `k` is supported only of integer data type. + Otherwise the function will be executed sequentially on CPU. + Examples -------- >>> import dpnp as np @@ -1351,17 +1358,25 @@ def tril(x1, k=0): """ - x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False) - if x1_desc: - if not isinstance(k, int): - pass - else: - return dpnp_tril(x1_desc, k).get_pyobj() + _k = None + try: + _k = operator.index(k) + except TypeError: + pass + + if not isinstance(x1, (dpnp.ndarray, dpt.usm_ndarray)): + pass + elif x1.ndim < 2: + pass + elif _k is None: + pass + else: + return dpnp_container.tril(x1, k=_k) return call_origin(numpy.tril, x1, k) -def triu(x1, k=0): +def triu(x1, /, *, k=0): """ Upper triangle of an array. @@ -1370,6 +1385,12 @@ def triu(x1, k=0): For full documentation refer to :obj:`numpy.triu`. + Limitations + ----------- + Parameter `x1` is supported as :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray` with two or more dimensions. + Parameter `k` is supported only of integer data type. + Otherwise the function will be executed sequentially on CPU. + Examples -------- >>> import dpnp as np @@ -1381,12 +1402,20 @@ def triu(x1, k=0): """ - x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False) - if x1_desc: - if not isinstance(k, int): - pass - else: - return dpnp_triu(x1_desc, k).get_pyobj() + _k = None + try: + _k = operator.index(k) + except TypeError: + pass + + if not isinstance(x1, (dpnp.ndarray, dpt.usm_ndarray)): + pass + elif x1.ndim < 2: + pass + elif _k is None: + pass + else: + return dpnp_container.triu(x1, k=_k) return call_origin(numpy.triu, x1, k) diff --git a/tests/test_arraycreation.py b/tests/test_arraycreation.py index 833ea6109c3c..fe371dbece6b 100644 --- a/tests/test_arraycreation.py +++ b/tests/test_arraycreation.py @@ -15,6 +15,7 @@ ) import tempfile +import operator @pytest.mark.parametrize("start", @@ -258,48 +259,48 @@ def test_tri_default_dtype(): @pytest.mark.parametrize("k", - [-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6], - ids=['-6', '-5', '-4', '-3', '-2', '-1', '0', '1', '2', '3', '4', '5', '6']) + [-3, -2, -1, 0, 1, 2, 3, 4, 5, + numpy.array(1), dpnp.array(2), dpt.asarray(3)], + ids=['-3', '-2', '-1', '0', '1', '2', '3', '4', '5', + 'np.array(1)', 'dpnp.array(2)', 'dpt.asarray(3)']) @pytest.mark.parametrize("m", - [[0, 1, 2, 3, 4], - [1, 1, 1, 1, 1], - [[0, 0], [0, 0]], + [[[0, 0], [0, 0]], [[1, 2], [1, 2]], [[1, 2], [3, 4]], [[0, 1, 2], [3, 4, 5], [6, 7, 8]], [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]], - ids=['[0, 1, 2, 3, 4]', - '[1, 1, 1, 1, 1]', - '[[0, 0], [0, 0]]', + ids=['[[0, 0], [0, 0]]', '[[1, 2], [1, 2]]', '[[1, 2], [3, 4]]', '[[0, 1, 2], [3, 4, 5], [6, 7, 8]]', '[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]']) -def test_tril(m, k): - a = numpy.array(m) +@pytest.mark.parametrize("dtype", get_all_dtypes(no_float16=False)) +def test_tril(m, k, dtype): + a = numpy.array(m, dtype=dtype) ia = dpnp.array(a) - expected = numpy.tril(a, k) - result = dpnp.tril(ia, k) + expected = numpy.tril(a, k=operator.index(k)) + result = dpnp.tril(ia, k=k) assert_array_equal(expected, result) @pytest.mark.parametrize("k", - [-4, -3, -2, -1, 0, 1, 2, 3, 4], - ids=['-4', '-3', '-2', '-1', '0', '1', '2', '3', '4']) + [-3, -2, -1, 0, 1, 2, 3, 4, 5, + numpy.array(1), dpnp.array(2), dpt.asarray(3)], + ids=['-3', '-2', '-1', '0', '1', '2', '3', '4', '5', + 'np.array(1)', 'dpnp.array(2)', 'dpt.asarray(3)']) @pytest.mark.parametrize("m", - [[0, 1, 2, 3, 4], - [[1, 2], [3, 4]], + [[[1, 2], [3, 4]], [[0, 1, 2], [3, 4, 5], [6, 7, 8]], [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]], - ids=['[0, 1, 2, 3, 4]', - '[[1, 2], [3, 4]]', + ids=['[[1, 2], [3, 4]]', '[[0, 1, 2], [3, 4, 5], [6, 7, 8]]', '[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]']) -def test_triu(m, k): - a = numpy.array(m) +@pytest.mark.parametrize("dtype", get_all_dtypes(no_float16=False)) +def test_triu(m, k, dtype): + a = numpy.array(m, dtype=dtype) ia = dpnp.array(a) - expected = numpy.triu(a, k) - result = dpnp.triu(ia, k) + expected = numpy.triu(a, k=operator.index(k)) + result = dpnp.triu(ia, k=k) assert_array_equal(expected, result) @@ -309,8 +310,8 @@ def test_triu(m, k): def test_triu_size_null(k): a = numpy.ones(shape=(1, 2, 0)) ia = dpnp.array(a) - expected = numpy.triu(a, k) - result = dpnp.triu(ia, k) + expected = numpy.triu(a, k=k) + result = dpnp.triu(ia, k=k) assert_array_equal(expected, result) diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index bc42f70b3700..77967a46af09 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -161,6 +161,16 @@ def test_array_creation_like(func, kwargs, device_x, device_y): assert_sycl_queue_equal(y.sycl_queue, x.to_device(device_y).sycl_queue) +@pytest.mark.parametrize("func", ["tril", "triu"], ids=["tril", "triu"]) +@pytest.mark.parametrize("device", + valid_devices, + ids=[device.filter_string for device in valid_devices]) +def test_tril_triu(func, device): + x0 = dpnp.ones((3,3), device=device) + x = getattr(dpnp, func)(x0) + assert_sycl_queue_equal(x.sycl_queue, x0.sycl_queue) + + @pytest.mark.usefixtures("allow_fall_back_on_numpy") @pytest.mark.parametrize( "func,data", diff --git a/tests/test_usm_type.py b/tests/test_usm_type.py index 15b853b3bfa2..91831648813d 100644 --- a/tests/test_usm_type.py +++ b/tests/test_usm_type.py @@ -63,6 +63,16 @@ def test_array_creation(func, args, usm_type_x, usm_type_y): assert x.usm_type == usm_type_x assert y.usm_type == usm_type_y + +@pytest.mark.skip() +@pytest.mark.parametrize("func", ["tril", "triu"], ids=["tril", "triu"]) +@pytest.mark.parametrize("usm_type", list_of_usm_types, ids=list_of_usm_types) +def test_tril_triu(func, usm_type): + x0 = dp.ones((3,3), usm_type=usm_type) + x = getattr(dp, func)(x0) + assert x.usm_type == usm_type + + @pytest.mark.parametrize("op", ['equal', 'greater', 'greater_equal', 'less', 'less_equal', 'logical_and', 'logical_or', 'logical_xor', 'not_equal'], diff --git a/tests/third_party/cupy/creation_tests/test_matrix.py b/tests/third_party/cupy/creation_tests/test_matrix.py index a5471f213ebf..fe144cbc58c4 100644 --- a/tests/third_party/cupy/creation_tests/test_matrix.py +++ b/tests/third_party/cupy/creation_tests/test_matrix.py @@ -140,6 +140,7 @@ def test_tri_posi(self, xp, dtype): {'shape': (2, 3, 4)}, ) @testing.gpu +@pytest.mark.usefixtures("allow_fall_back_on_numpy") class TestTriLowerAndUpper(unittest.TestCase): @testing.for_all_dtypes(no_complex=True) @@ -148,7 +149,6 @@ def test_tril(self, xp, dtype): m = testing.shaped_arange(self.shape, xp, dtype) return xp.tril(m) - @pytest.mark.usefixtures("allow_fall_back_on_numpy") @testing.numpy_cupy_array_equal() def test_tril_array_like(self, xp): return xp.tril([[1, 2], [3, 4]]) @@ -157,13 +157,13 @@ def test_tril_array_like(self, xp): @testing.numpy_cupy_array_equal() def test_tril_nega(self, xp, dtype): m = testing.shaped_arange(self.shape, xp, dtype) - return xp.tril(m, -1) + return xp.tril(m, k=-1) @testing.for_all_dtypes(no_complex=True) @testing.numpy_cupy_array_equal() def test_tril_posi(self, xp, dtype): m = testing.shaped_arange(self.shape, xp, dtype) - return xp.tril(m, 1) + return xp.tril(m, k=1) @testing.for_all_dtypes(no_complex=True) @testing.numpy_cupy_array_equal() @@ -171,7 +171,6 @@ def test_triu(self, xp, dtype): m = testing.shaped_arange(self.shape, xp, dtype) return xp.triu(m) - @pytest.mark.usefixtures("allow_fall_back_on_numpy") @testing.numpy_cupy_array_equal() def test_triu_array_like(self, xp): return xp.triu([[1, 2], [3, 4]]) @@ -180,10 +179,10 @@ def test_triu_array_like(self, xp): @testing.numpy_cupy_array_equal() def test_triu_nega(self, xp, dtype): m = testing.shaped_arange(self.shape, xp, dtype) - return xp.triu(m, -1) + return xp.triu(m, k=-1) @testing.for_all_dtypes(no_complex=True) @testing.numpy_cupy_array_equal() def test_triu_posi(self, xp, dtype): m = testing.shaped_arange(self.shape, xp, dtype) - return xp.triu(m, 1) + return xp.triu(m, k=1)