29 #ifndef COMMON_OPERATORS_H_ 
   30 #define COMMON_OPERATORS_H_ 
   33 namespace Vc_VERSIONED_NAMESPACE
 
   37 template <
typename T, 
typename Abi, 
typename U>
 
   38 enable_if<!std::is_same<T, U>::value, U> is_convertible_to_any_vector(Vector<U, Abi>);
 
   39 template <
typename T, 
typename Abi> T is_convertible_to_any_vector(Vector<T, Abi>);
 
   40 template <
typename T, 
typename Abi> 
void is_convertible_to_any_vector(...);
 
   42 template <typename T, typename U, bool = std::is_integral<T>::value,
 
   43           bool = std::is_integral<U>::value>
 
   44 struct FundamentalReturnType;
 
   45 template <
typename T, 
typename U> 
struct FundamentalReturnType<T, U, false, false> {
 
   46     using type = 
typename std::conditional<
 
   47         std::is_arithmetic<U>::value,
 
   48         typename std::conditional<(sizeof(T) < sizeof(U)), U, T>::type,
 
   52 template <
typename T, 
typename U> 
struct FundamentalReturnType<T, U, true, false> {
 
   53     using type = 
typename std::conditional<
 
   54         std::is_arithmetic<U>::value, U,
 
   58 template <
typename T, 
typename U> 
struct FundamentalReturnType<T, U, false, true> {
 
   62 template <
typename T> 
struct my_make_signed : 
public std::make_signed<T> {
 
   64 template <> 
struct my_make_signed<bool> {
 
   68 template <
typename TT, 
typename UU>
 
   69 struct higher_conversion_rank {
 
   72         typename std::conditional<(std::is_unsigned<TT>::value ||
 
   73                                    std::is_unsigned<UU>::value),
 
   74                                   typename std::make_unsigned<A>::type, A>::type;
 
   75     using T = 
typename my_make_signed<TT>::type;
 
   76     using U = 
typename my_make_signed<UU>::type;
 
   77     template <
typename Test, 
typename Otherwise>
 
   78     using c = 
typename std::conditional<std::is_same<T, Test>::value ||
 
   79                                             std::is_same<U, Test>::value,
 
   80                                         Test, Otherwise>::type;
 
   82     using type = fix_sign<c<long long, c<long, c<int, c<short, c<signed char, void>>>>>>;
 
   85 template <
typename T, 
typename U> 
struct FundamentalReturnType<T, U, true, true> {
 
   86     template <
bool B, 
class Then, 
class E>
 
   87     using c = 
typename std::conditional<B, Then, E>::type;
 
   89         c<(sizeof(T) > 
sizeof(U)), T,
 
   90           c<(sizeof(T) < sizeof(U)), U, typename higher_conversion_rank<T, U>::type>>;
 
   92 static_assert(std::is_same<
long, 
typename FundamentalReturnType<int, long>::type>::value, 
"");
 
   94 template <
typename V, 
typename T, 
bool, 
typename, 
bool> 
struct ReturnTypeImpl {
 
   97 template <
typename T, 
typename U, 
typename Abi, 
typename Deduced>
 
   98 struct ReturnTypeImpl<Vector<T, Abi>, Vector<U, Abi>, false, Deduced, false> {
 
   99     using type = Vector<typename FundamentalReturnType<T, U>::type, Abi>;
 
  101 template <
typename T, 
typename Abi>
 
  102 struct ReturnTypeImpl<Vector<T, Abi>, int, true, T, true> {
 
  103     using type = Vector<T, Abi>;
 
  105 template <
typename T, 
typename Abi>
 
  106 struct ReturnTypeImpl<Vector<T, Abi>, unsigned int, true, T, true> {
 
  107     using type = Vector<typename std::make_unsigned<T>::type, Abi>;
 
  109 template <
typename T, 
typename U, 
typename Abi, 
bool Integral>
 
  110 struct ReturnTypeImpl<Vector<T, Abi>, U, true, T, Integral> {
 
  111     using type = Vector<typename FundamentalReturnType<T, U>::type, Abi>;
 
  113 template <
typename T, 
typename U, 
typename Abi, 
bool Integral>
 
  114 struct ReturnTypeImpl<Vector<T, Abi>, U, false, void, Integral> {
 
  117 template <
typename T, 
typename U, 
typename Abi, 
typename V, 
bool Integral>
 
  118 struct ReturnTypeImpl<Vector<T, Abi>, U, false, V, Integral> {
 
  119     using type = Vector<typename FundamentalReturnType<T, V>::type, Abi>;
 
  121 template <
typename V, 
typename T>
 
  122 using ReturnType = 
typename ReturnTypeImpl<
 
  123     V, T, std::is_arithmetic<T>::value || std::is_convertible<T, int>::value,
 
  124     decltype(is_convertible_to_any_vector<typename V::value_type, typename V::abi>(
 
  125         std::declval<const T &>())),
 
  126     std::is_integral<typename V::value_type>::value>::type;
 
  128 template <
typename T> 
struct is_a_type : 
public std::true_type {
 
  131 #ifdef Vc_ENABLE_FLOAT_BIT_OPERATORS 
  132 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) true 
  134 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_)                                                \ 
  135     Detail::is_a_type<decltype(                                                          \ 
  136         std::declval<typename Detail::ReturnType<Vector<T, Abi>, U>::EntryType>()        \ 
  138                 typename Detail::ReturnType<Vector<T, Abi>, U>::EntryType>())>::value 
  142 #define Vc_GENERIC_OPERATOR(op_)                                                         \ 
  143     template <typename T, typename Abi, typename U>                                      \ 
  144     Vc_ALWAYS_INLINE enable_if<                                                          \ 
  145         Vc_TEST_FOR_BUILTIN_OPERATOR(op_) &&                                             \ 
  146             std::is_convertible<Vector<T, Abi>,                                          \ 
  147                                 Detail::ReturnType<Vector<T, Abi>, U>>::value &&         \ 
  148             std::is_convertible<U, Detail::ReturnType<Vector<T, Abi>, U>>::value,        \ 
  149         Detail::ReturnType<Vector<T, Abi>, U>>                                           \ 
  150     operator op_(Vector<T, Abi> x, const U &y)                                           \ 
  152         using V = Detail::ReturnType<Vector<T, Abi>, U>;                                 \ 
  153         return Detail::operator op_(V(x), V(y));                                         \ 
  155     template <typename T, typename Abi, typename U>                                      \ 
  156     Vc_ALWAYS_INLINE enable_if<                                                          \ 
  157         Vc_TEST_FOR_BUILTIN_OPERATOR(op_) &&                                             \ 
  158             !Traits::is_simd_vector_internal<U>::value &&                                \ 
  159             std::is_convertible<Vector<T, Abi>,                                          \ 
  160                                 Detail::ReturnType<Vector<T, Abi>, U>>::value &&         \ 
  161             std::is_convertible<U, Detail::ReturnType<Vector<T, Abi>, U>>::value,        \ 
  162         Detail::ReturnType<Vector<T, Abi>, U>>                                           \ 
  163     operator op_(const U &x, Vector<T, Abi> y)                                           \ 
  165         using V = Detail::ReturnType<Vector<T, Abi>, U>;                                 \ 
  166         return Detail::operator op_(V(x), V(y));                                         \ 
  168     template <typename T, typename Abi, typename U>                                      \ 
  169     Vc_ALWAYS_INLINE enable_if<                                                          \ 
  170         Vc_TEST_FOR_BUILTIN_OPERATOR(op_) &&                                             \ 
  171             std::is_convertible<Vector<T, Abi>,                                          \ 
  172                                 Detail::ReturnType<Vector<T, Abi>, U>>::value &&         \ 
  173             std::is_convertible<U, Detail::ReturnType<Vector<T, Abi>, U>>::value,        \ 
  175     operator op_##=(Vector<T, Abi> &x, const U &y)                                       \ 
  177         using V = Detail::ReturnType<Vector<T, Abi>, U>;                                 \ 
  178         x = Detail::operator op_(V(x), V(y));                                            \ 
  182 #define Vc_LOGICAL_OPERATOR(op_)                                                         \ 
  183     template <typename T, typename Abi>                                                  \ 
  184     Vc_ALWAYS_INLINE typename Vector<T, Abi>::Mask operator op_(Vector<T, Abi> x,        \ 
  187         return !!x op_ !!y;                                                              \ 
  189     template <typename T, typename Abi, typename U>                                      \ 
  191         enable_if<std::is_convertible<Vector<T, Abi>, Vector<U, Abi>>::value &&          \ 
  192                       std::is_convertible<Vector<U, Abi>, Vector<T, Abi>>::value,        \ 
  193                   typename Detail::ReturnType<Vector<T, Abi>, Vector<U, Abi>>::Mask>     \ 
  194         operator op_(Vector<T, Abi> x, Vector<U, Abi> y)                                 \ 
  196         return !!x op_ !!y;                                                              \ 
  198     template <typename T, typename Abi, typename U>                                      \ 
  200         enable_if<std::is_same<bool, decltype(!std::declval<const U &>())>::value,       \ 
  201                   typename Vector<T, Abi>::Mask>                                         \ 
  202         operator op_(Vector<T, Abi> x, const U &y)                                       \ 
  204         using M = typename Vector<T, Abi>::Mask;                                         \ 
  205         return !!x op_ M(!!y);                                                           \ 
  207     template <typename T, typename Abi, typename U>                                      \ 
  209         enable_if<std::is_same<bool, decltype(!std::declval<const U &>())>::value,       \ 
  210                   typename Vector<T, Abi>::Mask>                                         \ 
  211         operator op_(const U &x, Vector<T, Abi> y)                                       \ 
  213         using M = typename Vector<T, Abi>::Mask;                                         \ 
  214         return M(!!x) op_ !!y;                                                           \ 
  217 #define Vc_COMPARE_OPERATOR(op_)                                                         \ 
  218     template <typename T, typename Abi, typename U>                                      \ 
  219     Vc_ALWAYS_INLINE enable_if<                                                          \ 
  220         std::is_convertible<Vector<T, Abi>,                                              \ 
  221                             Detail::ReturnType<Vector<T, Abi>, U>>::value &&             \ 
  222             std::is_convertible<U, Detail::ReturnType<Vector<T, Abi>, U>>::value,        \ 
  223         typename Detail::ReturnType<Vector<T, Abi>, U>::Mask>                            \ 
  224     operator op_(Vector<T, Abi> x, const U &y)                                           \ 
  226         using V = Detail::ReturnType<Vector<T, Abi>, U>;                                 \ 
  227         return Detail::operator op_(V(x), V(y));                                         \ 
  229     template <typename T, typename Abi, typename U>                                      \ 
  230     Vc_ALWAYS_INLINE enable_if<                                                          \ 
  231         !Traits::is_simd_vector_internal<U>::value &&                                    \ 
  232             std::is_convertible<Vector<T, Abi>,                                          \ 
  233                                 Detail::ReturnType<Vector<T, Abi>, U>>::value &&         \ 
  234             std::is_convertible<U, Detail::ReturnType<Vector<T, Abi>, U>>::value,        \ 
  235         typename Detail::ReturnType<Vector<T, Abi>, U>::Mask>                            \ 
  236     operator op_(const U &x, Vector<T, Abi> y)                                           \ 
  238         using V = Detail::ReturnType<Vector<T, Abi>, U>;                                 \ 
  239         return Detail::operator op_(V(x), V(y));                                         \ 
  242 Vc_ALL_LOGICAL    (Vc_LOGICAL_OPERATOR);
 
  243 Vc_ALL_BINARY     (Vc_GENERIC_OPERATOR);
 
  244 Vc_ALL_ARITHMETICS(Vc_GENERIC_OPERATOR);
 
  245 Vc_ALL_COMPARES   (Vc_COMPARE_OPERATOR);
 
  247 #undef Vc_LOGICAL_OPERATOR 
  248 #undef Vc_GENERIC_OPERATOR 
  249 #undef Vc_COMPARE_OPERATOR 
  250 #undef Vc_INVALID_OPERATOR 
  253 #endif  // COMMON_OPERATORS_H_