1
/* This file is part of the Vc library.
3
Copyright (C) 2010-2012 Matthias Kretz <kretz@kde.org>
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.
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.
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/>.
20
#ifndef VC_COMMON_MACROS_H
21
#define VC_COMMON_MACROS_H
22
#undef VC_COMMON_UNDOMACROS_H
24
#include <Vc/global.h>
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"
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_
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)
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); }
52
#define Vc_ALIGNOF(_TYPE_) alignof(_TYPE_)
54
#define Vc_ALIGNOF(_TYPE_) __alignof(_TYPE_)
58
# define Vc_INTRINSIC_L inline
59
# define Vc_INTRINSIC_R __attribute__((always_inline))
60
# define Vc_INTRINSIC Vc_INTRINSIC_L Vc_INTRINSIC_R
62
# define Vc_CONST __attribute__((const))
64
# define Vc_CONST_R Vc_CONST
65
# define Vc_PURE __attribute__((pure))
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 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.
81
# define Vc_MAY_ALIAS __attribute__((__may_alias__))
84
// GCC 4.1 fails with "sorry unimplemented: inlining failed"
85
# define Vc_INTRINSIC_R __attribute__((__flatten__))
86
# elif VC_GCC < 0x40300 || defined(VC_OPEN64)
87
// the GCC 4.2 frontend doesn't know the __artificial__ attribute
88
# define Vc_INTRINSIC_R __attribute__((__flatten__, __always_inline__))
90
# define Vc_INTRINSIC_R __attribute__((__flatten__, __always_inline__, __artificial__))
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
99
// ICC miscompiles if there are functions marked as pure or const
103
# define Vc_PURE __attribute__((__pure__))
104
# define Vc_CONST __attribute__((__const__))
107
# define Vc_CONST_R Vc_CONST
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)))
119
# define Vc_MAY_ALIAS
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
127
# define Vc_PURE /*Vc_CONST*/
128
# define Vc_PURE_L Vc_PURE
130
# define Vc_INTRINSIC inline __forceinline
131
# define Vc_INTRINSIC_L Vc_INTRINSIC
132
# define Vc_INTRINSIC_R
134
# define Vc_ALWAYS_INLINE
135
# define Vc_ALWAYS_INLINE_L
136
# define Vc_ALWAYS_INLINE_R
143
# define Vc_INTRINSIC
144
# define Vc_INTRINSIC_L
145
# define Vc_INTRINSIC_R
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))
153
#if __cplusplus >= 201103 /*C++11*/
154
#define _VC_CONSTEXPR constexpr
155
#define _VC_CONSTEXPR_L _VC_CONSTEXPR
156
#define _VC_CONSTEXPR_R
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
164
# define _VC_NOEXCEPT noexcept
166
# define _VC_NOEXCEPT throw()
171
# define VC_WARN_INLINE
172
# define VC_WARN(msg) __attribute__((warning("\n\t" msg)))
174
# define VC_WARN_INLINE inline
175
# define VC_WARN(msg)
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 )
197
#define for_all_vector_entries(_it_, _code_) \
198
unrolled_loop16(_it_, 0, Size, _code_)
204
#define VC_ASSERT(x) assert(x);
208
#define VC_HAS_BUILTIN(x) __has_builtin(x)
210
#define VC_HAS_BUILTIN(x) 0
213
#ifndef VC_COMMON_MACROS_H_ONCE
214
#define VC_COMMON_MACROS_H_ONCE
216
#define _VC_CAT_HELPER(a, b, c, d) a##b##c##d
217
#define _VC_CAT(a, b, c, d) _VC_CAT_HELPER(a, b, c, d)
219
#if __cplusplus >= 201103 /*C++11*/ || (defined(VC_MSVC) && VC_MSVC >= 160000000)
220
#define VC_STATIC_ASSERT_NC(cond, msg) \
221
static_assert(cond, #msg)
222
#define VC_STATIC_ASSERT(cond, msg) VC_STATIC_ASSERT_NC(cond, msg)
226
template<bool> struct STATIC_ASSERT_FAILURE;
227
template<> struct STATIC_ASSERT_FAILURE<true> {};
230
#define VC_STATIC_ASSERT_NC(cond, msg) \
231
typedef STATIC_ASSERT_FAILURE<cond> _VC_CAT(static_assert_failed_on_line_,__LINE__,_,msg); \
233
_VC_CAT(static_assert_failed__on_line_,__LINE__,_,msg) = sizeof(_VC_CAT(static_assert_failed_on_line_,__LINE__,_,msg)) \
235
#define VC_STATIC_ASSERT(cond, msg) VC_STATIC_ASSERT_NC(cond, msg)
238
template<int e, int center> struct exponentToMultiplier { enum {
239
X = exponentToMultiplier<e - 1, center>::X * ((e - center < 31) ? 2 : 1),
240
Value = (X == 0 ? 1 : X)
242
template<int center> struct exponentToMultiplier<center,center> { enum { X = 1, Value = X }; };
243
template<int center> struct exponentToMultiplier< -1, center> { enum { X = 0, Value = 1 }; };
244
template<int center> struct exponentToMultiplier< -256, center> { enum { X = 0, Value = 1 }; };
245
template<int center> struct exponentToMultiplier< -512, center> { enum { X = 0, Value = 1 }; };
246
template<int center> struct exponentToMultiplier<-1024, center> { enum { X = 0, Value = 1 }; };
248
template<int e, int center> struct exponentToDivisor { enum {
249
X = exponentToDivisor<e + 1, center>::X * ((center - e < 31) ? 2 : 1),
250
Value = (X == 0 ? 1 : X)
252
template<int center> struct exponentToDivisor<center, center> { enum { X = 1, Value = X }; };
253
template<int center> struct exponentToDivisor< 1, center> { enum { X = 0, Value = 1 }; };
254
template<int center> struct exponentToDivisor< 256, center> { enum { X = 0, Value = 1 }; };
255
template<int center> struct exponentToDivisor< 512, center> { enum { X = 0, Value = 1 }; };
256
template<int center> struct exponentToDivisor< 1024, center> { enum { X = 0, Value = 1 }; };
257
#endif // VC_COMMON_MACROS_H_ONCE
259
#define _CAT_IMPL(a, b) a##b
260
#define CAT(a, b) _CAT_IMPL(a, b)
262
#define Vc_buildDouble(sign, mantissa, exponent) \
263
((static_cast<double>((mantissa & 0x000fffffffffffffull) | 0x0010000000000000ull) / 0x0010000000000000ull) \
264
* exponentToMultiplier<exponent, 0>::Value \
265
* exponentToMultiplier<exponent, 30>::Value \
266
* exponentToMultiplier<exponent, 60>::Value \
267
* exponentToMultiplier<exponent, 90>::Value \
268
/ exponentToDivisor<exponent, 0>::Value \
269
/ exponentToDivisor<exponent, -30>::Value \
270
/ exponentToDivisor<exponent, -60>::Value \
271
/ exponentToDivisor<exponent, -90>::Value \
272
* static_cast<double>(sign))
273
#define Vc_buildFloat(sign, mantissa, exponent) \
274
((static_cast<float>((mantissa & 0x007fffffu) | 0x00800000) / 0x00800000) \
275
* exponentToMultiplier<exponent, 0>::Value \
276
* exponentToMultiplier<exponent, 30>::Value \
277
* exponentToMultiplier<exponent, 60>::Value \
278
* exponentToMultiplier<exponent, 90>::Value \
279
/ exponentToDivisor<exponent, 0>::Value \
280
/ exponentToDivisor<exponent, -30>::Value \
281
/ exponentToDivisor<exponent, -60>::Value \
282
/ exponentToDivisor<exponent, -90>::Value \
283
* static_cast<float>(sign))
285
#define _VC_APPLY_IMPL_1(macro, a, b, c, d, e) macro(a)
286
#define _VC_APPLY_IMPL_2(macro, a, b, c, d, e) macro(a, b)
287
#define _VC_APPLY_IMPL_3(macro, a, b, c, d, e) macro(a, b, c)
288
#define _VC_APPLY_IMPL_4(macro, a, b, c, d, e) macro(a, b, c, d)
289
#define _VC_APPLY_IMPL_5(macro, a, b, c, d, e) macro(a, b, c, d, e)
291
#define VC_LIST_FLOAT_VECTOR_TYPES(size, macro, a, b, c, d) \
292
size(macro, double_v, a, b, c, d) \
293
size(macro, float_v, a, b, c, d) \
294
size(macro, sfloat_v, a, b, c, d)
295
#define VC_LIST_INT_VECTOR_TYPES(size, macro, a, b, c, d) \
296
size(macro, int_v, a, b, c, d) \
297
size(macro, uint_v, a, b, c, d) \
298
size(macro, short_v, a, b, c, d) \
299
size(macro, ushort_v, a, b, c, d)
300
#define VC_LIST_VECTOR_TYPES(size, macro, a, b, c, d) \
301
VC_LIST_FLOAT_VECTOR_TYPES(size, macro, a, b, c, d) \
302
VC_LIST_INT_VECTOR_TYPES(size, macro, a, b, c, d)
303
#define VC_LIST_COMPARES(size, macro, a, b, c, d) \
304
size(macro, ==, a, b, c, d) \
305
size(macro, !=, a, b, c, d) \
306
size(macro, <=, a, b, c, d) \
307
size(macro, >=, a, b, c, d) \
308
size(macro, < , a, b, c, d) \
309
size(macro, > , a, b, c, d)
310
#define VC_LIST_LOGICAL(size, macro, a, b, c, d) \
311
size(macro, &&, a, b, c, d) \
312
size(macro, ||, a, b, c, d)
313
#define VC_LIST_BINARY(size, macro, a, b, c, d) \
314
size(macro, |, a, b, c, d) \
315
size(macro, &, a, b, c, d) \
316
size(macro, ^, a, b, c, d)
317
#define VC_LIST_SHIFTS(size, macro, a, b, c, d) \
318
size(macro, <<, a, b, c, d) \
319
size(macro, >>, a, b, c, d)
320
#define VC_LIST_ARITHMETICS(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)
327
#define VC_APPLY_0(_list, macro) _list(_VC_APPLY_IMPL_1, macro, 0, 0, 0, 0)
328
#define VC_APPLY_1(_list, macro, a) _list(_VC_APPLY_IMPL_2, macro, a, 0, 0, 0)
329
#define VC_APPLY_2(_list, macro, a, b) _list(_VC_APPLY_IMPL_3, macro, a, b, 0, 0)
330
#define VC_APPLY_3(_list, macro, a, b, c) _list(_VC_APPLY_IMPL_4, macro, a, b, c, 0)
331
#define VC_APPLY_4(_list, macro, a, b, c, d) _list(_VC_APPLY_IMPL_5, macro, a, b, c, d)
333
#define VC_ALL_COMPARES(macro) VC_APPLY_0(VC_LIST_COMPARES, macro)
334
#define VC_ALL_LOGICAL(macro) VC_APPLY_0(VC_LIST_LOGICAL, macro)
335
#define VC_ALL_BINARY(macro) VC_APPLY_0(VC_LIST_BINARY, macro)
336
#define VC_ALL_SHIFTS(macro) VC_APPLY_0(VC_LIST_SHIFTS, macro)
337
#define VC_ALL_ARITHMETICS(macro) VC_APPLY_0(VC_LIST_ARITHMETICS, macro)
338
#define VC_ALL_FLOAT_VECTOR_TYPES(macro) VC_APPLY_0(VC_LIST_FLOAT_VECTOR_TYPES, macro)
339
#define VC_ALL_VECTOR_TYPES(macro) VC_APPLY_0(VC_LIST_VECTOR_TYPES, macro)
341
#define VC_EXACT_TYPE(_test, _reference, _type) \
342
typename EnableIf<IsEqualType<_test, _reference>::Value, _type>::Value
344
#ifdef VC_PASSING_VECTOR_BY_VALUE_IS_BROKEN
345
#define VC_ALIGNED_PARAMETER(_Type) const _Type &
347
#define VC_ALIGNED_PARAMETER(_Type) const _Type
350
#if defined(VC_ICC) || defined(VC_CLANG)
351
#define VC_OFFSETOF(Type, member) (reinterpret_cast<const char *>(&reinterpret_cast<const Type *>(0)->member) - reinterpret_cast<const char *>(0))
352
#elif defined(VC_GCC) && VC_GCC < 0x40500
353
#define VC_OFFSETOF(Type, member) (reinterpret_cast<const char *>(&reinterpret_cast<const Type *>(0x1000)->member) - reinterpret_cast<const char *>(0x1000))
355
#define VC_OFFSETOF(Type, member) offsetof(Type, member)
359
#endif // VC_COMMON_MACROS_H