Skip to content

Implements dpctl.tensor.any and dpctl.tensor.all #1204

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 9 commits into from
May 16, 2023
1 change: 1 addition & 0 deletions dpctl/tensor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pybind11_add_module(${python_module_name} MODULE
${CMAKE_CURRENT_SOURCE_DIR}/libtensor/source/full_ctor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libtensor/source/triul_ctor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libtensor/source/where.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libtensor/source/boolean_reductions.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libtensor/source/device_support_queries.cpp
)
target_compile_options(${python_module_name} PRIVATE -fno-sycl-id-queries-fit-in-int)
Expand Down
3 changes: 3 additions & 0 deletions dpctl/tensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
from dpctl.tensor._reshape import reshape
from dpctl.tensor._search_functions import where
from dpctl.tensor._usmarray import usm_ndarray
from dpctl.tensor._utility_functions import all, any

from ._constants import e, inf, nan, newaxis, pi

Expand Down Expand Up @@ -130,6 +131,8 @@
"tril",
"triu",
"where",
"all",
"any",
"dtype",
"isdtype",
"bool",
Expand Down
125 changes: 125 additions & 0 deletions dpctl/tensor/_utility_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
from numpy.core.numeric import normalize_axis_tuple

import dpctl
import dpctl.tensor as dpt
import dpctl.tensor._tensor_impl as ti


def _boolean_reduction(x, axis, keepdims, func):
if not isinstance(x, dpt.usm_ndarray):
raise TypeError(f"Expected dpctl.tensor.usm_ndarray, got {type(x)}")

nd = x.ndim
if axis is None:
red_nd = nd
# case of a scalar
if red_nd == 0:
return dpt.astype(x, dpt.bool)
x_tmp = x
res_shape = tuple()
perm = list(range(nd))
else:
if not isinstance(axis, (tuple, list)):
axis = (axis,)
axis = normalize_axis_tuple(axis, nd, "axis")

red_nd = len(axis)
# check for axis=()
if red_nd == 0:
return dpt.astype(x, dpt.bool)
perm = [i for i in range(nd) if i not in axis] + list(axis)
x_tmp = dpt.permute_dims(x, perm)
res_shape = x_tmp.shape[: nd - red_nd]

exec_q = x.sycl_queue
res_usm_type = x.usm_type

wait_list = []
res_tmp = dpt.empty(
res_shape,
dtype=dpt.int32,
usm_type=res_usm_type,
sycl_queue=exec_q,
)
hev0, ev0 = func(
src=x_tmp,
trailing_dims_to_reduce=red_nd,
dst=res_tmp,
sycl_queue=exec_q,
)
wait_list.append(hev0)

# copy to boolean result array
res = dpt.empty(
res_shape,
dtype=dpt.bool,
usm_type=res_usm_type,
sycl_queue=exec_q,
)
hev1, _ = ti._copy_usm_ndarray_into_usm_ndarray(
src=res_tmp, dst=res, sycl_queue=exec_q, depends=[ev0]
)
wait_list.append(hev1)

if keepdims:
res_shape = res_shape + (1,) * red_nd
inv_perm = sorted(range(nd), key=lambda d: perm[d])
res = dpt.permute_dims(dpt.reshape(res, res_shape), inv_perm)
dpctl.SyclEvent.wait_for(wait_list)
return res


def all(x, axis=None, keepdims=False):
"""all(x, axis=None, keepdims=False)

Tests whether all input array elements evaluate to True along a given axis.

Args:
x (usm_ndarray): Input array.
axis (Optional[Union[int, Tuple[int,...]]]): Axis (or axes)
along which to perform a logical AND reduction.
When `axis` is `None`, a logical AND reduction
is performed over all dimensions of `x`.
If `axis` is negative, the axis is counted from
the last dimension to the first.
Default: `None`.
keepdims (bool, optional): If `True`, the reduced axes are included
in the result as singleton dimensions, and the result is
broadcastable to the input array shape.
If `False`, the reduced axes are not included in the result.
Default: `False`.

Returns:
usm_ndarray:
An array with a data type of `bool`
containing the results of the logical AND reduction.
"""
return _boolean_reduction(x, axis, keepdims, ti._all)


def any(x, axis=None, keepdims=False):
"""any(x, axis=None, keepdims=False)

Tests whether any input array elements evaluate to True along a given axis.

Args:
x (usm_ndarray): Input array.
axis (Optional[Union[int, Tuple[int,...]]]): Axis (or axes)
along which to perform a logical OR reduction.
When `axis` is `None`, a logical OR reduction
is performed over all dimensions of `x`.
If `axis` is negative, the axis is counted from
the last dimension to the first.
Default: `None`.
keepdims (bool, optional): If `True`, the reduced axes are included
in the result as singleton dimensions, and the result is
broadcastable to the input array shape.
If `False`, the reduced axes are not included in the result.
Default: `False`.

Returns:
usm_ndarray:
An array with a data type of `bool`
containing the results of the logical OR reduction.
"""
return _boolean_reduction(x, axis, keepdims, ti._any)
Loading