DPC++ Runtime
Runtime libraries for oneAPI DPC++
generic_type_traits.hpp
Go to the documentation of this file.
1 //==----------- generic_type_traits - SYCL type traits ---------------------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
11 #include <sycl/access/access.hpp> // for decorated, address_space
12 #include <sycl/aliases.hpp> // for half, cl_char, cl_double
13 #include <sycl/detail/generic_type_lists.hpp> // for nonconst_address_space...
14 #include <sycl/detail/helpers.hpp> // for marray
15 #include <sycl/detail/type_list.hpp> // for is_contained, find_sam...
16 #include <sycl/detail/type_traits.hpp> // for is_gen_based_on_type_s...
17 #include <sycl/half_type.hpp> // for BIsRepresentationT
18 #include <sycl/multi_ptr.hpp> // for multi_ptr, address_spa...
19 
20 #include <cstddef> // for byte
21 #include <cstdint> // for uint8_t
22 #include <limits> // for numeric_limits
23 #include <type_traits> // for enable_if_t, condition...
24 
25 namespace sycl {
26 inline namespace _V1 {
27 namespace detail {
28 template <int N> struct Boolean;
29 
30 template <typename T>
31 inline constexpr bool is_svgenfloatf_v =
32  is_contained_v<T, gtl::scalar_vector_float_list>;
33 
34 template <typename T>
35 inline constexpr bool is_svgenfloatd_v =
36  is_contained_v<T, gtl::scalar_vector_double_list>;
37 
38 template <typename T>
39 inline constexpr bool is_half_v = is_contained_v<T, gtl::scalar_half_list>;
40 
41 template <typename T>
42 inline constexpr bool is_bfloat16_v =
43  is_contained_v<T, gtl::scalar_bfloat16_list>;
44 
45 template <typename T>
46 inline constexpr bool is_half_or_bf16_v =
47  is_contained_v<T, gtl::half_bfloat16_list>;
48 
49 template <typename T>
50 inline constexpr bool is_svgenfloath_v =
51  is_contained_v<T, gtl::scalar_vector_half_list>;
52 
53 template <typename T>
54 inline constexpr bool is_genfloat_v = is_contained_v<T, gtl::floating_list>;
55 
56 template <typename T>
57 inline constexpr bool is_sgenfloat_v =
58  is_contained_v<T, gtl::scalar_floating_list>;
59 
60 template <typename T>
61 inline constexpr bool is_vgenfloat_v =
62  is_contained_v<T, gtl::vector_floating_list>;
63 
64 template <typename T>
65 inline constexpr bool is_svgenfloat_v =
66  is_contained_v<T, gtl::scalar_vector_floating_list>;
67 
68 template <typename T>
69 inline constexpr bool is_mgenfloat_v =
70  is_marray_v<T> && is_svgenfloat_v<get_elem_type_t<T>>;
71 
72 template <typename T>
73 inline constexpr bool is_gengeofloat_v = is_contained_v<T, gtl::geo_float_list>;
74 
75 template <typename T>
76 inline constexpr bool is_gengeodouble_v =
77  is_contained_v<T, gtl::geo_double_list>;
78 
79 template <typename T>
80 inline constexpr bool is_gengeomarrayfloat_v =
81  is_contained_v<T, gtl::marray_geo_float_list>;
82 
83 template <typename T>
84 inline constexpr bool is_gengeomarray_v =
85  is_contained_v<T, gtl::marray_geo_list>;
86 
87 template <typename T>
88 inline constexpr bool is_gengeohalf_v = is_contained_v<T, gtl::geo_half_list>;
89 
90 template <typename T>
91 inline constexpr bool is_vgengeofloat_v =
92  is_contained_v<T, gtl::vector_geo_float_list>;
93 
94 template <typename T>
95 inline constexpr bool is_vgengeodouble_v =
96  is_contained_v<T, gtl::vector_geo_double_list>;
97 
98 template <typename T>
99 inline constexpr bool is_vgengeohalf_v =
100  is_contained_v<T, gtl::vector_geo_half_list>;
101 
102 template <typename T>
103 inline constexpr bool is_sgengeo_v = is_contained_v<T, gtl::scalar_geo_list>;
104 
105 template <typename T>
106 inline constexpr bool is_vgengeo_v = is_contained_v<T, gtl::vector_geo_list>;
107 
108 template <typename T>
109 inline constexpr bool is_gencrossfloat_v =
110  is_contained_v<T, gtl::cross_float_list>;
111 
112 template <typename T>
113 inline constexpr bool is_gencrossdouble_v =
114  is_contained_v<T, gtl::cross_double_list>;
115 
116 template <typename T>
117 inline constexpr bool is_gencrosshalf_v =
118  is_contained_v<T, gtl::cross_half_list>;
119 
120 template <typename T>
121 inline constexpr bool is_gencross_v =
122  is_contained_v<T, gtl::cross_floating_list>;
123 
124 template <typename T>
125 inline constexpr bool is_gencrossmarray_v =
126  is_contained_v<T, gtl::cross_marray_list>;
127 
128 template <typename T>
129 inline constexpr bool is_ugenint_v = is_contained_v<T, gtl::unsigned_int_list>;
130 
131 template <typename T>
132 inline constexpr bool is_intn_v =
133  is_contained_v<T, gtl::vector_signed_int_list>;
134 
135 template <typename T>
136 inline constexpr bool is_genint_v = is_contained_v<T, gtl::signed_int_list>;
137 
138 template <typename T>
139 inline constexpr bool is_geninteger_v = is_contained_v<T, gtl::integer_list>;
140 
141 template <typename T>
142 using is_geninteger = std::bool_constant<is_geninteger_v<T>>;
143 
144 template <typename T>
145 inline constexpr bool is_igeninteger_v =
146  is_contained_v<T, gtl::signed_integer_list>;
147 
148 template <typename T>
149 using is_igeninteger = std::bool_constant<is_igeninteger_v<T>>;
150 
151 template <typename T>
152 inline constexpr bool is_ugeninteger_v =
153  is_contained_v<T, gtl::unsigned_integer_list>;
154 
155 template <typename T>
156 using is_ugeninteger = std::bool_constant<is_ugeninteger_v<T>>;
157 
158 template <typename T>
159 inline constexpr bool is_sgeninteger_v =
160  is_contained_v<T, gtl::scalar_integer_list>;
161 
162 template <typename T>
163 inline constexpr bool is_vgeninteger_v =
164  is_contained_v<T, gtl::vector_integer_list>;
165 
166 template <typename T>
167 inline constexpr bool is_sigeninteger_v =
168  is_contained_v<T, gtl::scalar_signed_integer_list>;
169 
170 template <typename T>
171 inline constexpr bool is_sugeninteger_v =
172  is_contained_v<T, gtl::scalar_unsigned_integer_list>;
173 
174 template <typename T>
175 inline constexpr bool is_vigeninteger_v =
176  is_contained_v<T, gtl::vector_signed_integer_list>;
177 
178 template <typename T>
179 inline constexpr bool is_vugeninteger_v =
180  is_contained_v<T, gtl::vector_unsigned_integer_list>;
181 
182 template <typename T>
183 inline constexpr bool is_genbool_v = is_contained_v<T, gtl::bool_list>;
184 
185 template <typename T>
186 inline constexpr bool is_gentype_v = is_contained_v<T, gtl::basic_list>;
187 
188 template <typename T>
189 inline constexpr bool is_vgentype_v = is_contained_v<T, gtl::vector_basic_list>;
190 
191 template <typename T>
192 inline constexpr bool is_sgentype_v = is_contained_v<T, gtl::scalar_basic_list>;
193 
194 template <typename T>
195 inline constexpr bool is_igeninteger8bit_v =
196  is_gen_based_on_type_sizeof_v<T, 1, is_igeninteger>;
197 
198 template <typename T>
199 inline constexpr bool is_igeninteger16bit_v =
200  is_gen_based_on_type_sizeof_v<T, 2, is_igeninteger>;
201 
202 template <typename T>
203 inline constexpr bool is_igeninteger32bit_v =
204  is_gen_based_on_type_sizeof_v<T, 4, is_igeninteger>;
205 
206 template <typename T>
207 inline constexpr bool is_igeninteger64bit_v =
208  is_gen_based_on_type_sizeof_v<T, 8, is_igeninteger>;
209 
210 template <typename T>
211 inline constexpr bool is_ugeninteger8bit_v =
212  is_gen_based_on_type_sizeof_v<T, 1, is_ugeninteger>;
213 
214 template <typename T>
215 inline constexpr bool is_ugeninteger16bit_v =
216  is_gen_based_on_type_sizeof_v<T, 2, is_ugeninteger>;
217 
218 template <typename T>
219 inline constexpr bool is_ugeninteger32bit_v =
220  is_gen_based_on_type_sizeof_v<T, 4, is_ugeninteger>;
221 
222 template <typename T>
223 inline constexpr bool is_ugeninteger64bit_v =
224  is_gen_based_on_type_sizeof_v<T, 8, is_ugeninteger>;
225 
226 template <typename T>
227 inline constexpr bool is_genintptr_v =
228  is_pointer_v<T> && is_genint_v<remove_pointer_t<T>> &&
229  is_address_space_compliant_v<T, gvl::nonconst_address_space_list>;
230 
231 template <typename T, access::address_space AddressSpace,
232  access::decorated IsDecorated>
233 inline constexpr bool is_genintptr_marray_v =
234  std::is_same_v<T, sycl::marray<marray_element_t<T>, T::size()>> &&
235  is_genint_v<marray_element_t<remove_pointer_t<T>>> &&
236  is_address_space_compliant_v<multi_ptr<T, AddressSpace, IsDecorated>,
238  (IsDecorated == access::decorated::yes ||
239  IsDecorated == access::decorated::no);
240 
241 template <typename T>
242 inline constexpr bool is_genfloatptr_v =
243  is_pointer_v<T> && is_genfloat_v<remove_pointer_t<T>> &&
244  is_address_space_compliant_v<T, gvl::nonconst_address_space_list>;
245 
246 template <typename T, access::address_space AddressSpace,
247  access::decorated IsDecorated>
248 inline constexpr bool is_genfloatptr_marray_v =
249  is_mgenfloat_v<T> &&
250  is_address_space_compliant_v<multi_ptr<T, AddressSpace, IsDecorated>,
252  (IsDecorated == access::decorated::yes ||
253  IsDecorated == access::decorated::no);
254 
255 template <typename T>
257 
258 template <typename T>
260 
261 template <typename T>
264 
265 // select_apply_cl_scalar_t selects from T8/T16/T32/T64 basing on
266 // sizeof(IN). expected to handle scalar types.
267 template <typename T, typename T8, typename T16, typename T32, typename T64>
268 using select_apply_cl_scalar_t = std::conditional_t<
269  sizeof(T) == 1, T8,
270  std::conditional_t<sizeof(T) == 2, T16,
271  std::conditional_t<sizeof(T) == 4, T32, T64>>>;
272 
273 // Shortcuts for selecting scalar int/unsigned int/fp type.
274 template <typename T>
278 
279 template <typename T>
283 
284 // Use SFINAE so that std::complex specialization could be implemented in
285 // include/sycl/stl_wrappers/complex that would only be available if STL's
286 // <complex> is included by users. Note that "function template partial
287 // specialization" is not allowed, so we cannot perform that trick on
288 // convertToOpenCLType function directly.
289 template <typename T, typename = void> struct select_cl_scalar_complex_or_T {
290  using type = T;
291 };
292 
293 template <typename T>
296 
297 template <typename T> auto convertToOpenCLType(T &&x) {
298  using no_ref = std::remove_reference_t<T>;
299  if constexpr (is_multi_ptr_v<no_ref>) {
300  return convertToOpenCLType(x.get_decorated());
301  } else if constexpr (std::is_pointer_v<no_ref>) {
302  // TODO: Below ignores volatile, but we didn't have a need for it yet.
304  using converted_elem_type_no_cv = decltype(convertToOpenCLType(
305  std::declval<std::remove_const_t<elem_type>>()));
306  using converted_elem_type =
307  std::conditional_t<std::is_const_v<elem_type>,
308  const converted_elem_type_no_cv,
309  converted_elem_type_no_cv>;
310 #ifdef __SYCL_DEVICE_ONLY__
311  using result_type =
312  typename DecoratedType<converted_elem_type,
313  deduce_AS<no_ref>::value>::type *;
314 #else
315  using result_type = converted_elem_type *;
316 #endif
317  return reinterpret_cast<result_type>(x);
318  } else if constexpr (is_vec_v<no_ref>) {
319  using ElemTy = typename no_ref::element_type;
320  // sycl::half may convert to _Float16, and we would try to instantiate
321  // vec class with _Float16 DataType, which is not expected there. As
322  // such, leave vector<half, N> as-is.
323  using MatchingVec = vec<std::conditional_t<is_half_v<ElemTy>, ElemTy,
324  decltype(convertToOpenCLType(
325  std::declval<ElemTy>()))>,
326  no_ref::size()>;
327 #ifdef __SYCL_DEVICE_ONLY__
328  // TODO: for some mysterious reasons on NonUniformGroups E2E tests fail if
329  // we use the "else" version only. I suspect that's an issues with
330  // non-uniform groups implementation.
331  if constexpr (std::is_same_v<MatchingVec, no_ref>)
332  return static_cast<typename MatchingVec::vector_t>(x);
333  else
334  return static_cast<typename MatchingVec::vector_t>(
335  x.template as<MatchingVec>());
336 #else
337  return x.template as<MatchingVec>();
338 #endif
339  } else if constexpr (is_boolean_v<no_ref>) {
340 #ifdef __SYCL_DEVICE_ONLY__
341  if constexpr (std::is_same_v<Boolean<1>, no_ref>) {
342  // Or should it be "int"?
343  return std::forward<T>(x);
344  } else {
345  return static_cast<typename no_ref::vector_t>(x);
346  }
347 #else
348  return std::forward<T>(x);
349 #endif
350 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
351  } else if constexpr (std::is_same_v<no_ref, std::byte>) {
352  return static_cast<uint8_t>(x);
353 #endif
354  } else if constexpr (std::is_integral_v<no_ref>) {
355  using OpenCLType =
356  std::conditional_t<std::is_signed_v<no_ref>,
359  static_assert(sizeof(OpenCLType) == sizeof(T));
360  return static_cast<OpenCLType>(x);
361  } else if constexpr (is_half_v<no_ref>) {
363  static_assert(sizeof(OpenCLType) == sizeof(T));
364  return static_cast<OpenCLType>(x);
365  } else if constexpr (is_bfloat16_v<no_ref>) {
366  return std::forward<T>(x);
367  } else if constexpr (std::is_floating_point_v<no_ref>) {
368  static_assert(std::is_same_v<no_ref, float> ||
369  std::is_same_v<no_ref, double>,
370  "Other FP types are not expected/supported (yet?)");
371  static_assert(std::is_same_v<float, sycl::opencl::cl_float> &&
372  std::is_same_v<double, sycl::opencl::cl_double>);
373  return std::forward<T>(x);
374  } else {
375  using OpenCLType = select_cl_scalar_complex_or_T_t<no_ref>;
376  static_assert(sizeof(OpenCLType) == sizeof(T));
377  return static_cast<OpenCLType>(x);
378  }
379 }
380 
381 template <typename T>
382 using ConvertToOpenCLType_t = decltype(convertToOpenCLType(std::declval<T>()));
383 
384 template <typename To, typename From> auto convertFromOpenCLTypeFor(From &&x) {
385  if constexpr (std::is_same_v<To, bool> &&
386  std::is_same_v<std::remove_reference_t<From>, bool>) {
387  // FIXME: Something seems to be wrong elsewhere...
388  return x;
389  } else {
390  using OpenCLType = decltype(convertToOpenCLType(std::declval<To>()));
391  static_assert(std::is_same_v<std::remove_reference_t<From>, OpenCLType>);
392  static_assert(sizeof(OpenCLType) == sizeof(To));
393  using To_noref = std::remove_reference_t<To>;
394  using From_noref = std::remove_reference_t<From>;
395  if constexpr (is_vec_v<To_noref> && is_vec_v<From_noref>)
396  return x.template as<To_noref>();
397  else if constexpr (is_vec_v<To_noref> && is_ext_vector_v<From_noref>)
398  return To_noref{bit_cast<typename To_noref::vector_t>(x)};
399  else
400  return static_cast<To>(x);
401  }
402 }
403 
404 // Used for all, any and select relational built-in functions
405 template <typename T> inline constexpr T msbMask(T) {
406  using UT = make_unsigned_t<T>;
407  return T(UT(1) << (sizeof(T) * 8 - 1));
408 }
409 
410 template <typename T> inline constexpr bool msbIsSet(const T x) {
411  return (x & msbMask(x));
412 }
413 
414 // Try to get vector element count or 1 otherwise
415 template <typename T> struct GetNumElements {
416  static constexpr int value = 1;
417 };
418 template <typename Type, int NumElements>
419 struct GetNumElements<typename sycl::vec<Type, NumElements>> {
420  static constexpr int value = NumElements;
421 };
422 template <int N> struct GetNumElements<typename sycl::detail::Boolean<N>> {
423  static constexpr int value = N;
424 };
425 
426 // TryToGetElementType<T>::type is T::element_type or T::value_type if those
427 // exist, otherwise T.
428 template <typename T> class TryToGetElementType {
429  static T check(...);
430  template <typename A> static typename A::element_type check(const A &);
431  template <typename A, typename = std::enable_if_t<!std::is_same_v<
432  typename A::element_type, typename A::value_type>>>
433  static typename A::value_type check(const A &);
434 
435 public:
436  using type = decltype(check(T()));
437  static constexpr bool value = !std::is_same_v<T, type>;
438 };
439 
440 template <typename T> static constexpr T max_v() {
441  return (std::numeric_limits<T>::max)();
442 }
443 
444 template <typename T> static constexpr T min_v() {
445  return (std::numeric_limits<T>::min)();
446 }
447 } // namespace detail
448 } // namespace _V1
449 } // namespace sycl
Provides a cross-patform vector class template that works efficiently on SYCL devices as well as in h...
Definition: types.hpp:284
constexpr bool is_vgengeo_v
constexpr bool is_sgeninteger_v
constexpr bool is_ugeninteger8bit_v
constexpr bool is_svgenfloatd_v
constexpr bool is_half_v
constexpr bool is_gentype_v
std::bool_constant< is_ugeninteger_v< T > > is_ugeninteger
constexpr bool is_ugeninteger16bit_v
constexpr bool is_ugeninteger64bit_v
constexpr bool is_sugeninteger_v
constexpr bool is_ugeninteger_v
make_type_t< T, gtl::scalar_unsigned_integer_list > make_unsinged_integer_t
constexpr bool is_mgenfloat_v
constexpr bool is_igeninteger8bit_v
constexpr bool is_gengeofloat_v
static constexpr T min_v()
constexpr bool is_vugeninteger_v
constexpr bool is_sgengeo_v
std::conditional_t< sizeof(T)==1, T8, std::conditional_t< sizeof(T)==2, T16, std::conditional_t< sizeof(T)==4, T32, T64 > >> select_apply_cl_scalar_t
typename make_unsigned< T >::type make_unsigned_t
constexpr bool is_genfloat_v
constexpr bool is_vgengeofloat_v
constexpr bool is_igeninteger_v
make_type_t< T, gtl::scalar_signed_integer_list > make_singed_integer_t
constexpr bool is_ugenint_v
constexpr bool is_bfloat16_v
auto convertFromOpenCLTypeFor(From &&x)
select_apply_cl_scalar_t< T, sycl::opencl::cl_uchar, sycl::opencl::cl_ushort, sycl::opencl::cl_uint, sycl::opencl::cl_ulong > select_cl_scalar_integral_unsigned_t
constexpr bool is_genfloatptr_v
constexpr bool is_svgenfloath_v
constexpr bool is_sgenfloat_v
constexpr bool is_vgeninteger_v
constexpr bool is_sgentype_v
constexpr bool is_vgentype_v
constexpr bool is_gencrossmarray_v
constexpr bool is_ugeninteger32bit_v
constexpr bool is_igeninteger32bit_v
constexpr bool is_gencrosshalf_v
static constexpr T max_v()
constexpr bool is_igeninteger64bit_v
constexpr bool is_gengeodouble_v
constexpr bool is_gencross_v
constexpr bool is_svgenfloatf_v
constexpr bool is_vgenfloat_v
std::bool_constant< is_geninteger_v< T > > is_geninteger
constexpr bool is_geninteger_v
constexpr bool msbIsSet(const T x)
decltype(convertToOpenCLType(std::declval< T >())) ConvertToOpenCLType_t
constexpr bool is_gencrossfloat_v
constexpr bool is_genintptr_v
constexpr bool is_genintptr_marray_v
constexpr bool is_vgengeohalf_v
constexpr bool is_svgenfloat_v
constexpr bool is_vigeninteger_v
constexpr bool is_half_or_bf16_v
constexpr bool is_gengeomarray_v
std::bool_constant< is_igeninteger_v< T > > is_igeninteger
make_type_t< T, gtl::scalar_floating_list > make_floating_point_t
constexpr bool is_genfloatptr_marray_v
typename select_cl_scalar_complex_or_T< T >::type select_cl_scalar_complex_or_T_t
constexpr bool is_vgengeodouble_v
constexpr bool is_gengeohalf_v
constexpr bool is_gencrossdouble_v
typename make_type_impl< T, TL >::type make_type_t
select_apply_cl_scalar_t< T, sycl::opencl::cl_char, sycl::opencl::cl_short, sycl::opencl::cl_int, sycl::opencl::cl_long > select_cl_scalar_integral_signed_t
constexpr bool is_genint_v
constexpr bool is_gengeomarrayfloat_v
constexpr bool is_igeninteger16bit_v
constexpr bool is_sigeninteger_v
constexpr bool is_genbool_v
std::uint64_t cl_ulong
Definition: aliases.hpp:137
std::int32_t cl_int
Definition: aliases.hpp:134
std::int8_t cl_char
Definition: aliases.hpp:130
std::uint8_t cl_uchar
Definition: aliases.hpp:131
std::uint16_t cl_ushort
Definition: aliases.hpp:133
std::int16_t cl_short
Definition: aliases.hpp:132
std::uint32_t cl_uint
Definition: aliases.hpp:135
std::int64_t cl_long
Definition: aliases.hpp:136
autodecltype(x) x
const void value_type
Definition: multi_ptr.hpp:457
typename remove_decoration< T >::type remove_decoration_t
Definition: access.hpp:325
Definition: access.hpp:18