1#ifndef BOOST_CORE_BIT_HPP_INCLUDED
2#define BOOST_CORE_BIT_HPP_INCLUDED
3
4// MS compatible compilers support #pragma once
5
6#if defined(_MSC_VER) && (_MSC_VER >= 1020)
7# pragma once
8#endif
9
10// boost/core/bit.hpp
11//
12// A portable version of the C++20 standard header <bit>
13//
14// Copyright 2020 Peter Dimov
15// Distributed under the Boost Software License, Version 1.0.
16// https://www.boost.org/LICENSE_1_0.txt
17
18#include <boost/config.hpp>
19#include <boost/static_assert.hpp>
20#include <boost/cstdint.hpp>
21#include <limits>
22#include <cstring>
23#include <cstdlib>
24
25#if defined(_MSC_VER)
26
27# include <intrin.h>
28# pragma intrinsic(_BitScanForward)
29# pragma intrinsic(_BitScanReverse)
30
31# if defined(_M_X64)
32# pragma intrinsic(_BitScanForward64)
33# pragma intrinsic(_BitScanReverse64)
34# endif
35
36# pragma warning(push)
37# pragma warning(disable: 4127) // conditional expression is constant
38# pragma warning(disable: 4244) // conversion from int to T
39
40#endif // defined(_MSC_VER)
41
42#if defined(BOOST_MSVC) && BOOST_MSVC >= 1925
43# define BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL
44#endif
45
46#if defined(__has_builtin)
47# if __has_builtin(__builtin_bit_cast)
48# define BOOST_CORE_HAS_BUILTIN_BIT_CAST
49# endif
50#endif
51
52#if defined(BOOST_MSVC) && BOOST_MSVC >= 1926
53# define BOOST_CORE_HAS_BUILTIN_BIT_CAST
54#endif
55
56namespace boost
57{
58namespace core
59{
60
61// bit_cast
62
63#if defined(BOOST_CORE_HAS_BUILTIN_BIT_CAST)
64
65template<class To, class From>
66BOOST_CONSTEXPR To bit_cast( From const & from ) BOOST_NOEXCEPT
67{
68 return __builtin_bit_cast( To, from );
69}
70
71#else
72
73template<class To, class From>
74To bit_cast( From const & from ) BOOST_NOEXCEPT
75{
76 BOOST_STATIC_ASSERT( sizeof(To) == sizeof(From) );
77
78 To to;
79 std::memcpy( &to, &from, sizeof(To) );
80 return to;
81}
82
83#endif
84
85// countl
86
87#if defined(__GNUC__) || defined(__clang__)
88
89namespace detail
90{
91
92BOOST_CONSTEXPR inline int countl_impl( unsigned char x ) BOOST_NOEXCEPT
93{
94 return x? __builtin_clz( x ) - ( std::numeric_limits<unsigned int>::digits - std::numeric_limits<unsigned char>::digits ): std::numeric_limits<unsigned char>::digits;
95}
96
97BOOST_CONSTEXPR inline int countl_impl( unsigned short x ) BOOST_NOEXCEPT
98{
99 return x? __builtin_clz( x ) - ( std::numeric_limits<unsigned int>::digits - std::numeric_limits<unsigned short>::digits ): std::numeric_limits<unsigned short>::digits;
100}
101
102BOOST_CONSTEXPR inline int countl_impl( unsigned int x ) BOOST_NOEXCEPT
103{
104 return x? __builtin_clz( x ): std::numeric_limits<unsigned int>::digits;
105}
106
107BOOST_CONSTEXPR inline int countl_impl( unsigned long x ) BOOST_NOEXCEPT
108{
109 return x? __builtin_clzl( x ): std::numeric_limits<unsigned long>::digits;
110}
111
112BOOST_CONSTEXPR inline int countl_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT
113{
114 return x? __builtin_clzll( x ): std::numeric_limits<boost::ulong_long_type>::digits;
115}
116
117} // namespace detail
118
119template<class T>
120BOOST_CONSTEXPR int countl_zero( T x ) BOOST_NOEXCEPT
121{
122 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
123
124 return boost::core::detail::countl_impl( x );
125}
126
127#else // defined(__GNUC__) || defined(__clang__)
128
129namespace detail
130{
131
132#if defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
133
134BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT
135{
136 if( __builtin_is_constant_evaluated() )
137 {
138 constexpr unsigned char mod37[ 37 ] = { 32, 31, 6, 30, 9, 5, 0, 29, 16, 8, 2, 4, 21, 0, 19, 28, 25, 15, 0, 7, 10, 1, 17, 3, 22, 20, 26, 0, 11, 18, 23, 27, 12, 24, 13, 14, 0 };
139
140 x |= x >> 1;
141 x |= x >> 2;
142 x |= x >> 4;
143 x |= x >> 8;
144 x |= x >> 16;
145
146 return mod37[ x % 37 ];
147 }
148 else
149 {
150 unsigned long r;
151
152 if( _BitScanReverse( &r, x ) )
153 {
154 return 31 - static_cast<int>( r );
155 }
156 else
157 {
158 return 32;
159 }
160 }
161}
162
163BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint8_t x ) BOOST_NOEXCEPT
164{
165 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 24;
166}
167
168BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT
169{
170 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 16;
171}
172
173#elif defined(_MSC_VER)
174
175inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT
176{
177 unsigned long r;
178
179 if( _BitScanReverse( &r, x ) )
180 {
181 return 31 - static_cast<int>( r );
182 }
183 else
184 {
185 return 32;
186 }
187}
188
189inline int countl_impl( boost::uint8_t x ) BOOST_NOEXCEPT
190{
191 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 24;
192}
193
194inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT
195{
196 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 16;
197}
198
199#else
200
201inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT
202{
203 static unsigned char const mod37[ 37 ] = { 32, 31, 6, 30, 9, 5, 0, 29, 16, 8, 2, 4, 21, 0, 19, 28, 25, 15, 0, 7, 10, 1, 17, 3, 22, 20, 26, 0, 11, 18, 23, 27, 12, 24, 13, 14, 0 };
204
205 x |= x >> 1;
206 x |= x >> 2;
207 x |= x >> 4;
208 x |= x >> 8;
209 x |= x >> 16;
210
211 return mod37[ x % 37 ];
212}
213
214inline int countl_impl( boost::uint8_t x ) BOOST_NOEXCEPT
215{
216 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 24;
217}
218
219inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT
220{
221 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 16;
222}
223
224#endif
225
226#if defined(_MSC_VER) && defined(_M_X64) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
227
228BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT
229{
230 if( __builtin_is_constant_evaluated() )
231 {
232 return static_cast<boost::uint32_t>( x >> 32 ) != 0?
233 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x >> 32 ) ):
234 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) + 32;
235 }
236 else
237 {
238 unsigned long r;
239
240 if( _BitScanReverse64( &r, x ) )
241 {
242 return 63 - static_cast<int>( r );
243 }
244 else
245 {
246 return 64;
247 }
248 }
249}
250
251#elif defined(_MSC_VER) && defined(_M_X64)
252
253inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT
254{
255 unsigned long r;
256
257 if( _BitScanReverse64( &r, x ) )
258 {
259 return 63 - static_cast<int>( r );
260 }
261 else
262 {
263 return 64;
264 }
265}
266
267#elif defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
268
269BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT
270{
271 return static_cast<boost::uint32_t>( x >> 32 ) != 0?
272 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x >> 32 ) ):
273 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) + 32;
274}
275
276#else
277
278inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT
279{
280 return static_cast<boost::uint32_t>( x >> 32 ) != 0?
281 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x >> 32 ) ):
282 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) + 32;
283}
284
285#endif
286
287} // namespace detail
288
289template<class T>
290BOOST_CXX14_CONSTEXPR int countl_zero( T x ) BOOST_NOEXCEPT
291{
292 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
293
294 BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) );
295
296 BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) )
297 {
298 return boost::core::detail::countl_impl( static_cast<boost::uint8_t>( x ) );
299 }
300 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) )
301 {
302 return boost::core::detail::countl_impl( static_cast<boost::uint16_t>( x ) );
303 }
304 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) )
305 {
306 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) );
307 }
308 else
309 {
310 return boost::core::detail::countl_impl( static_cast<boost::uint64_t>( x ) );
311 }
312}
313
314#endif // defined(__GNUC__) || defined(__clang__)
315
316template<class T>
317BOOST_CONSTEXPR int countl_one( T x ) BOOST_NOEXCEPT
318{
319 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
320
321 return boost::core::countl_zero( static_cast<T>( ~x ) );
322}
323
324// countr
325
326#if defined(__GNUC__) || defined(__clang__)
327
328namespace detail
329{
330
331BOOST_CONSTEXPR inline int countr_impl( unsigned char x ) BOOST_NOEXCEPT
332{
333 return x? __builtin_ctz( x ): std::numeric_limits<unsigned char>::digits;
334}
335
336BOOST_CONSTEXPR inline int countr_impl( unsigned short x ) BOOST_NOEXCEPT
337{
338 return x? __builtin_ctz( x ): std::numeric_limits<unsigned short>::digits;
339}
340
341BOOST_CONSTEXPR inline int countr_impl( unsigned int x ) BOOST_NOEXCEPT
342{
343 return x? __builtin_ctz( x ): std::numeric_limits<unsigned int>::digits;
344}
345
346BOOST_CONSTEXPR inline int countr_impl( unsigned long x ) BOOST_NOEXCEPT
347{
348 return x? __builtin_ctzl( x ): std::numeric_limits<unsigned long>::digits;
349}
350
351BOOST_CONSTEXPR inline int countr_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT
352{
353 return x? __builtin_ctzll( x ): std::numeric_limits<boost::ulong_long_type>::digits;
354}
355
356} // namespace detail
357
358template<class T>
359BOOST_CONSTEXPR int countr_zero( T x ) BOOST_NOEXCEPT
360{
361 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
362
363 return boost::core::detail::countr_impl( x );
364}
365
366#else // defined(__GNUC__) || defined(__clang__)
367
368namespace detail
369{
370
371#if defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
372
373BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT
374{
375 if( __builtin_is_constant_evaluated() )
376 {
377 constexpr unsigned char mod37[ 37 ] = { 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18 };
378 return mod37[ ( -(boost::int32_t)x & x ) % 37 ];
379 }
380 else
381 {
382 unsigned long r;
383
384 if( _BitScanForward( &r, x ) )
385 {
386 return static_cast<int>( r );
387 }
388 else
389 {
390 return 32;
391 }
392 }
393}
394
395BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint8_t x ) BOOST_NOEXCEPT
396{
397 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x100 );
398}
399
400BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT
401{
402 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x10000 );
403}
404
405#elif defined(_MSC_VER)
406
407inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT
408{
409 unsigned long r;
410
411 if( _BitScanForward( &r, x ) )
412 {
413 return static_cast<int>( r );
414 }
415 else
416 {
417 return 32;
418 }
419}
420
421inline int countr_impl( boost::uint8_t x ) BOOST_NOEXCEPT
422{
423 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x100 );
424}
425
426inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT
427{
428 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x10000 );
429}
430
431#else
432
433inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT
434{
435 static unsigned char const mod37[ 37 ] = { 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18 };
436 return mod37[ ( -(boost::int32_t)x & x ) % 37 ];
437}
438
439inline int countr_impl( boost::uint8_t x ) BOOST_NOEXCEPT
440{
441 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x100 );
442}
443
444inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT
445{
446 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x10000 );
447}
448
449#endif
450
451#if defined(_MSC_VER) && defined(_M_X64) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
452
453BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT
454{
455 if( __builtin_is_constant_evaluated() )
456 {
457 return static_cast<boost::uint32_t>( x ) != 0?
458 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) ):
459 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x >> 32 ) ) + 32;
460 }
461 else
462 {
463 unsigned long r;
464
465 if( _BitScanForward64( &r, x ) )
466 {
467 return static_cast<int>( r );
468 }
469 else
470 {
471 return 64;
472 }
473 }
474}
475
476#elif defined(_MSC_VER) && defined(_M_X64)
477
478inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT
479{
480 unsigned long r;
481
482 if( _BitScanForward64( &r, x ) )
483 {
484 return static_cast<int>( r );
485 }
486 else
487 {
488 return 64;
489 }
490}
491
492#elif defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
493
494BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT
495{
496 return static_cast<boost::uint32_t>( x ) != 0?
497 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) ):
498 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x >> 32 ) ) + 32;
499}
500
501#else
502
503inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT
504{
505 return static_cast<boost::uint32_t>( x ) != 0?
506 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) ):
507 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x >> 32 ) ) + 32;
508}
509
510#endif
511
512} // namespace detail
513
514template<class T>
515BOOST_CXX14_CONSTEXPR int countr_zero( T x ) BOOST_NOEXCEPT
516{
517 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
518
519 BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) );
520
521 BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) )
522 {
523 return boost::core::detail::countr_impl( static_cast<boost::uint8_t>( x ) );
524 }
525 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) )
526 {
527 return boost::core::detail::countr_impl( static_cast<boost::uint16_t>( x ) );
528 }
529 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) )
530 {
531 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) );
532 }
533 else
534 {
535 return boost::core::detail::countr_impl( static_cast<boost::uint64_t>( x ) );
536 }
537}
538
539#endif // defined(__GNUC__) || defined(__clang__)
540
541template<class T>
542BOOST_CONSTEXPR int countr_one( T x ) BOOST_NOEXCEPT
543{
544 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
545
546 return boost::core::countr_zero( static_cast<T>( ~x ) );
547}
548
549// popcount
550
551#if defined(__GNUC__) || defined(__clang__)
552
553#if defined(__clang__) && __clang_major__ * 100 + __clang_minor__ < 304
554# define BOOST_CORE_POPCOUNT_CONSTEXPR
555#else
556# define BOOST_CORE_POPCOUNT_CONSTEXPR BOOST_CONSTEXPR
557#endif
558
559namespace detail
560{
561
562BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned char x ) BOOST_NOEXCEPT
563{
564 return __builtin_popcount( x );
565}
566
567BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned short x ) BOOST_NOEXCEPT
568{
569 return __builtin_popcount( x );
570}
571
572BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned int x ) BOOST_NOEXCEPT
573{
574 return __builtin_popcount( x );
575}
576
577BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned long x ) BOOST_NOEXCEPT
578{
579 return __builtin_popcountl( x );
580}
581
582BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT
583{
584 return __builtin_popcountll( x );
585}
586
587} // namespace detail
588
589#undef BOOST_CORE_POPCOUNT_CONSTEXPR
590
591template<class T>
592BOOST_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT
593{
594 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
595
596 return boost::core::detail::popcount_impl( x );
597}
598
599#else // defined(__GNUC__) || defined(__clang__)
600
601namespace detail
602{
603
604BOOST_CXX14_CONSTEXPR inline int popcount_impl( boost::uint32_t x ) BOOST_NOEXCEPT
605{
606 x = x - ( ( x >> 1 ) & 0x55555555 );
607 x = ( x & 0x33333333 ) + ( ( x >> 2 ) & 0x33333333 );
608 x = ( x + ( x >> 4 ) ) & 0x0F0F0F0F;
609
610 return static_cast<unsigned>( ( x * 0x01010101 ) >> 24 );
611}
612
613BOOST_CXX14_CONSTEXPR inline int popcount_impl( boost::uint64_t x ) BOOST_NOEXCEPT
614{
615 x = x - ( ( x >> 1 ) & 0x5555555555555555 );
616 x = ( x & 0x3333333333333333 ) + ( ( x >> 2 ) & 0x3333333333333333 );
617 x = ( x + ( x >> 4 ) ) & 0x0F0F0F0F0F0F0F0F;
618
619 return static_cast<unsigned>( ( x * 0x0101010101010101 ) >> 56 );
620}
621
622} // namespace detail
623
624template<class T>
625BOOST_CXX14_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT
626{
627 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
628
629 BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) );
630
631 BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) )
632 {
633 return boost::core::detail::popcount_impl( static_cast<boost::uint32_t>( x ) );
634 }
635 else
636 {
637 return boost::core::detail::popcount_impl( static_cast<boost::uint64_t>( x ) );
638 }
639}
640
641#endif // defined(__GNUC__) || defined(__clang__)
642
643// rotating
644
645template<class T>
646BOOST_CXX14_CONSTEXPR T rotl( T x, int s ) BOOST_NOEXCEPT
647{
648 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
649
650 unsigned const mask = std::numeric_limits<T>::digits - 1;
651 return static_cast<T>( x << (static_cast<unsigned>( s ) & mask) | x >> (static_cast<unsigned>( -s ) & mask) );
652}
653
654template<class T>
655BOOST_CXX14_CONSTEXPR T rotr( T x, int s ) BOOST_NOEXCEPT
656{
657 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
658
659 unsigned const mask = std::numeric_limits<T>::digits - 1;
660 return static_cast<T>( x >> (static_cast<unsigned>( s ) & mask) | x << (static_cast<unsigned>( -s ) & mask) );
661}
662
663// integral powers of 2
664
665template<class T>
666BOOST_CONSTEXPR bool has_single_bit( T x ) BOOST_NOEXCEPT
667{
668 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
669
670 return x != 0 && ( x & ( x - 1 ) ) == 0;
671}
672
673// bit_width returns `int` now, https://cplusplus.github.io/LWG/issue3656
674// has been applied to C++20 as a DR
675
676template<class T>
677BOOST_CONSTEXPR int bit_width( T x ) BOOST_NOEXCEPT
678{
679 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
680
681 return std::numeric_limits<T>::digits - boost::core::countl_zero( x );
682}
683
684template<class T>
685BOOST_CONSTEXPR T bit_floor( T x ) BOOST_NOEXCEPT
686{
687 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
688
689 return x == 0? T(0): static_cast<T>( T(1) << ( boost::core::bit_width( x ) - 1 ) );
690}
691
692namespace detail
693{
694
695BOOST_CXX14_CONSTEXPR inline boost::uint32_t bit_ceil_impl( boost::uint32_t x ) BOOST_NOEXCEPT
696{
697 if( x == 0 )
698 {
699 return 0;
700 }
701
702 --x;
703
704 x |= x >> 1;
705 x |= x >> 2;
706 x |= x >> 4;
707 x |= x >> 8;
708 x |= x >> 16;
709
710 ++x;
711
712 return x;
713}
714
715BOOST_CXX14_CONSTEXPR inline boost::uint64_t bit_ceil_impl( boost::uint64_t x ) BOOST_NOEXCEPT
716{
717 if( x == 0 )
718 {
719 return 0;
720 }
721
722 --x;
723
724 x |= x >> 1;
725 x |= x >> 2;
726 x |= x >> 4;
727 x |= x >> 8;
728 x |= x >> 16;
729 x |= x >> 32;
730
731 ++x;
732
733 return x;
734}
735
736} // namespace detail
737
738template<class T>
739BOOST_CXX14_CONSTEXPR T bit_ceil( T x ) BOOST_NOEXCEPT
740{
741 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
742
743 BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) );
744
745 BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) )
746 {
747 return static_cast<T>( boost::core::detail::bit_ceil_impl( x: static_cast<boost::uint32_t>( x ) ) );
748 }
749 else
750 {
751 return static_cast<T>( boost::core::detail::bit_ceil_impl( x: static_cast<boost::uint64_t>( x ) ) );
752 }
753}
754
755// endian
756
757#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
758
759# define BOOST_CORE_BIT_NATIVE_INITIALIZER =little
760
761#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
762
763# define BOOST_CORE_BIT_NATIVE_INITIALIZER =big
764
765#elif defined(__BYTE_ORDER__) && defined(__ORDER_PDP_ENDIAN__) && __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__
766
767# define BOOST_CORE_BIT_NATIVE_INITIALIZER
768
769#elif defined(__LITTLE_ENDIAN__)
770
771# define BOOST_CORE_BIT_NATIVE_INITIALIZER =little
772
773#elif defined(__BIG_ENDIAN__)
774
775# define BOOST_CORE_BIT_NATIVE_INITIALIZER =big
776
777#elif defined(_MSC_VER) || defined(__i386__) || defined(__x86_64__)
778
779# define BOOST_CORE_BIT_NATIVE_INITIALIZER =little
780
781#else
782
783# define BOOST_CORE_BIT_NATIVE_INITIALIZER
784
785#endif
786
787#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS)
788
789enum class endian
790{
791 big,
792 little,
793 native BOOST_CORE_BIT_NATIVE_INITIALIZER
794};
795
796typedef endian endian_type;
797
798#else
799
800namespace endian
801{
802
803enum type
804{
805 big,
806 little,
807 native BOOST_CORE_BIT_NATIVE_INITIALIZER
808};
809
810} // namespace endian
811
812typedef endian::type endian_type;
813
814#endif
815
816#undef BOOST_CORE_BIT_NATIVE_INITIALIZER
817
818// byteswap
819
820namespace detail
821{
822
823BOOST_CONSTEXPR inline boost::uint8_t byteswap_impl( boost::uint8_t x ) BOOST_NOEXCEPT
824{
825 return x;
826}
827
828BOOST_CONSTEXPR inline boost::uint16_t byteswap_impl( boost::uint16_t x ) BOOST_NOEXCEPT
829{
830 return static_cast<boost::uint16_t>( x << 8 | x >> 8 );
831}
832
833#if defined(__GNUC__) || defined(__clang__)
834
835BOOST_CXX14_CONSTEXPR inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT
836{
837 return __builtin_bswap32( x );
838}
839
840BOOST_CXX14_CONSTEXPR inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT
841{
842 return __builtin_bswap64( x );
843}
844
845#elif defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
846
847BOOST_CXX14_CONSTEXPR inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT
848{
849 if( __builtin_is_constant_evaluated() )
850 {
851 boost::uint32_t step16 = x << 16 | x >> 16;
852 return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff);
853 }
854 else
855 {
856 return _byteswap_ulong( x );
857 }
858}
859
860BOOST_CXX14_CONSTEXPR inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT
861{
862 if( __builtin_is_constant_evaluated() )
863 {
864 boost::uint64_t step32 = x << 32 | x >> 32;
865 boost::uint64_t step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
866 return (step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8;
867 }
868 else
869 {
870 return _byteswap_uint64( x );
871 }
872}
873
874#elif defined(_MSC_VER)
875
876inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT
877{
878 return _byteswap_ulong( x );
879}
880
881inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT
882{
883 return _byteswap_uint64( x );
884}
885
886#else
887
888BOOST_CXX14_CONSTEXPR inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT
889{
890 boost::uint32_t step16 = x << 16 | x >> 16;
891 return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff);
892}
893
894BOOST_CXX14_CONSTEXPR inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT
895{
896 boost::uint64_t step32 = x << 32 | x >> 32;
897 boost::uint64_t step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
898 return (step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8;
899}
900
901#endif
902
903} // namespace detail
904
905template<class T> BOOST_CXX14_CONSTEXPR T byteswap( T x ) BOOST_NOEXCEPT
906{
907 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer );
908
909 BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) );
910
911 BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) )
912 {
913 return static_cast<T>( boost::core::detail::byteswap_impl( x: static_cast<boost::uint8_t>( x ) ) );
914 }
915 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) )
916 {
917 return static_cast<T>( boost::core::detail::byteswap_impl( x: static_cast<boost::uint16_t>( x ) ) );
918 }
919 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) )
920 {
921 return static_cast<T>( boost::core::detail::byteswap_impl( x: static_cast<boost::uint32_t>( x ) ) );
922 }
923 else
924 {
925 return static_cast<T>( boost::core::detail::byteswap_impl( x: static_cast<boost::uint64_t>( x ) ) );
926 }
927}
928
929} // namespace core
930} // namespace boost
931
932#if defined(_MSC_VER)
933# pragma warning(pop)
934#endif
935
936#endif // #ifndef BOOST_CORE_BIT_HPP_INCLUDED
937