Vc  1.4.0
SIMD Vector Classes for C++
operators.h
1 /* This file is part of the Vc library. {{{
2 Copyright © 2012-2016 Matthias Kretz <kretz@kde.org>
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, 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 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON 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
24 SOFTWARE, 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 
33 namespace Vc_VERSIONED_NAMESPACE
34 {
35 namespace Detail
36 {
37 template <typename T, typename Abi, typename U>
38 enable_if<!std::is_same<T, U>::value, U> is_convertible_to_any_vector(Vector<U, Abi>);
39 template <typename T, typename Abi> T is_convertible_to_any_vector(Vector<T, Abi>);
40 
41 template <typename T, typename U, bool = std::is_integral<T>::value,
42  bool = std::is_integral<U>::value>
43 struct FundamentalReturnType;
44 template <class T, class U>
45 using fundamental_return_t = typename FundamentalReturnType<T, U>::type;
46 
47 template <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 };
54 template <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 };
60 template <typename T, typename U> struct FundamentalReturnType<T, U, false, true> {
61  using type = T;
62 };
63 
64 template <typename T> struct my_make_signed : public std::make_signed<T> {
65 };
66 template <> struct my_make_signed<bool> {
67  using type = bool;
68 };
69 
70 template <typename TT, typename UU>
71 struct 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 
87 template <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 
95 template <class V, class T, class = void> struct ReturnTypeImpl {
96  // no type => SFINAE
97 };
98 // 1. Vector × Vector
99 template <class T, class U, class Abi>
100 struct ReturnTypeImpl<Vector<T, Abi>, Vector<U, Abi>, void> {
101  using type = Vc::Vector<fundamental_return_t<T, U>, Abi>;
102 };
103 // 2. Vector × int
104 template <class T, class Abi> struct ReturnTypeImpl<Vector<T, Abi>, int, void> {
105  // conversion from int is always allowed (because its the default when you hardcode a
106  // number)
107  using type = Vc::Vector<T, Abi>;
108 };
109 // 3. Vector × unsigned
110 template <class T, class Abi> struct ReturnTypeImpl<Vector<T, Abi>, uint, void> {
111  // conversion from unsigned int is allowed for all integral Vector<T>, but ensures
112  // unsigned result
113  using type = Vc::Vector<
114  typename std::conditional<std::is_integral<T>::value, std::make_unsigned<T>,
115  std::enable_if<true, T>>::type::type,
116  Abi>;
117 };
118 // 4. Vector × {enum, arithmetic}
119 template <class T, class U, class Abi>
120 struct ReturnTypeImpl<
121  Vector<T, Abi>, U,
122  enable_if<!std::is_class<U>::value && !std::is_same<U, int>::value &&
123  !std::is_same<U, uint>::value &&
124  Traits::is_valid_vector_argument<fundamental_return_t<T, U>>::value,
125  void>> {
126  using type = Vc::Vector<fundamental_return_t<T, U>, Abi>;
127 };
128 // 5. Vector × UDT
129 template <class T, class U, class Abi>
130 struct ReturnTypeImpl<
131  Vector<T, Abi>, U,
132  enable_if<
133  std::is_class<U>::value && !Traits::is_simd_vector<U>::value &&
134  Traits::is_valid_vector_argument<decltype(
135  is_convertible_to_any_vector<T, Abi>(std::declval<const U &>()))>::value,
136  void>> {
137  using type =
139  std::declval<const U &>()))>,
140  Abi>;
141 };
142 template <class V, class T> using ReturnType = typename ReturnTypeImpl<V, T>::type;
143 
144 template <class T> struct is_a_type : public std::true_type {
145 };
146 
147 #ifdef Vc_ENABLE_FLOAT_BIT_OPERATORS
148 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) true
149 #else
150 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) \
151  Detail::is_a_type<decltype(std::declval<typename R::value_type>() \
152  op_ std::declval<typename R::value_type>())>::value
153 #endif
154 } // namespace Detail
155 
156 #define Vc_GENERIC_OPERATOR(op_) \
157  template <class T, class Abi, class U, \
158  class R = Detail::ReturnType<Vector<T, Abi>, U>> \
159  Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
160  std::is_convertible<Vector<T, Abi>, R>::value && \
161  std::is_convertible<U, R>::value, \
162  R> \
163  operator op_(Vector<T, Abi> x, const U &y) \
164  { \
165  return Detail::operator op_(R(x), R(y)); \
166  } \
167  template <class T, class Abi, class U, \
168  class R = Detail::ReturnType<Vector<T, Abi>, U>> \
169  Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
170  !Traits::is_simd_vector<U>::value && \
171  std::is_convertible<Vector<T, Abi>, R>::value && \
172  std::is_convertible<U, R>::value, \
173  R> \
174  operator op_(const U &x, Vector<T, Abi> y) \
175  { \
176  return Detail::operator op_(R(x), R(y)); \
177  } \
178  template <class T, class Abi, class U, \
179  class R = Detail::ReturnType<Vector<T, Abi>, U>> \
180  Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) && \
181  std::is_convertible<Vector<T, Abi>, R>::value && \
182  std::is_convertible<U, R>::value, \
183  Vector<T, Abi> &> \
184  operator op_##=(Vector<T, Abi> &x, const U &y) \
185  { \
186  x = Detail::operator op_(R(x), R(y)); \
187  return x; \
188  }
189 
190 #define Vc_LOGICAL_OPERATOR(op_) \
191  template <class T, class Abi> \
192  Vc_ALWAYS_INLINE typename Vector<T, Abi>::Mask operator op_(Vector<T, Abi> x, \
193  Vector<T, Abi> y) \
194  { \
195  return !!x op_ !!y; \
196  } \
197  template <class T, class Abi, class U> \
198  Vc_ALWAYS_INLINE \
199  enable_if<std::is_convertible<Vector<T, Abi>, Vector<U, Abi>>::value && \
200  std::is_convertible<Vector<U, Abi>, Vector<T, Abi>>::value, \
201  typename Detail::ReturnType<Vector<T, Abi>, Vector<U, Abi>>::Mask> \
202  operator op_(Vector<T, Abi> x, Vector<U, Abi> y) \
203  { \
204  return !!x op_ !!y; \
205  } \
206  template <class T, class Abi, class U> \
207  Vc_ALWAYS_INLINE \
208  enable_if<std::is_same<bool, decltype(!std::declval<const U &>())>::value, \
209  typename Vector<T, Abi>::Mask> \
210  operator op_(Vector<T, Abi> x, const U &y) \
211  { \
212  using M = typename Vector<T, Abi>::Mask; \
213  return !!x op_ M(!!y); \
214  } \
215  template <class T, class Abi, class U> \
216  Vc_ALWAYS_INLINE \
217  enable_if<std::is_same<bool, decltype(!std::declval<const U &>())>::value, \
218  typename Vector<T, Abi>::Mask> \
219  operator op_(const U &x, Vector<T, Abi> y) \
220  { \
221  using M = typename Vector<T, Abi>::Mask; \
222  return M(!!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, const U &y) \
232  { \
233  return Detail::operator op_(R(x), R(y)); \
234  } \
235  template <class T, class Abi, class U, \
236  class R = Detail::ReturnType<Vector<T, Abi>, U>> \
237  Vc_ALWAYS_INLINE enable_if<!Traits::is_simd_vector_internal<U>::value && \
238  std::is_convertible<Vector<T, Abi>, R>::value && \
239  std::is_convertible<U, R>::value, \
240  typename R::Mask> \
241  operator op_(const U &x, Vector<T, Abi> y) \
242  { \
243  return Detail::operator op_(R(x), R(y)); \
244  }
245 
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);
250 
251 #undef Vc_LOGICAL_OPERATOR
252 #undef Vc_GENERIC_OPERATOR
253 #undef Vc_COMPARE_OPERATOR
254 #undef Vc_INVALID_OPERATOR
255 
256 } // namespace Vc
257 #endif // COMMON_OPERATORS_H_
unsigned int uint
unsigned int shorthand
Definition: types.h:55
The main vector class for expressing data parallelism.
Definition: fwddecl.h:53
Definition: vector.h:249