BitMagic-C++
bmdef.h
Go to the documentation of this file.
1/*
2Copyright(c) 2002-2017 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15
16For more information please visit: http://bitmagic.io
17*/
18
19/*! \file bmdef.h
20 \brief Definitions(internal)
21*/
22
23#include <climits>
24
25// Incorporate appropriate tuneups when the NCBI C++ Toolkit's core
26// headers have been included.
27//
28#ifdef NCBI_ASSERT
29# define BM_ASSERT _ASSERT
30
31# ifdef HAVE_RESTRICT_CXX
32# define BM_HASRESTRICT
33# define BMRESTRICT NCBI_RESTRICT
34# endif
35
36# if defined(NCBI_FORCEINLINE) && \
37 ( !defined(NCBI_COMPILER_GCC) || NCBI_COMPILER_VERSION >= 400 || \
38 defined(__OPTIMIZE__))
39# define BM_HASFORCEINLINE
40# define BMFORCEINLINE NCBI_FORCEINLINE
41# endif
42
43# ifdef NCBI_SSE
44# if NCBI_SSE >= 20
45# define BMSSE2OPT 1
46# endif
47# if NCBI_SSE >= 40
48# define BMSSE2OPT 1
49# endif
50# if NCBI_SSE >= 42
51# define BMSSE42OPT 1
52# endif
53# endif
54#endif
55
56
57// macro to define/undefine unaligned memory access (x86, PowerPC)
58//
59#if defined(__i386) || defined(__x86_64) || defined(__ppc__) || \
60 defined(__ppc64__) || defined(_M_IX86) || defined(_M_AMD64) || \
61 defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \
62 (defined(_M_MPPC) && !defined(BM_FORBID_UNALIGNED_ACCESS))
63#define BM_UNALIGNED_ACCESS_OK 1
64#endif
65
66#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \
67 defined(__i386) || defined(__x86_64) || defined(_M_AMD64) || \
68 defined(BMSSE2OPT) || defined(BMSSE42OPT)
69#define BM_x86
70#endif
71
72// cxx11 features
73//
74#if defined(BM_NO_CXX11) || (defined(_MSC_VER) && _MSC_VER < 1900)
75# define BMNOEXCEPT
76# define BMNOEXCEPT2
77#else
78# ifndef BMNOEXCEPT
79# define BMNOEXCEPT noexcept
80#if defined(__EMSCRIPTEN__)
81#else
82# define BMNOEXCEPT2
83#endif
84# endif
85#endif
86
87// WebAssembly compilation settings
88//
89// detects use of EMSCRIPTEN engine and tweaks settings
90// WebAssemply compiles into 32-bit ptr yet 64-bit wordsize use GCC extensions
91//
92// BMNOEXCEPT2 is to declare "noexcept" for WebAsm only where needed
93// and silence GCC warnings where not
94#if defined(__EMSCRIPTEN__)
95# define BM64OPT
96# define BM_USE_GCC_BUILD
97# define BMNOEXCEPT2 noexcept
98#else
99# define BMNOEXCEPT2
100#endif
101
102
103// Enable MSVC 8.0 (2005) specific optimization options
104//
105#if(_MSC_VER >= 1400)
106# define BM_HASFORCEINLINE
107# ifndef BMRESTRICT
108# define BMRESTRICT __restrict
109# endif
110#endif
111
112#ifdef __GNUG__
113# ifndef BMRESTRICT
114# define BMRESTRICT __restrict__
115# endif
116
117# ifdef __OPTIMIZE__
118# define BM_NOASSERT
119# endif
120#endif
121
122# ifdef NDEBUG
123# define BM_NOASSERT
124# endif
125
126
127#ifndef BM_ASSERT
128# ifndef BM_NOASSERT
129# include <cassert>
130# define BM_ASSERT assert
131# else
132# ifndef BM_ASSERT
133# define BM_ASSERT(x)
134# endif
135# endif
136#endif
137
138
139#if defined(__x86_64) || defined(_M_AMD64) || defined(_WIN64) || \
140 defined(__LP64__) || defined(_LP64) || ( __WORDSIZE == 64 )
141#ifndef BM64OPT
142# define BM64OPT
143#endif
144#endif
145
146
147
148#define FULL_BLOCK_REAL_ADDR bm::all_set<true>::_block._p
149#define FULL_BLOCK_FAKE_ADDR bm::all_set<true>::_block._p_fullp
150#define FULL_SUB_BLOCK_REAL_ADDR bm::all_set<true>::_block._s
151#define BLOCK_ADDR_SAN(addr) (addr == FULL_BLOCK_FAKE_ADDR) ? FULL_BLOCK_REAL_ADDR : addr
152#define IS_VALID_ADDR(addr) bm::all_set<true>::is_valid_block_addr(addr)
153#define IS_FULL_BLOCK(addr) bm::all_set<true>::is_full_block(addr)
154#define IS_EMPTY_BLOCK(addr) bool(addr == 0)
155
156#define BM_BLOCK_TYPE(addr) bm::all_set<true>::block_type(addr)
157
158// Macro definitions to manipulate bits in pointers
159// This trick is based on the fact that pointers allocated by malloc are
160// aligned and bit 0 is never set. It means we are safe to use it.
161// BM library keeps GAP flag in pointer.
162
163
164
165# if ULONG_MAX != 0xffffffff || defined(_WIN64) // 64-bit
166
167# define BMPTR_SETBIT0(ptr) ( ((bm::id64_t)ptr) | 1 )
168# define BMPTR_CLEARBIT0(ptr) ( ((bm::id64_t)ptr) & ~(bm::id64_t)1 )
169# define BMPTR_TESTBIT0(ptr) ( ((bm::id64_t)ptr) & 1 )
170
171# else // 32-bit
172
173# define BMPTR_SETBIT0(ptr) ( ((bm::id_t)ptr) | 1 )
174# define BMPTR_CLEARBIT0(ptr) ( ((bm::id_t)ptr) & ~(bm::id_t)1 )
175# define BMPTR_TESTBIT0(ptr) ( ((bm::id_t)ptr) & 1 )
176
177# endif
178
179# define BMGAP_PTR(ptr) ((bm::gap_word_t*)BMPTR_CLEARBIT0(ptr))
180# define BMSET_PTRGAP(ptr) ptr = (bm::word_t*)BMPTR_SETBIT0(ptr)
181# define BM_IS_GAP(ptr) bool(BMPTR_TESTBIT0(ptr)!=0)
182
183
184
185
186
187#ifdef BM_HASRESTRICT
188# ifndef BMRESTRICT
189# define BMRESTRICT restrict
190# endif
191#else
192# ifndef BMRESTRICT
193# define BMRESTRICT
194# endif
195#endif
196
197
198#ifdef BM_HASFORCEINLINE
199# ifndef BMFORCEINLINE
200# define BMFORCEINLINE __forceinline
201# endif
202#else
203# define BMFORCEINLINE inline
204#endif
205
206
207// --------------------------------
208// SSE optmization macros
209//
210
211#ifdef BMSSE42OPT
212# if defined(BM64OPT) || defined(__x86_64) || defined(_M_AMD64) || defined(_WIN64) || \
213 defined(__LP64__) || defined(_LP64)
214# undef BM64OPT
215# define BM64_SSE4
216# endif
217# undef BMSSE2OPT
218#endif
219
220#ifdef BMAVX2OPT
221# if defined(BM64OPT) || defined(__x86_64) || defined(_M_AMD64) || defined(_WIN64) || \
222 defined(__LP64__) || defined(_LP64)
223# undef BM64OPT
224# undef BM64_SSE4
225# define BM64_AVX2
226# endif
227# undef BMSSE2OPT
228# undef BMSSE42OPT
229#endif
230
231#ifdef BMAVX512OPT
232# if defined(BM64OPT) || defined(__x86_64) || defined(_M_AMD64) || defined(_WIN64) || \
233 defined(__LP64__) || defined(_LP64)
234# undef BM64OPT
235# undef BM64_SSE4
236# undef BM64_AVX2
237# define BM64_AVX512
238# endif
239# undef BMSSE2OPT
240# undef BMSSE42OPT
241#endif
242
243
244
245# ifndef BM_SET_MMX_GUARD
246# define BM_SET_MMX_GUARD
247# endif
248
249
250#if (defined(BMSSE2OPT) || defined(BMSSE42OPT) || defined(BMAVX2OPT) || defined(BMAVX512OPT))
251
252 # ifndef BM_SET_MMX_GUARD
253 # define BM_SET_MMX_GUARD sse_empty_guard bm_mmx_guard_;
254 # endif
255
256 #ifdef _MSC_VER
257
258 #ifndef BM_ALIGN16
259 # define BM_ALIGN16 __declspec(align(16))
260 # define BM_ALIGN16ATTR
261 #endif
262
263 #ifndef BM_ALIGN32
264 # define BM_ALIGN32 __declspec(align(32))
265 # define BM_ALIGN32ATTR
266 #endif
267
268 #ifndef BM_ALIGN64
269 # define BM_ALIGN64 __declspec(align(64))
270 # define BM_ALIGN64ATTR
271 #endif
272
273 # else // GCC
274
275 #ifndef BM_ALIGN16
276 # define BM_ALIGN16
277 # define BM_ALIGN16ATTR __attribute__((aligned(16)))
278 #endif
279
280 #ifndef BM_ALIGN32
281 # define BM_ALIGN32
282 # define BM_ALIGN32ATTR __attribute__((aligned(32)))
283 #endif
284
285 #ifndef BM_ALIGN64
286 # define BM_ALIGN64
287 # define BM_ALIGN64ATTR __attribute__((aligned(64)))
288 #endif
289 #endif
290
291#else
292
293 #define BM_ALIGN16
294 #define BM_ALIGN16ATTR
295 #define BM_ALIGN32
296 #define BM_ALIGN32ATTR
297 #define BM_ALIGN64
298 #define BM_ALIGN64ATTR
299
300#endif
301
302
303/*
304#if !(defined(BMSSE2OPT) || defined(BMSSE42OPT) || defined(BMAVX2OPT) || defined(BMAVX512OPT))
305
306 #define BM_ALIGN16
307 #define BM_ALIGN16ATTR
308 #define BM_ALIGN32
309 #define BM_ALIGN32ATTR
310 #define BM_ALIGN64
311 #define BM_ALIGN64ATTR
312
313#else
314
315 # ifndef BM_SET_MMX_GUARD
316 # define BM_SET_MMX_GUARD sse_empty_guard bm_mmx_guard_;
317 # endif
318
319 #ifdef _MSC_VER
320
321 #ifndef BM_ALIGN16
322 # define BM_ALIGN16 __declspec(align(16))
323 # define BM_ALIGN16ATTR
324 #endif
325
326 #ifndef BM_ALIGN32
327 # define BM_ALIGN32 __declspec(align(32))
328 # define BM_ALIGN32ATTR
329 #endif
330
331 #ifndef BM_ALIGN64
332 # define BM_ALIGN64 __declspec(align(64))
333 # define BM_ALIGN64ATTR
334 #endif
335
336 # else // GCC
337
338 #ifndef BM_ALIGN16
339 # define BM_ALIGN16
340 # define BM_ALIGN16ATTR __attribute__((aligned(16)))
341 #endif
342
343 #ifndef BM_ALIGN32
344 # define BM_ALIGN32
345 # define BM_ALIGN32ATTR __attribute__((aligned(32)))
346 #endif
347
348 #ifndef BM_ALIGN64
349 # define BM_ALIGN64
350 # define BM_ALIGN64ATTR __attribute__((aligned(64)))
351 #endif
352 #endif
353
354#endif
355*/
356
357
358#if (defined(BMSSE2OPT) || defined(BMSSE42OPT))
359# define BM_VECT_ALIGN BM_ALIGN16
360# define BM_VECT_ALIGN_ATTR BM_ALIGN16ATTR
361#else
362# if defined(BMAVX2OPT)
363# define BM_VECT_ALIGN BM_ALIGN32
364# define BM_VECT_ALIGN_ATTR BM_ALIGN32ATTR
365# else
366# if defined(BMAVX512OPT)
367# define BM_VECT_ALIGN BM_ALIGN64
368# define BM_VECT_ALIGN_ATTR BM_ALIGN64ATTR
369# else
370# define BM_VECT_ALIGN
371# define BM_VECT_ALIGN_ATTR
372# endif
373# endif
374#endif
375
376
377
378
379/*!
380 Define calculates number of 1 bits in 32-bit word.
381 @ingroup bitfunc
382*/
383#ifndef BM_INCWORD_BITCOUNT
384
385#if (defined(BMSSE42OPT) || defined(BMAVX2OPT) || defined(BMAVX512OPT))
386# define BM_INCWORD_BITCOUNT(cnt, w) cnt += unsigned(_mm_popcnt_u32(w));
387#else
388
389# define BM_INCWORD_BITCOUNT(cnt, w) cnt += \
390 bm::bit_count_table<true>::_count[(unsigned char)(w)] + \
391 bm::bit_count_table<true>::_count[(unsigned char)((w) >> 8)] + \
392 bm::bit_count_table<true>::_count[(unsigned char)((w) >> 16)] + \
393 bm::bit_count_table<true>::_count[(unsigned char)((w) >> 24)];
394
395
396#endif
397
398// throw redefinintion for compatibility with language wrappers
399//
400#ifndef BM_ASSERT_THROW
401#define BM_ASSERT_THROW(x, xerrcode)
402#endif
403
404
405#ifndef __has_cpp_attribute
406# define __has_cpp_attribute(x) 0
407#endif
408#ifndef __has_attribute
409# define __has_attribute(x) 0
410#endif
411#if __has_cpp_attribute(fallthrough)
412# define BM_FALLTHROUGH [[fallthrough]]
413#elif __has_cpp_attribute(gcc::fallthrough)
414# define BM_FALLTHROUGH [[gcc::fallthrough]]
415#elif __has_cpp_attribute(clang::fallthrough)
416# define BM_FALLTHROUGH [[clang::fallthrough]]
417#elif __has_attribute(fallthrough)
418# define BM_FALLTHROUGH __attribute__ ((fallthrough))
419#else
420# define BM_FALLTHROUGH
421#endif
422
423#endif
424
425