File indexing completed on 2025-01-30 10:25:47
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