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