40#include "pasta/bit_vector/bit_vector.hpp"
41#include "pasta/bit_vector/support/l12_type.hpp"
44#include "pasta/bit_vector/support/rank.hpp"
50#include <tlx/container/simple_vector.hpp>
76 typename VectorType = BitVector>
92 using Array = tlx::SimpleVector<T, tlx::SimpleVectorMode::NoInitNoDestroy>;
96 Array<uint64_t> samples0_pos_;
98 Array<uint64_t> samples1_pos_;
100 std::vector<uint32_t> samples0_;
102 std::vector<uint32_t> samples1_;
116 :
Rank<optimized_for>(bv),
136 [[nodiscard(
"select0 computed but not used")]]
size_t
138 size_t const l0_end =
l0_.size();
139 size_t const l12_end =
l12_.size();
143 while (l0_pos + 1 < l0_end &&
150 while (l0_pos + 1 < l0_end &&
l0_[l0_pos + 1] < rank) {
154 if (l0_pos == l0_end) [[unlikely]] {
163 size_t const sample_pos =
165 samples0_pos_[l0_pos];
167 size_t l1_pos = samples0_[sample_pos];
170 size_t const l0_block_end =
176 l1_pos = std::min<size_t>(l1_pos, l0_block_end);
179 while (l1_pos + 1 < l0_block_end &&
181 l12_[l1_pos + 1].l1 <
188 auto l2 =
l12_[l1_pos].l2_values;
190 (l2 & uint16_t(0b1111111111)) <
198 while (l1_pos + 1 < l0_block_end &&
l12_[l1_pos + 1].l1 < rank) {
201 rank -=
l12_[l1_pos].l1;
202 auto l2 =
l12_[l1_pos].l2_values;
203 while (l2_pos < 3 && (l2 & uint16_t(0b1111111111)) < rank) {
204 rank -= (l2 & uint16_t(0b1111111111));
214 while ((
popcount = pasta::popcount_zeros<1>(
data_ + last_pos)) < rank) {
219 return (last_pos * 64) +
select(~
data_[last_pos], rank - 1);
227 [[nodiscard(
"select1 computed but not used")]]
size_t
229 size_t const l0_end =
l0_.size();
230 size_t const l12_end =
l12_.size();
234 while (l0_pos + 1 < l0_end &&
l0_[l0_pos + 1] < rank) {
238 while (l0_pos + 1 < l0_end &&
245 if (l0_pos == l0_end) [[unlikely]] {
254 size_t const sample_pos =
256 samples1_pos_[l0_pos];
258 size_t l1_pos = samples1_[sample_pos];
261 size_t const l0_block_end =
267 l1_pos = std::min(l1_pos, l0_block_end);
270 while (l1_pos + 1 < l0_block_end &&
l12_[l1_pos + 1].l1 < rank) {
273 rank -=
l12_[l1_pos].l1;
274 auto l2 =
l12_[l1_pos].l2_values;
275 while (l2_pos < 3 && (l2 & uint16_t(0b1111111111)) < rank) {
276 rank -= (l2 & uint16_t(0b1111111111));
281 while (l1_pos + 1 < l0_block_end &&
283 l12_[l1_pos + 1].l1 <
290 auto l2 =
l12_[l1_pos].l2_values;
292 (l2 & uint16_t(0b1111111111)) <
305 while ((
popcount = pasta::popcount<1>(
data_ + last_pos)) < rank) {
309 return (last_pos * 64) +
select(
data_[last_pos], rank - 1);
316 [[nodiscard(
"space usage computed but not used")]]
size_t
318 return samples0_.size() *
sizeof(uint32_t) +
319 samples1_.size() *
sizeof(uint32_t) +
320 samples0_pos_.size() *
sizeof(uint64_t) +
321 samples1_pos_.size() *
sizeof(uint64_t) +
sizeof(*
this);
327 size_t const l12_end =
l12_.size();
329 size_t next_sample0_value = 1;
330 size_t next_sample1_value = 1;
331 for (
size_t l0_pos = 0, l12_pos = 0; l12_pos < l12_end; ++l12_pos) {
335 samples0_pos_[l0_pos] = samples0_.size();
336 samples1_pos_[l0_pos++] = samples1_.size();
337 next_sample0_value = 1;
338 next_sample1_value = 1;
344 next_sample0_value) {
345 samples0_.push_back(l12_pos - 1);
348 if (
l12_[l12_pos].l1 >= next_sample1_value) {
349 samples1_.push_back(l12_pos - 1);
353 if (
l12_[l12_pos].l1 >= next_sample0_value) {
354 samples0_.push_back(l12_pos - 1);
360 next_sample1_value) {
361 samples1_.push_back(l12_pos - 1);
367 if (samples0_.size() == 0) [[unlikely]] {
368 samples0_.push_back(0);
370 if (samples1_.size() == 0) [[unlikely]] {
371 samples1_.push_back(0);
Select support for BitVector.
Definition rank_select.hpp:77
RankSelect & operator=(RankSelect &&other)=default
Default move assignment.
RankSelect()=default
Default constructor w/o parameter.
~RankSelect()=default
Destructor. Deleting manually created arrays.
size_t select1(size_t rank) const
Get position of specific one, i.e., select.
Definition rank_select.hpp:228
RankSelect(VectorType &bv)
Constructor. Creates the auxiliary information for efficient rank and select queries.
Definition rank_select.hpp:115
size_t space_usage() const final
Estimate for the space usage.
Definition rank_select.hpp:317
RankSelect(RankSelect &&other)=default
Default move constructor.
size_t select0(size_t rank) const
Get position of specific zero, i.e., select.
Definition rank_select.hpp:137
Rank support for BitVector.
Definition rank.hpp:102
tlx::SimpleVector< uint64_t, tlx::SimpleVectorMode::NoInitNoDestroy > l0_
Definition rank.hpp:112
BitVector::RawDataConstAccess data_
Definition rank.hpp:107
size_t data_size_
Definition rank.hpp:105
tlx::SimpleVector< L12Type, tlx::SimpleVectorMode::NoInitNoDestroy > l12_
Definition rank.hpp:115
OptimizedFor
Enum used to specify which queries the rank (and select) data structures should be optimized for.
Definition optimized_for.hpp:40
constexpr bool optimize_one_or_dont_care(OptimizedFor const optimized_for)
Helper function indicating if queries should be optimized for one queries or the caller does not care...
Definition optimized_for.hpp:59
@ DONT_CARE
It does not matter (both types are called equally often).
uint64_t popcount(uint64_t const *const buffer)
Compute popcount of a specific number of 64-bit words.
Definition popcount.hpp:41
uint64_t select(uint64_t x, uint64_t k)
Select set bit in 64-bit word and return its position starting from the LSB (starting from the left).
Definition select.hpp:144
Static configuration for Rank and RankSelect.
Definition rank.hpp:60
static constexpr size_t L0_WORD_SIZE
Number of 64-bit words covered by an L0-block.
Definition rank.hpp:74
static constexpr size_t SELECT_SAMPLE_RATE
Sample rate of positions for faster select queries.
Definition rank.hpp:77
static constexpr size_t L2_WORD_SIZE
Number of 64-bit words covered by an L2-block.
Definition rank.hpp:70
static constexpr size_t L2_BIT_SIZE
Bits covered by an L2-block.
Definition rank.hpp:62
static constexpr size_t L0_BIT_SIZE
Bits covered by an L0-block.
Definition rank.hpp:66
static constexpr size_t L1_BIT_SIZE
Bits covered by an L1-block.
Definition rank.hpp:64
static constexpr size_t L1_WORD_SIZE
Number of 64-bit words covered by an L1-block.
Definition rank.hpp:72