OGLplus  (0.59.0) a C++ wrapper for rendering APIs

shuffle.hpp
Go to the documentation of this file.
1 #ifndef EAGINE_VECT_SHUFFLE_HPP
9 #define EAGINE_VECT_SHUFFLE_HPP
10 
11 #include "data.hpp"
12 
13 namespace eagine::vect {
14 
15 template <int... I>
16 struct shuffle_mask {};
17 
18 #if EAGINE_USE_SIMD && defined(__GNUC__) && !defined(__clang__)
19 template <typename T, int N, bool V>
20 struct mask : _vec_data<T, N> {};
21 
22 template <int N, bool V>
23 struct mask<float, N, V> : _vec_data<std::int32_t, N> {};
24 
25 template <int N, bool V>
26 struct mask<double, N, V> : _vec_data<std::int64_t, N> {};
27 
28 template <typename T, int N, bool V>
29 using mask_t = typename mask<T, N, V>::type;
30 #endif
31 
32 template <typename T, int N, bool V>
33 struct shuffle {
34 private:
35  using _dT = data_t<T, N, V>;
36  using _dpT = data_param_t<T, N, V>;
37 
38  template <int... I>
39  static constexpr auto
40  _do_apply(_dpT v, shuffle_mask<I...>, std::false_type) noexcept {
41  return data_t<T, N, V>{v[I]...};
42  }
43 
44  template <int... I>
45  static constexpr auto
46  _do_apply(_dpT v, shuffle_mask<I...>, std::true_type) noexcept -> _dT {
47 #if EAGINE_USE_SIMD && defined(__clang__)
48  // NOLINTNEXTLINE(hicpp-vararg)
49  return _dT(__builtin_shufflevector(v, v, I...));
50 #elif EAGINE_USE_SIMD && defined(__GNUC__)
51  using _mT = mask_t<T, N, V>;
52  // NOLINTNEXTLINE(hicpp-vararg)
53  return __builtin_shuffle(v, _mT{I...});
54 #else
55  return _do_apply(v, shuffle_mask<I...>(), std::false_type());
56 #endif
57  }
58 
59 public:
60  template <int... I>
61  static constexpr auto apply(_dpT v, shuffle_mask<I...> m = {}) noexcept {
62  return _do_apply(v, m, has_vect_data<T, N, V>());
63  }
64 };
65 
66 template <typename T, int N, bool V>
67 struct shuffle2 {
68 private:
69  using _dT = data_t<T, N, V>;
70  using _dpT = data_param_t<T, N, V>;
71 
72  template <int U>
73  using _int = int_constant<U>;
74 
75  template <int M, int... I>
76  static auto _do_apply(
77  _dpT v1,
78  _dpT v2,
79  shuffle_mask<I...>,
80  _int<M>,
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])...};
84  }
85 
86  template <int M, int... I>
87  static auto _do_apply(
88  _dpT v1,
89  _dpT v2,
90  shuffle_mask<I...>,
91  _int<M>,
92  std::true_type) noexcept -> _dT {
93 #if EAGINE_USE_SIMD && defined(__clang__)
94  // NOLINTNEXTLINE(hicpp-vararg)
95  return _dT(__builtin_shufflevector(v1, v2, I...));
96 #elif EAGINE_USE_SIMD && defined(__GNUC__)
97  using _mT = mask_t<T, N, V>;
98  // NOLINTNEXTLINE(hicpp-vararg)
99  return __builtin_shuffle(v1, v2, _mT{I...});
100 #else
101  return _do_apply(
102  v1, v2, shuffle_mask<I...>(), _int<M>(), std::false_type());
103 #endif
104  }
105 
106  template <int... I>
107  static auto _do_apply(
108  _dpT v1,
109  _dpT v2,
110  shuffle_mask<I...>,
111  _int<3U>,
112  std::true_type) noexcept -> _dT {
113 #if EAGINE_USE_SIMD && defined(__clang__)
114  // NOLINTNEXTLINE(hicpp-vararg)
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>;
118  // NOLINTNEXTLINE(hicpp-vararg)
119  return __builtin_shuffle(v1, v2, _mT{(I >= 3 ? I + 1 : I)...});
120 #else
121  return _do_apply(
122  v1, v2, shuffle_mask<I...>(), _int<3>(), std::false_type());
123 #endif
124  }
125 
126 public:
127  template <int... I>
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>());
130  }
131 };
132 
133 } // namespace eagine::vect
134 
135 #endif // EAGINE_VECT_SHUFFLE_HPP
static auto shuffle(basic_span< T, P, S > spn, RandGen rg) -> basic_span< T, P, S >
Shuffles the elements of a span.
Definition: span_algo.hpp:596

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).