Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3ed8de2
Extend ufunc f/w to support binary funcs with two output arrays
antonwolfy Nov 19, 2025
a451607
Add dovmod implementation to ufunc extensions
antonwolfy Nov 19, 2025
1cae235
Add a function with SYCL kernel for divmod
antonwolfy Nov 19, 2025
6b62023
Add new DPNPBinaryTwoOutputsFunc class
antonwolfy Nov 19, 2025
d97c515
Add python implementation of divmod
antonwolfy Nov 19, 2025
0383fe9
Enabled muted umath tests
antonwolfy Nov 19, 2025
a533f1d
Add new test scope for binary ufuncs with two output arrays
antonwolfy Nov 19, 2025
09a80a8
Enable third party tests
antonwolfy Nov 19, 2025
5c59804
Add support of python built-in function divmod()
antonwolfy Nov 19, 2025
61141a4
Enable third party tests for elementwise operations
antonwolfy Nov 19, 2025
1940eb5
Remove unexsting keyword from docstring of DPNPBinaryTwoOutputsFunc c…
antonwolfy Dec 16, 2025
ac20a0e
Skip some tests for inplace operator due to numpy casting issue
antonwolfy Dec 16, 2025
7527d70
Adopt elementwise op tests to pass on a device without fp64 support
antonwolfy Dec 16, 2025
2bdba72
Suppress numpy overflow warning
antonwolfy Dec 16, 2025
0344c1a
Update test with ufunc signature to be passed on Windows
antonwolfy Dec 16, 2025
4db5d0e
Extend ufunc tests with binary ufunc divmod
antonwolfy Dec 16, 2025
24ed9bd
Add more tests to improve tests coverage for DPNPBinaryTwoOutputsFunc…
antonwolfy Dec 17, 2025
3c9e528
Add more tests with different input values to cover corner cases in c…
antonwolfy Dec 17, 2025
3d9ef40
Add CFD tests
antonwolfy Dec 17, 2025
abf3eaa
Update skip reason in third party test
antonwolfy Dec 17, 2025
7cfe338
Add testing of divmod operator
antonwolfy Dec 17, 2025
58b1a03
Render documentation for __rdivmod__ method
antonwolfy Dec 17, 2025
ffeba18
Add a link to python documentation of divmod function
antonwolfy Dec 17, 2025
7b0c529
Add PR to the changelog
antonwolfy Dec 17, 2025
a0df13d
Applied review comments
antonwolfy Dec 19, 2025
eaf4c1a
Add missing header
antonwolfy Dec 19, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ std::pair<sycl::event, sycl::event> py_binary_ufunc(
const dpctl::tensor::usm_ndarray &src2,
const dpctl::tensor::usm_ndarray &dst, // dst = op(src1, src2), elementwise
sycl::queue &exec_q,
const std::vector<sycl::event> depends,
const std::vector<sycl::event> &depends,
//
const output_typesT &output_type_table,
const contig_dispatchT &contig_dispatch_table,
Expand Down Expand Up @@ -870,7 +870,7 @@ std::pair<sycl::event, sycl::event>
const dpctl::tensor::usm_ndarray &dst1,
const dpctl::tensor::usm_ndarray &dst2,
sycl::queue &exec_q,
const std::vector<sycl::event> depends,
const std::vector<sycl::event> &depends,
//
const output_typesT &output_types_table,
const contig_dispatchT &contig_dispatch_table,
Expand Down Expand Up @@ -952,8 +952,10 @@ std::pair<sycl::event, sycl::event>
auto const &same_logical_tensors =
dpctl::tensor::overlap::SameLogicalTensors();
if ((overlap(src1, dst1) && !same_logical_tensors(src1, dst1)) ||
(overlap(src1, dst2) && !same_logical_tensors(src1, dst2)) ||
(overlap(src2, dst1) && !same_logical_tensors(src2, dst1)) ||
(overlap(dst1, dst2) && !same_logical_tensors(dst1, dst2)))
(overlap(src2, dst2) && !same_logical_tensors(src2, dst2)) ||
(overlap(dst1, dst2)))
{
throw py::value_error("Arrays index overlapping segments of memory");
}
Expand Down Expand Up @@ -1142,7 +1144,7 @@ std::pair<sycl::event, sycl::event>
py_binary_inplace_ufunc(const dpctl::tensor::usm_ndarray &lhs,
const dpctl::tensor::usm_ndarray &rhs,
sycl::queue &exec_q,
const std::vector<sycl::event> depends,
const std::vector<sycl::event> &depends,
//
const output_typesT &output_type_table,
const contig_dispatchT &contig_dispatch_table,
Expand Down
2 changes: 2 additions & 0 deletions dpnp/backend/kernels/elementwise_functions/divmod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#pragma once

#include <type_traits>

#include <sycl/sycl.hpp>

namespace dpnp::kernels::divmod
Expand Down
47 changes: 28 additions & 19 deletions dpnp/dpnp_algo/dpnp_elementwise_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ class DPNPBinaryFunc(BinaryElementwiseFunc):

Args:
name : {str}
Name of the unary function
Name of the binary function
result_type_resovle_fn : {callable}
Function that takes dtype of the input and returns the dtype of
the result if the implementation functions supports it, or
Expand All @@ -530,7 +530,7 @@ class DPNPBinaryFunc(BinaryElementwiseFunc):
corresponds to computational tasks associated with function
evaluation.
docs : {str}
Documentation string for the unary function.
Documentation string for the binary function.
mkl_fn_to_call : {None, str}
Check input arguments to answer if function from OneMKL VM library
can be used.
Expand Down Expand Up @@ -828,17 +828,17 @@ def __call__(self, *args, **kwargs):

class DPNPBinaryTwoOutputsFunc(BinaryElementwiseFunc):
"""
Class that implements unary element-wise functions with two output arrays.
Class that implements binary element-wise functions with two output arrays.

Parameters
----------
name : {str}
Name of the unary function
Name of the binary function
result_type_resolver_fn : {callable}
Function that takes dtype of the input and returns the dtype of
the result if the implementation functions supports it, or
returns `None` otherwise.
unary_dp_impl_fn : {callable}
binary_dp_impl_fn : {callable}
Data-parallel implementation function with signature
`impl_fn(src: usm_ndarray, dst: usm_ndarray,
sycl_queue: SyclQueue, depends: Optional[List[SyclEvent]])`
Expand All @@ -852,7 +852,7 @@ class DPNPBinaryTwoOutputsFunc(BinaryElementwiseFunc):
computational tasks complete execution, while the second event
corresponds to computational tasks associated with function evaluation.
docs : {str}
Documentation string for the unary function.
Documentation string for the binary function.

"""

Expand Down Expand Up @@ -1020,6 +1020,14 @@ def __call__(
if not res.flags.writable:
raise ValueError("output array is read-only")

for other_out in out[:i]:
if other_out is None:
continue

other_out = dpnp.get_usm_ndarray(other_out)
if dti._array_overlap(res, other_out):
raise ValueError("Output arrays cannot overlap")

if res.shape != res_shape:
raise ValueError(
"The shape of input and output arrays are inconsistent. "
Expand All @@ -1042,19 +1050,20 @@ def __call__(
# Allocate a temporary buffer with the required dtype
out[i] = dpt.empty_like(res, dtype=res_dt)
else:
for x, dt in zip([x1, x2], buf_dts):
if dpnp.isscalar(x):
pass
elif dt is not None:
pass
elif not dti._array_overlap(x, res):
pass
elif dti._same_logical_tensors(x, res):
pass

# Allocate a temporary buffer to avoid memory overlapping.
# Note if `dt` is not None, a temporary copy of `x` will be
# created, so the array overlap check isn't needed.
# If `dt` is not None, a temporary copy of `x` will be created,
# so the array overlap check isn't needed.
x_to_check = [
x
for x, dt in zip([x1, x2], buf_dts)
if not dpnp.isscalar(x) and dt is None
]

if any(
dti._array_overlap(x, res)
and not dti._same_logical_tensors(x, res)
for x in x_to_check
):
# allocate a temporary buffer to avoid memory overlapping
out[i] = dpt.empty_like(res)

x1 = dpnp.as_usm_ndarray(x1, dtype=x1_dt, sycl_queue=exec_q)
Expand Down
10 changes: 5 additions & 5 deletions dpnp/dpnp_iface_mathematical.py
Original file line number Diff line number Diff line change
Expand Up @@ -1581,19 +1581,19 @@ def diff(a, n=1, axis=-1, prepend=None, append=None):
Divisor input array, expected to have a real-valued floating-point data
type.
out1 : {None, dpnp.ndarray, usm_ndarray}, optional
Output array for the quotient to populate. Array must have the same shape
as `x` and the expected data type.
Output array for the quotient to populate. Array must have a shape that
the inputs broadcast to and the expected data type.

Default: ``None``.
out2 : {None, dpnp.ndarray, usm_ndarray}, optional
Output array for the remainder to populate. Array must have the same shape
as `x` and the expected data type.
Output array for the remainder to populate. Array must have a shape that
the inputs broadcast to and the expected data type.

Default: ``None``.
out : tuple of None, dpnp.ndarray, or usm_ndarray, optional
A location into which the result is stored. If provided, it must be a tuple
and have length equal to the number of outputs. Each provided array must
have the same shape as `x` and the expected data type.
have a shape that the inputs broadcast to and the expected data type.
It is prohibited to pass output arrays through `out` keyword when either
`out1` or `out2` is passed.

Expand Down
10 changes: 10 additions & 0 deletions dpnp/tests/test_binary_two_outputs_ufuncs.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@ def test_out1_overlap(self, func, dt):
_ = getattr(numpy, func)(a[size::], 1, a[::2])
assert_array_equal(ia, a)

def test_out_arrays_overlap(self, func):
a = dpnp.arange(7)
out = dpnp.zeros_like(a)

with pytest.raises(
ValueError,
match="Output arrays cannot overlap",
):
_ = getattr(dpnp, func)(a, 2, out=(out, out))

def test_out_scalar_input(self, func):
a = generate_random_numpy_array((3, 7), low=1, dtype=int)
out = numpy.zeros_like(a)
Expand Down
Loading