]> git.uio.no Git - u/mrichter/AliRoot.git/blame - Vc/include/Vc/common/macros.h
- support compilation with GCC 4.1 and 4.2
[u/mrichter/AliRoot.git] / Vc / include / Vc / common / macros.h
CommitLineData
f22341db 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#ifdef VC_MSVC
27# define ALIGN(n) __declspec(align(n))
28# define STRUCT_ALIGN1(n) ALIGN(n)
29# define STRUCT_ALIGN2(n)
30# define ALIGNED_TYPEDEF(n, _type_, _newType_) typedef ALIGN(n) _type_ _newType_
31#else
32# define ALIGN(n) __attribute__((aligned(n)))
33# define STRUCT_ALIGN1(n)
34# define STRUCT_ALIGN2(n) ALIGN(n)
35# define ALIGNED_TYPEDEF(n, _type_, _newType_) typedef _type_ _newType_ ALIGN(n)
36#endif
37
38#define FREE_STORE_OPERATORS_ALIGNED(alignment) \
39 void *operator new(size_t size) { return _mm_malloc(size, alignment); } \
40 void *operator new(size_t, void *p) { return p; } \
41 void *operator new[](size_t size) { return _mm_malloc(size, alignment); } \
42 void operator delete(void *ptr, size_t) { _mm_free(ptr); } \
43 void operator delete[](void *ptr, size_t) { _mm_free(ptr); }
44
45#ifdef VC_CLANG
46# define INTRINSIC __attribute__((always_inline))
47# define INTRINSIC_L
48# define INTRINSIC_R INTRINSIC
49# define FLATTEN
50# define CONST __attribute__((const))
51# define CONST_L
52# define CONST_R CONST
53# define PURE __attribute__((pure))
54# define PURE_L
55# define PURE_R PURE
56# define MAY_ALIAS __attribute__((may_alias))
57# define ALWAYS_INLINE __attribute__((always_inline))
58# define ALWAYS_INLINE_L
59# define ALWAYS_INLINE_R ALWAYS_INLINE
60# define VC_IS_UNLIKELY(x) __builtin_expect(x, 0)
61# define VC_IS_LIKELY(x) __builtin_expect(x, 1)
62# define VC_RESTRICT __restrict__
63#elif defined(__GNUC__)
6936ae04 64# if VC_GCC < 0x40300 || defined(VC_OPEN64)
65// GCC 4.1 and 4.2 ICE on may_alias. Since Open64 uses the GCC 4.2 frontend it has the same problem.
66# define MAY_ALIAS
67# else
68# define MAY_ALIAS __attribute__((__may_alias__))
69# endif
70# if VC_GCC < 0x40200
71// GCC 4.1 fails with "sorry unimplemented: inlining failed"
72# define INTRINSIC __attribute__((__flatten__))
73# elif VC_GCC < 0x40300 || defined(VC_OPEN64)
74// the GCC 4.2 frontend doesn't know the __artificial__ attribute
f22341db 75# define INTRINSIC __attribute__((__flatten__, __always_inline__))
76# else
77# define INTRINSIC __attribute__((__flatten__, __always_inline__, __artificial__))
78# endif
79# define INTRINSIC_L
80# define INTRINSIC_R INTRINSIC
81# define FLATTEN __attribute__((__flatten__))
82# define CONST __attribute__((__const__))
83# define CONST_L
84# define CONST_R CONST
85# define PURE __attribute__((__pure__))
86# define PURE_L
87# define PURE_R PURE
f22341db 88# define ALWAYS_INLINE __attribute__((__always_inline__))
89# define ALWAYS_INLINE_L
90# define ALWAYS_INLINE_R ALWAYS_INLINE
91# define VC_IS_UNLIKELY(x) __builtin_expect(x, 0)
92# define VC_IS_LIKELY(x) __builtin_expect(x, 1)
93# define VC_RESTRICT __restrict__
94#else
95# define FLATTEN
96# ifdef PURE
97# undef PURE
98# endif
99# define MAY_ALIAS
100# ifdef VC_MSVC
101# define ALWAYS_INLINE __forceinline
102# define ALWAYS_INLINE_L ALWAYS_INLINE
103# define ALWAYS_INLINE_R
104# define CONST __declspec(noalias)
105# define CONST_L CONST
106# define CONST_R
107# define PURE /*CONST*/
108# define PURE_L PURE
109# define PURE_R
110# define INTRINSIC __forceinline
111# define INTRINSIC_L INTRINSIC
112# define INTRINSIC_R
113# else
114# define ALWAYS_INLINE
115# define ALWAYS_INLINE_L
116# define ALWAYS_INLINE_R
117# define CONST
118# define CONST_L
119# define CONST_R
120# define PURE
121# define PURE_L
122# define PURE_R
123# define INTRINSIC
124# define INTRINSIC_L
125# define INTRINSIC_R
126# endif
127# define VC_IS_UNLIKELY(x) x
128# define VC_IS_LIKELY(x) x
129# define VC_RESTRICT __restrict
130#endif
131
132#if __cplusplus >= 201103 /*C++11*/
133#define _VC_CONSTEXPR constexpr
134#define _VC_CONSTEXPR_L _VC_CONSTEXPR
135#define _VC_CONSTEXPR_R
136#else
137#define _VC_CONSTEXPR inline INTRINSIC CONST
138#define _VC_CONSTEXPR_L inline INTRINSIC_L CONST_R
139#define _VC_CONSTEXPR_R INTRINSIC_R CONST_R
140#endif
141
142#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && VC_GCC >= 0x40600) || __cplusplus >= 201103
143# define _VC_NOEXCEPT noexcept
144#else
145# define _VC_NOEXCEPT throw()
146#endif
147
148
149#ifdef VC_GCC
150# define VC_WARN_INLINE
151# define VC_WARN(msg) __attribute__((warning("\n\t" msg)))
152#else
153# define VC_WARN_INLINE inline
154# define VC_WARN(msg)
155#endif
156
157#define unrolled_loop16(_it_, _start_, _end_, _code_) \
158if (_start_ + 0 < _end_) { enum { _it_ = (_start_ + 0) < _end_ ? (_start_ + 0) : _start_ }; _code_ } \
159if (_start_ + 1 < _end_) { enum { _it_ = (_start_ + 1) < _end_ ? (_start_ + 1) : _start_ }; _code_ } \
160if (_start_ + 2 < _end_) { enum { _it_ = (_start_ + 2) < _end_ ? (_start_ + 2) : _start_ }; _code_ } \
161if (_start_ + 3 < _end_) { enum { _it_ = (_start_ + 3) < _end_ ? (_start_ + 3) : _start_ }; _code_ } \
162if (_start_ + 4 < _end_) { enum { _it_ = (_start_ + 4) < _end_ ? (_start_ + 4) : _start_ }; _code_ } \
163if (_start_ + 5 < _end_) { enum { _it_ = (_start_ + 5) < _end_ ? (_start_ + 5) : _start_ }; _code_ } \
164if (_start_ + 6 < _end_) { enum { _it_ = (_start_ + 6) < _end_ ? (_start_ + 6) : _start_ }; _code_ } \
165if (_start_ + 7 < _end_) { enum { _it_ = (_start_ + 7) < _end_ ? (_start_ + 7) : _start_ }; _code_ } \
166if (_start_ + 8 < _end_) { enum { _it_ = (_start_ + 8) < _end_ ? (_start_ + 8) : _start_ }; _code_ } \
167if (_start_ + 9 < _end_) { enum { _it_ = (_start_ + 9) < _end_ ? (_start_ + 9) : _start_ }; _code_ } \
168if (_start_ + 10 < _end_) { enum { _it_ = (_start_ + 10) < _end_ ? (_start_ + 10) : _start_ }; _code_ } \
169if (_start_ + 11 < _end_) { enum { _it_ = (_start_ + 11) < _end_ ? (_start_ + 11) : _start_ }; _code_ } \
170if (_start_ + 12 < _end_) { enum { _it_ = (_start_ + 12) < _end_ ? (_start_ + 12) : _start_ }; _code_ } \
171if (_start_ + 13 < _end_) { enum { _it_ = (_start_ + 13) < _end_ ? (_start_ + 13) : _start_ }; _code_ } \
172if (_start_ + 14 < _end_) { enum { _it_ = (_start_ + 14) < _end_ ? (_start_ + 14) : _start_ }; _code_ } \
173if (_start_ + 15 < _end_) { enum { _it_ = (_start_ + 15) < _end_ ? (_start_ + 15) : _start_ }; _code_ } \
174do {} while ( false )
175
176#define for_all_vector_entries(_it_, _code_) \
177 unrolled_loop16(_it_, 0, Size, _code_)
178
179#ifdef NDEBUG
180#define VC_ASSERT(x)
181#else
182#include <assert.h>
183#define VC_ASSERT(x) assert(x);
184#endif
185
186#ifdef VC_CLANG
187#define VC_HAS_BUILTIN(x) __has_builtin(x)
188#else
189#define VC_HAS_BUILTIN(x) 0
190#endif
191
192#ifndef VC_COMMON_MACROS_H_ONCE
193#define VC_COMMON_MACROS_H_ONCE
194
195#define _VC_CAT_HELPER(a, b, c, d) a##b##c##d
196#define _VC_CAT(a, b, c, d) _VC_CAT_HELPER(a, b, c, d)
197
198#if __cplusplus >= 201103 /*C++11*/ || VC_MSVC >= 160000000
199#define VC_STATIC_ASSERT_NC(cond, msg) \
200 static_assert(cond, #msg)
201#define VC_STATIC_ASSERT(cond, msg) VC_STATIC_ASSERT_NC(cond, msg)
202#else // C++98
203namespace Vc {
204 namespace {
205 template<bool> struct STATIC_ASSERT_FAILURE;
206 template<> struct STATIC_ASSERT_FAILURE<true> {};
207}}
208
209#define VC_STATIC_ASSERT_NC(cond, msg) \
210 typedef STATIC_ASSERT_FAILURE<cond> _VC_CAT(static_assert_failed_on_line_,__LINE__,_,msg); \
211 enum { \
212 _VC_CAT(static_assert_failed__on_line_,__LINE__,_,msg) = sizeof(_VC_CAT(static_assert_failed_on_line_,__LINE__,_,msg)) \
213 }
214#define VC_STATIC_ASSERT(cond, msg) VC_STATIC_ASSERT_NC(cond, msg)
215#endif // C++11/98
216
217 template<int e, int center> struct exponentToMultiplier { enum {
218 X = exponentToMultiplier<e - 1, center>::X * ((e - center < 31) ? 2 : 1),
219 Value = (X == 0 ? 1 : X)
220 }; };
221 template<int center> struct exponentToMultiplier<center,center> { enum { X = 1, Value = X }; };
222 template<int center> struct exponentToMultiplier< -1, center> { enum { X = 0 }; };
223 template<int center> struct exponentToMultiplier< -256, center> { enum { X = 0 }; };
224 template<int center> struct exponentToMultiplier< -512, center> { enum { X = 0 }; };
225 template<int center> struct exponentToMultiplier<-1024, center> { enum { X = 0 }; };
226
227 template<int e> struct exponentToDivisor { enum {
228 X = exponentToDivisor<e + 1>::X * 2,
229 Value = (X == 0 ? 1 : X)
230 }; };
231 template<> struct exponentToDivisor<0> { enum { X = 1, Value = X }; };
232 template<> struct exponentToDivisor<256> { enum { X = 0 }; };
233 template<> struct exponentToDivisor<512> { enum { X = 0 }; };
234 template<> struct exponentToDivisor<1024> { enum { X = 0 }; };
235#endif // VC_COMMON_MACROS_H_ONCE
236
237#define _CAT_IMPL(a, b) a##b
238#define CAT(a, b) _CAT_IMPL(a, b)
239
240#define Vc_buildDouble(sign, mantissa, exponent) \
241 ((static_cast<double>((mantissa & 0x000fffffffffffffull) | 0x0010000000000000ull) / 0x0010000000000000ull) \
242 * exponentToMultiplier<exponent, 0>::Value \
243 * exponentToMultiplier<exponent, 30>::Value \
244 * exponentToMultiplier<exponent, 60>::Value \
245 * exponentToMultiplier<exponent, 90>::Value \
246 / exponentToDivisor<exponent>::Value \
247 * static_cast<double>(sign))
248#define Vc_buildFloat(sign, mantissa, exponent) \
249 ((static_cast<float>((mantissa & 0x007fffffu) | 0x00800000) / 0x00800000) \
250 * exponentToMultiplier<exponent, 0>::Value \
251 * exponentToMultiplier<exponent, 30>::Value \
252 * exponentToMultiplier<exponent, 60>::Value \
253 * exponentToMultiplier<exponent, 90>::Value \
254 / exponentToDivisor<exponent>::Value \
255 * static_cast<float>(sign))
256
257#define _VC_APPLY_IMPL_1(macro, a, b, c, d, e) macro(a)
258#define _VC_APPLY_IMPL_2(macro, a, b, c, d, e) macro(a, b)
259#define _VC_APPLY_IMPL_3(macro, a, b, c, d, e) macro(a, b, c)
260#define _VC_APPLY_IMPL_4(macro, a, b, c, d, e) macro(a, b, c, d)
261#define _VC_APPLY_IMPL_5(macro, a, b, c, d, e) macro(a, b, c, d, e)
262
263#define VC_LIST_FLOAT_VECTOR_TYPES(size, macro, a, b, c, d) \
264 size(macro, double_v, a, b, c, d) \
265 size(macro, float_v, a, b, c, d) \
266 size(macro, sfloat_v, a, b, c, d)
267#define VC_LIST_INT_VECTOR_TYPES(size, macro, a, b, c, d) \
268 size(macro, int_v, a, b, c, d) \
269 size(macro, uint_v, a, b, c, d) \
270 size(macro, short_v, a, b, c, d) \
271 size(macro, ushort_v, a, b, c, d)
272#define VC_LIST_VECTOR_TYPES(size, macro, a, b, c, d) \
273 VC_LIST_FLOAT_VECTOR_TYPES(size, macro, a, b, c, d) \
274 VC_LIST_INT_VECTOR_TYPES(size, macro, a, b, c, d)
275#define VC_LIST_COMPARES(size, macro, a, b, c, d) \
276 size(macro, ==, a, b, c, d) \
277 size(macro, !=, a, b, c, d) \
278 size(macro, <=, a, b, c, d) \
279 size(macro, >=, a, b, c, d) \
280 size(macro, < , a, b, c, d) \
281 size(macro, > , a, b, c, d)
282#define VC_LIST_LOGICAL(size, macro, a, b, c, d) \
283 size(macro, &&, a, b, c, d) \
284 size(macro, ||, a, b, c, d)
285#define VC_LIST_BINARY(size, macro, a, b, c, d) \
286 size(macro, |, a, b, c, d) \
287 size(macro, &, a, b, c, d) \
288 size(macro, ^, a, b, c, d)
289#define VC_LIST_SHIFTS(size, macro, a, b, c, d) \
290 size(macro, <<, a, b, c, d) \
291 size(macro, >>, a, b, c, d)
292#define VC_LIST_ARITHMETICS(size, macro, a, b, c, d) \
293 size(macro, +, a, b, c, d) \
294 size(macro, -, a, b, c, d) \
295 size(macro, *, a, b, c, d) \
296 size(macro, /, a, b, c, d) \
297 size(macro, %, a, b, c, d)
298
299#define VC_APPLY_0(_list, macro) _list(_VC_APPLY_IMPL_1, macro, 0, 0, 0, 0)
300#define VC_APPLY_1(_list, macro, a) _list(_VC_APPLY_IMPL_2, macro, a, 0, 0, 0)
301#define VC_APPLY_2(_list, macro, a, b) _list(_VC_APPLY_IMPL_3, macro, a, b, 0, 0)
302#define VC_APPLY_3(_list, macro, a, b, c) _list(_VC_APPLY_IMPL_4, macro, a, b, c, 0)
303#define VC_APPLY_4(_list, macro, a, b, c, d) _list(_VC_APPLY_IMPL_5, macro, a, b, c, d)
304
305#define VC_ALL_COMPARES(macro) VC_APPLY_0(VC_LIST_COMPARES, macro)
306#define VC_ALL_LOGICAL(macro) VC_APPLY_0(VC_LIST_LOGICAL, macro)
307#define VC_ALL_BINARY(macro) VC_APPLY_0(VC_LIST_BINARY, macro)
308#define VC_ALL_SHIFTS(macro) VC_APPLY_0(VC_LIST_SHIFTS, macro)
309#define VC_ALL_ARITHMETICS(macro) VC_APPLY_0(VC_LIST_ARITHMETICS, macro)
310#define VC_ALL_FLOAT_VECTOR_TYPES(macro) VC_APPLY_0(VC_LIST_FLOAT_VECTOR_TYPES, macro)
311#define VC_ALL_VECTOR_TYPES(macro) VC_APPLY_0(VC_LIST_VECTOR_TYPES, macro)
312
313#define VC_EXACT_TYPE(_test, _reference, _type) \
314 typename EnableIf<IsEqualType<_test, _reference>::Value, _type>::Value
315
316#endif // VC_COMMON_MACROS_H