14 #ifndef __has_extension
15 #define __has_extension(x) 0
17 #ifdef __HAS_EXT_VECTOR_TYPE__
18 #error "Undefine __HAS_EXT_VECTOR_TYPE__ macro"
20 #if __has_extension(attribute_ext_vector_type)
21 #define __HAS_EXT_VECTOR_TYPE__
25 #if !defined(__HAS_EXT_VECTOR_TYPE__) && defined(__SYCL_DEVICE_ONLY__)
26 #error "SYCL device compiler is built without ext_vector_type support"
29 #if defined(__SYCL_DEVICE_ONLY__)
30 #define __SYCL_USE_EXT_VECTOR_TYPE__
60 #include <type_traits>
68 inline namespace _V1 {
71 static constexpr
int x = 0;
72 static constexpr
int y = 1;
73 static constexpr
int z = 2;
74 static constexpr
int w = 3;
75 static constexpr
int r = 0;
76 static constexpr
int g = 1;
77 static constexpr
int b = 2;
78 static constexpr
int a = 3;
79 static constexpr
int s0 = 0;
80 static constexpr
int s1 = 1;
81 static constexpr
int s2 = 2;
82 static constexpr
int s3 = 3;
83 static constexpr
int s4 = 4;
84 static constexpr
int s5 = 5;
85 static constexpr
int s6 = 6;
86 static constexpr
int s7 = 7;
87 static constexpr
int s8 = 8;
88 static constexpr
int s9 = 9;
89 static constexpr
int sA = 10;
90 static constexpr
int sB = 11;
91 static constexpr
int sC = 12;
92 static constexpr
int sD = 13;
93 static constexpr
int sE = 14;
94 static constexpr
int sF = 15;
100 template <
typename _IN,
typename T8,
typename T16,
typename T32,
typename T64>
102 sizeof(_IN) == 1, T8,
103 std::conditional_t<
sizeof(_IN) == 2, T16,
104 std::conditional_t<
sizeof(_IN) == 4, T32, T64>>>;
122 #if defined(__SYCL_BITCAST_IS_CONSTEXPR)
123 return sycl::bit_cast<RetType>(value);
132 result.storage = value;
140 #if defined(__SYCL_BITCAST_IS_CONSTEXPR)
141 return sycl::bit_cast<BFloat16StorageT>(value);
148 return result.storage;
153 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
167 template <
typename VecT,
typename OperationLeftT,
typename OperationRightT,
168 template <
typename>
class OperationCurrentT,
int... Indexes>
171 template <
typename T,
int N,
typename V =
void>
struct VecStorage;
174 template <
typename DataT>
175 using rel_t =
typename std::conditional_t<
177 typename std::conditional_t<
179 typename std::conditional_t<
181 typename std::conditional_t<
sizeof(DataT) ==
209 return (Lhs == Rhs) ? -1 : 0;
215 return (Lhs != Rhs) ? -1 : 0;
221 return (Lhs >= Rhs) ? -1 : 0;
227 return (Lhs <= Rhs) ? -1 : 0;
233 return (Lhs > Rhs) ? -1 : 0;
239 return (Lhs < Rhs) ? -1 : 0;
245 return (Lhs && Rhs) ? -1 : 0;
251 return (Lhs || Rhs) ? -1 : 0;
268 template <
typename TransformedArgType,
int Dims,
typename KernelType>
269 class RoundedRangeKernel;
270 template <
typename TransformedArgType,
int Dims,
typename KernelType>
271 class RoundedRangeKernelWithKH;
275 template <
typename T>
using vec_data = detail::vec_helper<T>;
277 template <
typename T>
284 template <
typename Type,
int NumElements>
class vec {
291 static constexpr
bool IsHostHalf =
292 std::is_same_v<DataT, sycl::detail::half_impl::half> &&
296 static constexpr
bool IsBfloat16 =
297 std::is_same_v<DataT, sycl::ext::oneapi::bfloat16>;
299 static constexpr
size_t AdjustedNum = (NumElements == 3) ? 4 : NumElements;
300 static constexpr
size_t Sz =
sizeof(DataT) * AdjustedNum;
301 static constexpr
bool IsSizeGreaterThanMaxAlign =
309 static constexpr
bool IsUsingArrayOnDevice =
310 (IsHostHalf || IsBfloat16 || IsSizeGreaterThanMaxAlign);
312 #if defined(__SYCL_DEVICE_ONLY__)
313 static constexpr
bool NativeVec = NumElements > 1 && !IsUsingArrayOnDevice;
314 static constexpr
bool IsUsingArrayOnHost =
false;
316 static constexpr
bool NativeVec =
false;
317 static constexpr
bool IsUsingArrayOnHost =
true;
320 static constexpr
int getNumElements() {
return NumElements; }
323 template <
int Counter,
int MaxValue,
class...>
324 struct SizeChecker : std::conditional_t<Counter == MaxValue, std::true_type,
327 template <
int Counter,
int MaxValue,
typename DataT_,
class... tail>
328 struct SizeChecker<Counter, MaxValue, DataT_, tail...>
329 : std::conditional_t<Counter + 1 <= MaxValue,
330 SizeChecker<Counter + 1, MaxValue, tail...>,
334 template <typename DataT_, typename T, std::size_t... Is>
335 static constexpr std::array<DataT_, sizeof...(Is)>
336 VecToArray(const vec<T, sizeof...(Is)> &V, std::index_sequence<Is...>) {
337 return {static_cast<DataT_>(V.getValue(Is))...};
339 template <typename DataT_, typename T, int N, typename T2, typename T3,
340 template <typename> class T4, int... T5, std::size_t... Is>
341 static constexpr std::array<DataT_, sizeof...(Is)>
342 VecToArray(const detail::SwizzleOp<vec<T, N>, T2, T3, T4, T5...> &V,
343 std::index_sequence<Is...>) {
344 return {static_cast<DataT_>(V.getValue(Is))...};
346 template <typename DataT_, typename T, int N, typename T2, typename T3,
347 template <typename> class T4, int... T5, std::size_t... Is>
348 static constexpr std::array<DataT_, sizeof...(Is)>
349 VecToArray(const detail::SwizzleOp<const vec<T, N>, T2, T3, T4, T5...> &V,
350 std::index_sequence<Is...>) {
351 return {static_cast<DataT_>(V.getValue(Is))...};
353 template <typename DataT_, typename T, int N>
354 static constexpr std::array<DataT_, N>
355 FlattenVecArgHelper(const vec<T, N> &A) {
356 return VecToArray<DataT_>(A, std::make_index_sequence<N>());
358 template <typename DataT_, typename T, int N, typename T2, typename T3,
359 template <typename> class T4, int... T5>
360 static constexpr std::array<DataT_, sizeof...(T5)> FlattenVecArgHelper(
361 const detail::SwizzleOp<vec<T, N>, T2, T3, T4, T5...> &A) {
362 return VecToArray<DataT_>(A, std::make_index_sequence<sizeof...(T5)>());
364 template <typename DataT_, typename T, int N, typename T2, typename T3,
365 template <typename> class T4, int... T5>
366 static constexpr std::array<DataT_, sizeof...(T5)> FlattenVecArgHelper(
367 const detail::SwizzleOp<const vec<T, N>, T2, T3, T4, T5...> &A) {
368 return VecToArray<DataT_>(A, std::make_index_sequence<sizeof...(T5)>());
370 template <typename DataT_, typename T>
371 static constexpr auto FlattenVecArgHelper(const T &A) {
372 return std::array<DataT_, 1>{vec_data<DataT_>::get(static_cast<DataT_>(A))};
374 template <typename DataT_, typename T> struct FlattenVecArg {
375 constexpr auto operator()(const T &A) const {
376 return FlattenVecArgHelper<DataT_>(A);
381 template <typename DataT_, typename... ArgTN>
382 using VecArgArrayCreator =
383 detail::ArrayCreator<DataT_, FlattenVecArg, ArgTN...>;
385 #define __SYCL_ALLOW_VECTOR_SIZES(num_elements) \
386 template <int Counter, int MaxValue, typename DataT_, class... tail> \
387 struct SizeChecker<Counter, MaxValue, vec<DataT_, num_elements>, tail...> \
388 : std::conditional_t< \
389 Counter + (num_elements) <= MaxValue, \
390 SizeChecker<Counter + (num_elements), MaxValue, tail...>, \
391 std::false_type> {}; \
392 template <int Counter, int MaxValue, typename DataT_, typename T2, \
393 typename T3, template <typename> class T4, int... T5, \
395 struct SizeChecker< \
397 detail::SwizzleOp<vec<DataT_, num_elements>, T2, T3, T4, T5...>, \
399 : std::conditional_t< \
400 Counter + sizeof...(T5) <= MaxValue, \
401 SizeChecker<Counter + sizeof...(T5), MaxValue, tail...>, \
402 std::false_type> {}; \
403 template <int Counter, int MaxValue, typename DataT_, typename T2, \
404 typename T3, template <typename> class T4, int... T5, \
406 struct SizeChecker< \
408 detail::SwizzleOp<const vec<DataT_, num_elements>, T2, T3, T4, T5...>, \
410 : std::conditional_t< \
411 Counter + sizeof...(T5) <= MaxValue, \
412 SizeChecker<Counter + sizeof...(T5), MaxValue, tail...>, \
415 __SYCL_ALLOW_VECTOR_SIZES(1)
416 __SYCL_ALLOW_VECTOR_SIZES(2)
417 __SYCL_ALLOW_VECTOR_SIZES(3)
418 __SYCL_ALLOW_VECTOR_SIZES(4)
419 __SYCL_ALLOW_VECTOR_SIZES(8)
420 __SYCL_ALLOW_VECTOR_SIZES(16)
421 #undef __SYCL_ALLOW_VECTOR_SIZES
424 template <typename T, typename DataT_>
425 struct TypeChecker : std::is_convertible<T, DataT_> {};
426 #define __SYCL_ALLOW_VECTOR_TYPES(num_elements) \
427 template <typename DataT_> \
428 struct TypeChecker<vec<DataT_, num_elements>, DataT_> : std::true_type {}; \
429 template <typename DataT_, typename T2, typename T3, \
430 template <typename> class T4, int... T5> \
431 struct TypeChecker< \
432 detail::SwizzleOp<vec<DataT_, num_elements>, T2, T3, T4, T5...>, DataT_> \
433 : std::true_type {}; \
434 template <typename DataT_, typename T2, typename T3, \
435 template <typename> class T4, int... T5> \
436 struct TypeChecker< \
437 detail::SwizzleOp<const vec<DataT_, num_elements>, T2, T3, T4, T5...>, \
438 DataT_> : std::true_type {};
440 __SYCL_ALLOW_VECTOR_TYPES(1)
441 __SYCL_ALLOW_VECTOR_TYPES(2)
442 __SYCL_ALLOW_VECTOR_TYPES(3)
443 __SYCL_ALLOW_VECTOR_TYPES(4)
444 __SYCL_ALLOW_VECTOR_TYPES(8)
445 __SYCL_ALLOW_VECTOR_TYPES(16)
446 #undef __SYCL_ALLOW_VECTOR_TYPES
448 template <int... Indexes>
450 detail::SwizzleOp<vec, detail::GetOp<DataT>, detail::GetOp<DataT>,
451 detail::GetOp, Indexes...>;
453 template <int... Indexes>
455 detail::SwizzleOp<const vec, detail::GetOp<DataT>, detail::GetOp<DataT>,
456 detail::GetOp, Indexes...>;
459 template <typename... argTN>
460 using EnableIfSuitableTypes = typename std::enable_if_t<
461 std::conjunction_v<TypeChecker<argTN, DataT>...>>;
463 template <typename... argTN>
464 using EnableIfSuitableNumElements =
465 typename std::enable_if_t<SizeChecker<0, NumElements, argTN...>::value>;
467 template <size_t... Is>
468 constexpr vec(const std::array<vec_data_t<DataT>, NumElements> &Arr,
469 std::index_sequence<Is...>)
470 : m_Data{([&](vec_data_t<DataT> v) constexpr {
471 if constexpr (std::is_same_v<sycl::ext::oneapi::bfloat16, DataT>)
474 return vec_data_t<DataT>(static_cast<DataT>(v));
478 using element_type = DataT;
479 using value_type = DataT;
480 using rel_t = detail::rel_t<DataT>;
481 #ifdef __SYCL_DEVICE_ONLY__
483 typename detail::VecStorage<DataT, NumElements>::VectorDataType;
488 constexpr vec(const vec &Rhs) = default;
489 constexpr vec(vec &&Rhs) = default;
491 constexpr vec &operator=(const vec &Rhs) = default;
494 template <typename Ty = DataT>
495 typename std::enable_if_t<!std::is_same_v<Ty, rel_t> &&
496 std::is_convertible_v<vec_data_t<Ty>, rel_t>,
498 operator=(const vec<rel_t, NumElements> &Rhs) {
499 *this = Rhs.template as<vec>();
503 #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
504 template <typename T = void>
505 using EnableIfNotHostHalf = typename std::enable_if_t<!IsHostHalf, T>;
507 template <typename T = void>
508 using EnableIfHostHalf = typename std::enable_if_t<IsHostHalf, T>;
510 template <typename T = void>
511 using EnableIfUsingArrayOnDevice =
512 typename std::enable_if_t<IsUsingArrayOnDevice, T>;
514 template <typename T = void>
515 using EnableIfNotUsingArrayOnDevice =
516 typename std::enable_if_t<!IsUsingArrayOnDevice, T>;
519 template <typename T = void>
520 using EnableIfUsingArray =
521 typename std::enable_if_t<IsUsingArrayOnDevice || IsUsingArrayOnHost, T>;
523 template <typename T = void>
524 using EnableIfNotUsingArray =
525 typename std::enable_if_t<!IsUsingArrayOnDevice && !IsUsingArrayOnHost,
528 #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
530 template <typename Ty = DataT>
531 explicit constexpr vec(const EnableIfNotUsingArrayOnDevice<Ty> &arg)
532 : m_Data{DataType(vec_data<Ty>::get(arg))} {}
534 template <typename Ty = DataT>
535 typename std::enable_if_t<
536 std::is_fundamental_v<vec_data_t<Ty>> ||
537 detail::is_half_or_bf16_v<typename std::remove_const_t<Ty>>,
539 operator=(const EnableIfNotUsingArrayOnDevice<Ty> &Rhs) {
540 m_Data = (DataType)vec_data<Ty>::get(Rhs);
544 template <typename Ty = DataT>
545 explicit constexpr vec(const EnableIfUsingArrayOnDevice<Ty> &arg)
546 : vec{detail::RepeatValue<NumElements>(
547 static_cast<vec_data_t<DataT>>(arg)),
548 std::make_index_sequence<NumElements>()} {}
550 template <typename Ty = DataT>
551 typename std::enable_if_t<
552 std::is_fundamental_v<vec_data_t<Ty>> ||
553 detail::is_half_or_bf16_v<typename std::remove_const_t<Ty>>,
555 operator=(const EnableIfUsingArrayOnDevice<Ty> &Rhs) {
556 for (int i = 0; i < NumElements; ++i) {
562 explicit constexpr vec(const DataT &arg)
563 : vec{detail::RepeatValue<NumElements>(
564 static_cast<vec_data_t<DataT>>(arg)),
565 std::make_index_sequence<NumElements>()} {}
567 template <typename Ty = DataT>
568 typename std::enable_if_t<
569 std::is_fundamental_v<vec_data_t<Ty>> ||
570 detail::is_half_or_bf16_v<typename std::remove_const_t<Ty>>,
572 operator=(const DataT &Rhs) {
573 for (int i = 0; i < NumElements; ++i) {
580 #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
586 template <int IdxNum, typename T = void>
587 using EnableIfMultipleElems = typename std::enable_if_t<
588 std::is_convertible_v<T, DataT> && NumElements == IdxNum, DataT>;
589 template <typename Ty = DataT>
590 constexpr vec(const EnableIfMultipleElems<2, Ty> Arg0,
591 const EnableIfNotUsingArrayOnDevice<Ty> Arg1)
592 : m_Data{vec_data<Ty>::get(Arg0), vec_data<Ty>::get(Arg1)} {}
593 template <typename Ty = DataT>
594 constexpr vec(const EnableIfMultipleElems<3, Ty> Arg0,
595 const EnableIfNotUsingArrayOnDevice<Ty> Arg1, const DataT Arg2)
596 : m_Data{vec_data<Ty>::get(Arg0), vec_data<Ty>::get(Arg1),
597 vec_data<Ty>::get(Arg2)} {}
598 template <typename Ty = DataT>
599 constexpr vec(const EnableIfMultipleElems<4, Ty> Arg0,
600 const EnableIfNotUsingArrayOnDevice<Ty> Arg1, const DataT Arg2,
602 : m_Data{vec_data<Ty>::get(Arg0), vec_data<Ty>::get(Arg1),
603 vec_data<Ty>::get(Arg2), vec_data<Ty>::get(Arg3)} {}
604 template <typename Ty = DataT>
605 constexpr vec(const EnableIfMultipleElems<8, Ty> Arg0,
606 const EnableIfNotUsingArrayOnDevice<Ty> Arg1, const DataT Arg2,
607 const DataT Arg3, const DataT Arg4, const DataT Arg5,
608 const DataT Arg6, const DataT Arg7)
609 : m_Data{vec_data<Ty>::get(Arg0), vec_data<Ty>::get(Arg1),
610 vec_data<Ty>::get(Arg2), vec_data<Ty>::get(Arg3),
611 vec_data<Ty>::get(Arg4), vec_data<Ty>::get(Arg5),
612 vec_data<Ty>::get(Arg6), vec_data<Ty>::get(Arg7)} {}
613 template <typename Ty = DataT>
614 constexpr vec(const EnableIfMultipleElems<16, Ty> Arg0,
615 const EnableIfNotUsingArrayOnDevice<Ty> Arg1, const DataT Arg2,
616 const DataT Arg3, const DataT Arg4, const DataT Arg5,
617 const DataT Arg6, const DataT Arg7, const DataT Arg8,
618 const DataT Arg9, const DataT ArgA, const DataT ArgB,
619 const DataT ArgC, const DataT ArgD, const DataT ArgE,
621 : m_Data{vec_data<Ty>::get(Arg0), vec_data<Ty>::get(Arg1),
622 vec_data<Ty>::get(Arg2), vec_data<Ty>::get(Arg3),
623 vec_data<Ty>::get(Arg4), vec_data<Ty>::get(Arg5),
624 vec_data<Ty>::get(Arg6), vec_data<Ty>::get(Arg7),
625 vec_data<Ty>::get(Arg8), vec_data<Ty>::get(Arg9),
626 vec_data<Ty>::get(ArgA), vec_data<Ty>::get(ArgB),
627 vec_data<Ty>::get(ArgC), vec_data<Ty>::get(ArgD),
628 vec_data<Ty>::get(ArgE), vec_data<Ty>::get(ArgF)} {}
633 template <typename... argTN, typename = EnableIfSuitableTypes<argTN...>,
634 typename = EnableIfSuitableNumElements<argTN...>>
635 constexpr vec(const argTN &...args)
636 : vec{VecArgArrayCreator<vec_data_t<DataT>, argTN...>::Create(args...),
637 std::make_index_sequence<NumElements>()} {}
639 #ifdef __SYCL_DEVICE_ONLY__
640 template <typename vector_t_ = vector_t,
642 typename std::enable_if_t<std::is_same_v<vector_t_, vector_t> &&
643 !std::is_same_v<vector_t_, DataT>>>
644 constexpr vec(vector_t openclVector) {
645 if constexpr (!IsUsingArrayOnDevice) {
646 m_Data = openclVector;
648 m_Data = bit_cast<DataType>(openclVector);
652 operator vector_t() const {
653 if constexpr (!IsUsingArrayOnDevice) {
656 auto ptr = bit_cast<const vector_t *>((&m_Data)->data());
663 template <int N = NumElements>
664 operator typename std::enable_if_t<N == 1, DataT>() const {
665 return vec_data<DataT>::get(m_Data);
668 __SYCL2020_DEPRECATED("get_count() is deprecated, please use size() instead")
669 static constexpr size_t get_count() { return size(); }
670 static constexpr size_t size() noexcept { return NumElements; }
671 __SYCL2020_DEPRECATED(
672 "get_size() is deprecated, please use byte_size() instead")
673 static constexpr size_t get_size() { return byte_size(); }
674 static constexpr size_t byte_size() noexcept { return sizeof(m_Data); }
678 template <typename convertT,
679 rounding_mode roundingMode = rounding_mode::automatic>
681 std::is_same_v<vec_data_t<DataT>, vec_data_t<convertT>> ||
682 std::is_same_v<detail::ConvertToOpenCLType_t<vec_data_t<DataT>>,
683 detail::ConvertToOpenCLType_t<vec_data_t<convertT>>>,
684 vec<convertT, NumElements>>
686 static_assert(std::is_integral_v<vec_data_t<convertT>> ||
687 detail::is_floating_point<convertT>::value,
688 "Unsupported convertT");
689 if constexpr (!std::is_same_v<DataT, convertT>) {
691 vec<convertT, NumElements> Result;
692 for (size_t I = 0; I < NumElements; ++I)
693 Result.setValue(I, static_cast<convertT>(getValue(I)));
702 template <typename convertT,
703 rounding_mode roundingMode = rounding_mode::automatic>
705 !std::is_same_v<vec_data_t<DataT>, vec_data_t<convertT>> &&
706 !std::is_same_v<detail::ConvertToOpenCLType_t<vec_data_t<DataT>>,
707 detail::ConvertToOpenCLType_t<vec_data_t<convertT>>>,
708 vec<convertT, NumElements>>
710 static_assert(std::is_integral_v<vec_data_t<convertT>> ||
711 detail::is_floating_point<convertT>::value,
712 "Unsupported convertT");
713 using T = vec_data_t<DataT>;
714 using R = vec_data_t<convertT>;
715 using OpenCLT = detail::ConvertToOpenCLType_t<T>;
716 using OpenCLR = detail::ConvertToOpenCLType_t<R>;
717 vec<convertT, NumElements> Result;
719 #if defined(__SYCL_DEVICE_ONLY__)
720 using OpenCLVecT = OpenCLT __attribute__((ext_vector_type(NumElements)));
721 using OpenCLVecR = OpenCLR __attribute__((ext_vector_type(NumElements)));
723 constexpr bool canUseNativeVectorConvert =
729 NativeVec && vec<convertT, NumElements>::NativeVec &&
733 std::is_convertible_v<decltype(m_Data), OpenCLVecT> &&
734 std::is_convertible_v<decltype(Result.m_Data), OpenCLVecR> &&
737 !detail::is_sint_to_from_uint<T, R>::value &&
743 !std::is_same_v<convertT, bool>;
744 if constexpr (canUseNativeVectorConvert) {
745 Result.m_Data = detail::convertImpl<T, R, roundingMode, NumElements,
746 OpenCLVecT, OpenCLVecR>(m_Data);
751 for (size_t I = 0; I < NumElements; ++I) {
753 I, vec_data<convertT>::get(
754 detail::convertImpl<T, R, roundingMode, 1, OpenCLT, OpenCLR>(
755 vec_data<DataT>::get(getValue(I)))));
762 template <typename asT> asT as() const {
763 static_assert((sizeof(*this) == sizeof(asT)),
764 "The new SYCL vec type must have the same storage size in "
765 "bytes as this SYCL vec");
767 detail::is_contained<asT, detail::gtl::vector_basic_list>::value ||
768 detail::is_contained<asT, detail::gtl::vector_bool_list>::value,
769 "asT must be SYCL vec of a different element type and "
770 "number of elements specified by asT");
772 detail::memcpy(&Result.m_Data, &m_Data, sizeof(decltype(Result.m_Data)));
776 template <int... SwizzleIndexes> Swizzle<SwizzleIndexes...> swizzle() {
780 template <int... SwizzleIndexes>
781 ConstSwizzle<SwizzleIndexes...> swizzle() const {
800 template <typename T = DataT>
801 typename std::enable_if_t<!std::is_same_v<T, sycl::ext::oneapi::bfloat16>,
803 operator[](int i) const {
804 return reinterpret_cast<const DataT *>(&m_Data)[i];
807 template <typename T = DataT>
808 typename std::enable_if_t<!std::is_same_v<T, sycl::ext::oneapi::bfloat16>,
811 return reinterpret_cast<DataT *>(&m_Data)[i];
815 #define __SYCL_NOINLINE_BF16 __declspec(noinline)
817 #define __SYCL_NOINLINE_BF16 __attribute__((noinline))
820 template <typename T = DataT>
822 typename std::enable_if_t<std::is_same_v<T, sycl::ext::oneapi::bfloat16>,
824 operator[](int i) const {
825 return reinterpret_cast<const DataT *>(&m_Data)[i];
828 template <typename T = DataT>
830 typename std::enable_if_t<std::is_same_v<T, sycl::ext::oneapi::bfloat16>,
833 return reinterpret_cast<DataT *>(&m_Data)[i];
836 #undef __SYCL_NOINLINE_BF16
845 template <int Index> struct Indexer {
846 static constexpr int value = Index;
850 #ifdef __SYCL_ACCESS_RETURN
851 #error "Undefine __SYCL_ACCESS_RETURN macro"
853 #define __SYCL_ACCESS_RETURN this
854 #include "swizzles.def"
855 #undef __SYCL_ACCESS_RETURN
858 template <access::address_space Space, access::decorated DecorateAddress>
859 void load(size_t Offset, multi_ptr<const DataT, Space, DecorateAddress> Ptr) {
860 for (int I = 0; I < NumElements; I++) {
861 setValue(I, *multi_ptr<const DataT, Space, DecorateAddress>(
862 Ptr + Offset * NumElements + I));
865 template <access::address_space Space, access::decorated DecorateAddress>
866 void load(size_t Offset, multi_ptr<DataT, Space, DecorateAddress> Ptr) {
867 multi_ptr<const DataT, Space, DecorateAddress> ConstPtr(Ptr);
868 load(Offset, ConstPtr);
870 template <int Dimensions, access::mode Mode,
871 access::placeholder IsPlaceholder, access::target Target,
872 typename PropertyListT>
875 accessor<DataT, Dimensions, Mode, Target, IsPlaceholder, PropertyListT>
877 multi_ptr<const DataT, detail::TargetToAS<Target>::AS,
878 access::decorated::yes>
880 load(Offset, MultiPtr);
882 template <access::address_space Space, access::decorated DecorateAddress>
883 void store(size_t Offset,
884 multi_ptr<DataT, Space, DecorateAddress> Ptr) const {
885 for (int I = 0; I < NumElements; I++) {
886 *multi_ptr<DataT, Space, DecorateAddress>(Ptr + Offset * NumElements +
890 template <int Dimensions, access::mode Mode,
891 access::placeholder IsPlaceholder, access::target Target,
892 typename PropertyListT>
895 accessor<DataT, Dimensions, Mode, Target, IsPlaceholder, PropertyListT>
897 multi_ptr<DataT, detail::TargetToAS<Target>::AS, access::decorated::yes>
899 store(Offset, MultiPtr);
902 void ConvertToDataT() {
903 for (size_t i = 0; i < NumElements; ++i) {
904 DataT tmp = getValue(i);
910 #error "Undefine __SYCL_BINOP macro"
913 #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
914 #define __SYCL_BINOP(BINOP, OPASSIGN, CONVERT) \
915 friend vec operator BINOP(const vec &Lhs, const vec &Rhs) { \
917 if constexpr (IsUsingArrayOnDevice) { \
918 for (size_t I = 0; I < NumElements; ++I) { \
919 Ret.setValue(I, (Lhs.getValue(I) BINOP Rhs.getValue(I))); \
922 Ret.m_Data = Lhs.m_Data BINOP Rhs.m_Data; \
923 if constexpr (std::is_same_v<Type, bool> && CONVERT) { \
924 Ret.ConvertToDataT(); \
929 friend vec operator BINOP(const vec &Lhs, const DataT &Rhs) { \
930 return Lhs BINOP vec(Rhs); \
932 friend vec operator BINOP(const DataT &Lhs, const vec &Rhs) { \
933 return vec(Lhs) BINOP Rhs; \
935 friend vec &operator OPASSIGN(vec & Lhs, const vec & Rhs) { \
936 Lhs = Lhs BINOP Rhs; \
939 template <int Num = NumElements> \
940 friend typename std::enable_if_t<Num != 1, vec &> operator OPASSIGN( \
941 vec & Lhs, const DataT & Rhs) { \
942 Lhs = Lhs BINOP vec(Rhs); \
948 #define __SYCL_BINOP(BINOP, OPASSIGN, CONVERT) \
949 friend vec operator BINOP(const vec &Lhs, const vec &Rhs) { \
951 if constexpr (NativeVec) \
952 Ret.m_Data = Lhs.m_Data BINOP Rhs.m_Data; \
954 for (size_t I = 0; I < NumElements; ++I) \
955 Ret.setValue(I, (DataT)(vec_data<DataT>::get(Lhs.getValue( \
956 I)) BINOP vec_data<DataT>::get(Rhs.getValue(I)))); \
959 friend vec operator BINOP(const vec &Lhs, const DataT &Rhs) { \
960 return Lhs BINOP vec(Rhs); \
962 friend vec operator BINOP(const DataT &Lhs, const vec &Rhs) { \
963 return vec(Lhs) BINOP Rhs; \
965 friend vec &operator OPASSIGN(vec & Lhs, const vec & Rhs) { \
966 Lhs = Lhs BINOP Rhs; \
969 template <int Num = NumElements> \
970 friend typename std::enable_if_t<Num != 1, vec &> operator OPASSIGN( \
971 vec & Lhs, const DataT & Rhs) { \
972 Lhs = Lhs BINOP vec(Rhs); \
978 __SYCL_BINOP(+, +=, true)
979 __SYCL_BINOP(-, -=, true)
980 __SYCL_BINOP(*, *=, false)
981 __SYCL_BINOP(/, /=, false)
985 __SYCL_BINOP(%, %=, false)
986 __SYCL_BINOP(|, |=, false)
987 __SYCL_BINOP(&, &=, false)
988 __SYCL_BINOP(^, ^=, false)
989 __SYCL_BINOP(>>, >>=, false)
990 __SYCL_BINOP(<<, <<=, true)
992 #undef __SYCL_BINOP_HELP
1001 #ifdef __SYCL_RELLOGOP
1002 #error "Undefine __SYCL_RELLOGOP macro"
1006 #ifdef __SYCL_DEVICE_ONLY__
1007 #define __SYCL_RELLOGOP(RELLOGOP) \
1008 friend vec<rel_t, NumElements> operator RELLOGOP(const vec & Lhs, \
1009 const vec & Rhs) { \
1010 vec<rel_t, NumElements> Ret{}; \
1013 if constexpr (IsUsingArrayOnDevice && \
1014 (std::string_view(#RELLOGOP) == "||" || \
1015 std::string_view(#RELLOGOP) == "&&")) { \
1016 for (size_t I = 0; I < NumElements; ++I) { \
1019 Ret[I] = static_cast<rel_t>(-(vec_data<DataT>::get( \
1020 Lhs.getValue(I)) RELLOGOP vec_data<DataT>::get(Rhs.getValue(I)))); \
1023 Ret = vec<rel_t, NumElements>( \
1024 (typename vec<rel_t, NumElements>::vector_t)( \
1025 Lhs.m_Data RELLOGOP Rhs.m_Data)); \
1026 if (NumElements == 1) \
1031 friend vec<rel_t, NumElements> operator RELLOGOP(const vec & Lhs, \
1032 const DataT & Rhs) { \
1033 return Lhs RELLOGOP vec(Rhs); \
1035 friend vec<rel_t, NumElements> operator RELLOGOP(const DataT & Lhs, \
1036 const vec & Rhs) { \
1037 return vec(Lhs) RELLOGOP Rhs; \
1041 #define __SYCL_RELLOGOP(RELLOGOP) \
1042 friend vec<rel_t, NumElements> operator RELLOGOP(const vec & Lhs, \
1043 const vec & Rhs) { \
1044 vec<rel_t, NumElements> Ret{}; \
1045 for (size_t I = 0; I < NumElements; ++I) { \
1048 Ret[I] = static_cast<rel_t>(-(vec_data<DataT>::get( \
1049 Lhs.getValue(I)) RELLOGOP vec_data<DataT>::get(Rhs.getValue(I)))); \
1053 friend vec<rel_t, NumElements> operator RELLOGOP(const vec & Lhs, \
1054 const DataT & Rhs) { \
1055 return Lhs RELLOGOP vec(Rhs); \
1057 friend vec<rel_t, NumElements> operator RELLOGOP(const DataT & Lhs, \
1058 const vec & Rhs) { \
1059 return vec(Lhs) RELLOGOP Rhs; \
1072 #undef __SYCL_RELLOGOP
1075 #error "Undefine __SYCL_UOP macro"
1077 #define __SYCL_UOP(UOP, OPASSIGN) \
1078 friend vec &operator UOP(vec & Rhs) { \
1079 Rhs OPASSIGN vec_data<DataT>::get(1); \
1082 friend vec operator UOP(vec &Lhs, int) { \
1084 Lhs OPASSIGN vec_data<DataT>::get(1); \
1094 friend vec operator~(const vec &Rhs) {
1095 if constexpr (IsUsingArrayOnDevice || IsUsingArrayOnHost) {
1097 for (size_t I = 0; I < NumElements; ++I) {
1098 Ret.setValue(I, ~Rhs.getValue(I));
1102 vec Ret{(typename vec::DataType) ~Rhs.m_Data};
1103 if constexpr (std::is_same_v<Type, bool>) {
1104 Ret.ConvertToDataT();
1111 friend vec<detail::rel_t<DataT>, NumElements> operator!(const vec &Rhs) {
1112 if constexpr (IsUsingArrayOnDevice || IsUsingArrayOnHost) {
1114 for (size_t I = 0; I < NumElements; ++I) {
1115 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
1118 if constexpr (std::is_same_v<std::byte, DataT>) {
1119 Ret.setValue(I, std::byte{!vec_data<DataT>::get(Rhs.getValue(I))});
1123 Ret.setValue(I, !vec_data<DataT>::get(Rhs.getValue(I)));
1126 return Ret.template as<vec<detail::rel_t<DataT>, NumElements>>();
1128 return vec{(typename vec<DataT, NumElements>::DataType) !Rhs.m_Data}
1129 .template as<vec<detail::rel_t<DataT>, NumElements>>();
1134 friend vec operator+(const vec &Lhs) {
1135 if constexpr (IsUsingArrayOnDevice || IsUsingArrayOnHost) {
1137 for (size_t I = 0; I < NumElements; ++I)
1139 I, vec_data<DataT>::get(+vec_data<DataT>::get(Lhs.getValue(I))));
1142 return vec{+Lhs.m_Data};
1147 friend vec operator-(const vec &Lhs) {
1148 namespace oneapi = sycl::ext::oneapi;
1150 if constexpr (IsBfloat16 && NumElements == 1) {
1151 oneapi::bfloat16 v = oneapi::detail::bitsToBfloat16(Lhs.m_Data);
1152 oneapi::bfloat16 w = -v;
1153 Ret.m_Data = oneapi::detail::bfloat16ToBits(w);
1154 } else if constexpr (IsBfloat16) {
1155 for (size_t I = 0; I < NumElements; I++) {
1156 oneapi::bfloat16 v = oneapi::detail::bitsToBfloat16(Lhs.m_Data[I]);
1157 oneapi::bfloat16 w = -v;
1158 Ret.m_Data[I] = oneapi::detail::bfloat16ToBits(w);
1160 } else if constexpr (IsUsingArrayOnDevice || IsUsingArrayOnHost) {
1161 for (size_t I = 0; I < NumElements; ++I)
1163 I, vec_data<DataT>::get(-vec_data<DataT>::get(Lhs.getValue(I))));
1166 Ret = vec{-Lhs.m_Data};
1167 if constexpr (std::is_same_v<Type, bool>) {
1168 Ret.ConvertToDataT();
1184 #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
1185 template <template <typename> class Operation,
1186 typename Ty = vec<DataT, NumElements>>
1187 vec<DataT, NumElements>
1188 operatorHelper(const EnableIfNotUsingArrayOnDevice<Ty> &Rhs) const {
1189 vec<DataT, NumElements> Result;
1190 Operation<DataType> Op;
1191 Result.m_Data = Op(m_Data, Rhs.m_Data);
1195 template <template <typename> class Operation,
1196 typename Ty = vec<DataT, NumElements>>
1197 vec<DataT, NumElements>
1198 operatorHelper(const EnableIfUsingArrayOnDevice<Ty> &Rhs) const {
1199 vec<DataT, NumElements> Result;
1200 Operation<DataT> Op;
1201 for (size_t I = 0; I < NumElements; ++I) {
1202 Result.setValue(I, Op(Rhs.getValue(I), getValue(I)));
1207 template <template <typename> class Operation>
1208 vec<DataT, NumElements>
1209 operatorHelper(const vec<DataT, NumElements> &Rhs) const {
1210 vec<DataT, NumElements> Result;
1211 Operation<DataT> Op;
1212 for (size_t I = 0; I < NumElements; ++I) {
1213 Result.setValue(I, Op(Rhs.getValue(I), getValue(I)));
1222 #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
1223 template <int Num = NumElements, typename Ty = int,
1224 typename = typename std::enable_if_t<1 != Num>>
1225 constexpr void setValue(EnableIfNotHostHalf<Ty> Index, const DataT &Value,
1227 m_Data[Index] = vec_data<DataT>::set(Value);
1230 template <int Num = NumElements, typename Ty = int,
1231 typename = typename std::enable_if_t<1 != Num>>
1232 constexpr DataT getValue(EnableIfNotHostHalf<Ty> Index, int) const {
1233 return vec_data<DataT>::get(m_Data[Index]);
1236 template <int Num = NumElements, typename Ty = int,
1237 typename = typename std::enable_if_t<1 != Num>>
1238 constexpr void setValue(EnableIfHostHalf<Ty> Index, const DataT &Value, int) {
1239 m_Data.s[Index] = vec_data<DataT>::set(Value);
1242 template <int Num = NumElements, typename Ty = int,
1243 typename = typename std::enable_if_t<1 != Num>>
1244 constexpr DataT getValue(EnableIfHostHalf<Ty> Index, int) const {
1245 return vec_data<DataT>::get(m_Data.s[Index]);
1248 template <int Num = NumElements,
1249 typename = typename std::enable_if_t<1 != Num>>
1250 constexpr void setValue(int Index, const DataT &Value, int) {
1251 m_Data[Index] = vec_data<DataT>::set(Value);
1254 template <int Num = NumElements,
1255 typename = typename std::enable_if_t<1 != Num>>
1256 constexpr DataT getValue(int Index, int) const {
1257 return vec_data<DataT>::get(m_Data[Index]);
1262 template <int Num = NumElements,
1263 typename = typename std::enable_if_t<1 == Num>>
1264 constexpr void setValue(int, const DataT &Value, float) {
1265 m_Data = vec_data<DataT>::set(Value);
1268 template <int Num = NumElements,
1269 typename = typename std::enable_if_t<1 == Num>>
1270 DataT getValue(int, float) const {
1271 return vec_data<DataT>::get(m_Data);
1278 constexpr void setValue(int Index, const DataT &Value) {
1279 if (NumElements == 1)
1280 setValue(Index, Value, 0);
1282 setValue(Index, Value, 0.f);
1285 DataT getValue(int Index) const {
1286 return (NumElements == 1) ? getValue(Index, 0) : getValue(Index, 0.f);
1293 alignas(detail::vector_alignment<DataT, NumElements>::value) DataType m_Data;
1296 template <typename T1, typename T2, typename T3, template <typename> class T4,
1298 friend class detail::SwizzleOp;
1299 template <typename T1, int T2> friend class vec;
1302 #ifdef __cpp_deduction_guides
1304 template <class T, class... U,
1305 class = std::enable_if_t<(std::is_same_v<T, U> && ...)>>
1306 vec(T, U...) -> vec<T, sizeof...(U) + 1>;
1313 template <typename VecT, typename OperationLeftT, typename OperationRightT,
1314 template <typename> class OperationCurrentT, int... Indexes>
1316 using DataT = typename VecT::element_type;
1343 using OpLeftDataT = typename OperationLeftT::DataT;
1344 using OpRightDataT = typename OperationRightT::DataT;
1345 using CommonDataT = std::conditional_t<
1346 sizeof(DataT) >= sizeof(std::common_type_t<OpLeftDataT, OpRightDataT>),
1347 DataT, std::common_type_t<OpLeftDataT, OpRightDataT>>;
1348 static constexpr int getNumElements() { return sizeof...(Indexes); }
1350 using rel_t = detail::rel_t<DataT>;
1351 using vec_t = vec<DataT, sizeof...(Indexes)>;
1352 using vec_rel_t = vec<rel_t, sizeof...(Indexes)>;
1354 template <typename OperationRightT_,
1355 template <typename> class OperationCurrentT_, int... Idx_>
1356 using NewLHOp = SwizzleOp<VecT,
1357 SwizzleOp<VecT, OperationLeftT, OperationRightT,
1358 OperationCurrentT, Indexes...>,
1359 OperationRightT_, OperationCurrentT_, Idx_...>;
1361 template <typename OperationRightT_,
1362 template <typename> class OperationCurrentT_, int... Idx_>
1363 using NewRelOp = SwizzleOp<vec<rel_t, VecT::getNumElements()>,
1364 SwizzleOp<VecT, OperationLeftT, OperationRightT,
1365 OperationCurrentT, Indexes...>,
1366 OperationRightT_, OperationCurrentT_, Idx_...>;
1368 template <typename OperationLeftT_,
1369 template <typename> class OperationCurrentT_, int... Idx_>
1370 using NewRHOp = SwizzleOp<VecT, OperationLeftT_,
1371 SwizzleOp<VecT, OperationLeftT, OperationRightT,
1372 OperationCurrentT, Indexes...>,
1373 OperationCurrentT_, Idx_...>;
1375 template <int IdxNum, typename T = void>
1376 using EnableIfOneIndex = typename std::enable_if_t<
1377 1 == IdxNum && SwizzleOp::getNumElements() == IdxNum, T>;
1379 template <int IdxNum, typename T = void>
1380 using EnableIfMultipleIndexes = typename std::enable_if_t<
1381 1 != IdxNum && SwizzleOp::getNumElements() == IdxNum, T>;
1383 template <typename T>
1384 using EnableIfScalarType = typename std::enable_if_t<
1385 std::is_convertible_v<DataT, T> &&
1386 (std::is_fundamental_v<vec_data_t<T>> ||
1387 detail::is_half_or_bf16_v<typename std::remove_const_t<T>>)>;
1389 template <typename T>
1390 using EnableIfNoScalarType = typename std::enable_if_t<
1391 !std::is_convertible_v<DataT, T> ||
1392 !(std::is_fundamental_v<vec_data_t<T>> ||
1393 detail::is_half_or_bf16_v<typename std::remove_const_t<T>>)>;
1395 template <int... Indices>
1397 SwizzleOp<VecT, GetOp<DataT>, GetOp<DataT>, GetOp, Indices...>;
1399 template <int... Indices>
1400 using ConstSwizzle =
1401 SwizzleOp<const VecT, GetOp<DataT>, GetOp<DataT>, GetOp, Indices...>;
1404 using element_type = DataT;
1405 using value_type = DataT;
1407 #ifdef __SYCL_DEVICE_ONLY__
1408 using vector_t = typename vec_t::vector_t;
1411 const DataT &operator[](int i) const {
1412 std::array<int, getNumElements()> Idxs{Indexes...};
1413 return (*m_Vector)[Idxs[i]];
1416 template <typename _T = VecT>
1417 std::enable_if_t<!std::is_const_v<_T>, DataT> &operator[](int i) {
1418 std::array<int, getNumElements()> Idxs{Indexes...};
1419 return (*m_Vector)[Idxs[i]];
1422 __SYCL2020_DEPRECATED("get_count() is deprecated, please use size() instead")
1423 size_t get_count() const { return size(); }
1424 static constexpr size_t size() noexcept { return getNumElements(); }
1426 template <int Num = getNumElements()>
1427 __SYCL2020_DEPRECATED(
1428 "get_size() is deprecated, please use byte_size() instead")
1429 size_t get_size() const {
1430 return byte_size<Num>();
1433 template <int Num = getNumElements()> size_t byte_size() const noexcept {
1434 return sizeof(DataT) * (Num == 3 ? 4 : Num);
1437 template <typename T, int IdxNum = getNumElements(),
1438 typename = EnableIfOneIndex<IdxNum>,
1439 typename = EnableIfScalarType<T>>
1440 operator T() const {
1444 template <typename T, typename = EnableIfScalarType<T>>
1445 friend NewRHOp<GetScalarOp<T>, std::multiplies, Indexes...>
1446 operator*(const T &Lhs, const SwizzleOp &Rhs) {
1447 return NewRHOp<GetScalarOp<T>, std::multiplies, Indexes...>(
1448 Rhs.m_Vector, GetScalarOp<T>(Lhs), Rhs);
1451 template <typename T, typename = EnableIfScalarType<T>>
1452 friend NewRHOp<GetScalarOp<T>, std::plus, Indexes...>
1453 operator+(const T &Lhs, const SwizzleOp &Rhs) {
1454 return NewRHOp<GetScalarOp<T>, std::plus, Indexes...>(
1455 Rhs.m_Vector, GetScalarOp<T>(Lhs), Rhs);
1458 template <typename T, typename = EnableIfScalarType<T>>
1459 friend NewRHOp<GetScalarOp<T>, std::divides, Indexes...>
1460 operator/(const T &Lhs, const SwizzleOp &Rhs) {
1461 return NewRHOp<GetScalarOp<T>, std::divides, Indexes...>(
1462 Rhs.m_Vector, GetScalarOp<T>(Lhs), Rhs);
1466 #ifdef __SYCL_OPASSIGN
1467 #error "Undefine __SYCL_OPASSIGN macro."
1469 #define __SYCL_OPASSIGN(OPASSIGN, OP) \
1470 SwizzleOp &operator OPASSIGN(const DataT & Rhs) { \
1471 operatorHelper<OP>(vec_t(Rhs)); \
1474 template <typename RhsOperation> \
1475 SwizzleOp &operator OPASSIGN(const RhsOperation & Rhs) { \
1476 operatorHelper<OP>(Rhs); \
1480 __SYCL_OPASSIGN(+=, std::plus)
1481 __SYCL_OPASSIGN(-=, std::minus)
1482 __SYCL_OPASSIGN(*=, std::multiplies)
1483 __SYCL_OPASSIGN(/=, std::divides)
1484 __SYCL_OPASSIGN(%=, std::modulus)
1485 __SYCL_OPASSIGN(&=, std::bit_and)
1486 __SYCL_OPASSIGN(|=, std::bit_or)
1487 __SYCL_OPASSIGN(^=, std::bit_xor)
1488 __SYCL_OPASSIGN(>>=, RShift)
1489 __SYCL_OPASSIGN(<<=, LShift)
1490 #undef __SYCL_OPASSIGN
1493 #error "Undefine __SYCL_UOP macro"
1495 #define __SYCL_UOP(UOP, OPASSIGN) \
1496 SwizzleOp &operator UOP() { \
1497 *this OPASSIGN static_cast<DataT>(1); \
1500 vec_t operator UOP(int) { \
1501 vec_t Ret = *this; \
1502 *this OPASSIGN static_cast<DataT>(1); \
1510 template <typename T = DataT>
1511 friend typename std::enable_if_t<
1512 std::is_same_v<T, DataT> && std::is_integral_v<vec_data_t<T>>, vec_t>
1513 operator~(const SwizzleOp &Rhs) {
1518 friend vec_rel_t operator!(const SwizzleOp &Rhs) {
1523 friend vec_t operator+(const SwizzleOp &Rhs) {
1528 friend vec_t operator-(const SwizzleOp &Rhs) {
1537 #error "Undefine __SYCL_BINOP macro"
1539 #define __SYCL_BINOP(BINOP) \
1540 friend vec_t operator BINOP(const DataT &Lhs, const SwizzleOp &Rhs) { \
1542 return Lhs BINOP Tmp; \
1544 friend vec_t operator BINOP(const SwizzleOp &Lhs, const DataT &Rhs) { \
1546 return Tmp BINOP Rhs; \
1548 friend vec_t operator BINOP(const vec_t &Lhs, const SwizzleOp &Rhs) { \
1550 return Lhs BINOP Tmp; \
1552 friend vec_t operator BINOP(const SwizzleOp &Lhs, const vec_t &Rhs) { \
1554 return Tmp BINOP Rhs; \
1572 #ifdef __SYCL_RELLOGOP
1573 #error "Undefine __SYCL_RELLOGOP macro"
1575 #define __SYCL_RELLOGOP(RELLOGOP) \
1576 friend vec_rel_t operator RELLOGOP(const DataT &Lhs, const SwizzleOp &Rhs) { \
1578 return Lhs RELLOGOP Tmp; \
1580 friend vec_rel_t operator RELLOGOP(const SwizzleOp &Lhs, const DataT &Rhs) { \
1582 return Tmp RELLOGOP Rhs; \
1584 friend vec_rel_t operator RELLOGOP(const vec_t &Lhs, const SwizzleOp &Rhs) { \
1586 return Lhs RELLOGOP Tmp; \
1588 friend vec_rel_t operator RELLOGOP(const SwizzleOp &Lhs, const vec_t &Rhs) { \
1590 return Tmp RELLOGOP Rhs; \
1602 #undef __SYCL_RELLOGOP
1604 template <int IdxNum = getNumElements(),
1605 typename = EnableIfMultipleIndexes<IdxNum>>
1606 SwizzleOp &operator=(const vec<DataT, IdxNum> &Rhs) {
1607 std::array<int, IdxNum> Idxs{Indexes...};
1608 for (size_t I = 0; I < Idxs.size(); ++I) {
1609 m_Vector->setValue(Idxs[I], Rhs.getValue(I));
1614 template <int IdxNum = getNumElements(), typename = EnableIfOneIndex<IdxNum>>
1615 SwizzleOp &operator=(const DataT &Rhs) {
1616 std::array<int, IdxNum> Idxs{Indexes...};
1617 m_Vector->setValue(Idxs[0], Rhs);
1621 template <int IdxNum = getNumElements(),
1622 EnableIfMultipleIndexes<IdxNum, bool> = true>
1623 SwizzleOp &operator=(const DataT &Rhs) {
1624 std::array<int, IdxNum> Idxs{Indexes...};
1625 for (auto Idx : Idxs) {
1626 m_Vector->setValue(Idx, Rhs);
1631 template <int IdxNum = getNumElements(), typename = EnableIfOneIndex<IdxNum>>
1632 SwizzleOp &operator=(DataT &&Rhs) {
1633 std::array<int, IdxNum> Idxs{Indexes...};
1634 m_Vector->setValue(Idxs[0], Rhs);
1638 template <typename T, typename = EnableIfScalarType<T>>
1639 NewLHOp<GetScalarOp<T>, std::multiplies, Indexes...>
1640 operator*(const T &Rhs) const {
1641 return NewLHOp<GetScalarOp<T>, std::multiplies, Indexes...>(
1642 m_Vector, *this, GetScalarOp<T>(Rhs));
1645 template <typename RhsOperation,
1646 typename = EnableIfNoScalarType<RhsOperation>>
1647 NewLHOp<RhsOperation, std::multiplies, Indexes...>
1648 operator*(const RhsOperation &Rhs) const {
1649 return NewLHOp<RhsOperation, std::multiplies, Indexes...>(m_Vector, *this,
1653 template <typename T, typename = EnableIfScalarType<T>>
1654 NewLHOp<GetScalarOp<T>, std::plus, Indexes...> operator+(const T &Rhs) const {
1655 return NewLHOp<GetScalarOp<T>, std::plus, Indexes...>(m_Vector, *this,
1656 GetScalarOp<T>(Rhs));
1659 template <typename RhsOperation,
1660 typename = EnableIfNoScalarType<RhsOperation>>
1661 NewLHOp<RhsOperation, std::plus, Indexes...>
1662 operator+(const RhsOperation &Rhs) const {
1663 return NewLHOp<RhsOperation, std::plus, Indexes...>(m_Vector, *this, Rhs);
1666 template <typename T, typename = EnableIfScalarType<T>>
1667 NewLHOp<GetScalarOp<T>, std::minus, Indexes...>
1668 operator-(const T &Rhs) const {
1669 return NewLHOp<GetScalarOp<T>, std::minus, Indexes...>(m_Vector, *this,
1670 GetScalarOp<T>(Rhs));
1673 template <typename RhsOperation,
1674 typename = EnableIfNoScalarType<RhsOperation>>
1675 NewLHOp<RhsOperation, std::minus, Indexes...>
1676 operator-(const RhsOperation &Rhs) const {
1677 return NewLHOp<RhsOperation, std::minus, Indexes...>(m_Vector, *this, Rhs);
1680 template <typename T, typename = EnableIfScalarType<T>>
1681 NewLHOp<GetScalarOp<T>, std::divides, Indexes...>
1682 operator/(const T &Rhs) const {
1683 return NewLHOp<GetScalarOp<T>, std::divides, Indexes...>(
1684 m_Vector, *this, GetScalarOp<T>(Rhs));
1687 template <typename RhsOperation,
1688 typename = EnableIfNoScalarType<RhsOperation>>
1689 NewLHOp<RhsOperation, std::divides, Indexes...>
1690 operator/(const RhsOperation &Rhs) const {
1691 return NewLHOp<RhsOperation, std::divides, Indexes...>(m_Vector, *this,
1695 template <typename T, typename = EnableIfScalarType<T>>
1696 NewLHOp<GetScalarOp<T>, std::modulus, Indexes...>
1697 operator%(const T &Rhs) const {
1698 return NewLHOp<GetScalarOp<T>, std::modulus, Indexes...>(
1699 m_Vector, *this, GetScalarOp<T>(Rhs));
1702 template <typename RhsOperation,
1703 typename = EnableIfNoScalarType<RhsOperation>>
1704 NewLHOp<RhsOperation, std::modulus, Indexes...>
1705 operator%(const RhsOperation &Rhs) const {
1706 return NewLHOp<RhsOperation, std::modulus, Indexes...>(m_Vector, *this,
1710 template <typename T, typename = EnableIfScalarType<T>>
1711 NewLHOp<GetScalarOp<T>, std::bit_and, Indexes...>
1712 operator&(const T &Rhs) const {
1713 return NewLHOp<GetScalarOp<T>, std::bit_and, Indexes...>(
1714 m_Vector, *this, GetScalarOp<T>(Rhs));
1717 template <typename RhsOperation,
1718 typename = EnableIfNoScalarType<RhsOperation>>
1719 NewLHOp<RhsOperation, std::bit_and, Indexes...>
1720 operator&(const RhsOperation &Rhs) const {
1721 return NewLHOp<RhsOperation, std::bit_and, Indexes...>(m_Vector, *this,
1725 template <typename T, typename = EnableIfScalarType<T>>
1726 NewLHOp<GetScalarOp<T>, std::bit_or, Indexes...>
1727 operator|(const T &Rhs) const {
1728 return NewLHOp<GetScalarOp<T>, std::bit_or, Indexes...>(
1729 m_Vector, *this, GetScalarOp<T>(Rhs));
1732 template <typename RhsOperation,
1733 typename = EnableIfNoScalarType<RhsOperation>>
1734 NewLHOp<RhsOperation, std::bit_or, Indexes...>
1735 operator|(const RhsOperation &Rhs) const {
1736 return NewLHOp<RhsOperation, std::bit_or, Indexes...>(m_Vector, *this, Rhs);
1739 template <typename T, typename = EnableIfScalarType<T>>
1740 NewLHOp<GetScalarOp<T>, std::bit_xor, Indexes...>
1741 operator^(const T &Rhs) const {
1742 return NewLHOp<GetScalarOp<T>, std::bit_xor, Indexes...>(
1743 m_Vector, *this, GetScalarOp<T>(Rhs));
1746 template <typename RhsOperation,
1747 typename = EnableIfNoScalarType<RhsOperation>>
1748 NewLHOp<RhsOperation, std::bit_xor, Indexes...>
1749 operator^(const RhsOperation &Rhs) const {
1750 return NewLHOp<RhsOperation, std::bit_xor, Indexes...>(m_Vector, *this,
1754 template <typename T, typename = EnableIfScalarType<T>>
1755 NewLHOp<GetScalarOp<T>, RShift, Indexes...> operator>>(const T &Rhs) const {
1756 return NewLHOp<GetScalarOp<T>, RShift, Indexes...>(m_Vector, *this,
1757 GetScalarOp<T>(Rhs));
1760 template <typename RhsOperation,
1761 typename = EnableIfNoScalarType<RhsOperation>>
1762 NewLHOp<RhsOperation, RShift, Indexes...>
1763 operator>>(const RhsOperation &Rhs) const {
1764 return NewLHOp<RhsOperation, RShift, Indexes...>(m_Vector, *this, Rhs);
1767 template <typename T, typename = EnableIfScalarType<T>>
1768 NewLHOp<GetScalarOp<T>, LShift, Indexes...> operator<<(const T &Rhs) const {
1769 return NewLHOp<GetScalarOp<T>, LShift, Indexes...>(m_Vector, *this,
1770 GetScalarOp<T>(Rhs));
1773 template <typename RhsOperation,
1774 typename = EnableIfNoScalarType<RhsOperation>>
1775 NewLHOp<RhsOperation, LShift, Indexes...>
1776 operator<<(const RhsOperation &Rhs) const {
1777 return NewLHOp<RhsOperation, LShift, Indexes...>(m_Vector, *this, Rhs);
1781 typename T1, typename T2, typename T3, template <typename> class T4,
1783 typename = typename std::enable_if_t<sizeof...(T5) == getNumElements()>>
1784 SwizzleOp &operator=(const SwizzleOp<T1, T2, T3, T4, T5...> &Rhs) {
1785 std::array<int, getNumElements()> Idxs{Indexes...};
1786 for (size_t I = 0; I < Idxs.size(); ++I) {
1787 m_Vector->setValue(Idxs[I], Rhs.getValue(I));
1793 typename T1, typename T2, typename T3, template <typename> class T4,
1795 typename = typename std::enable_if_t<sizeof...(T5) == getNumElements()>>
1796 SwizzleOp &operator=(SwizzleOp<T1, T2, T3, T4, T5...> &&Rhs) {
1797 std::array<int, getNumElements()> Idxs{Indexes...};
1798 for (size_t I = 0; I < Idxs.size(); ++I) {
1799 m_Vector->setValue(Idxs[I], Rhs.getValue(I));
1804 template <typename T, typename = EnableIfScalarType<T>>
1805 NewRelOp<GetScalarOp<T>, EqualTo, Indexes...> operator==(const T &Rhs) const {
1806 return NewRelOp<GetScalarOp<T>, EqualTo, Indexes...>(NULL, *this,
1807 GetScalarOp<T>(Rhs));
1810 template <typename RhsOperation,
1811 typename = EnableIfNoScalarType<RhsOperation>>
1812 NewRelOp<RhsOperation, EqualTo, Indexes...>
1813 operator==(const RhsOperation &Rhs) const {
1814 return NewRelOp<RhsOperation, EqualTo, Indexes...>(NULL, *this, Rhs);
1817 template <typename T, typename = EnableIfScalarType<T>>
1818 NewRelOp<GetScalarOp<T>, NotEqualTo, Indexes...>
1819 operator!=(const T &Rhs) const {
1820 return NewRelOp<GetScalarOp<T>, NotEqualTo, Indexes...>(
1821 NULL, *this, GetScalarOp<T>(Rhs));
1824 template <typename RhsOperation,
1825 typename = EnableIfNoScalarType<RhsOperation>>
1826 NewRelOp<RhsOperation, NotEqualTo, Indexes...>
1827 operator!=(const RhsOperation &Rhs) const {
1828 return NewRelOp<RhsOperation, NotEqualTo, Indexes...>(NULL, *this, Rhs);
1831 template <typename T, typename = EnableIfScalarType<T>>
1832 NewRelOp<GetScalarOp<T>, GreaterEqualTo, Indexes...>
1833 operator>=(const T &Rhs) const {
1834 return NewRelOp<GetScalarOp<T>, GreaterEqualTo, Indexes...>(
1835 NULL, *this, GetScalarOp<T>(Rhs));
1838 template <typename RhsOperation,
1839 typename = EnableIfNoScalarType<RhsOperation>>
1840 NewRelOp<RhsOperation, GreaterEqualTo, Indexes...>
1841 operator>=(const RhsOperation &Rhs) const {
1842 return NewRelOp<RhsOperation, GreaterEqualTo, Indexes...>(NULL, *this, Rhs);
1845 template <typename T, typename = EnableIfScalarType<T>>
1846 NewRelOp<GetScalarOp<T>, LessEqualTo, Indexes...>
1847 operator<=(const T &Rhs) const {
1848 return NewRelOp<GetScalarOp<T>, LessEqualTo, Indexes...>(
1849 NULL, *this, GetScalarOp<T>(Rhs));
1852 template <typename RhsOperation,
1853 typename = EnableIfNoScalarType<RhsOperation>>
1854 NewRelOp<RhsOperation, LessEqualTo, Indexes...>
1855 operator<=(const RhsOperation &Rhs) const {
1856 return NewRelOp<RhsOperation, LessEqualTo, Indexes...>(NULL, *this, Rhs);
1859 template <typename T, typename = EnableIfScalarType<T>>
1860 NewRelOp<GetScalarOp<T>, GreaterThan, Indexes...>
1861 operator>(const T &Rhs) const {
1862 return NewRelOp<GetScalarOp<T>, GreaterThan, Indexes...>(
1863 NULL, *this, GetScalarOp<T>(Rhs));
1866 template <typename RhsOperation,
1867 typename = EnableIfNoScalarType<RhsOperation>>
1868 NewRelOp<RhsOperation, GreaterThan, Indexes...>
1869 operator>(const RhsOperation &Rhs) const {
1870 return NewRelOp<RhsOperation, GreaterThan, Indexes...>(NULL, *this, Rhs);
1873 template <typename T, typename = EnableIfScalarType<T>>
1874 NewRelOp<GetScalarOp<T>, LessThan, Indexes...> operator<(const T &Rhs) const {
1875 return NewRelOp<GetScalarOp<T>, LessThan, Indexes...>(NULL, *this,
1876 GetScalarOp<T>(Rhs));
1879 template <typename RhsOperation,
1880 typename = EnableIfNoScalarType<RhsOperation>>
1881 NewRelOp<RhsOperation, LessThan, Indexes...>
1882 operator<(const RhsOperation &Rhs) const {
1883 return NewRelOp<RhsOperation, LessThan, Indexes...>(NULL, *this, Rhs);
1886 template <typename T, typename = EnableIfScalarType<T>>
1887 NewRelOp<GetScalarOp<T>, LogicalAnd, Indexes...>
1888 operator&&(const T &Rhs) const {
1889 return NewRelOp<GetScalarOp<T>, LogicalAnd, Indexes...>(
1890 NULL, *this, GetScalarOp<T>(Rhs));
1893 template <typename RhsOperation,
1894 typename = EnableIfNoScalarType<RhsOperation>>
1895 NewRelOp<RhsOperation, LogicalAnd, Indexes...>
1896 operator&&(const RhsOperation &Rhs) const {
1897 return NewRelOp<RhsOperation, LogicalAnd, Indexes...>(NULL, *this, Rhs);
1900 template <typename T, typename = EnableIfScalarType<T>>
1901 NewRelOp<GetScalarOp<T>, LogicalOr, Indexes...>
1902 operator||(const T &Rhs) const {
1903 return NewRelOp<GetScalarOp<T>, LogicalOr, Indexes...>(NULL, *this,
1904 GetScalarOp<T>(Rhs));
1907 template <typename RhsOperation,
1908 typename = EnableIfNoScalarType<RhsOperation>>
1909 NewRelOp<RhsOperation, LogicalOr, Indexes...>
1910 operator||(const RhsOperation &Rhs) const {
1911 return NewRelOp<RhsOperation, LogicalOr, Indexes...>(NULL, *this, Rhs);
1921 template <int Index> struct Indexer {
1922 static constexpr int IDXs[sizeof...(Indexes)] = {Indexes...};
1923 static constexpr int value = IDXs[Index >= getNumElements() ? 0 : Index];
1927 #ifdef __SYCL_ACCESS_RETURN
1928 #error "Undefine __SYCL_ACCESS_RETURN macro"
1930 #define __SYCL_ACCESS_RETURN m_Vector
1931 #include "swizzles.def"
1932 #undef __SYCL_ACCESS_RETURN
1937 template <access::address_space Space, access::decorated DecorateAddress>
1938 void load(size_t offset, multi_ptr<DataT, Space, DecorateAddress> ptr) {
1940 Tmp.template load(offset, ptr);
1944 template <typename convertT, rounding_mode roundingMode>
1945 vec<convertT, sizeof...(Indexes)> convert() const {
1948 return Tmp.template convert<convertT, roundingMode>();
1951 template <typename asT> asT as() const {
1954 static_assert((sizeof(Tmp) == sizeof(asT)),
1955 "The new SYCL vec type must have the same storage size in "
1956 "bytes as this SYCL swizzled vec");
1958 detail::is_contained<asT, detail::gtl::vector_basic_list>::value ||
1959 detail::is_contained<asT, detail::gtl::vector_bool_list>::value,
1960 "asT must be SYCL vec of a different element type and "
1961 "number of elements specified by asT");
1962 return Tmp.template as<asT>();
1966 SwizzleOp(const SwizzleOp &Rhs)
1967 : m_Vector(Rhs.m_Vector), m_LeftOperation(Rhs.m_LeftOperation),
1968 m_RightOperation(Rhs.m_RightOperation) {}
1970 SwizzleOp(VecT *Vector, OperationLeftT LeftOperation,
1971 OperationRightT RightOperation)
1972 : m_Vector(Vector), m_LeftOperation(LeftOperation),
1973 m_RightOperation(RightOperation) {}
1975 SwizzleOp(VecT *Vector) : m_Vector(Vector) {}
1977 SwizzleOp(SwizzleOp &&Rhs)
1978 : m_Vector(Rhs.m_Vector), m_LeftOperation(std::move(Rhs.m_LeftOperation)),
1979 m_RightOperation(std::move(Rhs.m_RightOperation)) {}
1985 template <int IdxNum = getNumElements()>
1986 CommonDataT getValue(EnableIfOneIndex<IdxNum, size_t> Index) const {
1987 if (std::is_same_v<OperationCurrentT<DataT>, GetOp<DataT>>) {
1988 std::array<int, getNumElements()> Idxs{Indexes...};
1989 return m_Vector->getValue(Idxs[Index]);
1991 auto Op = OperationCurrentT<vec_data_t<CommonDataT>>();
1992 return vec_data<CommonDataT>::get(
1993 Op(vec_data<CommonDataT>::get(m_LeftOperation.getValue(Index)),
1994 vec_data<CommonDataT>::get(m_RightOperation.getValue(Index))));
1997 template <int IdxNum = getNumElements()>
1998 DataT getValue(EnableIfMultipleIndexes<IdxNum, size_t> Index) const {
1999 if (std::is_same_v<OperationCurrentT<DataT>, GetOp<DataT>>) {
2000 std::array<int, getNumElements()> Idxs{Indexes...};
2001 return m_Vector->getValue(Idxs[Index]);
2003 auto Op = OperationCurrentT<vec_data_t<DataT>>();
2004 return vec_data<DataT>::get(
2005 Op(vec_data<DataT>::get(m_LeftOperation.getValue(Index)),
2006 vec_data<DataT>::get(m_RightOperation.getValue(Index))));
2009 template <template <typename> class Operation, typename RhsOperation>
2010 void operatorHelper(const RhsOperation &Rhs) {
2011 Operation<vec_data_t<DataT>> Op;
2012 std::array<int, getNumElements()> Idxs{Indexes...};
2013 for (size_t I = 0; I < Idxs.size(); ++I) {
2014 DataT Res = vec_data<DataT>::get(
2015 Op(vec_data<DataT>::get(m_Vector->getValue(Idxs[I])),
2016 vec_data<DataT>::get(Rhs.getValue(I))));
2017 m_Vector->setValue(Idxs[I], Res);
2024 OperationLeftT m_LeftOperation;
2025 OperationRightT m_RightOperation;
2028 template <typename T1, int T2> friend class sycl::vec;
2030 template <typename T1, typename T2, typename T3, template <typename> class T4,
2032 friend class SwizzleOp;
2040 constexpr bool isValidVectorSize(int N) {
2041 return N == 2 || N == 3 || N == 4 || N == 8 || N == 16;
2043 template <typename T, int N, typename V> struct VecStorage {
2045 isValidVectorSize(N) || N == 1,
2046 "Incorrect number of elements for sycl::vec: only 1, 2, 3, 4, 8 "
2047 "or 16 are supported");
2048 static_assert(!std::is_same_v<V, void>, "Incorrect data type for sycl::vec");
2051 #ifdef __SYCL_DEVICE_ONLY__
2055 template <typename T, int N> struct VecStorageImpl {
2056 static constexpr size_t Num = (N == 3) ? 4 : N;
2057 static constexpr size_t Sz = Num * sizeof(T);
2059 typename std::conditional<Sz <= 64, T __attribute__((ext_vector_type(N))),
2060 std::array<T, Num>>::type;
2061 using VectorDataType = T __attribute__((ext_vector_type(N)));
2064 template <typename T, int N> struct VecStorageImpl {
2065 using DataType = std::array<T, (N == 3) ? 4 : N>;
2070 template <> struct VecStorage<bool, 1, void> {
2071 using DataType = bool;
2072 #ifdef __SYCL_DEVICE_ONLY__
2073 using VectorDataType = bool;
2079 struct VecStorage<bool, N, typename std::enable_if_t<isValidVectorSize(N)>> {
2081 typename VecStorageImpl<select_apply_cl_t<bool, std::int8_t, std::int16_t,
2082 std::int32_t, std::int64_t>,
2084 #ifdef __SYCL_DEVICE_ONLY__
2085 using VectorDataType =
2086 typename VecStorageImpl<select_apply_cl_t<bool, std::int8_t, std::int16_t,
2087 std::int32_t, std::int64_t>,
2092 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
2095 template <> struct VecStorage<std::byte, 1, void> {
2096 using DataType = std::int8_t;
2097 #ifdef __SYCL_DEVICE_ONLY__
2098 using VectorDataType = std::int8_t;
2104 template <typename T>
2105 struct VecStorage<T, 1, typename std::enable_if_t<is_sigeninteger_v<T>>> {
2107 #ifdef __SYCL_DEVICE_ONLY__
2108 using VectorDataType = DataType;
2113 template <typename T>
2114 struct VecStorage<T, 1, typename std::enable_if_t<is_sugeninteger_v<T>>> {
2116 #ifdef __SYCL_DEVICE_ONLY__
2117 using VectorDataType = DataType;
2122 template <typename T>
2125 typename std::enable_if_t<!is_half_or_bf16_v<T> && is_sgenfloat_v<T>>> {
2127 #ifdef __SYCL_DEVICE_ONLY__
2128 using VectorDataType = DataType;
2133 template <typename T, int N>
2136 typename std::enable_if_t<isValidVectorSize(N) &&
2137 (is_sgeninteger_v<T> ||
2138 (is_sgenfloat_v<T> && !is_half_or_bf16_v<T>))>> {
2140 typename VecStorageImpl<typename VecStorage<T, 1>::DataType, N>::DataType;
2141 #ifdef __SYCL_DEVICE_ONLY__
2142 using VectorDataType =
2143 typename VecStorageImpl<typename VecStorage<T, 1>::DataType,
2149 template <> struct VecStorage<half, 1, void> {
2150 using DataType = sycl::detail::half_impl::StorageT;
2151 #ifdef __SYCL_DEVICE_ONLY__
2152 using VectorDataType = sycl::detail::half_impl::StorageT;
2157 #if defined(__SYCL_DEVICE_ONLY__)
2158 #define __SYCL_DEFINE_HALF_VECSTORAGE(Num) \
2159 template <> struct VecStorage<half, Num, void> { \
2160 using DataType = sycl::detail::half_impl::Vec##Num##StorageT; \
2161 using VectorDataType = sycl::detail::half_impl::Vec##Num##StorageT; \
2164 #define __SYCL_DEFINE_HALF_VECSTORAGE(Num) \
2165 template <> struct VecStorage<half, Num, void> { \
2166 using DataType = sycl::detail::half_impl::Vec##Num##StorageT; \
2170 __SYCL_DEFINE_HALF_VECSTORAGE(2)
2171 __SYCL_DEFINE_HALF_VECSTORAGE(3)
2172 __SYCL_DEFINE_HALF_VECSTORAGE(4)
2173 __SYCL_DEFINE_HALF_VECSTORAGE(8)
2174 __SYCL_DEFINE_HALF_VECSTORAGE(16)
2175 #undef __SYCL_DEFINE_HALF_VECSTORAGE
2178 template <> struct VecStorage<sycl::ext::oneapi::bfloat16, 1, void> {
2179 using DataType = sycl::ext::oneapi::detail::Bfloat16StorageT;
2181 using VectorDataType = sycl::ext::oneapi::detail::Bfloat16StorageT;
2184 #define __SYCL_DEFINE_BF16_VECSTORAGE(Num) \
2185 template <> struct VecStorage<sycl::ext::oneapi::bfloat16, Num, void> { \
2186 using DataType = sycl::ext::oneapi::detail::bf16::Vec##Num##StorageT; \
2187 using VectorDataType = \
2188 sycl::ext::oneapi::detail::bf16::Vec##Num##StorageT; \
2190 __SYCL_DEFINE_BF16_VECSTORAGE(2)
2191 __SYCL_DEFINE_BF16_VECSTORAGE(3)
2192 __SYCL_DEFINE_BF16_VECSTORAGE(4)
2193 __SYCL_DEFINE_BF16_VECSTORAGE(8)
2194 __SYCL_DEFINE_BF16_VECSTORAGE(16)
2195 #undef __SYCL_DEFINE_BF16_VECSTORAGE
2201 #define SYCL_DEVICE_COPYABLE 1
2210 template <typename T> struct is_device_copyable;
2213 template <typename T, typename = void>
2214 struct is_device_copyable_impl : std::is_trivially_copyable<T> {};
2216 template <typename T>
2217 struct is_device_copyable_impl<
2218 T, std::enable_if_t<!std::is_same_v<T, std::remove_cv_t<T>>>>
2221 : is_device_copyable<std::remove_cv_t<T>> {};
2224 template <typename T>
2225 struct is_device_copyable : detail::is_device_copyable_impl<T> {};
2228 template <typename T>
2229 struct is_device_copyable<std::array<T, 0>> : std::true_type {};
2232 template <typename T, std::size_t N>
2233 struct is_device_copyable<std::array<T, N>> : is_device_copyable<T> {};
2236 template <typename T>
2237 struct is_device_copyable<std::optional<T>> : is_device_copyable<T> {};
2241 template <typename T1, typename T2>
2242 struct is_device_copyable<std::pair<T1, T2>>
2243 : std::bool_constant<is_device_copyable<T1>::value &&
2244 is_device_copyable<T2>::value> {};
2248 template <typename... Ts>
2249 struct is_device_copyable<std::tuple<Ts...>>
2250 : std::bool_constant<(... && is_device_copyable<Ts>::value)> {};
2254 template <typename... Ts>
2255 struct is_device_copyable<std::variant<Ts...>>
2256 : std::bool_constant<(... && is_device_copyable<Ts>::value)> {};
2259 template <typename T, std::size_t N>
2260 struct is_device_copyable<sycl::marray<T, N>> : is_device_copyable<T> {};
2263 template <typename T, std::size_t N>
2264 struct is_device_copyable<T[N]> : is_device_copyable<T> {};
2266 template <typename T>
2267 inline constexpr bool is_device_copyable_v = is_device_copyable<T>::value;
2270 template <typename T, typename = void>
2271 struct IsDeprecatedDeviceCopyable : std::false_type {};
2275 template <typename T>
2276 struct __SYCL2020_DEPRECATED("This type isn't device copyable in SYCL 2020")
2277 IsDeprecatedDeviceCopyable<
2278 T, std::enable_if_t<std::is_trivially_copy_constructible_v<T> &&
2279 std::is_trivially_destructible_v<T> &&
2280 !is_device_copyable_v<T>>> : std::true_type {};
2282 template <typename T, int N>
2283 struct __SYCL2020_DEPRECATED("This type isn't device copyable in SYCL 2020")
2284 IsDeprecatedDeviceCopyable<T[N]> : IsDeprecatedDeviceCopyable<T> {};
2286 #ifdef __SYCL_DEVICE_ONLY__
2289 template <typename T, unsigned NumFieldsToCheck>
2290 struct CheckFieldsAreDeviceCopyable
2291 : CheckFieldsAreDeviceCopyable<T, NumFieldsToCheck - 1> {
2292 using FieldT = decltype(__builtin_field_type(T, NumFieldsToCheck - 1));
2293 static_assert(is_device_copyable_v<FieldT> ||
2294 detail::IsDeprecatedDeviceCopyable<FieldT>::value,
2295 "The specified type is not device copyable");
2298 template <typename T> struct CheckFieldsAreDeviceCopyable<T, 0> {};
2302 template <typename T, unsigned NumBasesToCheck>
2303 struct CheckBasesAreDeviceCopyable
2304 : CheckBasesAreDeviceCopyable<T, NumBasesToCheck - 1> {
2305 using BaseT = decltype(__builtin_base_type(T, NumBasesToCheck - 1));
2306 static_assert(is_device_copyable_v<BaseT> ||
2307 detail::IsDeprecatedDeviceCopyable<BaseT>::value,
2308 "The specified type is not device copyable");
2311 template <typename T> struct CheckBasesAreDeviceCopyable<T, 0> {};
2324 template <typename FuncT>
2325 struct CheckDeviceCopyable
2326 : CheckFieldsAreDeviceCopyable<FuncT, __builtin_num_fields(FuncT)>,
2327 CheckBasesAreDeviceCopyable<FuncT, __builtin_num_bases(FuncT)> {};
2331 template <typename TransformedArgType, int Dims, typename KernelType>
2332 struct CheckDeviceCopyable<
2333 RoundedRangeKernel<TransformedArgType, Dims, KernelType>>
2334 : CheckDeviceCopyable<KernelType> {};
2336 template <typename TransformedArgType, int Dims, typename KernelType>
2337 struct CheckDeviceCopyable<
2338 RoundedRangeKernelWithKH<TransformedArgType, Dims, KernelType>>
2339 : CheckDeviceCopyable<KernelType> {};
DataT operator()(DataT, DataT)
DataT getValue(size_t) const
DataT getValue(size_t) const
Provides a cross-patform vector class template that works efficiently on SYCL devices as well as in h...
detail::host_half_impl::half StorageT
std::conditional_t< sizeof(_IN)==1, T8, std::conditional_t< sizeof(_IN)==2, T16, std::conditional_t< sizeof(_IN)==4, T32, T64 > >> select_apply_cl_t
typename std::conditional_t< sizeof(DataT)==sizeof(opencl::cl_char), opencl::cl_char, typename std::conditional_t< sizeof(DataT)==sizeof(opencl::cl_short), opencl::cl_short, typename std::conditional_t< sizeof(DataT)==sizeof(opencl::cl_int), opencl::cl_int, typename std::conditional_t< sizeof(DataT)==sizeof(opencl::cl_long), opencl::cl_long, bool > >> > rel_t
conditional< sizeof(long)==8, long, long long >::type int64_t
constexpr size_t MaxVecAlignment
uint16_t Bfloat16StorageT
typename detail::vec_helper< T >::RetType vec_data_t
detail::vec_helper< T > vec_data
constexpr rel_t< T > operator()(const T &Lhs, const T &Rhs) const
constexpr rel_t< T > operator()(const T &Lhs, const T &Rhs) const
constexpr rel_t< T > operator()(const T &Lhs, const T &Rhs) const
constexpr T operator()(const T &Lhs, const T &Rhs) const
constexpr rel_t< T > operator()(const T &Lhs, const T &Rhs) const
constexpr rel_t< T > operator()(const T &Lhs, const T &Rhs) const
constexpr rel_t< T > operator()(const T &Lhs, const T &Rhs) const
constexpr rel_t< T > operator()(const T &Lhs, const T &Rhs) const
constexpr rel_t< T > operator()(const T &Lhs, const T &Rhs) const
constexpr T operator()(const T &Lhs, const T &Rhs) const
static constexpr RetType set(bool value)
select_apply_cl_t< bool, std::int8_t, std::int16_t, std::int32_t, std::int64_t > RetType
static constexpr RetType get(bool value)
static constexpr RetType get(std::byte value)
static constexpr RetType set(std::byte value)
static constexpr std::byte get(std::uint8_t value)
static constexpr std::byte set(std::uint8_t value)
static constexpr RetType get(BFloat16StorageT value)
static constexpr BFloat16StorageT set(RetType value)
static constexpr RetType get(RetType value)
sycl::ext::oneapi::detail::Bfloat16StorageT BFloat16StorageT
static constexpr RetType set(T value)
static constexpr RetType get(T value)
Implementation of vec::convert.