diff --git a/loopy/target/opencl.py b/loopy/target/opencl.py index 39e4844116f10e7527f35ea34b3aaa5027a20e93..1e558e99b0fd8c73dd8b2ac34b2de8711cb2108c 100644 --- a/loopy/target/opencl.py +++ b/loopy/target/opencl.py @@ -189,51 +189,53 @@ class OpenCLCallable(ScalarCallable): def with_types(self, arg_id_to_dtype, callables_table): name = self.name - # unary functions - if name in ["fabs", "acos", "asin", "atan", "cos", "cosh", "sin", "sinh", - "tan", "tanh", "exp", "log", "log10", "sqrt", "ceil", "floor", - "erf", "erfc"]: - + # {{{ unary functions + if name == "abs": for id in arg_id_to_dtype: if not -1 <= id <= 0: raise LoopyError(f"'{name}' can take only one argument.") if 0 not in arg_id_to_dtype or arg_id_to_dtype[0] is None: - # the types provided aren't mature enough to specialize the - # callable return ( self.copy(arg_id_to_dtype=arg_id_to_dtype), callables_table) - dtype = arg_id_to_dtype[0] - dtype = dtype.numpy_dtype + dtype = arg_id_to_dtype[0].numpy_dtype if dtype.kind in ("u", "i"): - # ints and unsigned casted to float32 - dtype = np.float32 - elif dtype.kind == "c": - raise LoopyTypeError(f"{name} does not support type {dtype}") + # OpenCL C 2.2, Section 6.13.3: abs returns *u*gentype + from loopy.types import to_unsigned_dtype + return (self.copy(name_in_target=name, + arg_id_to_dtype={ + 0: NumpyType(dtype), + -1: NumpyType(to_unsigned_dtype(dtype))}), + callables_table) + elif dtype.kind == "f": + name = "fabs" + else: + raise LoopyTypeError(f"'{name}' does not support type {dtype}") + + # deliberately not elif: abs branch above may end up taking this. + if name in ["fabs", "acos", "asin", "atan", "cos", "cosh", "sin", "sinh", + "tan", "tanh", "exp", "log", "log10", "sqrt", "ceil", "floor", + "erf", "erfc"]: - return ( - self.copy(name_in_target=name, - arg_id_to_dtype={0: NumpyType(dtype), -1: - NumpyType(dtype)}), - callables_table) - elif name == "abs": for id in arg_id_to_dtype: if not -1 <= id <= 0: raise LoopyError(f"'{name}' can take only one argument.") if 0 not in arg_id_to_dtype or arg_id_to_dtype[0] is None: - # the types provided aren't mature enough to specialize the - # callable return ( self.copy(arg_id_to_dtype=arg_id_to_dtype), callables_table) - dtype = arg_id_to_dtype[0].numpy_dtype + dtype = arg_id_to_dtype[0] + dtype = dtype.numpy_dtype - if dtype.kind not in ("u", "i"): + if dtype.kind in ("u", "i"): + # ints and unsigned casted to float32 + dtype = np.float32 + elif dtype.kind == "c": raise LoopyTypeError(f"{name} does not support type {dtype}") return ( @@ -241,6 +243,9 @@ class OpenCLCallable(ScalarCallable): arg_id_to_dtype={0: NumpyType(dtype), -1: NumpyType(dtype)}), callables_table) + + # }}} + # binary functions elif name in ["fmax", "fmin", "atan2", "copysign"]: @@ -253,8 +258,6 @@ class OpenCLCallable(ScalarCallable): if 0 not in arg_id_to_dtype or 1 not in arg_id_to_dtype or ( arg_id_to_dtype[0] is None or arg_id_to_dtype[1] is None): - # the types provided aren't mature enough to specialize the - # callable return ( self.copy(arg_id_to_dtype=arg_id_to_dtype), callables_table) diff --git a/loopy/types.py b/loopy/types.py index e7504862acc7944fa65fbdebb6cfd851f07ac812..14bf89fa197bf1aacbf1488ca53b8cfeebe9a174 100644 --- a/loopy/types.py +++ b/loopy/types.py @@ -20,6 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +from typing import Any from warnings import warn import numpy as np @@ -245,4 +246,22 @@ def to_loopy_type(dtype, allow_auto=False, allow_none=False, for_atomic=False, raise TypeError("dtype must be a LoopyType, or convertible to one, " "found '%s' instead" % type(dtype)) + +_TO_UNSIGNED_MAPPING = { + np.int8: np.uint8, + np.int16: np.uint16, + np.int32: np.uint32, + np.int64: np.uint64, + } + + +def to_unsigned_dtype(dtype: "np.dtype[Any]") -> "np.dtype[Any]": + if dtype.kind == "u": + return dtype + if dtype.kind != "i": + raise ValueError("can only convert integer types to unsigned") + + return _TO_UNSIGNED_MAPPING[dtype.type] + + # vim: foldmethod=marker