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