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"
51 #include <type_traits>
59 inline namespace _V1 {
62 static constexpr
int x = 0;
63 static constexpr
int y = 1;
64 static constexpr
int z = 2;
65 static constexpr
int w = 3;
66 static constexpr
int r = 0;
67 static constexpr
int g = 1;
68 static constexpr
int b = 2;
69 static constexpr
int a = 3;
70 static constexpr
int s0 = 0;
71 static constexpr
int s1 = 1;
72 static constexpr
int s2 = 2;
73 static constexpr
int s3 = 3;
74 static constexpr
int s4 = 4;
75 static constexpr
int s5 = 5;
76 static constexpr
int s6 = 6;
77 static constexpr
int s7 = 7;
78 static constexpr
int s8 = 8;
79 static constexpr
int s9 = 9;
80 static constexpr
int sA = 10;
81 static constexpr
int sB = 11;
82 static constexpr
int sC = 12;
83 static constexpr
int sD = 13;
84 static constexpr
int sE = 14;
85 static constexpr
int sF = 15;
89 template <
typename VecT,
typename OperationLeftT,
typename OperationRightT,
90 template <
typename>
class OperationCurrentT,
int... Indexes>
95 template <
typename T>
class GetOp {
116 template <
typename Vec,
typename T,
int N,
typename =
void>
119 template <
typename Vec,
typename T,
int N>
121 operator T()
const {
return (*
static_cast<const Vec *
>(
this))[0]; }
129 template <
typename DataT,
int NumElements>
133 DataT, NumElements> {
135 static_assert(NumElements == 1 || NumElements == 2 || NumElements == 3 ||
136 NumElements == 4 || NumElements == 8 || NumElements == 16,
137 "Invalid number of elements for sycl::vec: only 1, 2, 3, 4, 8 "
138 "or 16 are supported");
139 static_assert(
sizeof(
bool) ==
sizeof(uint8_t),
"bool size is not 1 byte");
143 static constexpr
size_t AdjustedNum = (NumElements == 3) ? 4 : NumElements;
147 using DataType = std::array<DataT, AdjustedNum>;
149 #ifdef __SYCL_DEVICE_ONLY__
152 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
168 typename std::conditional_t<NumElements == 1, element_type_for_vector_t,
170 ext_vector_type(NumElements)))>;
175 static constexpr
int getNumElements() {
return NumElements; }
178 template <
int Counter,
int MaxValue,
class...>
179 struct SizeChecker : std::conditional_t<Counter == MaxValue, std::true_type,
182 template <
int Counter,
int MaxValue,
typename DataT_,
class... tail>
183 struct SizeChecker<Counter, MaxValue, DataT_, tail...>
184 : std::conditional_t<Counter + 1 <= MaxValue,
185 SizeChecker<Counter + 1, MaxValue, tail...>,
189 template <typename DataT_, typename T> class FlattenVecArg {
190 template <std::size_t... Is>
191 static constexpr auto helper(const T &V, std::index_sequence<Is...>) {
196 if constexpr (detail::is_swizzle_v<T>)
197 return std::array{static_cast<DataT_>(V.getValue(Is))...};
199 return std::array{static_cast<DataT_>(V[Is])...};
203 constexpr auto operator()(const T &A) const {
204 if constexpr (detail::is_vec_or_swizzle_v<T>) {
205 return helper(A, std::make_index_sequence<T ::size()>());
207 return std::array{static_cast<DataT_>(A)};
213 template <typename DataT_, typename... ArgTN>
214 using VecArgArrayCreator =
215 detail::ArrayCreator<DataT_, FlattenVecArg, ArgTN...>;
217 template <int... Indexes>
219 detail::SwizzleOp<vec, detail::GetOp<DataT>, detail::GetOp<DataT>,
220 detail::GetOp, Indexes...>;
222 template <int... Indexes>
224 detail::SwizzleOp<const vec, detail::GetOp<DataT>, detail::GetOp<DataT>,
225 detail::GetOp, Indexes...>;
228 template <typename CtorArgTy>
229 static constexpr bool AllowArgTypeInVariadicCtor = []() constexpr {
231 if constexpr (detail::is_vec_or_swizzle_v<CtorArgTy>) {
232 if constexpr (CtorArgTy::size() == 1)
233 return std::is_convertible_v<typename CtorArgTy::element_type, DataT>;
235 return std::is_same_v<typename CtorArgTy::element_type, DataT>;
237 return std::is_convertible_v<CtorArgTy, DataT>;
241 template <typename T> static constexpr int num_elements() {
242 if constexpr (detail::is_vec_or_swizzle_v<T>)
249 using rel_t = detail::select_cl_scalar_integral_signed_t<DataT>;
254 using element_type = DataT;
255 using value_type = DataT;
259 constexpr vec(const vec &Rhs) = default;
260 constexpr vec(vec &&Rhs) = default;
264 template <size_t... Is>
265 constexpr vec(const std::array<DataT, NumElements> &Arr,
266 std::index_sequence<Is...>)
267 : m_Data{Arr[Is]...} {}
270 explicit constexpr vec(const DataT &arg)
271 : vec{detail::RepeatValue<NumElements>(arg),
272 std::make_index_sequence<NumElements>()} {}
276 template <typename... argTN,
277 typename = std::enable_if_t<
278 ((AllowArgTypeInVariadicCtor<argTN> && ...)) &&
279 ((num_elements<argTN>() + ...)) == NumElements>>
280 constexpr vec(const argTN &...args)
281 : vec{VecArgArrayCreator<DataT, argTN...>::Create(args...),
282 std::make_index_sequence<NumElements>()} {}
285 constexpr vec &operator=(const vec &Rhs) = default;
290 template <typename Ty = DataT>
291 typename std::enable_if_t<
292 std::is_fundamental_v<Ty> ||
293 detail::is_half_or_bf16_v<typename std::remove_const_t<Ty>>,
295 operator=(const DataT &Rhs) {
301 template <typename Ty = DataT>
302 typename std::enable_if_t<
303 !std::is_same_v<Ty, rel_t> && std::is_convertible_v<Ty, rel_t>, vec &>
304 operator=(const vec<rel_t, NumElements> &Rhs) {
305 *this = Rhs.template as<vec>();
309 #ifdef __SYCL_DEVICE_ONLY__
315 typename vector_t_ = vector_t,
316 typename = typename std::enable_if_t<std::is_same_v<vector_t_, vector_t>>>
317 constexpr vec(vector_t_ openclVector) {
318 m_Data = sycl::bit_cast<DataType>(openclVector);
326 operator vector_t() const { return sycl::bit_cast<vector_t>(m_Data); }
329 __SYCL2020_DEPRECATED("get_count() is deprecated, please use size() instead")
330 static constexpr size_t get_count() { return size(); }
331 static constexpr size_t size() noexcept { return NumElements; }
332 __SYCL2020_DEPRECATED(
333 "get_size() is deprecated, please use byte_size() instead")
334 static constexpr size_t get_size() { return byte_size(); }
335 static constexpr size_t byte_size() noexcept { return sizeof(m_Data); }
340 constexpr auto getValue(int Index) const {
342 typename std::conditional_t<detail::is_byte_v<DataT>, int8_t,
343 #ifdef __SYCL_DEVICE_ONLY__
344 element_type_for_vector_t
350 #ifdef __SYCL_DEVICE_ONLY__
351 if constexpr (std::is_same_v<DataT, sycl::ext::oneapi::bfloat16>)
352 return sycl::bit_cast<RetType>(m_Data[Index]);
355 return static_cast<RetType>(m_Data[Index]);
360 template <typename convertT,
361 rounding_mode roundingMode = rounding_mode::automatic>
362 vec<convertT, NumElements> convert() const;
364 template <typename asT> asT as() const { return sycl::bit_cast<asT>(*this); }
366 template <int... SwizzleIndexes> Swizzle<SwizzleIndexes...> swizzle() {
370 template <int... SwizzleIndexes>
371 ConstSwizzle<SwizzleIndexes...> swizzle() const {
375 const DataT &operator[](int i) const { return m_Data[i]; }
377 DataT &operator[](int i) { return m_Data[i]; }
386 template <int Index> struct Indexer {
387 static constexpr int value = Index;
391 #ifdef __SYCL_ACCESS_RETURN
392 #error "Undefine __SYCL_ACCESS_RETURN macro"
394 #define __SYCL_ACCESS_RETURN this
395 #include "swizzles.def"
396 #undef __SYCL_ACCESS_RETURN
399 template <access::address_space Space, access::decorated DecorateAddress>
400 void load(size_t Offset, multi_ptr<const DataT, Space, DecorateAddress> Ptr) {
401 for (int I = 0; I < NumElements; I++) {
402 m_Data[I] = *multi_ptr<const DataT, Space, DecorateAddress>(
403 Ptr + Offset * NumElements + I);
406 template <access::address_space Space, access::decorated DecorateAddress>
407 void load(size_t Offset, multi_ptr<DataT, Space, DecorateAddress> Ptr) {
408 multi_ptr<const DataT, Space, DecorateAddress> ConstPtr(Ptr);
409 load(Offset, ConstPtr);
411 template <int Dimensions, access::mode Mode,
412 access::placeholder IsPlaceholder, access::target Target,
413 typename PropertyListT>
416 accessor<DataT, Dimensions, Mode, Target, IsPlaceholder, PropertyListT>
418 multi_ptr<const DataT, detail::TargetToAS<Target>::AS,
419 access::decorated::yes>
421 load(Offset, MultiPtr);
423 void load(size_t Offset, const DataT *Ptr) {
424 for (int I = 0; I < NumElements; ++I)
425 m_Data[I] = Ptr[Offset * NumElements + I];
428 template <access::address_space Space, access::decorated DecorateAddress>
429 void store(size_t Offset,
430 multi_ptr<DataT, Space, DecorateAddress> Ptr) const {
431 for (int I = 0; I < NumElements; I++) {
432 *multi_ptr<DataT, Space, DecorateAddress>(Ptr + Offset * NumElements +
436 template <int Dimensions, access::mode Mode,
437 access::placeholder IsPlaceholder, access::target Target,
438 typename PropertyListT>
441 accessor<DataT, Dimensions, Mode, Target, IsPlaceholder, PropertyListT>
443 multi_ptr<DataT, detail::TargetToAS<Target>::AS, access::decorated::yes>
445 store(Offset, MultiPtr);
447 void store(size_t Offset, DataT *Ptr) const {
448 for (int I = 0; I < NumElements; ++I)
449 Ptr[Offset * NumElements + I] = m_Data[I];
458 static constexpr int alignment = (std::min)((size_t)64, sizeof(DataType));
459 alignas(alignment) DataType m_Data;
462 template <typename T1, typename T2, typename T3, template <typename> class T4,
464 friend class detail::SwizzleOp;
465 template <typename T1, int T2> friend class __SYCL_EBO vec;
467 template <typename T1, int T2> friend class detail::vec_arith;
468 template <typename T1, int T2> friend class detail::vec_arith_common;
472 #ifdef __cpp_deduction_guides
474 template <class T, class... U,
475 class = std::enable_if_t<(std::is_same_v<T, U> && ...)>>
476 vec(T, U...) -> vec<T, sizeof...(U) + 1>;
484 template <typename T> class GetScalarOp {
487 GetScalarOp(DataT Data) : m_Data(Data) {}
488 DataT getValue(size_t) const { return m_Data; }
493 template <typename T>
494 using rel_t = detail::select_cl_scalar_integral_signed_t<T>;
496 template <typename T> struct EqualTo {
497 constexpr rel_t<T> operator()(const T &Lhs, const T &Rhs) const {
498 return (Lhs == Rhs) ? -1 : 0;
502 template <typename T> struct NotEqualTo {
503 constexpr rel_t<T> operator()(const T &Lhs, const T &Rhs) const {
504 return (Lhs != Rhs) ? -1 : 0;
508 template <typename T> struct GreaterEqualTo {
509 constexpr rel_t<T> operator()(const T &Lhs, const T &Rhs) const {
510 return (Lhs >= Rhs) ? -1 : 0;
514 template <typename T> struct LessEqualTo {
515 constexpr rel_t<T> operator()(const T &Lhs, const T &Rhs) const {
516 return (Lhs <= Rhs) ? -1 : 0;
520 template <typename T> struct GreaterThan {
521 constexpr rel_t<T> operator()(const T &Lhs, const T &Rhs) const {
522 return (Lhs > Rhs) ? -1 : 0;
526 template <typename T> struct LessThan {
527 constexpr rel_t<T> operator()(const T &Lhs, const T &Rhs) const {
528 return (Lhs < Rhs) ? -1 : 0;
532 template <typename T> struct LogicalAnd {
533 constexpr rel_t<T> operator()(const T &Lhs, const T &Rhs) const {
534 return (Lhs && Rhs) ? -1 : 0;
538 template <typename T> struct LogicalOr {
539 constexpr rel_t<T> operator()(const T &Lhs, const T &Rhs) const {
540 return (Lhs || Rhs) ? -1 : 0;
544 template <typename T> struct RShift {
545 constexpr T operator()(const T &Lhs, const T &Rhs) const {
550 template <typename T> struct LShift {
551 constexpr T operator()(const T &Lhs, const T &Rhs) const {
559 template <typename VecT, typename OperationLeftT, typename OperationRightT,
560 template <typename> class OperationCurrentT, int... Indexes>
562 using DataT = typename VecT::element_type;
589 using OpLeftDataT = typename OperationLeftT::DataT;
590 using OpRightDataT = typename OperationRightT::DataT;
591 using CommonDataT = std::conditional_t<
592 sizeof(DataT) >= sizeof(std::common_type_t<OpLeftDataT, OpRightDataT>),
593 DataT, std::common_type_t<OpLeftDataT, OpRightDataT>>;
594 static constexpr int getNumElements() { return sizeof...(Indexes); }
596 using rel_t = detail::rel_t<DataT>;
597 using vec_t = vec<DataT, sizeof...(Indexes)>;
598 using vec_rel_t = vec<rel_t, sizeof...(Indexes)>;
600 template <typename OperationRightT_,
601 template <typename> class OperationCurrentT_, int... Idx_>
602 using NewLHOp = SwizzleOp<VecT,
603 SwizzleOp<VecT, OperationLeftT, OperationRightT,
604 OperationCurrentT, Indexes...>,
605 OperationRightT_, OperationCurrentT_, Idx_...>;
607 template <typename OperationRightT_,
608 template <typename> class OperationCurrentT_, int... Idx_>
609 using NewRelOp = SwizzleOp<vec<rel_t, VecT::getNumElements()>,
610 SwizzleOp<VecT, OperationLeftT, OperationRightT,
611 OperationCurrentT, Indexes...>,
612 OperationRightT_, OperationCurrentT_, Idx_...>;
614 template <typename OperationLeftT_,
615 template <typename> class OperationCurrentT_, int... Idx_>
616 using NewRHOp = SwizzleOp<VecT, OperationLeftT_,
617 SwizzleOp<VecT, OperationLeftT, OperationRightT,
618 OperationCurrentT, Indexes...>,
619 OperationCurrentT_, Idx_...>;
621 template <int IdxNum, typename T = void>
622 using EnableIfOneIndex = typename std::enable_if_t<
623 1 == IdxNum && SwizzleOp::getNumElements() == IdxNum, T>;
625 template <int IdxNum, typename T = void>
626 using EnableIfMultipleIndexes = typename std::enable_if_t<
627 1 != IdxNum && SwizzleOp::getNumElements() == IdxNum, T>;
629 template <typename T>
630 using EnableIfScalarType = typename std::enable_if_t<
631 std::is_convertible_v<DataT, T> &&
632 (std::is_fundamental_v<T> ||
633 detail::is_half_or_bf16_v<typename std::remove_const_t<T>>)>;
635 template <typename T>
636 using EnableIfNoScalarType = typename std::enable_if_t<
637 !std::is_convertible_v<DataT, T> ||
638 !(std::is_fundamental_v<T> ||
639 detail::is_half_or_bf16_v<typename std::remove_const_t<T>>)>;
641 template <int... Indices>
643 SwizzleOp<VecT, GetOp<DataT>, GetOp<DataT>, GetOp, Indices...>;
645 template <int... Indices>
647 SwizzleOp<const VecT, GetOp<DataT>, GetOp<DataT>, GetOp, Indices...>;
650 using element_type = DataT;
651 using value_type = DataT;
653 #ifdef __SYCL_DEVICE_ONLY__
654 using vector_t = typename vec_t::vector_t;
657 const DataT &operator[](int i) const {
658 std::array<int, getNumElements()> Idxs{Indexes...};
659 return (*m_Vector)[Idxs[i]];
662 template <typename _T = VecT>
663 std::enable_if_t<!std::is_const_v<_T>, DataT> &operator[](int i) {
664 std::array<int, getNumElements()> Idxs{Indexes...};
665 return (*m_Vector)[Idxs[i]];
668 __SYCL2020_DEPRECATED("get_count() is deprecated, please use size() instead")
669 size_t get_count() const { return size(); }
670 static constexpr size_t size() noexcept { return getNumElements(); }
672 template <int Num = getNumElements()>
673 __SYCL2020_DEPRECATED(
674 "get_size() is deprecated, please use byte_size() instead")
675 size_t get_size() const {
676 return byte_size<Num>();
679 template <int Num = getNumElements()> size_t byte_size() const noexcept {
680 return sizeof(DataT) * (Num == 3 ? 4 : Num);
683 template <typename T, int IdxNum = getNumElements(),
684 typename = EnableIfOneIndex<IdxNum>,
685 typename = EnableIfScalarType<T>>
690 template <typename T, typename = EnableIfScalarType<T>>
691 friend NewRHOp<GetScalarOp<T>, std::multiplies, Indexes...>
692 operator*(const T &Lhs, const SwizzleOp &Rhs) {
693 return NewRHOp<GetScalarOp<T>, std::multiplies, Indexes...>(
694 Rhs.m_Vector, GetScalarOp<T>(Lhs), Rhs);
697 template <typename T, typename = EnableIfScalarType<T>>
698 friend NewRHOp<GetScalarOp<T>, std::plus, Indexes...>
699 operator+(const T &Lhs, const SwizzleOp &Rhs) {
700 return NewRHOp<GetScalarOp<T>, std::plus, Indexes...>(
701 Rhs.m_Vector, GetScalarOp<T>(Lhs), Rhs);
704 template <typename T, typename = EnableIfScalarType<T>>
705 friend NewRHOp<GetScalarOp<T>, std::divides, Indexes...>
706 operator/(const T &Lhs, const SwizzleOp &Rhs) {
707 return NewRHOp<GetScalarOp<T>, std::divides, Indexes...>(
708 Rhs.m_Vector, GetScalarOp<T>(Lhs), Rhs);
712 #ifdef __SYCL_OPASSIGN
713 #error "Undefine __SYCL_OPASSIGN macro."
715 #define __SYCL_OPASSIGN(OPASSIGN, OP) \
716 friend const SwizzleOp &operator OPASSIGN(const SwizzleOp & Lhs, \
717 const DataT & Rhs) { \
718 Lhs.operatorHelper<OP>(vec_t(Rhs)); \
721 template <typename RhsOperation> \
722 friend const SwizzleOp &operator OPASSIGN(const SwizzleOp & Lhs, \
723 const RhsOperation & Rhs) { \
724 Lhs.operatorHelper<OP>(Rhs); \
727 friend const SwizzleOp &operator OPASSIGN(const SwizzleOp & Lhs, \
728 const vec_t & Rhs) { \
729 Lhs.operatorHelper<OP>(Rhs); \
733 __SYCL_OPASSIGN(+=, std::plus)
734 __SYCL_OPASSIGN(-=, std::minus)
735 __SYCL_OPASSIGN(*=, std::multiplies)
736 __SYCL_OPASSIGN(/=, std::divides)
737 __SYCL_OPASSIGN(%=, std::modulus)
738 __SYCL_OPASSIGN(&=, std::bit_and)
739 __SYCL_OPASSIGN(|=, std::bit_or)
740 __SYCL_OPASSIGN(^=, std::bit_xor)
741 __SYCL_OPASSIGN(>>=, RShift)
742 __SYCL_OPASSIGN(<<=, LShift)
743 #undef __SYCL_OPASSIGN
746 #error "Undefine __SYCL_UOP macro"
748 #define __SYCL_UOP(UOP, OPASSIGN) \
749 friend const SwizzleOp &operator UOP(const SwizzleOp & sv) { \
750 sv OPASSIGN static_cast<DataT>(1); \
753 friend vec_t operator UOP(const SwizzleOp &sv, int) { \
755 sv OPASSIGN static_cast<DataT>(1); \
763 template <typename T = DataT>
764 friend typename std::enable_if_t<
765 std::is_same_v<T, DataT> && !detail::is_vgenfloat_v<T>, vec_t>
766 operator~(const SwizzleOp &Rhs) {
771 friend vec_rel_t operator!(const SwizzleOp &Rhs) {
776 friend vec_t operator+(const SwizzleOp &Rhs) {
781 friend vec_t operator-(const SwizzleOp &Rhs) {
790 #error "Undefine __SYCL_BINOP macro"
792 #define __SYCL_BINOP(BINOP, COND) \
793 template <typename T = DataT> \
794 friend std::enable_if_t<(COND), vec_t> operator BINOP( \
795 const DataT & Lhs, const SwizzleOp & Rhs) { \
797 return Lhs BINOP Tmp; \
799 template <typename T = DataT> \
800 friend std::enable_if_t<(COND), vec_t> operator BINOP(const SwizzleOp & Lhs, \
801 const DataT & Rhs) { \
803 return Tmp BINOP Rhs; \
805 template <typename T = DataT> \
806 friend std::enable_if_t<(COND), vec_t> operator BINOP( \
807 const vec_t & Lhs, const SwizzleOp & Rhs) { \
809 return Lhs BINOP Tmp; \
811 template <typename T = DataT> \
812 friend std::enable_if_t<(COND), vec_t> operator BINOP(const SwizzleOp & Lhs, \
813 const vec_t & Rhs) { \
815 return Tmp BINOP Rhs; \
818 __SYCL_BINOP(+, (!detail::is_byte_v<T>))
819 __SYCL_BINOP(-, (!detail::is_byte_v<T>))
820 __SYCL_BINOP(*, (!detail::is_byte_v<T>))
821 __SYCL_BINOP(/, (!detail::is_byte_v<T>))
822 __SYCL_BINOP(%, (!detail::is_byte_v<T>))
823 __SYCL_BINOP(&, true)
824 __SYCL_BINOP(|, true)
825 __SYCL_BINOP(^, true)
827 __SYCL_BINOP(>>, (!detail::is_byte_v<T>))
828 __SYCL_BINOP(<<, (!detail::is_byte_v<T>))
830 template <typename T = DataT>
831 friend std::enable_if_t<detail::is_byte_v<T>, vec_t>
832 operator>>(const SwizzleOp &Lhs, const int shift) {
837 template <typename T = DataT>
838 friend std::enable_if_t<detail::is_byte_v<T>, vec_t>
839 operator<<(const SwizzleOp &Lhs, const int shift) {
848 #ifdef __SYCL_RELLOGOP
849 #error "Undefine __SYCL_RELLOGOP macro"
851 #define __SYCL_RELLOGOP(RELLOGOP, COND) \
852 template <typename T = DataT> \
853 friend std::enable_if_t<(COND), vec_rel_t> operator RELLOGOP( \
854 const DataT & Lhs, const SwizzleOp & Rhs) { \
856 return Lhs RELLOGOP Tmp; \
858 template <typename T = DataT> \
859 friend std::enable_if_t<(COND), vec_rel_t> operator RELLOGOP( \
860 const SwizzleOp & Lhs, const DataT & Rhs) { \
862 return Tmp RELLOGOP Rhs; \
864 template <typename T = DataT> \
865 friend std::enable_if_t<(COND), vec_rel_t> operator RELLOGOP( \
866 const vec_t & Lhs, const SwizzleOp & Rhs) { \
868 return Lhs RELLOGOP Tmp; \
870 template <typename T = DataT> \
871 friend std::enable_if_t<(COND), vec_rel_t> operator RELLOGOP( \
872 const SwizzleOp & Lhs, const vec_t & Rhs) { \
874 return Tmp RELLOGOP Rhs; \
877 __SYCL_RELLOGOP(==, (!detail::is_byte_v<T>))
878 __SYCL_RELLOGOP(!=, (!detail::is_byte_v<T>))
879 __SYCL_RELLOGOP(>, (!detail::is_byte_v<T>))
880 __SYCL_RELLOGOP(<, (!detail::is_byte_v<T>))
881 __SYCL_RELLOGOP(>=, (!detail::is_byte_v<T>))
882 __SYCL_RELLOGOP(<=, (!detail::is_byte_v<T>))
883 __SYCL_RELLOGOP(&&, (!detail::is_byte_v<T> && !detail::is_vgenfloat_v<T>))
884 __SYCL_RELLOGOP(||, (!detail::is_byte_v<T> && !detail::is_vgenfloat_v<T>))
885 #undef __SYCL_RELLOGOP
887 template <int IdxNum = getNumElements(),
888 typename = EnableIfMultipleIndexes<IdxNum>>
889 SwizzleOp &operator=(const vec<DataT, IdxNum> &Rhs) {
890 std::array<int, IdxNum> Idxs{Indexes...};
891 for (size_t I = 0; I < Idxs.size(); ++I) {
892 (*m_Vector)[Idxs[I]] = Rhs[I];
897 template <int IdxNum = getNumElements(), typename = EnableIfOneIndex<IdxNum>>
898 SwizzleOp &operator=(const DataT &Rhs) {
899 std::array<int, IdxNum> Idxs{Indexes...};
900 (*m_Vector)[Idxs[0]] = Rhs;
904 template <int IdxNum = getNumElements(),
905 EnableIfMultipleIndexes<IdxNum, bool> = true>
906 SwizzleOp &operator=(const DataT &Rhs) {
907 std::array<int, IdxNum> Idxs{Indexes...};
908 for (auto Idx : Idxs) {
909 (*m_Vector)[Idx] = Rhs;
914 template <int IdxNum = getNumElements(), typename = EnableIfOneIndex<IdxNum>>
915 SwizzleOp &operator=(DataT &&Rhs) {
916 std::array<int, IdxNum> Idxs{Indexes...};
917 (*m_Vector)[Idxs[0]] = Rhs;
921 template <typename T, typename = EnableIfScalarType<T>>
922 NewLHOp<GetScalarOp<T>, std::multiplies, Indexes...>
923 operator*(const T &Rhs) const {
924 return NewLHOp<GetScalarOp<T>, std::multiplies, Indexes...>(
925 m_Vector, *this, GetScalarOp<T>(Rhs));
928 template <typename RhsOperation,
929 typename = EnableIfNoScalarType<RhsOperation>>
930 NewLHOp<RhsOperation, std::multiplies, Indexes...>
931 operator*(const RhsOperation &Rhs) const {
932 return NewLHOp<RhsOperation, std::multiplies, Indexes...>(m_Vector, *this,
936 template <typename T, typename = EnableIfScalarType<T>>
937 NewLHOp<GetScalarOp<T>, std::plus, Indexes...> operator+(const T &Rhs) const {
938 return NewLHOp<GetScalarOp<T>, std::plus, Indexes...>(m_Vector, *this,
939 GetScalarOp<T>(Rhs));
942 template <typename RhsOperation,
943 typename = EnableIfNoScalarType<RhsOperation>>
944 NewLHOp<RhsOperation, std::plus, Indexes...>
945 operator+(const RhsOperation &Rhs) const {
946 return NewLHOp<RhsOperation, std::plus, Indexes...>(m_Vector, *this, Rhs);
949 template <typename T, typename = EnableIfScalarType<T>>
950 NewLHOp<GetScalarOp<T>, std::minus, Indexes...>
951 operator-(const T &Rhs) const {
952 return NewLHOp<GetScalarOp<T>, std::minus, Indexes...>(m_Vector, *this,
953 GetScalarOp<T>(Rhs));
956 template <typename RhsOperation,
957 typename = EnableIfNoScalarType<RhsOperation>>
958 NewLHOp<RhsOperation, std::minus, Indexes...>
959 operator-(const RhsOperation &Rhs) const {
960 return NewLHOp<RhsOperation, std::minus, Indexes...>(m_Vector, *this, Rhs);
963 template <typename T, typename = EnableIfScalarType<T>>
964 NewLHOp<GetScalarOp<T>, std::divides, Indexes...>
965 operator/(const T &Rhs) const {
966 return NewLHOp<GetScalarOp<T>, std::divides, Indexes...>(
967 m_Vector, *this, GetScalarOp<T>(Rhs));
970 template <typename RhsOperation,
971 typename = EnableIfNoScalarType<RhsOperation>>
972 NewLHOp<RhsOperation, std::divides, Indexes...>
973 operator/(const RhsOperation &Rhs) const {
974 return NewLHOp<RhsOperation, std::divides, Indexes...>(m_Vector, *this,
978 template <typename T, typename = EnableIfScalarType<T>>
979 NewLHOp<GetScalarOp<T>, std::modulus, Indexes...>
980 operator%(const T &Rhs) const {
981 return NewLHOp<GetScalarOp<T>, std::modulus, Indexes...>(
982 m_Vector, *this, GetScalarOp<T>(Rhs));
985 template <typename RhsOperation,
986 typename = EnableIfNoScalarType<RhsOperation>>
987 NewLHOp<RhsOperation, std::modulus, Indexes...>
988 operator%(const RhsOperation &Rhs) const {
989 return NewLHOp<RhsOperation, std::modulus, Indexes...>(m_Vector, *this,
993 template <typename T, typename = EnableIfScalarType<T>>
994 NewLHOp<GetScalarOp<T>, std::bit_and, Indexes...>
995 operator&(const T &Rhs) const {
996 return NewLHOp<GetScalarOp<T>, std::bit_and, Indexes...>(
997 m_Vector, *this, GetScalarOp<T>(Rhs));
1000 template <typename RhsOperation,
1001 typename = EnableIfNoScalarType<RhsOperation>>
1002 NewLHOp<RhsOperation, std::bit_and, Indexes...>
1003 operator&(const RhsOperation &Rhs) const {
1004 return NewLHOp<RhsOperation, std::bit_and, Indexes...>(m_Vector, *this,
1008 template <typename T, typename = EnableIfScalarType<T>>
1009 NewLHOp<GetScalarOp<T>, std::bit_or, Indexes...>
1010 operator|(const T &Rhs) const {
1011 return NewLHOp<GetScalarOp<T>, std::bit_or, Indexes...>(
1012 m_Vector, *this, GetScalarOp<T>(Rhs));
1015 template <typename RhsOperation,
1016 typename = EnableIfNoScalarType<RhsOperation>>
1017 NewLHOp<RhsOperation, std::bit_or, Indexes...>
1018 operator|(const RhsOperation &Rhs) const {
1019 return NewLHOp<RhsOperation, std::bit_or, Indexes...>(m_Vector, *this, Rhs);
1022 template <typename T, typename = EnableIfScalarType<T>>
1023 NewLHOp<GetScalarOp<T>, std::bit_xor, Indexes...>
1024 operator^(const T &Rhs) const {
1025 return NewLHOp<GetScalarOp<T>, std::bit_xor, Indexes...>(
1026 m_Vector, *this, GetScalarOp<T>(Rhs));
1029 template <typename RhsOperation,
1030 typename = EnableIfNoScalarType<RhsOperation>>
1031 NewLHOp<RhsOperation, std::bit_xor, Indexes...>
1032 operator^(const RhsOperation &Rhs) const {
1033 return NewLHOp<RhsOperation, std::bit_xor, Indexes...>(m_Vector, *this,
1037 template <typename T, typename = EnableIfScalarType<T>>
1038 NewLHOp<GetScalarOp<T>, RShift, Indexes...> operator>>(const T &Rhs) const {
1039 return NewLHOp<GetScalarOp<T>, RShift, Indexes...>(m_Vector, *this,
1040 GetScalarOp<T>(Rhs));
1043 template <typename RhsOperation,
1044 typename = EnableIfNoScalarType<RhsOperation>>
1045 NewLHOp<RhsOperation, RShift, Indexes...>
1046 operator>>(const RhsOperation &Rhs) const {
1047 return NewLHOp<RhsOperation, RShift, Indexes...>(m_Vector, *this, Rhs);
1050 template <typename T, typename = EnableIfScalarType<T>>
1051 NewLHOp<GetScalarOp<T>, LShift, Indexes...> operator<<(const T &Rhs) const {
1052 return NewLHOp<GetScalarOp<T>, LShift, Indexes...>(m_Vector, *this,
1053 GetScalarOp<T>(Rhs));
1056 template <typename RhsOperation,
1057 typename = EnableIfNoScalarType<RhsOperation>>
1058 NewLHOp<RhsOperation, LShift, Indexes...>
1059 operator<<(const RhsOperation &Rhs) const {
1060 return NewLHOp<RhsOperation, LShift, Indexes...>(m_Vector, *this, Rhs);
1064 typename T1, typename T2, typename T3, template <typename> class T4,
1066 typename = typename std::enable_if_t<sizeof...(T5) == getNumElements()>>
1067 SwizzleOp &operator=(const SwizzleOp<T1, T2, T3, T4, T5...> &Rhs) {
1068 std::array<int, getNumElements()> Idxs{Indexes...};
1069 for (size_t I = 0; I < Idxs.size(); ++I) {
1070 (*m_Vector)[Idxs[I]] = Rhs.getValue(I);
1076 typename T1, typename T2, typename T3, template <typename> class T4,
1078 typename = typename std::enable_if_t<sizeof...(T5) == getNumElements()>>
1079 SwizzleOp &operator=(SwizzleOp<T1, T2, T3, T4, T5...> &&Rhs) {
1080 std::array<int, getNumElements()> Idxs{Indexes...};
1081 for (size_t I = 0; I < Idxs.size(); ++I) {
1082 (*m_Vector)[Idxs[I]] = Rhs.getValue(I);
1087 template <typename T, typename = EnableIfScalarType<T>>
1088 NewRelOp<GetScalarOp<T>, EqualTo, Indexes...> operator==(const T &Rhs) const {
1089 return NewRelOp<GetScalarOp<T>, EqualTo, Indexes...>(NULL, *this,
1090 GetScalarOp<T>(Rhs));
1093 template <typename RhsOperation,
1094 typename = EnableIfNoScalarType<RhsOperation>>
1095 NewRelOp<RhsOperation, EqualTo, Indexes...>
1096 operator==(const RhsOperation &Rhs) const {
1097 return NewRelOp<RhsOperation, EqualTo, Indexes...>(NULL, *this, Rhs);
1100 template <typename T, typename = EnableIfScalarType<T>>
1101 NewRelOp<GetScalarOp<T>, NotEqualTo, Indexes...>
1102 operator!=(const T &Rhs) const {
1103 return NewRelOp<GetScalarOp<T>, NotEqualTo, Indexes...>(
1104 NULL, *this, GetScalarOp<T>(Rhs));
1107 template <typename RhsOperation,
1108 typename = EnableIfNoScalarType<RhsOperation>>
1109 NewRelOp<RhsOperation, NotEqualTo, Indexes...>
1110 operator!=(const RhsOperation &Rhs) const {
1111 return NewRelOp<RhsOperation, NotEqualTo, Indexes...>(NULL, *this, Rhs);
1114 template <typename T, typename = EnableIfScalarType<T>>
1115 NewRelOp<GetScalarOp<T>, GreaterEqualTo, Indexes...>
1116 operator>=(const T &Rhs) const {
1117 return NewRelOp<GetScalarOp<T>, GreaterEqualTo, Indexes...>(
1118 NULL, *this, GetScalarOp<T>(Rhs));
1121 template <typename RhsOperation,
1122 typename = EnableIfNoScalarType<RhsOperation>>
1123 NewRelOp<RhsOperation, GreaterEqualTo, Indexes...>
1124 operator>=(const RhsOperation &Rhs) const {
1125 return NewRelOp<RhsOperation, GreaterEqualTo, Indexes...>(NULL, *this, Rhs);
1128 template <typename T, typename = EnableIfScalarType<T>>
1129 NewRelOp<GetScalarOp<T>, LessEqualTo, Indexes...>
1130 operator<=(const T &Rhs) const {
1131 return NewRelOp<GetScalarOp<T>, LessEqualTo, Indexes...>(
1132 NULL, *this, GetScalarOp<T>(Rhs));
1135 template <typename RhsOperation,
1136 typename = EnableIfNoScalarType<RhsOperation>>
1137 NewRelOp<RhsOperation, LessEqualTo, Indexes...>
1138 operator<=(const RhsOperation &Rhs) const {
1139 return NewRelOp<RhsOperation, LessEqualTo, Indexes...>(NULL, *this, Rhs);
1142 template <typename T, typename = EnableIfScalarType<T>>
1143 NewRelOp<GetScalarOp<T>, GreaterThan, Indexes...>
1144 operator>(const T &Rhs) const {
1145 return NewRelOp<GetScalarOp<T>, GreaterThan, Indexes...>(
1146 NULL, *this, GetScalarOp<T>(Rhs));
1149 template <typename RhsOperation,
1150 typename = EnableIfNoScalarType<RhsOperation>>
1151 NewRelOp<RhsOperation, GreaterThan, Indexes...>
1152 operator>(const RhsOperation &Rhs) const {
1153 return NewRelOp<RhsOperation, GreaterThan, Indexes...>(NULL, *this, Rhs);
1156 template <typename T, typename = EnableIfScalarType<T>>
1157 NewRelOp<GetScalarOp<T>, LessThan, Indexes...> operator<(const T &Rhs) const {
1158 return NewRelOp<GetScalarOp<T>, LessThan, Indexes...>(NULL, *this,
1159 GetScalarOp<T>(Rhs));
1162 template <typename RhsOperation,
1163 typename = EnableIfNoScalarType<RhsOperation>>
1164 NewRelOp<RhsOperation, LessThan, Indexes...>
1165 operator<(const RhsOperation &Rhs) const {
1166 return NewRelOp<RhsOperation, LessThan, Indexes...>(NULL, *this, Rhs);
1169 template <typename T, typename = EnableIfScalarType<T>>
1170 NewRelOp<GetScalarOp<T>, LogicalAnd, Indexes...>
1171 operator&&(const T &Rhs) const {
1172 return NewRelOp<GetScalarOp<T>, LogicalAnd, Indexes...>(
1173 NULL, *this, GetScalarOp<T>(Rhs));
1176 template <typename RhsOperation,
1177 typename = EnableIfNoScalarType<RhsOperation>>
1178 NewRelOp<RhsOperation, LogicalAnd, Indexes...>
1179 operator&&(const RhsOperation &Rhs) const {
1180 return NewRelOp<RhsOperation, LogicalAnd, Indexes...>(NULL, *this, Rhs);
1183 template <typename T, typename = EnableIfScalarType<T>>
1184 NewRelOp<GetScalarOp<T>, LogicalOr, Indexes...>
1185 operator||(const T &Rhs) const {
1186 return NewRelOp<GetScalarOp<T>, LogicalOr, Indexes...>(NULL, *this,
1187 GetScalarOp<T>(Rhs));
1190 template <typename RhsOperation,
1191 typename = EnableIfNoScalarType<RhsOperation>>
1192 NewRelOp<RhsOperation, LogicalOr, Indexes...>
1193 operator||(const RhsOperation &Rhs) const {
1194 return NewRelOp<RhsOperation, LogicalOr, Indexes...>(NULL, *this, Rhs);
1204 template <int Index> struct Indexer {
1205 static constexpr int IDXs[sizeof...(Indexes)] = {Indexes...};
1206 static constexpr int value = IDXs[Index >= getNumElements() ? 0 : Index];
1210 #ifdef __SYCL_ACCESS_RETURN
1211 #error "Undefine __SYCL_ACCESS_RETURN macro"
1213 #define __SYCL_ACCESS_RETURN m_Vector
1214 #include "swizzles.def"
1215 #undef __SYCL_ACCESS_RETURN
1220 template <access::address_space Space, access::decorated DecorateAddress>
1221 void load(size_t offset, multi_ptr<DataT, Space, DecorateAddress> ptr) {
1223 Tmp.load(offset, ptr);
1227 template <typename convertT, rounding_mode roundingMode>
1228 vec<convertT, sizeof...(Indexes)> convert() const {
1231 std::array<int, getNumElements()> Idxs{Indexes...};
1232 for (size_t I = 0; I < Idxs.size(); ++I) {
1233 Tmp[I] = (*m_Vector)[Idxs[I]];
1235 return Tmp.template convert<convertT, roundingMode>();
1238 template <typename asT> asT as() const {
1241 static_assert((sizeof(Tmp) == sizeof(asT)),
1242 "The new SYCL vec type must have the same storage size in "
1243 "bytes as this SYCL swizzled vec");
1245 detail::is_contained<asT, detail::gtl::vector_basic_list>::value ||
1246 detail::is_contained<asT, detail::gtl::vector_bool_list>::value,
1247 "asT must be SYCL vec of a different element type and "
1248 "number of elements specified by asT");
1249 return Tmp.template as<asT>();
1253 SwizzleOp(const SwizzleOp &Rhs)
1254 : m_Vector(Rhs.m_Vector), m_LeftOperation(Rhs.m_LeftOperation),
1255 m_RightOperation(Rhs.m_RightOperation) {}
1257 SwizzleOp(VecT *Vector, OperationLeftT LeftOperation,
1258 OperationRightT RightOperation)
1259 : m_Vector(Vector), m_LeftOperation(LeftOperation),
1260 m_RightOperation(RightOperation) {}
1262 SwizzleOp(VecT *Vector) : m_Vector(Vector) {}
1264 SwizzleOp(SwizzleOp &&Rhs)
1265 : m_Vector(Rhs.m_Vector), m_LeftOperation(std::move(Rhs.m_LeftOperation)),
1266 m_RightOperation(std::move(Rhs.m_RightOperation)) {}
1272 template <int IdxNum = getNumElements()>
1273 CommonDataT getValue(EnableIfOneIndex<IdxNum, size_t> Index) const {
1274 if (std::is_same_v<OperationCurrentT<DataT>, GetOp<DataT>>) {
1275 std::array<int, getNumElements()> Idxs{Indexes...};
1276 return (*m_Vector)[Idxs[Index]];
1278 auto Op = OperationCurrentT<CommonDataT>();
1279 return Op(m_LeftOperation.getValue(Index),
1280 m_RightOperation.getValue(Index));
1283 template <int IdxNum = getNumElements()>
1284 DataT getValue(EnableIfMultipleIndexes<IdxNum, size_t> Index) const {
1285 if (std::is_same_v<OperationCurrentT<DataT>, GetOp<DataT>>) {
1286 std::array<int, getNumElements()> Idxs{Indexes...};
1287 return (*m_Vector)[Idxs[Index]];
1289 auto Op = OperationCurrentT<DataT>();
1290 return Op(m_LeftOperation.getValue(Index),
1291 m_RightOperation.getValue(Index));
1294 template <template <typename> class Operation, typename RhsOperation>
1295 void operatorHelper(const RhsOperation &Rhs) const {
1296 Operation<DataT> Op;
1297 std::array<int, getNumElements()> Idxs{Indexes...};
1298 for (size_t I = 0; I < Idxs.size(); ++I) {
1299 DataT Res = Op((*m_Vector)[Idxs[I]], Rhs.getValue(I));
1300 (*m_Vector)[Idxs[I]] = Res;
1307 OperationLeftT m_LeftOperation;
1308 OperationRightT m_RightOperation;
1311 template <typename T1, int T2> friend class sycl::vec;
1313 template <typename T1, typename T2, typename T3, template <typename> class T4,
1315 friend class SwizzleOp;
DataT operator()(DataT, DataT)
DataT getValue(size_t) const
sycl::ext::oneapi::bfloat16 bfloat16
decltype(convertToOpenCLType(std::declval< T >())) ConvertToOpenCLType_t
uint16_t Bfloat16StorageT
__attribute__((always_inline)) auto invoke_simd(sycl
The invoke_simd free function invokes a SIMD function using all work-items in a sub_group.
sycl::detail::half_impl::half half