Warning, file /include/Vc/common/operators.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifndef COMMON_OPERATORS_H_
0029 #define COMMON_OPERATORS_H_
0030 #include "simdarray.h"
0031 #include "macros.h"
0032
0033 namespace Vc_VERSIONED_NAMESPACE
0034 {
0035 namespace Detail
0036 {
0037 template <typename T, typename Abi, typename U>
0038 enable_if<!std::is_same<T, U>::value, U> is_convertible_to_any_vector(Vector<U, Abi>);
0039 template <typename T, typename Abi> T is_convertible_to_any_vector(Vector<T, Abi>);
0040
0041 template <typename T, typename U, bool = std::is_integral<T>::value,
0042 bool = std::is_integral<U>::value>
0043 struct FundamentalReturnType;
0044 template <class T, class U>
0045 using fundamental_return_t = typename FundamentalReturnType<T, U>::type;
0046
0047 template <typename T, typename U> struct FundamentalReturnType<T, U, false, false> {
0048 using type = typename std::conditional<
0049 std::is_arithmetic<U>::value,
0050 typename std::conditional<(sizeof(T) < sizeof(U)), U, T>::type,
0051
0052 T>::type;
0053 };
0054 template <typename T, typename U> struct FundamentalReturnType<T, U, true, false> {
0055 using type = typename std::conditional<
0056 std::is_arithmetic<U>::value, U,
0057
0058 T>::type;
0059 };
0060 template <typename T, typename U> struct FundamentalReturnType<T, U, false, true> {
0061 using type = T;
0062 };
0063
0064 template <typename T> struct my_make_signed : public std::make_signed<T> {
0065 };
0066 template <> struct my_make_signed<bool> {
0067 using type = bool;
0068 };
0069
0070 template <typename TT, typename UU>
0071 struct higher_conversion_rank {
0072 template <typename A>
0073 using fix_sign =
0074 typename std::conditional<(std::is_unsigned<TT>::value ||
0075 std::is_unsigned<UU>::value),
0076 typename std::make_unsigned<A>::type, A>::type;
0077 using T = typename my_make_signed<TT>::type;
0078 using U = typename my_make_signed<UU>::type;
0079 template <typename Test, typename Otherwise>
0080 using c = typename std::conditional<std::is_same<T, Test>::value ||
0081 std::is_same<U, Test>::value,
0082 Test, Otherwise>::type;
0083
0084 using type = fix_sign<c<long long, c<long, c<int, c<short, c<signed char, void>>>>>>;
0085 };
0086
0087 template <typename T, typename U> struct FundamentalReturnType<T, U, true, true> {
0088 template <bool B, class Then, class E>
0089 using c = typename std::conditional<B, Then, E>::type;
0090 using type =
0091 c<(sizeof(T) > sizeof(U)), T,
0092 c<(sizeof(T) < sizeof(U)), U, typename higher_conversion_rank<T, U>::type>>;
0093 };
0094
0095 template <class V, class T, class Tq, class = void> struct ReturnTypeImpl {
0096
0097 };
0098
0099 template <class T, class U, class Abi, class Uq>
0100 struct ReturnTypeImpl<Vector<T, Abi>, Vector<U, Abi>, Uq, void> {
0101 using type = Vc::Vector<fundamental_return_t<T, U>, Abi>;
0102 };
0103
0104 template <class T, class Abi, class Uq>
0105 struct ReturnTypeImpl<Vector<T, Abi>, int, Uq, void> {
0106
0107
0108 using type = Vc::Vector<T, Abi>;
0109 };
0110
0111 template <class T, class Abi, class Uq>
0112 struct ReturnTypeImpl<Vector<T, Abi>, uint, Uq, void> {
0113
0114
0115 using type = Vc::Vector<
0116 typename std::conditional<std::is_integral<T>::value, std::make_unsigned<T>,
0117 std::enable_if<true, T>>::type::type,
0118 Abi>;
0119 };
0120
0121 template <class T, class U, class Abi, class Uq>
0122 struct ReturnTypeImpl<
0123 Vector<T, Abi>, U, Uq,
0124 enable_if<!std::is_class<U>::value && !std::is_same<U, int>::value &&
0125 !std::is_same<U, uint>::value &&
0126 Traits::is_valid_vector_argument<fundamental_return_t<T, U>>::value,
0127 void>> {
0128 using type = Vc::Vector<fundamental_return_t<T, U>, Abi>;
0129 };
0130
0131 template <class T, class U, class Abi, class Uq>
0132 struct ReturnTypeImpl<
0133 Vector<T, Abi>, U, Uq,
0134 enable_if<std::is_class<U>::value && !Traits::is_simd_vector<U>::value &&
0135 Traits::is_valid_vector_argument<decltype(
0136 is_convertible_to_any_vector<T, Abi>(std::declval<Uq>()))>::value,
0137 void>> {
0138 using type =
0139 Vc::Vector<fundamental_return_t<T, decltype(is_convertible_to_any_vector<T, Abi>(
0140 std::declval<Uq>()))>,
0141 Abi>;
0142 };
0143 template <class V, class Tq, class T = remove_cvref_t<Tq>>
0144 using ReturnType = typename ReturnTypeImpl<V, T, Tq>::type;
0145
0146 template <class T> struct is_a_type : public std::true_type {
0147 };
0148
0149 #ifdef Vc_ENABLE_FLOAT_BIT_OPERATORS
0150 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) true
0151 #else
0152 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) \
0153 Detail::is_a_type<decltype(std::declval<typename R::value_type>() \
0154 op_ std::declval<typename R::value_type>())>::value
0155 #endif
0156 }
0157
0158 #define Vc_GENERIC_OPERATOR(op_) \
0159 template <class T, class Abi, class U, \
0160 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
0161 Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
0162 std::is_convertible<Vector<T, Abi>, R>::value && \
0163 std::is_convertible<U, R>::value, \
0164 R> \
0165 operator op_(Vector<T, Abi> x, U &&y) \
0166 { \
0167 return Detail::operator op_(R(x), R(std::forward<U>(y))); \
0168 } \
0169 template <class T, class Abi, class U, \
0170 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
0171 Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
0172 !Traits::is_simd_vector<U>::value && \
0173 std::is_convertible<Vector<T, Abi>, R>::value && \
0174 std::is_convertible<U, R>::value, \
0175 R> \
0176 operator op_(U &&x, Vector<T, Abi> y) \
0177 { \
0178 return Detail::operator op_(R(std::forward<U>(x)), R(y)); \
0179 } \
0180 template <class T, class Abi, class U, \
0181 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
0182 Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
0183 std::is_convertible<Vector<T, Abi>, R>::value && \
0184 std::is_convertible<U, R>::value, \
0185 Vector<T, Abi> &> \
0186 operator op_##=(Vector<T, Abi> &x, U &&y) \
0187 { \
0188 x = Detail::operator op_(R(x), R(std::forward<U>(y))); \
0189 return x; \
0190 }
0191
0192 #define Vc_LOGICAL_OPERATOR(op_) \
0193 template <class T, class Abi> \
0194 Vc_ALWAYS_INLINE typename Vector<T, Abi>::Mask operator op_(Vector<T, Abi> x, \
0195 Vector<T, Abi> y) \
0196 { \
0197 return !!x op_ !!y; \
0198 } \
0199 template <class T, class Abi, class U> \
0200 Vc_ALWAYS_INLINE \
0201 enable_if<std::is_convertible<Vector<T, Abi>, Vector<U, Abi>>::value && \
0202 std::is_convertible<Vector<U, Abi>, Vector<T, Abi>>::value, \
0203 typename Detail::ReturnType<Vector<T, Abi>, Vector<U, Abi>>::Mask> \
0204 operator op_(Vector<T, Abi> x, Vector<U, Abi> y) \
0205 { \
0206 return !!x op_ !!y; \
0207 } \
0208 template <class T, class Abi, class U> \
0209 Vc_ALWAYS_INLINE enable_if<std::is_same<bool, decltype(!std::declval<U>())>::value, \
0210 typename Vector<T, Abi>::Mask> \
0211 operator op_(Vector<T, Abi> x, U &&y) \
0212 { \
0213 using M = typename Vector<T, Abi>::Mask; \
0214 return !!x op_ M(!!std::forward<U>(y)); \
0215 } \
0216 template <class T, class Abi, class U> \
0217 Vc_ALWAYS_INLINE enable_if<std::is_same<bool, decltype(!std::declval<U>())>::value, \
0218 typename Vector<T, Abi>::Mask> \
0219 operator op_(U &&x, Vector<T, Abi> y) \
0220 { \
0221 using M = typename Vector<T, Abi>::Mask; \
0222 return M(!!std::forward<U>(x)) op_ !!y; \
0223 }
0224
0225 #define Vc_COMPARE_OPERATOR(op_) \
0226 template <class T, class Abi, class U, \
0227 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
0228 Vc_ALWAYS_INLINE enable_if<std::is_convertible<Vector<T, Abi>, R>::value && \
0229 std::is_convertible<U, R>::value, \
0230 typename R::Mask> \
0231 operator op_(Vector<T, Abi> x, U &&y) \
0232 { \
0233 return Detail::operator op_(R(x), R(std::forward<U>(y))); \
0234 } \
0235 template <class T, class Abi, class U, \
0236 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
0237 Vc_ALWAYS_INLINE \
0238 enable_if<!Traits::is_simd_vector_internal<remove_cvref_t<U>>::value && \
0239 std::is_convertible<Vector<T, Abi>, R>::value && \
0240 std::is_convertible<U, R>::value, \
0241 typename R::Mask> \
0242 operator op_(U &&x, Vector<T, Abi> y) \
0243 { \
0244 return Detail::operator op_(R(std::forward<U>(x)), R(y)); \
0245 }
0246
0247 Vc_ALL_LOGICAL (Vc_LOGICAL_OPERATOR);
0248 Vc_ALL_BINARY (Vc_GENERIC_OPERATOR);
0249 Vc_ALL_ARITHMETICS(Vc_GENERIC_OPERATOR);
0250 Vc_ALL_COMPARES (Vc_COMPARE_OPERATOR);
0251
0252 #undef Vc_LOGICAL_OPERATOR
0253 #undef Vc_GENERIC_OPERATOR
0254 #undef Vc_COMPARE_OPERATOR
0255 #undef Vc_INVALID_OPERATOR
0256
0257 }
0258 #endif