DPC++ Runtime
Runtime libraries for oneAPI DPC++
type_traits.hpp
Go to the documentation of this file.
1 //==----------------- type_traits.hpp - 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/detail/generic_type_lists.hpp> // for vec, marray, integer_list
13 #include <sycl/detail/type_list.hpp> // for is_contained, find_twi...
14 
15 #include <array> // for array
16 #include <cstddef> // for size_t
17 #include <tuple> // for tuple
18 #include <type_traits> // for true_type, false_type
19 
20 namespace sycl {
21 inline namespace _V1 {
22 namespace detail {
23 template <class T> struct is_fixed_size_group : std::false_type {};
24 
25 template <class T>
27 
28 template <typename VecT, typename OperationLeftT, typename OperationRightT,
29  template <typename> class OperationCurrentT, int... Indexes>
30 class SwizzleOp;
31 } // namespace detail
32 
33 template <int Dimensions> class group;
34 struct sub_group;
35 namespace ext::oneapi {
36 struct sub_group;
37 
38 namespace experimental {
39 template <typename Group, std::size_t Extent> class group_with_scratchpad;
40 
41 template <class T> struct is_fixed_topology_group : std::false_type {};
42 
43 template <class T>
44 inline constexpr bool is_fixed_topology_group_v =
46 
47 template <int Dimensions> class root_group;
48 template <int Dimensions>
49 struct is_fixed_topology_group<root_group<Dimensions>> : std::true_type {};
50 
51 template <int Dimensions>
52 struct is_fixed_topology_group<sycl::group<Dimensions>> : std::true_type {};
53 
54 template <>
55 struct is_fixed_topology_group<sycl::ext::oneapi::sub_group> : std::true_type {
56 };
57 template <> struct is_fixed_topology_group<sycl::sub_group> : std::true_type {};
58 
59 template <class T> struct is_user_constructed_group : std::false_type {};
60 
61 template <class T>
62 inline constexpr bool is_user_constructed_group_v =
64 
65 namespace detail {
66 template <typename T> struct is_group_helper : std::false_type {};
67 
68 template <typename Group, std::size_t Extent>
69 struct is_group_helper<group_with_scratchpad<Group, Extent>> : std::true_type {
70 };
71 } // namespace detail
72 } // namespace experimental
73 } // namespace ext::oneapi
74 
75 namespace detail {
76 
77 template <typename T> struct is_group : std::false_type {};
78 
79 template <int Dimensions>
80 struct is_group<group<Dimensions>> : std::true_type {};
81 
82 template <typename T> struct is_sub_group : std::false_type {};
83 
84 template <> struct is_sub_group<ext::oneapi::sub_group> : std::true_type {};
85 template <> struct is_sub_group<sycl::sub_group> : std::true_type {};
86 
87 template <typename T>
89  : std::bool_constant<is_group<T>::value || is_sub_group<T>::value> {};
90 template <typename T>
92 
93 namespace half_impl {
94 class half;
95 }
96 } // namespace detail
98 
99 // Forward declaration
100 template <typename ElementType, access::address_space Space,
101  access::decorated DecorateAddress>
102 class multi_ptr;
103 
104 template <class T>
105 struct is_group : std::bool_constant<detail::is_group<T>::value ||
106  detail::is_sub_group<T>::value> {};
107 
108 template <class T> inline constexpr bool is_group_v = is_group<T>::value;
109 
110 namespace ext::oneapi::experimental {
111 template <class T>
112 inline constexpr bool is_group_helper_v =
114 } // namespace ext::oneapi::experimental
115 
116 namespace detail {
117 // Type for Intel device UUID extension.
118 // For details about this extension, see
119 // sycl/doc/extensions/supported/sycl_ext_intel_device_info.md
120 using uuid_type = std::array<unsigned char, 16>;
121 
122 template <typename T, typename R> struct copy_cv_qualifiers;
123 
124 template <typename T, typename R>
126 
127 template <int V> using int_constant = std::integral_constant<int, V>;
128 // vector_size
129 // scalars are interpreted as a vector of 1 length.
130 template <typename T> struct vector_size_impl : int_constant<1> {};
131 template <typename T, int N>
132 struct vector_size_impl<vec<T, N>> : int_constant<N> {};
133 template <typename T>
135  : vector_size_impl<std::remove_cv_t<std::remove_reference_t<T>>> {};
136 
137 // vector_element
138 template <typename T> struct vector_element_impl;
139 template <typename T>
141 template <typename T> struct vector_element_impl {
142  using type = T;
143 };
144 template <typename T, int N> struct vector_element_impl<vec<T, N>> {
145  using type = T;
146 };
147 template <typename T> struct vector_element {
148  using type =
150 };
151 template <class T> using vector_element_t = typename vector_element<T>::type;
152 
153 template <class T> using marray_element_t = typename T::value_type;
154 
155 // get_elem_type
156 // Get the element type of T. If T is a scalar, the element type is considered
157 // the type of the scalar.
158 template <typename T, typename = void> struct get_elem_type_unqual {
159  using type = T;
160 };
161 template <typename T, size_t N> struct get_elem_type_unqual<marray<T, N>> {
162  using type = T;
163 };
164 template <typename T, int N> struct get_elem_type_unqual<vec<T, N>> {
165  using type = T;
166 };
167 template <typename VecT, typename OperationLeftT, typename OperationRightT,
168  template <typename> class OperationCurrentT, int... Indexes>
169 struct get_elem_type_unqual<SwizzleOp<VecT, OperationLeftT, OperationRightT,
170  OperationCurrentT, Indexes...>> {
172 };
173 
174 template <typename ElementType, access::address_space Space,
175  access::decorated DecorateAddress>
176 struct get_elem_type_unqual<multi_ptr<ElementType, Space, DecorateAddress>> {
177  using type = ElementType;
178 };
179 
180 template <typename ElementType> struct get_elem_type_unqual<ElementType *> {
181  using type = ElementType;
182 };
183 
184 template <typename T, typename = void>
185 struct is_ext_vector : std::false_type {};
186 
187 template <typename T>
189  T, std::void_t<decltype(__builtin_reduce_max(std::declval<T>()))>>
190  : std::true_type {};
191 
192 template <typename T>
193 inline constexpr bool is_ext_vector_v = is_ext_vector<T>::value;
194 
195 template <typename T>
196 struct get_elem_type_unqual<T, std::enable_if_t<is_ext_vector_v<T>>> {
197  using type = decltype(__builtin_reduce_max(std::declval<T>()));
198 };
199 
200 template <typename T>
201 struct get_elem_type : get_elem_type_unqual<std::remove_cv_t<T>> {};
202 
203 template <typename T> using get_elem_type_t = typename get_elem_type<T>::type;
204 
205 // change_base_type_t
206 template <typename T, typename B> struct change_base_type {
207  using type = B;
208 };
209 
210 template <typename T, int N, typename B> struct change_base_type<vec<T, N>, B> {
211  using type = vec<B, N>;
212 };
213 
214 template <typename T, typename B>
216 
217 // Applies the same the cv-qualifiers from T type to R type
218 template <typename T, typename R> struct copy_cv_qualifiers_impl {
219  using type = R;
220 };
221 
222 template <typename T, typename R> struct copy_cv_qualifiers_impl<const T, R> {
223  using type = const R;
224 };
225 
226 template <typename T, typename R>
227 struct copy_cv_qualifiers_impl<volatile T, R> {
228  using type = volatile R;
229 };
230 
231 template <typename T, typename R>
232 struct copy_cv_qualifiers_impl<const volatile T, R> {
233  using type = const volatile R;
234 };
235 
236 template <typename T, typename R> struct copy_cv_qualifiers {
238 };
239 
240 // make_signed with support SYCL vec class
241 template <typename T> struct make_signed {
242  using type = std::make_signed_t<T>;
243 };
244 template <typename T> using make_signed_t = typename make_signed<T>::type;
245 template <class T> struct make_signed<const T> {
246  using type = const make_signed_t<T>;
247 };
248 template <class T, int N> struct make_signed<vec<T, N>> {
250 };
251 template <typename VecT, typename OperationLeftT, typename OperationRightT,
252  template <typename> class OperationCurrentT, int... Indexes>
253 struct make_signed<SwizzleOp<VecT, OperationLeftT, OperationRightT,
254  OperationCurrentT, Indexes...>> {
256 };
257 template <class T, std::size_t N> struct make_signed<marray<T, N>> {
259 };
260 
261 // make_unsigned with support SYCL vec class
262 template <typename T> struct make_unsigned {
263  using type = std::make_unsigned_t<T>;
264 };
265 template <typename T> using make_unsigned_t = typename make_unsigned<T>::type;
266 template <class T> struct make_unsigned<const T> {
267  using type = const make_unsigned_t<T>;
268 };
269 template <class T, int N> struct make_unsigned<vec<T, N>> {
271 };
272 template <typename VecT, typename OperationLeftT, typename OperationRightT,
273  template <typename> class OperationCurrentT, int... Indexes>
274 struct make_unsigned<SwizzleOp<VecT, OperationLeftT, OperationRightT,
275  OperationCurrentT, Indexes...>> {
277 };
278 template <class T, std::size_t N> struct make_unsigned<marray<T, N>> {
280 };
281 
282 // Checks that sizeof base type of T equal N and T satisfies S<T>::value
283 template <typename T, int N, template <typename> class S>
284 inline constexpr bool is_gen_based_on_type_sizeof_v =
285  S<T>::value && (sizeof(vector_element_t<T>) == N);
286 
287 template <typename> struct is_vec : std::false_type {};
288 template <typename T, int N> struct is_vec<sycl::vec<T, N>> : std::true_type {};
289 
290 template <typename T> constexpr bool is_vec_v = is_vec<T>::value;
291 
292 template <typename> struct get_vec_size {
293  static constexpr int size = 1;
294 };
295 
296 template <typename T, int N> struct get_vec_size<sycl::vec<T, N>> {
297  static constexpr int size = N;
298 };
299 
300 // is_swizzle
301 template <typename> struct is_swizzle : std::false_type {};
302 template <typename VecT, typename OperationLeftT, typename OperationRightT,
303  template <typename> class OperationCurrentT, int... Indexes>
304 struct is_swizzle<SwizzleOp<VecT, OperationLeftT, OperationRightT,
305  OperationCurrentT, Indexes...>> : std::true_type {};
306 
307 template <typename T> constexpr bool is_swizzle_v = is_swizzle<T>::value;
308 
309 // is_swizzle_or_vec_v
310 
311 template <typename T>
312 constexpr bool is_vec_or_swizzle_v = is_vec_v<T> || is_swizzle_v<T>;
313 
314 // is_marray
315 template <typename> struct is_marray : std::false_type {};
316 template <typename T, size_t N>
317 struct is_marray<sycl::marray<T, N>> : std::true_type {};
318 
319 template <typename T> constexpr bool is_marray_v = is_marray<T>::value;
320 
321 // is_integral
322 template <typename T>
323 struct is_integral : std::is_integral<get_elem_type_t<T>> {};
324 
325 // is_floating_point
326 template <typename T>
327 struct is_floating_point_impl : std::is_floating_point<T> {};
328 
329 template <> struct is_floating_point_impl<half> : std::true_type {};
330 
331 template <typename T>
333  : is_floating_point_impl<std::remove_cv_t<get_elem_type_t<T>>> {};
334 
335 template <typename T>
337 
338 // is_arithmetic
339 template <typename T>
341  : std::bool_constant<is_integral<T>::value || is_floating_point<T>::value> {
342 };
343 
344 template <typename T>
346  : std::bool_constant<!is_vec_or_swizzle_v<T> && !is_ext_vector_v<T> &&
347  !is_marray_v<T> && is_arithmetic<T>::value> {};
348 
349 template <typename T>
351 
352 template <typename T>
354  : std::bool_constant<(is_vec_or_swizzle_v<T> || is_ext_vector_v<T> ||
355  is_marray_v<T>) &&
356  is_arithmetic<T>::value> {};
357 
358 // is_bool
359 template <typename T>
361  : std::bool_constant<std::is_same_v<std::remove_cv_t<T>, bool>> {};
362 
363 template <typename T>
365  : std::bool_constant<is_vec<T>::value &&
366  is_scalar_bool<vector_element_t<T>>::value> {};
367 
368 template <typename T>
369 struct is_bool
370  : std::bool_constant<is_scalar_bool<vector_element_t<T>>::value> {};
371 
372 // is_pointer
373 template <typename T> struct is_pointer_impl : std::false_type {};
374 
375 template <typename T> struct is_pointer_impl<T *> : std::true_type {};
376 
377 template <typename T, access::address_space Space,
378  access::decorated DecorateAddress>
379 struct is_pointer_impl<multi_ptr<T, Space, DecorateAddress>> : std::true_type {
380 };
381 
382 template <typename T>
383 struct is_pointer : is_pointer_impl<std::remove_cv_t<T>> {};
384 
385 template <typename T> inline constexpr bool is_pointer_v = is_pointer<T>::value;
386 
387 // is_multi_ptr
388 template <typename T> struct is_multi_ptr : std::false_type {};
389 
390 template <typename ElementType, access::address_space Space,
391  access::decorated IsDecorated>
392 struct is_multi_ptr<multi_ptr<ElementType, Space, IsDecorated>>
393  : std::true_type {};
394 
395 template <class T>
396 inline constexpr bool is_multi_ptr_v = is_multi_ptr<T>::value;
397 
398 // is_non_legacy_multi_ptr
399 template <typename T> struct is_non_legacy_multi_ptr : std::false_type {};
400 
401 template <typename ElementType, access::address_space Space>
403  multi_ptr<ElementType, Space, access::decorated::yes>> : std::true_type {};
404 
405 template <typename ElementType, access::address_space Space>
407  multi_ptr<ElementType, Space, access::decorated::no>> : std::true_type {};
408 
409 template <class T>
410 inline constexpr bool is_non_legacy_multi_ptr_v =
412 
413 // is_legacy_multi_ptr
414 template <typename T> struct is_legacy_multi_ptr : std::false_type {};
415 
416 template <typename ElementType, access::address_space Space>
418  multi_ptr<ElementType, Space, access::decorated::legacy>> : std::true_type {
419 };
420 
421 template <class T>
423 
424 // remove_pointer_t
425 template <typename T> struct remove_pointer_impl {
426  using type = T;
427 };
428 
429 template <typename T> struct remove_pointer_impl<T *> {
430  using type = T;
431 };
432 
433 template <typename T, access::address_space Space,
434  access::decorated DecorateAddress>
435 struct remove_pointer_impl<multi_ptr<T, Space, DecorateAddress>> {
436  using type = T;
437 };
438 
439 template <typename T>
440 struct remove_pointer : remove_pointer_impl<std::remove_cv_t<T>> {};
441 
442 template <typename T> using remove_pointer_t = typename remove_pointer<T>::type;
443 
444 // is_address_space_compliant
445 template <typename T, typename SpaceList>
446 struct is_address_space_compliant_impl : std::false_type {};
447 
448 template <typename T, typename SpaceList>
449 struct is_address_space_compliant_impl<T *, SpaceList> : std::true_type {};
450 
451 template <typename T, typename SpaceList, access::address_space Space,
452  access::decorated DecorateAddress>
453 struct is_address_space_compliant_impl<multi_ptr<T, Space, DecorateAddress>,
454  SpaceList>
455  : std::bool_constant<is_one_of_spaces<Space, SpaceList>::value> {};
456 
457 template <typename T, typename SpaceList>
459  : is_address_space_compliant_impl<std::remove_cv_t<T>, SpaceList> {};
460 
461 template <typename T, typename SpaceList>
462 inline constexpr bool is_address_space_compliant_v =
464 
465 // make_type_t
466 template <typename T, typename TL> struct make_type_impl {
468 };
469 
470 template <typename T, int N, typename TL> struct make_type_impl<vec<T, N>, TL> {
473 };
474 
475 template <typename T, typename TL>
477 
478 // make_larger_t
479 template <typename T, typename Enable = void> struct make_larger_impl;
480 template <typename T>
482  T, std::enable_if_t<is_contained<T, gtl::scalar_floating_list>::value, T>> {
484 };
485 
486 template <typename T>
488  T, std::enable_if_t<is_contained<T, gtl::scalar_signed_integer_list>::value,
489  T>> {
491 };
492 
493 template <typename T>
495  T, std::enable_if_t<
496  is_contained<T, gtl::scalar_unsigned_integer_list>::value, T>> {
498 };
499 
500 template <typename T, int N> struct make_larger_impl<vec<T, N>, vec<T, N>> {
504  static constexpr bool found = !std::is_same_v<upper_type, void>;
505  using type = std::conditional_t<found, new_type, void>;
506 };
507 
508 template <typename T, size_t N>
509 struct make_larger_impl<marray<T, N>, marray<T, N>> {
513  static constexpr bool found = !std::is_same_v<upper_type, void>;
514  using type = std::conditional_t<found, new_type, void>;
515 };
516 
517 template <typename T> struct make_larger {
519 };
520 
521 template <typename T> using make_larger_t = typename make_larger<T>::type;
522 
523 #if defined(RESTRICT_WRITE_ACCESS_TO_CONSTANT_PTR)
524 template <access::address_space AS, class DataT>
525 using const_if_const_AS =
526  typename std::conditional<AS == access::address_space::constant_space,
527  const DataT, DataT>::type;
528 #else
529 template <access::address_space AS, class DataT>
530 using const_if_const_AS = DataT;
531 #endif
532 
533 template <typename T> struct function_traits {};
534 
535 template <typename Ret, typename... Args> struct function_traits<Ret(Args...)> {
536  using ret_type = Ret;
537  using args_type = std::tuple<Args...>;
538 };
539 
540 // No first_type_t due to
541 // https://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1430.
542 template <typename T, typename... Ts> struct first_type {
543  using type = T;
544 };
545 
546 template <typename T0, typename... Ts>
547 inline constexpr bool all_same_v = (... && std::is_same_v<T0, Ts>);
548 
549 // Example usage:
550 // using mapped = map_type<type_to_map, from0, /*->*/ to0,
551 // from1, /*->*/ to1,
552 // ...>
553 template <typename...> struct map_type {
554  using type = void;
555 };
556 
557 template <typename T, typename From, typename To, typename... Rest>
558 struct map_type<T, From, To, Rest...> {
559  using type = std::conditional_t<std::is_same_v<From, T>, To,
560  typename map_type<T, Rest...>::type>;
561 };
562 template <typename T, typename... Ts> constexpr bool CheckTypeIn() {
563  constexpr bool SameType[] = {
564  std::is_same_v<std::remove_cv_t<T>, std::remove_cv_t<Ts>>...};
565  // Replace with std::any_of with C++20.
566  for (size_t I = 0; I < sizeof...(Ts); ++I)
567  if (SameType[I])
568  return true;
569  return false;
570 }
571 
572 // NOTE: We need a constexpr variable definition for the constexpr functions
573 // as MSVC thinks function definitions are the same otherwise.
574 template <typename... Ts> constexpr bool check_type_in_v = CheckTypeIn<Ts...>();
575 
576 } // namespace detail
577 } // namespace _V1
578 } // namespace sycl
Provides a cross-platform math array class template that works on SYCL devices as well as in host C++...
Definition: marray.hpp:49
constexpr bool check_type_in_v
typename change_base_type< T, B >::type change_base_type_t
constexpr bool is_vec_or_swizzle_v
constexpr bool is_scalar_arithmetic_v
constexpr bool is_pointer_v
typename T::value_type marray_element_t
constexpr bool is_floating_point_v
constexpr bool is_marray_v
constexpr bool is_vec_v
constexpr bool is_gen_based_on_type_sizeof_v
constexpr bool is_non_legacy_multi_ptr_v
typename remove_pointer< T >::type remove_pointer_t
typename make_larger< T >::type make_larger_t
typename make_unsigned< T >::type make_unsigned_t
typename vector_element_impl< T >::type vector_element_impl_t
constexpr bool is_address_space_compliant_v
constexpr bool is_ext_vector_v
typename get_elem_type< T >::type get_elem_type_t
constexpr bool all_same_v
constexpr bool is_legacy_multi_ptr_v
constexpr bool CheckTypeIn()
typename vector_element< T >::type vector_element_t
typename copy_cv_qualifiers< T, R >::type copy_cv_qualifiers_t
typename make_signed< T >::type make_signed_t
constexpr bool is_multi_ptr_v
std::array< unsigned char, 16 > uuid_type
find_type_t< TypeList, is_type_size_equal, T > find_same_size_type_t
Definition: type_list.hpp:91
constexpr bool is_fixed_size_group_v
Definition: type_traits.hpp:26
find_type_t< TypeList, is_type_size_double_of, T > find_twice_as_large_type_t
Definition: type_list.hpp:95
std::integral_constant< int, V > int_constant
typename make_type_impl< T, TL >::type make_type_t
constexpr bool is_generic_group_v
Definition: type_traits.hpp:91
constexpr bool is_swizzle_v
class __SYCL_EBO __SYCL_SPECIAL_CLASS Dimensions
constexpr bool is_group_v
sycl::detail::half_impl::half half
Definition: aliases.hpp:101
const void value_type
Definition: multi_ptr.hpp:457
Definition: access.hpp:18
typename copy_cv_qualifiers_impl< T, std::remove_cv_t< R > >::type type
typename make_larger_impl< base_type, base_type >::type upper_type
typename make_larger_impl< base_type, base_type >::type upper_type
std::conditional_t< found, new_type, void > type
typename make_larger_impl< T, T >::type type
std::make_signed_t< T > type
typename make_type_impl< T, TL >::type scalar_type
find_same_size_type_t< TL, T > type
std::make_unsigned_t< T > type
std::conditional_t< std::is_same_v< From, T >, To, typename map_type< T, Rest... >::type > type
copy_cv_qualifiers_t< T, vector_element_impl_t< std::remove_cv_t< T > >> type