16
16
17
17
namespace sycl {
18
18
inline namespace _V1 {
19
-
20
- template <typename DataT, int NumElem> class __SYCL_EBO vec;
21
-
22
19
namespace detail {
23
-
24
20
template <typename T> struct from_incomplete ;
25
21
template <typename T>
26
22
struct from_incomplete <const T> : public from_incomplete<T> {};
@@ -31,6 +27,33 @@ struct from_incomplete<vec<DataT, NumElements>> {
31
27
static constexpr size_t size () { return NumElements; }
32
28
};
33
29
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
+
34
57
template <bool Cond, typename Mixin> struct ApplyIf {};
35
58
template <typename Mixin> struct ApplyIf <true , Mixin> : Mixin {};
36
59
@@ -477,6 +500,172 @@ template <typename Self> struct VecOperators {
477
500
OpAssign<ShiftRight>, IncDec> {};
478
501
};
479
502
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
+
480
669
#if __SYCL_USE_LIBSYCL8_VEC_IMPL
481
670
template <typename DataT, int NumElements>
482
671
class vec_arith : public VecOperators <vec<DataT, NumElements>>::Combined {};
0 commit comments