ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
macros.h
Go to the documentation of this file.
1 /* This file is part of the Vc library.
2 
3  Copyright (C) 2010-2012 Matthias Kretz <kretz@kde.org>
4 
5  Vc is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as
7  published by the Free Software Foundation, either version 3 of
8  the License, or (at your option) any later version.
9 
10  Vc is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with Vc. If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 
20 #ifndef VC_COMMON_MACROS_H
21 #define VC_COMMON_MACROS_H
22 #undef VC_COMMON_UNDOMACROS_H
23 
24 #include <Vc/global.h>
25 
26 #if defined(VC_GCC) && !defined(__OPTIMIZE__)
27 # if VC_GCC >= 0x40500
28 # pragma GCC diagnostic push
29 # define Vc_POP_GCC_DIAGNOSTIC__ 1
30 # endif
31 // GCC uses lots of old-style-casts in macros that disguise as intrinsics
32 # pragma GCC diagnostic ignored "-Wold-style-cast"
33 #endif
34 
35 #ifdef VC_MSVC
36 # define ALIGN(n) __declspec(align(n))
37 # define STRUCT_ALIGN1(n) ALIGN(n)
38 # define STRUCT_ALIGN2(n)
39 # define ALIGNED_TYPEDEF(n, _type_, _newType_) typedef ALIGN(n) _type_ _newType_
40 #else
41 # define ALIGN(n) __attribute__((aligned(n)))
42 # define STRUCT_ALIGN1(n)
43 # define STRUCT_ALIGN2(n) ALIGN(n)
44 # define ALIGNED_TYPEDEF(n, _type_, _newType_) typedef _type_ _newType_ ALIGN(n)
45 #endif
46 
47 #ifdef VC_CXX11
48 #define Vc_ALIGNOF(_TYPE_) alignof(_TYPE_)
49 #else
50 #define Vc_ALIGNOF(_TYPE_) __alignof(_TYPE_)
51 #endif
52 
53 #ifdef VC_CLANG
54 # define Vc_INTRINSIC_L inline
55 # define Vc_INTRINSIC_R __attribute__((always_inline))
56 # define Vc_INTRINSIC Vc_INTRINSIC_L Vc_INTRINSIC_R
57 # define Vc_FLATTEN
58 # define Vc_CONST __attribute__((const))
59 # define Vc_CONST_L
60 # define Vc_CONST_R Vc_CONST
61 # define Vc_PURE __attribute__((pure))
62 # define Vc_PURE_L
63 # define Vc_PURE_R Vc_PURE
64 # define Vc_MAY_ALIAS __attribute__((may_alias))
65 # define Vc_ALWAYS_INLINE_L inline
66 # define Vc_ALWAYS_INLINE_R __attribute__((always_inline))
67 # define Vc_ALWAYS_INLINE Vc_ALWAYS_INLINE_L Vc_ALWAYS_INLINE_R
68 # define VC_IS_UNLIKELY(x) __builtin_expect(x, 0)
69 # define VC_IS_LIKELY(x) __builtin_expect(x, 1)
70 # define VC_RESTRICT __restrict__
71 # define VC_DEPRECATED(msg)
72 #elif defined(__GNUC__)
73 # if (defined(VC_GCC) && VC_GCC < 0x40300) || defined(VC_OPEN64)
74 // GCC 4.1 and 4.2 ICE on may_alias. Since Open64 uses the GCC 4.2 frontend it has the same problem.
75 # define Vc_MAY_ALIAS
76 # else
77 # define Vc_MAY_ALIAS __attribute__((__may_alias__))
78 # endif
79 # if (defined(VC_GCC) && VC_GCC < 0x40300)
80 // GCC 4.1 fails with "sorry unimplemented: inlining failed"
81 # define Vc_INTRINSIC_R __attribute__((__flatten__))
82 # elif defined(VC_OPEN64)
83 // the GCC 4.2 frontend doesn't know the __artificial__ attribute
84 # define Vc_INTRINSIC_R __attribute__((__flatten__, __always_inline__))
85 # else
86 # define Vc_INTRINSIC_R __attribute__((__flatten__, __always_inline__, __artificial__))
87 # endif
88 # define Vc_INTRINSIC_L inline
89 # define Vc_INTRINSIC Vc_INTRINSIC_L Vc_INTRINSIC_R
90 # define Vc_FLATTEN __attribute__((__flatten__))
91 # define Vc_ALWAYS_INLINE_L inline
92 # define Vc_ALWAYS_INLINE_R __attribute__((__always_inline__))
93 # define Vc_ALWAYS_INLINE Vc_ALWAYS_INLINE_L Vc_ALWAYS_INLINE_R
94 # ifdef VC_ICC
95  // ICC miscompiles if there are functions marked as pure or const
96 # define Vc_PURE
97 # define Vc_CONST
98 # else
99 # define Vc_PURE __attribute__((__pure__))
100 # define Vc_CONST __attribute__((__const__))
101 # endif
102 # define Vc_CONST_L
103 # define Vc_CONST_R Vc_CONST
104 # define Vc_PURE_L
105 # define Vc_PURE_R Vc_PURE
106 # define VC_IS_UNLIKELY(x) __builtin_expect(x, 0)
107 # define VC_IS_LIKELY(x) __builtin_expect(x, 1)
108 # define VC_RESTRICT __restrict__
109 # define VC_DEPRECATED(msg) __attribute__((__deprecated__(msg)))
110 #else
111 # define Vc_FLATTEN
112 # ifdef Vc_PURE
113 # undef Vc_PURE
114 # endif
115 # define Vc_MAY_ALIAS
116 # ifdef VC_MSVC
117 # define Vc_ALWAYS_INLINE inline __forceinline
118 # define Vc_ALWAYS_INLINE_L Vc_ALWAYS_INLINE
119 # define Vc_ALWAYS_INLINE_R
120 # define Vc_CONST __declspec(noalias)
121 # define Vc_CONST_L Vc_CONST
122 # define Vc_CONST_R
123 # define Vc_PURE /*Vc_CONST*/
124 # define Vc_PURE_L Vc_PURE
125 # define Vc_PURE_R
126 # define Vc_INTRINSIC inline __forceinline
127 # define Vc_INTRINSIC_L Vc_INTRINSIC
128 # define Vc_INTRINSIC_R
129 # else
130 # define Vc_ALWAYS_INLINE
131 # define Vc_ALWAYS_INLINE_L
132 # define Vc_ALWAYS_INLINE_R
133 # define Vc_CONST
134 # define Vc_CONST_L
135 # define Vc_CONST_R
136 # define Vc_PURE
137 # define Vc_PURE_L
138 # define Vc_PURE_R
139 # define Vc_INTRINSIC
140 # define Vc_INTRINSIC_L
141 # define Vc_INTRINSIC_R
142 # endif
143 # define VC_IS_UNLIKELY(x) x
144 # define VC_IS_LIKELY(x) x
145 # define VC_RESTRICT __restrict
146 # define VC_DEPRECATED(msg) __declspec(deprecated(msg))
147 #endif
148 
149 #if __cplusplus >= 201103 /*C++11*/
150 #define _VC_CONSTEXPR constexpr
151 #define _VC_CONSTEXPR_L _VC_CONSTEXPR
152 #define _VC_CONSTEXPR_R
153 #else
154 #define _VC_CONSTEXPR Vc_INTRINSIC Vc_CONST
155 #define _VC_CONSTEXPR_L Vc_INTRINSIC_L Vc_CONST_L
156 #define _VC_CONSTEXPR_R Vc_INTRINSIC_R Vc_CONST_R
157 #endif
158 
159 #ifdef VC_CXX11
160 # define _VC_NOEXCEPT noexcept
161 #else
162 # define _VC_NOEXCEPT throw()
163 #endif
164 
165 #define FREE_STORE_OPERATORS_ALIGNED(alignment) \
166  Vc_ALWAYS_INLINE void *operator new(size_t size) { return _mm_malloc(size, alignment); } \
167  Vc_ALWAYS_INLINE void *operator new(size_t, void *p) { return p; } \
168  Vc_ALWAYS_INLINE void *operator new[](size_t size) { return _mm_malloc(size, alignment); } \
169  Vc_ALWAYS_INLINE void *operator new[](size_t , void *p) { return p; } \
170  Vc_ALWAYS_INLINE void operator delete(void *ptr, size_t) { _mm_free(ptr); } \
171  Vc_ALWAYS_INLINE void operator delete(void *, void *) {} \
172  Vc_ALWAYS_INLINE void operator delete[](void *ptr, size_t) { _mm_free(ptr); } \
173  Vc_ALWAYS_INLINE void operator delete[](void *, void *) {}
174 
175 #ifdef VC_GCC
176 # define VC_WARN_INLINE
177 # define VC_WARN(msg) __attribute__((warning("\n\t" msg)))
178 #else
179 # define VC_WARN_INLINE inline
180 # define VC_WARN(msg)
181 #endif
182 
183 #define unrolled_loop16(_it_, _start_, _end_, _code_) \
184 if (_start_ + 0 < _end_) { enum { _it_ = (_start_ + 0) < _end_ ? (_start_ + 0) : _start_ }; _code_ } \
185 if (_start_ + 1 < _end_) { enum { _it_ = (_start_ + 1) < _end_ ? (_start_ + 1) : _start_ }; _code_ } \
186 if (_start_ + 2 < _end_) { enum { _it_ = (_start_ + 2) < _end_ ? (_start_ + 2) : _start_ }; _code_ } \
187 if (_start_ + 3 < _end_) { enum { _it_ = (_start_ + 3) < _end_ ? (_start_ + 3) : _start_ }; _code_ } \
188 if (_start_ + 4 < _end_) { enum { _it_ = (_start_ + 4) < _end_ ? (_start_ + 4) : _start_ }; _code_ } \
189 if (_start_ + 5 < _end_) { enum { _it_ = (_start_ + 5) < _end_ ? (_start_ + 5) : _start_ }; _code_ } \
190 if (_start_ + 6 < _end_) { enum { _it_ = (_start_ + 6) < _end_ ? (_start_ + 6) : _start_ }; _code_ } \
191 if (_start_ + 7 < _end_) { enum { _it_ = (_start_ + 7) < _end_ ? (_start_ + 7) : _start_ }; _code_ } \
192 if (_start_ + 8 < _end_) { enum { _it_ = (_start_ + 8) < _end_ ? (_start_ + 8) : _start_ }; _code_ } \
193 if (_start_ + 9 < _end_) { enum { _it_ = (_start_ + 9) < _end_ ? (_start_ + 9) : _start_ }; _code_ } \
194 if (_start_ + 10 < _end_) { enum { _it_ = (_start_ + 10) < _end_ ? (_start_ + 10) : _start_ }; _code_ } \
195 if (_start_ + 11 < _end_) { enum { _it_ = (_start_ + 11) < _end_ ? (_start_ + 11) : _start_ }; _code_ } \
196 if (_start_ + 12 < _end_) { enum { _it_ = (_start_ + 12) < _end_ ? (_start_ + 12) : _start_ }; _code_ } \
197 if (_start_ + 13 < _end_) { enum { _it_ = (_start_ + 13) < _end_ ? (_start_ + 13) : _start_ }; _code_ } \
198 if (_start_ + 14 < _end_) { enum { _it_ = (_start_ + 14) < _end_ ? (_start_ + 14) : _start_ }; _code_ } \
199 if (_start_ + 15 < _end_) { enum { _it_ = (_start_ + 15) < _end_ ? (_start_ + 15) : _start_ }; _code_ } \
200 do {} while ( false )
201 
202 #define for_all_vector_entries(_it_, _code_) \
203  unrolled_loop16(_it_, 0, Size, _code_)
204 
205 #ifdef VC_ASSERT
206 #define VC_EXTERNAL_ASSERT 1
207 #else
208 #ifdef NDEBUG
209 #define VC_ASSERT(x)
210 #else
211 #include <assert.h>
212 #define VC_ASSERT(x) assert(x);
213 #endif
214 #endif
215 
216 #ifdef VC_CLANG
217 #define VC_HAS_BUILTIN(x) __has_builtin(x)
218 #else
219 #define VC_HAS_BUILTIN(x) 0
220 #endif
221 
222 #ifndef VC_COMMON_MACROS_H_ONCE
223 #define VC_COMMON_MACROS_H_ONCE
224 
225 #define _VC_CAT_HELPER(a, b, c, d) a##b##c##d
226 #define _VC_CAT(a, b, c, d) _VC_CAT_HELPER(a, b, c, d)
227 
228 #if __cplusplus >= 201103 /*C++11*/ || (defined(VC_MSVC) && VC_MSVC >= 160000000)
229 #define VC_STATIC_ASSERT_NC(cond, msg) \
230  static_assert(cond, #msg)
231 #define VC_STATIC_ASSERT(cond, msg) VC_STATIC_ASSERT_NC(cond, msg)
232 #else // C++98
233 namespace ROOT {
234 namespace Vc {
235  namespace {
236  template<bool> struct STATIC_ASSERT_FAILURE;
237  template<> struct STATIC_ASSERT_FAILURE<true> {};
238 }}
239 } // namespace ROOT
240 
241 #define VC_STATIC_ASSERT_NC(cond, msg) \
242  typedef STATIC_ASSERT_FAILURE<cond> _VC_CAT(static_assert_failed_on_line_,__LINE__,_,msg); \
243  enum { \
244  _VC_CAT(static_assert_failed__on_line_,__LINE__,_,msg) = sizeof(_VC_CAT(static_assert_failed_on_line_,__LINE__,_,msg)) \
245  }
246 #define VC_STATIC_ASSERT(cond, msg) VC_STATIC_ASSERT_NC(cond, msg)
247 #endif // C++11/98
248 
249  template<int e, int center> struct exponentToMultiplier { enum Values__ {
250  X = exponentToMultiplier<e - 1, center>::X * ((e - center < 31) ? 2 : 1),
251  Value = (X == 0 ? 1 : X)
252  }; };
253  template<int center> struct exponentToMultiplier<center,center> { enum Values__ { X = 1, Value = X }; };
254  template<int center> struct exponentToMultiplier< -1, center> { enum Values__ { X = 0, Value = 1 }; };
255  template<int center> struct exponentToMultiplier< -128, center> { enum Values__ { X = 0, Value = 1 }; };
256  template<int center> struct exponentToMultiplier< -256, center> { enum Values__ { X = 0, Value = 1 }; };
257  template<int center> struct exponentToMultiplier< -384, center> { enum Values__ { X = 0, Value = 1 }; };
258  template<int center> struct exponentToMultiplier< -512, center> { enum Values__ { X = 0, Value = 1 }; };
259  template<int center> struct exponentToMultiplier< -640, center> { enum Values__ { X = 0, Value = 1 }; };
260  template<int center> struct exponentToMultiplier< -768, center> { enum Values__ { X = 0, Value = 1 }; };
261  template<int center> struct exponentToMultiplier< -896, center> { enum Values__ { X = 0, Value = 1 }; };
262  template<int center> struct exponentToMultiplier<-1024, center> { enum Values__ { X = 0, Value = 1 }; };
263 
264  template<int e, int center> struct exponentToDivisor { enum Values__ {
265  X = exponentToDivisor<e + 1, center>::X * ((center - e < 31) ? 2 : 1),
266  Value = (X == 0 ? 1 : X)
267  }; };
268  template<int center> struct exponentToDivisor<center, center> { enum Values__ { X = 1, Value = X }; };
269  template<int center> struct exponentToDivisor< 1, center> { enum Values__ { X = 0, Value = 1 }; };
270  template<int center> struct exponentToDivisor< 128, center> { enum Values__ { X = 0, Value = 1 }; };
271  template<int center> struct exponentToDivisor< 256, center> { enum Values__ { X = 0, Value = 1 }; };
272  template<int center> struct exponentToDivisor< 384, center> { enum Values__ { X = 0, Value = 1 }; };
273  template<int center> struct exponentToDivisor< 512, center> { enum Values__ { X = 0, Value = 1 }; };
274  template<int center> struct exponentToDivisor< 640, center> { enum Values__ { X = 0, Value = 1 }; };
275  template<int center> struct exponentToDivisor< 768, center> { enum Values__ { X = 0, Value = 1 }; };
276  template<int center> struct exponentToDivisor< 896, center> { enum Values__ { X = 0, Value = 1 }; };
277  template<int center> struct exponentToDivisor< 1024, center> { enum Values__ { X = 0, Value = 1 }; };
278 #endif // VC_COMMON_MACROS_H_ONCE
279 
280 #define _CAT_IMPL(a, b) a##b
281 #define CAT(a, b) _CAT_IMPL(a, b)
282 
283 #define Vc_buildDouble(sign, mantissa, exponent) \
284  ((static_cast<double>((mantissa & 0x000fffffffffffffull) | 0x0010000000000000ull) / 0x0010000000000000ull) \
285  * exponentToMultiplier<exponent, 0>::Value \
286  * exponentToMultiplier<exponent, 30>::Value \
287  * exponentToMultiplier<exponent, 60>::Value \
288  * exponentToMultiplier<exponent, 90>::Value \
289  / exponentToDivisor<exponent, 0>::Value \
290  / exponentToDivisor<exponent, -30>::Value \
291  / exponentToDivisor<exponent, -60>::Value \
292  / exponentToDivisor<exponent, -90>::Value \
293  * static_cast<double>(sign))
294 #define Vc_buildFloat(sign, mantissa, exponent) \
295  ((static_cast<float>((mantissa & 0x007fffffu) | 0x00800000) / 0x00800000) \
296  * exponentToMultiplier<exponent, 0>::Value \
297  * exponentToMultiplier<exponent, 30>::Value \
298  * exponentToMultiplier<exponent, 60>::Value \
299  * exponentToMultiplier<exponent, 90>::Value \
300  / exponentToDivisor<exponent, 0>::Value \
301  / exponentToDivisor<exponent, -30>::Value \
302  / exponentToDivisor<exponent, -60>::Value \
303  / exponentToDivisor<exponent, -90>::Value \
304  * static_cast<float>(sign))
305 
306 #define _VC_APPLY_IMPL_1(macro, a, b, c, d, e) macro(a)
307 #define _VC_APPLY_IMPL_2(macro, a, b, c, d, e) macro(a, b)
308 #define _VC_APPLY_IMPL_3(macro, a, b, c, d, e) macro(a, b, c)
309 #define _VC_APPLY_IMPL_4(macro, a, b, c, d, e) macro(a, b, c, d)
310 #define _VC_APPLY_IMPL_5(macro, a, b, c, d, e) macro(a, b, c, d, e)
311 
312 #define VC_LIST_FLOAT_VECTOR_TYPES(size, macro, a, b, c, d) \
313  size(macro, double_v, a, b, c, d) \
314  size(macro, float_v, a, b, c, d) \
315  size(macro, sfloat_v, a, b, c, d)
316 #define VC_LIST_INT_VECTOR_TYPES(size, macro, a, b, c, d) \
317  size(macro, int_v, a, b, c, d) \
318  size(macro, uint_v, a, b, c, d) \
319  size(macro, short_v, a, b, c, d) \
320  size(macro, ushort_v, a, b, c, d)
321 #define VC_LIST_VECTOR_TYPES(size, macro, a, b, c, d) \
322  VC_LIST_FLOAT_VECTOR_TYPES(size, macro, a, b, c, d) \
323  VC_LIST_INT_VECTOR_TYPES(size, macro, a, b, c, d)
324 #define VC_LIST_COMPARES(size, macro, a, b, c, d) \
325  size(macro, ==, a, b, c, d) \
326  size(macro, !=, a, b, c, d) \
327  size(macro, <=, a, b, c, d) \
328  size(macro, >=, a, b, c, d) \
329  size(macro, < , a, b, c, d) \
330  size(macro, > , a, b, c, d)
331 #define VC_LIST_LOGICAL(size, macro, a, b, c, d) \
332  size(macro, &&, a, b, c, d) \
333  size(macro, ||, a, b, c, d)
334 #define VC_LIST_BINARY(size, macro, a, b, c, d) \
335  size(macro, |, a, b, c, d) \
336  size(macro, &, a, b, c, d) \
337  size(macro, ^, a, b, c, d)
338 #define VC_LIST_SHIFTS(size, macro, a, b, c, d) \
339  size(macro, <<, a, b, c, d) \
340  size(macro, >>, a, b, c, d)
341 #define VC_LIST_ARITHMETICS(size, macro, a, b, c, d) \
342  size(macro, +, a, b, c, d) \
343  size(macro, -, a, b, c, d) \
344  size(macro, *, a, b, c, d) \
345  size(macro, /, a, b, c, d) \
346  size(macro, %, a, b, c, d)
347 
348 #define VC_APPLY_0(_list, macro) _list(_VC_APPLY_IMPL_1, macro, 0, 0, 0, 0)
349 #define VC_APPLY_1(_list, macro, a) _list(_VC_APPLY_IMPL_2, macro, a, 0, 0, 0)
350 #define VC_APPLY_2(_list, macro, a, b) _list(_VC_APPLY_IMPL_3, macro, a, b, 0, 0)
351 #define VC_APPLY_3(_list, macro, a, b, c) _list(_VC_APPLY_IMPL_4, macro, a, b, c, 0)
352 #define VC_APPLY_4(_list, macro, a, b, c, d) _list(_VC_APPLY_IMPL_5, macro, a, b, c, d)
353 
354 #define VC_ALL_COMPARES(macro) VC_APPLY_0(VC_LIST_COMPARES, macro)
355 #define VC_ALL_LOGICAL(macro) VC_APPLY_0(VC_LIST_LOGICAL, macro)
356 #define VC_ALL_BINARY(macro) VC_APPLY_0(VC_LIST_BINARY, macro)
357 #define VC_ALL_SHIFTS(macro) VC_APPLY_0(VC_LIST_SHIFTS, macro)
358 #define VC_ALL_ARITHMETICS(macro) VC_APPLY_0(VC_LIST_ARITHMETICS, macro)
359 #define VC_ALL_FLOAT_VECTOR_TYPES(macro) VC_APPLY_0(VC_LIST_FLOAT_VECTOR_TYPES, macro)
360 #define VC_ALL_VECTOR_TYPES(macro) VC_APPLY_0(VC_LIST_VECTOR_TYPES, macro)
361 
362 #define VC_EXACT_TYPE(_test, _reference, _type) \
363  typename EnableIf<IsEqualType<_test, _reference>::Value, _type>::Value
364 
365 #ifdef VC_PASSING_VECTOR_BY_VALUE_IS_BROKEN
366 #define VC_ALIGNED_PARAMETER(_Type) const _Type &
367 #else
368 #define VC_ALIGNED_PARAMETER(_Type) const _Type
369 #endif
370 
371 #ifndef Vc__make_unique
372 #define Vc__make_unique(name) _VC_CAT(Vc__,name,_,__LINE__)
373 #endif
374 
375 #if defined(VC_ICC) || defined(VC_CLANG)
376 #define VC_OFFSETOF(Type, member) (reinterpret_cast<const char *>(&reinterpret_cast<const Type *>(0)->member) - reinterpret_cast<const char *>(0))
377 #elif defined(VC_GCC) && VC_GCC < 0x40500
378 #define VC_OFFSETOF(Type, member) (reinterpret_cast<const char *>(&reinterpret_cast<const Type *>(0x1000)->member) - reinterpret_cast<const char *>(0x1000))
379 #else
380 #define VC_OFFSETOF(Type, member) offsetof(Type, member)
381 #endif
382 
383 
384 #endif // VC_COMMON_MACROS_H