Vc 1.4.5
SIMD Vector Classes for C++
 
Loading...
Searching...
No Matches
operators.h
1/* This file is part of the Vc library. {{{
2Copyright © 2012-2016 Matthias Kretz <kretz@kde.org>
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the names of contributing organizations nor the
12 names of its contributors may be used to endorse or promote products
13 derived from this software without specific prior written permission.
14
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26}}}*/
27
28#ifndef COMMON_OPERATORS_H_
29#define COMMON_OPERATORS_H_
30#include "simdarray.h"
31#include "macros.h"
32
33namespace Vc_VERSIONED_NAMESPACE
34{
35namespace Detail
36{
37template <typename T, typename Abi, typename U>
38enable_if<!std::is_same<T, U>::value, U> is_convertible_to_any_vector(Vector<U, Abi>);
39template <typename T, typename Abi> T is_convertible_to_any_vector(Vector<T, Abi>);
40
41template <typename T, typename U, bool = std::is_integral<T>::value,
42 bool = std::is_integral<U>::value>
43struct FundamentalReturnType;
44template <class T, class U>
45using fundamental_return_t = typename FundamentalReturnType<T, U>::type;
46
47template <typename T, typename U> struct FundamentalReturnType<T, U, false, false> {
48 using type = typename std::conditional<
49 std::is_arithmetic<U>::value,
50 typename std::conditional<(sizeof(T) < sizeof(U)), U, T>::type,
51 // U is not arithmetic, e.g. an enum or a type with e.g. operator int()
52 T>::type;
53};
54template <typename T, typename U> struct FundamentalReturnType<T, U, true, false> {
55 using type = typename std::conditional<
56 std::is_arithmetic<U>::value, U,
57 // U is not arithmetic, e.g. an enum or a type with e.g. operator int()
58 T>::type;
59};
60template <typename T, typename U> struct FundamentalReturnType<T, U, false, true> {
61 using type = T;
62};
63
64template <typename T> struct my_make_signed : public std::make_signed<T> {
65};
66template <> struct my_make_signed<bool> {
67 using type = bool;
68};
69
70template <typename TT, typename UU>
71struct higher_conversion_rank {
72 template <typename A>
73 using fix_sign =
74 typename std::conditional<(std::is_unsigned<TT>::value ||
75 std::is_unsigned<UU>::value),
76 typename std::make_unsigned<A>::type, A>::type;
77 using T = typename my_make_signed<TT>::type;
78 using U = typename my_make_signed<UU>::type;
79 template <typename Test, typename Otherwise>
80 using c = typename std::conditional<std::is_same<T, Test>::value ||
81 std::is_same<U, Test>::value,
82 Test, Otherwise>::type;
83
84 using type = fix_sign<c<long long, c<long, c<int, c<short, c<signed char, void>>>>>>;
85};
86
87template <typename T, typename U> struct FundamentalReturnType<T, U, true, true> {
88 template <bool B, class Then, class E>
89 using c = typename std::conditional<B, Then, E>::type;
90 using type =
91 c<(sizeof(T) > sizeof(U)), T,
92 c<(sizeof(T) < sizeof(U)), U, typename higher_conversion_rank<T, U>::type>>;
93};
94
95template <class V, class T, class Tq, class = void> struct ReturnTypeImpl {
96 // no type => SFINAE
97};
98// 1. Vector × Vector
99template <class T, class U, class Abi, class Uq>
100struct ReturnTypeImpl<Vector<T, Abi>, Vector<U, Abi>, Uq, void> {
101 using type = Vc::Vector<fundamental_return_t<T, U>, Abi>;
102};
103// 2. Vector × int
104template <class T, class Abi, class Uq>
105struct ReturnTypeImpl<Vector<T, Abi>, int, Uq, void> {
106 // conversion from int is always allowed (because its the default when you hardcode a
107 // number)
108 using type = Vc::Vector<T, Abi>;
109};
110// 3. Vector × unsigned
111template <class T, class Abi, class Uq>
112struct ReturnTypeImpl<Vector<T, Abi>, uint, Uq, void> {
113 // conversion from unsigned int is allowed for all integral Vector<T>, but ensures
114 // unsigned result
115 using type = Vc::Vector<
116 typename std::conditional<std::is_integral<T>::value, std::make_unsigned<T>,
117 std::enable_if<true, T>>::type::type,
118 Abi>;
119};
120// 4. Vector × {enum, arithmetic}
121template <class T, class U, class Abi, class Uq>
122struct ReturnTypeImpl<
123 Vector<T, Abi>, U, Uq,
124 enable_if<!std::is_class<U>::value && !std::is_same<U, int>::value &&
125 !std::is_same<U, uint>::value &&
126 Traits::is_valid_vector_argument<fundamental_return_t<T, U>>::value,
127 void>> {
128 using type = Vc::Vector<fundamental_return_t<T, U>, Abi>;
129};
130// 5. Vector × UDT
131template <class T, class U, class Abi, class Uq>
132struct ReturnTypeImpl<
133 Vector<T, Abi>, U, Uq,
134 enable_if<std::is_class<U>::value && !Traits::is_simd_vector<U>::value &&
135 Traits::is_valid_vector_argument<decltype(
136 is_convertible_to_any_vector<T, Abi>(std::declval<Uq>()))>::value,
137 void>> {
138 using type =
140 std::declval<Uq>()))>,
141 Abi>;
142};
143template <class V, class Tq, class T = remove_cvref_t<Tq>>
144using ReturnType = typename ReturnTypeImpl<V, T, Tq>::type;
145
146template <class T> struct is_a_type : public std::true_type {
147};
148
149#ifdef Vc_ENABLE_FLOAT_BIT_OPERATORS
150#define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) true
151#else
152#define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) \
153 Detail::is_a_type<decltype(std::declval<typename R::value_type>() \
154 op_ std::declval<typename R::value_type>())>::value
155#endif
156} // namespace Detail
157
158#define Vc_GENERIC_OPERATOR(op_) \
159 template <class T, class Abi, class U, \
160 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
161 Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
162 std::is_convertible<Vector<T, Abi>, R>::value && \
163 std::is_convertible<U, R>::value, \
164 R> \
165 operator op_(Vector<T, Abi> x, U &&y) \
166 { \
167 return Detail::operator op_(R(x), R(std::forward<U>(y))); \
168 } \
169 template <class T, class Abi, class U, \
170 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
171 Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
172 !Traits::is_simd_vector<U>::value && \
173 std::is_convertible<Vector<T, Abi>, R>::value && \
174 std::is_convertible<U, R>::value, \
175 R> \
176 operator op_(U &&x, Vector<T, Abi> y) \
177 { \
178 return Detail::operator op_(R(std::forward<U>(x)), R(y)); \
179 } \
180 template <class T, class Abi, class U, \
181 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
182 Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
183 std::is_convertible<Vector<T, Abi>, R>::value && \
184 std::is_convertible<U, R>::value, \
185 Vector<T, Abi> &> \
186 operator op_##=(Vector<T, Abi> &x, U &&y) \
187 { \
188 x = Detail::operator op_(R(x), R(std::forward<U>(y))); \
189 return x; \
190 }
191
192#define Vc_LOGICAL_OPERATOR(op_) \
193 template <class T, class Abi> \
194 Vc_ALWAYS_INLINE typename Vector<T, Abi>::Mask operator op_(Vector<T, Abi> x, \
195 Vector<T, Abi> y) \
196 { \
197 return !!x op_ !!y; \
198 } \
199 template <class T, class Abi, class U> \
200 Vc_ALWAYS_INLINE \
201 enable_if<std::is_convertible<Vector<T, Abi>, Vector<U, Abi>>::value && \
202 std::is_convertible<Vector<U, Abi>, Vector<T, Abi>>::value, \
203 typename Detail::ReturnType<Vector<T, Abi>, Vector<U, Abi>>::Mask> \
204 operator op_(Vector<T, Abi> x, Vector<U, Abi> y) \
205 { \
206 return !!x op_ !!y; \
207 } \
208 template <class T, class Abi, class U> \
209 Vc_ALWAYS_INLINE enable_if<std::is_same<bool, decltype(!std::declval<U>())>::value, \
210 typename Vector<T, Abi>::Mask> \
211 operator op_(Vector<T, Abi> x, U &&y) \
212 { \
213 using M = typename Vector<T, Abi>::Mask; \
214 return !!x op_ M(!!std::forward<U>(y)); \
215 } \
216 template <class T, class Abi, class U> \
217 Vc_ALWAYS_INLINE enable_if<std::is_same<bool, decltype(!std::declval<U>())>::value, \
218 typename Vector<T, Abi>::Mask> \
219 operator op_(U &&x, Vector<T, Abi> y) \
220 { \
221 using M = typename Vector<T, Abi>::Mask; \
222 return M(!!std::forward<U>(x)) op_ !!y; \
223 }
224
225#define Vc_COMPARE_OPERATOR(op_) \
226 template <class T, class Abi, class U, \
227 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
228 Vc_ALWAYS_INLINE enable_if<std::is_convertible<Vector<T, Abi>, R>::value && \
229 std::is_convertible<U, R>::value, \
230 typename R::Mask> \
231 operator op_(Vector<T, Abi> x, U &&y) \
232 { \
233 return Detail::operator op_(R(x), R(std::forward<U>(y))); \
234 } \
235 template <class T, class Abi, class U, \
236 class R = Detail::ReturnType<Vector<T, Abi>, U>> \
237 Vc_ALWAYS_INLINE \
238 enable_if<!Traits::is_simd_vector_internal<remove_cvref_t<U>>::value && \
239 std::is_convertible<Vector<T, Abi>, R>::value && \
240 std::is_convertible<U, R>::value, \
241 typename R::Mask> \
242 operator op_(U &&x, Vector<T, Abi> y) \
243 { \
244 return Detail::operator op_(R(std::forward<U>(x)), R(y)); \
245 }
246
247Vc_ALL_LOGICAL (Vc_LOGICAL_OPERATOR);
248Vc_ALL_BINARY (Vc_GENERIC_OPERATOR);
249Vc_ALL_ARITHMETICS(Vc_GENERIC_OPERATOR);
250Vc_ALL_COMPARES (Vc_COMPARE_OPERATOR);
251
252#undef Vc_LOGICAL_OPERATOR
253#undef Vc_GENERIC_OPERATOR
254#undef Vc_COMPARE_OPERATOR
255#undef Vc_INVALID_OPERATOR
256
257} // namespace Vc
258#endif // COMMON_OPERATORS_H_
The main vector class for expressing data parallelism.
Definition vector.h:126
unsigned int uint
unsigned int shorthand
Definition types.h:56