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 { \
47 template <typename V, typename... Args> \
48 Vc_INTRINSIC void operator()(V &v, Args &&... args) \
50 v.name_(std::forward<Args>(args)...); \
53 Vc_DEFINE_OPERATION(gather);
54 Vc_DEFINE_OPERATION(scatter);
55 Vc_DEFINE_OPERATION(load);
56 Vc_DEFINE_OPERATION(store);
57 Vc_DEFINE_OPERATION(setZero);
58 Vc_DEFINE_OPERATION(setZeroInverted);
59 Vc_DEFINE_OPERATION(
assign);
60 #undef Vc_DEFINE_OPERATION
61 #define Vc_DEFINE_OPERATION(name_, code_) \
62 struct name_ : public tag { \
63 template <typename V> Vc_INTRINSIC void operator()(V &v) { code_; } \
65 Vc_DEFINE_OPERATION(increment, ++(v));
66 Vc_DEFINE_OPERATION(decrement, --(v));
67 Vc_DEFINE_OPERATION(random, v = V::Random());
68 #undef Vc_DEFINE_OPERATION
69 #define Vc_DEFINE_OPERATION_FORWARD(name_) \
70 struct Forward_##name_ : public tag \
72 template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \
73 Vc_INTRINSIC void operator()(decltype(name_(std::declval<Args>()...)) &v, \
76 v = name_(std::forward<Args>(args)...); \
78 template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \
79 Vc_INTRINSIC void operator()(std::nullptr_t, Args && ... args) \
81 name_(std::forward<Args>(args)...); \
84 Vc_DEFINE_OPERATION_FORWARD(
abs);
85 Vc_DEFINE_OPERATION_FORWARD(
asin);
86 Vc_DEFINE_OPERATION_FORWARD(
atan);
87 Vc_DEFINE_OPERATION_FORWARD(
atan2);
88 Vc_DEFINE_OPERATION_FORWARD(
cos);
89 Vc_DEFINE_OPERATION_FORWARD(ceil);
90 Vc_DEFINE_OPERATION_FORWARD(copysign);
91 Vc_DEFINE_OPERATION_FORWARD(
exp);
92 Vc_DEFINE_OPERATION_FORWARD(exponent);
93 Vc_DEFINE_OPERATION_FORWARD(
fma);
94 Vc_DEFINE_OPERATION_FORWARD(floor);
95 Vc_DEFINE_OPERATION_FORWARD(
frexp);
96 Vc_DEFINE_OPERATION_FORWARD(
isfinite);
97 Vc_DEFINE_OPERATION_FORWARD(isinf);
98 Vc_DEFINE_OPERATION_FORWARD(
isnan);
99 Vc_DEFINE_OPERATION_FORWARD(isnegative);
100 Vc_DEFINE_OPERATION_FORWARD(
ldexp);
101 Vc_DEFINE_OPERATION_FORWARD(
log);
102 Vc_DEFINE_OPERATION_FORWARD(
log10);
103 Vc_DEFINE_OPERATION_FORWARD(
log2);
105 Vc_DEFINE_OPERATION_FORWARD(
round);
106 Vc_DEFINE_OPERATION_FORWARD(
rsqrt);
107 Vc_DEFINE_OPERATION_FORWARD(
sin);
108 Vc_DEFINE_OPERATION_FORWARD(sincos);
109 Vc_DEFINE_OPERATION_FORWARD(
sqrt);
110 Vc_DEFINE_OPERATION_FORWARD(trunc);
111 Vc_DEFINE_OPERATION_FORWARD(
min);
112 Vc_DEFINE_OPERATION_FORWARD(
max);
113 #undef Vc_DEFINE_OPERATION_FORWARD
114 template<
typename T>
using is_operation = std::is_base_of<tag, T>;
122 template <
typename T_, std::
size_t Pieces_, std::
size_t Index_>
struct Segment
124 static_assert(Index_ < Pieces_,
"You found a bug in Vc. Please report.");
127 using type_decayed =
typename std::decay<type>::type;
128 static constexpr std::size_t Pieces = Pieces_;
129 static constexpr std::size_t Index = Index_;
130 using simd_array_type = SimdArray<
131 typename std::conditional<Traits::is_simd_vector<type_decayed>::value,
132 typename type_decayed::EntryType,
float>::type,
133 type_decayed::size() / Pieces>;
137 static constexpr std::size_t EntryOffset = Index * type_decayed::Size / Pieces;
139 decltype(std::declval<type>()[0]) operator[](
size_t i) {
return data[i + EntryOffset]; }
140 decltype(std::declval<type>()[0]) operator[](
size_t i)
const {
return data[i + EntryOffset]; }
142 simd_array_type asSimdArray()
const
144 return simd_cast<simd_array_type, Index>(data);
149 template <
typename T_, std::
size_t Pieces_, std::
size_t Index_>
150 struct Segment<T_ *, Pieces_, Index_> {
151 static_assert(Index_ < Pieces_,
"You found a bug in Vc. Please report.");
154 using type_decayed =
typename std::decay<T_>::type;
155 static constexpr
size_t Pieces = Pieces_;
156 static constexpr
size_t Index = Index_;
157 using simd_array_type = SimdArray<
158 typename std::conditional<Traits::is_simd_vector<type_decayed>::value,
159 typename type_decayed::VectorEntryType,
float>::type,
160 type_decayed::size() / Pieces> *;
164 static constexpr std::size_t EntryOffset = Index * type_decayed::size() / Pieces;
166 simd_array_type asSimdArray()
const
168 return reinterpret_cast<
172 typename std::remove_pointer<simd_array_type>::type
174 MayAlias<typename std::remove_pointer<simd_array_type>::type
>
193 template <
typename T, std::
size_t Offset>
struct AddOffset
195 constexpr AddOffset() =
default;
207 template <std::
size_t secondOffset>
class Split
209 static Vc_INTRINSIC AddOffset<VectorSpecialInitializerIndexesFromZero, secondOffset>
210 hiImpl(VectorSpecialInitializerIndexesFromZero)
214 template <std::
size_t Offset>
216 AddOffset<VectorSpecialInitializerIndexesFromZero, Offset + secondOffset>
217 hiImpl(AddOffset<VectorSpecialInitializerIndexesFromZero, Offset>)
223 template <
typename U, std::size_t N,
typename V, std::size_t M,
224 typename = enable_if<N != M>>
225 static Vc_INTRINSIC
auto loImpl(
const SimdArray<U, N, V, M> &x)
226 -> decltype(internal_data0(x))
228 return internal_data0(x);
230 template <
typename U, std::size_t N,
typename V, std::size_t M,
231 typename = enable_if<N != M>>
232 static Vc_INTRINSIC
auto hiImpl(
const SimdArray<U, N, V, M> &x)
233 -> decltype(internal_data1(x))
235 return internal_data1(x);
237 template <
typename U, std::size_t N,
typename V, std::size_t M,
238 typename = enable_if<N != M>>
239 static Vc_INTRINSIC
auto loImpl(SimdArray<U, N, V, M> *x)
240 -> decltype(&internal_data0(*x))
242 return &internal_data0(*x);
244 template <
typename U, std::size_t N,
typename V, std::size_t M,
245 typename = enable_if<N != M>>
246 static Vc_INTRINSIC
auto hiImpl(SimdArray<U, N, V, M> *x)
247 -> decltype(&internal_data1(*x))
249 return &internal_data1(*x);
253 template <
typename U, std::
size_t N,
typename V>
254 static Vc_INTRINSIC Segment<V, 2, 0> loImpl(
const SimdArray<U, N, V, N> &x)
256 return {internal_data(x)};
258 template <
typename U, std::
size_t N,
typename V>
259 static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(
const SimdArray<U, N, V, N> &x)
261 return {internal_data(x)};
263 template <
typename U, std::
size_t N,
typename V>
264 static Vc_INTRINSIC Segment<V *, 2, 0> loImpl(SimdArray<U, N, V, N> *x)
266 return {&internal_data(*x)};
268 template <
typename U, std::
size_t N,
typename V>
269 static Vc_INTRINSIC Segment<V *, 2, 1> hiImpl(SimdArray<U, N, V, N> *x)
271 return {&internal_data(*x)};
275 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
276 static Vc_INTRINSIC
auto loImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data0(x))
278 return internal_data0(x);
280 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
281 static Vc_INTRINSIC
auto hiImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data1(x))
283 return internal_data1(x);
286 template <
typename U, std::
size_t N,
typename V>
287 static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 0> loImpl(
288 const SimdMaskArray<U, N, V, N> &x)
290 return {internal_data(x)};
292 template <
typename U, std::
size_t N,
typename V>
293 static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 1> hiImpl(
294 const SimdMaskArray<U, N, V, N> &x)
296 return {internal_data(x)};
300 template <
typename T>
301 static constexpr
bool is_vector_or_mask(){
302 return (Traits::is_simd_vector<T>::value && !Traits::isSimdArray<T>::value) ||
303 (Traits::is_simd_mask<T>::value && !Traits::isSimdMaskArray<T>::value);
305 template <
typename V>
306 static Vc_INTRINSIC Segment<V, 2, 0> loImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
308 return {std::forward<V>(x)};
310 template <
typename V>
311 static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
313 return {std::forward<V>(x)};
317 template <
typename V, std::
size_t Pieces, std::
size_t Index>
318 static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index> loImpl(
319 const Segment<V, Pieces, Index> &x)
323 template <
typename V, std::
size_t Pieces, std::
size_t Index>
324 static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index + 1> hiImpl(
325 const Segment<V, Pieces, Index> &x)
334 template <
typename T,
typename = decltype(loImpl(std::declval<T>()))>
335 static std::true_type have_lo_impl(
int);
336 template <
typename T>
static std::false_type have_lo_impl(
float);
337 template <
typename T>
static constexpr
bool have_lo_impl()
339 return decltype(have_lo_impl<T>(1))::value;
342 template <
typename T,
typename = decltype(hiImpl(std::declval<T>()))>
343 static std::true_type have_hi_impl(
int);
344 template <
typename T>
static std::false_type have_hi_impl(
float);
345 template <
typename T>
static constexpr
bool have_hi_impl()
347 return decltype(have_hi_impl<T>(1))::value;
359 template <
typename U>
360 static Vc_INTRINSIC
const U *lo(Operations::gather,
const U *ptr)
364 template <
typename U>
365 static Vc_INTRINSIC
const U *hi(Operations::gather,
const U *ptr)
367 return ptr + secondOffset;
369 template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
370 static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>()))
371 lo(Operations::gather, U &&x)
373 return loImpl(std::forward<U>(x));
375 template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
376 static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>()))
377 hi(Operations::gather, U &&x)
379 return hiImpl(std::forward<U>(x));
381 template <
typename U>
382 static Vc_INTRINSIC
const U *lo(Operations::scatter,
const U *ptr)
386 template <
typename U>
387 static Vc_INTRINSIC
const U *hi(Operations::scatter,
const U *ptr)
389 return ptr + secondOffset;
404 template <
typename U>
405 static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>())) lo(U &&x)
407 return loImpl(std::forward<U>(x));
409 template <
typename U>
410 static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>())) hi(U &&x)
412 return hiImpl(std::forward<U>(x));
415 template <
typename U>
416 static Vc_ALWAYS_INLINE enable_if<!have_lo_impl<U>(), U> lo(U &&x)
418 return std::forward<U>(x);
420 template <
typename U>
421 static Vc_ALWAYS_INLINE enable_if<!have_hi_impl<U>(), U> hi(U &&x)
423 return std::forward<U>(x);
429 template <
typename Op,
typename U, std::
size_t M,
typename V>
430 static Vc_INTRINSIC
const V &actual_value(Op,
const SimdArray<U, M, V, M> &x)
432 return internal_data(x);
434 template <
typename Op,
typename U, std::
size_t M,
typename V>
435 static Vc_INTRINSIC V *actual_value(Op, SimdArray<U, M, V, M> *x)
437 return &internal_data(*x);
439 template <
typename Op,
typename T,
size_t Pieces,
size_t Index>
440 static Vc_INTRINSIC
typename Segment<T, Pieces, Index>::simd_array_type actual_value(
441 Op, Segment<T, Pieces, Index> &&seg)
443 return seg.asSimdArray();
446 template <
typename Op,
typename U, std::
size_t M,
typename V>
447 static Vc_INTRINSIC
const typename V::Mask &actual_value(Op,
const SimdMaskArray<U, M, V, M> &x)
449 return internal_data(x);
451 template <
typename Op,
typename U, std::
size_t M,
typename V>
452 static Vc_INTRINSIC
typename V::Mask *actual_value(Op, SimdMaskArray<U, M, V, M> *x)
454 return &internal_data(*x);
476 template <
typename Op,
typename Arg>
478 std::true_type, Op op, Arg &&arg)
480 return actual_value(op, std::forward<Arg>(arg));
485 return std::forward<Arg>(arg);
489 template <
size_t A,
size_t B,
size_t N>
490 using selectorType = std::integral_constant<bool, ((A & (1 << B)) != 0)>;
493 template <
typename... Args>
static constexpr
size_t icc_sizeof_workaround()
495 return sizeof...(Args);
499 template <
size_t I,
typename Op,
typename R,
typename... Args,
size_t... Indexes>
500 Vc_INTRINSIC decltype(std::declval<Op &>()(
503 std::declval<Op &>(), std::declval<Args>())...))
506 op(std::forward<R>(r),
508 std::forward<Args>(args))...);
512 template <
size_t I,
typename Op,
typename R,
typename... Args,
size_t... Indexes>
514 R &&r, Args &&... args)
516 static_assert(I < (1 <<
sizeof...(Args)),
517 "Vc or compiler bug. Please report. Failed to find a combination of "
518 "actual_value(arg) transformations that allows calling Op.");
520 std::forward<Args>(args)...);
524 template <
typename Op,
typename R,
typename... Args>
533 std::is_same<R, std::nullptr_t>::value ? 1 : 0>(
534 int(), make_index_sequence<
sizeof...(Args)>(), op, std::forward<R>(r),
535 std::forward<Args>(args)...);
544 #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 > log2(const Vc::Vector< T > &v)
Vc::Vector< T > exp(const Vc::Vector< T > &v)
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.
Arg conditionalUnpack(std::false_type, Op, Arg &&arg)
forwards arg to its return value
Vc::Vector< T > max(const Vc::Vector< T > &x, const Vc::Vector< T > &y)
Vc::Vector< T > log(const Vc::Vector< T > &v)
void unpackArgumentsAuto(Op op, R &&r, Args &&...args)
The interface to start the machinery.
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...
enable_if< std::is_same< To, Traits::decay< From > >::value, To > simd_cast(From &&x)
Casts the argument x from type From to type To.
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.
Vc::Vector< T > log10(const Vc::Vector< T > &v)
std::integral_constant< bool,((A &(1<< B))!=0)> selectorType
true-/false_type that selects whether the argument with index B should be unpacked ...
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...
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)
void unpackArgumentsAutoImpl(float, index_sequence< Indexes... > is, Op op, R &&r, Args &&...args)
the current actual_value calls don't work: recurse to I + 1
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...
Vc::Vector< T > sqrt(const Vc::Vector< T > &v)
Returns the square root of v.