28 #ifndef VC_COMMON_SIMDIZE_H_ 29 #define VC_COMMON_SIMDIZE_H_ 121 namespace Vc_VERSIONED_NAMESPACE
129 namespace SimdizeDetail
136 using std::is_base_of;
137 using std::false_type;
138 using std::true_type;
139 using std::iterator_traits;
140 using std::conditional;
142 template <
bool B,
typename T,
typename F>
143 using conditional_t =
typename conditional<B, T, F>::type;
149 template <
typename... Ts>
struct Typelist;
154 enum class Category {
158 ArithmeticVectorizable,
166 BidirectionalIterator,
168 RandomAccessIterator,
177 template <
typename T,
typename ItCat =
typename T::iterator_category>
178 constexpr Category iteratorCategories(
int, ItCat * =
nullptr)
180 return is_base_of<std::random_access_iterator_tag, ItCat>::value
181 ? Category::RandomAccessIterator
182 : is_base_of<std::bidirectional_iterator_tag, ItCat>::value
183 ? Category::BidirectionalIterator
184 : is_base_of<std::forward_iterator_tag, ItCat>::value
185 ? Category::ForwardIterator
186 : is_base_of<std::output_iterator_tag, ItCat>::value
187 ? Category::OutputIterator
188 : is_base_of<std::input_iterator_tag, ItCat>::value
189 ? Category::InputIterator
195 template <
typename T>
196 constexpr enable_if<std::is_pointer<T>::value, Category> iteratorCategories(
float)
198 return Category::RandomAccessIterator;
203 template <
typename T> constexpr Category iteratorCategories(...)
205 return Category::None;
211 template <
typename T>
struct is_class_template :
public false_type
214 template <
template <
typename...>
class C,
typename... Ts>
215 struct is_class_template<C<Ts...>> :
public true_type
222 template <
typename T> constexpr Category typeCategory()
224 return (is_same<T, bool>::value || is_same<T, short>::value ||
225 is_same<T, unsigned short>::value || is_same<T, int>::value ||
226 is_same<T, unsigned int>::value || is_same<T, float>::value ||
227 is_same<T, double>::value)
228 ? Category::ArithmeticVectorizable
229 : iteratorCategories<T>(int()) != Category::None
230 ? iteratorCategories<T>(
int())
231 : is_class_template<T>::value ? Category::ClassTemplate
240 template <typename T, size_t TupleSize = std::tuple_size<T>::value>
241 constexpr
size_t determine_tuple_size()
245 template <
typename T,
size_t TupleSize = T::tuple_size>
246 constexpr
size_t determine_tuple_size(
size_t = T::tuple_size)
253 template <
typename T>
struct determine_tuple_size_
254 :
public std::integral_constant<size_t, determine_tuple_size<T>()>
259 template <
typename T>
struct The_simdization_for_the_requested_type_is_not_implemented;
274 template <
typename T,
size_t N,
typename MT, Category = typeCategory<T>()>
275 struct ReplaceTypes :
public The_simdization_for_the_requested_type_is_not_implemented<T>
283 template <
typename T,
size_t N,
typename MT>
struct ReplaceTypes<T, N, MT, Category::None>
292 template <
typename T,
size_t N = 0,
typename MT =
void>
293 using simdize =
typename SimdizeDetail::ReplaceTypes<T, N, MT>::type;
299 template <
typename T,
size_t N,
typename MT>
300 struct ReplaceTypes<T, N, MT, Category::ArithmeticVectorizable>
301 :
public conditional<(N == 0 || Vector<T>::Size == N), Vector<T>, SimdArray<T, N>>
309 template <
size_t N,
typename MT>
310 struct ReplaceTypes<bool, N, MT, Category::ArithmeticVectorizable>
311 :
public conditional<(N == 0 || Mask<MT>::Size == N), Mask<MT>,
312 SimdMaskArray<MT, N>>
319 struct ReplaceTypes<bool, N, void, Category::ArithmeticVectorizable>
320 :
public ReplaceTypes<bool, N, float, Category::ArithmeticVectorizable>
330 template <
size_t N,
typename MT,
typename Replaced,
typename... Remaining>
331 struct SubstituteOneByOne;
337 template <
size_t N,
typename MT,
typename... Replaced,
typename T,
338 typename... Remaining>
339 struct SubstituteOneByOne<N, MT, Typelist<Replaced...>, T, Remaining...>
346 template <
typename U,
size_t M = U::Size>
347 static std::integral_constant<size_t, M> size_or_0(
int);
348 template <
typename U>
static std::integral_constant<size_t, 0> size_or_0(...);
351 using V = simdize<T, N, MT>;
357 static constexpr
auto NewN = N != 0 ? N : decltype(size_or_0<V>(
int()))::value;
364 typedef conditional_t<(N != NewN && is_same<MT, void>::value),
365 conditional_t<is_same<T, bool>::value,
float, T>, MT> NewMT;
371 using type =
typename SubstituteOneByOne<NewN, NewMT, Typelist<Replaced..., V>,
377 template <
size_t Size,
typename... Replaced>
struct SubstitutedBase;
379 template <
typename Replaced>
struct SubstitutedBase<1, Replaced> {
380 template <
typename ValueT,
template <
typename, ValueT...>
class C, ValueT... Values>
381 using SubstitutedWithValues = C<Replaced, Values...>;
384 template <
typename R0,
typename R1>
struct SubstitutedBase<2, R0, R1>
386 template <
typename ValueT,
template <
typename,
typename, ValueT...>
class C,
388 using SubstitutedWithValues = C<R0, R1, Values...>;
391 template <
typename R0,
typename R1,
typename R2>
struct SubstitutedBase<3, R0, R1, R2>
393 template <
typename ValueT,
template <
typename,
typename,
typename, ValueT...>
class C,
395 using SubstitutedWithValues = C<R0, R1, R2, Values...>;
397 #if defined Vc_ICC || defined Vc_MSVC 398 #define Vc_VALUE_PACK_EXPANSION_IS_BROKEN 1 400 template <
typename... Replaced>
struct SubstitutedBase<4, Replaced...> {
402 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 403 template <
typename ValueT,
404 template <
typename,
typename,
typename,
typename, ValueT...>
class C,
406 using SubstitutedWithValues = C<Replaced..., Values...>;
407 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 410 template <
typename... Replaced>
struct SubstitutedBase<5, Replaced...> {
411 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 412 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
415 using SubstitutedWithValues = C<Replaced..., Values...>;
416 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 419 template <
typename... Replaced>
struct SubstitutedBase<6, Replaced...> {
420 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 421 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
422 typename, ValueT...>
class C,
424 using SubstitutedWithValues = C<Replaced..., Values...>;
425 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 428 template <
typename... Replaced>
struct SubstitutedBase<7, Replaced...> {
429 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 430 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
431 typename,
typename, ValueT...>
class C,
433 using SubstitutedWithValues = C<Replaced..., Values...>;
434 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 437 template <
typename... Replaced>
struct SubstitutedBase<8, Replaced...> {
438 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 439 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
440 typename,
typename,
typename, ValueT...>
class C,
442 using SubstitutedWithValues = C<Replaced..., Values...>;
443 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 451 template <
size_t N_,
typename MT,
typename Replaced0,
typename... Replaced>
452 struct SubstituteOneByOne<N_, MT, Typelist<Replaced0, Replaced...>>
458 :
public SubstitutedBase<sizeof...(Replaced) + 1, Replaced0, Replaced...> {
459 static constexpr
auto N = N_;
464 template <
template <
typename...>
class C>
465 using Substituted = C<Replaced0, Replaced...>;
485 template <
typename Scalar,
typename Base,
size_t N>
class Adapter;
491 template <
template <
typename...>
class C,
typename... Ts,
size_t N,
typename MT>
492 struct ReplaceTypes<C<Ts...>, N, MT, Category::ClassTemplate>
495 using SubstitutionResult =
496 typename SubstituteOneByOne<N, MT, Typelist<>, Ts...>::type;
502 using Vectorized =
typename SubstitutionResult::template Substituted<C>;
508 using type = conditional_t<is_same<C<Ts...>, Vectorized>::value, C<Ts...>,
509 Adapter<C<Ts...>, Vectorized, SubstitutionResult::N>>;
517 #ifdef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 519 #define Vc_DEFINE_NONTYPE_REPLACETYPES_(ValueType_) \ 520 template <template <typename, ValueType_...> class C, typename T, ValueType_ Value0, \ 521 ValueType_... Values> \ 522 struct is_class_template<C<T, Value0, Values...>> : public true_type { \ 524 template <template <typename, typename, ValueType_...> class C, typename T0, \ 525 typename T1, ValueType_ Value0, ValueType_... Values> \ 526 struct is_class_template<C<T0, T1, Value0, Values...>> : public true_type { \ 528 template <template <typename, typename, typename, ValueType_...> class C, \ 529 typename T0, typename T1, typename T2, ValueType_ Value0, \ 530 ValueType_... Values> \ 531 struct is_class_template<C<T0, T1, T2, Value0, Values...>> : public true_type { \ 533 template <template <typename, typename, typename, typename, ValueType_...> class C, \ 534 typename T0, typename T1, typename T2, typename T3, ValueType_ Value0, \ 535 ValueType_... Values> \ 536 struct is_class_template<C<T0, T1, T2, T3, Value0, Values...>> : public true_type { \ 538 template <template <typename, typename, typename, typename, typename, ValueType_...> \ 540 typename T0, typename T1, typename T2, typename T3, typename T4, \ 541 ValueType_ Value0, ValueType_... Values> \ 542 struct is_class_template<C<T0, T1, T2, T3, T4, Value0, Values...>> \ 543 : public true_type { \ 545 template <template <typename, typename, typename, typename, typename, typename, \ 546 ValueType_...> class C, \ 547 typename T0, typename T1, typename T2, typename T3, typename T4, \ 548 typename T5, ValueType_ Value0, ValueType_... Values> \ 549 struct is_class_template<C<T0, T1, T2, T3, T4, T5, Value0, Values...>> \ 550 : public true_type { \ 552 template <template <typename, typename, typename, typename, typename, typename, \ 553 typename, ValueType_...> class C, \ 554 typename T0, typename T1, typename T2, typename T3, typename T4, \ 555 typename T5, typename T6, ValueType_ Value0, ValueType_... Values> \ 556 struct is_class_template<C<T0, T1, T2, T3, T4, T5, T6, Value0, Values...>> \ 557 : public true_type { \ 559 template <template <typename, ValueType_> class C, typename T0, ValueType_ Value0, \ 560 size_t N, typename MT> \ 561 struct ReplaceTypes<C<T0, Value0>, N, MT, Category::ClassTemplate> { \ 562 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0>::type tmp; \ 563 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \ 565 static constexpr auto NN = tmp::N; \ 566 typedef conditional_t<is_same<C<T0, Value0>, Substituted>::value, C<T0, Value0>, \ 567 Adapter<C<T0, Value0>, Substituted, NN>> type; \ 569 template <template <typename, typename, ValueType_> class C, typename T0, \ 570 typename T1, ValueType_ Value0, size_t N, typename MT> \ 571 struct ReplaceTypes<C<T0, T1, Value0>, N, MT, Category::ClassTemplate> { \ 572 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1>::type tmp; \ 573 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \ 575 static constexpr auto NN = tmp::N; \ 576 typedef conditional_t<is_same<C<T0, T1, Value0>, Substituted>::value, \ 578 Adapter<C<T0, T1, Value0>, Substituted, NN>> type; \ 580 template <template <typename, typename, typename, ValueType_> class C, typename T0, \ 581 typename T1, typename T2, ValueType_ Value0, size_t N, typename MT> \ 582 struct ReplaceTypes<C<T0, T1, T2, Value0>, N, MT, Category::ClassTemplate> { \ 583 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1, T2>::type tmp; \ 584 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \ 586 static constexpr auto NN = tmp::N; \ 587 typedef conditional_t<is_same<C<T0, T1, T2, Value0>, Substituted>::value, \ 588 C<T0, T1, T2, Value0>, \ 589 Adapter<C<T0, T1, T2, Value0>, Substituted, NN>> type; \ 592 #define Vc_DEFINE_NONTYPE_REPLACETYPES_(ValueType_) \ 593 template <template <typename, ValueType_...> class C, typename T, ValueType_ Value0, \ 594 ValueType_... Values> \ 595 struct is_class_template<C<T, Value0, Values...>> : public true_type { \ 597 template <template <typename, typename, ValueType_...> class C, typename T0, \ 598 typename T1, ValueType_ Value0, ValueType_... Values> \ 599 struct is_class_template<C<T0, T1, Value0, Values...>> : public true_type { \ 601 template <template <typename, typename, typename, ValueType_...> class C, \ 602 typename T0, typename T1, typename T2, ValueType_ Value0, \ 603 ValueType_... Values> \ 604 struct is_class_template<C<T0, T1, T2, Value0, Values...>> : public true_type { \ 606 template <template <typename, typename, typename, typename, ValueType_...> class C, \ 607 typename T0, typename T1, typename T2, typename T3, ValueType_ Value0, \ 608 ValueType_... Values> \ 609 struct is_class_template<C<T0, T1, T2, T3, Value0, Values...>> : public true_type { \ 611 template <template <typename, typename, typename, typename, typename, ValueType_...> \ 613 typename T0, typename T1, typename T2, typename T3, typename T4, \ 614 ValueType_ Value0, ValueType_... Values> \ 615 struct is_class_template<C<T0, T1, T2, T3, T4, Value0, Values...>> \ 616 : public true_type { \ 618 template <template <typename, typename, typename, typename, typename, typename, \ 619 ValueType_...> class C, \ 620 typename T0, typename T1, typename T2, typename T3, typename T4, \ 621 typename T5, ValueType_ Value0, ValueType_... Values> \ 622 struct is_class_template<C<T0, T1, T2, T3, T4, T5, Value0, Values...>> \ 623 : public true_type { \ 625 template <template <typename, typename, typename, typename, typename, typename, \ 626 typename, ValueType_...> class C, \ 627 typename T0, typename T1, typename T2, typename T3, typename T4, \ 628 typename T5, typename T6, ValueType_ Value0, ValueType_... Values> \ 629 struct is_class_template<C<T0, T1, T2, T3, T4, T5, T6, Value0, Values...>> \ 630 : public true_type { \ 632 template <template <typename, ValueType_...> class C, typename T0, \ 633 ValueType_ Value0, ValueType_... Values, size_t N, typename MT> \ 634 struct ReplaceTypes<C<T0, Value0, Values...>, N, MT, Category::ClassTemplate> { \ 635 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0>::type tmp; \ 636 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \ 637 Values...> Substituted; \ 638 static constexpr auto NN = tmp::N; \ 639 typedef conditional_t<is_same<C<T0, Value0, Values...>, Substituted>::value, \ 640 C<T0, Value0, Values...>, \ 641 Adapter<C<T0, Value0, Values...>, Substituted, NN>> type; \ 643 template <template <typename, typename, ValueType_...> class C, typename T0, \ 644 typename T1, ValueType_ Value0, ValueType_... Values, size_t N, \ 646 struct ReplaceTypes<C<T0, T1, Value0, Values...>, N, MT, Category::ClassTemplate> { \ 647 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1>::type tmp; \ 648 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \ 649 Values...> Substituted; \ 650 static constexpr auto NN = tmp::N; \ 651 typedef conditional_t<is_same<C<T0, T1, Value0, Values...>, Substituted>::value, \ 652 C<T0, T1, Value0, Values...>, \ 653 Adapter<C<T0, T1, Value0, Values...>, Substituted, NN>> \ 656 template <template <typename, typename, typename, ValueType_...> class C, \ 657 typename T0, typename T1, typename T2, ValueType_ Value0, \ 658 ValueType_... Values, size_t N, typename MT> \ 659 struct ReplaceTypes<C<T0, T1, T2, Value0, Values...>, N, MT, \ 660 Category::ClassTemplate> { \ 661 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1, T2>::type tmp; \ 662 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \ 663 Values...> Substituted; \ 664 static constexpr auto NN = tmp::N; \ 665 typedef conditional_t< \ 666 is_same<C<T0, T1, T2, Value0, Values...>, Substituted>::value, \ 667 C<T0, T1, T2, Value0, Values...>, \ 668 Adapter<C<T0, T1, T2, Value0, Values...>, Substituted, NN>> type; \ 670 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 671 Vc_DEFINE_NONTYPE_REPLACETYPES_(
bool);
672 Vc_DEFINE_NONTYPE_REPLACETYPES_(
wchar_t);
673 Vc_DEFINE_NONTYPE_REPLACETYPES_(
char);
674 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed char);
675 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned char);
676 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed short);
677 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned short);
678 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed int);
679 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned int);
680 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed long);
681 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned long);
682 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed long long);
683 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned long long);
684 #undef Vc_DEFINE_NONTYPE_REPLACETYPES_ 686 namespace is_constructible_with_single_paren_impl
688 template <
typename T> T create();
689 #if defined Vc_CLANG || defined Vc_APPLECLANG 690 template <
typename Class,
typename... Args,
typename = decltype(Class(create<Args>()...))>
693 template <
typename Class,
typename... Args>
694 typename std::conditional<
698 sizeof(Class(create<Args>()...)),
702 template <
typename Class,
typename... Args>
double test(...);
705 template <
typename Class,
typename... Args>
706 struct is_constructible_with_single_paren
707 :
public std::integral_constant<
709 1 == sizeof(is_constructible_with_single_paren_impl::test<Class, Args...>(1))> {
712 namespace is_constructible_with_single_brace_impl
714 template <
typename T> T create();
716 template <
typename Class,
typename... Args>
char test(
int);
717 #elif defined Vc_CLANG || defined Vc_APPLECLANG 718 template <
typename Class,
typename... Args,
typename = decltype(Class{create<Args>()...})>
721 template <
typename Class,
typename... Args>
722 typename std::conditional<
726 sizeof(Class{create<Args>()...}),
730 template <
typename Class,
typename... Args>
double test(...);
733 template <
typename Class,
typename... Args>
734 struct is_constructible_with_single_brace
735 :
public std::integral_constant<
737 1 == sizeof(is_constructible_with_single_brace_impl::test<Class, Args...>(1))> {
740 namespace is_constructible_with_double_brace_impl
742 template <
typename T> T create();
743 #if defined Vc_CLANG || defined Vc_APPLECLANG 744 template <
typename Class,
typename... Args,
745 typename = decltype(Class{{create<Args>()...}})>
748 template <
typename Class,
typename... Args>
749 typename std::conditional<
753 sizeof(Class{{create<Args>()...}}),
757 template <
typename Class,
typename... Args>
double test(...);
760 template <
typename Class,
typename... Args>
761 struct is_constructible_with_double_brace
762 :
public std::integral_constant<
764 1 == sizeof(is_constructible_with_double_brace_impl::test<Class, Args...>(1))> {
767 template <
size_t I,
typename T,
768 typename R = decltype(std::declval<T &>().
template vc_get_<I>())>
769 R get_dispatcher(T &x,
void * =
nullptr)
771 return x.template vc_get_<I>();
773 template <
size_t I,
typename T,
774 typename R = decltype(std::declval<const T &>().
template vc_get_<I>())>
775 R get_dispatcher(
const T &x,
void * =
nullptr)
777 return x.template vc_get_<I>();
779 template <
size_t I,
typename T,
typename R = decltype(std::get<I>(std::declval<T &>()))>
780 R get_dispatcher(T &x,
int = 0)
782 return std::get<I>(x);
784 template <
size_t I,
typename T,
785 typename R = decltype(std::get<I>(std::declval<const T &>()))>
786 R get_dispatcher(
const T &x,
int = 0)
788 return std::get<I>(x);
793 template <
typename Scalar,
typename Base,
size_t N>
class Adapter :
public Base
797 template <std::size_t... Indexes,
typename T>
798 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_, T, std::true_type)
799 : Base{{get_dispatcher<Indexes>(x_)...}}
804 template <std::size_t... Indexes>
805 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_, std::false_type,
807 : Base{get_dispatcher<Indexes>(x_)...}
812 template <std::size_t... Indexes>
813 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_, std::true_type,
815 : Base(get_dispatcher<Indexes>(x_)...)
819 template <std::size_t... Indexes>
820 Adapter(Vc::index_sequence<Indexes...> seq_,
const Scalar &x_)
822 std::integral_constant<
823 bool, is_constructible_with_single_paren<
824 Base, decltype(get_dispatcher<Indexes>(
825 std::declval<const Scalar &>()))...>::value>(),
826 std::integral_constant<
827 bool, is_constructible_with_double_brace<
828 Base, decltype(get_dispatcher<Indexes>(
829 std::declval<const Scalar &>()))...>::value>())
835 static constexpr
size_t size() {
return N; }
836 static constexpr
size_t Size = N;
839 using base_type = Base;
842 using scalar_type = Scalar;
849 #if defined Vc_CLANG && Vc_CLANG < 0x30700 850 Vc_INTRINSIC Adapter(
const Adapter &x) : Base(x) {}
852 Adapter(
const Adapter &) =
default;
854 Adapter(Adapter &&) =
default;
857 Adapter &operator=(
const Adapter &) =
default;
859 Adapter &operator=(Adapter &&) =
default;
862 template <typename U, size_t TupleSize = determine_tuple_size_<Scalar>::value,
863 typename Seq = Vc::make_index_sequence<TupleSize>,
864 typename = enable_if<std::is_convertible<U, Scalar>::value>>
866 : Adapter(Seq(), static_cast<const Scalar &>(x_))
871 template <
typename A0,
typename... Args,
872 typename =
typename std::enable_if<
873 !Traits::is_index_sequence<A0>::value &&
874 (
sizeof...(Args) > 0 || !std::is_convertible<A0, Scalar>::value)>::type>
875 Adapter(A0 &&arg0_, Args &&... arguments_)
876 : Base(
std::forward<A0>(arg0_),
std::forward<Args>(arguments_)...)
881 template <
typename T,
882 typename = decltype(Base(std::declval<
const std::initializer_list<T> &>()))>
883 Adapter(
const std::initializer_list<T> &l_)
890 void *
operator new(
size_t size)
892 return Vc::Common::aligned_malloc<alignof(Adapter)>(size);
894 void *
operator new(size_t,
void *p_) {
return p_; }
895 void *
operator new[](
size_t size)
897 return Vc::Common::aligned_malloc<alignof(Adapter)>(size);
899 void *
operator new[](size_t ,
void *p_) {
return p_; }
901 void operator delete(
void *,
void *) {}
903 void operator delete[](
void *,
void *) {}
910 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
911 inline void operator==(
912 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
913 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
914 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
915 inline void operator!=(
916 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
917 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
918 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
919 inline void operator<=(
920 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
921 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
922 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
923 inline void operator>=(
924 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
925 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
926 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
927 inline void operator<(
928 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
929 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
930 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
931 inline void operator>(
932 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
933 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
944 template <
typename Scalar,
typename Base,
size_t N>
945 class tuple_size<
Vc::SimdizeDetail::Adapter<Scalar, Base, N>> :
public tuple_size<Base>
951 template <
size_t I,
typename Scalar,
typename Base,
size_t N>
952 class tuple_element<I, Vc::SimdizeDetail::Adapter<Scalar, Base, N>>
953 :
public tuple_element<I, Base>
963 template <
typename S,
typename T,
size_t N>
964 class allocator<Vc::SimdizeDetail::Adapter<S, T, N>>
968 template <
typename U>
struct rebind
970 typedef std::allocator<U> other;
975 namespace Vc_VERSIONED_NAMESPACE
977 namespace SimdizeDetail
987 template <
typename T>
static inline T decay_workaround(
const T &x) {
return x; }
992 template <
typename S,
typename T,
size_t N,
size_t... Indexes>
993 inline void assign_impl(Adapter<S, T, N> &a,
size_t i,
const S &x,
994 Vc::index_sequence<Indexes...>)
996 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(x)))...> tmp(
997 decay_workaround(get_dispatcher<Indexes>(x))...);
998 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(tmp), 0)...};
999 if (&unused == &unused) {}
1006 template <
typename S,
typename T,
size_t N>
1007 inline void assign(Adapter<S, T, N> &a,
size_t i,
const S &x)
1009 assign_impl(a, i, x, Vc::make_index_sequence<determine_tuple_size<T>()>());
1014 template <typename V, typename = enable_if<Traits::is_simd_vector<V>::value>>
1015 Vc_INTRINSIC
void assign(V &v,
size_t i,
typename V::EntryType x)
1023 template <
typename S,
typename T,
size_t N,
size_t... Indexes>
1024 inline S extract_impl(
const Adapter<S, T, N> &a,
size_t i, Vc::index_sequence<Indexes...>)
1026 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a)[i]))...> tmp(
1027 decay_workaround(get_dispatcher<Indexes>(a)[i])...);
1028 return S(get_dispatcher<Indexes>(tmp)...);
1035 template <
typename S,
typename T,
size_t N>
1036 inline S
extract(
const Adapter<S, T, N> &a,
size_t i)
1038 return extract_impl(a, i, Vc::make_index_sequence<determine_tuple_size<S>()>());
1043 template <typename V, typename = enable_if<Traits::is_simd_vector<V>::value>>
1044 Vc_INTRINSIC
typename V::EntryType
extract(
const V &v,
size_t i)
1049 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1050 inline Adapter<S, T, N> shifted_impl(
const Adapter<S, T, N> &a,
int shift,
1051 Vc::index_sequence<Indexes...>)
1054 auto &&unused = {(get_dispatcher<Indexes>(r) = get_dispatcher<Indexes>(a).shifted(shift), 0)...};
1055 if (&unused == &unused) {}
1067 template <
typename S,
typename T,
size_t N>
1068 inline Adapter<S, T, N>
shifted(
const Adapter<S, T, N> &a,
int shift)
1070 return shifted_impl(a, shift, Vc::make_index_sequence<determine_tuple_size<T>()>());
1076 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1077 inline void swap_impl(Adapter<S, T, N> &a, std::size_t i, S &x,
1078 Vc::index_sequence<Indexes...>)
1080 const auto &a_const = a;
1081 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a_const)[0]))...>
1082 tmp{decay_workaround(get_dispatcher<Indexes>(a_const)[i])...};
1083 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(x), 0)...};
1084 auto &&unused2 = {(get_dispatcher<Indexes>(x) = get_dispatcher<Indexes>(tmp), 0)...};
1085 if (&unused == &unused2) {}
1087 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1088 inline void swap_impl(Adapter<S, T, N> &a, std::size_t i, Adapter<S, T, N> &b,
1089 std::size_t j, Vc::index_sequence<Indexes...>)
1091 const auto &a_const = a;
1092 const auto &b_const = b;
1093 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a_const)[0]))...>
1094 tmp{decay_workaround(get_dispatcher<Indexes>(a_const)[i])...};
1095 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(b_const)[j], 0)...};
1096 auto &&unused2 = {(get_dispatcher<Indexes>(b)[j] = get_dispatcher<Indexes>(tmp), 0)...};
1097 if (&unused == &unused2) {}
1104 template <
typename S,
typename T, std::
size_t N>
1105 inline void swap(Adapter<S, T, N> &a, std::size_t i, S &x)
1107 swap_impl(a, i, x, Vc::make_index_sequence<determine_tuple_size<T>()>());
1109 template <
typename S,
typename T, std::
size_t N>
1110 inline void swap(Adapter<S, T, N> &a, std::size_t i, Adapter<S, T, N> &b, std::size_t j)
1112 swap_impl(a, i, b, j, Vc::make_index_sequence<determine_tuple_size<T>()>());
1115 template <
typename A>
class Scalar
1117 using reference =
typename std::add_lvalue_reference<A>::type;
1118 using S =
typename A::scalar_type;
1119 using IndexSeq = Vc::make_index_sequence<determine_tuple_size<S>()>;
1122 Scalar(reference aa,
size_t ii) : a(aa), i(ii) {}
1125 Scalar(
const Scalar &) =
delete;
1126 Scalar(Scalar &&) =
delete;
1127 Scalar &operator=(
const Scalar &) =
delete;
1128 Scalar &operator=(Scalar &&) =
delete;
1130 void operator=(
const S &x) { assign_impl(a, i, x, IndexSeq()); }
1131 operator S()
const {
return extract_impl(a, i, IndexSeq()); }
1133 template <
typename AA>
1134 friend inline void swap(Scalar<AA> &&a,
typename AA::scalar_type &b);
1135 template <
typename AA>
1136 friend inline void swap(
typename AA::scalar_type &b, Scalar<AA> &&a);
1137 template <
typename AA>
friend inline void swap(Scalar<AA> &&a, Scalar<AA> &&b);
1146 template <
typename A>
inline void swap(Scalar<A> &&a,
typename A::scalar_type &b)
1148 swap_impl(a.a, a.i, b,
typename Scalar<A>::IndexSeq());
1152 template <
typename A>
inline void swap(
typename A::scalar_type &b, Scalar<A> &&a)
1154 swap_impl(a.a, a.i, b,
typename Scalar<A>::IndexSeq());
1157 template <
typename A>
inline void swap(Scalar<A> &&a, Scalar<A> &&b)
1159 swap_impl(a.a, a.i, b.a, b.i,
typename Scalar<A>::IndexSeq());
1162 template <
typename A>
class Interface
1164 using reference =
typename std::add_lvalue_reference<A>::type;
1166 Vc::make_index_sequence<determine_tuple_size<typename A::scalar_type>()>;
1169 Interface(reference aa) : a(aa) {}
1171 Scalar<A> operator[](
size_t i)
1175 typename A::scalar_type operator[](
size_t i)
const 1177 return extract_impl(a, i, IndexSeq());
1182 return shifted_impl(a, amount, IndexSeq());
1189 template <
typename S,
typename T,
size_t N>
1190 Interface<Adapter<S, T, N>> decorate(Adapter<S, T, N> &a)
1194 template <
typename S,
typename T,
size_t N>
1195 const Interface<const Adapter<S, T, N>> decorate(
const Adapter<S, T, N> &a)
1200 namespace IteratorDetails
1202 enum class Mutable { Yes, No };
1204 template <
typename It,
typename V,
size_t I,
size_t End>
1205 Vc_INTRINSIC V fromIteratorImpl(enable_if<(I == End), It>)
1209 template <
typename It,
typename V,
size_t I,
size_t End>
1210 Vc_INTRINSIC V fromIteratorImpl(enable_if<(I < End), It> it)
1212 V r = fromIteratorImpl<It, V, I + 1, End>(it);
1213 Traits::decay<decltype(get_dispatcher<I>(r))> tmp;
1214 for (
size_t j = 0; j < V::size(); ++j, ++it) {
1215 tmp[j] = get_dispatcher<I>(*it);
1217 get_dispatcher<I>(r) = tmp;
1220 template <
typename It,
typename V>
1223 return fromIteratorImpl<It, V, 0, determine_tuple_size<V>()>(it);
1225 template <
typename It,
typename V>
1229 for (
size_t j = 0; j < V::size(); ++j, ++it) {
1238 template <
typename T,
typename value_vector, Mutable>
class Pointer;
1248 template <
typename T,
typename value_vector>
class Pointer<T, value_vector, Mutable::Yes>
1250 static constexpr
auto Size = value_vector::size();
1254 value_vector *operator->() {
return &data; }
1261 Pointer(
const Pointer &) =
delete;
1262 Pointer &operator=(
const Pointer &) =
delete;
1263 Pointer &operator=(Pointer &&) =
delete;
1266 Pointer(Pointer &&) =
default;
1276 for (
size_t i = 0; i < Size; ++i, ++begin_iterator) {
1277 *begin_iterator =
extract(data, i);
1282 Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)), begin_iterator(it) {}
1295 template <
typename T,
typename value_vector>
class Pointer<T, value_vector, Mutable::No>
1297 static constexpr
auto Size = value_vector::size();
1300 const value_vector *operator->()
const {
return &data; }
1303 Pointer(
const Pointer &) =
delete;
1304 Pointer &operator=(
const Pointer &) =
delete;
1305 Pointer &operator=(Pointer &&) =
delete;
1307 Pointer(Pointer &&) =
default;
1309 Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)) {}
1327 template <
typename T,
typename value_vector, Mutable M>
class Reference;
1330 template <
typename T,
typename value_vector>
1331 class Reference<T, value_vector, Mutable::Yes> :
public value_vector
1333 static constexpr
auto Size = value_vector::size();
1335 using reference =
typename std::add_lvalue_reference<T>::type;
1336 reference scalar_it;
1341 Reference(reference first_it)
1342 : value_vector(fromIterator<T, value_vector>(first_it)), scalar_it(first_it)
1347 Reference(
const Reference &) =
delete;
1348 Reference(Reference &&) =
default;
1349 Reference &operator=(
const Reference &) =
delete;
1350 Reference &operator=(Reference &&) =
delete;
1357 void operator=(
const value_vector &x)
1359 static_cast<value_vector &
>(*this) = x;
1360 auto it = scalar_it;
1361 for (
size_t i = 0; i < Size; ++i, ++it) {
1366 #define Vc_OP(op_) \ 1367 template <typename T0, typename V0, typename T1, typename V1> \ 1368 decltype(std::declval<const V0 &>() op_ std::declval<const V1 &>()) operator op_( \ 1369 const Reference<T0, V0, Mutable::Yes> &x, \ 1370 const Reference<T1, V1, Mutable::Yes> &y) \ 1372 return static_cast<const V0 &>(x) op_ static_cast<const V1 &>(y); \ 1374 Vc_ALL_COMPARES(Vc_OP);
1375 Vc_ALL_ARITHMETICS(Vc_OP);
1376 Vc_ALL_BINARY(Vc_OP);
1377 Vc_ALL_LOGICAL(Vc_OP);
1378 Vc_ALL_SHIFTS(Vc_OP);
1382 template <
typename T,
typename value_vector>
1383 class Reference<T, value_vector, Mutable::No> :
public value_vector
1385 static constexpr
auto Size = value_vector::size();
1388 Reference(
const T &it) : value_vector(fromIterator<T, value_vector>(it)) {}
1390 Reference(
const Reference &) =
delete;
1391 Reference(Reference &&) =
default;
1392 Reference &operator=(
const Reference &) =
delete;
1393 Reference &operator=(Reference &&) =
delete;
1396 void operator=(
const value_vector &x) =
delete;
1399 template <
typename T,
size_t N,
1400 IteratorDetails::Mutable M =
1401 (Traits::is_output_iterator<T>::value ? Mutable::Yes : Mutable::No),
1402 typename V = simdize<
typename std::iterator_traits<T>::value_type, N>,
1403 size_t Size = V::Size,
1404 typename =
typename std::iterator_traits<T>::iterator_category>
1407 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size_>
1408 class Iterator<T, N, M, V, Size_, std::forward_iterator_tag>
1409 :
public std::iterator<typename std::iterator_traits<T>::iterator_category, V,
1410 typename std::iterator_traits<T>::difference_type,
1411 IteratorDetails::Pointer<T, V, M>,
1412 IteratorDetails::Reference<T, V, M>>
1415 using pointer = IteratorDetails::Pointer<T, V, M>;
1416 using reference = IteratorDetails::Reference<T, V, M>;
1417 using const_pointer = IteratorDetails::Pointer<T, V, IteratorDetails::Mutable::No>;
1418 using const_reference =
1419 IteratorDetails::Reference<T, V, IteratorDetails::Mutable::No>;
1422 static constexpr std::size_t size() {
return Size_; }
1423 static constexpr std::size_t Size = Size_;
1425 Iterator() =
default;
1433 Iterator(
const T &x) : scalar_it(x) {}
1437 Iterator(T &&x) : scalar_it(std::move(x)) {}
1441 Iterator &operator=(
const T &x)
1449 Iterator &operator=(T &&x)
1451 scalar_it = std::move(x);
1456 Iterator(
const Iterator &) =
default;
1458 Iterator(Iterator &&) =
default;
1460 Iterator &operator=(
const Iterator &) =
default;
1462 Iterator &operator=(Iterator &&) =
default;
1465 Iterator &operator++()
1467 std::advance(scalar_it, Size);
1471 Iterator operator++(
int)
1473 Iterator copy(*
this);
1486 bool operator==(
const Iterator &rhs)
const 1489 if (scalar_it == rhs.scalar_it) {
1493 for (
size_t i = 1; i < Size; ++i) {
1494 Vc_ASSERT((++it != rhs.scalar_it));
1499 return scalar_it == rhs.scalar_it;
1510 bool operator!=(
const Iterator &rhs)
const 1512 return !operator==(rhs);
1515 pointer operator->() {
return scalar_it; }
1523 reference
operator*() {
return scalar_it; }
1525 const_pointer operator->()
const {
return scalar_it; }
1534 const_reference
operator*()
const {
return scalar_it; }
1549 operator const T &()
const {
return scalar_it; }
1559 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1560 class Iterator<T, N, M, V, Size,
std::bidirectional_iterator_tag>
1561 :
public Iterator<T, N, M, V, Size, std::forward_iterator_tag>
1563 using Base = Iterator<T, N, M, V, Size, std::forward_iterator_tag>;
1566 using Base::scalar_it;
1569 using pointer =
typename Base::pointer;
1570 using reference =
typename Base::reference;
1571 using const_pointer =
typename Base::const_pointer;
1572 using const_reference =
typename Base::const_reference;
1574 using Iterator<T, N, M, V, Size,
1575 std::forward_iterator_tag>::Iterator;
1581 std::advance(scalar_it, -Size);
1587 Iterator copy(*
this);
1597 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1598 class Iterator<T, N, M, V, Size,
std::random_access_iterator_tag>
1599 :
public Iterator<T, N, M, V, Size, std::bidirectional_iterator_tag>
1604 using Base::scalar_it;
1607 using pointer =
typename Base::pointer;
1608 using reference =
typename Base::reference;
1609 using const_pointer =
typename Base::const_pointer;
1610 using const_reference =
typename Base::const_reference;
1611 using difference_type =
typename std::iterator_traits<T>::difference_type;
1616 Iterator &operator+=(difference_type n)
1618 scalar_it += n * difference_type(Size);
1621 Iterator
operator+(difference_type n)
const {
return Iterator(*
this) += n; }
1623 Iterator &operator-=(difference_type n)
1625 scalar_it -= n * difference_type(Size);
1628 Iterator
operator-(difference_type n)
const {
return Iterator(*
this) -= n; }
1630 difference_type
operator-(
const Iterator &rhs)
const 1632 constexpr difference_type n = Size;
1633 Vc_ASSERT((scalar_it - rhs.scalar_it) % n ==
1639 return (scalar_it - rhs.scalar_it) / n;
1648 return rhs.scalar_it - scalar_it >= difference_type(Size);
1651 bool operator>(
const Iterator &rhs)
const 1653 return scalar_it - rhs.scalar_it >= difference_type(Size);
1656 bool operator<=(
const Iterator &rhs)
const 1658 return rhs.scalar_it - scalar_it >= difference_type(Size) - 1;
1661 bool operator>=(
const Iterator &rhs)
const 1663 return scalar_it - rhs.scalar_it >= difference_type(Size) - 1;
1666 reference operator[](difference_type i) {
return *(*
this + i); }
1667 const_reference operator[](difference_type i)
const {
return *(*
this + i); }
1670 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1672 typename Iterator<T, N, M, V, Size, std::random_access_iterator_tag>::difference_type
1689 template <
typename T,
size_t N,
typename MT>
1690 struct ReplaceTypes<T, N, MT, Category::ForwardIterator>
1692 using type = IteratorDetails::Iterator<T, N>;
1694 template <
typename T,
size_t N,
typename MT>
1695 struct ReplaceTypes<T, N, MT, Category::BidirectionalIterator>
1697 using type = IteratorDetails::Iterator<T, N>;
1699 template <
typename T,
size_t N,
typename MT>
1700 struct ReplaceTypes<T, N, MT, Category::RandomAccessIterator>
1702 using type = IteratorDetails::Iterator<T, N>;
1708 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
typename U,
1710 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N),
void>
1711 conditional_assign(Adapter<S, T, N> &,
const M &,
const U &)
1714 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
typename U,
1715 std::size_t Offset = 0>
1716 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N),
void>
1717 conditional_assign(Adapter<S, T, N> &lhs,
const M &mask,
const U &rhs)
1719 using V =
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
1720 using M2 =
typename V::mask_type;
1721 conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask), get_dispatcher<Offset>(rhs));
1722 conditional_assign<Op, S, T, N, M, U, Offset + 1>(lhs, mask, rhs);
1724 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
1726 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N),
void>
1727 conditional_assign(Adapter<S, T, N> &,
const M &)
1730 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
1731 std::size_t Offset = 0>
1732 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N),
void>
1733 conditional_assign(Adapter<S, T, N> &lhs,
const M &mask)
1735 using V =
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
1736 using M2 =
typename V::mask_type;
1737 conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask));
1738 conditional_assign<Op, S, T, N, M, Offset + 1>(lhs, mask);
1762 template <
typename T,
size_t N = 0,
typename MT =
void>
1763 using simdize = SimdizeDetail::simdize<T, N, MT>;
1784 #define Vc_SIMDIZE_INTERFACE(MEMBERS_) \ 1785 template <std::size_t N_> \ 1786 inline auto vc_get_()->decltype(std::get<N_>(std::tie MEMBERS_)) \ 1788 return std::get<N_>(std::tie MEMBERS_); \ 1790 template <std::size_t N_> \ 1791 inline auto vc_get_() const->decltype(std::get<N_>(std::tie MEMBERS_)) \ 1793 return std::get<N_>(std::tie MEMBERS_); \ 1795 enum : std::size_t { \ 1796 tuple_size = std::tuple_size<decltype(std::make_tuple MEMBERS_)>::value \ 1803 using Vc::SimdizeDetail::swap;
1806 #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].
Identifies any SIMD vector type (independent of implementation or whether it's SimdArray<T, N>).
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.
This is the iterator type created when applying simdize to a random access iterator type...
Vector Classes Namespace.
This is the iterator type created when applying simdize to a bidirectional iterator type...