28 #ifndef VC_COMMON_SIMDARRAYHELPER_H_ 29 #define VC_COMMON_SIMDARRAYHELPER_H_ 33 namespace Vc_VERSIONED_NAMESPACE
38 static constexpr
struct private_init_t {} private_init = {};
51 #define Vc_DEFINE_OPERATION(name_) \ 52 struct name_ : public tag { \ 53 template <typename V, typename... Args> \ 54 Vc_INTRINSIC void operator()(V &v, Args &&... args) \ 56 v.name_(std::forward<Args>(args)...); \ 59 Vc_DEFINE_OPERATION(gather);
60 Vc_DEFINE_OPERATION(scatter);
61 Vc_DEFINE_OPERATION(load);
62 Vc_DEFINE_OPERATION(store);
63 Vc_DEFINE_OPERATION(setZero);
64 Vc_DEFINE_OPERATION(setZeroInverted);
65 Vc_DEFINE_OPERATION(assign);
66 #undef Vc_DEFINE_OPERATION 67 #define Vc_DEFINE_OPERATION(name_, code_) \ 68 struct name_ : public tag { \ 69 template <typename V> Vc_INTRINSIC void operator()(V &v) { code_; } \ 71 Vc_DEFINE_OPERATION(increment, ++(v));
72 Vc_DEFINE_OPERATION(decrement, --(v));
73 Vc_DEFINE_OPERATION(random, v = V::Random());
74 #undef Vc_DEFINE_OPERATION 75 #define Vc_DEFINE_OPERATION_FORWARD(name_) \ 76 struct Forward_##name_ : public tag \ 78 template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \ 79 Vc_INTRINSIC void operator()(decltype(name_(std::declval<Args>()...)) &v, \ 82 v = name_(std::forward<Args>(args)...); \ 84 template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \ 85 Vc_INTRINSIC void operator()(std::nullptr_t, Args && ... args) \ 87 name_(std::forward<Args>(args)...); \ 90 Vc_DEFINE_OPERATION_FORWARD(
abs);
91 Vc_DEFINE_OPERATION_FORWARD(
asin);
92 Vc_DEFINE_OPERATION_FORWARD(
atan);
93 Vc_DEFINE_OPERATION_FORWARD(
atan2);
94 Vc_DEFINE_OPERATION_FORWARD(
cos);
95 Vc_DEFINE_OPERATION_FORWARD(
ceil);
96 Vc_DEFINE_OPERATION_FORWARD(
copysign);
97 Vc_DEFINE_OPERATION_FORWARD(
exp);
98 Vc_DEFINE_OPERATION_FORWARD(
exponent);
99 Vc_DEFINE_OPERATION_FORWARD(
fma);
100 Vc_DEFINE_OPERATION_FORWARD(
floor);
101 Vc_DEFINE_OPERATION_FORWARD(
frexp);
102 Vc_DEFINE_OPERATION_FORWARD(
isfinite);
103 Vc_DEFINE_OPERATION_FORWARD(
isinf);
104 Vc_DEFINE_OPERATION_FORWARD(
isnan);
106 Vc_DEFINE_OPERATION_FORWARD(
ldexp);
107 Vc_DEFINE_OPERATION_FORWARD(
log);
108 Vc_DEFINE_OPERATION_FORWARD(
log10);
109 Vc_DEFINE_OPERATION_FORWARD(
log2);
111 Vc_DEFINE_OPERATION_FORWARD(
round);
112 Vc_DEFINE_OPERATION_FORWARD(
rsqrt);
113 Vc_DEFINE_OPERATION_FORWARD(
sin);
114 Vc_DEFINE_OPERATION_FORWARD(
sincos);
115 Vc_DEFINE_OPERATION_FORWARD(
sqrt);
116 Vc_DEFINE_OPERATION_FORWARD(
trunc);
117 Vc_DEFINE_OPERATION_FORWARD(
min);
118 Vc_DEFINE_OPERATION_FORWARD(
max);
119 #undef Vc_DEFINE_OPERATION_FORWARD 120 template<
typename T>
using is_operation = std::is_base_of<tag, T>;
130 template <
typename T_, std::
size_t Pieces_, std::
size_t Index_>
struct Segment
132 static_assert(Index_ < Pieces_,
"You found a bug in Vc. Please report.");
135 using type_decayed =
typename std::decay<type>::type;
136 static constexpr std::size_t Pieces = Pieces_;
137 static constexpr std::size_t Index = Index_;
138 using simd_array_type = SimdArray<
139 typename std::conditional<Traits::is_simd_vector<type_decayed>::value,
140 typename type_decayed::EntryType,
float>::type,
141 type_decayed::Size / Pieces>;
145 static constexpr std::size_t EntryOffset = Index * type_decayed::Size / Pieces;
148 decltype(std::declval<const type &>()[0]) operator[](
size_t i)
const {
return data[i + EntryOffset]; }
150 simd_array_type asSimdArray()
const 152 return simd_cast<simd_array_type, Index>(data);
157 template <
typename T_, std::
size_t Pieces_, std::
size_t Index_>
158 struct Segment<T_ *, Pieces_, Index_> {
159 static_assert(Index_ < Pieces_,
"You found a bug in Vc. Please report.");
162 using type_decayed =
typename std::decay<T_>::type;
163 static constexpr
size_t Pieces = Pieces_;
164 static constexpr
size_t Index = Index_;
165 using simd_array_type = SimdArray<
166 typename std::conditional<Traits::is_simd_vector<type_decayed>::value,
167 typename type_decayed::VectorEntryType,
float>::type,
168 type_decayed::Size / Pieces> *;
172 static constexpr std::size_t EntryOffset = Index * type_decayed::size() / Pieces;
174 simd_array_type asSimdArray()
const 176 return reinterpret_cast< 180 typename std::remove_pointer<simd_array_type>::type
182 MayAlias<typename std::remove_pointer<simd_array_type>::type
> 201 template <
typename T, std::
size_t Offset>
struct AddOffset
203 constexpr AddOffset() =
default;
215 template <std::
size_t secondOffset>
class Split
219 struct GeneratorOffset {
221 Vc_INTRINSIC decltype(gen(std::size_t())) operator()(
std::
size_t i)
223 return gen(i + secondOffset);
226 template <
class G,
class = decltype(std::declval<G>()(std::
size_t())),
227 class =
typename std::enable_if<!Traits::is_simd_vector<G>::value>::type>
228 static Vc_INTRINSIC GeneratorOffset<G> hiImpl(G &&gen)
230 return {std::forward<G>(gen)};
234 static Vc_INTRINSIC AddOffset<VectorSpecialInitializerIndexesFromZero, secondOffset>
235 hiImpl(VectorSpecialInitializerIndexesFromZero)
239 template <std::
size_t Offset>
241 AddOffset<VectorSpecialInitializerIndexesFromZero, Offset + secondOffset>
242 hiImpl(AddOffset<VectorSpecialInitializerIndexesFromZero, Offset>)
248 template <
typename U, std::size_t N,
typename V, std::size_t M,
249 typename = enable_if<N != M>>
250 static Vc_INTRINSIC
auto loImpl(
const SimdArray<U, N, V, M> &x)
251 -> decltype(internal_data0(x))
253 return internal_data0(x);
255 template <
typename U, std::size_t N,
typename V, std::size_t M,
256 typename = enable_if<N != M>>
257 static Vc_INTRINSIC
auto hiImpl(
const SimdArray<U, N, V, M> &x)
258 -> decltype(internal_data1(x))
260 return internal_data1(x);
262 template <
typename U, std::size_t N,
typename V, std::size_t M,
263 typename = enable_if<N != M>>
264 static Vc_INTRINSIC
auto loImpl(SimdArray<U, N, V, M> *x)
265 -> decltype(&internal_data0(*x))
267 return &internal_data0(*x);
269 template <
typename U, std::size_t N,
typename V, std::size_t M,
270 typename = enable_if<N != M>>
271 static Vc_INTRINSIC
auto hiImpl(SimdArray<U, N, V, M> *x)
272 -> decltype(&internal_data1(*x))
274 return &internal_data1(*x);
278 template <
typename U, std::
size_t N,
typename V>
279 static Vc_INTRINSIC Segment<V, 2, 0> loImpl(
const SimdArray<U, N, V, N> &x)
281 return {internal_data(x)};
283 template <
typename U, std::
size_t N,
typename V>
284 static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(
const SimdArray<U, N, V, N> &x)
286 return {internal_data(x)};
288 template <
typename U, std::
size_t N,
typename V>
289 static Vc_INTRINSIC Segment<V *, 2, 0> loImpl(SimdArray<U, N, V, N> *x)
291 return {&internal_data(*x)};
293 template <
typename U, std::
size_t N,
typename V>
294 static Vc_INTRINSIC Segment<V *, 2, 1> hiImpl(SimdArray<U, N, V, N> *x)
296 return {&internal_data(*x)};
300 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
301 static Vc_INTRINSIC
auto loImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data0(x))
303 return internal_data0(x);
305 template <
typename U, std::
size_t N,
typename V, std::
size_t M>
306 static Vc_INTRINSIC
auto hiImpl(
const SimdMaskArray<U, N, V, M> &x) -> decltype(internal_data1(x))
308 return internal_data1(x);
311 template <
typename U, std::
size_t N,
typename V>
312 static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 0> loImpl(
313 const SimdMaskArray<U, N, V, N> &x)
315 return {internal_data(x)};
317 template <
typename U, std::
size_t N,
typename V>
318 static Vc_INTRINSIC Segment<typename SimdMaskArray<U, N, V, N>::mask_type, 2, 1> hiImpl(
319 const SimdMaskArray<U, N, V, N> &x)
321 return {internal_data(x)};
325 template <
typename T>
326 static constexpr
bool is_vector_or_mask(){
327 return (Traits::is_simd_vector<T>::value && !Traits::isSimdArray<T>::value) ||
328 (Traits::is_simd_mask<T>::value && !Traits::isSimdMaskArray<T>::value);
330 template <
typename V>
331 static Vc_INTRINSIC Segment<V, 2, 0> loImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
333 return {std::forward<V>(x)};
335 template <
typename V>
336 static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
338 return {std::forward<V>(x)};
342 template <
typename V, std::
size_t Pieces, std::
size_t Index>
343 static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index> loImpl(
344 const Segment<V, Pieces, Index> &x)
348 template <
typename V, std::
size_t Pieces, std::
size_t Index>
349 static Vc_INTRINSIC Segment<V, 2 * Pieces, 2 * Index + 1> hiImpl(
350 const Segment<V, Pieces, Index> &x)
359 template <
typename T,
typename = decltype(loImpl(std::declval<T>()))>
360 static std::true_type have_lo_impl(
int);
361 template <
typename T>
static std::false_type have_lo_impl(
float);
362 template <
typename T>
static constexpr
bool have_lo_impl()
364 return decltype(have_lo_impl<T>(1))::value;
367 template <
typename T,
typename = decltype(hiImpl(std::declval<T>()))>
368 static std::true_type have_hi_impl(
int);
369 template <
typename T>
static std::false_type have_hi_impl(
float);
370 template <
typename T>
static constexpr
bool have_hi_impl()
372 return decltype(have_hi_impl<T>(1))::value;
384 template <
typename U>
385 static Vc_INTRINSIC
const U *lo(Operations::gather,
const U *ptr)
389 template <
typename U>
390 static Vc_INTRINSIC
const U *hi(Operations::gather,
const U *ptr)
392 return ptr + secondOffset;
394 template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
395 static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>()))
396 lo(Operations::gather, U &&x)
398 return loImpl(std::forward<U>(x));
400 template <typename U, typename = enable_if<!std::is_pointer<U>::value>>
401 static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>()))
402 hi(Operations::gather, U &&x)
404 return hiImpl(std::forward<U>(x));
406 template <
typename U>
407 static Vc_INTRINSIC
const U *lo(Operations::scatter,
const U *ptr)
411 template <
typename U>
412 static Vc_INTRINSIC
const U *hi(Operations::scatter,
const U *ptr)
414 return ptr + secondOffset;
429 template <
typename U>
430 static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>())) lo(U &&x)
432 return loImpl(std::forward<U>(x));
434 template <
typename U>
435 static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>())) hi(U &&x)
437 return hiImpl(std::forward<U>(x));
440 template <
typename U>
441 static Vc_ALWAYS_INLINE enable_if<!have_lo_impl<U>(), U> lo(U &&x)
443 return std::forward<U>(x);
445 template <
typename U>
446 static Vc_ALWAYS_INLINE enable_if<!have_hi_impl<U>(), U> hi(U &&x)
448 return std::forward<U>(x);
454 template <
typename Op,
typename U, std::
size_t M,
typename V>
455 static Vc_INTRINSIC
const V &actual_value(Op,
const SimdArray<U, M, V, M> &x)
457 return internal_data(x);
459 template <
typename Op,
typename U, std::
size_t M,
typename V>
460 static Vc_INTRINSIC V *actual_value(Op, SimdArray<U, M, V, M> *x)
462 return &internal_data(*x);
464 template <
typename Op,
typename T,
size_t Pieces,
size_t Index>
465 static Vc_INTRINSIC
typename Segment<T, Pieces, Index>::simd_array_type actual_value(
466 Op, Segment<T, Pieces, Index> &&seg)
468 return seg.asSimdArray();
471 template <
typename Op,
typename U, std::
size_t M,
typename V>
472 static Vc_INTRINSIC
const typename V::Mask &actual_value(Op,
const SimdMaskArray<U, M, V, M> &x)
474 return internal_data(x);
476 template <
typename Op,
typename U, std::
size_t M,
typename V>
477 static Vc_INTRINSIC
typename V::Mask *actual_value(Op, SimdMaskArray<U, M, V, M> *x)
479 return &internal_data(*x);
501 template <
typename Op,
typename Arg>
502 Vc_INTRINSIC decltype(actual_value(std::declval<Op &>(), std::declval<Arg>()))
503 conditionalUnpack(
std::true_type, Op op, Arg &&arg)
505 return actual_value(op, std::forward<Arg>(arg));
508 template <
typename Op,
typename Arg>
509 Vc_INTRINSIC Arg conditionalUnpack(std::false_type, Op, Arg &&arg)
511 return std::forward<Arg>(arg);
515 template <
size_t A,
size_t B>
516 struct selectorType :
public std::integral_constant<bool, !((A & (size_t(1) << B)) != 0)> {
520 template <size_t I, typename Op, typename R, typename... Args, size_t... Indexes>
521 Vc_INTRINSIC decltype(std::declval<Op &>()(std::declval<R &>(),
522 conditionalUnpack(selectorType<I, Indexes>(),
523 std::declval<Op &>(),
524 std::declval<Args>())...))
525 unpackArgumentsAutoImpl(int, index_sequence<Indexes...>, Op op, R &&r, Args &&... args)
527 op(std::forward<R>(r),
528 conditionalUnpack(selectorType<I, Indexes>(), op, std::forward<Args>(args))...);
532 template <size_t I, typename Op, typename R, typename... Args, size_t... Indexes>
533 Vc_INTRINSIC enable_if<(I <= (size_t(1) << sizeof...(Args))), void> unpackArgumentsAutoImpl(
534 float, index_sequence<Indexes...> is, Op op, R &&r, Args &&... args)
541 I < (1 << sizeof...(Args)) - (std::is_same<R, std::nullptr_t>::value ? 1 : 0),
542 "Vc or compiler bug. Please report. Failed to find a combination of "
543 "actual_value(arg) transformations that allows calling Op.");
544 unpackArgumentsAutoImpl<I + 1, Op, R, Args...>(int(), is, op, std::forward<R>(r),
545 std::forward<Args>(args)...);
549 template <size_t, typename... Ts> struct IccWorkaround {
552 template <typename... Ts> struct IccWorkaround<2, Ts...> {
553 using type = typename std::remove_pointer<typename std::decay<
554 typename std::tuple_element<1, std::tuple<Ts...>>::type>::type>::type;
559 template <typename Op, typename R, typename... Args>
560 Vc_INTRINSIC void unpackArgumentsAuto(Op op, R &&r, Args &&... args)
566 const int recursionStart =
568 typename IccWorkaround<sizeof...(Args), Args...>::type>::value &&
569 (std::is_same<Op, Common::Operations::Forward_frexp>::value ||
570 std::is_same<Op, Common::Operations::Forward_ldexp>::value)
574 const int recursionStart = 0;
576 unpackArgumentsAutoImpl<recursionStart>(
577 int(), make_index_sequence<sizeof...(Args)>(), op, std::forward<R>(r),
578 std::forward<Args>(args)...);
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 > 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.
fixed_size_simd< T, N > floor(const SimdArray< T, N, V, M > &x)
Applies the std:: floor function component-wise and concurrently.
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.
fixed_size_simd< T, N > atan(const SimdArray< T, N, V, M > &x)
Applies the std:: atan function component-wise and concurrently.
fixed_size_simd< T, N > 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 > max(const Vc::Vector< T > &x, const Vc::Vector< T > &y)
fixed_size_simd< T, N > atan2(const SimdArray< T, N, V, M > &x, const SimdArray< T, N, V, M > &y)
Applies the std:: atan2 function component-wise and concurrently.
fixed_size_simd< T, N > asin(const SimdArray< T, N, V, M > &x)
Applies the std:: asin function component-wise and concurrently.
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.
fixed_size_simd_mask< T, N > 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)
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...
fixed_size_simd< T, N > cos(const SimdArray< T, N, V, M > &x)
Applies the std:: cos function component-wise and concurrently.
fixed_size_simd< T, N > sin(const SimdArray< T, N, V, M > &x)
Applies the std:: sin function component-wise and concurrently.
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.
fixed_size_simd< T, N > trunc(const SimdArray< T, N, V, M > &x)
Applies the std:: trunc function component-wise and concurrently.
fixed_size_simd_mask< T, N > isinf(const SimdArray< T, N, V, M > &x)
Applies the std:: isinf function component-wise and concurrently.
fixed_size_simd< T, N > exponent(const SimdArray< T, N, V, M > &x)
Applies the std:: exponent function component-wise and concurrently.
Vc::Vector< T > sqrt(const Vc::Vector< T > &v)
Returns the square root of v.
fixed_size_simd< T, N > ceil(const SimdArray< T, N, V, M > &x)
Applies the std:: ceil function component-wise and concurrently.