28 #ifndef VC_COMMON_SIMDIZE_H_ 29 #define VC_COMMON_SIMDIZE_H_ 34 #include "../Allocator" 35 #include "interleavedmemory.h" 122 namespace Vc_VERSIONED_NAMESPACE
130 namespace SimdizeDetail
137 using std::is_base_of;
138 using std::false_type;
139 using std::true_type;
140 using std::iterator_traits;
141 using std::conditional;
143 template <
bool B,
typename T,
typename F>
144 using conditional_t =
typename conditional<B, T, F>::type;
150 template <
typename... Ts>
struct Typelist;
155 enum class Category {
159 ArithmeticVectorizable,
167 BidirectionalIterator,
169 RandomAccessIterator,
178 template <
typename T,
typename ItCat =
typename T::iterator_category>
179 constexpr Category iteratorCategories(
int, ItCat * =
nullptr)
181 return is_base_of<std::random_access_iterator_tag, ItCat>::value
182 ? Category::RandomAccessIterator
183 : is_base_of<std::bidirectional_iterator_tag, ItCat>::value
184 ? Category::BidirectionalIterator
185 : is_base_of<std::forward_iterator_tag, ItCat>::value
186 ? Category::ForwardIterator
187 : is_base_of<std::output_iterator_tag, ItCat>::value
188 ? Category::OutputIterator
189 : is_base_of<std::input_iterator_tag, ItCat>::value
190 ? Category::InputIterator
196 template <
typename T>
197 constexpr enable_if<std::is_pointer<T>::value, Category> iteratorCategories(
float)
199 return Category::RandomAccessIterator;
204 template <
typename T> constexpr Category iteratorCategories(...)
206 return Category::None;
212 template <
typename T>
struct is_class_template :
public false_type
215 template <
template <
typename...>
class C,
typename... Ts>
216 struct is_class_template<C<Ts...>> :
public true_type
223 template <
typename T> constexpr Category typeCategory()
225 return (is_same<T, bool>::value || is_same<T, short>::value ||
226 is_same<T, unsigned short>::value || is_same<T, int>::value ||
227 is_same<T, unsigned int>::value || is_same<T, float>::value ||
228 is_same<T, double>::value)
229 ? Category::ArithmeticVectorizable
230 : iteratorCategories<T>(int()) != Category::None
231 ? iteratorCategories<T>(
int())
232 : is_class_template<T>::value ? Category::ClassTemplate
241 template <typename T, size_t TupleSize = std::tuple_size<T>::value>
242 constexpr
size_t determine_tuple_size()
246 template <
typename T,
size_t TupleSize = T::tuple_size>
247 constexpr
size_t determine_tuple_size(
size_t = T::tuple_size)
254 template <
typename T>
struct determine_tuple_size_
255 :
public std::integral_constant<size_t, determine_tuple_size<T>()>
260 template <
typename T>
struct The_simdization_for_the_requested_type_is_not_implemented;
275 template <
typename T,
size_t N,
typename MT, Category = typeCategory<T>()>
276 struct ReplaceTypes :
public The_simdization_for_the_requested_type_is_not_implemented<T>
284 template <
typename T,
size_t N,
typename MT>
struct ReplaceTypes<T, N, MT, Category::None>
293 template <
typename T,
size_t N = 0,
typename MT =
void>
294 using simdize =
typename SimdizeDetail::ReplaceTypes<T, N, MT>::type;
297 template <
class T,
size_t N,
298 class Best =
typename Common::select_best_vector_type<T, N>::type>
299 using deduce_vector_t =
300 typename std::conditional<Best::size() == N, Best, SimdArray<T, N>>::type;
306 template <
typename T,
size_t N,
typename MT>
307 struct ReplaceTypes<T, N, MT, Category::ArithmeticVectorizable>
308 :
public conditional<N == 0, Vector<T>, deduce_vector_t<T, N>> {
315 template <
size_t N,
typename MT>
316 struct ReplaceTypes<bool, N, MT, Category::ArithmeticVectorizable>
317 :
public std::enable_if<true, typename ReplaceTypes<MT, N, MT>::type::mask_type> {
323 struct ReplaceTypes<bool, N, void, Category::ArithmeticVectorizable>
324 :
public ReplaceTypes<bool, N, float, Category::ArithmeticVectorizable>
334 template <
size_t N,
typename MT,
typename Replaced,
typename... Remaining>
335 struct SubstituteOneByOne;
341 template <
size_t N,
typename MT,
typename... Replaced,
typename T,
342 typename... Remaining>
343 struct SubstituteOneByOne<N, MT, Typelist<Replaced...>, T, Remaining...>
350 template <
typename U,
size_t M = U::Size>
351 static std::integral_constant<size_t, M> size_or_0(
int);
352 template <
typename U>
static std::integral_constant<size_t, 0> size_or_0(...);
355 using V = simdize<T, N, MT>;
361 static constexpr
auto NewN = N != 0 ? N : decltype(size_or_0<V>(
int()))::value;
368 typedef conditional_t<(N != NewN && is_same<MT, void>::value),
369 conditional_t<is_same<T, bool>::value,
float, T>, MT> NewMT;
375 using type =
typename SubstituteOneByOne<NewN, NewMT, Typelist<Replaced..., V>,
381 template <
size_t Size,
typename... Replaced>
struct SubstitutedBase;
383 template <
typename Replaced>
struct SubstitutedBase<1, Replaced> {
384 template <
typename ValueT,
template <
typename, ValueT...>
class C, ValueT... Values>
385 using SubstitutedWithValues = C<Replaced, Values...>;
388 template <
typename R0,
typename R1>
struct SubstitutedBase<2, R0, R1>
390 template <
typename ValueT,
template <
typename,
typename, ValueT...>
class C,
392 using SubstitutedWithValues = C<R0, R1, Values...>;
395 template <
typename R0,
typename R1,
typename R2>
struct SubstitutedBase<3, R0, R1, R2>
397 template <
typename ValueT,
template <
typename,
typename,
typename, ValueT...>
class C,
399 using SubstitutedWithValues = C<R0, R1, R2, Values...>;
401 #if defined Vc_ICC || defined Vc_MSVC 402 #define Vc_VALUE_PACK_EXPANSION_IS_BROKEN 1 404 template <
typename... Replaced>
struct SubstitutedBase<4, Replaced...> {
406 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 407 template <
typename ValueT,
408 template <
typename,
typename,
typename,
typename, ValueT...>
class C,
410 using SubstitutedWithValues = C<Replaced..., Values...>;
411 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 414 template <
typename... Replaced>
struct SubstitutedBase<5, Replaced...> {
415 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 416 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
419 using SubstitutedWithValues = C<Replaced..., Values...>;
420 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 423 template <
typename... Replaced>
struct SubstitutedBase<6, Replaced...> {
424 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 425 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
426 typename, ValueT...>
class C,
428 using SubstitutedWithValues = C<Replaced..., Values...>;
429 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 432 template <
typename... Replaced>
struct SubstitutedBase<7, Replaced...> {
433 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 434 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
435 typename,
typename, ValueT...>
class C,
437 using SubstitutedWithValues = C<Replaced..., Values...>;
438 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 441 template <
typename... Replaced>
struct SubstitutedBase<8, Replaced...> {
442 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 443 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
444 typename,
typename,
typename, ValueT...>
class C,
446 using SubstitutedWithValues = C<Replaced..., Values...>;
447 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 455 template <
size_t N_,
typename MT,
typename Replaced0,
typename... Replaced>
456 struct SubstituteOneByOne<N_, MT, Typelist<Replaced0, Replaced...>>
462 :
public SubstitutedBase<sizeof...(Replaced) + 1, Replaced0, Replaced...> {
463 static constexpr
auto N = N_;
468 template <
template <
typename...>
class C>
469 using Substituted = C<Replaced0, Replaced...>;
489 template <
typename Scalar,
typename Base,
size_t N>
class Adapter;
495 template <
template <
typename...>
class C,
typename... Ts,
size_t N,
typename MT>
496 struct ReplaceTypes<C<Ts...>, N, MT, Category::ClassTemplate>
499 using SubstitutionResult =
500 typename SubstituteOneByOne<N, MT, Typelist<>, Ts...>::type;
506 using Vectorized =
typename SubstitutionResult::template Substituted<C>;
512 using type = conditional_t<is_same<C<Ts...>, Vectorized>::value, C<Ts...>,
513 Adapter<C<Ts...>, Vectorized, SubstitutionResult::N>>;
521 #ifdef Vc_VALUE_PACK_EXPANSION_IS_BROKEN 523 #define Vc_DEFINE_NONTYPE_REPLACETYPES_(ValueType_) \ 524 template <template <typename, ValueType_...> class C, typename T, ValueType_ Value0, \ 525 ValueType_... Values> \ 526 struct is_class_template<C<T, Value0, Values...>> : public true_type { \ 528 template <template <typename, typename, ValueType_...> class C, typename T0, \ 529 typename T1, ValueType_ Value0, ValueType_... Values> \ 530 struct is_class_template<C<T0, T1, Value0, Values...>> : public true_type { \ 532 template <template <typename, typename, typename, ValueType_...> class C, \ 533 typename T0, typename T1, typename T2, ValueType_ Value0, \ 534 ValueType_... Values> \ 535 struct is_class_template<C<T0, T1, T2, Value0, Values...>> : public true_type { \ 537 template <template <typename, typename, typename, typename, ValueType_...> class C, \ 538 typename T0, typename T1, typename T2, typename T3, ValueType_ Value0, \ 539 ValueType_... Values> \ 540 struct is_class_template<C<T0, T1, T2, T3, Value0, Values...>> : public true_type { \ 542 template <template <typename, typename, typename, typename, typename, ValueType_...> \ 544 typename T0, typename T1, typename T2, typename T3, typename T4, \ 545 ValueType_ Value0, ValueType_... Values> \ 546 struct is_class_template<C<T0, T1, T2, T3, T4, Value0, Values...>> \ 547 : public true_type { \ 549 template <template <typename, typename, typename, typename, typename, typename, \ 550 ValueType_...> class C, \ 551 typename T0, typename T1, typename T2, typename T3, typename T4, \ 552 typename T5, ValueType_ Value0, ValueType_... Values> \ 553 struct is_class_template<C<T0, T1, T2, T3, T4, T5, Value0, Values...>> \ 554 : public true_type { \ 556 template <template <typename, typename, typename, typename, typename, typename, \ 557 typename, ValueType_...> class C, \ 558 typename T0, typename T1, typename T2, typename T3, typename T4, \ 559 typename T5, typename T6, ValueType_ Value0, ValueType_... Values> \ 560 struct is_class_template<C<T0, T1, T2, T3, T4, T5, T6, Value0, Values...>> \ 561 : public true_type { \ 563 template <template <typename, ValueType_> class C, typename T0, ValueType_ Value0, \ 564 size_t N, typename MT> \ 565 struct ReplaceTypes<C<T0, Value0>, N, MT, Category::ClassTemplate> { \ 566 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0>::type tmp; \ 567 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \ 569 static constexpr auto NN = tmp::N; \ 570 typedef conditional_t<is_same<C<T0, Value0>, Substituted>::value, C<T0, Value0>, \ 571 Adapter<C<T0, Value0>, Substituted, NN>> type; \ 573 template <template <typename, typename, ValueType_> class C, typename T0, \ 574 typename T1, ValueType_ Value0, size_t N, typename MT> \ 575 struct ReplaceTypes<C<T0, T1, Value0>, N, MT, Category::ClassTemplate> { \ 576 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1>::type tmp; \ 577 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \ 579 static constexpr auto NN = tmp::N; \ 580 typedef conditional_t<is_same<C<T0, T1, Value0>, Substituted>::value, \ 582 Adapter<C<T0, T1, Value0>, Substituted, NN>> type; \ 584 template <template <typename, typename, typename, ValueType_> class C, typename T0, \ 585 typename T1, typename T2, ValueType_ Value0, size_t N, typename MT> \ 586 struct ReplaceTypes<C<T0, T1, T2, Value0>, N, MT, Category::ClassTemplate> { \ 587 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1, T2>::type tmp; \ 588 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \ 590 static constexpr auto NN = tmp::N; \ 591 typedef conditional_t<is_same<C<T0, T1, T2, Value0>, Substituted>::value, \ 592 C<T0, T1, T2, Value0>, \ 593 Adapter<C<T0, T1, T2, Value0>, Substituted, NN>> type; \ 596 #define Vc_DEFINE_NONTYPE_REPLACETYPES_(ValueType_) \ 597 template <template <typename, ValueType_...> class C, typename T, ValueType_ Value0, \ 598 ValueType_... Values> \ 599 struct is_class_template<C<T, Value0, Values...>> : public true_type { \ 601 template <template <typename, typename, ValueType_...> class C, typename T0, \ 602 typename T1, ValueType_ Value0, ValueType_... Values> \ 603 struct is_class_template<C<T0, T1, Value0, Values...>> : public true_type { \ 605 template <template <typename, typename, typename, ValueType_...> class C, \ 606 typename T0, typename T1, typename T2, ValueType_ Value0, \ 607 ValueType_... Values> \ 608 struct is_class_template<C<T0, T1, T2, Value0, Values...>> : public true_type { \ 610 template <template <typename, typename, typename, typename, ValueType_...> class C, \ 611 typename T0, typename T1, typename T2, typename T3, ValueType_ Value0, \ 612 ValueType_... Values> \ 613 struct is_class_template<C<T0, T1, T2, T3, Value0, Values...>> : public true_type { \ 615 template <template <typename, typename, typename, typename, typename, ValueType_...> \ 617 typename T0, typename T1, typename T2, typename T3, typename T4, \ 618 ValueType_ Value0, ValueType_... Values> \ 619 struct is_class_template<C<T0, T1, T2, T3, T4, Value0, Values...>> \ 620 : public true_type { \ 622 template <template <typename, typename, typename, typename, typename, typename, \ 623 ValueType_...> class C, \ 624 typename T0, typename T1, typename T2, typename T3, typename T4, \ 625 typename T5, ValueType_ Value0, ValueType_... Values> \ 626 struct is_class_template<C<T0, T1, T2, T3, T4, T5, Value0, Values...>> \ 627 : public true_type { \ 629 template <template <typename, typename, typename, typename, typename, typename, \ 630 typename, ValueType_...> class C, \ 631 typename T0, typename T1, typename T2, typename T3, typename T4, \ 632 typename T5, typename T6, ValueType_ Value0, ValueType_... Values> \ 633 struct is_class_template<C<T0, T1, T2, T3, T4, T5, T6, Value0, Values...>> \ 634 : public true_type { \ 636 template <template <typename, ValueType_...> class C, typename T0, \ 637 ValueType_ Value0, ValueType_... Values, size_t N, typename MT> \ 638 struct ReplaceTypes<C<T0, Value0, Values...>, N, MT, Category::ClassTemplate> { \ 639 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0>::type tmp; \ 640 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \ 641 Values...> Substituted; \ 642 static constexpr auto NN = tmp::N; \ 643 typedef conditional_t<is_same<C<T0, Value0, Values...>, Substituted>::value, \ 644 C<T0, Value0, Values...>, \ 645 Adapter<C<T0, Value0, Values...>, Substituted, NN>> type; \ 647 template <template <typename, typename, ValueType_...> class C, typename T0, \ 648 typename T1, ValueType_ Value0, ValueType_... Values, size_t N, \ 650 struct ReplaceTypes<C<T0, T1, Value0, Values...>, N, MT, Category::ClassTemplate> { \ 651 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1>::type tmp; \ 652 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \ 653 Values...> Substituted; \ 654 static constexpr auto NN = tmp::N; \ 655 typedef conditional_t<is_same<C<T0, T1, Value0, Values...>, Substituted>::value, \ 656 C<T0, T1, Value0, Values...>, \ 657 Adapter<C<T0, T1, Value0, Values...>, Substituted, NN>> \ 660 template <template <typename, typename, typename, ValueType_...> class C, \ 661 typename T0, typename T1, typename T2, ValueType_ Value0, \ 662 ValueType_... Values, size_t N, typename MT> \ 663 struct ReplaceTypes<C<T0, T1, T2, Value0, Values...>, N, MT, \ 664 Category::ClassTemplate> { \ 665 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1, T2>::type tmp; \ 666 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \ 667 Values...> Substituted; \ 668 static constexpr auto NN = tmp::N; \ 669 typedef conditional_t< \ 670 is_same<C<T0, T1, T2, Value0, Values...>, Substituted>::value, \ 671 C<T0, T1, T2, Value0, Values...>, \ 672 Adapter<C<T0, T1, T2, Value0, Values...>, Substituted, NN>> type; \ 674 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 675 Vc_DEFINE_NONTYPE_REPLACETYPES_(
bool);
676 Vc_DEFINE_NONTYPE_REPLACETYPES_(
wchar_t);
677 Vc_DEFINE_NONTYPE_REPLACETYPES_(
char);
678 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed char);
679 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned char);
680 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed short);
681 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned short);
682 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed int);
683 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned int);
684 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed long);
685 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned long);
686 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed long long);
687 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned long long);
688 #undef Vc_DEFINE_NONTYPE_REPLACETYPES_ 691 namespace preferred_construction_impl
693 template <
typename T> T create();
695 template <
class Type,
class... Init,
class = decltype(Type(create<Init>()...))>
696 constexpr std::integral_constant<int, 0> test(
int);
698 template <
class Type,
class... Init,
class = decltype(Type{create<Init>()...})>
699 constexpr std::integral_constant<int, 1> test(
float);
701 template <
class Type,
class... Init,
class T,
class = decltype(Type{{create<Init>()...}})>
702 constexpr std::integral_constant<int, 2> test(T);
704 template <
class Type,
class... Init> constexpr std::integral_constant<int, 3> test(...);
707 template <
class Type,
class... Init>
708 constexpr
inline decltype(preferred_construction_impl::test<Type, Init...>(0))
709 preferred_construction()
720 template <
size_t I,
typename T,
721 typename R = decltype(std::declval<T &>().
template vc_get_<I>())>
722 R get_dispatcher(T &x,
void * =
nullptr)
724 return x.template vc_get_<I>();
726 template <
size_t I,
typename T,
727 typename R = decltype(std::declval<const T &>().
template vc_get_<I>())>
728 R get_dispatcher(
const T &x,
void * =
nullptr)
730 return x.template vc_get_<I>();
732 template <
size_t I,
typename T,
typename R = decltype(std::get<I>(std::declval<T &>()))>
733 R get_dispatcher(T &x,
int = 0)
735 return std::get<I>(x);
737 template <
size_t I,
typename T,
738 typename R = decltype(std::get<I>(std::declval<const T &>()))>
739 R get_dispatcher(
const T &x,
int = 0)
741 return std::get<I>(x);
751 template <
class... Ts>
struct homogeneous_sizeof;
752 template <
class T,
class =
void>
struct homogeneous_sizeof_one;
754 template <
class T,
size_t... Is>
755 std::integral_constant<size_t,
756 homogeneous_sizeof<
typename std::remove_reference<decltype(
757 get_dispatcher<Is>(std::declval<T>()))>::type...>::value>
758 homogeneous_sizeof_helper(index_sequence<Is...>);
761 struct homogeneous_sizeof_one<T,
762 typename
std::enable_if<std::is_arithmetic<T>::value>::type>
763 : std::integral_constant<size_t, sizeof(T)> {
767 struct homogeneous_sizeof_one<T, typename std::enable_if<std::is_class<T>::value>::type>
768 : decltype(homogeneous_sizeof_helper<T>(
769 make_index_sequence<determine_tuple_size_<T>::value>())) {
772 template <
class T0>
struct homogeneous_sizeof<T0> : homogeneous_sizeof_one<T0> {
775 template <
class T0,
class... Ts>
776 struct homogeneous_sizeof<T0, Ts...>
777 : std::integral_constant<size_t, homogeneous_sizeof<T0>::value ==
778 homogeneous_sizeof<Ts...>::value
779 ? homogeneous_sizeof<T0>::value
784 template <
typename Scalar,
typename Base,
size_t N>
class Adapter :
public Base
788 template <std::size_t... Indexes,
int X>
789 Adapter(Vc::index_sequence<Indexes...>,
const Scalar,
790 std::integral_constant<int, X>)
793 X < 3,
"Failed to construct an object of type Base. Neither via " 794 "parenthesis-init, brace-init, nor double-brace init appear to work.");
798 template <std::size_t... Indexes>
799 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_,
800 std::integral_constant<int, 2>)
801 : Base{{get_dispatcher<Indexes>(x_)...}}
806 template <std::size_t... Indexes>
807 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_,
808 std::integral_constant<int, 1>)
809 : Base{get_dispatcher<Indexes>(x_)...}
814 template <std::size_t... Indexes>
815 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_,
816 std::integral_constant<int, 0>)
817 : Base(get_dispatcher<Indexes>(x_)...)
821 template <std::size_t... Indexes>
822 Adapter(Vc::index_sequence<Indexes...> seq_,
const Scalar &x_)
824 preferred_construction<Base, decltype(get_dispatcher<Indexes>(
825 std::declval<const Scalar &>()))...>())
831 static constexpr
size_t size() {
return N; }
832 static constexpr
size_t Size = N;
835 using base_type = Base;
838 using scalar_type = Scalar;
845 #if defined Vc_CLANG && Vc_CLANG < 0x30700 846 Vc_INTRINSIC Adapter(
const Adapter &x) : Base(x) {}
848 Adapter(
const Adapter &) =
default;
850 Adapter(Adapter &&) =
default;
853 Adapter &operator=(
const Adapter &) =
default;
855 Adapter &operator=(Adapter &&) =
default;
858 template <typename U, size_t TupleSize = determine_tuple_size_<Scalar>::value,
859 typename Seq = Vc::make_index_sequence<TupleSize>,
860 typename = enable_if<std::is_convertible<U, Scalar>::value>>
862 : Adapter(Seq(), static_cast<const Scalar &>(x_))
868 class = decltype(static_cast<Scalar>(std::declval<F>()(
872 for (
size_t i = 0; i < N; ++i) {
879 template <
typename A0,
typename... Args,
880 typename =
typename std::enable_if<
881 !Traits::is_index_sequence<A0>::value &&
882 (
sizeof...(Args) > 0 || !std::is_convertible<A0, Scalar>::value)>::type>
883 Adapter(A0 &&arg0_, Args &&... arguments_)
884 : Base(std::forward<A0>(arg0_), std::forward<Args>(arguments_)...)
889 template <
typename T,
890 typename = decltype(Base(std::declval<
const std::initializer_list<T> &>()))>
891 Adapter(
const std::initializer_list<T> &l_)
898 void *
operator new(
size_t size)
900 return Vc::Common::aligned_malloc<alignof(Adapter)>(size);
902 void *
operator new(size_t,
void *p_) {
return p_; }
903 void *
operator new[](
size_t size)
905 return Vc::Common::aligned_malloc<alignof(Adapter)>(size);
907 void *
operator new[](size_t ,
void *p_) {
return p_; }
909 void operator delete(
void *,
void *) {}
911 void operator delete[](
void *,
void *) {}
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;
934 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
935 inline void operator<(
936 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
937 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
938 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
939 inline void operator>(
940 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
941 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
952 template <
typename Scalar,
typename Base,
size_t N>
953 class tuple_size<
Vc::SimdizeDetail::Adapter<Scalar, Base, N>> :
public tuple_size<Base>
959 template <
size_t I,
typename Scalar,
typename Base,
size_t N>
960 class tuple_element<I, Vc::SimdizeDetail::Adapter<Scalar, Base, N>>
961 :
public tuple_element<I, Base>
971 template <
typename S,
typename T,
size_t N>
972 class allocator<Vc::SimdizeDetail::Adapter<S, T, N>>
976 template <
typename U>
struct rebind
978 typedef std::allocator<U> other;
983 namespace Vc_VERSIONED_NAMESPACE
985 namespace SimdizeDetail
995 template <
typename T>
static inline T decay_workaround(
const T &x) {
return x; }
1001 template <
typename S,
typename T,
size_t N,
size_t... Indexes>
1002 inline void assign_impl(Adapter<S, T, N> &a,
size_t i,
const S &x,
1003 Vc::index_sequence<Indexes...>)
1005 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(x)))...> tmp(
1006 decay_workaround(get_dispatcher<Indexes>(x))...);
1007 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(tmp), 0)...};
1008 if (&unused == &unused) {}
1011 template <
class S,
class... Args>
1012 S construct(std::integral_constant<int, 0>, Args &&... args)
1014 return S(std::forward<Args>(args)...);
1016 template <
class S,
class... Args>
1017 S construct(std::integral_constant<int, 1>, Args &&... args)
1019 return S{std::forward<Args>(args)...};
1021 template <
class S,
class... Args>
1022 S construct(std::integral_constant<int, 2>, Args &&... args)
1024 return S{{std::forward<Args>(args)...}};
1031 template <
typename S,
typename T,
size_t N,
size_t... Indexes>
1032 inline S extract_impl(
const Adapter<S, T, N> &a,
size_t i, Vc::index_sequence<Indexes...>)
1034 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a)[i]))...> tmp(
1035 decay_workaround(get_dispatcher<Indexes>(a)[i])...);
1036 return construct<S>(
1037 preferred_construction<S, decltype(decay_workaround(
1038 get_dispatcher<Indexes>(a)[i]))...>(),
1039 decay_workaround(get_dispatcher<Indexes>(a)[i])...);
1044 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1045 inline Adapter<S, T, N> shifted_impl(
const Adapter<S, T, N> &a,
int shift,
1046 Vc::index_sequence<Indexes...>)
1049 auto &&unused = {(get_dispatcher<Indexes>(r) = get_dispatcher<Indexes>(a).shifted(shift), 0)...};
1050 if (&unused == &unused) {}
1063 template <
typename S,
typename T,
size_t N>
1064 inline Adapter<S, T, N>
shifted(
const Adapter<S, T, N> &a,
int shift)
1066 return shifted_impl(a, shift, Vc::make_index_sequence<determine_tuple_size<T>()>());
1073 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1074 inline void swap_impl(Adapter<S, T, N> &a, std::size_t i, S &x,
1075 Vc::index_sequence<Indexes...>)
1077 const auto &a_const = a;
1078 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a_const)[0]))...>
1079 tmp{decay_workaround(get_dispatcher<Indexes>(a_const)[i])...};
1080 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(x), 0)...};
1081 auto &&unused2 = {(get_dispatcher<Indexes>(x) = get_dispatcher<Indexes>(tmp), 0)...};
1082 if (&unused == &unused2) {}
1084 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1085 inline void swap_impl(Adapter<S, T, N> &a, std::size_t i, Adapter<S, T, N> &b,
1086 std::size_t j, Vc::index_sequence<Indexes...>)
1088 const auto &a_const = a;
1089 const auto &b_const = b;
1090 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a_const)[0]))...>
1091 tmp{decay_workaround(get_dispatcher<Indexes>(a_const)[i])...};
1092 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(b_const)[j], 0)...};
1093 auto &&unused2 = {(get_dispatcher<Indexes>(b)[j] = get_dispatcher<Indexes>(tmp), 0)...};
1094 if (&unused == &unused2) {}
1102 template <
typename S,
typename T, std::
size_t N>
1103 inline void swap(Adapter<S, T, N> &a, std::size_t i, S &x)
1105 swap_impl(a, i, x, Vc::make_index_sequence<determine_tuple_size<T>()>());
1107 template <
typename S,
typename T, std::
size_t N>
1108 inline void swap(Adapter<S, T, N> &a, std::size_t i, Adapter<S, T, N> &b, std::size_t j)
1110 swap_impl(a, i, b, j, Vc::make_index_sequence<determine_tuple_size<T>()>());
1113 template <
typename A>
class Scalar
1115 using reference =
typename std::add_lvalue_reference<A>::type;
1116 using S =
typename A::scalar_type;
1117 using IndexSeq = Vc::make_index_sequence<determine_tuple_size<S>()>;
1120 Scalar(reference aa,
size_t ii) : a(aa), i(ii) {}
1123 Scalar(
const Scalar &) =
delete;
1124 Scalar(Scalar &&) =
delete;
1125 Scalar &operator=(
const Scalar &) =
delete;
1126 Scalar &operator=(Scalar &&) =
delete;
1128 void operator=(
const S &x) { assign_impl(a, i, x, IndexSeq()); }
1129 operator S()
const {
return extract_impl(a, i, IndexSeq()); }
1131 template <
typename AA>
1132 friend inline void swap(Scalar<AA> &&a,
typename AA::scalar_type &b);
1133 template <
typename AA>
1134 friend inline void swap(
typename AA::scalar_type &b, Scalar<AA> &&a);
1135 template <
typename AA>
friend inline void swap(Scalar<AA> &&a, Scalar<AA> &&b);
1144 template <
typename A>
inline void swap(Scalar<A> &&a,
typename A::scalar_type &b)
1146 swap_impl(a.a, a.i, b,
typename Scalar<A>::IndexSeq());
1150 template <
typename A>
inline void swap(
typename A::scalar_type &b, Scalar<A> &&a)
1152 swap_impl(a.a, a.i, b,
typename Scalar<A>::IndexSeq());
1155 template <
typename A>
inline void swap(Scalar<A> &&a, Scalar<A> &&b)
1157 swap_impl(a.a, a.i, b.a, b.i,
typename Scalar<A>::IndexSeq());
1161 template <
class S,
class T,
size_t N,
size_t... I>
1162 inline void load_interleaved_impl(Vc::index_sequence<I...>, Adapter<S, T, N> &a,
1165 const InterleavedMemoryWrapper<S, decltype(decay_workaround(get_dispatcher<0>(a)))>
1166 wrapper(const_cast<S *>(mem));
1167 Vc::tie(get_dispatcher<I>(a)...) = wrapper[0];
1171 template <
class S,
class T,
size_t N,
size_t... I>
1172 inline void store_interleaved_impl(Vc::index_sequence<I...>,
const Adapter<S, T, N> &a,
1175 InterleavedMemoryWrapper<S, decltype(decay_workaround(get_dispatcher<0>(a)))> wrapper(
1177 wrapper[0] = Vc::tie(get_dispatcher<I>(a)...);
1180 template <
typename A>
class Interface
1182 using reference =
typename std::add_lvalue_reference<A>::type;
1184 Vc::make_index_sequence<determine_tuple_size<typename A::scalar_type>()>;
1187 Interface(reference aa) : a(aa) {}
1189 Scalar<A> operator[](
size_t i)
1193 typename A::scalar_type operator[](
size_t i)
const 1195 return extract_impl(a, i, IndexSeq());
1200 return shifted_impl(a, amount, IndexSeq());
1203 void load(
const typename A::scalar_type *mem) { load_interleaved(*
this, mem); }
1204 void store(
typename A::scalar_type *mem) { store_interleaved(*
this, mem); }
1215 template <
typename S,
typename T,
size_t N>
1216 inline void assign(SimdizeDetail::Adapter<S, T, N> &a,
size_t i,
const S &x)
1218 SimdizeDetail::assign_impl(
1219 a, i, x, Vc::make_index_sequence<SimdizeDetail::determine_tuple_size<T>()>());
1224 template <typename V, typename = enable_if<Traits::is_simd_vector<V>::value>>
1225 Vc_INTRINSIC
void assign(V &v,
size_t i,
typename V::EntryType x)
1235 template <
typename S,
typename T,
size_t N>
1236 inline S
extract(
const SimdizeDetail::Adapter<S, T, N> &a,
size_t i)
1238 return SimdizeDetail::extract_impl(
1239 a, i, Vc::make_index_sequence<SimdizeDetail::determine_tuple_size<S>()>());
1244 template <typename V, typename = enable_if<Traits::is_simd_vector<V>::value>>
1245 Vc_INTRINSIC
typename V::EntryType
extract(
const V &v,
size_t i)
1251 template <
class S,
class T,
size_t N>
1252 inline void load_interleaved(SimdizeDetail::Adapter<S, T, N> &a,
const S *mem)
1254 if (SimdizeDetail::homogeneous_sizeof<S>::value == 0) {
1255 Common::unrolled_loop<std::size_t, 0, N>(
1256 [&](std::size_t i) {
assign(a, i, mem[i]); });
1258 constexpr
size_t TupleSize = SimdizeDetail::determine_tuple_size_<S>::value;
1259 SimdizeDetail::load_interleaved_impl(Vc::make_index_sequence<TupleSize>(), a,
1265 class = enable_if<Traits::is_simd_vector<V>::value && std::is_arithmetic<T>::value>>
1266 Vc_INTRINSIC
void load_interleaved(V &a,
const T *mem)
1272 template <
class S,
class T,
size_t N>
1273 inline void store_interleaved(
const SimdizeDetail::Adapter<S, T, N> &a, S *mem)
1275 if (SimdizeDetail::homogeneous_sizeof<S>::value == 0) {
1276 Common::unrolled_loop<std::size_t, 0, N>(
1277 [&](std::size_t i) { mem[i] =
extract(a, i); });
1279 constexpr
size_t TupleSize = SimdizeDetail::determine_tuple_size_<S>::value;
1280 SimdizeDetail::store_interleaved_impl(Vc::make_index_sequence<TupleSize>(), a,
1286 class = enable_if<Traits::is_simd_vector<V>::value && std::is_arithmetic<T>::value>>
1287 Vc_INTRINSIC
void store_interleaved(
const V &a, T *mem)
1293 template <
typename S,
typename T,
size_t N>
1294 SimdizeDetail::Interface<SimdizeDetail::Adapter<S, T, N>> decorate(
1295 SimdizeDetail::Adapter<S, T, N> &a)
1299 template <
typename S,
typename T,
size_t N>
1300 const SimdizeDetail::Interface<const SimdizeDetail::Adapter<S, T, N>> decorate(
1301 const SimdizeDetail::Adapter<S, T, N> &a)
1305 template <
class V,
class =
typename std::enable_if<
1309 return std::forward<V>(v);
1312 namespace SimdizeDetail
1314 namespace IteratorDetails
1316 enum class Mutable { Yes, No };
1318 template <
typename It,
typename V,
size_t I,
size_t End>
1319 Vc_INTRINSIC V fromIteratorImpl(enable_if<(I == End), It>)
1323 template <
typename It,
typename V,
size_t I,
size_t End>
1324 Vc_INTRINSIC V fromIteratorImpl(enable_if<(I < End), It> it)
1326 V r = fromIteratorImpl<It, V, I + 1, End>(it);
1327 Traits::decay<decltype(get_dispatcher<I>(r))> tmp;
1328 for (
size_t j = 0; j < V::size(); ++j, ++it) {
1329 tmp[j] = get_dispatcher<I>(*it);
1331 get_dispatcher<I>(r) = tmp;
1334 template <
typename It,
typename V>
1337 return fromIteratorImpl<It, V, 0, determine_tuple_size<V>()>(it);
1339 template <
typename It,
typename V>
1343 for (
size_t j = 0; j < V::size(); ++j, ++it) {
1352 template <
typename T,
typename value_vector, Mutable>
class Pointer;
1362 template <
typename T,
typename value_vector>
class Pointer<T, value_vector, Mutable::Yes>
1364 static constexpr
auto Size = value_vector::size();
1368 value_vector *operator->() {
return &data; }
1375 Pointer(
const Pointer &) =
delete;
1376 Pointer &operator=(
const Pointer &) =
delete;
1377 Pointer &operator=(Pointer &&) =
delete;
1380 Pointer(Pointer &&) =
default;
1390 for (
size_t i = 0; i < Size; ++i, ++begin_iterator) {
1391 *begin_iterator =
extract(data, i);
1396 Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)), begin_iterator(it) {}
1409 template <
typename T,
typename value_vector>
class Pointer<T, value_vector, Mutable::No>
1411 static constexpr
auto Size = value_vector::size();
1414 const value_vector *operator->()
const {
return &data; }
1417 Pointer(
const Pointer &) =
delete;
1418 Pointer &operator=(
const Pointer &) =
delete;
1419 Pointer &operator=(Pointer &&) =
delete;
1421 Pointer(Pointer &&) =
default;
1423 Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)) {}
1441 template <
typename T,
typename value_vector, Mutable M>
class Reference;
1444 template <
typename T,
typename value_vector>
1445 class Reference<T, value_vector, Mutable::Yes> :
public value_vector
1447 static constexpr
auto Size = value_vector::size();
1449 using reference =
typename std::add_lvalue_reference<T>::type;
1450 reference scalar_it;
1455 Reference(reference first_it)
1456 : value_vector(fromIterator<T, value_vector>(first_it)), scalar_it(first_it)
1461 Reference(
const Reference &) =
delete;
1462 Reference(Reference &&) =
default;
1463 Reference &operator=(
const Reference &) =
delete;
1464 Reference &operator=(Reference &&) =
delete;
1471 void operator=(
const value_vector &x)
1473 static_cast<value_vector &
>(*this) = x;
1474 auto it = scalar_it;
1475 for (
size_t i = 0; i < Size; ++i, ++it) {
1480 #define Vc_OP(op_) \ 1481 template <typename T0, typename V0, typename T1, typename V1> \ 1482 decltype(std::declval<const V0 &>() op_ std::declval<const V1 &>()) operator op_( \ 1483 const Reference<T0, V0, Mutable::Yes> &x, \ 1484 const Reference<T1, V1, Mutable::Yes> &y) \ 1486 return static_cast<const V0 &>(x) op_ static_cast<const V1 &>(y); \ 1488 Vc_ALL_COMPARES(Vc_OP);
1489 Vc_ALL_ARITHMETICS(Vc_OP);
1490 Vc_ALL_BINARY(Vc_OP);
1491 Vc_ALL_LOGICAL(Vc_OP);
1492 Vc_ALL_SHIFTS(Vc_OP);
1496 template <
typename T,
typename value_vector>
1497 class Reference<T, value_vector, Mutable::No> :
public value_vector
1499 static constexpr
auto Size = value_vector::size();
1502 Reference(
const T &it) : value_vector(fromIterator<T, value_vector>(it)) {}
1504 Reference(
const Reference &) =
delete;
1505 Reference(Reference &&) =
default;
1506 Reference &operator=(
const Reference &) =
delete;
1507 Reference &operator=(Reference &&) =
delete;
1510 void operator=(
const value_vector &x) =
delete;
1513 template <
typename T,
size_t N,
1514 IteratorDetails::Mutable M =
1515 (Traits::is_output_iterator<T>::value ? Mutable::Yes : Mutable::No),
1516 typename V = simdize<
typename std::iterator_traits<T>::value_type, N>,
1517 size_t Size = V::Size,
1518 typename =
typename std::iterator_traits<T>::iterator_category>
1521 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size_>
1522 class Iterator<T, N, M, V, Size_, std::forward_iterator_tag>
1523 :
public std::iterator<typename std::iterator_traits<T>::iterator_category, V,
1524 typename std::iterator_traits<T>::difference_type,
1525 IteratorDetails::Pointer<T, V, M>,
1526 IteratorDetails::Reference<T, V, M>>
1529 using pointer = IteratorDetails::Pointer<T, V, M>;
1530 using reference = IteratorDetails::Reference<T, V, M>;
1531 using const_pointer = IteratorDetails::Pointer<T, V, IteratorDetails::Mutable::No>;
1532 using const_reference =
1533 IteratorDetails::Reference<T, V, IteratorDetails::Mutable::No>;
1536 static constexpr std::size_t size() {
return Size_; }
1537 static constexpr std::size_t Size = Size_;
1539 Iterator() =
default;
1547 Iterator(
const T &x) : scalar_it(x) {}
1551 Iterator(T &&x) : scalar_it(std::move(x)) {}
1555 Iterator &operator=(
const T &x)
1563 Iterator &operator=(T &&x)
1565 scalar_it = std::move(x);
1570 Iterator(
const Iterator &) =
default;
1572 Iterator(Iterator &&) =
default;
1574 Iterator &operator=(
const Iterator &) =
default;
1576 Iterator &operator=(Iterator &&) =
default;
1579 Iterator &operator++()
1581 std::advance(scalar_it, Size);
1585 Iterator operator++(
int)
1587 Iterator copy(*
this);
1600 bool operator==(
const Iterator &rhs)
const 1603 if (scalar_it == rhs.scalar_it) {
1607 for (
size_t i = 1; i < Size; ++i) {
1608 Vc_ASSERT((++it != rhs.scalar_it));
1613 return scalar_it == rhs.scalar_it;
1624 bool operator!=(
const Iterator &rhs)
const 1626 return !operator==(rhs);
1629 pointer operator->() {
return scalar_it; }
1637 reference
operator*() {
return scalar_it; }
1639 const_pointer operator->()
const {
return scalar_it; }
1648 const_reference
operator*()
const {
return scalar_it; }
1663 operator const T &()
const {
return scalar_it; }
1673 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1674 class Iterator<T, N, M, V, Size, std::bidirectional_iterator_tag>
1675 :
public Iterator<T, N, M, V, Size, std::forward_iterator_tag>
1677 using Base = Iterator<T, N, M, V, Size, std::forward_iterator_tag>;
1680 using Base::scalar_it;
1683 using pointer =
typename Base::pointer;
1684 using reference =
typename Base::reference;
1685 using const_pointer =
typename Base::const_pointer;
1686 using const_reference =
typename Base::const_reference;
1688 using Iterator<T, N, M, V, Size,
1689 std::forward_iterator_tag>::Iterator;
1695 std::advance(scalar_it, -Size);
1701 Iterator copy(*
this);
1711 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1712 class Iterator<T, N, M, V, Size, std::random_access_iterator_tag>
1713 :
public Iterator<T, N, M, V, Size, std::bidirectional_iterator_tag>
1718 using Base::scalar_it;
1721 using pointer =
typename Base::pointer;
1722 using reference =
typename Base::reference;
1723 using const_pointer =
typename Base::const_pointer;
1724 using const_reference =
typename Base::const_reference;
1725 using difference_type =
typename std::iterator_traits<T>::difference_type;
1730 Iterator &operator+=(difference_type n)
1732 scalar_it += n * difference_type(Size);
1735 Iterator
operator+(difference_type n)
const {
return Iterator(*
this) += n; }
1737 Iterator &operator-=(difference_type n)
1739 scalar_it -= n * difference_type(Size);
1742 Iterator
operator-(difference_type n)
const {
return Iterator(*
this) -= n; }
1744 difference_type
operator-(
const Iterator &rhs)
const 1746 constexpr difference_type n = Size;
1747 Vc_ASSERT((scalar_it - rhs.scalar_it) % n ==
1753 return (scalar_it - rhs.scalar_it) / n;
1762 return rhs.scalar_it - scalar_it >= difference_type(Size);
1765 bool operator>(
const Iterator &rhs)
const 1767 return scalar_it - rhs.scalar_it >= difference_type(Size);
1770 bool operator<=(
const Iterator &rhs)
const 1772 return rhs.scalar_it - scalar_it >= difference_type(Size) - 1;
1775 bool operator>=(
const Iterator &rhs)
const 1777 return scalar_it - rhs.scalar_it >= difference_type(Size) - 1;
1780 reference operator[](difference_type i) {
return *(*
this + i); }
1781 const_reference operator[](difference_type i)
const {
return *(*
this + i); }
1784 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1786 typename Iterator<T, N, M, V, Size, std::random_access_iterator_tag>::difference_type
1803 template <
typename T,
size_t N,
typename MT>
1804 struct ReplaceTypes<T, N, MT, Category::ForwardIterator>
1806 using type = IteratorDetails::Iterator<T, N>;
1808 template <
typename T,
size_t N,
typename MT>
1809 struct ReplaceTypes<T, N, MT, Category::BidirectionalIterator>
1811 using type = IteratorDetails::Iterator<T, N>;
1813 template <
typename T,
size_t N,
typename MT>
1814 struct ReplaceTypes<T, N, MT, Category::RandomAccessIterator>
1816 using type = IteratorDetails::Iterator<T, N>;
1822 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
typename U,
1824 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N),
void>
1825 conditional_assign(Adapter<S, T, N> &,
const M &,
const U &)
1828 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
typename U,
1829 std::size_t Offset = 0>
1830 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N),
void>
1831 conditional_assign(Adapter<S, T, N> &lhs,
const M &mask,
const U &rhs)
1833 using V =
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
1834 using M2 =
typename V::mask_type;
1835 conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask), get_dispatcher<Offset>(rhs));
1836 conditional_assign<Op, S, T, N, M, U, Offset + 1>(lhs, mask, rhs);
1838 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
1840 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N),
void>
1841 conditional_assign(Adapter<S, T, N> &,
const M &)
1844 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
1845 std::size_t Offset = 0>
1846 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N),
void>
1847 conditional_assign(Adapter<S, T, N> &lhs,
const M &mask)
1849 using V =
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
1850 using M2 =
typename V::mask_type;
1851 conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask));
1852 conditional_assign<Op, S, T, N, M, Offset + 1>(lhs, mask);
1877 template <
typename T,
size_t N = 0,
typename MT =
void>
1878 using simdize = SimdizeDetail::simdize<T, N, MT>;
1899 #define Vc_SIMDIZE_INTERFACE(MEMBERS_) \ 1900 template <std::size_t N_> \ 1901 inline auto vc_get_()->decltype(std::get<N_>(std::tie MEMBERS_)) \ 1903 return std::get<N_>(std::tie MEMBERS_); \ 1905 template <std::size_t N_> \ 1906 inline auto vc_get_() const->decltype(std::get<N_>(std::tie MEMBERS_)) \ 1908 return std::get<N_>(std::tie MEMBERS_); \ 1910 enum : std::size_t { \ 1911 tuple_size = std::tuple_size<decltype(std::make_tuple MEMBERS_)>::value \ 1918 using Vc::SimdizeDetail::swap;
1921 #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.
void assign(SimdizeDetail::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.
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.
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...
S extract(const SimdizeDetail::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...
constexpr UnalignedTag Unaligned
Use this object for a flags parameter to request unaligned loads and stores.