8#include "cplib/port/bit.hpp"
9#include "cplib/utils/bit.hpp"
15class alignas(64) BitDictBlock {
17 using size_type = std::size_t;
18 using word_type = std::uint64_t;
19 static constexpr size_type words_per_block = 6;
20 static constexpr size_type word_size = std::numeric_limits<word_type>::digits;
21 static constexpr size_type block_size = word_size * words_per_block;
23 BitDictBlock() : data_({0}) {}
25 size_type build(size_type block_rank) {
26 block_rank_ = block_rank;
27 wrap_word_ = words_per_block;
28 size_type acc_rank = 0;
29 for (
int i = 0; i < words_per_block; i++) {
30 if (acc_rank >= 256 && wrap_word_ == words_per_block) {
33 word_rank_[i] = acc_rank;
34 acc_rank += port::popcount(data_[i]);
36 return block_rank_ + acc_rank;
39 bool get(size_type idx)
const {
return (data_[idx / word_size] >> (idx % word_size)) & 1; }
41 void set(size_type idx) { data_[idx / word_size] |= word_type(1) << (idx % word_size); }
43 size_type rank(size_type idx)
const {
44 size_type word_idx = idx / word_size;
45 return block_rank_ + get_word_rank_(word_idx) + impl::popcount_low(data_[word_idx], idx % word_size);
49 size_type get_word_rank_(size_type idx)
const {
return word_rank_[idx] + (idx >= wrap_word_) * 256; }
51 std::array<word_type, words_per_block> data_;
52 size_type block_rank_;
53 std::array<std::uint8_t, words_per_block> word_rank_;
54 std::uint8_t wrap_word_;
57static_assert(
sizeof(BitDictBlock) == 64);
75 using size_type = impl::BitDictBlock::size_type;
85 BitDict(size_type num_bits) : size_(num_bits), blocks_(num_bits / block_size + 1) {}
88 size_type
size()
const {
return size_; }
91 size_type
zeros()
const {
return zeros_; }
94 size_type
ones()
const {
return size_ - zeros_; }
97 bool get(size_type idx)
const {
return blocks_[idx / block_size].get(idx % block_size); }
104 void set(size_type idx) { blocks_[idx / block_size].set(idx % block_size); }
111 template <
typename BitGenerator>
113 for (size_type i = 0; i < size_; i++) {
122 size_type acc_rank = 0;
123 for (
auto& block : blocks_) {
124 acc_rank = block.build(acc_rank);
126 zeros_ = size_ - acc_rank;
134 size_type
rank1(size_type idx)
const {
return blocks_[idx / block_size].rank(idx % block_size); }
138 size_type
rank0(size_type idx)
const {
return idx -
rank1(idx); }
154 static constexpr size_type block_size = impl::BitDictBlock::block_size;
155 std::vector<impl::BitDictBlock> blocks_;
156 size_type size_, zeros_;
Static bit sequence with rank query in .
Definition: bit_dict.hpp:73
size_type zeros() const
Returns the number of zero bits.
Definition: bit_dict.hpp:91
size_type rank_to_child(size_type idx, bool bit) const
Move one level downwards in a wavelet tree.
Definition: bit_dict.hpp:151
void fill_with_bit_generator(BitGenerator &gen)
Overwrite all bits with a bit generator.
Definition: bit_dict.hpp:112
size_type ones() const
Returns the number of one bits.
Definition: bit_dict.hpp:94
size_type size() const
Returns the number of bits.
Definition: bit_dict.hpp:88
BitDict()
Creates an empty BitDict.
Definition: bit_dict.hpp:78
BitDict(size_type num_bits)
Creates a BitDict with num_bits bits, all initialized to 0.
Definition: bit_dict.hpp:85
size_type rank1(size_type idx) const
Returns the number of 1 bits in the range [0, idx).
Definition: bit_dict.hpp:134
bool get(size_type idx) const
Read-only access to a bit. Requires 0 <= idx < size()
Definition: bit_dict.hpp:97
void build()
Set up auxiliary data to prepare for rank queries.
Definition: bit_dict.hpp:121
size_type rank0(size_type idx) const
Returns the number of 0 bits in the range [0, idx).
Definition: bit_dict.hpp:138
void set(size_type idx)
Set a bit to 1. Requires 0 <= idx < size().
Definition: bit_dict.hpp:104