35 return (value & (value - 1)) == 0;
62 return (
static_cast<u32
>(-1) >> (31 - b)) & ~((1u << a) - 1);
82 return static_cast<u32
>(std::popcount(v));
87 return static_cast<u8
>(std::countl_zero(v));
92 return static_cast<u8
>(std::countl_zero(v));
97 return static_cast<u8
>(std::countl_zero(v));
102 return static_cast<u8
>(std::countl_zero(v));
107 return static_cast<u8
>(std::countr_zero(v));
112 return static_cast<u8
>(std::countr_zero(v));
117 return static_cast<u8
>(std::countr_zero(v));
122 return static_cast<u8
>(std::countr_zero(v));
131 return lzcnt(
static_cast<u8
>(v));
140 return lzcnt(
static_cast<u16
>(v));
149 return lzcnt(
static_cast<u32
>(v));
158 return lzcnt(
static_cast<u64
>(v));
167 return tzcnt(
static_cast<u8
>(v));
176 return tzcnt(
static_cast<u16
>(v));
185 return tzcnt(
static_cast<u32
>(v));
194 return tzcnt(
static_cast<u64
>(v));
207 *out_first_set_index =
static_cast<u32
>(std::countr_zero(v));
221 *out_first_set_index =
static_cast<u32
>(std::countr_zero(v));
254 return sizeof(T) * 8 - 1 -
lzcnt(v);
264 return sizeof(T) * 8 -
lzcnt(v - 1);
275 return (v << sh) | (v >> ((
sizeof(T) * 8) - sh));
318 const std::vector<u64>
GetWords()
const {
return data_; }
320 std::vector<u64>& GetWords() {
return data_; }
323 const static size_t kDataSize = 8;
324 const static size_t kDataSizeBits = kDataSize * 8;
325 std::vector<u64> data_;
337template <
typename Block>
340 return std::make_pair(first,
static_cast<size_t>(0));
342 size_t last = first + length - 1;
343 const size_t block_bits =
sizeof(Block) * CHAR_BIT;
344 size_t block_first = first / block_bits;
345 size_t block_last = last / block_bits;
346 size_t range_start = SIZE_MAX;
347 for (
size_t i = block_first; i <= block_last; ++i) {
348 Block block = bits[i];
349 if (i == block_first) {
350 block |= (Block(1) << (first & (block_bits - 1))) - 1;
352 if (i == block_last && (last & (block_bits - 1)) != block_bits - 1) {
353 block |= ~((Block(1) << ((last & (block_bits - 1)) + 1)) - 1);
357 if (range_start == SIZE_MAX) {
361 range_start = i * block_bits + block_bit;
363 Block block_bits_set_from_start = block;
364 if (i == range_start / block_bits) {
365 block_bits_set_from_start &= ~((Block(1) << (range_start & (block_bits - 1))) - 1);
370 return std::make_pair(range_start, (i * block_bits) + block_bit - range_start);
374 if (range_start != SIZE_MAX) {
375 return std::make_pair(range_start, last +
static_cast<size_t>(1) - range_start);
377 return std::make_pair(first + length,
static_cast<size_t>(0));
388template <
typename Block>
389void SetRange(Block* bits,
size_t first,
size_t length) {
393 size_t last = first + length - 1;
394 const size_t block_bits =
sizeof(Block) * CHAR_BIT;
395 size_t block_first = first / block_bits;
396 size_t block_last = last / block_bits;
397 Block set_first = ~((Block(1) << (first & (block_bits - 1))) - 1);
398 Block set_last = ~Block(0);
399 if ((last & (block_bits - 1)) != (block_bits - 1)) {
400 set_last &= (Block(1) << ((last & (block_bits - 1)) + 1)) - 1;
402 if (block_first == block_last) {
403 bits[block_first] |= set_first & set_last;
406 bits[block_first] |= set_first;
407 if (block_first + 1 < block_last) {
408 std::fill_n(bits + block_first + 1, block_last - (block_first + 1), ~Block(0));
410 bits[block_last] |= set_last;
428template <FlagsEnum E>
429[[nodiscard]]
constexpr E operator|(E lhs, E rhs) {
430 return static_cast<E
>(std::to_underlying(lhs) | std::to_underlying(rhs));
433template <FlagsEnum E>
434[[nodiscard]]
constexpr E operator&(E lhs, E rhs) {
435 return static_cast<E
>(std::to_underlying(lhs) & std::to_underlying(rhs));
438template <FlagsEnum E>
439[[nodiscard]]
constexpr E operator^(E lhs, E rhs) {
440 return static_cast<E
>(std::to_underlying(lhs) ^ std::to_underlying(rhs));
443template <FlagsEnum E>
444[[nodiscard]]
constexpr E operator~(E value) {
445 return static_cast<E
>(~std::to_underlying(value));
453template <FlagsEnum E>
464template <FlagsEnum E>
475template <FlagsEnum E>
482template <FlagsEnum E>
483[[nodiscard]]
constexpr bool HasFlags(E value, E flags) {
484 return (value & flags) == flags;
494#define REX_RESTRICT_VAR __restrict
497template <
typename Dst,
typename Src>
499 static_assert(
sizeof(Dst) ==
sizeof(Src));
500 static_assert(std::is_trivially_copyable_v<Dst>);
501 static_assert(std::is_trivially_copyable_v<Src>);
502 dst = std::bit_cast<Dst>(src);
506template <
typename Dst,
typename Src>
518inline bool AreBitsEqual(std::span<const f32> a, std::span<const f32> b) {
519 return std::ranges::equal(
520 a, b, [](f32 x, f32 y) {
return std::bit_cast<u32>(x) == std::bit_cast<u32>(y); });
#define REX_RESTRICT_VAR
Definition bit.h:494
BitMap(u64 *data, size_t size_bits)
const std::vector< u64 > GetWords() const
Definition bit.h:318
void ReleaseEntry(size_t index)
void Resize(size_t new_size_bits)
constexpr bool is_flags_enum
Definition bit.h:422
constexpr E & operator&=(E &lhs, E rhs)
Definition bit.h:465
void Reinterpret(Dst &REX_RESTRICT_VAR dst, const Src &REX_RESTRICT_VAR src)
Definition bit.h:498
constexpr u32 select_bits(u32 value, u32 a, u32 b)
Definition bit.h:71
T log2_floor(T v)
Definition bit.h:253
u8 tzcnt(u8 v)
Definition bit.h:106
constexpr bool is_pow2(T value)
Definition bit.h:34
constexpr bool HasFlags(E value, E flags)
Definition bit.h:483
bool AreBitsEqual(std::span< const f32 > a, std::span< const f32 > b)
Definition bit.h:518
constexpr u32 BitCount(T v)
Definition bit.h:81
T RotateLeft(T v, u8 sh)
Definition bit.h:274
T log2_ceil(T v)
Definition bit.h:263
void SetRange(Block *bits, size_t first, size_t length)
Definition bit.h:389
bool bit_scan_forward(u32 v, u32 *out_first_set_index)
Definition bit.h:203
constexpr u32 MakeBitmask(u32 a, u32 b)
Definition bit.h:61
u8 lzcnt(u8 v)
Definition bit.h:86
constexpr E & operator|=(E &lhs, E rhs)
Definition bit.h:454
T next_pow2(T value)
Definition bit.h:44
std::pair< size_t, size_t > GetNextRangeUnset(const Block *bits, size_t first, size_t length)
Definition bit.h:338
constexpr E & operator^=(E &lhs, E rhs)
Definition bit.h:476
Integer types, byte order wrappers and size literals.