BitMagic-C++
bmdef.h
Go to the documentation of this file.
1 /*
2 Copyright(c) 2002-2017 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
3 
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 
16 For 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  (!defined(__clang__) || __clang_major__ > 7 || __cplusplus >= 201703L)
413 # define BM_FALLTHROUGH [[fallthrough]]
414 #elif __has_cpp_attribute(gcc::fallthrough)
415 # define BM_FALLTHROUGH [[gcc::fallthrough]]
416 #elif __has_cpp_attribute(clang::fallthrough)
417 # define BM_FALLTHROUGH [[clang::fallthrough]]
418 #elif __has_attribute(fallthrough)
419 # define BM_FALLTHROUGH __attribute__ ((fallthrough))
420 #else
421 # define BM_FALLTHROUGH
422 #endif
423 
424 #endif
425 
426