54class SuccinctIncreasingStack {
56 explicit SuccinctIncreasingStack(std::size_t capacity)
57 : words_(word_count(capacity)),
58 nonempty_words_(word_count(words_.size())),
59 nonempty_super_words_(word_count(nonempty_words_.size())),
60 capacity_(capacity) {}
65 bool empty()
const {
return size_ == 0; }
72 std::size_t
top()
const {
84 void push(std::size_t key) {
85 assert(key < capacity_);
88 const std::size_t block = block_index(key);
89 words_[block] |= std::uint64_t{1} << block_position(key);
103 const std::size_t block = block_index(top_key_);
104 std::uint64_t word = words_[block];
105 word &= ~(std::uint64_t{1} << block_position(top_key_));
106 words_[block] = word;
111 clear_nonempty(block);
118 top_key_ = block * kBlockBits + highest_bit(word);
122 clear_nonempty(block);
123 const std::size_t previous_block = previous_nonempty_block(block);
124 const std::uint64_t previous_word = words_[previous_block];
125 assert(previous_word != 0);
126 top_key_ = previous_block * kBlockBits + highest_bit(previous_word);
130 static constexpr std::size_t kBlockBits = 64;
131 static constexpr std::size_t kBlockShift = 6;
132 static constexpr std::size_t kBlockMask = kBlockBits - 1;
134 static std::size_t word_count(std::size_t bit_count) {
135 return (bit_count + kBlockBits - 1) / kBlockBits;
138 static std::size_t block_index(std::size_t key) {
return key >> kBlockShift; }
140 static std::size_t block_position(std::size_t key) {
141 return key & kBlockMask;
144 static std::size_t highest_bit(std::uint64_t word) {
146 return static_cast<std::size_t
>(std::bit_width(word) - 1);
149 static std::uint64_t low_bits(std::size_t count) {
150 return count == 0 ? 0 : ((std::uint64_t{1} << count) - 1);
153 void set_nonempty(std::size_t block) {
154 const std::size_t summary = block_index(block);
155 const std::uint64_t bit = std::uint64_t{1} << block_position(block);
156 if ((nonempty_words_[summary] & bit) == 0) {
157 nonempty_words_[summary] |= bit;
158 nonempty_super_words_[block_index(summary)] |= std::uint64_t{1}
159 << block_position(summary);
163 void clear_nonempty(std::size_t block) {
164 const std::size_t summary = block_index(block);
165 nonempty_words_[summary] &= ~(std::uint64_t{1} << block_position(block));
166 if (nonempty_words_[summary] == 0) {
167 nonempty_super_words_[block_index(summary)] &=
168 ~(std::uint64_t{1} << block_position(summary));
172 std::size_t previous_nonempty_block(std::size_t block)
const {
174 std::size_t summary = block_index(block);
175 const std::size_t summary_position = block_position(block);
176 if (summary_position != 0) {
177 const std::uint64_t same_summary =
178 nonempty_words_[summary] & low_bits(summary_position);
179 if (same_summary != 0) {
180 return summary * kBlockBits + highest_bit(same_summary);
184 std::size_t super = block_index(summary);
185 const std::size_t super_position = block_position(summary);
186 std::uint64_t super_mask =
189 : nonempty_super_words_[super] & low_bits(super_position);
190 while (super_mask == 0) {
193 super_mask = nonempty_super_words_[super];
196 const std::size_t previous_summary =
197 super * kBlockBits + highest_bit(super_mask);
198 assert(previous_summary < nonempty_words_.size());
199 const std::uint64_t previous_summary_word =
200 nonempty_words_[previous_summary];
201 assert(previous_summary_word != 0);
202 return previous_summary * kBlockBits + highest_bit(previous_summary_word);
205 std::vector<std::uint64_t> words_;
206 std::vector<std::uint64_t> nonempty_words_;
207 std::vector<std::uint64_t> nonempty_super_words_;
208 std::size_t capacity_ = 0;
209 std::size_t size_ = 0;
210 std::size_t top_key_ = 0;