9#ifndef HPP_ALIB_LANG_BITS
10#define HPP_ALIB_LANG_BITS 1
12#if !defined(HPP_ALIB_LANG_INTEGERS)
16#if !defined (HPP_ALIB_LANG_TMP) && !defined(ALIB_DOX)
20#if defined(_WIN32) && !defined (__INTRIN_H_)
24#if !defined (_GLIBCXX_ITERATOR) && !defined (_ITERATOR_)
52#define bitsof(type) static_cast<int>(sizeof(type) * 8)
68template<
typename T>
inline constexpr int bitsofval(
const T& val)
70 (void) val;
return sizeof(T) * 8;
87 template<ShiftOpRHS TW
idth,
typename TIntegral>
92 template<ShiftOpRHS TW
idth,
typename TIntegral>
93 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value && TWidth >=
bitsof(TIntegral) )
97 return TIntegral(~TIntegral(0));
100 template<ShiftOpRHS TW
idth,
typename TIntegral>
101 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value && TWidth <
bitsof(TIntegral) )
106 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
107 return TIntegral(~(TUnsigned(~TUnsigned(0)) << TWidth) );
126 template<
typename TIntegral>
130 template<
typename TIntegral>
131 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value )
137 "Requested mask width wider than integral: ", width )
138 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
139 return TIntegral(~(TUnsigned(~TUnsigned(0)) << width ));
157 template<ShiftOpRHS TW
idth,
typename TIntegral>
162 template<ShiftOpRHS TW
idth,
typename TIntegral>
163 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value && TWidth >=
bitsof(TIntegral))
169 template<ShiftOpRHS TW
idth,
typename TIntegral>
170 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value && TWidth <
bitsof(TIntegral) )
174 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
175 return TIntegral((TUnsigned(~TUnsigned(0)) << TWidth));
193 template<
typename TIntegral>
197 template<
typename TIntegral>
198 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value )
203 "Requested mask width wider than integral: ", width )
204 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
205 return TIntegral( (TUnsigned(~TUnsigned(0)) << width) );
225 template<ShiftOpRHS TW
idth,
typename TIntegral>
inline constexpr TIntegral
LowerBits( TIntegral value );
227 template<ShiftOpRHS TW
idth,
typename TIntegral>
228 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value )
232 if constexpr ( TWidth >=
bitsof(TIntegral) )
234 return value & LowerMask<TWidth,TIntegral>( );
256 template<
typename TIntegral>
257 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value )
261 return value & LowerMask<TIntegral>( width );
277 template<
typename TIntegral>
inline constexpr int Log2OfSize();
279 template<
typename TIntegral>
280 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
284 static_assert(
bitsof(TIntegral) <= 128,
"Integrals larger than 128 not supported.");
285 if constexpr (
bitsof(TIntegral) == 32)
return 5;
286 if constexpr (
bitsof(TIntegral) == 64)
return 7;
287 if constexpr (
bitsof(TIntegral) == 8)
return 3;
288 if constexpr (
bitsof(TIntegral) == 16)
return 4;
306 template<
typename TIntegral>
constexpr int BitCount( TIntegral value );
310 namespace {
inline int countBitsFast(uint32_t n)
312 n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u);
313 n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u);
314 n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu);
315 n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu);
316 n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu);
321 template<
typename TIntegral>
322 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
328 using TUnsigned =
typename std::make_unsigned<TIntegral>::type;
329 if constexpr (
bitsof(TIntegral) <= 32 )
330 return __popcnt (
static_cast<TUnsigned
>( value ));
331 return __popcnt64 (
static_cast<TUnsigned
>( value ));
332#elif defined(__has_builtin) && __has_builtin( __builtin_popcount )
333 using TUnsigned =
typename std::make_unsigned<TIntegral>::type;
335 if constexpr (
sizeof(TIntegral) ==
sizeof(
long long))
return int(__builtin_popcountll( TUnsigned(value) ));
336 if constexpr (
sizeof(TIntegral) ==
sizeof(
long ))
return int(__builtin_popcountl ( TUnsigned(value) ));
337 if constexpr (
sizeof(TIntegral) ==
sizeof(
int ))
return int(__builtin_popcount ( TUnsigned(value) ));
338 return int(__builtin_popcountll(
static_cast<unsigned long long>(value)));
340 if constexpr (
bitsof(TIntegral) <= 32)
341 return countBitsFast(uint32_t(value));
342 return countBitsFast(uint32_t(value) & 0xFFFFFFFF)
343 + countBitsFast(uint32_t(value >> 32));
367 template<
typename TIntegral>
constexpr int CLZ( TIntegral value );
369 template<
typename TIntegral>
370 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
372 CLZ( TIntegral value )
375 "Illegal value 0 passed to MSB(). Use MSB0() if 0 values need to be handled." )
378 unsigned long bitScanResult;
379 if constexpr (
bitsof(TIntegral) <= 32 )
381 _BitScanReverse( &bitScanResult,
static_cast<unsigned long>(value) );
382 return bitsof(TIntegral) -
bitsof(
unsigned long) + 31 - bitScanResult;
386 _BitScanReverse64( &bitScanResult, uint64_t(value) );
387 return bitsof(TIntegral) -
bitsof(uint64_t) + 63 - bitScanResult;
389 #elif defined(__has_builtin) && __has_builtin( __builtin_clz ) \
390 && __has_builtin( __builtin_clzl ) \
391 && __has_builtin( __builtin_clzll )
392 if constexpr (
sizeof(TIntegral) ==
sizeof(
int ))
return int(__builtin_clz (
static_cast<unsigned int >(value) ));
393 if constexpr (
sizeof(TIntegral) ==
sizeof(
long ))
return int(__builtin_clzl (
static_cast<unsigned long >(value) ));
394 if constexpr (
sizeof(TIntegral) ==
sizeof(
long long))
return int(__builtin_clzll(
static_cast<unsigned long long>(value) ));
395 return bitsof(TIntegral) -
bitsof(
int) + int(__builtin_clz (
static_cast<unsigned int >(value) ));
404 if( (TIntegral(1) << mid) > value )
412 return bitsof(TIntegral) -1 - msb;
428 template<
typename TIntegral>
constexpr int CLZ0( TIntegral value);
430 template<
typename TIntegral>
431 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
433 CLZ0( TIntegral value)
460 template<
typename TIntegral>
constexpr int CTZ( TIntegral value );
462 template<
typename TIntegral>
463 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
465 CTZ( TIntegral value )
468 "Illegal value 0 passed to MSB(). Use MSB0() if 0 values need to be handled." )
471 unsigned long bitScanResult;
472 if constexpr (
bitsof(TIntegral) <= 32 )
474 _BitScanForward( &bitScanResult,
static_cast<unsigned long>(value) );
475 return bitScanResult;
477 _BitScanForward64( &bitScanResult, uint64_t(value) );
478 return bitScanResult;
480#elif defined(__has_builtin) && __has_builtin( __builtin_ctz ) \
481 && __has_builtin( __builtin_ctzl ) \
482 && __has_builtin( __builtin_ctzll )
483 if constexpr (
sizeof(TIntegral) ==
sizeof(
int ))
return int(__builtin_ctz (
static_cast<unsigned int >(value) ));
484 if constexpr (
sizeof(TIntegral) ==
sizeof(
long ))
return int(__builtin_ctzl (
static_cast<unsigned long >(value) ));
485 if constexpr (
sizeof(TIntegral) ==
sizeof(
long long))
return int(__builtin_ctzll(
static_cast<unsigned long long>(value) ));
486 return int(__builtin_ctz (
static_cast<unsigned int >(value) ));
490 int width=
bitsof(TIntegral) / 2;
491 TIntegral mask= LowerMask<TIntegral>(width);
494 if( (value & mask) == 0 )
520 template<
typename TIntegral>
constexpr int CTZ0( TIntegral value);
522 template<
typename TIntegral>
523 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
525 CTZ0( TIntegral value)
555 template<
typename TIntegral>
constexpr int MSB( TIntegral value);
557 template<
typename TIntegral>
558 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
560 MSB( TIntegral value)
563 "Illegal value 0 passed to MSB(). Use MSB0() if 0 values need to be handled." )
579 template<
typename TIntegral>
constexpr int MSB0( TIntegral value);
582 template<
typename TIntegral>
583 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
586 MSB0( TIntegral value)
#define ALIB_WARNINGS_IGNORE_INTEGRAL_CONSTANT_OVERFLOW
#define ALIB_WARNINGS_RESTORE
#define ALIB_FORCE_INLINE
#define ALIB_ASSERT_ERROR(cond,...)
#define ATMP_T_IF(T, Cond)
constexpr int bitsofval(const T &val)
constexpr int BitCount(TIntegral value)
constexpr int CLZ(TIntegral value)
constexpr TIntegral LowerMask()
constexpr int MSB0(TIntegral value)
constexpr int Log2OfSize()
constexpr int CLZ0(TIntegral value)
constexpr int MSB(TIntegral value)
constexpr int CTZ0(TIntegral value)
constexpr int CTZ(TIntegral value)
constexpr TIntegral LowerBits(TIntegral value)
constexpr TIntegral UpperMask()