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;
148 template <
typename... Ts>
struct Typelist;
153 enum class Category {
157 ArithmeticVectorizable,
165 BidirectionalIterator,
167 RandomAccessIterator,
176 template <
typename T,
typename ItCat =
typename T::iterator_category>
177 constexpr Category iteratorCategories(
int, ItCat * =
nullptr)
179 return is_base_of<std::random_access_iterator_tag, ItCat>::value
180 ? Category::RandomAccessIterator
181 : is_base_of<std::bidirectional_iterator_tag, ItCat>::value
182 ? Category::BidirectionalIterator
183 : is_base_of<std::forward_iterator_tag, ItCat>::value
184 ? Category::ForwardIterator
185 : is_base_of<std::output_iterator_tag, ItCat>::value
186 ? Category::OutputIterator
187 : is_base_of<std::input_iterator_tag, ItCat>::value
188 ? Category::InputIterator
194 template <
typename T>
195 constexpr enable_if<std::is_pointer<T>::value, Category> iteratorCategories(
float)
197 return Category::RandomAccessIterator;
202 template <
typename T> constexpr Category iteratorCategories(...)
204 return Category::None;
210 template <
typename T>
struct is_class_template :
public false_type
213 template <
template <
typename...>
class C,
typename... Ts>
214 struct is_class_template<C<Ts...>> :
public true_type
221 template <
typename T> constexpr Category typeCategory()
223 return (is_same<T, bool>::value || is_same<T, short>::value ||
224 is_same<T, unsigned short>::value || is_same<T, int>::value ||
225 is_same<T, unsigned int>::value || is_same<T, float>::value ||
226 is_same<T, double>::value)
227 ? Category::ArithmeticVectorizable
228 : iteratorCategories<T>(
int()) != Category::None
229 ? iteratorCategories<T>(
int())
230 : is_class_template<T>::value ? Category::ClassTemplate
239 template <typename T, size_t TupleSize = std::tuple_size<T>::value>
240 constexpr
size_t determine_tuple_size()
244 template <
typename T,
size_t TupleSize = T::tuple_size>
245 constexpr
size_t determine_tuple_size(
size_t = T::tuple_size)
252 template <
typename T>
struct determine_tuple_size_
253 :
public std::integral_constant<size_t, determine_tuple_size<T>()>
258 template <
typename T>
struct The_simdization_for_the_requested_type_is_not_implemented;
273 template <typename T, size_t N, typename MT, Category = typeCategory<T>()>
274 struct ReplaceTypes :
public The_simdization_for_the_requested_type_is_not_implemented<T>
282 template <
typename T,
size_t N,
typename MT>
struct ReplaceTypes<T, N, MT, Category::None>
291 template <
typename T,
size_t N = 0,
typename MT =
void>
292 using simdize =
typename SimdizeDetail::ReplaceTypes<T, N, MT>::type;
295 template <
class T,
size_t N,
296 class Best =
typename Common::select_best_vector_type<T, N>::type>
297 using deduce_vector_t =
298 typename std::conditional<Best::size() == N, Best, SimdArray<T, N>>::type;
304 template <
typename T,
size_t N,
typename MT>
305 struct ReplaceTypes<T, N, MT, Category::ArithmeticVectorizable>
306 :
public conditional<N == 0, Vector<T>, deduce_vector_t<T, N>> {
313 template <
size_t N,
typename MT>
314 struct ReplaceTypes<bool, N, MT, Category::ArithmeticVectorizable>
315 :
public std::enable_if<true, typename ReplaceTypes<MT, N, MT>::type::mask_type> {
321 struct ReplaceTypes<bool, N, void, Category::ArithmeticVectorizable>
322 :
public ReplaceTypes<bool, N, float, Category::ArithmeticVectorizable>
332 template <
size_t N,
typename MT,
typename Replaced,
typename... Remaining>
333 struct SubstituteOneByOne;
339 template <
size_t N,
typename MT,
typename... Replaced,
typename T,
340 typename... Remaining>
341 struct SubstituteOneByOne<N, MT, Typelist<Replaced...>, T, Remaining...>
348 template <
typename U,
size_t M = U::Size>
349 static std::integral_constant<size_t, M> size_or_0(
int);
350 template <
typename U>
static std::integral_constant<size_t, 0> size_or_0(...);
353 using V = simdize<T, N, MT>;
359 static constexpr
auto NewN = N != 0 ? N : decltype(size_or_0<V>(
int()))::value;
366 typedef conditional_t<(N != NewN && is_same<MT, void>::value),
367 conditional_t<is_same<T, bool>::value,
float, T>, MT> NewMT;
373 using type =
typename SubstituteOneByOne<NewN, NewMT, Typelist<Replaced..., V>,
379 template <
size_t Size,
typename... Replaced>
struct SubstitutedBase;
381 template <
typename Replaced>
struct SubstitutedBase<1, Replaced> {
382 template <
typename ValueT,
template <
typename, ValueT...>
class C, ValueT... Values>
383 using SubstitutedWithValues = C<Replaced, Values...>;
386 template <
typename R0,
typename R1>
struct SubstitutedBase<2, R0, R1>
388 template <
typename ValueT,
template <
typename,
typename, ValueT...>
class C,
390 using SubstitutedWithValues = C<R0, R1, Values...>;
393 template <
typename R0,
typename R1,
typename R2>
struct SubstitutedBase<3, R0, R1, R2>
395 template <
typename ValueT,
template <
typename,
typename,
typename, ValueT...>
class C,
397 using SubstitutedWithValues = C<R0, R1, R2, Values...>;
399 #if defined Vc_ICC || defined Vc_MSVC
400 #define Vc_VALUE_PACK_EXPANSION_IS_BROKEN 1
403 template <
typename... Replaced>
struct SubstitutedBase<4, Replaced...> {
404 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
405 template <
typename ValueT,
406 template <
typename,
typename,
typename,
typename, ValueT...>
class C,
408 using SubstitutedWithValues = C<Replaced..., Values...>;
412 template <
typename... Replaced>
struct SubstitutedBase<5, Replaced...> {
413 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
414 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
417 using SubstitutedWithValues = C<Replaced..., Values...>;
421 template <
typename... Replaced>
struct SubstitutedBase<6, Replaced...> {
422 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
423 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
424 typename, ValueT...>
class C,
426 using SubstitutedWithValues = C<Replaced..., Values...>;
430 template <
typename... Replaced>
struct SubstitutedBase<7, Replaced...> {
431 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
432 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
433 typename,
typename, ValueT...>
class C,
435 using SubstitutedWithValues = C<Replaced..., Values...>;
439 template <
typename... Replaced>
struct SubstitutedBase<8, Replaced...> {
440 #ifndef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
441 template <
typename ValueT,
template <
typename,
typename,
typename,
typename,
typename,
442 typename,
typename,
typename, ValueT...>
class C,
444 using SubstitutedWithValues = C<Replaced..., Values...>;
453 template <
size_t N_,
typename MT,
typename Replaced0,
typename... Replaced>
454 struct SubstituteOneByOne<N_, MT, Typelist<Replaced0, Replaced...>>
460 :
public SubstitutedBase<sizeof...(Replaced) + 1, Replaced0, Replaced...> {
461 static constexpr
auto N = N_;
466 template <
template <
typename...>
class C>
467 using Substituted = C<Replaced0, Replaced...>;
487 template <
typename Scalar,
typename Base,
size_t N>
class Adapter;
493 template <
template <
typename...>
class C,
typename... Ts,
size_t N,
typename MT>
494 struct ReplaceTypes<C<Ts...>, N, MT, Category::ClassTemplate>
497 using SubstitutionResult =
498 typename SubstituteOneByOne<N, MT, Typelist<>, Ts...>::type;
504 using Vectorized =
typename SubstitutionResult::template Substituted<C>;
510 using type = conditional_t<is_same<C<Ts...>, Vectorized>::value, C<Ts...>,
511 Adapter<C<Ts...>, Vectorized, SubstitutionResult::N>>;
519 #ifdef Vc_VALUE_PACK_EXPANSION_IS_BROKEN
521 #define Vc_DEFINE_NONTYPE_REPLACETYPES_(ValueType_) \
522 template <template <typename, ValueType_...> class C, typename T, ValueType_ Value0, \
523 ValueType_... Values> \
524 struct is_class_template<C<T, Value0, Values...>> : public true_type { \
526 template <template <typename, typename, ValueType_...> class C, typename T0, \
527 typename T1, ValueType_ Value0, ValueType_... Values> \
528 struct is_class_template<C<T0, T1, Value0, Values...>> : public true_type { \
530 template <template <typename, typename, typename, ValueType_...> class C, \
531 typename T0, typename T1, typename T2, ValueType_ Value0, \
532 ValueType_... Values> \
533 struct is_class_template<C<T0, T1, T2, Value0, Values...>> : public true_type { \
535 template <template <typename, typename, typename, typename, ValueType_...> class C, \
536 typename T0, typename T1, typename T2, typename T3, ValueType_ Value0, \
537 ValueType_... Values> \
538 struct is_class_template<C<T0, T1, T2, T3, Value0, Values...>> : public true_type { \
540 template <template <typename, typename, typename, typename, typename, ValueType_...> \
542 typename T0, typename T1, typename T2, typename T3, typename T4, \
543 ValueType_ Value0, ValueType_... Values> \
544 struct is_class_template<C<T0, T1, T2, T3, T4, Value0, Values...>> \
545 : public true_type { \
547 template <template <typename, typename, typename, typename, typename, typename, \
548 ValueType_...> class C, \
549 typename T0, typename T1, typename T2, typename T3, typename T4, \
550 typename T5, ValueType_ Value0, ValueType_... Values> \
551 struct is_class_template<C<T0, T1, T2, T3, T4, T5, Value0, Values...>> \
552 : public true_type { \
554 template <template <typename, typename, typename, typename, typename, typename, \
555 typename, ValueType_...> class C, \
556 typename T0, typename T1, typename T2, typename T3, typename T4, \
557 typename T5, typename T6, ValueType_ Value0, ValueType_... Values> \
558 struct is_class_template<C<T0, T1, T2, T3, T4, T5, T6, Value0, Values...>> \
559 : public true_type { \
561 template <template <typename, ValueType_> class C, typename T0, ValueType_ Value0, \
562 size_t N, typename MT> \
563 struct ReplaceTypes<C<T0, Value0>, N, MT, Category::ClassTemplate> { \
564 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0>::type tmp; \
565 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \
567 static constexpr auto NN = tmp::N; \
568 typedef conditional_t<is_same<C<T0, Value0>, Substituted>::value, C<T0, Value0>, \
569 Adapter<C<T0, Value0>, Substituted, NN>> type; \
571 template <template <typename, typename, ValueType_> class C, typename T0, \
572 typename T1, ValueType_ Value0, size_t N, typename MT> \
573 struct ReplaceTypes<C<T0, T1, Value0>, N, MT, Category::ClassTemplate> { \
574 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1>::type tmp; \
575 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \
577 static constexpr auto NN = tmp::N; \
578 typedef conditional_t<is_same<C<T0, T1, Value0>, Substituted>::value, \
580 Adapter<C<T0, T1, Value0>, Substituted, NN>> type; \
582 template <template <typename, typename, typename, ValueType_> class C, typename T0, \
583 typename T1, typename T2, ValueType_ Value0, size_t N, typename MT> \
584 struct ReplaceTypes<C<T0, T1, T2, Value0>, N, MT, Category::ClassTemplate> { \
585 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1, T2>::type tmp; \
586 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0> \
588 static constexpr auto NN = tmp::N; \
589 typedef conditional_t<is_same<C<T0, T1, T2, Value0>, Substituted>::value, \
590 C<T0, T1, T2, Value0>, \
591 Adapter<C<T0, T1, T2, Value0>, Substituted, NN>> type; \
594 #define Vc_DEFINE_NONTYPE_REPLACETYPES_(ValueType_) \
595 template <template <typename, ValueType_...> class C, typename T, ValueType_ Value0, \
596 ValueType_... Values> \
597 struct is_class_template<C<T, Value0, Values...>> : public true_type { \
599 template <template <typename, typename, ValueType_...> class C, typename T0, \
600 typename T1, ValueType_ Value0, ValueType_... Values> \
601 struct is_class_template<C<T0, T1, Value0, Values...>> : public true_type { \
603 template <template <typename, typename, typename, ValueType_...> class C, \
604 typename T0, typename T1, typename T2, ValueType_ Value0, \
605 ValueType_... Values> \
606 struct is_class_template<C<T0, T1, T2, Value0, Values...>> : public true_type { \
608 template <template <typename, typename, typename, typename, ValueType_...> class C, \
609 typename T0, typename T1, typename T2, typename T3, ValueType_ Value0, \
610 ValueType_... Values> \
611 struct is_class_template<C<T0, T1, T2, T3, Value0, Values...>> : public true_type { \
613 template <template <typename, typename, typename, typename, typename, ValueType_...> \
615 typename T0, typename T1, typename T2, typename T3, typename T4, \
616 ValueType_ Value0, ValueType_... Values> \
617 struct is_class_template<C<T0, T1, T2, T3, T4, Value0, Values...>> \
618 : public true_type { \
620 template <template <typename, typename, typename, typename, typename, typename, \
621 ValueType_...> class C, \
622 typename T0, typename T1, typename T2, typename T3, typename T4, \
623 typename T5, ValueType_ Value0, ValueType_... Values> \
624 struct is_class_template<C<T0, T1, T2, T3, T4, T5, Value0, Values...>> \
625 : public true_type { \
627 template <template <typename, typename, typename, typename, typename, typename, \
628 typename, ValueType_...> class C, \
629 typename T0, typename T1, typename T2, typename T3, typename T4, \
630 typename T5, typename T6, ValueType_ Value0, ValueType_... Values> \
631 struct is_class_template<C<T0, T1, T2, T3, T4, T5, T6, Value0, Values...>> \
632 : public true_type { \
634 template <template <typename, ValueType_...> class C, typename T0, \
635 ValueType_ Value0, ValueType_... Values, size_t N, typename MT> \
636 struct ReplaceTypes<C<T0, Value0, Values...>, N, MT, Category::ClassTemplate> { \
637 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0>::type tmp; \
638 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \
639 Values...> Substituted; \
640 static constexpr auto NN = tmp::N; \
641 typedef conditional_t<is_same<C<T0, Value0, Values...>, Substituted>::value, \
642 C<T0, Value0, Values...>, \
643 Adapter<C<T0, Value0, Values...>, Substituted, NN>> type; \
645 template <template <typename, typename, ValueType_...> class C, typename T0, \
646 typename T1, ValueType_ Value0, ValueType_... Values, size_t N, \
648 struct ReplaceTypes<C<T0, T1, Value0, Values...>, N, MT, Category::ClassTemplate> { \
649 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1>::type tmp; \
650 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \
651 Values...> Substituted; \
652 static constexpr auto NN = tmp::N; \
653 typedef conditional_t<is_same<C<T0, T1, Value0, Values...>, Substituted>::value, \
654 C<T0, T1, Value0, Values...>, \
655 Adapter<C<T0, T1, Value0, Values...>, Substituted, NN>> \
658 template <template <typename, typename, typename, ValueType_...> class C, \
659 typename T0, typename T1, typename T2, ValueType_ Value0, \
660 ValueType_... Values, size_t N, typename MT> \
661 struct ReplaceTypes<C<T0, T1, T2, Value0, Values...>, N, MT, \
662 Category::ClassTemplate> { \
663 typedef typename SubstituteOneByOne<N, MT, Typelist<>, T0, T1, T2>::type tmp; \
664 typedef typename tmp::template SubstitutedWithValues<ValueType_, C, Value0, \
665 Values...> Substituted; \
666 static constexpr auto NN = tmp::N; \
667 typedef conditional_t< \
668 is_same<C<T0, T1, T2, Value0, Values...>, Substituted>::value, \
669 C<T0, T1, T2, Value0, Values...>, \
670 Adapter<C<T0, T1, T2, Value0, Values...>, Substituted, NN>> type; \
673 Vc_DEFINE_NONTYPE_REPLACETYPES_(
bool);
674 Vc_DEFINE_NONTYPE_REPLACETYPES_(
wchar_t);
675 Vc_DEFINE_NONTYPE_REPLACETYPES_(
char);
676 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed char);
677 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned char);
678 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed short);
679 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned short);
680 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed int);
681 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned int);
682 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed long);
683 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned long);
684 Vc_DEFINE_NONTYPE_REPLACETYPES_(
signed long long);
685 Vc_DEFINE_NONTYPE_REPLACETYPES_(
unsigned long long);
686 #undef Vc_DEFINE_NONTYPE_REPLACETYPES_
689 namespace preferred_construction_impl
691 template <
typename T> T create();
693 template <
class Type,
class... Init,
class = decltype(Type(create<Init>()...))>
694 constexpr std::integral_constant<int, 0> test(
int);
696 template <
class Type,
class... Init,
class = decltype(Type{create<Init>()...})>
697 constexpr std::integral_constant<int, 1> test(
float);
699 template <
class Type,
class... Init,
class T,
class = decltype(Type{{create<Init>()...}})>
700 constexpr std::integral_constant<int, 2> test(T);
702 template <
class Type,
class... Init> constexpr std::integral_constant<int, 3> test(...);
705 template <
class Type,
class... Init>
706 constexpr
inline decltype(preferred_construction_impl::test<Type, Init...>(0))
707 preferred_construction()
718 template <
size_t I,
typename T,
719 typename R = decltype(std::declval<T &>().
template vc_get_<I>())>
720 R get_dispatcher(T &x,
void * =
nullptr)
722 return x.template vc_get_<I>();
724 template <
size_t I,
typename T,
725 typename R = decltype(std::declval<const T &>().
template vc_get_<I>())>
726 R get_dispatcher(
const T &x,
void * =
nullptr)
728 return x.template vc_get_<I>();
730 template <size_t I, typename T, typename R = decltype(std::get<I>(std::declval<T &>()))>
731 R get_dispatcher(T &x,
int = 0)
733 return std::get<I>(x);
735 template <
size_t I,
typename T,
736 typename R = decltype(std::get<I>(std::declval<const T &>()))>
737 R get_dispatcher(
const T &x,
int = 0)
739 return std::get<I>(x);
744 template <
size_t I,
class T,
class =
void>
745 struct my_tuple_element : std::tuple_element<I, T> {
748 template <
size_t I,
class T>
749 struct my_tuple_element<
750 I, T, typename std::conditional<
751 true, void, decltype(std::declval<T>().template vc_get_<I>())>::type> {
753 typename std::decay<decltype(std::declval<T>().template vc_get_<I>())>::type;
763 template <
class... Ts>
struct homogeneous_sizeof;
764 template <
class T,
class =
void>
struct homogeneous_sizeof_one;
766 struct homogeneous_sizeof_one<T,
767 typename std::enable_if<std::is_arithmetic<T>::value>::type>
768 : std::integral_constant<size_t, sizeof(T)> {
770 template <
class T0>
struct homogeneous_sizeof<T0> : homogeneous_sizeof_one<T0> {
773 template <
class T0,
class... Ts>
774 struct homogeneous_sizeof<T0, Ts...>
775 : std::integral_constant<size_t, homogeneous_sizeof<T0>::value ==
776 homogeneous_sizeof<Ts...>::value
777 ? homogeneous_sizeof<T0>::value
781 template <
class T,
size_t... Is>
782 std::integral_constant<
783 size_t, homogeneous_sizeof<typename my_tuple_element<Is, T>::type...>::value>
784 homogeneous_sizeof_helper(index_sequence<Is...>);
787 struct homogeneous_sizeof_one<T, typename std::enable_if<std::is_class<T>::value>::type>
788 : decltype(homogeneous_sizeof_helper<T>(
789 make_index_sequence<determine_tuple_size_<T>::value>())) {
794 template <
typename Scalar,
typename Base,
size_t N>
class Adapter :
public Base
798 template <std::size_t... Indexes,
int X>
799 Adapter(Vc::index_sequence<Indexes...>,
const Scalar,
800 std::integral_constant<int, X>)
803 X < 3,
"Failed to construct an object of type Base. Neither via "
804 "parenthesis-init, brace-init, nor double-brace init appear to work.");
808 template <std::size_t... Indexes>
809 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_,
810 std::integral_constant<int, 2>)
811 : Base{{get_dispatcher<Indexes>(x_)...}}
816 template <std::size_t... Indexes>
817 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_,
818 std::integral_constant<int, 1>)
819 : Base{get_dispatcher<Indexes>(x_)...}
824 template <std::size_t... Indexes>
825 Adapter(Vc::index_sequence<Indexes...>,
const Scalar &x_,
826 std::integral_constant<int, 0>)
827 : Base(get_dispatcher<Indexes>(x_)...)
831 template <std::size_t... Indexes>
832 Adapter(Vc::index_sequence<Indexes...> seq_,
const Scalar &x_)
834 preferred_construction<Base, decltype(get_dispatcher<Indexes>(
835 std::declval<const Scalar &>()))...>())
841 static constexpr
size_t size() {
return N; }
842 static constexpr
size_t Size = N;
845 using base_type = Base;
848 using scalar_type = Scalar;
855 #if defined Vc_CLANG && Vc_CLANG < 0x30700
856 Vc_INTRINSIC Adapter(
const Adapter &x) : Base(x) {}
858 Adapter(
const Adapter &) =
default;
861 Adapter(Adapter &&) =
default;
863 Adapter &operator=(
const Adapter &) =
default;
865 Adapter &operator=(Adapter &&) =
default;
868 template <typename U, size_t TupleSize = determine_tuple_size_<Scalar>::value,
869 typename Seq = Vc::make_index_sequence<TupleSize>,
870 typename = enable_if<std::is_convertible<U, Scalar>::value>>
872 : Adapter(Seq(), static_cast<const Scalar &>(x_))
878 class = decltype(
static_cast<Scalar
>(std::declval<F>()(
884 template <
typename A0,
typename... Args,
885 typename =
typename std::enable_if<
886 !Traits::is_index_sequence<A0>::value &&
887 (
sizeof...(Args) > 0 || !std::is_convertible<A0, Scalar>::value)>::type>
888 Adapter(A0 &&arg0_, Args &&... arguments_)
889 : Base(std::forward<A0>(arg0_), std::forward<Args>(arguments_)...)
894 template <
typename T,
895 typename = decltype(Base(std::declval<
const std::initializer_list<T> &>()))>
896 Adapter(
const std::initializer_list<T> &l_)
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_; }
908 void *
operator new[](
size_t size)
910 return Vc::Common::aligned_malloc<alignof(Adapter)>(size);
912 void *
operator new[](size_t ,
void *p_) {
return p_; }
914 void operator delete(
void *,
void *) {}
916 void operator delete[](
void *,
void *) {}
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;
935 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
936 inline void operator>=(
937 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
938 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
939 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
940 inline void operator<(
941 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
942 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
943 template <
class... TTypes,
class... TTypesV,
class... UTypes,
class... UTypesV,
size_t N>
944 inline void operator>(
945 const Adapter<std::tuple<TTypes...>, std::tuple<TTypesV...>, N> &t,
946 const Adapter<std::tuple<UTypes...>, std::tuple<UTypesV...>, N> &u) =
delete;
957 template <
typename Scalar,
typename Base,
size_t N>
958 class tuple_size<
Vc::SimdizeDetail::Adapter<Scalar, Base, N>> :
public tuple_size<Base>
964 template <
size_t I,
typename Scalar,
typename Base,
size_t N>
965 class tuple_element<I,
Vc::SimdizeDetail::Adapter<Scalar, Base, N>>
966 :
public tuple_element<I, Base>
976 template <
typename S,
typename T,
size_t N>
977 class allocator<
Vc::SimdizeDetail::Adapter<S, T, N>>
981 template <
typename U>
struct rebind
983 typedef std::allocator<U> other;
988 namespace Vc_VERSIONED_NAMESPACE
990 namespace SimdizeDetail
1000 template <
typename T>
static inline T decay_workaround(
const T &x) {
return x; }
1006 template <
typename S,
typename T,
size_t N,
size_t... Indexes>
1007 inline void assign_impl(Adapter<S, T, N> &a,
size_t i,
const S &x,
1008 Vc::index_sequence<Indexes...>)
1010 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(x)))...> tmp(
1011 decay_workaround(get_dispatcher<Indexes>(x))...);
1012 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(tmp), 0)...};
1013 if (&unused == &unused) {}
1016 template <
class S,
class... Args>
1017 S construct(std::integral_constant<int, 0>, Args &&... args)
1019 return S(std::forward<Args>(args)...);
1021 template <
class S,
class... Args>
1022 S construct(std::integral_constant<int, 1>, Args &&... args)
1024 return S{std::forward<Args>(args)...};
1026 template <
class S,
class... Args>
1027 S construct(std::integral_constant<int, 2>, Args &&... args)
1029 return S{{std::forward<Args>(args)...}};
1036 template <
typename S,
typename T,
size_t N,
size_t... Indexes>
1037 inline S extract_impl(
const Adapter<S, T, N> &a,
size_t i, Vc::index_sequence<Indexes...>)
1039 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a)[i]))...> tmp(
1040 decay_workaround(get_dispatcher<Indexes>(a)[i])...);
1041 return construct<S>(
1042 preferred_construction<S, decltype(decay_workaround(
1043 get_dispatcher<Indexes>(a)[i]))...>(),
1044 decay_workaround(get_dispatcher<Indexes>(a)[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) {}
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>()>());
1078 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1079 inline void swap_impl(Adapter<S, T, N> &a, std::size_t i, S &x,
1080 Vc::index_sequence<Indexes...>)
1082 const auto &a_const = a;
1083 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a_const)[0]))...>
1084 tmp{decay_workaround(get_dispatcher<Indexes>(a_const)[i])...};
1085 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(x), 0)...};
1086 auto &&unused2 = {(get_dispatcher<Indexes>(x) = get_dispatcher<Indexes>(tmp), 0)...};
1087 if (&unused == &unused2) {}
1089 template <
typename S,
typename T, std::size_t N, std::size_t... Indexes>
1090 inline void swap_impl(Adapter<S, T, N> &a, std::size_t i, Adapter<S, T, N> &b,
1091 std::size_t j, Vc::index_sequence<Indexes...>)
1093 const auto &a_const = a;
1094 const auto &b_const = b;
1095 const std::tuple<decltype(decay_workaround(get_dispatcher<Indexes>(a_const)[0]))...>
1096 tmp{decay_workaround(get_dispatcher<Indexes>(a_const)[i])...};
1097 auto &&unused = {(get_dispatcher<Indexes>(a)[i] = get_dispatcher<Indexes>(b_const)[j], 0)...};
1098 auto &&unused2 = {(get_dispatcher<Indexes>(b)[j] = get_dispatcher<Indexes>(tmp), 0)...};
1099 if (&unused == &unused2) {}
1107 template <
typename S,
typename T, std::
size_t N>
1108 inline void swap(Adapter<S, T, N> &a, std::size_t i, S &x)
1110 swap_impl(a, i, x, Vc::make_index_sequence<determine_tuple_size<T>()>());
1112 template <
typename S,
typename T, std::
size_t N>
1113 inline void swap(Adapter<S, T, N> &a, std::size_t i, Adapter<S, T, N> &b, std::size_t j)
1115 swap_impl(a, i, b, j, Vc::make_index_sequence<determine_tuple_size<T>()>());
1118 template <
typename A>
class Scalar
1120 using reference =
typename std::add_lvalue_reference<A>::type;
1121 using S =
typename A::scalar_type;
1122 using IndexSeq = Vc::make_index_sequence<determine_tuple_size<S>()>;
1125 Scalar(reference aa,
size_t ii) : a(aa), i(ii) {}
1128 Scalar(
const Scalar &) =
delete;
1129 Scalar(Scalar &&) =
delete;
1130 Scalar &operator=(
const Scalar &) =
delete;
1131 Scalar &operator=(Scalar &&) =
delete;
1133 void operator=(
const S &x) { assign_impl(a, i, x, IndexSeq()); }
1134 operator S()
const {
return extract_impl(a, i, IndexSeq()); }
1136 template <
typename AA>
1137 friend inline void swap(Scalar<AA> &&a,
typename AA::scalar_type &b);
1138 template <
typename AA>
1139 friend inline void swap(
typename AA::scalar_type &b, Scalar<AA> &&a);
1140 template <
typename AA>
friend inline void swap(Scalar<AA> &&a, Scalar<AA> &&b);
1149 template <
typename A>
inline void swap(Scalar<A> &&a,
typename A::scalar_type &b)
1151 swap_impl(a.a, a.i, b,
typename Scalar<A>::IndexSeq());
1155 template <
typename A>
inline void swap(
typename A::scalar_type &b, Scalar<A> &&a)
1157 swap_impl(a.a, a.i, b,
typename Scalar<A>::IndexSeq());
1160 template <
typename A>
inline void swap(Scalar<A> &&a, Scalar<A> &&b)
1162 swap_impl(a.a, a.i, b.a, b.i,
typename Scalar<A>::IndexSeq());
1166 template <
class S,
class T,
size_t N,
size_t... I>
1167 inline void load_interleaved_impl(Vc::index_sequence<I...>, Adapter<S, T, N> &a,
1170 const InterleavedMemoryWrapper<S, decltype(decay_workaround(get_dispatcher<0>(a)))>
1171 wrapper(
const_cast<S *
>(mem));
1172 Vc::tie(get_dispatcher<I>(a)...) = wrapper[0];
1176 template <
class S,
class T,
size_t N,
size_t... I>
1177 inline void store_interleaved_impl(Vc::index_sequence<I...>,
const Adapter<S, T, N> &a,
1180 InterleavedMemoryWrapper<S, decltype(decay_workaround(get_dispatcher<0>(a)))> wrapper(
1182 wrapper[0] = Vc::tie(get_dispatcher<I>(a)...);
1185 template <
typename A>
class Interface
1187 using reference =
typename std::add_lvalue_reference<A>::type;
1189 Vc::make_index_sequence<determine_tuple_size<typename A::scalar_type>()>;
1192 Interface(reference aa) : a(aa) {}
1194 Scalar<A> operator[](
size_t i)
1198 typename A::scalar_type operator[](
size_t i)
const
1200 return extract_impl(a, i, IndexSeq());
1205 return shifted_impl(a, amount, IndexSeq());
1208 void load(
const typename A::scalar_type *mem) { load_interleaved(*
this, mem); }
1209 void store(
typename A::scalar_type *mem) { store_interleaved(*
this, mem); }
1220 template <
typename S,
typename T,
size_t N>
1221 inline void assign(SimdizeDetail::Adapter<S, T, N> &a,
size_t i,
const S &x)
1223 SimdizeDetail::assign_impl(
1224 a, i, x, Vc::make_index_sequence<SimdizeDetail::determine_tuple_size<T>()>());
1229 template <typename V, typename = enable_if<Traits::is_simd_vector<V>::value>>
1230 Vc_INTRINSIC
void assign(V &v,
size_t i,
typename V::EntryType x)
1240 template <
typename S,
typename T,
size_t N>
1241 inline S
extract(
const SimdizeDetail::Adapter<S, T, N> &a,
size_t i)
1243 return SimdizeDetail::extract_impl(
1244 a, i, Vc::make_index_sequence<SimdizeDetail::determine_tuple_size<S>()>());
1249 template <typename V, typename = enable_if<Traits::is_simd_vector<V>::value>>
1250 Vc_INTRINSIC
typename V::EntryType extract(
const V &v,
size_t i)
1256 template <
class S,
class T,
size_t N>
1257 inline void load_interleaved(SimdizeDetail::Adapter<S, T, N> &a,
const S *mem)
1259 if (SimdizeDetail::homogeneous_sizeof<S>::value == 0) {
1260 Common::unrolled_loop<std::size_t, 0, N>(
1261 [&](std::size_t i) {
assign(a, i, mem[i]); });
1263 constexpr
size_t TupleSize = SimdizeDetail::determine_tuple_size_<S>::value;
1264 SimdizeDetail::load_interleaved_impl(Vc::make_index_sequence<TupleSize>(), a,
1270 class = enable_if<Traits::is_simd_vector<V>::value && std::is_arithmetic<T>::value>>
1271 Vc_INTRINSIC
void load_interleaved(V &a,
const T *mem)
1277 template <
class S,
class T,
size_t N>
1278 inline void store_interleaved(
const SimdizeDetail::Adapter<S, T, N> &a, S *mem)
1280 if (SimdizeDetail::homogeneous_sizeof<S>::value == 0) {
1281 Common::unrolled_loop<std::size_t, 0, N>(
1282 [&](std::size_t i) { mem[i] =
extract(a, i); });
1284 constexpr
size_t TupleSize = SimdizeDetail::determine_tuple_size_<S>::value;
1285 SimdizeDetail::store_interleaved_impl(Vc::make_index_sequence<TupleSize>(), a,
1291 class = enable_if<Traits::is_simd_vector<V>::value && std::is_arithmetic<T>::value>>
1292 Vc_INTRINSIC
void store_interleaved(
const V &a, T *mem)
1298 template <
typename S,
typename T,
size_t N>
1299 SimdizeDetail::Interface<SimdizeDetail::Adapter<S, T, N>> decorate(
1300 SimdizeDetail::Adapter<S, T, N> &a)
1304 template <
typename S,
typename T,
size_t N>
1305 const SimdizeDetail::Interface<const SimdizeDetail::Adapter<S, T, N>> decorate(
1306 const SimdizeDetail::Adapter<S, T, N> &a)
1310 template <
class V,
class =
typename std::enable_if<
1311 Traits::is_simd_vector<typename std::decay<V>::type>::value>>
1314 return std::forward<V>(v);
1317 namespace SimdizeDetail
1320 template <
typename Scalar,
typename Base,
size_t N>
1321 template <
class F,
class>
1322 Adapter<Scalar, Base, N>::Adapter(F &&fun)
1324 for (
size_t i = 0; i < N; ++i) {
1329 namespace IteratorDetails
1331 enum class Mutable { Yes, No };
1333 template <
typename It,
typename V,
size_t I,
size_t End>
1334 Vc_INTRINSIC V fromIteratorImpl(enable_if<(I == End), It>)
1338 template <
typename It,
typename V,
size_t I,
size_t End>
1339 Vc_INTRINSIC V fromIteratorImpl(enable_if<(I < End), It> it)
1341 V r = fromIteratorImpl<It, V, I + 1, End>(it);
1342 Traits::decay<decltype(get_dispatcher<I>(r))> tmp;
1343 for (
size_t j = 0; j < V::size(); ++j, ++it) {
1344 tmp[j] = get_dispatcher<I>(*it);
1346 get_dispatcher<I>(r) = tmp;
1349 template <
typename It,
typename V>
1350 Vc_INTRINSIC V fromIterator(enable_if<!Traits::is_simd_vector<V>::value,
const It &> it)
1352 return fromIteratorImpl<It, V, 0, determine_tuple_size<V>()>(it);
1355 template <
typename It,
typename V>
1356 Vc_INTRINSIC V fromIterator(
1358 Traits::is_simd_vector<V>::value && Traits::has_contiguous_storage<It>::value, It>
1364 Vc_ASSERT(&*it + 1 == &*(it + 1));
1369 template <
typename It,
typename V>
1370 Vc_INTRINSIC V fromIterator(enable_if<Traits::is_simd_vector<V>::value &&
1371 !Traits::has_contiguous_storage<It>::value,
1376 for (
size_t j = 0; j < V::size(); ++j, ++it) {
1385 template <
typename T,
typename value_vector, Mutable>
class Pointer;
1395 template <
typename T,
typename value_vector>
class Pointer<T, value_vector, Mutable::Yes>
1397 static constexpr
auto Size = value_vector::size();
1401 value_vector *operator->() {
return &data; }
1408 Pointer(
const Pointer &) =
delete;
1409 Pointer &operator=(
const Pointer &) =
delete;
1410 Pointer &operator=(Pointer &&) =
delete;
1413 Pointer(Pointer &&) =
default;
1423 for (
size_t i = 0; i < Size; ++i, ++begin_iterator) {
1424 *begin_iterator =
extract(data, i);
1429 Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)), begin_iterator(it) {}
1442 template <
typename T,
typename value_vector>
class Pointer<T, value_vector, Mutable::No>
1444 static constexpr
auto Size = value_vector::size();
1447 const value_vector *operator->()
const {
return &data; }
1450 Pointer(
const Pointer &) =
delete;
1451 Pointer &operator=(
const Pointer &) =
delete;
1452 Pointer &operator=(Pointer &&) =
delete;
1454 Pointer(Pointer &&) =
default;
1456 Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)) {}
1474 template <
typename T,
typename value_vector, Mutable M>
class Reference;
1477 template <
typename T,
typename value_vector>
1478 class Reference<T, value_vector, Mutable::Yes> :
public value_vector
1480 static constexpr
auto Size = value_vector::size();
1482 using reference =
typename std::add_lvalue_reference<T>::type;
1483 reference scalar_it;
1488 Reference(reference first_it)
1489 : value_vector(fromIterator<T, value_vector>(first_it)), scalar_it(first_it)
1494 Reference(
const Reference &) =
delete;
1495 Reference(Reference &&) =
default;
1496 Reference &operator=(
const Reference &) =
delete;
1497 Reference &operator=(Reference &&) =
delete;
1504 void operator=(
const value_vector &x)
1506 static_cast<value_vector &
>(*this) = x;
1507 auto it = scalar_it;
1508 for (
size_t i = 0; i < Size; ++i, ++it) {
1513 #define Vc_OP(op_) \
1514 template <typename T0, typename V0, typename T1, typename V1> \
1515 decltype(std::declval<const V0 &>() op_ std::declval<const V1 &>()) operator op_( \
1516 const Reference<T0, V0, Mutable::Yes> &x, \
1517 const Reference<T1, V1, Mutable::Yes> &y) \
1519 return static_cast<const V0 &>(x) op_ static_cast<const V1 &>(y); \
1521 Vc_ALL_COMPARES(Vc_OP);
1522 Vc_ALL_ARITHMETICS(Vc_OP);
1523 Vc_ALL_BINARY(Vc_OP);
1524 Vc_ALL_LOGICAL(Vc_OP);
1525 Vc_ALL_SHIFTS(Vc_OP);
1529 template <
typename T,
typename value_vector>
1530 class Reference<T, value_vector, Mutable::No> :
public value_vector
1532 static constexpr
auto Size = value_vector::size();
1535 Reference(
const T &it) : value_vector(fromIterator<T, value_vector>(it)) {}
1537 Reference(
const Reference &) =
delete;
1538 Reference(Reference &&) =
default;
1539 Reference &operator=(
const Reference &) =
delete;
1540 Reference &operator=(Reference &&) =
delete;
1543 void operator=(
const value_vector &x) =
delete;
1546 template <
typename T,
size_t N,
1547 IteratorDetails::Mutable M =
1548 (Traits::is_output_iterator<T>::value ? Mutable::Yes : Mutable::No),
1549 typename V =
simdize<
typename std::iterator_traits<T>::value_type, N>,
1550 size_t Size = V::Size,
1551 typename =
typename std::iterator_traits<T>::iterator_category>
1554 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size_>
1555 class Iterator<T, N, M, V, Size_, std::forward_iterator_tag>
1556 :
public std::iterator<typename std::iterator_traits<T>::iterator_category, V,
1557 typename std::iterator_traits<T>::difference_type,
1558 IteratorDetails::Pointer<T, V, M>,
1559 IteratorDetails::Reference<T, V, M>>
1562 using pointer = IteratorDetails::Pointer<T, V, M>;
1563 using reference = IteratorDetails::Reference<T, V, M>;
1564 using const_pointer = IteratorDetails::Pointer<T, V, IteratorDetails::Mutable::No>;
1565 using const_reference =
1566 IteratorDetails::Reference<T, V, IteratorDetails::Mutable::No>;
1569 static constexpr std::size_t size() {
return Size_; }
1570 static constexpr std::size_t Size = Size_;
1572 Iterator() =
default;
1580 Iterator(
const T &x) : scalar_it(x) {}
1584 Iterator(T &&x) : scalar_it(std::move(x)) {}
1588 Iterator &operator=(
const T &x)
1596 Iterator &operator=(T &&x)
1598 scalar_it = std::move(x);
1603 Iterator(
const Iterator &) =
default;
1605 Iterator(Iterator &&) =
default;
1607 Iterator &operator=(
const Iterator &) =
default;
1609 Iterator &operator=(Iterator &&) =
default;
1612 Iterator &operator++()
1614 std::advance(scalar_it, Size);
1618 Iterator operator++(
int)
1620 Iterator copy(*
this);
1633 bool operator==(
const Iterator &rhs)
const
1636 if (scalar_it == rhs.scalar_it) {
1640 for (
size_t i = 1; i < Size; ++i) {
1641 Vc_ASSERT((++it != rhs.scalar_it));
1646 return scalar_it == rhs.scalar_it;
1657 bool operator!=(
const Iterator &rhs)
const
1659 return !operator==(rhs);
1662 pointer operator->() {
return scalar_it; }
1670 reference
operator*() {
return scalar_it; }
1672 const_pointer operator->()
const {
return scalar_it; }
1681 const_reference
operator*()
const {
return scalar_it; }
1696 operator const T &()
const {
return scalar_it; }
1706 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1707 class Iterator<T, N, M, V, Size, std::bidirectional_iterator_tag>
1708 :
public Iterator<T, N, M, V, Size, std::forward_iterator_tag>
1710 using Base = Iterator<T, N, M, V, Size, std::forward_iterator_tag>;
1713 using Base::scalar_it;
1716 using pointer =
typename Base::pointer;
1717 using reference =
typename Base::reference;
1718 using const_pointer =
typename Base::const_pointer;
1719 using const_reference =
typename Base::const_reference;
1721 using Iterator<T, N, M, V, Size,
1722 std::forward_iterator_tag>::Iterator;
1728 std::advance(scalar_it, -Size);
1734 Iterator copy(*
this);
1744 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1745 class Iterator<T, N, M, V, Size, std::random_access_iterator_tag>
1746 :
public Iterator<T, N, M, V, Size, std::bidirectional_iterator_tag>
1751 using Base::scalar_it;
1754 using pointer =
typename Base::pointer;
1755 using reference =
typename Base::reference;
1756 using const_pointer =
typename Base::const_pointer;
1757 using const_reference =
typename Base::const_reference;
1758 using difference_type =
typename std::iterator_traits<T>::difference_type;
1763 Iterator &operator+=(difference_type n)
1765 scalar_it += n * difference_type(Size);
1768 Iterator
operator+(difference_type n)
const {
return Iterator(*
this) += n; }
1770 Iterator &operator-=(difference_type n)
1772 scalar_it -= n * difference_type(Size);
1775 Iterator
operator-(difference_type n)
const {
return Iterator(*
this) -= n; }
1777 difference_type
operator-(
const Iterator &rhs)
const
1779 constexpr difference_type n = Size;
1780 Vc_ASSERT((scalar_it - rhs.scalar_it) % n ==
1786 return (scalar_it - rhs.scalar_it) / n;
1795 return rhs.scalar_it - scalar_it >= difference_type(Size);
1798 bool operator>(
const Iterator &rhs)
const
1800 return scalar_it - rhs.scalar_it >= difference_type(Size);
1803 bool operator<=(
const Iterator &rhs)
const
1805 return rhs.scalar_it - scalar_it >= difference_type(Size) - 1;
1808 bool operator>=(
const Iterator &rhs)
const
1810 return scalar_it - rhs.scalar_it >= difference_type(Size) - 1;
1813 reference operator[](difference_type i) {
return *(*
this + i); }
1814 const_reference operator[](difference_type i)
const {
return *(*
this + i); }
1817 template <
typename T,
size_t N, IteratorDetails::Mutable M,
typename V,
size_t Size>
1818 Iterator<T, N, M, V, Size, std::random_access_iterator_tag>
operator+(
1819 typename Iterator<T, N, M, V, Size, std::random_access_iterator_tag>::difference_type
1821 const Iterator<T, N, M, V, Size, std::random_access_iterator_tag> &i)
1836 template <
typename T,
size_t N,
typename MT>
1837 struct ReplaceTypes<T, N, MT, Category::ForwardIterator>
1839 using type = IteratorDetails::Iterator<T, N>;
1841 template <
typename T,
size_t N,
typename MT>
1842 struct ReplaceTypes<T, N, MT, Category::BidirectionalIterator>
1844 using type = IteratorDetails::Iterator<T, N>;
1846 template <
typename T,
size_t N,
typename MT>
1847 struct ReplaceTypes<T, N, MT, Category::RandomAccessIterator>
1849 using type = IteratorDetails::Iterator<T, N>;
1855 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
typename U,
1857 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N),
void>
1858 conditional_assign(Adapter<S, T, N> &,
const M &,
const U &)
1861 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
typename U,
1862 std::size_t Offset = 0>
1863 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N),
void>
1864 conditional_assign(Adapter<S, T, N> &lhs,
const M &mask,
const U &rhs)
1866 using V =
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
1867 using M2 =
typename V::mask_type;
1868 conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask), get_dispatcher<Offset>(rhs));
1869 conditional_assign<Op, S, T, N, M, U, Offset + 1>(lhs, mask, rhs);
1871 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
1873 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N),
void>
1874 conditional_assign(Adapter<S, T, N> &,
const M &)
1877 template <Vc::Operator Op,
typename S,
typename T, std::size_t N,
typename M,
1878 std::size_t Offset = 0>
1879 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N),
void>
1880 conditional_assign(Adapter<S, T, N> &lhs,
const M &mask)
1882 using V =
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
1883 using M2 =
typename V::mask_type;
1884 conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask));
1885 conditional_assign<Op, S, T, N, M, Offset + 1>(lhs, mask);
1910 template <
typename T,
size_t N = 0,
typename MT =
void>
1932 #define Vc_SIMDIZE_INTERFACE(MEMBERS_) \
1933 template <std::size_t N_> \
1934 inline auto vc_get_()->decltype(std::get<N_>(std::tie MEMBERS_)) \
1936 return std::get<N_>(std::tie MEMBERS_); \
1938 template <std::size_t N_> \
1939 inline auto vc_get_() const->decltype(std::get<N_>(std::tie MEMBERS_)) \
1941 return std::get<N_>(std::tie MEMBERS_); \
1943 enum : std::size_t { \
1944 tuple_size = std::tuple_size<decltype(std::make_tuple MEMBERS_)>::value \
An allocator that uses global new and supports over-aligned types, as per [C++11 20....
bool operator<(const Iterator &rhs) const
Returns whether all entries accessed via iterator dereferencing come before the iterator rhs.
This is the iterator type created when applying simdize to a bidirectional iterator type.
Iterator & operator--()
Advances the iterator by one vector width, or respectively N scalar steps.
Iterator operator--(int)
Postfix overload of the above.
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.
result_vector_type< L, R > operator*(L &&lhs, R &&rhs)
Applies * component-wise and concurrently.
void swap(Adapter< S, T, N > &a, std::size_t i, S &x)
Swaps one scalar object x with a SIMD slot at offset i in the simdized object a.
SimdizeDetail::simdize< T, N, MT > simdize
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.
constexpr UnalignedTag Unaligned
Use this object for a flags parameter to request unaligned loads and stores.
void free(T *p)
Frees memory that was allocated with Vc::malloc.
Vector Classes Namespace.
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.
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.