28 #ifndef VC_COMMON_SIMDARRAYHELPER_H_
29 #define VC_COMMON_SIMDARRAYHELPER_H_
33 namespace Vc_VERSIONED_NAMESPACE
44 #define Vc_DEFINE_OPERATION(name_) \
45 struct name_ : public tag { \
46 template <typename V, typename... Args> \
47 Vc_INTRINSIC void operator()(V &v, Args &&... args) \
49 v.name_(std::forward<Args>(args)...); \
52 Vc_DEFINE_OPERATION(gather);
53 Vc_DEFINE_OPERATION(scatter);
54 Vc_DEFINE_OPERATION(load);
55 Vc_DEFINE_OPERATION(store);
56 Vc_DEFINE_OPERATION(setZero);
57 Vc_DEFINE_OPERATION(setZeroInverted);
58 Vc_DEFINE_OPERATION(
assign);
59 #undef Vc_DEFINE_OPERATION
60 #define Vc_DEFINE_OPERATION(name_, code_) \
61 struct name_ : public tag { \
62 template <typename V> Vc_INTRINSIC void operator()(V &v) { code_; } \
64 Vc_DEFINE_OPERATION(increment, ++(v));
65 Vc_DEFINE_OPERATION(decrement, --(v));
66 Vc_DEFINE_OPERATION(random, v = V::Random());
67 #undef Vc_DEFINE_OPERATION
68 #define Vc_DEFINE_OPERATION_FORWARD(name_) \
69 struct Forward_##name_ : public tag \
71 template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \
72 Vc_INTRINSIC void operator()(decltype(name_(std::declval<Args>()...)) &v, \
75 v = name_(std::forward<Args>(args)...); \
77 template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \
78 Vc_INTRINSIC void operator()(std::nullptr_t, Args && ... args) \
80 name_(std::forward<Args>(args)...); \
83 Vc_DEFINE_OPERATION_FORWARD(
abs);
84 Vc_DEFINE_OPERATION_FORWARD(
asin);
85 Vc_DEFINE_OPERATION_FORWARD(
atan);
86 Vc_DEFINE_OPERATION_FORWARD(
atan2);
87 Vc_DEFINE_OPERATION_FORWARD(
cos);
88 Vc_DEFINE_OPERATION_FORWARD(
ceil);
89 Vc_DEFINE_OPERATION_FORWARD(
copysign);
90 Vc_DEFINE_OPERATION_FORWARD(
exp);
91 Vc_DEFINE_OPERATION_FORWARD(
exponent);
92 Vc_DEFINE_OPERATION_FORWARD(
fma);
93 Vc_DEFINE_OPERATION_FORWARD(
floor);
94 Vc_DEFINE_OPERATION_FORWARD(
frexp);
95 Vc_DEFINE_OPERATION_FORWARD(
isfinite);
96 Vc_DEFINE_OPERATION_FORWARD(
isinf);
97 Vc_DEFINE_OPERATION_FORWARD(
isnan);
99 Vc_DEFINE_OPERATION_FORWARD(
ldexp);
100 Vc_DEFINE_OPERATION_FORWARD(
log);
101 Vc_DEFINE_OPERATION_FORWARD(
log10);
102 Vc_DEFINE_OPERATION_FORWARD(
log2);
104 Vc_DEFINE_OPERATION_FORWARD(
round);
105 Vc_DEFINE_OPERATION_FORWARD(
rsqrt);
106 Vc_DEFINE_OPERATION_FORWARD(
sin);
107 Vc_DEFINE_OPERATION_FORWARD(
sincos);
108 Vc_DEFINE_OPERATION_FORWARD(
sqrt);
109 Vc_DEFINE_OPERATION_FORWARD(
trunc);
110 Vc_DEFINE_OPERATION_FORWARD(
min);
111 Vc_DEFINE_OPERATION_FORWARD(
max);
112 #undef Vc_DEFINE_OPERATION_FORWARD
113 template<
typename T>
using is_operation = std::is_base_of<tag, T>;
121 template <
typename T_, std::
size_t Pieces_, std::
size_t Index_>
struct Segment
123 static_assert(Index_ < Pieces_,
"You found a bug in Vc. Please report.");
126 using type_decayed =
typename std::decay<type>::type;
127 static constexpr std::size_t Pieces = Pieces_;
128 static constexpr std::size_t Index = Index_;
129 using simd_array_type = SimdArray<
130 typename std::conditional<Traits::is_simd_vector<type_decayed>::value,
131 typename type_decayed::EntryType,
float>::type,
132 type_decayed::Size / Pieces>;
136 static constexpr std::size_t EntryOffset = Index * type_decayed::Size / Pieces;
139 decltype(std::declval<const type &>()[0]) operator[](
size_t i)
const {
return data[i + EntryOffset]; }
141 simd_array_type asSimdArray()
const
143 return simd_cast<simd_array_type, Index>(data);
148 template <
typename T_, std::
size_t Pieces_, std::
size_t Index_>
149 struct Segment<T_ *, Pieces_, Index_> {
150 static_assert(Index_ < Pieces_,
"You found a bug in Vc. Please report.");
153 using type_decayed =
typename std::decay<T_>::type;
154 static constexpr
size_t Pieces = Pieces_;
155 static constexpr
size_t Index = Index_;
156 using simd_array_type = SimdArray<
157 typename std::conditional<Traits::is_simd_vector<type_decayed>::value,
158 typename type_decayed::VectorEntryType,
float>::type,
159 type_decayed::Size / Pieces> *;
163 static constexpr std::size_t EntryOffset = Index * type_decayed::size() / Pieces;
165 simd_array_type asSimdArray()
const
167 return reinterpret_cast<
171 typename std::remove_pointer<simd_array_type>::type
173 MayAlias<typename std::remove_pointer<simd_array_type>::type
>
192 template <
typename T, std::
size_t Offset>
struct AddOffset
194 constexpr AddOffset() =
default;
206 template <std::
size_t secondOffset>
class Split
208 static Vc_INTRINSIC AddOffset<VectorSpecialInitializerIndexesFromZero, secondOffset>
209 hiImpl(VectorSpecialInitializerIndexesFromZero)
213 template <std::
size_t Offset>
215 AddOffset<VectorSpecialInitializerIndexesFromZero, Offset + secondOffset>
216 hiImpl(AddOffset<VectorSpecialInitializerIndexesFromZero, Offset>)
222 template <
typename U, std::size_t N,
typename V, std::size_t M,
223 typename = enable_if<N != M>>
224 static Vc_INTRINSIC
auto loImpl(
const SimdArray<U, N, V, M> &x)
225 -> decltype(internal_data0(x))
227 return internal_data0(x);
229 template <
typename U, std::size_t N,
typename V, std::size_t M,
230 typename = enable_if<N != M>>
231 static Vc_INTRINSIC
auto hiImpl(
const SimdArray<U, N, V, M> &x)
232 -> decltype(internal_data1(x))
234 return internal_data1(x);
236 template <
typename U, std::size_t N,
typename V, std::size_t M,
237 typename = enable_if<N != M>>
238 static Vc_INTRINSIC
auto loImpl(SimdArray<U, N, V, M> *x)
239 -> decltype(&internal_data0(*x))
241 return &internal_data0(*x);
243 template <
typename U, std::size_t N,
typename V, std::size_t M,
244 typename = enable_if<N != M>>
245 static Vc_INTRINSIC
auto hiImpl(SimdArray<U, N, V, M> *x)
246 -> decltype(&internal_data1(*x))
248 return &internal_data1(*x);
252 template <
typename U, std::
size_t N,
typename V>
253 static Vc_INTRINSIC Segment<V, 2, 0> loImpl(
const SimdArray<U, N, V, N> &x)
255 return {internal_data(x)};
257 template <
typename U, std::
size_t N,
typename V>
258 static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(
const SimdArray<U, N, V, N> &x)
260 return {internal_data(x)};
262 template <
typename U, std::
size_t N,
typename V>
263 static Vc_INTRINSIC Segment<V *, 2, 0> loImpl(SimdArray<U, N, V, N> *x)
265 return {&internal_data(*x)};
267 template <
typename U, std::
size_t N,
typename V>
268 static Vc_INTRINSIC Segment<V *, 2, 1> hiImpl(SimdArray<U, N, V, N> *x)
270 return {&internal_data(*x)};
274 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
275 static Vc_INTRINSIC
auto loImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data0(x))
277 return internal_data0(x);
279 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
280 static Vc_INTRINSIC
auto hiImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data1(x))
282 return internal_data1(x);
285 template <
typename U, std::
size_t N,
typename V>
286 static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 0> loImpl(
287 const SimdMaskArray<U, N, V, N> &x)
289 return {internal_data(x)};
291 template <
typename U, std::
size_t N,
typename V>
292 static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 1> hiImpl(
293 const SimdMaskArray<U, N, V, N> &x)
295 return {internal_data(x)};
299 template <
typename T>
300 static constexpr
bool is_vector_or_mask(){
301 return (Traits::is_simd_vector<T>::value && !Traits::isSimdArray<T>::value) ||
302 (Traits::is_simd_mask<T>::value && !Traits::isSimdMaskArray<T>::value);
304 template <
typename V>
305 static Vc_INTRINSIC Segment<V, 2, 0> loImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
307 return {std::forward<V>(x)};
309 template <
typename V>
310 static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
312 return {std::forward<V>(x)};
316 template <
typename V, std::
size_t Pieces, std::
size_t Index>
317 static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index> loImpl(
318 const Segment<V, Pieces, Index> &x)
322 template <
typename V, std::
size_t Pieces, std::
size_t Index>
323 static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index + 1> hiImpl(
324 const Segment<V, Pieces, Index> &x)
333 template <
typename T,
typename = decltype(loImpl(std::declval<T>()))>
334 static std::true_type have_lo_impl(
int);
335 template <
typename T>
static std::false_type have_lo_impl(
float);
336 template <
typename T>
static constexpr
bool have_lo_impl()
338 return decltype(have_lo_impl<T>(1))::value;
341 template <
typename T,
typename = decltype(hiImpl(std::declval<T>()))>
342 static std::true_type have_hi_impl(
int);
343 template <
typename T>
static std::false_type have_hi_impl(
float);
344 template <
typename T>
static constexpr
bool have_hi_impl()
346 return decltype(have_hi_impl<T>(1))::value;
358 template <
typename U>
359 static Vc_INTRINSIC
const U *lo(Operations::gather,
const U *ptr)
363 template <
typename U>
364 static Vc_INTRINSIC
const U *hi(Operations::gather,
const U *ptr)
366 return ptr + secondOffset;
368 template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
369 static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>()))
370 lo(Operations::gather, U &&x)
372 return loImpl(std::forward<U>(x));
374 template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
375 static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>()))
376 hi(Operations::gather, U &&x)
378 return hiImpl(std::forward<U>(x));
380 template <
typename U>
381 static Vc_INTRINSIC
const U *lo(Operations::scatter,
const U *ptr)
385 template <
typename U>
386 static Vc_INTRINSIC
const U *hi(Operations::scatter,
const U *ptr)
388 return ptr + secondOffset;
403 template <
typename U>
404 static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>())) lo(U &&x)
406 return loImpl(std::forward<U>(x));
408 template <
typename U>
409 static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>())) hi(U &&x)
411 return hiImpl(std::forward<U>(x));
414 template <
typename U>
415 static Vc_ALWAYS_INLINE enable_if<!have_lo_impl<U>(), U> lo(U &&x)
417 return std::forward<U>(x);
419 template <
typename U>
420 static Vc_ALWAYS_INLINE enable_if<!have_hi_impl<U>(), U> hi(U &&x)
422 return std::forward<U>(x);
428 template <
typename Op,
typename U, std::
size_t M,
typename V>
429 static Vc_INTRINSIC
const V &actual_value(Op,
const SimdArray<U, M, V, M> &x)
431 return internal_data(x);
433 template <
typename Op,
typename U, std::
size_t M,
typename V>
434 static Vc_INTRINSIC V *actual_value(Op, SimdArray<U, M, V, M> *x)
436 return &internal_data(*x);
438 template <
typename Op,
typename T,
size_t Pieces,
size_t Index>
439 static Vc_INTRINSIC
typename Segment<T, Pieces, Index>::simd_array_type actual_value(
440 Op, Segment<T, Pieces, Index> &&seg)
442 return seg.asSimdArray();
445 template <
typename Op,
typename U, std::
size_t M,
typename V>
446 static Vc_INTRINSIC
const typename V::Mask &actual_value(Op,
const SimdMaskArray<U, M, V, M> &x)
448 return internal_data(x);
450 template <
typename Op,
typename U, std::
size_t M,
typename V>
451 static Vc_INTRINSIC
typename V::Mask *actual_value(Op, SimdMaskArray<U, M, V, M> *x)
453 return &internal_data(*x);
475 template <
typename Op,
typename Arg>
476 Vc_INTRINSIC decltype(actual_value(std::declval<Op &>(), std::declval<Arg>()))
477 conditionalUnpack(
std::true_type, Op op, Arg &&arg)
479 return actual_value(op, std::forward<Arg>(arg));
482 template <
typename Op,
typename Arg>
483 Vc_INTRINSIC Arg conditionalUnpack(std::false_type, Op, Arg &&arg)
485 return std::forward<Arg>(arg);
489 template <
size_t A,
size_t B>
490 struct selectorType :
public std::integral_constant<bool, !((A & (size_t(1) << B)) != 0)> {
494 template <size_t I, typename Op, typename R, typename... Args, size_t... Indexes>
495 Vc_INTRINSIC decltype(std::declval<Op &>()(std::declval<R &>(),
496 conditionalUnpack(selectorType<I, Indexes>(),
497 std::declval<Op &>(),
498 std::declval<Args>())...))
499 unpackArgumentsAutoImpl(int, index_sequence<Indexes...>, Op op, R &&r, Args &&... args)
501 op(std::forward<R>(r),
502 conditionalUnpack(selectorType<I, Indexes>(), op, std::forward<Args>(args))...);
506 template <size_t I, typename Op, typename R, typename... Args, size_t... Indexes>
507 Vc_INTRINSIC enable_if<(I <= (size_t(1) << sizeof...(Args))), void> unpackArgumentsAutoImpl(
508 float, index_sequence<Indexes...> is, Op op, R &&r, Args &&... args)
515 I < (1 << sizeof...(Args)) - (std::is_same<R, std::nullptr_t>::value ? 1 : 0),
516 "Vc or compiler bug. Please report. Failed to find a combination of "
517 "actual_value(arg) transformations that allows calling Op.");
518 unpackArgumentsAutoImpl<I + 1, Op, R, Args...>(int(), is, op, std::forward<R>(r),
519 std::forward<Args>(args)...);
523 template <size_t, typename... Ts> struct IccWorkaround {
526 template <typename... Ts> struct IccWorkaround<2, Ts...> {
527 using type = typename std::remove_pointer<typename std::decay<
528 typename std::tuple_element<1, std::tuple<Ts...>>::type>::type>::type;
533 template <typename Op, typename R, typename... Args>
534 Vc_INTRINSIC void unpackArgumentsAuto(Op op, R &&r, Args &&... args)
540 const int recursionStart =
542 typename IccWorkaround<sizeof...(Args), Args...>::type>::value &&
543 (std::is_same<Op, Common::Operations::Forward_frexp>::value ||
544 std::is_same<Op, Common::Operations::Forward_ldexp>::value)
548 const int recursionStart = 0;
550 unpackArgumentsAutoImpl<recursionStart>(
551 int(), make_index_sequence<sizeof...(Args)>(), op, std::forward<R>(r),
552 std::forward<Args>(args)...);
SimdArray< T, N, V, M > ceil(const SimdArray< T, N, V, M > &x)
Applies the std:: ceil function component-wise and concurrently.
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 > log2(const Vc::Vector< T > &v)
Vc::Vector< T > exp(const Vc::Vector< T > &v)
SimdArray< T, N, V, M > floor(const SimdArray< T, N, V, M > &x)
Applies the std:: floor function component-wise and concurrently.
Vc::Vector< T > sin(const Vc::Vector< T > &v)
Vc::Vector< T > cos(const Vc::Vector< T > &v)
Vc::Vector< T > min(const Vc::Vector< T > &x, const Vc::Vector< T > &y)
Vc::Vector< T > reciprocal(const Vc::Vector< T > &v)
Returns the reciprocal of v.
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.
Vc::Vector< T > max(const Vc::Vector< T > &x, const Vc::Vector< T > &y)
Vc::Vector< T > log(const Vc::Vector< T > &v)
Vc::Vector< T > fma(Vc::Vector< T > a, Vc::Vector< T > b, Vc::Vector< T > c)
Multiplies a with b and then adds c, without rounding between the multiplication and the addition...
Vc::Vector< T > round(const Vc::Vector< T > &v)
Returns the closest integer to v; 0.5 is rounded to even.
Vc::Vector< T > rsqrt(const Vc::Vector< T > &v)
Returns the reciprocal square root of v.
SimdMaskArray< T, N, V, M > isnegative(const SimdArray< T, N, V, M > &x)
Applies the std:: isnegative function component-wise and concurrently.
Vc::Vector< T > log10(const Vc::Vector< T > &v)
SimdArray< T, N, V, M > trunc(const SimdArray< T, N, V, M > &x)
Applies the std:: trunc function component-wise and concurrently.
SimdArray< T, N, V, M > exponent(const SimdArray< T, N, V, M > &x)
Applies the std:: exponent function component-wise and concurrently.
Vc::Vector< T > atan2(const Vc::Vector< T > &y, const Vc::Vector< T > &x)
Calculates the angle given the lengths of the opposite and adjacent legs in a right triangle...
SimdArray< T, N, V, M > copysign(const SimdArray< T, N, V, M > &x, const SimdArray< T, N, V, M > &y)
Applies the std:: copysign function component-wise and concurrently.
Vc::Vector< T > atan(const Vc::Vector< T > &v)
Vc::Vector< T > asin(const Vc::Vector< T > &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 > isfinite(const Vc::Vector< T > &x)
Vc::Mask< T > isnan(const Vc::Vector< T > &x)
#define Vc_GCC
This macro is defined to a number identifying the GCC version if the current translation unit is comp...
void sincos(const SimdArray< T, N > &x, SimdArray< T, N > *sin, SimdArray< T, N > *cos)
Determines sine and cosine concurrently and component-wise on x.
Vc::Vector< T > sqrt(const Vc::Vector< T > &v)
Returns the square root of v.
SimdMaskArray< T, N, V, M > isinf(const SimdArray< T, N, V, M > &x)
Applies the std:: isinf function component-wise and concurrently.