29 #ifndef VC_COMMON_SIMDARRAYHELPER_H_
30 #define VC_COMMON_SIMDARRAYHELPER_H_
34 namespace Vc_VERSIONED_NAMESPACE
45 #define Vc_DEFINE_OPERATION(name__) \
46 struct name__ : public tag \
48 template <typename V, typename... Args> \
49 Vc_INTRINSIC void operator()(V &v, Args &&... args) \
51 v.name__(std::forward<Args>(args)...); \
54 Vc_DEFINE_OPERATION(gather);
55 Vc_DEFINE_OPERATION(scatter);
56 Vc_DEFINE_OPERATION(load);
57 Vc_DEFINE_OPERATION(store);
58 Vc_DEFINE_OPERATION(setZero);
59 Vc_DEFINE_OPERATION(setZeroInverted);
60 Vc_DEFINE_OPERATION(
assign);
61 #undef Vc_DEFINE_OPERATION
62 #define Vc_DEFINE_OPERATION(name__, code__) \
63 struct name__ : public tag \
65 template <typename V> Vc_INTRINSIC void operator()(V & v) { code__; } \
67 Vc_DEFINE_OPERATION(increment, ++v);
68 Vc_DEFINE_OPERATION(decrement, --v);
69 Vc_DEFINE_OPERATION(random, v = V::Random());
70 #undef Vc_DEFINE_OPERATION
71 #define Vc_DEFINE_OPERATION(name__, code__) \
72 struct name__ : public tag \
74 template <typename V, typename... Args> \
75 Vc_INTRINSIC void operator()(V &v, Args &&... args) \
80 Vc_DEFINE_OPERATION(Abs, v =
abs(std::forward<Args>(args)...));
81 Vc_DEFINE_OPERATION(Isnan, v =
isnan(std::forward<Args>(args)...));
82 Vc_DEFINE_OPERATION(Frexp, v =
frexp(std::forward<Args>(args)...));
83 Vc_DEFINE_OPERATION(Ldexp, v =
ldexp(std::forward<Args>(args)...));
84 #undef Vc_DEFINE_OPERATION
85 template<
typename T>
using is_operation = std::is_base_of<tag, T>;
93 template <
typename T_, std::
size_t Pieces_, std::
size_t Index_>
struct Segment
95 static_assert(Index_ < Pieces_,
"You found a bug in Vc. Please report.");
98 using type_decayed =
typename std::decay<type>::type;
99 static constexpr std::size_t Pieces = Pieces_;
100 static constexpr std::size_t Index = Index_;
104 static constexpr std::size_t EntryOffset = Index * type_decayed::Size / Pieces;
106 decltype(std::declval<type>()[0]) operator[](
size_t i) {
return data[i + EntryOffset]; }
107 decltype(std::declval<type>()[0]) operator[](
size_t i)
const {
return data[i + EntryOffset]; }
119 template <
typename T, std::
size_t Offset>
struct AddOffset
121 constexpr AddOffset() =
default;
132 template <std::
size_t secondOffset>
class Split
134 static Vc_INTRINSIC AddOffset<VectorSpecialInitializerIndexesFromZero, secondOffset>
135 hiImpl(VectorSpecialInitializerIndexesFromZero)
139 template <std::
size_t Offset>
141 AddOffset<VectorSpecialInitializerIndexesFromZero, Offset + secondOffset>
142 hiImpl(AddOffset<VectorSpecialInitializerIndexesFromZero, Offset>)
148 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
149 static Vc_INTRINSIC
auto loImpl(
const SimdArray<U, N, V, M> &x) -> decltype(internal_data0(x))
151 return internal_data0(x);
153 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
154 static Vc_INTRINSIC
auto hiImpl(
const SimdArray<U, N, V, M> &x) -> decltype(internal_data1(x))
156 return internal_data1(x);
158 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
159 static Vc_INTRINSIC
auto loImpl(SimdArray<U, N, V, M> *x) -> decltype(&internal_data0(*x))
161 return &internal_data0(*x);
163 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
164 static Vc_INTRINSIC
auto hiImpl(SimdArray<U, N, V, M> *x) -> decltype(&internal_data1(*x))
166 return &internal_data1(*x);
169 template <
typename U, std::
size_t N,
typename V>
170 static Vc_INTRINSIC Segment<V, 2, 0> loImpl(
const SimdArray<U, N, V, N> &x)
172 return {internal_data(x)};
174 template <
typename U, std::
size_t N,
typename V>
175 static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(
const SimdArray<U, N, V, N> &x)
177 return {internal_data(x)};
179 template <
typename U, std::
size_t N,
typename V>
180 static Vc_INTRINSIC Segment<V *, 2, 0> loImpl(
const SimdArray<U, N, V, N> *x)
182 return {&internal_data(*x)};
184 template <
typename U, std::
size_t N,
typename V>
185 static Vc_INTRINSIC Segment<V *, 2, 1> hiImpl(
const SimdArray<U, N, V, N> *x)
187 return {&internal_data(*x)};
191 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
192 static Vc_INTRINSIC
auto loImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data0(x))
194 return internal_data0(x);
196 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
197 static Vc_INTRINSIC
auto hiImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data1(x))
199 return internal_data1(x);
202 template <
typename U, std::
size_t N,
typename V>
203 static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 0> loImpl(
204 const SimdMaskArray<U, N, V, N> &x)
206 return {internal_data(x)};
208 template <
typename U, std::
size_t N,
typename V>
209 static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 1> hiImpl(
210 const SimdMaskArray<U, N, V, N> &x)
212 return {internal_data(x)};
216 template <
typename T>
217 static constexpr
bool is_vector_or_mask(){
218 return (Traits::is_simd_vector<T>::value && !Traits::isSimdArray<T>::value) ||
219 (Traits::is_simd_mask<T>::value && !Traits::isSimdMaskArray<T>::value);
221 template <
typename V>
222 static Vc_INTRINSIC Segment<V, 2, 0> loImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
224 return {std::forward<V>(x)};
226 template <
typename V>
227 static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
229 return {std::forward<V>(x)};
233 template <
typename V, std::
size_t Pieces, std::
size_t Index>
234 static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index> loImpl(
235 const Segment<V, Pieces, Index> &x)
239 template <
typename V, std::
size_t Pieces, std::
size_t Index>
240 static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index + 1> hiImpl(
241 const Segment<V, Pieces, Index> &x)
250 template <
typename T,
typename = decltype(loImpl(std::declval<T>()))>
251 static std::true_type have_lo_impl(
int);
252 template <
typename T>
static std::false_type have_lo_impl(
float);
253 template <
typename T>
static constexpr
bool have_lo_impl()
255 return decltype(have_lo_impl<T>(1))::value;
258 template <
typename T,
typename = decltype(hiImpl(std::declval<T>()))>
259 static std::true_type have_hi_impl(
int);
260 template <
typename T>
static std::false_type have_hi_impl(
float);
261 template <
typename T>
static constexpr
bool have_hi_impl()
263 return decltype(have_hi_impl<T>(1))::value;
275 template <
typename U>
276 static Vc_INTRINSIC
const U *lo(Operations::gather,
const U *ptr)
280 template <
typename U>
281 static Vc_INTRINSIC
const U *hi(Operations::gather,
const U *ptr)
283 return ptr + secondOffset;
285 template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
286 static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>()))
287 lo(Operations::gather, U &&x)
289 return loImpl(std::forward<U>(x));
291 template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
292 static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>()))
293 hi(Operations::gather, U &&x)
295 return hiImpl(std::forward<U>(x));
297 template <
typename U>
298 static Vc_INTRINSIC
const U *lo(Operations::scatter,
const U *ptr)
302 template <
typename U>
303 static Vc_INTRINSIC
const U *hi(Operations::scatter,
const U *ptr)
305 return ptr + secondOffset;
320 template <
typename U>
321 static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>())) lo(U &&x)
323 return loImpl(std::forward<U>(x));
325 template <
typename U>
326 static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>())) hi(U &&x)
328 return hiImpl(std::forward<U>(x));
331 template <
typename U>
332 static Vc_ALWAYS_INLINE enable_if<!have_lo_impl<U>(), U> lo(U &&x)
334 return std::forward<U>(x);
336 template <
typename U>
337 static Vc_ALWAYS_INLINE enable_if<!have_hi_impl<U>(), U> hi(U &&x)
339 return std::forward<U>(x);
344 template <
typename Op,
typename U>
static Vc_INTRINSIC U actual_value(Op, U &&x)
346 return std::forward<U>(x);
348 template <
typename Op,
typename U, std::
size_t M,
typename V>
349 static Vc_INTRINSIC
const V &actual_value(Op,
const SimdArray<U, M, V, M> &x)
351 return internal_data(x);
353 template <
typename Op,
typename U, std::
size_t M,
typename V>
354 static Vc_INTRINSIC
const V &actual_value(Op, SimdArray<U, M, V, M> &&x)
356 return internal_data(x);
358 template <
typename Op,
typename U, std::
size_t M,
typename V>
359 static Vc_INTRINSIC V *actual_value(Op, SimdArray<U, M, V, M> *x)
361 return &internal_data(*x);
363 template <
typename Op,
typename U, std::
size_t M,
typename V>
364 static Vc_INTRINSIC
const typename V::Mask &actual_value(Op,
const SimdMaskArray<U, M, V, M> &x)
366 return internal_data(x);
368 template <
typename Op,
typename U, std::
size_t M,
typename V>
369 static Vc_INTRINSIC
const typename V::Mask &actual_value(Op, SimdMaskArray<U, M, V, M> &&x)
371 return internal_data(x);
373 template <
typename Op,
typename U, std::
size_t M,
typename V>
374 static Vc_INTRINSIC
typename V::Mask *actual_value(Op, SimdMaskArray<U, M, V, M> *x)
376 return &internal_data(*x);
384 #endif // VC_COMMON_SIMDARRAYHELPER_H_
Vc::Vector< T > frexp(const Vc::Vector< T > &x, Vc::SimdArray< int, size()> *e)
Convert floating-point number to fractional and integral components.
Vc::Vector< T > ldexp(Vc::Vector< T > x, Vc::SimdArray< int, size()> e)
Multiply floating-point number by integral power of 2.
Vc::Vector< T > abs(const Vc::Vector< T > &v)
Returns the absolute value of v.
void assign(Adapter< S, T, N > &a, size_t i, const S &x)
Assigns one scalar object x to a SIMD slot at offset i in the simdized object a.
Vc::Mask< T > isnan(const Vc::Vector< T > &x)