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_