31 namespace Vc_VERSIONED_NAMESPACE
35 template <
bool C,
typename T,
typename F>
36 using conditional_t =
typename std::conditional<C, T, F>::type;
38 using std::is_convertible;
39 using std::is_floating_point;
40 using std::is_integral;
43 template <
typename T> constexpr
bool isUnsigned()
45 return !std::is_same<Traits::decay<T>,
bool>::value && Traits::is_unsigned<T>::value;
47 template <
typename T> constexpr
bool isIntegral()
49 return Traits::is_integral<T>::value;
51 template <
typename T> constexpr
bool isVector()
53 return Traits::is_simd_vector_internal<Traits::decay<T>>::value;
56 template <
typename T,
bool = isIntegral<T>(),
bool = isVector<T>()>
57 struct MakeUnsignedInternal;
58 template <
template <
typename,
typename>
class Vector__,
typename T,
typename Abi>
59 struct MakeUnsignedInternal<Vector__<T, Abi>, true, true>
61 using type = Vector__<typename std::make_unsigned<T>::type, Abi>;
63 template <
typename T>
struct MakeUnsignedInternal<T, false, true>
68 template <
typename Test,
typename T>
69 using CopyUnsigned =
typename MakeUnsignedInternal<T, isIntegral<T>() && isUnsigned<Test>()>::type;
85 template <
typename From,
typename To> constexpr
bool isNarrowingFloatConversion()
87 return is_floating_point<From>::value &&
88 (is_integral<To>::value || (is_floating_point<To>::value &&
sizeof(From) >
sizeof(To)));
91 template <
typename T>
static constexpr
bool convertsToSomeVector()
93 return is_convertible<T, double_v>::value || is_convertible<T, float_v>::value ||
94 is_convertible<T, int_v>::value || is_convertible<T, uint_v>::value ||
95 is_convertible<T, short_v>::value || is_convertible<T, ushort_v>::value;
98 static_assert(isNarrowingFloatConversion<double, float>(),
"");
99 static_assert(isNarrowingFloatConversion<long double, float>(),
"");
100 static_assert(isNarrowingFloatConversion<long double, double>(),
"");
101 static_assert(is_convertible<double, float_v>::value,
"");
102 static_assert(
false == ((is_convertible<double, float_v>::value ||
103 (isVector<double>() && is_convertible<float_v, double>::value)) &&
104 !isNarrowingFloatConversion<double, float_v::EntryType>()),
107 template <
typename V,
typename W>
108 using DetermineReturnType =
109 conditional_t<(is_same<V, int_v>::value || is_same<V, uint_v>::value) &&
110 (is_same<W, float>::value || is_same<W, float_v>::value),
114 template <
typename V,
typename W> constexpr
bool participateInOverloadResolution()
116 return isVector<V>() &&
117 !is_same<V, W>::value &&
119 convertsToSomeVector<W>();
124 template <
typename V,
typename W> constexpr enable_if<isVector<V>(),
bool> isValidOperandTypes()
128 ? (is_convertible<V, W>::value || is_convertible<W, V>::value)
129 : (is_convertible<W, DetermineReturnType<V, W>>::value &&
130 !isNarrowingFloatConversion<W, typename DetermineReturnType<V, W>::EntryType>());
136 bool VectorOperation = participateInOverloadResolution<V, W>() && isValidOperandTypes<V, W>()>
137 struct TypesForOperatorInternal
141 template <
typename V,
typename W>
struct TypesForOperatorInternal<V, W, true>
143 using type = DetermineReturnType<V, W>;
146 template <
typename L,
typename R>
147 using TypesForOperator =
typename TypesForOperatorInternal<
148 Traits::decay<conditional_t<isVector<L>(), L, R>>,
149 Traits::decay<conditional_t<!isVector<L>(), L, R>>>::type;
154 bool IsIncorrect = participateInOverloadResolution<V, W>() && !isValidOperandTypes<V, W>()>
155 struct IsIncorrectVectorOperands
158 template <
typename V,
typename W>
struct IsIncorrectVectorOperands<V, W, true>
163 template <
typename L,
typename R>
164 using Vc_does_not_allow_operands_to_a_binary_operator_which_can_have_different_SIMD_register_sizes_on_some_targets_and_thus_enforces_portability =
165 typename IsIncorrectVectorOperands<
166 Traits::decay<conditional_t<isVector<L>(), L, R>>,
167 Traits::decay<conditional_t<!isVector<L>(), L, R>>>::type;
170 #define Vc_GENERIC_OPERATOR(op) \
171 template <typename L, typename R> \
172 Vc_ALWAYS_INLINE Common::TypesForOperator<L, R> operator op(L &&x, R &&y) \
174 using V = Common::TypesForOperator<L, R>; \
175 return V(std::forward<L>(x)) op V(std::forward<R>(y)); \
178 #define Vc_COMPARE_OPERATOR(op) \
179 template <typename L, typename R> \
180 Vc_ALWAYS_INLINE typename Common::TypesForOperator<L, R>::Mask operator op(L &&x, \
183 using V = Common::TypesForOperator<L, R>; \
184 return V(std::forward<L>(x)) op V(std::forward<R>(y)); \
187 #define Vc_INVALID_OPERATOR(op) \
188 template <typename L, typename R> \
190 Vc_does_not_allow_operands_to_a_binary_operator_which_can_have_different_SIMD_register_sizes_on_some_targets_and_thus_enforces_portability< \
191 L, R> operator op(L &&, R &&) = delete;
195 Vc_ALL_LOGICAL (Vc_GENERIC_OPERATOR)
196 Vc_ALL_BINARY (Vc_GENERIC_OPERATOR)
197 Vc_ALL_ARITHMETICS(Vc_GENERIC_OPERATOR)
198 Vc_ALL_COMPARES (Vc_COMPARE_OPERATOR)
200 Vc_ALL_LOGICAL (Vc_INVALID_OPERATOR)
201 Vc_ALL_BINARY (Vc_INVALID_OPERATOR)
202 Vc_ALL_ARITHMETICS(Vc_INVALID_OPERATOR)
203 Vc_ALL_COMPARES (Vc_INVALID_OPERATOR)
205 #undef Vc_GENERIC_OPERATOR
206 #undef Vc_COMPARE_OPERATOR
207 #undef Vc_INVALID_OPERATOR
Vector< float > float_v
vector of single precision