Skip to content

Commit d17d7df

Browse files
committed
Add more tests to improve tests coverage for DPNPBinaryTwoOutputsFunc class
1 parent 0e8deed commit d17d7df

File tree

4 files changed

+142
-9
lines changed

4 files changed

+142
-9
lines changed

dpnp/dpnp_algo/dpnp_elementwise_common.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,30 @@ def nout(self):
304304
"""Returns the number of arguments treated as outputs."""
305305
return 2
306306

307+
@property
308+
def types(self):
309+
"""
310+
Returns information about types supported by implementation function,
311+
using NumPy's character encoding for data type.
312+
313+
Examples
314+
--------
315+
>>> import dpnp as np
316+
>>> np.frexp.types
317+
['e->ei', 'f->fi', 'd->di']
318+
319+
"""
320+
321+
types = self.types_
322+
if not types:
323+
types = []
324+
for dt1 in dtu._all_data_types(True, True):
325+
dt2 = self.result_type_resolver_fn_(dt1)
326+
if all(dt for dt in dt2):
327+
types.append(f"{dt1.char}->{dt2[0].char}{dt2[1].char}")
328+
self.types_ = types
329+
return types
330+
307331
def __call__(
308332
self,
309333
x,
@@ -852,6 +876,35 @@ def nout(self):
852876
"""Returns the number of arguments treated as outputs."""
853877
return 2
854878

879+
@property
880+
def types(self):
881+
"""
882+
Returns information about types supported by implementation function,
883+
using NumPy's character encoding for data types, e.g.
884+
885+
Examples
886+
--------
887+
>>> import dpnp as np
888+
>>> np.divmod.types
889+
['bb->bb', 'BB->BB', 'hh->hh', 'HH->HH', 'ii->ii', 'II->II',
890+
'll->ll', 'LL->LL', 'ee->ee', 'ff->ff', 'dd->dd']
891+
892+
"""
893+
894+
types = self.types_
895+
if not types:
896+
types = []
897+
_all_dtypes = dtu._all_data_types(True, True)
898+
for dt1 in _all_dtypes:
899+
for dt2 in _all_dtypes:
900+
dt3 = self.result_type_resolver_fn_(dt1, dt2)
901+
if all(dt for dt in dt3):
902+
types.append(
903+
f"{dt1.char}{dt2.char}->{dt3[0].char}{dt3[1].char}"
904+
)
905+
self.types_ = types
906+
return types
907+
855908
def __call__(
856909
self,
857910
x1,
@@ -916,7 +969,9 @@ def __call__(
916969
sycl_dev = exec_q.sycl_device
917970
x1_dt = _get_dtype(x1, sycl_dev)
918971
x2_dt = _get_dtype(x2, sycl_dev)
919-
if not all(_validate_dtype(dt) for dt in [x1_dt, x2_dt]):
972+
if not all(
973+
_validate_dtype(dt) for dt in [x1_dt, x2_dt]
974+
): # pragma: no cover
920975
raise ValueError("Operands have unsupported data types")
921976

922977
x1_dt, x2_dt = self.get_array_dtype_scalar_type_resolver_function()(
@@ -1001,7 +1056,6 @@ def __call__(
10011056
# Note if `dt` is not None, a temporary copy of `x` will be
10021057
# created, so the array overlap check isn't needed.
10031058
out[i] = dpt.empty_like(res)
1004-
break
10051059

10061060
x1 = dpnp.as_usm_ndarray(x1, dtype=x1_dt, sycl_queue=exec_q)
10071061
x2 = dpnp.as_usm_ndarray(x2, dtype=x2_dt, sycl_queue=exec_q)

dpnp/tests/helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def generate_random_numpy_array(
188188
numpy.random.seed(seed_value)
189189

190190
if numpy.issubdtype(dtype, numpy.unsignedinteger):
191-
low = 0
191+
low = max(low, 0)
192192

193193
# dtype=int is needed for 0d arrays
194194
size = numpy.prod(shape, dtype=int)

dpnp/tests/test_binary_two_outputs_ufuncs.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,42 @@ def test_out1_overlap(self, func, dt):
217217
_ = getattr(numpy, func)(a[size::], 1, a[::2])
218218
assert_array_equal(ia, a)
219219

220+
def test_out_scalar_input(self, func):
221+
a = generate_random_numpy_array((3, 7), low=1, dtype=int)
222+
out = numpy.zeros_like(a)
223+
ia, iout = dpnp.array(a), dpnp.array(out)
224+
225+
res1, res2 = getattr(dpnp, func)(ia, 3, out=(None, iout))
226+
exp1, exp2 = getattr(numpy, func)(a, 3, out=(None, out))
227+
assert_array_equal(res1, exp1)
228+
assert_array_equal(res2, exp2)
229+
assert res2 is iout
230+
231+
res1, res2 = getattr(dpnp, func)(7, ia, iout)
232+
exp1, exp2 = getattr(numpy, func)(7, a, out)
233+
assert_array_equal(res1, exp1)
234+
assert_array_equal(res2, exp2)
235+
assert res1 is iout
236+
237+
def test_out_same_logical_tensor(self, func):
238+
a = generate_random_numpy_array(8, low=1, dtype=int)
239+
ia = dpnp.array(a)
240+
241+
res1, res2 = getattr(dpnp, func)(ia, 3, out=(None, ia))
242+
exp1, exp2 = getattr(numpy, func)(a, 3, out=(None, a))
243+
assert_array_equal(res1, exp1)
244+
assert_array_equal(res2, exp2)
245+
assert res2 is ia
246+
247+
a = generate_random_numpy_array(8, low=1, dtype=int)
248+
ia = dpnp.array(a)
249+
250+
res1, res2 = getattr(dpnp, func)(7, ia, ia)
251+
exp1, exp2 = getattr(numpy, func)(7, a, a)
252+
assert_array_equal(res1, exp1)
253+
assert_array_equal(res2, exp2)
254+
assert res1 is ia
255+
220256
@pytest.mark.parametrize("dt", ALL_FLOAT_DTYPES)
221257
def test_empty(self, func, dt):
222258
a = numpy.empty(0, dtype=dt)
@@ -236,6 +272,35 @@ def test_complex_dtype(self, func, xp, dt):
236272
with pytest.raises((TypeError, ValueError)):
237273
_ = getattr(xp, func)(a, 7)
238274

275+
def test_f_contiguous_input(self, func):
276+
a = generate_random_numpy_array((3, 7), low=1, dtype="i2", order="F")
277+
b = generate_random_numpy_array((3, 7), low=1, dtype="u2", order="F")
278+
ia, ib = dpnp.array(a), dpnp.array(b)
279+
280+
res1, res2 = getattr(dpnp, func)(ia, ib)
281+
exp1, exp2 = getattr(numpy, func)(a, b)
282+
assert_array_equal(res1, exp1)
283+
assert_array_equal(res2, exp2)
284+
285+
out = numpy.zeros_like(a)
286+
iout = dpnp.array(out)
287+
288+
res1, res2 = getattr(dpnp, func)(ia, ib, iout)
289+
exp1, exp2 = getattr(numpy, func)(a, b, out)
290+
assert_array_equal(res1, exp1)
291+
assert_array_equal(res2, exp2)
292+
assert res1 is iout
293+
294+
@pytest.mark.parametrize("xp", [numpy, dpnp])
295+
def test_broadcast_error(self, func, xp):
296+
a = xp.arange(10).reshape((2, 5))
297+
b = xp.ones(2)
298+
with pytest.raises(
299+
ValueError,
300+
match="operands could not be broadcast together with shapes",
301+
):
302+
_ = getattr(xp, func)(a, b)
303+
239304

240305
class TestDivmod:
241306
@pytest.mark.usefixtures("suppress_divide_numpy_warnings")

dpnp/tests/test_mathematical.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,8 +2127,9 @@ def test_unary_two_outs_cfd_error(self, func):
21272127

21282128
@pytest.mark.parametrize("func", ["abs", "frexp", "add", "divmod"])
21292129
@pytest.mark.parametrize("order", [None, "K", "A", "f", "c"])
2130-
def test_order(self, func, order):
2131-
a = numpy.array([1, 2, 3])
2130+
@pytest.mark.parametrize("in_order", ["C", "F"])
2131+
def test_order(self, func, order, in_order):
2132+
a = numpy.arange(1, 7).reshape((2, 3), order=in_order)
21322133
ia = dpnp.array(a)
21332134

21342135
fn = getattr(numpy, func)
@@ -2140,10 +2141,23 @@ def test_order(self, func, order):
21402141
result = ifn(*iargs, order=order)
21412142
expected = fn(*args, order=order)
21422143
if fn.nout == 1:
2143-
assert_dtype_allclose(result, expected)
2144-
else:
2145-
for i in range(fn.nout):
2146-
assert_dtype_allclose(result[i], expected[i])
2144+
result = (result,)
2145+
expected = (expected,)
2146+
2147+
for i in range(fn.nout):
2148+
assert_dtype_allclose(result[i], expected[i])
2149+
assert (
2150+
result[i].flags.c_contiguous == expected[i].flags.c_contiguous
2151+
)
2152+
assert (
2153+
result[i].flags.f_contiguous == expected[i].flags.f_contiguous
2154+
)
2155+
2156+
@pytest.mark.parametrize("func", ["abs", "frexp", "add", "divmod"])
2157+
def test_types(self, func):
2158+
types = getattr(dpnp, func).types
2159+
assert isinstance(types, list)
2160+
assert len(types) > 0
21472161

21482162

21492163
class TestUnwrap:

0 commit comments

Comments
 (0)