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