diff --git a/pyopencl/array.py b/pyopencl/array.py index fe96f91efb67ada5cb0daf5a8305291b6b08fdd5..42dc569bb73255b17fbab43b9263ca6a3462f910 100644 --- a/pyopencl/array.py +++ b/pyopencl/array.py @@ -400,6 +400,7 @@ class Array(object): .. automethod :: __ior__ .. automethod :: __abs__ + .. automethod :: __invert__ .. UNDOC reverse() @@ -885,6 +886,14 @@ class Array(object): return elementwise.get_array_binop_kernel( out.context, op, out.dtype, a.dtype, b.dtype) + @staticmethod + @elwise_kernel_runner + def _unop(out, a, queue=None, op=None): + if out.shape != a.shape: + raise ValueError("shapes of arguments do not match") + return elementwise.get_unop_kernel( + out.context, op, a.dtype, out.dtype) + # }}} # {{{ operators @@ -1225,6 +1234,15 @@ class Array(object): self._rpow_scalar(result, common_dtype.type(other), self)) return result + def __invert__(self): + if not np.issubdtype(self.dtype, np.integer): + raise TypeError("Integral types only") + + result = self._new_like_me() + result.add_event(self._unop(result, self, op="~")) + + return result + # }}} def reverse(self, queue=None): diff --git a/pyopencl/elementwise.py b/pyopencl/elementwise.py index b373d2fc2640715075ff6623b6cefa1326275b8a..f7d68eb0f4f78ce044cd307f368c379ac5ba670e 100644 --- a/pyopencl/elementwise.py +++ b/pyopencl/elementwise.py @@ -823,6 +823,16 @@ def get_pow_kernel(context, dtype_x, dtype_y, dtype_z, name="pow_method") +@context_dependent_memoize +def get_unop_kernel(context, operator, res_dtype, in_dtype): + return get_elwise_kernel(context, [ + VectorArg(res_dtype, "z", with_offset=True), + VectorArg(in_dtype, "y", with_offset=True), + ], + "z[i] = %s y[i]" % operator, + name="unary_op_kernel") + + @context_dependent_memoize def get_array_scalar_binop_kernel(context, operator, dtype_res, dtype_a, dtype_b): return get_elwise_kernel(context, [ diff --git a/test/test_array.py b/test/test_array.py index fd9a76e504f552bee14b32a50cf0eb906d64cbc9..045deb26b12770b0da396d8da8bac3c957a867c7 100644 --- a/test/test_array.py +++ b/test/test_array.py @@ -477,31 +477,25 @@ def test_bitwise(ctx_factory): dtypes = [np.dtype(t) for t in (np.int64, np.int32, np.int16, np.int8)] + from pyopencl.clrandom import rand as clrand + for a_dtype, b_dtype in product(dtypes, dtypes): l = 16 np.random.seed(10) - a_dev = cl.array.to_device( - queue, - np.random.randint( - low=np.iinfo(a_dtype).min, - high=1+np.iinfo(a_dtype).max, - size=(l,), - dtype=a_dtype)) - b_dev = cl.array.to_device( - queue, - np.random.randint( - low=np.iinfo(b_dtype).min, - high=1+np.iinfo(b_dtype).max, - size=(l,), - dtype=b_dtype)) + int32_min = np.iinfo(np.int32).min + int32_max = np.iinfo(np.int32).max + + a_dev = clrand( + queue, (l,), a=int32_min, b=1+int32_max, dtype=np.int64).astype(a_dtype) + b_dev = clrand( + queue, (l,), a=int32_min, b=1+int32_max, dtype=np.int64).astype(b_dtype) a = a_dev.get() b = b_dev.get() - s = np.random.randint( - low=np.iinfo(b_dtype).min, - high=1+np.iinfo(b_dtype).max) + s = int((clrand(queue, (), a=int32_min, b=1+int32_max, dtype=np.int64) + .astype(b_dtype).get())) import operator as o @@ -536,6 +530,11 @@ def test_bitwise(ctx_factory): assert (res_dev.get() == res).all() + # Test unary ~ + res_dev = ~a_dev + res = ~a + assert (res_dev.get() == res).all() + # }}}