Vc  1.3.2-dev
SIMD Vector Classes for C++
simdarrayhelper.h
1 /* This file is part of the Vc library. {{{
2 Copyright © 2013-2015 Matthias Kretz <kretz@kde.org>
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6  * Redistributions of source code must retain the above copyright
7  notice, this list of conditions and the following disclaimer.
8  * Redistributions in binary form must reproduce the above copyright
9  notice, this list of conditions and the following disclaimer in the
10  documentation and/or other materials provided with the distribution.
11  * Neither the names of contributing organizations nor the
12  names of its contributors may be used to endorse or promote products
13  derived from this software without specific prior written permission.
14 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 }}}*/
27 
28 #ifndef VC_COMMON_SIMDARRAYHELPER_H_
29 #define VC_COMMON_SIMDARRAYHELPER_H_
30 
31 #include "macros.h"
32 
33 namespace Vc_VERSIONED_NAMESPACE
34 {
35 namespace Common
36 {
37 
40 
41 namespace Operations/*{{{*/
42 {
43 struct tag {};
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) \
48  { \
49  v.name_(std::forward<Args>(args)...); \
50  } \
51  }
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_; } \
63  }
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 \
70  { \
71  template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \
72  Vc_INTRINSIC void operator()(decltype(name_(std::declval<Args>()...)) &v, \
73  Args &&... args) \
74  { \
75  v = name_(std::forward<Args>(args)...); \
76  } \
77  template <typename... Args, typename = decltype(name_(std::declval<Args>()...))> \
78  Vc_INTRINSIC void operator()(std::nullptr_t, Args && ... args) \
79  { \
80  name_(std::forward<Args>(args)...); \
81  } \
82  }
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);
98 Vc_DEFINE_OPERATION_FORWARD(isnegative);
99 Vc_DEFINE_OPERATION_FORWARD(ldexp);
100 Vc_DEFINE_OPERATION_FORWARD(log);
101 Vc_DEFINE_OPERATION_FORWARD(log10);
102 Vc_DEFINE_OPERATION_FORWARD(log2);
103 Vc_DEFINE_OPERATION_FORWARD(reciprocal);
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>;
114 } // namespace Operations }}}
115 
121 template <typename T_, std::size_t Pieces_, std::size_t Index_> struct Segment/*{{{*/
122 {
123  static_assert(Index_ < Pieces_, "You found a bug in Vc. Please report.");
124 
125  using type = T_;
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>;
133 
134  type data;
135 
136  static constexpr std::size_t EntryOffset = Index * type_decayed::Size / Pieces;
137 
138  // no non-const operator[] needed
139  decltype(std::declval<const type &>()[0]) operator[](size_t i) const { return data[i + EntryOffset]; }
140 
141  simd_array_type asSimdArray() const
142  {
143  return simd_cast<simd_array_type, Index>(data);
144  }
145 };/*}}}*/
146 
147 //Segment<T *, ...> specialization {{{
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.");
151 
152  using type = T_ *;
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> *;
160 
161  type data;
162 
163  static constexpr std::size_t EntryOffset = Index * type_decayed::size() / Pieces;
164 
165  simd_array_type asSimdArray() const
166  {
167  return reinterpret_cast<
168 #ifdef Vc_GCC
169  // GCC might ICE if this type is declared with may_alias. If it doesn't
170  // ICE it warns about ignoring the attribute.
171  typename std::remove_pointer<simd_array_type>::type
172 #else
173  MayAlias<typename std::remove_pointer<simd_array_type>::type>
174 #endif
175  *>(data) +
176  Index;
177  }
178 
179  //decltype(std::declval<type>()[0]) operator[](size_t i) { return data[i + EntryOffset]; }
180  //decltype(std::declval<type>()[0]) operator[](size_t i) const { return data[i + EntryOffset]; }
181 };/*}}}*/
182 
192 template <typename T, std::size_t Offset> struct AddOffset
193 {
194  constexpr AddOffset() = default;
195 };
196 
197 // class Split {{{1
206 template <std::size_t secondOffset> class Split
207 {
208  static Vc_INTRINSIC AddOffset<VectorSpecialInitializerIndexesFromZero, secondOffset>
209  hiImpl(VectorSpecialInitializerIndexesFromZero)
210  {
211  return {};
212  }
213  template <std::size_t Offset>
214  static Vc_INTRINSIC
215  AddOffset<VectorSpecialInitializerIndexesFromZero, Offset + secondOffset>
216  hiImpl(AddOffset<VectorSpecialInitializerIndexesFromZero, Offset>)
217  {
218  return {};
219  }
220 
221  // split composite SimdArray
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))
226  {
227  return internal_data0(x);
228  }
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))
233  {
234  return internal_data1(x);
235  }
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))
240  {
241  return &internal_data0(*x);
242  }
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))
247  {
248  return &internal_data1(*x);
249  }
250 
251  // split atomic SimdArray
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)
254  {
255  return {internal_data(x)};
256  }
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)
259  {
260  return {internal_data(x)};
261  }
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)
264  {
265  return {&internal_data(*x)};
266  }
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)
269  {
270  return {&internal_data(*x)};
271  }
272 
273  // split composite SimdMaskArray
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))
276  {
277  return internal_data0(x);
278  }
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))
281  {
282  return internal_data1(x);
283  }
284 
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)
288  {
289  return {internal_data(x)};
290  }
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)
294  {
295  return {internal_data(x)};
296  }
297 
298  // split Vector<T> and Mask<T>
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);
303  }
304  template <typename V>
305  static Vc_INTRINSIC Segment<V, 2, 0> loImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
306  {
307  return {std::forward<V>(x)};
308  }
309  template <typename V>
310  static Vc_INTRINSIC Segment<V, 2, 1> hiImpl(V &&x, enable_if<is_vector_or_mask<V>()> = nullarg)
311  {
312  return {std::forward<V>(x)};
313  }
314 
315  // generically split Segments
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)
319  {
320  return {x.data};
321  }
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)
325  {
326  return {x.data};
327  }
328 
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()
337  {
338  return decltype(have_lo_impl<T>(1))::value;
339  }
340 
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()
345  {
346  return decltype(have_hi_impl<T>(1))::value;
347  }
349 
350 public:
358  template <typename U>
359  static Vc_INTRINSIC const U *lo(Operations::gather, const U *ptr)
360  {
361  return ptr;
362  }
363  template <typename U>
364  static Vc_INTRINSIC const U *hi(Operations::gather, const U *ptr)
365  {
366  return ptr + secondOffset;
367  }
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)
371  {
372  return loImpl(std::forward<U>(x));
373  }
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)
377  {
378  return hiImpl(std::forward<U>(x));
379  }
380  template <typename U>
381  static Vc_INTRINSIC const U *lo(Operations::scatter, const U *ptr)
382  {
383  return ptr;
384  }
385  template <typename U>
386  static Vc_INTRINSIC const U *hi(Operations::scatter, const U *ptr)
387  {
388  return ptr + secondOffset;
389  }
391 
403  template <typename U>
404  static Vc_ALWAYS_INLINE decltype(loImpl(std::declval<U>())) lo(U &&x)
405  {
406  return loImpl(std::forward<U>(x));
407  }
408  template <typename U>
409  static Vc_ALWAYS_INLINE decltype(hiImpl(std::declval<U>())) hi(U &&x)
410  {
411  return hiImpl(std::forward<U>(x));
412  }
413 
414  template <typename U>
415  static Vc_ALWAYS_INLINE enable_if<!have_lo_impl<U>(), U> lo(U &&x)
416  {
417  return std::forward<U>(x);
418  }
419  template <typename U>
420  static Vc_ALWAYS_INLINE enable_if<!have_hi_impl<U>(), U> hi(U &&x)
421  {
422  return std::forward<U>(x);
423  }
425 };
426 
427 // actual_value {{{1
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)
430 {
431  return internal_data(x);
432 }
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)
435 {
436  return &internal_data(*x);
437 }
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)
441 {
442  return seg.asSimdArray();
443 }
444 
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)
447 {
448  return internal_data(x);
449 }
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)
452 {
453  return &internal_data(*x);
454 }
455 
456 // unpackArgumentsAuto {{{1
472 
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)
478 {
479  return actual_value(op, std::forward<Arg>(arg));
480 }
482 template <typename Op, typename Arg>
483 Vc_INTRINSIC Arg conditionalUnpack(std::false_type, Op, Arg &&arg)
484 {
485  return std::forward<Arg>(arg);
486 }
487 
489 template <size_t A, size_t B>
490 struct selectorType : public std::integral_constant<bool, !((A & (size_t(1) << B)) != 0)> {
491 };
492 
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)
500 {
501  op(std::forward<R>(r),
502  conditionalUnpack(selectorType<I, Indexes>(), op, std::forward<Args>(args))...);
503 }
504 
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)
509 {
510  // if R is nullptr_t then the return type cannot enforce that actually any unwrapping
511  // of the SimdArray types happens. Thus, you could get an endless loop of the
512  // SimdArray function overload calling itself, if the index goes up to (1 <<
513  // sizeof...(Args)) - 1 (which means no argument transformations via actual_value).
514  static_assert(
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)...);
520 }
521 
522 #ifdef Vc_ICC
523 template <size_t, typename... Ts> struct IccWorkaround {
524  using type = void;
525 };
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;
529 };
530 #endif
531 
533 template <typename Op, typename R, typename... Args>
534 Vc_INTRINSIC void unpackArgumentsAuto(Op op, R &&r, Args &&... args)
535 {
536 #ifdef Vc_ICC
537  // ugly hacky workaround for ICC:
538  // The compiler fails to do SFINAE right on recursion. We have to hit the right
539  // recursionStart number from the start.
540  const int recursionStart =
541  Traits::isSimdArray<
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)
545  ? 2
546  : 0;
547 #else
548  const int recursionStart = 0;
549 #endif
550  unpackArgumentsAutoImpl<recursionStart>(
551  int(), make_index_sequence<sizeof...(Args)>(), op, std::forward<R>(r),
552  std::forward<Args>(args)...);
553 }
555 
556 //}}}1
558 } // namespace Common
559 } // namespace Vc
560 
561 #endif // VC_COMMON_SIMDARRAYHELPER_H_
562 
563 // vim: foldmethod=marker
SimdArray< T, N, V, M > ceil(const SimdArray< T, N, V, M > &x)
Applies the std:: ceil function component-wise and concurrently.
Definition: simdarray.h:1687
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.
Definition: simdarray.h:1692
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)
Definition: vector.h:257
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.
Definition: simdarray.h:1719
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.
Definition: simdarray.h:1746
SimdArray< T, N, V, M > exponent(const SimdArray< T, N, V, M > &x)
Applies the std:: exponent function component-wise and concurrently.
Definition: simdarray.h:1691
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.
Definition: simdarray.h:1688
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.
Definition: simdize.h:1008
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...
Definition: global.h:74
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.
Definition: simdarray.h:1741
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.
Definition: simdarray.h:1701