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 
  402 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...>;
 
  409 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 
  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...>;
 
  418 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 
  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...>;
 
  427 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 
  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...>;
 
  436 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 
  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...>;
 
  445 #endif // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 
  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;            \ 
  672 #endif  // Vc_VALUE_PACK_EXPANSION_IS_BROKEN 
  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;
 
  860     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>
 
 1361     Vc_ASSERT(&*it + 1 == &*(it + 1));
 
 1365 template <
typename It, 
typename V>
 
 1366 Vc_INTRINSIC V fromIterator(enable_if<Traits::is_simd_vector<V>::value &&
 
 1367                                           !Traits::has_contiguous_storage<It>::value,
 
 1372     for (
size_t j = 0; j < V::size(); ++j, ++it) {
 
 1381 template <
typename T, 
typename value_vector, Mutable> 
class Pointer;
 
 1391 template <
typename T, 
typename value_vector> 
class Pointer<T, value_vector, Mutable::Yes>
 
 1393     static constexpr 
auto Size = value_vector::size();
 
 1397     value_vector *operator->() { 
return &data; }
 
 1404     Pointer(
const Pointer &) = 
delete;
 
 1405     Pointer &operator=(
const Pointer &) = 
delete;
 
 1406     Pointer &operator=(Pointer &&) = 
delete;
 
 1409     Pointer(Pointer &&) = 
default;
 
 1419         for (
size_t i = 0; i < Size; ++i, ++begin_iterator) {
 
 1420             *begin_iterator = 
extract(data, i);
 
 1425     Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)), begin_iterator(it) {}
 
 1438 template <
typename T, 
typename value_vector> 
class Pointer<T, value_vector, Mutable::No>
 
 1440     static constexpr 
auto Size = value_vector::size();
 
 1443     const value_vector *operator->()
 const { 
return &data; }
 
 1446     Pointer(
const Pointer &) = 
delete;
 
 1447     Pointer &operator=(
const Pointer &) = 
delete;
 
 1448     Pointer &operator=(Pointer &&) = 
delete;
 
 1450     Pointer(Pointer &&) = 
default;  
 
 1452     Pointer(
const T &it) : data(fromIterator<T, value_vector>(it)) {}
 
 1470 template <
typename T, 
typename value_vector, Mutable M> 
class Reference;
 
 1473 template <
typename T, 
typename value_vector>
 
 1474 class Reference<T, value_vector, Mutable::Yes> : 
public value_vector
 
 1476     static constexpr 
auto Size = value_vector::size();
 
 1478     using reference = 
typename std::add_lvalue_reference<T>::type;
 
 1479     reference scalar_it;
 
 1484     Reference(reference first_it)
 
 1485         : value_vector(fromIterator<T, value_vector>(first_it)), scalar_it(first_it)
 
 1490     Reference(
const Reference &) = 
delete;
 
 1491     Reference(Reference &&) = 
default;
 
 1492     Reference &operator=(
const Reference &) = 
delete;
 
 1493     Reference &operator=(Reference &&) = 
delete;
 
 1500     void operator=(
const value_vector &x)
 
 1502         static_cast<value_vector &
>(*this) = x;
 
 1503         auto it = scalar_it;
 
 1504         for (
size_t i = 0; i < Size; ++i, ++it) {
 
 1509 #define Vc_OP(op_)                                                                       \ 
 1510     template <typename T0, typename V0, typename T1, typename V1>                        \ 
 1511     decltype(std::declval<const V0 &>() op_ std::declval<const V1 &>()) operator op_(    \ 
 1512         const Reference<T0, V0, Mutable::Yes> &x,                                        \ 
 1513         const Reference<T1, V1, Mutable::Yes> &y)                                        \ 
 1515         return static_cast<const V0 &>(x) op_ static_cast<const V1 &>(y);                \ 
 1517 Vc_ALL_COMPARES(Vc_OP);
 
 1518 Vc_ALL_ARITHMETICS(Vc_OP);
 
 1519 Vc_ALL_BINARY(Vc_OP);
 
 1520 Vc_ALL_LOGICAL(Vc_OP);
 
 1521 Vc_ALL_SHIFTS(Vc_OP);
 
 1525 template <
typename T, 
typename value_vector>
 
 1526 class Reference<T, value_vector, Mutable::No> : 
public value_vector
 
 1528     static constexpr 
auto Size = value_vector::size();
 
 1531     Reference(
const T &it) : value_vector(fromIterator<T, value_vector>(it)) {}
 
 1533     Reference(
const Reference &) = 
delete;
 
 1534     Reference(Reference &&) = 
default;
 
 1535     Reference &operator=(
const Reference &) = 
delete;
 
 1536     Reference &operator=(Reference &&) = 
delete;
 
 1539     void operator=(
const value_vector &x) = 
delete;
 
 1542 template <
typename T, 
size_t N,
 
 1543           IteratorDetails::Mutable M =
 
 1544               (Traits::is_output_iterator<T>::value ? Mutable::Yes : Mutable::No),
 
 1545           typename V = 
simdize<
typename std::iterator_traits<T>::value_type, N>,
 
 1546           size_t Size = V::Size,
 
 1547           typename = 
typename std::iterator_traits<T>::iterator_category>
 
 1550 template <
typename T, 
size_t N, IteratorDetails::Mutable M, 
typename V, 
size_t Size_>
 
 1551 class Iterator<T, N, M, V, Size_, std::forward_iterator_tag>
 
 1552     : 
public std::iterator<typename std::iterator_traits<T>::iterator_category, V,
 
 1553                            typename std::iterator_traits<T>::difference_type,
 
 1554                            IteratorDetails::Pointer<T, V, M>,
 
 1555                            IteratorDetails::Reference<T, V, M>>
 
 1558     using pointer = IteratorDetails::Pointer<T, V, M>;
 
 1559     using reference = IteratorDetails::Reference<T, V, M>;
 
 1560     using const_pointer = IteratorDetails::Pointer<T, V, IteratorDetails::Mutable::No>;
 
 1561     using const_reference =
 
 1562         IteratorDetails::Reference<T, V, IteratorDetails::Mutable::No>;
 
 1565     static constexpr std::size_t size() { 
return Size_; }
 
 1566     static constexpr std::size_t Size = Size_;
 
 1568     Iterator() = 
default;
 
 1576     Iterator(
const T &x) : scalar_it(x) {}
 
 1580     Iterator(T &&x) : scalar_it(std::move(x)) {}
 
 1584     Iterator &operator=(
const T &x)
 
 1592     Iterator &operator=(T &&x)
 
 1594         scalar_it = std::move(x);
 
 1599     Iterator(
const Iterator &) = 
default;
 
 1601     Iterator(Iterator &&) = 
default;
 
 1603     Iterator &operator=(
const Iterator &) = 
default;
 
 1605     Iterator &operator=(Iterator &&) = 
default;
 
 1608     Iterator &operator++()
 
 1610         std::advance(scalar_it, Size);
 
 1614     Iterator operator++(
int)
 
 1616         Iterator copy(*
this);
 
 1629     bool operator==(
const Iterator &rhs)
 const 
 1632         if (scalar_it == rhs.scalar_it) {
 
 1636             for (
size_t i = 1; i < Size; ++i) {
 
 1637                 Vc_ASSERT((++it != rhs.scalar_it));
 
 1642         return scalar_it == rhs.scalar_it;
 
 1653     bool operator!=(
const Iterator &rhs)
 const 
 1655         return !operator==(rhs);
 
 1658     pointer operator->() { 
return scalar_it; }
 
 1666     reference 
operator*() { 
return scalar_it; }
 
 1668     const_pointer operator->()
 const { 
return scalar_it; }
 
 1677     const_reference 
operator*()
 const { 
return scalar_it; }
 
 1692     operator const T &() 
const { 
return scalar_it; }
 
 1702 template <
typename T, 
size_t N, IteratorDetails::Mutable M, 
typename V, 
size_t Size>
 
 1703 class Iterator<T, N, M, V, Size, std::bidirectional_iterator_tag>
 
 1704     : 
public Iterator<T, N, M, V, Size, std::forward_iterator_tag>
 
 1706     using Base = Iterator<T, N, M, V, Size, std::forward_iterator_tag>;
 
 1709     using Base::scalar_it;
 
 1712     using pointer = 
typename Base::pointer;
 
 1713     using reference = 
typename Base::reference;
 
 1714     using const_pointer = 
typename Base::const_pointer;
 
 1715     using const_reference = 
typename Base::const_reference;
 
 1717     using Iterator<T, N, M, V, Size,
 
 1718                    std::forward_iterator_tag>::Iterator;  
 
 1724         std::advance(scalar_it, -Size);
 
 1730         Iterator copy(*
this);
 
 1740 template <
typename T, 
size_t N, IteratorDetails::Mutable M, 
typename V, 
size_t Size>
 
 1741 class Iterator<T, N, M, V, Size, std::random_access_iterator_tag>
 
 1742     : 
public Iterator<T, N, M, V, Size, std::bidirectional_iterator_tag>
 
 1747     using Base::scalar_it;
 
 1750     using pointer = 
typename Base::pointer;
 
 1751     using reference = 
typename Base::reference;
 
 1752     using const_pointer = 
typename Base::const_pointer;
 
 1753     using const_reference = 
typename Base::const_reference;
 
 1754     using difference_type = 
typename std::iterator_traits<T>::difference_type;
 
 1759     Iterator &operator+=(difference_type n)
 
 1761         scalar_it += n * difference_type(Size);
 
 1764     Iterator 
operator+(difference_type n)
 const { 
return Iterator(*
this) += n; }
 
 1766     Iterator &operator-=(difference_type n)
 
 1768         scalar_it -= n * difference_type(Size);
 
 1771     Iterator 
operator-(difference_type n)
 const { 
return Iterator(*
this) -= n; }
 
 1773     difference_type 
operator-(
const Iterator &rhs)
 const 
 1775         constexpr difference_type n = Size;
 
 1776         Vc_ASSERT((scalar_it - rhs.scalar_it) % n ==
 
 1782         return (scalar_it - rhs.scalar_it) / n;
 
 1791         return rhs.scalar_it - scalar_it >= difference_type(Size);
 
 1794     bool operator>(
const Iterator &rhs)
 const 
 1796         return scalar_it - rhs.scalar_it >= difference_type(Size);
 
 1799     bool operator<=(
const Iterator &rhs)
 const 
 1801         return rhs.scalar_it - scalar_it >= difference_type(Size) - 1;
 
 1804     bool operator>=(
const Iterator &rhs)
 const 
 1806         return scalar_it - rhs.scalar_it >= difference_type(Size) - 1;
 
 1809     reference operator[](difference_type i) { 
return *(*
this + i); }
 
 1810     const_reference operator[](difference_type i)
 const { 
return *(*
this + i); }
 
 1813 template <
typename T, 
size_t N, IteratorDetails::Mutable M, 
typename V, 
size_t Size>
 
 1814 Iterator<T, N, M, V, Size, std::random_access_iterator_tag> 
operator+(
 
 1815     typename Iterator<T, N, M, V, Size, std::random_access_iterator_tag>::difference_type
 
 1817     const Iterator<T, N, M, V, Size, std::random_access_iterator_tag> &i)
 
 1832 template <
typename T, 
size_t N, 
typename MT>
 
 1833 struct ReplaceTypes<T, N, MT, Category::ForwardIterator>
 
 1835     using type = IteratorDetails::Iterator<T, N>;
 
 1837 template <
typename T, 
size_t N, 
typename MT>
 
 1838 struct ReplaceTypes<T, N, MT, Category::BidirectionalIterator>
 
 1840     using type = IteratorDetails::Iterator<T, N>;
 
 1842 template <
typename T, 
size_t N, 
typename MT>
 
 1843 struct ReplaceTypes<T, N, MT, Category::RandomAccessIterator>
 
 1845     using type = IteratorDetails::Iterator<T, N>;
 
 1851 template <Vc::Operator Op, 
typename S, 
typename T, std::size_t N, 
typename M, 
typename U,
 
 1853 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N), 
void>
 
 1854     conditional_assign(Adapter<S, T, N> &, 
const M &, 
const U &)
 
 1857 template <Vc::Operator Op, 
typename S, 
typename T, std::size_t N, 
typename M, 
typename U,
 
 1858           std::size_t Offset = 0>
 
 1859 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N), 
void>
 
 1860     conditional_assign(Adapter<S, T, N> &lhs, 
const M &mask, 
const U &rhs)
 
 1862     using V = 
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
 
 1863     using M2 = 
typename V::mask_type;
 
 1864     conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask), get_dispatcher<Offset>(rhs));
 
 1865     conditional_assign<Op, S, T, N, M, U, Offset + 1>(lhs, mask, rhs);
 
 1867 template <Vc::Operator Op, 
typename S, 
typename T, std::size_t N, 
typename M,
 
 1869 Vc_INTRINSIC Vc::enable_if<(Offset >= determine_tuple_size_<S>::value && M::Size == N), 
void>
 
 1870     conditional_assign(Adapter<S, T, N> &, 
const M &)
 
 1873 template <Vc::Operator Op, 
typename S, 
typename T, std::size_t N, 
typename M,
 
 1874           std::size_t Offset = 0>
 
 1875 Vc_INTRINSIC Vc::enable_if<(Offset < determine_tuple_size_<S>::value && M::Size == N), 
void>
 
 1876     conditional_assign(Adapter<S, T, N> &lhs, 
const M &mask)
 
 1878     using V = 
typename std::decay<decltype(get_dispatcher<Offset>(lhs))>::type;
 
 1879     using M2 = 
typename V::mask_type;
 
 1880     conditional_assign<Op>(get_dispatcher<Offset>(lhs), simd_cast<M2>(mask));
 
 1881     conditional_assign<Op, S, T, N, M, Offset + 1>(lhs, mask);
 
 1906 template <
typename T, 
size_t N = 0, 
typename MT = 
void>
 
 1928 #define Vc_SIMDIZE_INTERFACE(MEMBERS_)                                                   \ 
 1929     template <std::size_t N_>                                                            \ 
 1930     inline auto vc_get_()->decltype(std::get<N_>(std::tie MEMBERS_))                     \ 
 1932         return std::get<N_>(std::tie MEMBERS_);                                          \ 
 1934     template <std::size_t N_>                                                            \ 
 1935     inline auto vc_get_() const->decltype(std::get<N_>(std::tie MEMBERS_))               \ 
 1937         return std::get<N_>(std::tie MEMBERS_);                                          \ 
 1939     enum : std::size_t {                                                                 \ 
 1940         tuple_size = std::tuple_size<decltype(std::make_tuple MEMBERS_)>::value          \ 
 1947 using Vc::SimdizeDetail::swap;
 
 1950 #endif  // VC_COMMON_SIMDIZE_H_