28 #ifndef COMMON_OPERATORS_H_
29 #define COMMON_OPERATORS_H_
32 namespace Vc_VERSIONED_NAMESPACE
36 template <
typename T,
typename Abi,
typename U>
37 enable_if<!std::is_same<T, U>::value, U> is_convertible_to_any_vector(Vector<U, Abi>);
38 template <
typename T,
typename Abi> T is_convertible_to_any_vector(Vector<T, Abi>);
39 template <
typename T,
typename Abi>
void is_convertible_to_any_vector(...);
41 template <typename T, typename U, bool = std::is_integral<T>::value,
42 bool = std::is_integral<U>::value>
43 struct FundamentalReturnType;
44 template <
typename T,
typename U>
struct FundamentalReturnType<T, U, false, false> {
45 using type =
typename std::conditional<
46 std::is_arithmetic<U>::value,
47 typename std::conditional<(sizeof(T) < sizeof(U)), U, T>::type,
51 template <
typename T,
typename U>
struct FundamentalReturnType<T, U, true, false> {
52 using type =
typename std::conditional<
53 std::is_arithmetic<U>::value, U,
57 template <
typename T,
typename U>
struct FundamentalReturnType<T, U, false, true> {
61 template <
typename T>
struct my_make_signed :
public std::make_signed<T> {
63 template <>
struct my_make_signed<bool> {
67 template <
typename TT,
typename UU>
68 struct higher_conversion_rank {
71 typename std::conditional<(std::is_unsigned<TT>::value ||
72 std::is_unsigned<UU>::value),
73 typename std::make_unsigned<A>::type, A>::type;
74 using T =
typename my_make_signed<TT>::type;
75 using U =
typename my_make_signed<UU>::type;
76 template <
typename Test,
typename Otherwise>
77 using c =
typename std::conditional<std::is_same<T, Test>::value ||
78 std::is_same<U, Test>::value,
79 Test, Otherwise>::type;
81 using type = fix_sign<c<long long, c<long, c<int, c<short, c<signed char, void>>>>>>;
84 template <
typename T,
typename U>
struct FundamentalReturnType<T, U, true, true> {
85 template <
bool B,
class Then,
class E>
86 using c =
typename std::conditional<B, Then, E>::type;
88 c<(sizeof(T) >
sizeof(U)), T,
89 c<(sizeof(T) < sizeof(U)), U, typename higher_conversion_rank<T, U>::type>>;
91 static_assert(std::is_same<
long,
typename FundamentalReturnType<int, long>::type>::value,
"");
93 template <
typename V,
typename T,
bool,
typename,
bool>
struct ReturnTypeImpl {
96 template <
typename T,
typename U,
typename Abi,
typename Deduced>
97 struct ReturnTypeImpl<Vector<T, Abi>, Vector<U, Abi>, false, Deduced, false> {
100 template <
typename T,
typename Abi>
101 struct ReturnTypeImpl<Vector<T, Abi>, int, true, T, true> {
104 template <
typename T,
typename Abi>
105 struct ReturnTypeImpl<Vector<T, Abi>, unsigned int, true, T, true> {
108 template <
typename T,
typename U,
typename Abi,
bool Integral>
109 struct ReturnTypeImpl<Vector<T, Abi>, U, true, T, Integral> {
112 template <
typename T,
typename U,
typename Abi,
bool Integral>
113 struct ReturnTypeImpl<Vector<T, Abi>, U, false, void, Integral> {
116 template <
typename T,
typename U,
typename Abi,
typename V,
bool Integral>
117 struct ReturnTypeImpl<Vector<T, Abi>, U, false, V, Integral> {
120 template <
typename V,
typename T>
121 using ReturnType = ReturnTypeImpl<
122 V, T, std::is_arithmetic<T>::value || std::is_convertible<T, int>::value,
123 decltype(is_convertible_to_any_vector<typename V::value_type, typename V::abi>(
124 std::declval<const T &>())),
125 std::is_integral<typename V::value_type>::value>;
127 template <
typename T>
struct is_a_type :
public std::true_type {
130 #ifdef Vc_ENABLE_FLOAT_BIT_OPERATORS
131 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) true
133 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) \
134 Detail::is_a_type<decltype( \
135 std::declval<typename Detail::ReturnType<Vector<T, Abi>, U>::type::EntryType>() \
136 op_ std::declval<typename Detail::ReturnType<Vector<T, Abi>, \
137 U>::type::EntryType>())>::value
141 #define Vc_GENERIC_OPERATOR(op_) \
142 template <typename T, typename Abi, typename U> \
143 Vc_ALWAYS_INLINE enable_if< \
144 Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
145 std::is_convertible<Vector<T, Abi>, typename Detail::ReturnType< \
146 Vector<T, Abi>, U>::type>::value && \
147 std::is_convertible< \
148 U, typename Detail::ReturnType<Vector<T, Abi>, U>::type>::value, \
149 typename Detail::ReturnType<Vector<T, Abi>, U>::type> \
150 operator op_(Vector<T, Abi> x, const U &y) \
152 using V = typename Detail::ReturnType<Vector<T, Abi>, U>::type; \
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>, typename Detail::ReturnType< \
160 Vector<T, Abi>, U>::type>::value && \
161 std::is_convertible< \
162 U, typename Detail::ReturnType<Vector<T, Abi>, U>::type>::value, \
163 typename Detail::ReturnType<Vector<T, Abi>, U>::type> \
164 operator op_(const U &x, Vector<T, Abi> y) \
166 using V = typename Detail::ReturnType<Vector<T, Abi>, U>::type; \
167 return Detail::operator op_(V(x), V(y)); \
169 template <typename T, typename Abi, typename U> \
170 Vc_ALWAYS_INLINE enable_if< \
171 Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
172 std::is_convertible<Vector<T, Abi>, typename Detail::ReturnType< \
173 Vector<T, Abi>, U>::type>::value && \
174 std::is_convertible< \
175 U, typename Detail::ReturnType<Vector<T, Abi>, U>::type>::value, \
177 operator op_##=(Vector<T, Abi> &x, const U &y) \
179 using V = typename Detail::ReturnType<Vector<T, Abi>, U>::type; \
180 x = Detail::operator op_(V(x), V(y)); \
184 #define Vc_LOGICAL_OPERATOR(op_) \
185 template <typename T, typename Abi> \
186 Vc_ALWAYS_INLINE typename Vector<T, Abi>::Mask operator op_(Vector<T, Abi> x, \
189 return !!x op_ !!y; \
191 template <typename T, typename Abi, typename U> \
192 Vc_ALWAYS_INLINE enable_if< \
193 std::is_convertible<Vector<T, Abi>, Vector<U, Abi>>::value && \
194 std::is_convertible<Vector<U, Abi>, Vector<T, Abi>>::value, \
195 typename Detail::ReturnType<Vector<T, Abi>, Vector<U, Abi>>::type::Mask> \
196 operator op_(Vector<T, Abi> x, Vector<U, Abi> y) \
198 return !!x op_ !!y; \
200 template <typename T, typename Abi, typename U> \
202 enable_if<std::is_same<bool, decltype(!std::declval<const U &>())>::value, \
203 typename Vector<T, Abi>::Mask> \
204 operator op_(Vector<T, Abi> x, const U &y) \
206 using M = typename Vector<T, Abi>::Mask; \
207 return !!x op_ M(!!y); \
209 template <typename T, typename Abi, typename U> \
211 enable_if<std::is_same<bool, decltype(!std::declval<const U &>())>::value, \
212 typename Vector<T, Abi>::Mask> \
213 operator op_(const U &x, Vector<T, Abi> y) \
215 using M = typename Vector<T, Abi>::Mask; \
216 return M(!!x) op_ !!y; \
219 #define Vc_COMPARE_OPERATOR(op_) \
220 template <typename T, typename Abi, typename U> \
221 Vc_ALWAYS_INLINE enable_if< \
222 std::is_convertible<Vector<T, Abi>, typename Detail::ReturnType< \
223 Vector<T, Abi>, U>::type>::value && \
224 std::is_convertible< \
225 U, typename Detail::ReturnType<Vector<T, Abi>, U>::type>::value, \
226 typename Detail::ReturnType<Vector<T, Abi>, U>::type::Mask> \
227 operator op_(Vector<T, Abi> x, const U &y) \
229 using V = typename Detail::ReturnType<Vector<T, Abi>, U>::type; \
230 return Detail::operator op_(V(x), V(y)); \
232 template <typename T, typename Abi, typename U> \
233 Vc_ALWAYS_INLINE enable_if< \
234 !Traits::is_simd_vector_internal<U>::value && \
235 std::is_convertible<Vector<T, Abi>, typename Detail::ReturnType< \
236 Vector<T, Abi>, U>::type>::value && \
237 std::is_convertible< \
238 U, typename Detail::ReturnType<Vector<T, Abi>, U>::type>::value, \
239 typename Detail::ReturnType<Vector<T, Abi>, U>::type::Mask> \
240 operator op_(const U &x, Vector<T, Abi> y) \
242 using V = typename Detail::ReturnType<Vector<T, Abi>, U>::type; \
243 return Detail::operator op_(V(x), V(y)); \
246 Vc_ALL_LOGICAL (Vc_LOGICAL_OPERATOR);
247 Vc_ALL_BINARY (Vc_GENERIC_OPERATOR);
248 Vc_ALL_ARITHMETICS(Vc_GENERIC_OPERATOR);
249 Vc_ALL_COMPARES (Vc_COMPARE_OPERATOR);
251 #undef Vc_LOGICAL_OPERATOR
252 #undef Vc_GENERIC_OPERATOR
253 #undef Vc_COMPARE_OPERATOR
254 #undef Vc_INVALID_OPERATOR
257 #endif // COMMON_OPERATORS_H_
The main vector class for expressing data parallelism.