28 #ifndef COMMON_OPERATORS_H_ 29 #define COMMON_OPERATORS_H_ 30 #include "simdarray.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>);
41 template <typename T, typename U, bool = std::is_integral<T>::value,
42 bool = std::is_integral<U>::value>
43 struct FundamentalReturnType;
44 template <
class T,
class U>
45 using fundamental_return_t =
typename FundamentalReturnType<T, U>::type;
47 template <
typename T,
typename U>
struct FundamentalReturnType<T, U, false, false> {
48 using type =
typename std::conditional<
49 std::is_arithmetic<U>::value,
50 typename std::conditional<(sizeof(T) < sizeof(U)), U, T>::type,
54 template <
typename T,
typename U>
struct FundamentalReturnType<T, U, true, false> {
55 using type =
typename std::conditional<
56 std::is_arithmetic<U>::value, U,
60 template <
typename T,
typename U>
struct FundamentalReturnType<T, U, false, true> {
64 template <
typename T>
struct my_make_signed :
public std::make_signed<T> {
66 template <>
struct my_make_signed<bool> {
70 template <
typename TT,
typename UU>
71 struct higher_conversion_rank {
74 typename std::conditional<(std::is_unsigned<TT>::value ||
75 std::is_unsigned<UU>::value),
76 typename std::make_unsigned<A>::type, A>::type;
77 using T =
typename my_make_signed<TT>::type;
78 using U =
typename my_make_signed<UU>::type;
79 template <
typename Test,
typename Otherwise>
80 using c =
typename std::conditional<std::is_same<T, Test>::value ||
81 std::is_same<U, Test>::value,
82 Test, Otherwise>::type;
84 using type = fix_sign<c<long long, c<long, c<int, c<short, c<signed char, void>>>>>>;
87 template <
typename T,
typename U>
struct FundamentalReturnType<T, U, true, true> {
88 template <
bool B,
class Then,
class E>
89 using c =
typename std::conditional<B, Then, E>::type;
91 c<(sizeof(T) >
sizeof(U)), T,
92 c<(sizeof(T) < sizeof(U)), U, typename higher_conversion_rank<T, U>::type>>;
95 template <
class V,
class T,
class Tq,
class =
void>
struct ReturnTypeImpl {
99 template <
class T,
class U,
class Abi,
class Uq>
100 struct ReturnTypeImpl<Vector<T, Abi>, Vector<U, Abi>, Uq, void> {
104 template <
class T,
class Abi,
class Uq>
105 struct ReturnTypeImpl<Vector<T, Abi>, int, Uq, void> {
111 template <
class T,
class Abi,
class Uq>
112 struct ReturnTypeImpl<Vector<T, Abi>,
uint, Uq, void> {
116 typename std::conditional<std::is_integral<T>::value, std::make_unsigned<T>,
117 std::enable_if<true, T>>::type::type,
121 template <
class T,
class U,
class Abi,
class Uq>
122 struct ReturnTypeImpl<
123 Vector<T, Abi>, U, Uq,
124 enable_if<!
std::is_class<U>::value && !std::is_same<U, int>::value &&
125 !std::is_same<U, uint>::value &&
126 Traits::is_valid_vector_argument<fundamental_return_t<T, U>>::value,
131 template <
class T,
class U,
class Abi,
class Uq>
132 struct ReturnTypeImpl<
133 Vector<T, Abi>, U, Uq,
134 enable_if<
std::is_class<U>::value && !Traits::is_simd_vector<U>::value &&
135 Traits::is_valid_vector_argument<decltype(
136 is_convertible_to_any_vector<T, Abi>(std::declval<Uq>()))>::value,
140 std::declval<Uq>()))>,
143 template <
class V,
class Tq,
class T = remove_cvref_t<Tq>>
144 using ReturnType =
typename ReturnTypeImpl<V, T, Tq>::type;
146 template <
class T>
struct is_a_type :
public std::true_type {
149 #ifdef Vc_ENABLE_FLOAT_BIT_OPERATORS 150 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) true 152 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) \ 153 Detail::is_a_type<decltype(std::declval<typename R::value_type>() \ 154 op_ std::declval<typename R::value_type>())>::value 158 #define Vc_GENERIC_OPERATOR(op_) \ 159 template <class T, class Abi, class U, \ 160 class R = Detail::ReturnType<Vector<T, Abi>, U>> \ 161 Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \ 162 std::is_convertible<Vector<T, Abi>, R>::value && \ 163 std::is_convertible<U, R>::value, \ 165 operator op_(Vector<T, Abi> x, U &&y) \ 167 return Detail::operator op_(R(x), R(std::forward<U>(y))); \ 169 template <class T, class Abi, class U, \ 170 class R = Detail::ReturnType<Vector<T, Abi>, U>> \ 171 Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \ 172 !Traits::is_simd_vector<U>::value && \ 173 std::is_convertible<Vector<T, Abi>, R>::value && \ 174 std::is_convertible<U, R>::value, \ 176 operator op_(U &&x, Vector<T, Abi> y) \ 178 return Detail::operator op_(R(std::forward<U>(x)), R(y)); \ 180 template <class T, class Abi, class U, \ 181 class R = Detail::ReturnType<Vector<T, Abi>, U>> \ 182 Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \ 183 std::is_convertible<Vector<T, Abi>, R>::value && \ 184 std::is_convertible<U, R>::value, \ 186 operator op_##=(Vector<T, Abi> &x, U &&y) \ 188 x = Detail::operator op_(R(x), R(std::forward<U>(y))); \ 192 #define Vc_LOGICAL_OPERATOR(op_) \ 193 template <class T, class Abi> \ 194 Vc_ALWAYS_INLINE typename Vector<T, Abi>::Mask operator op_(Vector<T, Abi> x, \ 197 return !!x op_ !!y; \ 199 template <class T, class Abi, class U> \ 201 enable_if<std::is_convertible<Vector<T, Abi>, Vector<U, Abi>>::value && \ 202 std::is_convertible<Vector<U, Abi>, Vector<T, Abi>>::value, \ 203 typename Detail::ReturnType<Vector<T, Abi>, Vector<U, Abi>>::Mask> \ 204 operator op_(Vector<T, Abi> x, Vector<U, Abi> y) \ 206 return !!x op_ !!y; \ 208 template <class T, class Abi, class U> \ 209 Vc_ALWAYS_INLINE enable_if<std::is_same<bool, decltype(!std::declval<U>())>::value, \ 210 typename Vector<T, Abi>::Mask> \ 211 operator op_(Vector<T, Abi> x, U &&y) \ 213 using M = typename Vector<T, Abi>::Mask; \ 214 return !!x op_ M(!!std::forward<U>(y)); \ 216 template <class T, class Abi, class U> \ 217 Vc_ALWAYS_INLINE enable_if<std::is_same<bool, decltype(!std::declval<U>())>::value, \ 218 typename Vector<T, Abi>::Mask> \ 219 operator op_(U &&x, Vector<T, Abi> y) \ 221 using M = typename Vector<T, Abi>::Mask; \ 222 return M(!!std::forward<U>(x)) op_ !!y; \ 225 #define Vc_COMPARE_OPERATOR(op_) \ 226 template <class T, class Abi, class U, \ 227 class R = Detail::ReturnType<Vector<T, Abi>, U>> \ 228 Vc_ALWAYS_INLINE enable_if<std::is_convertible<Vector<T, Abi>, R>::value && \ 229 std::is_convertible<U, R>::value, \ 231 operator op_(Vector<T, Abi> x, U &&y) \ 233 return Detail::operator op_(R(x), R(std::forward<U>(y))); \ 235 template <class T, class Abi, class U, \ 236 class R = Detail::ReturnType<Vector<T, Abi>, U>> \ 238 enable_if<!Traits::is_simd_vector_internal<remove_cvref_t<U>>::value && \ 239 std::is_convertible<Vector<T, Abi>, R>::value && \ 240 std::is_convertible<U, R>::value, \ 242 operator op_(U &&x, Vector<T, Abi> y) \ 244 return Detail::operator op_(R(std::forward<U>(x)), R(y)); \ 247 Vc_ALL_LOGICAL (Vc_LOGICAL_OPERATOR);
248 Vc_ALL_BINARY (Vc_GENERIC_OPERATOR);
249 Vc_ALL_ARITHMETICS(Vc_GENERIC_OPERATOR);
250 Vc_ALL_COMPARES (Vc_COMPARE_OPERATOR);
252 #undef Vc_LOGICAL_OPERATOR 253 #undef Vc_GENERIC_OPERATOR 254 #undef Vc_COMPARE_OPERATOR 255 #undef Vc_INVALID_OPERATOR 258 #endif // COMMON_OPERATORS_H_ unsigned int uint
unsigned int shorthand
The main vector class for expressing data parallelism.