1616
1717namespace sycl {
1818inline namespace _V1 {
19-
20- template <typename DataT, int NumElem> class __SYCL_EBO vec;
21-
2219namespace detail {
23-
2420template <typename T> struct from_incomplete ;
2521template <typename T>
2622struct from_incomplete <const T> : public from_incomplete<T> {};
@@ -31,6 +27,33 @@ struct from_incomplete<vec<DataT, NumElements>> {
3127 static constexpr size_t size () { return NumElements; }
3228};
3329
30+ #if !__SYCL_USE_LIBSYCL8_VEC_IMPL
31+ template <bool IsConstVec, typename DataT, int VecSize, int ... Indexes>
32+ struct from_incomplete <
33+ hide_swizzle_from_adl::Swizzle<IsConstVec, DataT, VecSize, Indexes...>> {
34+ using element_type = DataT;
35+ static constexpr size_t size () { return sizeof ...(Indexes); }
36+
37+ using vec_ty = std::conditional_t <IsConstVec, const vec<DataT, VecSize>,
38+ vec<DataT, VecSize>>;
39+ using result_vec_ty = vec<DataT, size()>;
40+ static constexpr int vec_size = VecSize;
41+ static constexpr bool is_over_const_vec = IsConstVec;
42+ static constexpr bool has_repeating_indexes = []() constexpr {
43+ int Idxs[] = {Indexes...};
44+ for (std::size_t i = 1 ; i < sizeof ...(Indexes); ++i) {
45+ for (std::size_t j = 0 ; j < i; ++j)
46+ if (Idxs[j] == Idxs[i])
47+ // Repeating index
48+ return true ;
49+ }
50+
51+ return false ;
52+ }();
53+ static constexpr bool is_assignable = !IsConstVec && !has_repeating_indexes;
54+ };
55+ #endif
56+
3457template <bool Cond, typename Mixin> struct ApplyIf {};
3558template <typename Mixin> struct ApplyIf <true , Mixin> : Mixin {};
3659
@@ -477,6 +500,172 @@ template <typename Self> struct VecOperators {
477500 OpAssign<ShiftRight>, IncDec> {};
478501};
479502
503+ #if !__SYCL_USE_LIBSYCL8_VEC_IMPL
504+ template <typename Self> struct SwizzleOperators {
505+ using element_type = typename from_incomplete<Self>::element_type;
506+ using vec_ty = typename from_incomplete<Self>::result_vec_ty;
507+ static constexpr int N = from_incomplete<Self>::size();
508+
509+ template <typename T>
510+ static constexpr bool is_compatible_scalar =
511+ std::is_convertible_v<T, typename from_incomplete<Self>::element_type> &&
512+ !is_swizzle_v<T>;
513+
514+ // Can't use partial specialization on constexpr variables because it took too
515+ // long for gcc to fix https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71954 and
516+ // we need to support older versions without the fix.
517+ template <typename OtherSwizzle, typename = void >
518+ struct is_compatible_swizzle_impl : std::false_type {};
519+
520+ template <typename OtherSwizzle>
521+ struct is_compatible_swizzle_impl <
522+ OtherSwizzle, std::enable_if_t <is_swizzle_v<OtherSwizzle>>>
523+ : std::bool_constant<
524+ std::is_same_v<typename from_incomplete<OtherSwizzle>::element_type,
525+ typename from_incomplete<Self>::element_type> &&
526+ from_incomplete<OtherSwizzle>::size() ==
527+ from_incomplete<Self>::size()> {};
528+
529+ template <typename OtherSwizzle>
530+ static constexpr bool is_compatible_swizzle =
531+ is_compatible_swizzle_impl<OtherSwizzle>::value;
532+
533+ template <typename OtherSwizzle, typename = void >
534+ struct is_compatible_swizzle_opposite_const_impl : std::false_type {};
535+
536+ template <typename OtherSwizzle>
537+ struct is_compatible_swizzle_opposite_const_impl <
538+ OtherSwizzle, std::enable_if_t <is_swizzle_v<OtherSwizzle>>>
539+ : std::bool_constant<is_compatible_swizzle<OtherSwizzle> &&
540+ from_incomplete<OtherSwizzle>::is_over_const_vec !=
541+ from_incomplete<Self>::is_over_const_vec> {};
542+
543+ template <typename OtherSwizzle>
544+ static constexpr bool is_compatible_swizzle_opposite_const =
545+ is_compatible_swizzle_opposite_const_impl<OtherSwizzle>::value;
546+
547+ template <typename Op>
548+ using result_t = std::conditional_t <
549+ is_logical<Op>, vec<fixed_width_signed<sizeof (element_type)>, N>, vec_ty>;
550+
551+ // Uglier than possible due to
552+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282.
553+ template <typename Op, typename = void > struct OpMixin ;
554+
555+ template <typename Op>
556+ struct OpMixin <Op, std::enable_if_t <std::is_same_v<Op, IncDec>>>
557+ : public IncDecImpl<const Self> {};
558+
559+ #define __SYCL_SWIZZLE_BINOP_MIXIN (OP, OPERATOR ) \
560+ template <typename Op> \
561+ struct OpMixin <Op, std::enable_if_t <std::is_same_v<Op, OP>>> { \
562+ friend result_t <OP> operator OPERATOR (const Self & lhs, \
563+ const vec_ty & rhs) { \
564+ return OP{}(vec_ty{lhs}, rhs); \
565+ } \
566+ friend result_t <OP> operator OPERATOR (const vec_ty & lhs, \
567+ const Self & rhs) { \
568+ return OP{}(lhs, vec_ty{rhs}); \
569+ } \
570+ template <typename T> \
571+ friend std::enable_if_t <is_compatible_scalar<T>, result_t <OP>> \
572+ operator OPERATOR (const Self & lhs, const T & rhs) { \
573+ return OP{}(vec_ty{lhs}, vec_ty{rhs}); \
574+ } \
575+ template <typename T> \
576+ friend std::enable_if_t <is_compatible_scalar<T>, result_t <OP>> \
577+ operator OPERATOR (const T & lhs, const Self & rhs) { \
578+ return OP{}(vec_ty{lhs}, vec_ty{rhs}); \
579+ } \
580+ template <typename OtherSwizzle> \
581+ friend std::enable_if_t <is_compatible_swizzle<OtherSwizzle>, result_t <OP>> \
582+ operator OPERATOR (const Self & lhs, const OtherSwizzle & rhs) { \
583+ return OP{}(vec_ty{lhs}, vec_ty{rhs}); \
584+ } \
585+ template <typename OtherSwizzle> \
586+ friend std::enable_if_t < \
587+ is_compatible_swizzle_opposite_const<OtherSwizzle>, result_t <OP>> \
588+ operator OPERATOR (const OtherSwizzle & lhs, const Self & rhs) { \
589+ return OP{}(vec_ty{lhs}, vec_ty{rhs}); \
590+ } \
591+ };
592+
593+ #define __SYCL_SWIZZLE_OPASSIGN_MIXIN (OP, OPERATOR ) \
594+ template <typename Op> \
595+ struct OpMixin <OpAssign<Op>, std::enable_if_t <std::is_same_v<Op, OP>>> { \
596+ friend const Self &operator OPERATOR (const Self & lhs, \
597+ const vec_ty & rhs) { \
598+ lhs = OP{}(vec_ty{lhs}, rhs); \
599+ return lhs; \
600+ } \
601+ template <typename T> \
602+ friend std::enable_if_t <is_compatible_scalar<T>, const Self &> \
603+ operator OPERATOR (const Self & lhs, const T & rhs) { \
604+ lhs = OP{}(vec_ty{lhs}, vec_ty{rhs}); \
605+ return lhs; \
606+ } \
607+ template <typename OtherSwizzle> \
608+ friend std::enable_if_t <is_compatible_swizzle<OtherSwizzle>, const Self &> \
609+ operator OPERATOR (const Self & lhs, const OtherSwizzle & rhs) { \
610+ lhs = OP{}(vec_ty{lhs}, vec_ty{rhs}); \
611+ return lhs; \
612+ } \
613+ };
614+
615+ #define __SYCL_SWIZZLE_UOP_MIXIN (OP, OPERATOR ) \
616+ template <typename Op> \
617+ struct OpMixin <Op, std::enable_if_t <std::is_same_v<Op, OP>>> { \
618+ friend result_t <OP> operator OPERATOR (const Self & v) { \
619+ return OP{}(vec_ty{v}); \
620+ } \
621+ };
622+
623+ __SYCL_INSTANTIATE_OPERATORS (__SYCL_SWIZZLE_BINOP_MIXIN,
624+ __SYCL_SWIZZLE_OPASSIGN_MIXIN,
625+ __SYCL_SWIZZLE_UOP_MIXIN)
626+
627+ #undef __SYCL_SWIZZLE_UOP_MIXIN
628+ #undef __SYCL_SWIZZLE_OPASSIGN_MIXIN
629+ #undef __SYCL_SWIZZLE_BINOP_MIXIN
630+
631+ template <typename ... Op>
632+ struct __SYCL_EBO CombineImpl
633+ : ApplyIf<is_op_available_for_type<Op, element_type>, OpMixin<Op>>... {};
634+
635+ template <typename _Self, typename = void >
636+ struct CombinedImpl
637+ : CombineImpl<std::plus<void >, std::minus<void >, std::multiplies<void >,
638+ std::divides<void >, std::modulus<void >, std::bit_and<void >,
639+ std::bit_or<void >, std::bit_xor<void >, std::equal_to<void >,
640+ std::not_equal_to<void >, std::less<void >,
641+ std::greater<void >, std::less_equal<void >,
642+ std::greater_equal<void >, std::logical_and<void >,
643+ std::logical_or<void >, ShiftLeft, ShiftRight,
644+ std::negate<void >, std::logical_not<void >,
645+ std::bit_not<void >, UnaryPlus> {};
646+
647+ template <typename _Self>
648+ struct CombinedImpl <_Self,
649+ std::enable_if_t <from_incomplete<_Self>::is_assignable>>
650+ : CombineImpl<std::plus<void >, std::minus<void >, std::multiplies<void >,
651+ std::divides<void >, std::modulus<void >, std::bit_and<void >,
652+ std::bit_or<void >, std::bit_xor<void >, std::equal_to<void >,
653+ std::not_equal_to<void >, std::less<void >,
654+ std::greater<void >, std::less_equal<void >,
655+ std::greater_equal<void >, std::logical_and<void >,
656+ std::logical_or<void >, ShiftLeft, ShiftRight,
657+ std::negate<void >, std::logical_not<void >,
658+ std::bit_not<void >, UnaryPlus, OpAssign<std::plus<void >>,
659+ OpAssign<std::minus<void >>, OpAssign<std::multiplies<void >>,
660+ OpAssign<std::divides<void >>, OpAssign<std::modulus<void >>,
661+ OpAssign<std::bit_and<void >>, OpAssign<std::bit_or<void >>,
662+ OpAssign<std::bit_xor<void >>, OpAssign<ShiftLeft>,
663+ OpAssign<ShiftRight>, IncDec> {};
664+
665+ using Combined = CombinedImpl<Self>;
666+ };
667+ #endif
668+
480669#if __SYCL_USE_LIBSYCL8_VEC_IMPL
481670template <typename DataT, int NumElements>
482671class vec_arith : public VecOperators <vec<DataT, NumElements>>::Combined {};
0 commit comments