File indexing completed on 2025-07-04 08:09:30
0001 #ifndef BOOST_CORE_BIT_HPP_INCLUDED
0002 #define BOOST_CORE_BIT_HPP_INCLUDED
0003
0004
0005
0006 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
0007 # pragma once
0008 #endif
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <boost/config.hpp>
0019 #include <boost/static_assert.hpp>
0020 #include <boost/cstdint.hpp>
0021 #include <limits>
0022 #include <cstring>
0023 #include <cstdlib>
0024
0025 #if defined(_MSC_VER)
0026
0027 # include <intrin.h>
0028 # pragma intrinsic(_BitScanForward)
0029 # pragma intrinsic(_BitScanReverse)
0030
0031 # if defined(_M_X64)
0032 # pragma intrinsic(_BitScanForward64)
0033 # pragma intrinsic(_BitScanReverse64)
0034 # endif
0035
0036 # pragma warning(push)
0037 # pragma warning(disable: 4127)
0038 # pragma warning(disable: 4244)
0039
0040 #endif
0041
0042 #if defined(BOOST_MSVC) && BOOST_MSVC >= 1925
0043 # define BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL
0044 #endif
0045
0046 #if defined(__has_builtin)
0047 # if __has_builtin(__builtin_bit_cast)
0048 # define BOOST_CORE_HAS_BUILTIN_BIT_CAST
0049 # endif
0050 # if __has_builtin(__builtin_bswap16)
0051 # define BOOST_CORE_HAS_BUILTIN_BSWAP16
0052 # endif
0053 #endif
0054
0055 #if !defined(BOOST_CORE_HAS_BUILTIN_BIT_CAST) && (defined(BOOST_MSVC) && BOOST_MSVC >= 1926)
0056 # define BOOST_CORE_HAS_BUILTIN_BIT_CAST
0057 #endif
0058
0059 #if !defined(BOOST_CORE_HAS_BUILTIN_BSWAP16) && (defined(BOOST_GCC) && BOOST_GCC >= 40800)
0060 # define BOOST_CORE_HAS_BUILTIN_BSWAP16
0061 #endif
0062
0063 namespace boost
0064 {
0065 namespace core
0066 {
0067
0068
0069
0070 #if defined(BOOST_CORE_HAS_BUILTIN_BIT_CAST)
0071
0072 template<class To, class From>
0073 BOOST_CONSTEXPR To bit_cast( From const & from ) BOOST_NOEXCEPT
0074 {
0075 return __builtin_bit_cast( To, from );
0076 }
0077
0078 #else
0079
0080 template<class To, class From>
0081 To bit_cast( From const & from ) BOOST_NOEXCEPT
0082 {
0083 BOOST_STATIC_ASSERT( sizeof(To) == sizeof(From) );
0084
0085 To to;
0086 std::memcpy( &to, &from, sizeof(To) );
0087 return to;
0088 }
0089
0090 #endif
0091
0092
0093
0094 #if defined(__GNUC__) || defined(__clang__)
0095
0096 namespace detail
0097 {
0098
0099 BOOST_CONSTEXPR inline int countl_impl( unsigned char x ) BOOST_NOEXCEPT
0100 {
0101 return x? __builtin_clz( x ) - ( std::numeric_limits<unsigned int>::digits - std::numeric_limits<unsigned char>::digits ): std::numeric_limits<unsigned char>::digits;
0102 }
0103
0104 BOOST_CONSTEXPR inline int countl_impl( unsigned short x ) BOOST_NOEXCEPT
0105 {
0106 return x? __builtin_clz( x ) - ( std::numeric_limits<unsigned int>::digits - std::numeric_limits<unsigned short>::digits ): std::numeric_limits<unsigned short>::digits;
0107 }
0108
0109 BOOST_CONSTEXPR inline int countl_impl( unsigned int x ) BOOST_NOEXCEPT
0110 {
0111 return x? __builtin_clz( x ): std::numeric_limits<unsigned int>::digits;
0112 }
0113
0114 BOOST_CONSTEXPR inline int countl_impl( unsigned long x ) BOOST_NOEXCEPT
0115 {
0116 return x? __builtin_clzl( x ): std::numeric_limits<unsigned long>::digits;
0117 }
0118
0119 BOOST_CONSTEXPR inline int countl_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT
0120 {
0121 return x? __builtin_clzll( x ): std::numeric_limits<boost::ulong_long_type>::digits;
0122 }
0123
0124 }
0125
0126 template<class T>
0127 BOOST_CONSTEXPR int countl_zero( T x ) BOOST_NOEXCEPT
0128 {
0129 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0130
0131 return boost::core::detail::countl_impl( x );
0132 }
0133
0134 #else
0135
0136 namespace detail
0137 {
0138
0139 #if defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
0140
0141 BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0142 {
0143 if( __builtin_is_constant_evaluated() )
0144 {
0145 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 };
0146
0147 x |= x >> 1;
0148 x |= x >> 2;
0149 x |= x >> 4;
0150 x |= x >> 8;
0151 x |= x >> 16;
0152
0153 return mod37[ x % 37 ];
0154 }
0155 else
0156 {
0157 unsigned long r;
0158
0159 if( _BitScanReverse( &r, x ) )
0160 {
0161 return 31 - static_cast<int>( r );
0162 }
0163 else
0164 {
0165 return 32;
0166 }
0167 }
0168 }
0169
0170 BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint8_t x ) BOOST_NOEXCEPT
0171 {
0172 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 24;
0173 }
0174
0175 BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT
0176 {
0177 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 16;
0178 }
0179
0180 #elif defined(_MSC_VER)
0181
0182 inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0183 {
0184 unsigned long r;
0185
0186 if( _BitScanReverse( &r, x ) )
0187 {
0188 return 31 - static_cast<int>( r );
0189 }
0190 else
0191 {
0192 return 32;
0193 }
0194 }
0195
0196 inline int countl_impl( boost::uint8_t x ) BOOST_NOEXCEPT
0197 {
0198 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 24;
0199 }
0200
0201 inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT
0202 {
0203 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 16;
0204 }
0205
0206 #else
0207
0208 inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0209 {
0210 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 };
0211
0212 x |= x >> 1;
0213 x |= x >> 2;
0214 x |= x >> 4;
0215 x |= x >> 8;
0216 x |= x >> 16;
0217
0218 return mod37[ x % 37 ];
0219 }
0220
0221 inline int countl_impl( boost::uint8_t x ) BOOST_NOEXCEPT
0222 {
0223 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 24;
0224 }
0225
0226 inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT
0227 {
0228 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) - 16;
0229 }
0230
0231 #endif
0232
0233 #if defined(_MSC_VER) && defined(_M_X64) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
0234
0235 BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0236 {
0237 if( __builtin_is_constant_evaluated() )
0238 {
0239 return static_cast<boost::uint32_t>( x >> 32 ) != 0?
0240 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x >> 32 ) ):
0241 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) + 32;
0242 }
0243 else
0244 {
0245 unsigned long r;
0246
0247 if( _BitScanReverse64( &r, x ) )
0248 {
0249 return 63 - static_cast<int>( r );
0250 }
0251 else
0252 {
0253 return 64;
0254 }
0255 }
0256 }
0257
0258 #elif defined(_MSC_VER) && defined(_M_X64)
0259
0260 inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0261 {
0262 unsigned long r;
0263
0264 if( _BitScanReverse64( &r, x ) )
0265 {
0266 return 63 - static_cast<int>( r );
0267 }
0268 else
0269 {
0270 return 64;
0271 }
0272 }
0273
0274 #elif defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
0275
0276 BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0277 {
0278 return static_cast<boost::uint32_t>( x >> 32 ) != 0?
0279 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x >> 32 ) ):
0280 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) + 32;
0281 }
0282
0283 #else
0284
0285 inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0286 {
0287 return static_cast<boost::uint32_t>( x >> 32 ) != 0?
0288 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x >> 32 ) ):
0289 boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) ) + 32;
0290 }
0291
0292 #endif
0293
0294 }
0295
0296 template<class T>
0297 BOOST_CXX14_CONSTEXPR int countl_zero( T x ) BOOST_NOEXCEPT
0298 {
0299 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0300
0301 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) );
0302
0303 BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) )
0304 {
0305 return boost::core::detail::countl_impl( static_cast<boost::uint8_t>( x ) );
0306 }
0307 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) )
0308 {
0309 return boost::core::detail::countl_impl( static_cast<boost::uint16_t>( x ) );
0310 }
0311 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) )
0312 {
0313 return boost::core::detail::countl_impl( static_cast<boost::uint32_t>( x ) );
0314 }
0315 else
0316 {
0317 return boost::core::detail::countl_impl( static_cast<boost::uint64_t>( x ) );
0318 }
0319 }
0320
0321 #endif
0322
0323 template<class T>
0324 BOOST_CONSTEXPR int countl_one( T x ) BOOST_NOEXCEPT
0325 {
0326 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0327
0328 return boost::core::countl_zero( static_cast<T>( ~x ) );
0329 }
0330
0331
0332
0333 #if defined(__GNUC__) || defined(__clang__)
0334
0335 namespace detail
0336 {
0337
0338 BOOST_CONSTEXPR inline int countr_impl( unsigned char x ) BOOST_NOEXCEPT
0339 {
0340 return x? __builtin_ctz( x ): std::numeric_limits<unsigned char>::digits;
0341 }
0342
0343 BOOST_CONSTEXPR inline int countr_impl( unsigned short x ) BOOST_NOEXCEPT
0344 {
0345 return x? __builtin_ctz( x ): std::numeric_limits<unsigned short>::digits;
0346 }
0347
0348 BOOST_CONSTEXPR inline int countr_impl( unsigned int x ) BOOST_NOEXCEPT
0349 {
0350 return x? __builtin_ctz( x ): std::numeric_limits<unsigned int>::digits;
0351 }
0352
0353 BOOST_CONSTEXPR inline int countr_impl( unsigned long x ) BOOST_NOEXCEPT
0354 {
0355 return x? __builtin_ctzl( x ): std::numeric_limits<unsigned long>::digits;
0356 }
0357
0358 BOOST_CONSTEXPR inline int countr_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT
0359 {
0360 return x? __builtin_ctzll( x ): std::numeric_limits<boost::ulong_long_type>::digits;
0361 }
0362
0363 }
0364
0365 template<class T>
0366 BOOST_CONSTEXPR int countr_zero( T x ) BOOST_NOEXCEPT
0367 {
0368 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0369
0370 return boost::core::detail::countr_impl( x );
0371 }
0372
0373 #else
0374
0375 namespace detail
0376 {
0377
0378 #if defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
0379
0380 BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0381 {
0382 if( __builtin_is_constant_evaluated() )
0383 {
0384 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 };
0385 return mod37[ ( -(boost::int32_t)x & x ) % 37 ];
0386 }
0387 else
0388 {
0389 unsigned long r;
0390
0391 if( _BitScanForward( &r, x ) )
0392 {
0393 return static_cast<int>( r );
0394 }
0395 else
0396 {
0397 return 32;
0398 }
0399 }
0400 }
0401
0402 BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint8_t x ) BOOST_NOEXCEPT
0403 {
0404 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x100 );
0405 }
0406
0407 BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT
0408 {
0409 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x10000 );
0410 }
0411
0412 #elif defined(_MSC_VER)
0413
0414 inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0415 {
0416 unsigned long r;
0417
0418 if( _BitScanForward( &r, x ) )
0419 {
0420 return static_cast<int>( r );
0421 }
0422 else
0423 {
0424 return 32;
0425 }
0426 }
0427
0428 inline int countr_impl( boost::uint8_t x ) BOOST_NOEXCEPT
0429 {
0430 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x100 );
0431 }
0432
0433 inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT
0434 {
0435 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x10000 );
0436 }
0437
0438 #else
0439
0440 inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0441 {
0442 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 };
0443 return mod37[ ( -(boost::int32_t)x & x ) % 37 ];
0444 }
0445
0446 inline int countr_impl( boost::uint8_t x ) BOOST_NOEXCEPT
0447 {
0448 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x100 );
0449 }
0450
0451 inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT
0452 {
0453 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) | 0x10000 );
0454 }
0455
0456 #endif
0457
0458 #if defined(_MSC_VER) && defined(_M_X64) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
0459
0460 BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0461 {
0462 if( __builtin_is_constant_evaluated() )
0463 {
0464 return static_cast<boost::uint32_t>( x ) != 0?
0465 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) ):
0466 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x >> 32 ) ) + 32;
0467 }
0468 else
0469 {
0470 unsigned long r;
0471
0472 if( _BitScanForward64( &r, x ) )
0473 {
0474 return static_cast<int>( r );
0475 }
0476 else
0477 {
0478 return 64;
0479 }
0480 }
0481 }
0482
0483 #elif defined(_MSC_VER) && defined(_M_X64)
0484
0485 inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0486 {
0487 unsigned long r;
0488
0489 if( _BitScanForward64( &r, x ) )
0490 {
0491 return static_cast<int>( r );
0492 }
0493 else
0494 {
0495 return 64;
0496 }
0497 }
0498
0499 #elif defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
0500
0501 BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0502 {
0503 return static_cast<boost::uint32_t>( x ) != 0?
0504 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) ):
0505 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x >> 32 ) ) + 32;
0506 }
0507
0508 #else
0509
0510 inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0511 {
0512 return static_cast<boost::uint32_t>( x ) != 0?
0513 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) ):
0514 boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x >> 32 ) ) + 32;
0515 }
0516
0517 #endif
0518
0519 }
0520
0521 template<class T>
0522 BOOST_CXX14_CONSTEXPR int countr_zero( T x ) BOOST_NOEXCEPT
0523 {
0524 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0525
0526 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) );
0527
0528 BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) )
0529 {
0530 return boost::core::detail::countr_impl( static_cast<boost::uint8_t>( x ) );
0531 }
0532 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) )
0533 {
0534 return boost::core::detail::countr_impl( static_cast<boost::uint16_t>( x ) );
0535 }
0536 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) )
0537 {
0538 return boost::core::detail::countr_impl( static_cast<boost::uint32_t>( x ) );
0539 }
0540 else
0541 {
0542 return boost::core::detail::countr_impl( static_cast<boost::uint64_t>( x ) );
0543 }
0544 }
0545
0546 #endif
0547
0548 template<class T>
0549 BOOST_CONSTEXPR int countr_one( T x ) BOOST_NOEXCEPT
0550 {
0551 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0552
0553 return boost::core::countr_zero( static_cast<T>( ~x ) );
0554 }
0555
0556
0557
0558 #if defined(__GNUC__) || defined(__clang__)
0559
0560 #if defined(__clang__) && __clang_major__ * 100 + __clang_minor__ < 304
0561 # define BOOST_CORE_POPCOUNT_CONSTEXPR
0562 #else
0563 # define BOOST_CORE_POPCOUNT_CONSTEXPR BOOST_CONSTEXPR
0564 #endif
0565
0566 namespace detail
0567 {
0568
0569 BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned char x ) BOOST_NOEXCEPT
0570 {
0571 return __builtin_popcount( x );
0572 }
0573
0574 BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned short x ) BOOST_NOEXCEPT
0575 {
0576 return __builtin_popcount( x );
0577 }
0578
0579 BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned int x ) BOOST_NOEXCEPT
0580 {
0581 return __builtin_popcount( x );
0582 }
0583
0584 BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned long x ) BOOST_NOEXCEPT
0585 {
0586 return __builtin_popcountl( x );
0587 }
0588
0589 BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT
0590 {
0591 return __builtin_popcountll( x );
0592 }
0593
0594 }
0595
0596 #undef BOOST_CORE_POPCOUNT_CONSTEXPR
0597
0598 template<class T>
0599 BOOST_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT
0600 {
0601 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0602
0603 return boost::core::detail::popcount_impl( x );
0604 }
0605
0606 #else
0607
0608 namespace detail
0609 {
0610
0611 BOOST_CXX14_CONSTEXPR inline int popcount_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0612 {
0613 x = x - ( ( x >> 1 ) & 0x55555555 );
0614 x = ( x & 0x33333333 ) + ( ( x >> 2 ) & 0x33333333 );
0615 x = ( x + ( x >> 4 ) ) & 0x0F0F0F0F;
0616
0617 return static_cast<unsigned>( ( x * 0x01010101 ) >> 24 );
0618 }
0619
0620 BOOST_CXX14_CONSTEXPR inline int popcount_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0621 {
0622 x = x - ( ( x >> 1 ) & 0x5555555555555555 );
0623 x = ( x & 0x3333333333333333 ) + ( ( x >> 2 ) & 0x3333333333333333 );
0624 x = ( x + ( x >> 4 ) ) & 0x0F0F0F0F0F0F0F0F;
0625
0626 return static_cast<unsigned>( ( x * 0x0101010101010101 ) >> 56 );
0627 }
0628
0629 }
0630
0631 template<class T>
0632 BOOST_CXX14_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT
0633 {
0634 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0635
0636 BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) );
0637
0638 BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) )
0639 {
0640 return boost::core::detail::popcount_impl( static_cast<boost::uint32_t>( x ) );
0641 }
0642 else
0643 {
0644 return boost::core::detail::popcount_impl( static_cast<boost::uint64_t>( x ) );
0645 }
0646 }
0647
0648 #endif
0649
0650
0651
0652 template<class T>
0653 BOOST_CXX14_CONSTEXPR T rotl( T x, int s ) BOOST_NOEXCEPT
0654 {
0655 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0656
0657 unsigned const mask = std::numeric_limits<T>::digits - 1;
0658 return static_cast<T>( x << (static_cast<unsigned>( s ) & mask) | x >> (static_cast<unsigned>( -s ) & mask) );
0659 }
0660
0661 template<class T>
0662 BOOST_CXX14_CONSTEXPR T rotr( T x, int s ) BOOST_NOEXCEPT
0663 {
0664 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0665
0666 unsigned const mask = std::numeric_limits<T>::digits - 1;
0667 return static_cast<T>( x >> (static_cast<unsigned>( s ) & mask) | x << (static_cast<unsigned>( -s ) & mask) );
0668 }
0669
0670
0671
0672 template<class T>
0673 BOOST_CONSTEXPR bool has_single_bit( T x ) BOOST_NOEXCEPT
0674 {
0675 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0676
0677 return x != 0 && ( x & ( x - 1 ) ) == 0;
0678 }
0679
0680
0681
0682
0683 template<class T>
0684 BOOST_CONSTEXPR int bit_width( T x ) BOOST_NOEXCEPT
0685 {
0686 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0687
0688 return std::numeric_limits<T>::digits - boost::core::countl_zero( x );
0689 }
0690
0691 template<class T>
0692 BOOST_CONSTEXPR T bit_floor( T x ) BOOST_NOEXCEPT
0693 {
0694 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0695
0696 return x == 0? T(0): static_cast<T>( T(1) << ( boost::core::bit_width( x ) - 1 ) );
0697 }
0698
0699 namespace detail
0700 {
0701
0702 BOOST_CXX14_CONSTEXPR inline boost::uint32_t bit_ceil_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0703 {
0704 if( x == 0 )
0705 {
0706 return 0;
0707 }
0708
0709 --x;
0710
0711 x |= x >> 1;
0712 x |= x >> 2;
0713 x |= x >> 4;
0714 x |= x >> 8;
0715 x |= x >> 16;
0716
0717 ++x;
0718
0719 return x;
0720 }
0721
0722 BOOST_CXX14_CONSTEXPR inline boost::uint64_t bit_ceil_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0723 {
0724 if( x == 0 )
0725 {
0726 return 0;
0727 }
0728
0729 --x;
0730
0731 x |= x >> 1;
0732 x |= x >> 2;
0733 x |= x >> 4;
0734 x |= x >> 8;
0735 x |= x >> 16;
0736 x |= x >> 32;
0737
0738 ++x;
0739
0740 return x;
0741 }
0742
0743 }
0744
0745 template<class T>
0746 BOOST_CXX14_CONSTEXPR T bit_ceil( T x ) BOOST_NOEXCEPT
0747 {
0748 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed );
0749
0750 BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) );
0751
0752 BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) )
0753 {
0754 return static_cast<T>( boost::core::detail::bit_ceil_impl( static_cast<boost::uint32_t>( x ) ) );
0755 }
0756 else
0757 {
0758 return static_cast<T>( boost::core::detail::bit_ceil_impl( static_cast<boost::uint64_t>( x ) ) );
0759 }
0760 }
0761
0762
0763
0764 #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
0765
0766 # define BOOST_CORE_BIT_NATIVE_INITIALIZER =little
0767
0768 #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
0769
0770 # define BOOST_CORE_BIT_NATIVE_INITIALIZER =big
0771
0772 #elif defined(__BYTE_ORDER__) && defined(__ORDER_PDP_ENDIAN__) && __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__
0773
0774 # define BOOST_CORE_BIT_NATIVE_INITIALIZER
0775
0776 #elif defined(__LITTLE_ENDIAN__)
0777
0778 # define BOOST_CORE_BIT_NATIVE_INITIALIZER =little
0779
0780 #elif defined(__BIG_ENDIAN__)
0781
0782 # define BOOST_CORE_BIT_NATIVE_INITIALIZER =big
0783
0784 #elif defined(_MSC_VER) || defined(__i386__) || defined(__x86_64__)
0785
0786 # define BOOST_CORE_BIT_NATIVE_INITIALIZER =little
0787
0788 #else
0789
0790 # define BOOST_CORE_BIT_NATIVE_INITIALIZER
0791
0792 #endif
0793
0794 #if !defined(BOOST_NO_CXX11_SCOPED_ENUMS)
0795
0796 enum class endian
0797 {
0798 big,
0799 little,
0800 native BOOST_CORE_BIT_NATIVE_INITIALIZER
0801 };
0802
0803 typedef endian endian_type;
0804
0805 #else
0806
0807 namespace endian
0808 {
0809
0810 enum type
0811 {
0812 big,
0813 little,
0814 native BOOST_CORE_BIT_NATIVE_INITIALIZER
0815 };
0816
0817 }
0818
0819 typedef endian::type endian_type;
0820
0821 #endif
0822
0823 #undef BOOST_CORE_BIT_NATIVE_INITIALIZER
0824
0825
0826
0827 namespace detail
0828 {
0829
0830 BOOST_CONSTEXPR inline boost::uint8_t byteswap_impl( boost::uint8_t x ) BOOST_NOEXCEPT
0831 {
0832 return x;
0833 }
0834
0835 #if defined(BOOST_CORE_HAS_BUILTIN_BSWAP16)
0836
0837 BOOST_CONSTEXPR inline boost::uint16_t byteswap_impl( boost::uint16_t x ) BOOST_NOEXCEPT
0838 {
0839 return __builtin_bswap16( x );
0840 }
0841
0842 #else
0843
0844 BOOST_CONSTEXPR inline boost::uint16_t byteswap_impl( boost::uint16_t x ) BOOST_NOEXCEPT
0845 {
0846 return static_cast<boost::uint16_t>( x << 8 | x >> 8 );
0847 }
0848
0849 #endif
0850
0851 #if defined(__GNUC__) || defined(__clang__)
0852
0853 BOOST_CXX14_CONSTEXPR inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0854 {
0855 return __builtin_bswap32( x );
0856 }
0857
0858 BOOST_CXX14_CONSTEXPR inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0859 {
0860 return __builtin_bswap64( x );
0861 }
0862
0863 #elif defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL)
0864
0865 BOOST_CXX14_CONSTEXPR inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0866 {
0867 if( __builtin_is_constant_evaluated() )
0868 {
0869 boost::uint32_t step16 = x << 16 | x >> 16;
0870 return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff);
0871 }
0872 else
0873 {
0874 return _byteswap_ulong( x );
0875 }
0876 }
0877
0878 BOOST_CXX14_CONSTEXPR inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0879 {
0880 if( __builtin_is_constant_evaluated() )
0881 {
0882 boost::uint64_t step32 = x << 32 | x >> 32;
0883 boost::uint64_t step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
0884 return (step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8;
0885 }
0886 else
0887 {
0888 return _byteswap_uint64( x );
0889 }
0890 }
0891
0892 #elif defined(_MSC_VER)
0893
0894 inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0895 {
0896 return _byteswap_ulong( x );
0897 }
0898
0899 inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0900 {
0901 return _byteswap_uint64( x );
0902 }
0903
0904 #else
0905
0906 BOOST_CXX14_CONSTEXPR inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT
0907 {
0908 boost::uint32_t step16 = x << 16 | x >> 16;
0909 return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff);
0910 }
0911
0912 BOOST_CXX14_CONSTEXPR inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT
0913 {
0914 boost::uint64_t step32 = x << 32 | x >> 32;
0915 boost::uint64_t step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
0916 return (step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8;
0917 }
0918
0919 #endif
0920
0921 }
0922
0923 template<class T> BOOST_CXX14_CONSTEXPR T byteswap( T x ) BOOST_NOEXCEPT
0924 {
0925 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_integer );
0926
0927 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) );
0928
0929 BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) )
0930 {
0931 return static_cast<T>( boost::core::detail::byteswap_impl( static_cast<boost::uint8_t>( x ) ) );
0932 }
0933 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) )
0934 {
0935 return static_cast<T>( boost::core::detail::byteswap_impl( static_cast<boost::uint16_t>( x ) ) );
0936 }
0937 else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) )
0938 {
0939 return static_cast<T>( boost::core::detail::byteswap_impl( static_cast<boost::uint32_t>( x ) ) );
0940 }
0941 else
0942 {
0943 return static_cast<T>( boost::core::detail::byteswap_impl( static_cast<boost::uint64_t>( x ) ) );
0944 }
0945 }
0946
0947 }
0948 }
0949
0950 #if defined(_MSC_VER)
0951 # pragma warning(pop)
0952 #endif
0953
0954 #endif