28 #ifndef VC_COMMON_SIMDIZE_H_
29 #define VC_COMMON_SIMDIZE_H_
89 namespace Vc_VERSIONED_NAMESPACE
97 namespace SimdizeDetail
104 using std::is_base_of;
105 using std::false_type;
106 using std::true_type;
107 using std::iterator_traits;
108 using std::conditional;
110 template <
bool B,
typename T,
typename F>
111 using conditional_t =
typename conditional<B, T, F>::type;
117 template <
typename... Ts>
struct Typelist;
122 enum class Category {
126 ArithmeticVectorizable,
134 BidirectionalIterator,
136 RandomAccessIterator,
145 template <
typename T,
typename ItCat =
typename T::iterator_category>
146 constexpr Category iteratorCategories(
int, ItCat * =
nullptr)
148 return is_base_of<std::random_access_iterator_tag, ItCat>::value
149 ? Category::RandomAccessIterator
150 : is_base_of<std::bidirectional_iterator_tag, ItCat>::value
151 ? Category::BidirectionalIterator
152 : is_base_of<std::forward_iterator_tag, ItCat>::value
153 ? Category::ForwardIterator
154 : is_base_of<std::output_iterator_tag, ItCat>::value
155 ? Category::OutputIterator
156 : is_base_of<std::input_iterator_tag, ItCat>::value
157 ? Category::InputIterator
163 template <
typename T>
164 constexpr enable_if<std::is_pointer<T>::value, Category> iteratorCategories(
float)
166 return Category::RandomAccessIterator;
171 template <
typename T> constexpr Category iteratorCategories(...)
173 return Category::None;
179 template <
typename T>
struct is_class_template :
public false_type
182 template <
template <
typename...>
class C,
typename... Ts>
183 struct is_class_template<C<Ts...>> :
public true_type
190 template <
typename T> constexpr Category typeCategory()
192 return (is_same<T, bool>::value || is_same<T, short>::value ||
193 is_same<T, unsigned short>::value || is_same<T, int>::value ||
194 is_same<T, unsigned int>::value || is_same<T, float>::value ||
195 is_same<T, double>::value)
196 ? Category::ArithmeticVectorizable
197 : iteratorCategories<T>(int()) != Category::None
198 ? iteratorCategories<T>(
int())
199 : is_class_template<T>::value ? Category::ClassTemplate
208 template <typename T, size_t TupleSize = std::tuple_size<T>::value>
209 constexpr
size_t determine_tuple_size()
213 template <
typename T,
size_t TupleSize = T::tuple_size>
214 constexpr
size_t determine_tuple_size(
size_t = T::tuple_size)
221 template <
typename T>
struct determine_tuple_size_
222 :
public std::integral_constant<size_t, determine_tuple_size<T>()>
227 template <
typename T>
struct The_simdization_for_the_requested_type_is_not_implemented;
242 template <
typename T,
size_t N,
typename MT, Category = typeCategory<T>()>
243 struct ReplaceTypes :
public The_simdization_for_the_requested_type_is_not_implemented<T>
251 template <
typename T,
size_t N,
typename MT>
struct ReplaceTypes<T, N, MT, Category::None>
260 template <
typename T,
size_t N = 0,
typename MT =
void>
261 using simdize =
typename SimdizeDetail::ReplaceTypes<T, N, MT>::type;
267 template <
typename T,
size_t N,
typename MT>
268 struct ReplaceTypes<T, N, MT, Category::ArithmeticVectorizable>
269 :
public conditional<(N == 0 || Vector<T>::Size == N), Vector<T>, SimdArray<T, N>>
277 template <
size_t N,
typename MT>
278 struct ReplaceTypes<bool, N, MT, Category::ArithmeticVectorizable>
279 :
public conditional<(N == 0 || Mask<MT>::Size == N), Mask<MT>,
280 SimdMaskArray<MT, N>>
287 struct ReplaceTypes<bool, N, void, Category::ArithmeticVectorizable>
288 :
public ReplaceTypes<bool, N, float, Category::ArithmeticVectorizable>
298 template <
size_t N,
typename MT,
typename Replaced,
typename... Remaining>
299 struct SubstituteOneByOne;
305 template <
size_t N,
typename MT,
typename... Replaced,
typename T,
306 typename... Remaining>
307 struct SubstituteOneByOne<N, MT, Typelist<Replaced...>, T, Remaining...>
314 template <
typename U,
size_t M = U::Size>
315 static std::integral_constant<size_t, M> size_or_0(
int);
316 template <
typename U>
static std::integral_constant<size_t, 0> size_or_0(...);
319 using V = simdize<T, N, MT>;
325 static constexpr
auto NewN = N != 0 ? N : decltype(size_or_0<V>(
int()))::value;
332 typedef conditional_t<(N != NewN && is_same<MT, void>::value),
333 conditional_t<is_same<T, bool>::value,
float, T>, MT> NewMT;
339 using type =
typename SubstituteOneByOne<NewN, NewMT, Typelist<Replaced..., V>,
345 template <
size_t Size,
typename... Replaced>
struct SubstitutedBase;
347 template <
typename Replaced>
struct SubstitutedBase<1, Replaced> {
348 template <
typename ValueT,
template <
typename, ValueT...>
class C, ValueT... Values>
349 using SubstitutedWithValues = C<Replaced, Values...>;
352 template <
typename R0,
typename R1>
struct SubstitutedBase<2, R0, R1>
354 template <
typename ValueT,
template <
typename,
typename, ValueT...>
class C,
356 using SubstitutedWithValues = C<R0, R1, Values...>;
359 template <
typename R0,
typename R1,
typename R2>
struct SubstitutedBase<3, R0, R1, R2>
361 template <
typename ValueT,
template <
typename,
typename,
typename, ValueT...>
class C,
363 using SubstitutedWithValues = C<R0, R1, R2, Values...>;
365 #if defined Vc_ICC || defined Vc_MSVC
366 #define Vc_VALUE_PACK_EXPANSION_IS_BROKEN 1
368 template <
typename... Replaced>
struct SubstitutedBase<4, Replaced...> {
370 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
371 template <
typename ValueT,
372 template <
typename,
typename,
typename,
typename, ValueT...>
class C,
374 using SubstitutedWithValues = C<Replaced..., Values...>;
375 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN
378 template <
typename... Replaced>
struct SubstitutedBase<5, Replaced...> {
379 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
380 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
383 using SubstitutedWithValues = C<Replaced..., Values...>;
384 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN
387 template <
typename... Replaced>
struct SubstitutedBase<6, Replaced...> {
388 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
389 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
390 typename, ValueT...>
class C,
392 using SubstitutedWithValues = C<Replaced..., Values...>;
393 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN
396 template <
typename... Replaced>
struct SubstitutedBase<7, Replaced...> {
397 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
398 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
399 typename,
typename, ValueT...>
class C,
401 using SubstitutedWithValues = C<Replaced..., Values...>;
402 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN
405 template <
typename... Replaced>
struct SubstitutedBase<8, Replaced...> {
406 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
407 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
408 typename,
typename,
typename, ValueT...>
class C,
410 using SubstitutedWithValues = C<Replaced..., Values...>;
411 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN
419 template <
size_t N_,
typename MT,
typename Replaced0,
typename... Replaced>
420 struct SubstituteOneByOne<N_, MT, Typelist<Replaced0, Replaced...>>
426 :
public SubstitutedBase<sizeof...(Replaced) + 1, Replaced0, Replaced...> {
427 static constexpr
auto N = N_;
432 template <
template <
typename...>
class C>
433 using Substituted = C<Replaced0, Replaced...>;
453 template <
typename Scalar,
typename Base,
size_t N>
class Adapter;
459 template <
template <
typename...>
class C,
typename... Ts,
size_t N,
typename MT>
460 struct ReplaceTypes<C<Ts...>, N, MT, Category::ClassTemplate>
463 using SubstitutionResult =
464 typename SubstituteOneByOne<N, MT, Typelist<>, Ts...>::type;
470 using Vectorized =
typename SubstitutionResult::template Substituted<C>;
476 using type = conditional_t<is_same<C<Ts...>, Vectorized>::value, C<Ts...>,
477 Adapter<C<Ts...>, Vectorized, SubstitutionResult::N>>;
485 #ifdef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
487 #define Vc_DEFINE_NONTYPE_REPLACETYPES_(ValueType_) \
488 template <template <typename, ValueType_...> class C, typename T, ValueType_ Value0, \
489 ValueType_... Values> \
490 struct is_class_template<C<T, Value0, Values...>> : public true_type { \
492 template <template <typename, typename, ValueType_...> class C, typename T0, \
493 typename T1, ValueType_ Value0, ValueType_... Values> \
494 struct is_class_template<C<T0, T1, Value0, Values...>> : public true_type { \
496 template <template <typename, typename, typename, ValueType_...> class C, \
497 typename T0, typename T1, typename T2, ValueType_ Value0, \
498 ValueType_... Values> \
499 struct is_class_template<C<T0, T1, T2, Value0, Values...>> : public true_type { \
501 template <template <typename, typename, typename, typename, ValueType_...> class C, \
502 typename T0, typename T1, typename T2, typename T3, ValueType_ Value0, \
503 ValueType_... Values> \
504 struct is_class_template<C<T0, T1, T2, T3, Value0, Values...>> : public true_type { \
506 template <template <typename, typename, typename, typename, typename, ValueType_...> \
508 typename T0, typename T1, typename T2, typename T3, typename T4, \
509 ValueType_ Value0, ValueType_... Values> \
510 struct is_class_template<C<T0, T1, T2, T3, T4, Value0, Values...>> \
511 : public true_type { \
513 template <template <typename, typename, typename, typename, typename, typename, \
514 ValueType_...> class C, \
515 typename T0, typename T1, typename T2, typename T3, typename T4, \
516 typename T5, ValueType_ Value0, ValueType_... Values> \
517 struct is_class_template<C<T0, T1, T2, T3, T4, T5, Value0, Values...>> \
518 : public true_type { \
520 template <template <typename, typename, typename, typename, typename, typename, \
521 typename, ValueType_...> class C, \
522 typename T0, typename T1, typename T2, typename T3, typename T4, \
523 typename T5, typename T6, ValueType_ Value0, ValueType_... Values> \
524 struct is_class_template<C<T0, T1, T2, T3, T4, T5, T6, Value0, Values...>> \
525 : public true_type { \
527 template <template <typename, ValueType_> class C, typename T0, ValueType_ Value0, \
528 size_t N, typename MT> \
529 struct ReplaceTypes<C<T0, Value0>, N, MT, Category::ClassTemplate> { \
530 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0>::type tmp; \
531 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \
533 static constexpr auto NN = tmp::N; \
534 typedef conditional_t<is_same<C<T0, Value0>, Substituted>::value, C<T0, Value0>, \
535 Adapter<C<T0, Value0>, Substituted, NN>> type; \
537 template <template <typename, typename, ValueType_> class C, typename T0, \
538 typename T1, ValueType_ Value0, size_t N, typename MT> \
539 struct ReplaceTypes<C<T0, T1, Value0>, N, MT, Category::ClassTemplate> { \
540 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1>::type tmp; \
541 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \
543 static constexpr auto NN = tmp::N; \
544 typedef conditional_t<is_same<C<T0, T1, Value0>, Substituted>::value, \
546 Adapter<C<T0, T1, Value0>, Substituted, NN>> type; \
548 template <template <typename, typename, typename, ValueType_> class C, typename T0, \
549 typename T1, typename T2, ValueType_ Value0, size_t N, typename MT> \
550 struct ReplaceTypes<C<T0, T1, T2, Value0>, N, MT, Category::ClassTemplate> { \
551 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1, T2>::type tmp; \
552 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \
554 static constexpr auto NN = tmp::N; \
555 typedef conditional_t<is_same<C<T0, T1, T2, Value0>, Substituted>::value, \
556 C<T0, T1, T2, Value0>, \
557 Adapter<C<T0, T1, T2, Value0>, Substituted, NN>> type; \
560 #define Vc_DEFINE_NONTYPE_REPLACETYPES_(ValueType_) \
561 template <template <typename, ValueType_...> class C, typename T, ValueType_ Value0, \
562 ValueType_... Values> \
563 struct is_class_template<C<T, Value0, Values...>> : public true_type { \
565 template <template <typename, typename, ValueType_...> class C, typename T0, \
566 typename T1, ValueType_ Value0, ValueType_... Values> \
567 struct is_class_template<C<T0, T1, Value0, Values...>> : public true_type { \
569 template <template <typename, typename, typename, ValueType_...> class C, \
570 typename T0, typename T1, typename T2, ValueType_ Value0, \
571 ValueType_... Values> \
572 struct is_class_template<C<T0, T1, T2, Value0, Values...>> : public true_type { \
574 template <template <typename, typename, typename, typename, ValueType_...> class C, \
575 typename T0, typename T1, typename T2, typename T3, ValueType_ Value0, \
576 ValueType_... Values> \
577 struct is_class_template<C<T0, T1, T2, T3, Value0, Values...>> : public true_type { \
579 template <template <typename, typename, typename, typename, typename, ValueType_...> \
581 typename T0, typename T1, typename T2, typename T3, typename T4, \
582 ValueType_ Value0, ValueType_... Values> \
583 struct is_class_template<C<T0, T1, T2, T3, T4, Value0, Values...>> \
584 : public true_type { \
586 template <template <typename, typename, typename, typename, typename, typename, \
587 ValueType_...> class C, \
588 typename T0, typename T1, typename T2, typename T3, typename T4, \
589 typename T5, ValueType_ Value0, ValueType_... Values> \
590 struct is_class_template<C<T0, T1, T2, T3, T4, T5, Value0, Values...>> \
591 : public true_type { \
593 template <template <typename, typename, typename, typename, typename, typename, \
594 typename, ValueType_...> class C, \
595 typename T0, typename T1, typename T2, typename T3, typename T4, \
596 typename T5, typename T6, ValueType_ Value0, ValueType_... Values> \
597 struct is_class_template<C<T0, T1, T2, T3, T4, T5, T6, Value0, Values...>> \
598 : public true_type { \
600 template <template <typename, ValueType_...> class C, typename T0, \
601 ValueType_ Value0, ValueType_... Values, size_t N, typename MT> \
602 struct ReplaceTypes<C<T0, Value0, Values...>, N, MT, Category::ClassTemplate> { \
603 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0>::type tmp; \
604 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \
605 Values...> Substituted; \
606 static constexpr auto NN = tmp::N; \
607 typedef conditional_t<is_same<C<T0, Value0, Values...>, Substituted>::value, \
608 C<T0, Value0, Values...>, \
609 Adapter<C<T0, Value0, Values...>, Substituted, NN>> type; \
611 template <template <typename, typename, ValueType_...> class C, typename T0, \
612 typename T1, ValueType_ Value0, ValueType_... Values, size_t N, \
614 struct ReplaceTypes<C<T0, T1, Value0, Values...>, N, MT, Category::ClassTemplate> { \
615 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1>::type tmp; \
616 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \
617 Values...> Substituted; \
618 static constexpr auto NN = tmp::N; \
619 typedef conditional_t<is_same<C<T0, T1, Value0, Values...>, Substituted>::value, \
620 C<T0, T1, Value0, Values...>, \
621 Adapter<C<T0, T1, Value0, Values...>, Substituted, NN>> \
624 template <template <typename, typename, typename, ValueType_...> class C, \
625 typename T0, typename T1, typename T2, ValueType_ Value0, \
626 ValueType_... Values, size_t N, typename MT> \
627 struct ReplaceTypes<C<T0, T1, T2, Value0, Values...>, N, MT, \
628 Category::ClassTemplate> { \
629 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1, T2>::type tmp; \
630 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \
631 Values...> Substituted; \
632 static constexpr auto NN = tmp::N; \
633 typedef conditional_t< \
634 is_same<C<T0, T1, T2, Value0, Values...>, Substituted>::value, \
635 C<T0, T1, T2, Value0, Values...>, \
636 Adapter<C<T0, T1, T2, Value0, Values...>, Substituted, NN>> type; \
638 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN
639 Vc_DEFINE_NONTYPE_REPLACETYPES_(
bool);
640 Vc_DEFINE_NONTYPE_REPLACETYPES_(
wchar_t);
641 Vc_DEFINE_NONTYPE_REPLACETYPES_(
char);
642 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed char);
643 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned char);
644 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed short);
645 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned short);
646 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed int);
647 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned int);
648 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed long);
649 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned long);
650 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed long long);
651 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned long long);
652 #undef Vc_DEFINE_NONTYPE_REPLACETYPES_
654 namespace is_constructible_with_single_paren_impl
656 template <
typename T> T create();
657 #if defined Vc_CLANG || defined Vc_APPLECLANG
658 template <
typename Class,
typename... Args,
typename = decltype(Class(create<Args>()...))>
661 template <
typename Class,
typename... Args>
662 typename std::conditional<
666 sizeof(Class(create<Args>()...)),
670 template <
typename Class,
typename... Args>
double test(...);
673 template <
typename Class,
typename... Args>
674 struct is_constructible_with_single_paren
675 :
public std::integral_constant<
677 1 == sizeof(is_constructible_with_single_paren_impl::test<Class, Args...>(1))> {
680 !is_constructible_with_single_paren<
int, std::tuple<int, int, int>>::value,
681 "is_constructible_with_single_paren<int> does not work as expected");
683 is_constructible_with_single_paren<std::tuple<int, int, int>,
int,
int,
int>::value,
684 "is_constructible_with_single_paren<tuple> does not work as expected");
686 !is_constructible_with_single_paren<std::array<int, 3>,
int,
int,
int>::value,
687 "is_constructible_with_single_paren<array> does not work as expected");
689 namespace is_constructible_with_single_brace_impl
691 template <
typename T> T create();
693 template <
typename Class,
typename... Args>
char test(
int);
694 #elif defined Vc_CLANG || defined Vc_APPLECLANG
695 template <
typename Class,
typename... Args,
typename = decltype(Class{create<Args>()...})>
698 template <
typename Class,
typename... Args>
699 typename std::conditional<
703 sizeof(Class{create<Args>()...}),
707 template <
typename Class,
typename... Args>
double test(...);
710 template <
typename Class,
typename... Args>
711 struct is_constructible_with_single_brace
712 :
public std::integral_constant<
714 1 == sizeof(is_constructible_with_single_brace_impl::test<Class, Args...>(1))> {
718 !is_constructible_with_single_brace<
int, std::tuple<int, int, int>>::value,
719 "is_constructible_with_single_brace<int> does not work as expected");
722 is_constructible_with_single_brace<std::tuple<int, int, int>,
int,
int,
int>::value,
723 "is_constructible_with_single_brace<tuple> does not work as expected");
725 is_constructible_with_single_brace<std::array<int, 3>,
int,
int,
int>::value,
726 "is_constructible_with_single_brace<array> does not work as expected");
728 namespace is_constructible_with_double_brace_impl
730 template <
typename T> T create();
731 #if defined Vc_CLANG || defined Vc_APPLECLANG
732 template <
typename Class,
typename... Args,
733 typename = decltype(Class{{create<Args>()...}})>
736 template <
typename Class,
typename... Args>
737 typename std::conditional<
741 sizeof(Class{{create<Args>()...}}),
745 template <
typename Class,
typename... Args>
double test(...);
748 template <
typename Class,
typename... Args>
749 struct is_constructible_with_double_brace
750 :
public std::integral_constant<
752 1 == sizeof(is_constructible_with_double_brace_impl::test<Class, Args...>(1))> {
754 #if !(defined Vc_CLANG || defined Vc_APPLECLANG)
759 !is_constructible_with_double_brace<int, int>::value,
760 "is_constructible_with_double_brace<int> does not work as expected");
763 !is_constructible_with_double_brace<std::tuple<int, int, int>,
int,
int,
int>::value,
764 "is_constructible_with_double_brace<tuple> does not work as expected");
765 static_assert(is_constructible_with_double_brace<std::array<int, 3>,
int,
int,
int>::value,
766 "is_constructible_with_double_brace<array> does not work as expected");
768 template <
size_t I,
typename T,
769 typename R = decltype(std::declval<T &>().
template vc_get_<I>())>
770 R get_dispatcher(T &x,
void * =
nullptr)
772 return x.template vc_get_<I>();
774 template <
size_t I,
typename T,
775 typename R = decltype(std::declval<const T &>().
template vc_get_<I>())>
776 R get_dispatcher(
const T &x,
void * =
nullptr)
778 return x.template vc_get_<I>();
780 template <
size_t I,
typename T,
typename R = decltype(std::get<I>(std::declval<T &>()))>
781 R get_dispatcher(T &x,
int = 0)
783 return std::get<I>(x);
785 template <
size_t I,
typename T,
786 typename R = decltype(std::get<I>(std::declval<const T &>()))>
787 R get_dispatcher(
const T &x,
int = 0)
789 return std::get<I>(x);
794 template <
typename Scalar,
typename Base,
size_t N>
class Adapter :
public Base
798 template <std::size_t... Indexes,
typename T>
799 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_, T, std::true_type)
800 : Base{{get_dispatcher<Indexes>(x_)...}}
805 template <std::size_t... Indexes>
806 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_, std::false_type,
808 : Base{get_dispatcher<Indexes>(x_)...}
813 template <std::size_t... Indexes>
814 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_, std::true_type,
816 : Base(get_dispatcher<Indexes>(x_)...)
820 template <std::size_t... Indexes>
821 Adapter(Vc::index_sequence<Indexes...> seq_,
const Scalar &x_)
823 std::integral_constant<
824 bool, is_constructible_with_single_paren<
825 Base, decltype(get_dispatcher<Indexes>(
826 std::declval<const Scalar &>()))...>::value>(),
827 std::integral_constant<
828 bool, is_constructible_with_double_brace<
829 Base, decltype(get_dispatcher<Indexes>(
830 std::declval<const Scalar &>()))...>::value>())
836 static constexpr
size_t size() {
return N; }
837 static constexpr
size_t Size = N;
840 using base_type = Base;
843 using scalar_type = Scalar;
850 #if defined Vc_CLANG && Vc_CLANG < 0x30700
851 Vc_INTRINSIC Adapter(
const Adapter &x) : Base(x) {}
853 Adapter(
const Adapter &) =
default;
855 Adapter(Adapter &&) =
default;
858 Adapter &operator=(
const Adapter &) =
default;
860 Adapter &operator=(Adapter &&) =
default;
863 template <typename U, size_t TupleSize = determine_tuple_size_<Scalar>::value,
864 typename Seq = Vc::make_index_sequence<TupleSize>,
865 typename = enable_if<std::is_convertible<U, Scalar>::value>>
867 : Adapter(Seq(), static_cast<const Scalar &>(x_))
872 template <
typename A0,
typename... Args,
873 typename =
typename std::enable_if<
874 !Traits::is_index_sequence<A0>::value &&
875 (
sizeof...(Args) > 0 || !std::is_convertible<A0, Scalar>::value)>::type>
876 Adapter(A0 &&arg0_, Args &&... arguments_)
877 : Base(
std::forward<A0>(arg0_),
std::forward<Args>(arguments_)...)
882 template <
typename T,
883 typename = decltype(Base(std::declval<
const std::initializer_list<T> &>()))>
884 Adapter(
const std::initializer_list<T> &l_)
891 void *
operator new(
size_t size)
893 return Vc::Common::aligned_malloc<alignof(Adapter)>(size);
895 void *
operator new(size_t,
void *p_) {
return p_; }
896 void *
operator new[](
size_t size)
898 return Vc::Common::aligned_malloc<alignof(Adapter)>(size);
900 void *
operator new[](size_t ,
void *p_) {
return p_; }
902 void operator delete(
void *,
void *) {}
904 void operator delete[](
void *,
void *) {}
911 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
912 inline void operator==(
913 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
914 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
915 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
916 inline void operator!=(
917 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
918 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
919 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
920 inline void operator<=(
921 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
922 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
923 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
924 inline void operator>=(
925 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
926 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
927 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
928 inline void operator<(
929 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
930 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
931 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
932 inline void operator>(
933 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
934 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
945 template <
typename Scalar,
typename Base,
size_t N>
946 class tuple_size<
Vc::SimdizeDetail::Adapter<Scalar, Base, N>> :
public tuple_size<Base>
952 template <
size_t I,
typename Scalar,
typename Base,
size_t N>
953 class tuple_element<I,
Vc::SimdizeDetail::Adapter<Scalar, Base, N>>
954 :
public tuple_element<I, Base>
964 template <
typename S,
typename T,
size_t N>
965 class allocator<
Vc::SimdizeDetail::Adapter<S, T, N>>
969 template <
typename U>
struct rebind
971 typedef std::allocator<U> other;
976 namespace Vc_VERSIONED_NAMESPACE
978 namespace SimdizeDetail
988 template <
typename T>
static inline T decay_workaround(
const T &x) {
return x; }
993 template <
typename S,
typename T,
size_t N,
size_t... Indexes>
994 inline void assign_impl(Adapter<S, T, N> &a,
size_t i,
const S &x,
995 Vc::index_sequence<Indexes...>)
997 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(x)))...> tmp(
998 decay_workaround(get_dispatcher<Indexes>(x))...);
999 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(tmp), 0)...};
1000 if (&unused == &unused) {}
1007 template <
typename S,
typename T,
size_t N>
1008 inline void assign(Adapter<S, T, N> &a,
size_t i,
const S &x)
1010 assign_impl(a, i, x, Vc::make_index_sequence<determine_tuple_size<T>()>());
1015 template <typename V, typename = enable_if<Traits::is_simd_vector<V>::value>>
1016 Vc_INTRINSIC
void assign(V &v,
size_t i,
typename V::EntryType x)
1024 template <
typename S,
typename T,
size_t N,
size_t... Indexes>
1025 inline S extract_impl(
const Adapter<S, T, N> &a,
size_t i, Vc::index_sequence<Indexes...>)
1027 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a)[i]))...> tmp(
1028 decay_workaround(get_dispatcher<Indexes>(a)[i])...);
1029 return S(get_dispatcher<Indexes>(tmp)...);
1036 template <
typename S,
typename T,
size_t N>
1037 inline S
extract(
const Adapter<S, T, N> &a,
size_t i)
1039 return extract_impl(a, i, Vc::make_index_sequence<determine_tuple_size<S>()>());
1044 template <typename V, typename = enable_if<Traits::is_simd_vector<V>::value>>
1045 Vc_INTRINSIC
typename V::EntryType extract(
const V &v,
size_t i)
1050 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1051 inline Adapter<S, T, N> shifted_impl(
const Adapter<S, T, N> &a,
int shift,
1052 Vc::index_sequence<Indexes...>)
1055 auto &&unused = {(get_dispatcher<Indexes>(r) = get_dispatcher<Indexes>(a).shifted(shift), 0)...};
1056 if (&unused == &unused) {}
1068 template <
typename S,
typename T,
size_t N>
1069 inline Adapter<S, T, N>
shifted(
const Adapter<S, T, N> &a,
int shift)
1071 return shifted_impl(a, shift, Vc::make_index_sequence<determine_tuple_size<T>()>());
1077 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1078 inline void swap_impl(Adapter<S, T, N> &a, std::size_t i, S &x,
1079 Vc::index_sequence<Indexes...>)
1081 const auto &a_const = a;
1082 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a_const)[0]))...>
1083 tmp{decay_workaround(get_dispatcher<Indexes>(a_const)[i])...};
1084 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(x), 0)...};
1085 auto &&unused2 = {(get_dispatcher<Indexes>(x) = get_dispatcher<Indexes>(tmp), 0)...};
1086 if (&unused == &unused2) {}
1088 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1089 inline void swap_impl(Adapter<S, T, N> &a, std::size_t i, Adapter<S, T, N> &b,
1090 std::size_t j, Vc::index_sequence<Indexes...>)
1092 const auto &a_const = a;
1093 const auto &b_const = b;
1094 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a_const)[0]))...>
1095 tmp{decay_workaround(get_dispatcher<Indexes>(a_const)[i])...};
1096 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(b_const)[j], 0)...};
1097 auto &&unused2 = {(get_dispatcher<Indexes>(b)[j] = get_dispatcher<Indexes>(tmp), 0)...};
1098 if (&unused == &unused2) {}
1105 template <
typename S,
typename T, std::
size_t N>
1106 inline void swap(Adapter<S, T, N> &a, std::size_t i, S &x)
1108 swap_impl(a, i, x, Vc::make_index_sequence<determine_tuple_size<T>()>());
1110 template <
typename S,
typename T, std::
size_t N>
1111 inline void swap(Adapter<S, T, N> &a, std::size_t i, Adapter<S, T, N> &b, std::size_t j)
1113 swap_impl(a, i, b, j, Vc::make_index_sequence<determine_tuple_size<T>()>());
1116 template <
typename A>
class Scalar
1118 using reference =
typename std::add_lvalue_reference<A>::type;
1119 using S =
typename A::scalar_type;
1120 using IndexSeq = Vc::make_index_sequence<determine_tuple_size<S>()>;
1123 Scalar(reference aa,
size_t ii) : a(aa), i(ii) {}
1126 Scalar(
const Scalar &) =
delete;
1127 Scalar(Scalar &&) =
delete;
1128 Scalar &operator=(
const Scalar &) =
delete;
1129 Scalar &operator=(Scalar &&) =
delete;
1131 void operator=(
const S &x) { assign_impl(a, i, x, IndexSeq()); }
1132 operator S()
const {
return extract_impl(a, i, IndexSeq()); }
1134 template <
typename AA>
1135 friend inline void swap(Scalar<AA> &&a,
typename AA::scalar_type &b);
1136 template <
typename AA>
1137 friend inline void swap(
typename AA::scalar_type &b, Scalar<AA> &&a);
1138 template <
typename AA>
friend inline void swap(Scalar<AA> &&a, Scalar<AA> &&b);
1147 template <
typename A>
inline void swap(Scalar<A> &&a,
typename A::scalar_type &b)
1149 swap_impl(a.a, a.i, b,
typename Scalar<A>::IndexSeq());
1153 template <
typename A>
inline void swap(
typename A::scalar_type &b, Scalar<A> &&a)
1155 swap_impl(a.a, a.i, b,
typename Scalar<A>::IndexSeq());
1158 template <
typename A>
inline void swap(Scalar<A> &&a, Scalar<A> &&b)
1160 swap_impl(a.a, a.i, b.a, b.i,
typename Scalar<A>::IndexSeq());
1163 template <
typename A>
class Interface
1165 using reference =
typename std::add_lvalue_reference<A>::type;
1167 Vc::make_index_sequence<determine_tuple_size<typename A::scalar_type>()>;
1170 Interface(reference aa) : a(aa) {}
1172 Scalar<A> operator[](
size_t i)
1176 typename A::scalar_type operator[](
size_t i)
const
1178 return extract_impl(a, i, IndexSeq());
1183 return shifted_impl(a, amount, IndexSeq());
1190 template <
typename S,
typename T,
size_t N>
1191 Interface<Adapter<S, T, N>> decorate(Adapter<S, T, N> &a)
1195 template <
typename S,
typename T,
size_t N>
1196 const Interface<const Adapter<S, T, N>> decorate(
const Adapter<S, T, N> &a)
1201 namespace IteratorDetails
1203 enum class Mutable { Yes, No };
1205 template <
typename It,
typename V,
size_t I,
size_t End>
1206 Vc_INTRINSIC V fromIteratorImpl(enable_if<(I == End), It>)
1210 template <
typename It,
typename V,
size_t I,
size_t End>
1211 Vc_INTRINSIC V fromIteratorImpl(enable_if<(I < End), It> it)
1213 V r = fromIteratorImpl<It, V, I + 1, End>(it);
1214 Traits::decay<decltype(get_dispatcher<I>(r))> tmp;
1215 for (
size_t j = 0; j < V::size(); ++j, ++it) {
1216 tmp[j] = get_dispatcher<I>(*it);
1218 get_dispatcher<I>(r) = tmp;
1221 template <
typename It,
typename V>
1222 Vc_INTRINSIC V fromIterator(enable_if<!Traits::is_simd_vector<V>::value,
const It &> it)
1224 return fromIteratorImpl<It, V, 0, determine_tuple_size<V>()>(it);
1226 template <
typename It,
typename V>
1227 Vc_INTRINSIC V fromIterator(enable_if<Traits::is_simd_vector<V>::value, It> it)
1230 for (
size_t j = 0; j < V::size(); ++j, ++it) {
1239 template <
typename T,
typename value_vector, Mutable>
class Pointer;
1249 template <
typename T,
typename value_vector>
class Pointer<T, value_vector, Mutable::Yes>
1251 static constexpr
auto Size = value_vector::size();
1255 value_vector *operator->() {
return &data; }
1262 Pointer(
const Pointer &) =
delete;
1263 Pointer &operator=(
const Pointer &) =
delete;
1264 Pointer &operator=(Pointer &&) =
delete;
1267 Pointer(Pointer &&) =
default;
1277 for (
size_t i = 0; i < Size; ++i, ++begin_iterator) {
1278 *begin_iterator =
extract(data, i);
1283 Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)), begin_iterator(it) {}
1296 template <
typename T,
typename value_vector>
class Pointer<T, value_vector, Mutable::No>
1298 static constexpr
auto Size = value_vector::size();
1301 const value_vector *operator->()
const {
return &data; }
1304 Pointer(
const Pointer &) =
delete;
1305 Pointer &operator=(
const Pointer &) =
delete;
1306 Pointer &operator=(Pointer &&) =
delete;
1308 Pointer(Pointer &&) =
default;
1310 Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)) {}
1328 template <
typename T,
typename value_vector, Mutable M>
class Reference;
1331 template <
typename T,
typename value_vector>
1332 class Reference<T, value_vector, Mutable::Yes> :
public value_vector
1334 static constexpr
auto Size = value_vector::size();
1336 using reference =
typename std::add_lvalue_reference<T>::type;
1337 reference scalar_it;
1342 Reference(reference first_it)
1343 : value_vector(fromIterator<T, value_vector>(first_it)), scalar_it(first_it)
1348 Reference(
const Reference &) =
delete;
1349 Reference(Reference &&) =
default;
1350 Reference &operator=(
const Reference &) =
delete;
1351 Reference &operator=(Reference &&) =
delete;
1358 void operator=(
const value_vector &x)
1360 static_cast<value_vector &
>(*this) = x;
1361 auto it = scalar_it;
1362 for (
size_t i = 0; i < Size; ++i, ++it) {
1367 #define Vc_OP(op_) \
1368 template <typename T0, typename V0, typename T1, typename V1> \
1369 decltype(std::declval<const V0 &>() op_ std::declval<const V1 &>()) operator op_( \
1370 const Reference<T0, V0, Mutable::Yes> &x, \
1371 const Reference<T1, V1, Mutable::Yes> &y) \
1373 return static_cast<const V0 &>(x) op_ static_cast<const V1 &>(y); \
1375 Vc_ALL_COMPARES(Vc_OP);
1376 Vc_ALL_ARITHMETICS(Vc_OP);
1377 Vc_ALL_BINARY(Vc_OP);
1378 Vc_ALL_LOGICAL(Vc_OP);
1379 Vc_ALL_SHIFTS(Vc_OP);
1383 template <
typename T,
typename value_vector>
1384 class Reference<T, value_vector, Mutable::No> :
public value_vector
1386 static constexpr
auto Size = value_vector::size();
1389 Reference(
const T &it) : value_vector(fromIterator<T, value_vector>(it)) {}
1391 Reference(
const Reference &) =
delete;
1392 Reference(Reference &&) =
default;
1393 Reference &operator=(
const Reference &) =
delete;
1394 Reference &operator=(Reference &&) =
delete;
1397 void operator=(
const value_vector &x) =
delete;
1400 template <
typename T,
size_t N,
1401 IteratorDetails::Mutable M =
1402 (Traits::is_output_iterator<T>::value ? Mutable::Yes : Mutable::No),
1403 typename V = simdize<
typename std::iterator_traits<T>::value_type, N>,
1404 size_t Size = V::Size,
1405 typename =
typename std::iterator_traits<T>::iterator_category>
1408 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size_>
1409 class Iterator<T, N, M, V, Size_, std::forward_iterator_tag>
1410 :
public std::iterator<typename std::iterator_traits<T>::iterator_category, V,
1411 typename std::iterator_traits<T>::difference_type,
1412 IteratorDetails::Pointer<T, V, M>,
1413 IteratorDetails::Reference<T, V, M>>
1416 using pointer = IteratorDetails::Pointer<T, V, M>;
1417 using reference = IteratorDetails::Reference<T, V, M>;
1418 using const_pointer = IteratorDetails::Pointer<T, V, IteratorDetails::Mutable::No>;
1419 using const_reference =
1420 IteratorDetails::Reference<T, V, IteratorDetails::Mutable::No>;
1423 static constexpr std::size_t size() {
return Size_; }
1424 static constexpr std::size_t Size = Size_;
1426 Iterator() =
default;
1434 Iterator(
const T &x) : scalar_it(x) {}
1438 Iterator(T &&x) : scalar_it(
std::move(x)) {}
1442 Iterator &operator=(
const T &x)
1450 Iterator &operator=(T &&x)
1452 scalar_it = std::move(x);
1457 Iterator(
const Iterator &) =
default;
1459 Iterator(Iterator &&) =
default;
1461 Iterator &operator=(
const Iterator &) =
default;
1463 Iterator &operator=(Iterator &&) =
default;
1466 Iterator &operator++()
1468 std::advance(scalar_it, Size);
1472 Iterator operator++(
int)
1474 Iterator copy(*
this);
1487 bool operator==(
const Iterator &rhs)
const
1490 if (scalar_it == rhs.scalar_it) {
1494 for (
size_t i = 1; i < Size; ++i) {
1495 Vc_ASSERT((++it != rhs.scalar_it));
1500 return scalar_it == rhs.scalar_it;
1511 bool operator!=(
const Iterator &rhs)
const
1513 return !operator==(rhs);
1516 pointer operator->() {
return scalar_it; }
1524 reference
operator*() {
return scalar_it; }
1526 const_pointer operator->()
const {
return scalar_it; }
1535 const_reference
operator*()
const {
return scalar_it; }
1550 operator const T &()
const {
return scalar_it; }
1560 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1561 class Iterator<T, N, M, V, Size,
std::bidirectional_iterator_tag>
1562 :
public Iterator<T, N, M, V, Size, std::forward_iterator_tag>
1564 using Base = Iterator<T, N, M, V, Size, std::forward_iterator_tag>;
1567 using Base::scalar_it;
1570 using pointer =
typename Base::pointer;
1571 using reference =
typename Base::reference;
1572 using const_pointer =
typename Base::const_pointer;
1573 using const_reference =
typename Base::const_reference;
1575 using Iterator<T, N, M, V, Size,
1576 std::forward_iterator_tag>::Iterator;
1582 std::advance(scalar_it, -Size);
1588 Iterator copy(*
this);
1598 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1599 class Iterator<T, N, M, V, Size,
std::random_access_iterator_tag>
1600 :
public Iterator<T, N, M, V, Size, std::bidirectional_iterator_tag>
1605 using Base::scalar_it;
1608 using pointer =
typename Base::pointer;
1609 using reference =
typename Base::reference;
1610 using const_pointer =
typename Base::const_pointer;
1611 using const_reference =
typename Base::const_reference;
1612 using difference_type =
typename std::iterator_traits<T>::difference_type;
1617 Iterator &operator+=(difference_type n)
1619 scalar_it += n * difference_type(Size);
1622 Iterator
operator+(difference_type n)
const {
return Iterator(*
this) += n; }
1624 Iterator &operator-=(difference_type n)
1626 scalar_it -= n * difference_type(Size);
1629 Iterator
operator-(difference_type n)
const {
return Iterator(*
this) -= n; }
1631 difference_type
operator-(
const Iterator &rhs)
const
1633 constexpr difference_type n = Size;
1634 Vc_ASSERT((scalar_it - rhs.scalar_it) % n ==
1640 return (scalar_it - rhs.scalar_it) / n;
1649 return rhs.scalar_it - scalar_it >= difference_type(Size);
1652 bool operator>(
const Iterator &rhs)
const
1654 return scalar_it - rhs.scalar_it >= difference_type(Size);
1657 bool operator<=(
const Iterator &rhs)
const
1659 return rhs.scalar_it - scalar_it >= difference_type(Size) - 1;
1662 bool operator>=(
const Iterator &rhs)
const
1664 return scalar_it - rhs.scalar_it >= difference_type(Size) - 1;
1667 reference operator[](difference_type i) {
return *(*
this + i); }
1668 const_reference operator[](difference_type i)
const {
return *(*
this + i); }
1671 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1672 Iterator<T, N, M, V, Size, std::random_access_iterator_tag>
operator+(
1673 typename Iterator<T, N, M, V, Size, std::random_access_iterator_tag>::difference_type
1675 const Iterator<T, N, M, V, Size, std::random_access_iterator_tag> &i)
1690 template <
typename T,
size_t N,
typename MT>
1691 struct ReplaceTypes<T, N, MT, Category::ForwardIterator>
1693 using type = IteratorDetails::Iterator<T, N>;
1695 template <
typename T,
size_t N,
typename MT>
1696 struct ReplaceTypes<T, N, MT, Category::BidirectionalIterator>
1698 using type = IteratorDetails::Iterator<T, N>;
1700 template <
typename T,
size_t N,
typename MT>
1701 struct ReplaceTypes<T, N, MT, Category::RandomAccessIterator>
1703 using type = IteratorDetails::Iterator<T, N>;
1709 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
typename U,
1711 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N),
void>
1712 conditional_assign(Adapter<S, T, N> &,
const M &,
const U &)
1715 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
typename U,
1716 std::size_t Offset = 0>
1717 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N),
void>
1718 conditional_assign(Adapter<S, T, N> &lhs,
const M &mask,
const U &rhs)
1720 using V =
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
1721 using M2 =
typename V::mask_type;
1722 conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask), get_dispatcher<Offset>(rhs));
1723 conditional_assign<Op, S, T, N, M, U, Offset + 1>(lhs, mask, rhs);
1725 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
1727 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N),
void>
1728 conditional_assign(Adapter<S, T, N> &,
const M &)
1731 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
1732 std::size_t Offset = 0>
1733 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N),
void>
1734 conditional_assign(Adapter<S, T, N> &lhs,
const M &mask)
1736 using V =
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
1737 using M2 =
typename V::mask_type;
1738 conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask));
1739 conditional_assign<Op, S, T, N, M, Offset + 1>(lhs, mask);
1763 template <
typename T,
size_t N = 0,
typename MT =
void>
1764 using simdize = SimdizeDetail::simdize<T, N, MT>;
1785 #define Vc_SIMDIZE_INTERFACE(MEMBERS_) \
1786 template <std::size_t N_> \
1787 inline auto vc_get_()->decltype(std::get<N_>(std::tie MEMBERS_)) \
1789 return std::get<N_>(std::tie MEMBERS_); \
1791 template <std::size_t N_> \
1792 inline auto vc_get_() const->decltype(std::get<N_>(std::tie MEMBERS_)) \
1794 return std::get<N_>(std::tie MEMBERS_); \
1796 enum : std::size_t { \
1797 tuple_size = std::tuple_size<decltype(std::make_tuple MEMBERS_)>::value \
1804 using Vc::SimdizeDetail::swap;
1807 #endif // VC_COMMON_SIMDIZE_H_
void free(T *p)
Frees memory that was allocated with Vc::malloc.
bool operator<(const Iterator &rhs) const
Returns whether all entries accessed via iterator dereferencing come before the iterator rhs...
result_vector_type< L, R > operator-(L &&lhs, R &&rhs)
Applies - component-wise and concurrently.
result_vector_type< L, R > operator*(L &&lhs, R &&rhs)
Applies * component-wise and concurrently.
SimdizeDetail::simdize< T, N, MT > simdize
Iterator operator--(int)
Postfix overload of the above.
S extract(const Adapter< S, T, N > &a, size_t i)
Extracts and returns one scalar object from a SIMD slot at offset i in the simdized object a...
An allocator that uses global new and supports over-aligned types, as per [C++11 20.6.9].
result_vector_type< L, R > operator+(L &&lhs, R &&rhs)
Applies + component-wise and concurrently.
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.
Iterator & operator--()
Advances the iterator by one vector width, or respectively N scalar steps.
Adapter< S, T, N > shifted(const Adapter< S, T, N > &a, int shift)
Returns a new vectorized object where each entry is shifted by shift.
Vector Classes Namespace.
This is the iterator type created when applying simdize to a bidirectional iterator type...