9#ifndef HPP_ALIB_LANG_BITS
10#define HPP_ALIB_LANG_BITS 1
18#if ALIB_CPP_STANDARD >= 20
49#define bitsof(type) static_cast<int>(sizeof(type) * 8)
63template<
typename T>
inline constexpr int bitsofval(
const T& val)
65 (void) val;
return sizeof(T) * 8;
80 template<ShiftOpRHS TW
idth,
typename TIntegral>
85 template<ShiftOpRHS TW
idth,
typename TIntegral>
86 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value && TWidth >=
bitsof(TIntegral) )
90 return TIntegral(~TIntegral(0));
93 template<ShiftOpRHS TW
idth,
typename TIntegral>
94 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value && TWidth <
bitsof(TIntegral) )
99 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
100 return TIntegral(~(TUnsigned(~TUnsigned(0)) << TWidth) );
117 template<
typename TIntegral>
121 template<
typename TIntegral>
122 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value )
128 "Requested mask width wider than integral: ", width )
129 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
130 return TIntegral(~(TUnsigned(~TUnsigned(0)) << width ));
146 template<ShiftOpRHS TW
idth,
typename TIntegral>
151 template<ShiftOpRHS TW
idth,
typename TIntegral>
152 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value && TWidth >=
bitsof(TIntegral))
158 template<ShiftOpRHS TW
idth,
typename TIntegral>
159 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value && TWidth <
bitsof(TIntegral) )
163 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
164 return TIntegral((TUnsigned(~TUnsigned(0)) << TWidth));
180 template<
typename TIntegral>
184 template<
typename TIntegral>
185 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value )
190 "Requested mask width wider than integral: ", width )
191 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
192 return TIntegral( (TUnsigned(~TUnsigned(0)) << width) );
210 template<ShiftOpRHS TW
idth,
typename TIntegral>
inline constexpr TIntegral
LowerBits( TIntegral value );
212 template<ShiftOpRHS TW
idth,
typename TIntegral>
213 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value )
217 if constexpr ( TWidth >=
bitsof(TIntegral) )
239 template<
typename TIntegral>
240 ATMP_T_IF(TIntegral, std::is_integral<TIntegral>::value )
258 template<
typename TIntegral>
inline constexpr int Log2OfSize();
260 template<
typename TIntegral>
261 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
265 static_assert(
bitsof(TIntegral) <= 128,
"Integrals larger than 128 are not supported.");
266 if constexpr (
bitsof(TIntegral) == 32)
return 5;
267 if constexpr (
bitsof(TIntegral) == 64)
return 7;
268 if constexpr (
bitsof(TIntegral) == 8)
return 3;
269 if constexpr (
bitsof(TIntegral) == 16)
return 4;
285 template<
typename TIntegral>
constexpr int BitCount( TIntegral value );
289 namespace {
inline int countBitsFast(uint32_t n)
291 n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u);
292 n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u);
293 n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu);
294 n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu);
295 n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu);
300 template<
typename TIntegral>
301 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
306 #if ALIB_CPP_STANDARD >= 20
307 return std::popcount(
static_cast<typename std::make_unsigned<TIntegral>::type
>( value ) );
308 #elif defined(_WIN64)
309 using TUnsigned =
typename std::make_unsigned<TIntegral>::type;
310 if constexpr (
bitsof(TIntegral) <= 32 )
311 return __popcnt (
static_cast<TUnsigned
>( value ));
312 return int(__popcnt64 (
static_cast<TUnsigned
>( value )));
313 #elif defined(__has_builtin) && __has_builtin( __builtin_popcount )
314 using TUnsigned =
typename std::make_unsigned<TIntegral>::type;
316 if constexpr (
sizeof(TIntegral) ==
sizeof(
long long))
return int(__builtin_popcountll( TUnsigned(value) ));
317 if constexpr (
sizeof(TIntegral) ==
sizeof(long ))
return int(__builtin_popcountl ( TUnsigned(value) ));
318 if constexpr (
sizeof(TIntegral) ==
sizeof(int ))
return int(__builtin_popcount ( TUnsigned(value) ));
319 return int(__builtin_popcountll(
static_cast<unsigned long long>(value)));
321 if constexpr (
bitsof(TIntegral) <= 32)
322 return countBitsFast(uint32_t(value));
323 return countBitsFast(uint32_t(value) & 0xFFFFFFFF)
324 + countBitsFast(uint32_t(value >> 32));
346 template<
typename TIntegral>
constexpr int CLZ( TIntegral value );
348 template<
typename TIntegral>
349 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
351 CLZ( TIntegral value )
354 "Illegal value 0 passed to MSB(). Use MSB0() if 0 values need to be handled." )
356 #if ALIB_CPP_STANDARD >= 20
357 return std::countl_zero(
static_cast<typename std::make_unsigned<TIntegral>::type
>( value ) );
359 #elif defined(_WIN64)
360 unsigned long bitScanResult;
361 if constexpr (
bitsof(TIntegral) <= 32 )
363 _BitScanReverse( &bitScanResult,
static_cast<unsigned long>(value) );
364 return bitsof(TIntegral) -
bitsof(
unsigned long) + 31 - bitScanResult;
368 _BitScanReverse64( &bitScanResult, uint64_t(value) );
369 return bitsof(TIntegral) -
bitsof(uint64_t) + 63 - bitScanResult;
371 #elif defined(__has_builtin) && __has_builtin( __builtin_clz ) \
372 && __has_builtin( __builtin_clzl ) \
373 && __has_builtin( __builtin_clzll )
374 if constexpr (
sizeof(TIntegral) ==
sizeof(int ))
return int(__builtin_clz (
static_cast<unsigned int >(value) ));
375 if constexpr (
sizeof(TIntegral) ==
sizeof(long ))
return int(__builtin_clzl (
static_cast<unsigned long >(value) ));
376 if constexpr (
sizeof(TIntegral) ==
sizeof(
long long))
return int(__builtin_clzll(
static_cast<unsigned long long>(value) ));
377 return bitsof(TIntegral) -
bitsof(
int) + int(__builtin_clz (
static_cast<unsigned int >(value) ));
386 if( (TIntegral(1) << mid) > value )
394 return bitsof(TIntegral) -1 - msb;
408 template<
typename TIntegral>
constexpr int CLZ0( TIntegral value);
410 template<
typename TIntegral>
411 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
413 CLZ0( TIntegral value)
438 template<
typename TIntegral>
constexpr int CTZ( TIntegral value );
440 template<
typename TIntegral>
441 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
443 CTZ( TIntegral value )
446 "Illegal value 0 passed to MSB(). Use MSB0() if 0 values need to be handled." )
448 #if ALIB_CPP_STANDARD >= 20
449 return std::countr_zero(
static_cast<typename std::make_unsigned<TIntegral>::type
>( value ) );
451 #elif defined(_WIN64)
452 unsigned long bitScanResult;
453 if constexpr (
bitsof(TIntegral) <= 32 )
455 _BitScanForward( &bitScanResult,
static_cast<unsigned long>(value) );
456 return bitScanResult;
458 _BitScanForward64( &bitScanResult, uint64_t(value) );
459 return bitScanResult;
461#elif defined(__has_builtin) && __has_builtin( __builtin_ctz ) \
462 && __has_builtin( __builtin_ctzl ) \
463 && __has_builtin( __builtin_ctzll )
464 if constexpr (
sizeof(TIntegral) ==
sizeof(int ))
return int(__builtin_ctz (
static_cast<unsigned int >(value) ));
465 if constexpr (
sizeof(TIntegral) ==
sizeof(long ))
return int(__builtin_ctzl (
static_cast<unsigned long >(value) ));
466 if constexpr (
sizeof(TIntegral) ==
sizeof(
long long))
return int(__builtin_ctzll(
static_cast<unsigned long long>(value) ));
467 return int(__builtin_ctz (
static_cast<unsigned int >(value) ));
471 int width=
bitsof(TIntegral) / 2;
475 if( (value & mask) == 0 )
499 template<
typename TIntegral>
constexpr int CTZ0( TIntegral value);
501 template<
typename TIntegral>
502 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
504 CTZ0( TIntegral value)
532 template<
typename TIntegral>
constexpr int MSB( TIntegral value);
534 template<
typename TIntegral>
535 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
537 MSB( TIntegral value)
540 "Illegal value 0 passed to MSB(). Use MSB0() if 0 values need to be handled." )
554 template<
typename TIntegral>
constexpr int MSB0( TIntegral value);
557 template<
typename TIntegral>
558 ATMP_T_IF(
int, std::is_integral<TIntegral>::value )
561 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()
int ShiftOpRHS
Type alias in namespace alib.