Skip to content

Commit 1a0231e

Browse files
committed
Added tests and fixed typo in logical_not
1 parent d3fc623 commit 1a0231e

File tree

6 files changed

+1061
-4
lines changed

6 files changed

+1061
-4
lines changed

dpctl/tensor/_elementwise_funcs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@
602602

603603
# U24: ==== LOGICAL_NOT (x)
604604
_logical_not_docstring = """
605-
log(x, out=None, order='K')
605+
logical_not(x, out=None, order='K')
606606
Computes the logical NOT for each element `x_i` of input array `x`.
607607
Args:
608608
x (usm_ndarray):

dpctl/tensor/libtensor/include/kernels/elementwise_functions/logical_not.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,8 @@ template <typename argT, typename resT> struct LogicalNotFunctor
5252
{
5353
static_assert(std::is_same_v<resT, bool>);
5454

55-
using is_constant = typename std::disjunction<std::is_same<argT, bool>,
56-
std::is_integral<argT>>;
57-
static constexpr resT constant_value = false;
55+
using is_constant = typename std::false_type;
56+
// constexpr resT constant_value = resT{};
5857
using supports_vec = typename std::false_type;
5958
using supports_sg_loadstore = typename std::negation<
6059
std::disjunction<tu_ns::is_complex<resT>, tu_ns::is_complex<argT>>>;
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
# Data Parallel Control (dpctl)
2+
#
3+
# Copyright 2023 Intel Corporation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless_equal required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
import ctypes
18+
19+
import numpy as np
20+
import pytest
21+
22+
import dpctl
23+
import dpctl.tensor as dpt
24+
from dpctl.tests.helper import get_queue_or_skip, skip_if_dtype_not_supported
25+
26+
from .utils import _all_dtypes, _compare_dtypes, _usm_types
27+
28+
29+
@pytest.mark.parametrize("op1_dtype", _all_dtypes)
30+
@pytest.mark.parametrize("op2_dtype", _all_dtypes)
31+
def test_logical_and_dtype_matrix(op1_dtype, op2_dtype):
32+
q = get_queue_or_skip()
33+
skip_if_dtype_not_supported(op1_dtype, q)
34+
skip_if_dtype_not_supported(op2_dtype, q)
35+
36+
sz = 127
37+
ar1 = dpt.asarray(np.random.randint(0, 2, sz), dtype=op1_dtype)
38+
ar2 = dpt.asarray(np.random.randint(0, 2, sz), dtype=op2_dtype)
39+
40+
r = dpt.logical_and(ar1, ar2)
41+
assert isinstance(r, dpt.usm_ndarray)
42+
43+
expected = np.logical_and(dpt.asnumpy(ar1), dpt.asnumpy(ar2))
44+
assert _compare_dtypes(r.dtype, expected.dtype, sycl_queue=q)
45+
assert r.shape == ar1.shape
46+
assert (dpt.asnumpy(r) == expected).all()
47+
assert r.sycl_queue == ar1.sycl_queue
48+
49+
r2 = dpt.empty_like(r, dtype=r.dtype)
50+
dpt.logical_and(ar1, ar2, out=r2)
51+
assert (dpt.asnumpy(r) == dpt.asnumpy(r2)).all()
52+
53+
ar3 = dpt.zeros(sz, dtype=op1_dtype)
54+
ar4 = dpt.ones(2 * sz, dtype=op2_dtype)
55+
56+
r = dpt.logical_and(ar3[::-1], ar4[::2])
57+
assert isinstance(r, dpt.usm_ndarray)
58+
expected = np.logical_and(
59+
np.zeros(1, dtype=op1_dtype), np.ones(1, dtype=op2_dtype)
60+
)
61+
assert _compare_dtypes(r.dtype, expected.dtype, sycl_queue=q)
62+
assert r.shape == ar3.shape
63+
assert (dpt.asnumpy(r) == expected).all()
64+
65+
r2 = dpt.empty_like(r, dtype=r.dtype)
66+
dpt.logical_and(ar3[::-1], ar4[::2], out=r2)
67+
assert (dpt.asnumpy(r) == dpt.asnumpy(r2)).all()
68+
69+
70+
@pytest.mark.parametrize("op_dtype", ["c8", "c16"])
71+
def test_logical_and_complex_matrix(op_dtype):
72+
q = get_queue_or_skip()
73+
skip_if_dtype_not_supported(op_dtype, q)
74+
75+
sz = 127
76+
ar1_np_real = np.random.randint(0, 2, sz)
77+
ar1_np_imag = np.random.randint(0, 2, sz)
78+
ar1 = dpt.asarray(ar1_np_real + 1j * ar1_np_imag, dtype=op_dtype)
79+
80+
ar2_np_real = np.random.randint(0, 2, sz)
81+
ar2_np_imag = np.random.randint(0, 2, sz)
82+
ar2 = dpt.asarray(ar2_np_real + 1j * ar2_np_imag, dtype=op_dtype)
83+
84+
r = dpt.logical_and(ar1, ar2)
85+
expected = np.logical_and(dpt.asnumpy(ar1), dpt.asnumpy(ar2))
86+
assert _compare_dtypes(r.dtype, expected.dtype, sycl_queue=q)
87+
assert r.shape == expected.shape
88+
assert (dpt.asnumpy(r) == expected).all()
89+
90+
r1 = dpt.logical_and(ar1[::-2], ar2[::2])
91+
expected1 = np.logical_and(dpt.asnumpy(ar1[::-2]), dpt.asnumpy(ar2[::2]))
92+
assert _compare_dtypes(r.dtype, expected1.dtype, sycl_queue=q)
93+
assert r1.shape == expected1.shape
94+
assert (dpt.asnumpy(r1) == expected1).all()
95+
96+
ar3 = dpt.asarray(
97+
[
98+
2.0 + 0j,
99+
dpt.nan,
100+
dpt.nan * 1j,
101+
dpt.inf,
102+
dpt.inf * 1j,
103+
-dpt.inf,
104+
-dpt.inf * 1j,
105+
],
106+
dtype=op_dtype,
107+
)
108+
ar4 = dpt.full(ar3.shape, fill_value=1.0 + 2j, dtype=op_dtype)
109+
r2 = dpt.logical_and(ar3, ar4)
110+
with np.errstate(invalid="ignore"):
111+
expected2 = np.logical_and(dpt.asnumpy(ar3), dpt.asnumpy(ar4))
112+
assert (dpt.asnumpy(r2) == expected2).all()
113+
114+
r3 = dpt.logical_and(ar4, ar4)
115+
with np.errstate(invalid="ignore"):
116+
expected3 = np.logical_and(dpt.asnumpy(ar4), dpt.asnumpy(ar4))
117+
assert (dpt.asnumpy(r3) == expected3).all()
118+
119+
120+
def test_logical_and_complex_float():
121+
get_queue_or_skip()
122+
123+
ar1 = dpt.asarray([1j, 1.0 + 9j, 2.0 + 0j, 2.0 + 1j], dtype="c8")
124+
ar2 = dpt.full(ar1.shape, 2, dtype="f4")
125+
126+
r = dpt.logical_and(ar1, ar2)
127+
expected = np.logical_and(dpt.asnumpy(ar1), dpt.asnumpy(ar2))
128+
assert (dpt.asnumpy(r) == expected).all()
129+
130+
r1 = dpt.logical_and(ar2, ar1)
131+
expected1 = np.logical_and(dpt.asnumpy(ar2), dpt.asnumpy(ar1))
132+
assert (dpt.asnumpy(r1) == expected1).all()
133+
with np.errstate(invalid="ignore"):
134+
for tp in [
135+
dpt.nan,
136+
dpt.nan * 1j,
137+
dpt.inf,
138+
dpt.inf * 1j,
139+
-dpt.inf,
140+
-dpt.inf * 1j,
141+
]:
142+
ar3 = dpt.full(ar1.shape, tp)
143+
r2 = dpt.logical_and(ar1, ar3)
144+
expected2 = np.logical_and(dpt.asnumpy(ar1), dpt.asnumpy(ar3))
145+
assert (dpt.asnumpy(r2) == expected2).all()
146+
147+
r3 = dpt.logical_and(ar3, ar1)
148+
expected3 = np.logical_and(dpt.asnumpy(ar3), dpt.asnumpy(ar1))
149+
assert (dpt.asnumpy(r3) == expected3).all()
150+
151+
152+
@pytest.mark.parametrize("op1_usm_type", _usm_types)
153+
@pytest.mark.parametrize("op2_usm_type", _usm_types)
154+
def test_logical_and_usm_type_matrix(op1_usm_type, op2_usm_type):
155+
get_queue_or_skip()
156+
157+
sz = 128
158+
ar1 = dpt.asarray(
159+
np.random.randint(0, 2, sz), dtype="i4", usm_type=op1_usm_type
160+
)
161+
ar2 = dpt.asarray(
162+
np.random.randint(0, 2, sz), dtype=ar1.dtype, usm_type=op2_usm_type
163+
)
164+
165+
r = dpt.logical_and(ar1, ar2)
166+
assert isinstance(r, dpt.usm_ndarray)
167+
expected_usm_type = dpctl.utils.get_coerced_usm_type(
168+
(op1_usm_type, op2_usm_type)
169+
)
170+
assert r.usm_type == expected_usm_type
171+
172+
173+
def test_logical_and_order():
174+
get_queue_or_skip()
175+
176+
ar1 = dpt.ones((20, 20), dtype="i4", order="C")
177+
ar2 = dpt.ones((20, 20), dtype="i4", order="C")
178+
r1 = dpt.logical_and(ar1, ar2, order="C")
179+
assert r1.flags.c_contiguous
180+
r2 = dpt.logical_and(ar1, ar2, order="F")
181+
assert r2.flags.f_contiguous
182+
r3 = dpt.logical_and(ar1, ar2, order="A")
183+
assert r3.flags.c_contiguous
184+
r4 = dpt.logical_and(ar1, ar2, order="K")
185+
assert r4.flags.c_contiguous
186+
187+
ar1 = dpt.ones((20, 20), dtype="i4", order="F")
188+
ar2 = dpt.ones((20, 20), dtype="i4", order="F")
189+
r1 = dpt.logical_and(ar1, ar2, order="C")
190+
assert r1.flags.c_contiguous
191+
r2 = dpt.logical_and(ar1, ar2, order="F")
192+
assert r2.flags.f_contiguous
193+
r3 = dpt.logical_and(ar1, ar2, order="A")
194+
assert r3.flags.f_contiguous
195+
r4 = dpt.logical_and(ar1, ar2, order="K")
196+
assert r4.flags.f_contiguous
197+
198+
ar1 = dpt.ones((40, 40), dtype="i4", order="C")[:20, ::-2]
199+
ar2 = dpt.ones((40, 40), dtype="i4", order="C")[:20, ::-2]
200+
r4 = dpt.logical_and(ar1, ar2, order="K")
201+
assert r4.strides == (20, -1)
202+
203+
ar1 = dpt.ones((40, 40), dtype="i4", order="C")[:20, ::-2].mT
204+
ar2 = dpt.ones((40, 40), dtype="i4", order="C")[:20, ::-2].mT
205+
r4 = dpt.logical_and(ar1, ar2, order="K")
206+
assert r4.strides == (-1, 20)
207+
208+
209+
def test_logical_and_broadcasting():
210+
get_queue_or_skip()
211+
212+
m = dpt.asarray(np.random.randint(0, 2, (100, 5)), dtype="i4")
213+
v = dpt.arange(1, 6, dtype="i4")
214+
215+
r = dpt.logical_and(m, v)
216+
217+
expected = np.logical_and(dpt.asnumpy(m), dpt.asnumpy(v))
218+
assert (dpt.asnumpy(r) == expected).all()
219+
220+
r2 = dpt.logical_and(v, m)
221+
expected2 = np.logical_and(dpt.asnumpy(v), dpt.asnumpy(m))
222+
assert (dpt.asnumpy(r2) == expected2).all()
223+
224+
r3 = dpt.empty_like(r)
225+
dpt.logical_and(m, v, out=r3)
226+
assert (dpt.asnumpy(r3) == expected).all()
227+
228+
r4 = dpt.empty_like(r)
229+
dpt.logical_and(v, m, out=r4)
230+
assert (dpt.asnumpy(r4) == expected).all()
231+
232+
233+
@pytest.mark.parametrize("arr_dt", _all_dtypes)
234+
@pytest.mark.parametrize("scalar_val", [0, 1])
235+
def test_logical_and_python_scalar(arr_dt, scalar_val):
236+
q = get_queue_or_skip()
237+
skip_if_dtype_not_supported(arr_dt, q)
238+
239+
X = dpt.asarray(
240+
np.random.randint(0, 2, (10, 10)), dtype=arr_dt, sycl_queue=q
241+
)
242+
py_ones = (
243+
bool(scalar_val),
244+
int(scalar_val),
245+
float(scalar_val),
246+
complex(scalar_val),
247+
np.float32(scalar_val),
248+
ctypes.c_int(scalar_val),
249+
)
250+
for sc in py_ones:
251+
R = dpt.logical_and(X, sc)
252+
assert isinstance(R, dpt.usm_ndarray)
253+
E = np.logical_and(dpt.asnumpy(X), sc)
254+
assert (dpt.asnumpy(R) == E).all()
255+
256+
R = dpt.logical_and(sc, X)
257+
assert isinstance(R, dpt.usm_ndarray)
258+
E = np.logical_and(sc, dpt.asnumpy(X))
259+
assert (dpt.asnumpy(R) == E).all()
260+
261+
262+
class MockArray:
263+
def __init__(self, arr):
264+
self.data_ = arr
265+
266+
@property
267+
def __sycl_usm_array_interface__(self):
268+
return self.data_.__sycl_usm_array_interface__
269+
270+
271+
def test_logical_and_mock_array():
272+
get_queue_or_skip()
273+
a = dpt.arange(10)
274+
b = dpt.ones(10)
275+
c = MockArray(b)
276+
r = dpt.logical_and(a, c)
277+
assert isinstance(r, dpt.usm_ndarray)
278+
279+
280+
def test_logical_and_canary_mock_array():
281+
get_queue_or_skip()
282+
a = dpt.arange(10)
283+
284+
class Canary:
285+
def __init__(self):
286+
pass
287+
288+
@property
289+
def __sycl_usm_array_interface__(self):
290+
return None
291+
292+
c = Canary()
293+
with pytest.raises(ValueError):
294+
dpt.logical_and(a, c)

0 commit comments

Comments
 (0)