Skip to content

Use tril() and triu() function from dpctl.tensor #1286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions dpnp/backend/include/dpnp_iface_fptr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
32 changes: 0 additions & 32 deletions dpnp/backend/kernels/dpnp_krnl_arraycreation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1055,17 +1055,6 @@ void (*dpnp_tril_default_c)(void*,
const size_t,
const size_t) = dpnp_tril_c<_DataType>;

template <typename _DataType>
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 <typename _DataType>
DPCTLSyclEventRef dpnp_triu_c(DPCTLSyclQueueRef q_ref,
void* array_in,
Expand Down Expand Up @@ -1218,17 +1207,6 @@ void (*dpnp_triu_default_c)(void*,
const size_t,
const size_t) = dpnp_triu_c<_DataType>;

template <typename _DataType>
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 <typename _DataType>
DPCTLSyclEventRef dpnp_zeros_c(DPCTLSyclQueueRef q_ref,
void* result,
Expand Down Expand Up @@ -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<float>};
fmap[DPNPFuncName::DPNP_FN_TRIL][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_tril_default_c<double>};

fmap[DPNPFuncName::DPNP_FN_TRIL_EXT][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_tril_ext_c<int32_t>};
fmap[DPNPFuncName::DPNP_FN_TRIL_EXT][eft_LNG][eft_LNG] = {eft_LNG, (void*)dpnp_tril_ext_c<int64_t>};
fmap[DPNPFuncName::DPNP_FN_TRIL_EXT][eft_FLT][eft_FLT] = {eft_FLT, (void*)dpnp_tril_ext_c<float>};
fmap[DPNPFuncName::DPNP_FN_TRIL_EXT][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_tril_ext_c<double>};

fmap[DPNPFuncName::DPNP_FN_TRIU][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_triu_default_c<int32_t>};
fmap[DPNPFuncName::DPNP_FN_TRIU][eft_LNG][eft_LNG] = {eft_LNG, (void*)dpnp_triu_default_c<int64_t>};
fmap[DPNPFuncName::DPNP_FN_TRIU][eft_FLT][eft_FLT] = {eft_FLT, (void*)dpnp_triu_default_c<float>};
fmap[DPNPFuncName::DPNP_FN_TRIU][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_triu_default_c<double>};

fmap[DPNPFuncName::DPNP_FN_TRIU_EXT][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_triu_ext_c<int32_t>};
fmap[DPNPFuncName::DPNP_FN_TRIU_EXT][eft_LNG][eft_LNG] = {eft_LNG, (void*)dpnp_triu_ext_c<int64_t>};
fmap[DPNPFuncName::DPNP_FN_TRIU_EXT][eft_FLT][eft_FLT] = {eft_FLT, (void*)dpnp_triu_ext_c<float>};
fmap[DPNPFuncName::DPNP_FN_TRIU_EXT][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_triu_ext_c<double>};

fmap[DPNPFuncName::DPNP_FN_ZEROS][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_zeros_default_c<int32_t>};
fmap[DPNPFuncName::DPNP_FN_ZEROS][eft_LNG][eft_LNG] = {eft_LNG, (void*)dpnp_zeros_default_c<int64_t>};
fmap[DPNPFuncName::DPNP_FN_ZEROS][eft_FLT][eft_FLT] = {eft_FLT, (void*)dpnp_zeros_default_c<float>};
Expand Down
90 changes: 0 additions & 90 deletions dpnp/dpnp_algo/dpnp_algo_arraycreation.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ __all__ += [
"dpnp_ptp",
"dpnp_trace",
"dpnp_tri",
"dpnp_tril",
"dpnp_triu",
"dpnp_vander",
]

Expand Down Expand Up @@ -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 = <c_dpctl.SyclQueue> result_sycl_queue
cdef c_dpctl.DPCTLSyclQueueRef q_ref = q.get_queue_ref()

cdef custom_1in_1out_func_ptr_t func = <custom_1in_1out_func_ptr_t > 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 = <c_dpctl.SyclQueue> result_sycl_queue
cdef c_dpctl.DPCTLSyclQueueRef q_ref = q.get_queue_ref()

cdef custom_1in_1out_func_ptr_t func = <custom_1in_1out_func_ptr_t > 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)
Expand Down
14 changes: 14 additions & 0 deletions dpnp/dpnp_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
"eye",
"full",
"ones"
"tril",
"triu",
"zeros",
]

Expand Down Expand Up @@ -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,
Expand Down
57 changes: 43 additions & 14 deletions dpnp/dpnp_iface_arraycreation.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import numpy
import dpnp
import operator

import dpnp.config as config
from dpnp.dpnp_algo import *
Expand Down Expand Up @@ -1332,14 +1333,20 @@ 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.

Return a copy of an array with elements above the `k`-th diagonal zeroed.

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
Expand All @@ -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.

Expand All @@ -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
Expand All @@ -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)

Expand Down
49 changes: 25 additions & 24 deletions tests/test_arraycreation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
)

import tempfile
import operator


@pytest.mark.parametrize("start",
Expand Down Expand Up @@ -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)


Expand All @@ -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)


Expand Down
Loading