1 #ifndef EAGINE_VECT_SHUFFLE_HPP
9 #define EAGINE_VECT_SHUFFLE_HPP
13 namespace eagine::vect {
16 struct shuffle_mask {};
18 #if EAGINE_USE_SIMD && defined(__GNUC__) && !defined(__clang__)
19 template <
typename T,
int N,
bool V>
20 struct mask : _vec_data<T, N> {};
22 template <
int N,
bool V>
23 struct mask<float, N, V> : _vec_data<std::int32_t, N> {};
25 template <
int N,
bool V>
26 struct mask<double, N, V> : _vec_data<std::int64_t, N> {};
28 template <
typename T,
int N,
bool V>
29 using mask_t =
typename mask<T, N, V>::type;
32 template <
typename T,
int N,
bool V>
35 using _dT = data_t<T, N, V>;
36 using _dpT = data_param_t<T, N, V>;
40 _do_apply(_dpT v, shuffle_mask<I...>, std::false_type) noexcept {
41 return data_t<T, N, V>{v[I]...};
46 _do_apply(_dpT v, shuffle_mask<I...>, std::true_type) noexcept -> _dT {
47 #if EAGINE_USE_SIMD && defined(__clang__)
49 return _dT(__builtin_shufflevector(v, v, I...));
50 #elif EAGINE_USE_SIMD && defined(__GNUC__)
51 using _mT = mask_t<T, N, V>;
53 return __builtin_shuffle(v, _mT{I...});
55 return _do_apply(v, shuffle_mask<I...>(), std::false_type());
61 static constexpr
auto apply(_dpT v, shuffle_mask<I...> m = {}) noexcept {
62 return _do_apply(v, m, has_vect_data<T, N, V>());
66 template <
typename T,
int N,
bool V>
69 using _dT = data_t<T, N, V>;
70 using _dpT = data_param_t<T, N, V>;
73 using _int = int_constant<U>;
75 template <
int M,
int... I>
76 static auto _do_apply(
81 std::false_type) noexcept {
82 return data_t<T, N, V>{
83 I < 0 ? T(0) : (int(I) < N ? v1[int(I)] : v2[int(I) % N])...};
86 template <
int M,
int... I>
87 static auto _do_apply(
92 std::true_type) noexcept -> _dT {
93 #if EAGINE_USE_SIMD && defined(__clang__)
95 return _dT(__builtin_shufflevector(v1, v2, I...));
96 #elif EAGINE_USE_SIMD && defined(__GNUC__)
97 using _mT = mask_t<T, N, V>;
99 return __builtin_shuffle(v1, v2, _mT{I...});
102 v1, v2, shuffle_mask<I...>(), _int<M>(), std::false_type());
107 static auto _do_apply(
112 std::true_type) noexcept -> _dT {
113 #if EAGINE_USE_SIMD && defined(__clang__)
115 return _dT(__builtin_shufflevector(v1, v2, I >= 3 ? I + 1 : I...));
116 #elif EAGINE_USE_SIMD && defined(__GNUC__)
117 using _mT = mask_t<T, N, V>;
119 return __builtin_shuffle(v1, v2, _mT{(I >= 3 ? I + 1 : I)...});
122 v1, v2, shuffle_mask<I...>(), _int<3>(), std::false_type());
128 static auto apply(_dpT v1, _dpT v2, shuffle_mask<I...> m = {}) noexcept {
129 return _do_apply(v1, v2, m, _int<N>(), has_vect_data<T, N, V>());
135 #endif // EAGINE_VECT_SHUFFLE_HPP