52 template <util::AllocType AT = util::AllocType::MALLOC>
class EliasFano :
public Rank,
public Select {
57 uint64_t num_bits, num_ones;
61 uint64_t block_size_mask;
62 uint64_t lower_l_bits_mask;
70 const int start_word = start / 64;
71 const int start_bit = start % 64;
72 const int total_offset = start_bit + width;
73 const uint64_t result = bits[start_word] >> start_bit;
74 return (total_offset <= 64 ? result : result | bits[start_word + 1] << (64 - start_bit)) & ((1ULL << width) - 1);
78 const uint64_t start_word = start / 64;
79 const uint64_t end_word = (start + width - 1) / 64;
80 const uint64_t start_bit = start % 64;
82 if (start_word == end_word) {
83 bits[start_word] &= ~(((1ULL << width) - 1) << start_bit);
84 bits[start_word] |= value << start_bit;
87 bits[start_word] &= (1ULL << start_bit) - 1;
88 bits[start_word] |= value << start_bit;
89 bits[end_word] &= -(1ULL << (width - 64 + start_bit));
90 bits[end_word] |= value >> (64 - start_bit);
102 EliasFano(
const uint64_t *
const bits,
const uint64_t num_bits) {
103 const uint64_t num_words = (num_bits + 63) / 64;
105 for (uint64_t i = num_words; i-- != 0;) m += __builtin_popcountll(bits[i]);
107 this->num_bits = num_bits;
108 l = num_ones == 0 ? 0 : max(0,
lambda_safe(num_bits / num_ones));
111 printf(
"Number of ones: %lld l: %d\n", num_ones, l);
112 printf(
"Upper bits: %lld\n", num_ones + (num_bits >> l) + 1);
113 printf(
"Lower bits: %lld\n", num_ones * l);
116 const uint64_t lower_bits_mask = (1ULL << l) - 1;
118 lower_bits.
size((num_ones * l + 63) / 64 + 2 * (l == 0));
119 upper_bits.
size(((num_ones + (num_bits >> l) + 1) + 63) / 64);
122 for (uint64_t i = 0; i < num_bits; i++) {
123 if (bits[i / 64] & (1ULL << i % 64)) {
124 if (l != 0) set_bits(lower_bits, pos * l, l, i & lower_bits_mask);
125 set(upper_bits, (i >> l) + pos);
143 while (block_size * l + block_size <= 64 && block_size <= l);
147 printf(
"Block size: %d\n", block_size);
150 block_size_mask = (1ULL << block_size) - 1;
151 block_length = block_size * l;
155 for (
int i = 0; i < block_size; i++) ones_step_l |= 1ULL << i * l;
156 msbs_step_l = ones_step_l << (l - 1);
159 for (
int i = 0; i < block_size; i++) compressor |= 1ULL << ((l - 1) * i + block_size);
162 lower_l_bits_mask = (1ULL << l) - 1;
178 EliasFano(
const std::vector<uint64_t> ones,
const uint64_t num_bits) {
179 num_ones = ones.size();
180 this->num_bits = num_bits;
181 l = num_ones == 0 ? 0 : max(0,
lambda_safe(num_bits / num_ones));
184 printf(
"Number of ones: %lld l: %d\n", num_ones, l);
185 printf(
"Upper bits: %lld\n", num_ones + (num_bits >> l) + 1);
186 printf(
"Lower bits: %lld\n", num_ones * l);
189 const uint64_t lower_bits_mask = (1ULL << l) - 1;
191 lower_bits =
new uint64_t[(num_ones * l + 63) / 64 + 2 * (l == 0)];
192 upper_bits =
new uint64_t[((num_ones + (num_bits >> l) + 1) + 63) / 64]();
194 for (uint64_t i = 0; i < num_ones; i++) {
195 if (l != 0) set_bits(lower_bits, i * l, l, ones[i] & lower_bits_mask);
196 set(upper_bits, (ones[i] >> l) + i);
200 printf(
"First lower: %016llx %016llx %016llx %016llx\n", lower_bits[0], lower_bits[1], lower_bits[2], lower_bits[3]);
201 printf(
"First upper: %016llx %016llx %016llx %016llx\n", upper_bits[0], upper_bits[1], upper_bits[2], upper_bits[3]);
210 while (block_size * l + block_size <= 64 && block_size <= l);
214 printf(
"Block size: %d\n", block_size);
216 block_size_mask = (1ULL << block_size) - 1;
217 block_length = block_size * l;
221 for (
int i = 0; i < block_size; i++) ones_step_l |= 1ULL << i * l;
222 msbs_step_l = ones_step_l << (l - 1);
225 for (
int i = 0; i < block_size; i++) compressor |= 1ULL << ((l - 1) * i + block_size);
228 lower_l_bits_mask = (1ULL << l) - 1;
231 uint64_t
rank(
const size_t k) {
232 if (num_ones == 0)
return 0;
233 if (k >= num_bits)
return num_ones;
235 printf(
"Ranking %lld...\n", k);
237 const uint64_t k_shiftr_l = k >> l;
240 int64_t pos = selectz_upper.
selectZero(k_shiftr_l);
241 uint64_t rank = pos - (k_shiftr_l);
244 printf(
"Position: %lld rank: %lld\n", pos, rank);
246 uint64_t rank_times_l = rank * l;
247 const uint64_t k_lower_bits = k & lower_l_bits_mask;
253 }
while (pos >= 0 && (upper_bits[pos / 64] & 1ULL << pos % 64) && get_bits(lower_bits, rank_times_l, l) >= k_lower_bits);
258 const uint64_t k_lower_bits = k & lower_l_bits_mask;
261 printf(
"k: %llx lower %d : %llx\n", k, l, k_lower_bits);
264 const uint64_t k_lower_bits_step_l = k_lower_bits * ones_step_l;
266 uint64_t pos = selectz_upper.
selectZero(k_shiftr_l);
267 uint64_t rank = pos - (k_shiftr_l);
268 uint64_t rank_times_l = rank * l;
271 printf(
"pos: %lld rank: %lld\n", pos, rank);
274 uint64_t block_upper_bits, block_lower_bits;
276 while (rank > block_size) {
278 rank_times_l -= block_length;
280 block_upper_bits = get_bits(upper_bits, pos, block_size);
281 block_lower_bits = get_bits(lower_bits, rank_times_l, block_length);
287 ((((block_lower_bits | msbs_step_l) - (k_lower_bits_step_l & ~msbs_step_l)) | (k_lower_bits_step_l ^ block_lower_bits)) ^ (k_lower_bits_step_l & ~block_lower_bits)) & msbs_step_l;
292 const uint64_t cmp_compr = ~(cmp * compressor >> block_length & block_upper_bits) & block_size_mask;
296 if (cmp_compr)
return rank + 1 +
lambda_safe(cmp_compr);
299 block_upper_bits = get_bits(upper_bits, pos - rank, rank);
300 block_lower_bits = get_bits(lower_bits, 0, rank_times_l);
308 ((((block_lower_bits | msbs_step_l) - (k_lower_bits_step_l & ~msbs_step_l)) | (k_lower_bits_step_l ^ block_lower_bits)) ^ (k_lower_bits_step_l & ~block_lower_bits)) & msbs_step_l;
314 const uint64_t cmp_compr = ~(cmp * compressor >> block_length & block_upper_bits) & (1ULL << rank) - 1;
325 printf(
"Selecting %lld...\n", rank);
328 printf(
"Returning %lld = %llx << %d | %llx\n", (select_upper.
select(rank) - rank) << l | get_bits(lower_bits, rank * l, l), select_upper.
select(rank) - rank, l,
329 get_bits(lower_bits, rank * l, l));
331 return (select_upper.
select(rank) - rank) << l | get_bits(lower_bits, rank * l, l);
334 uint64_t
select(
const uint64_t rank, uint64_t *
const next) {
336 s = select_upper.
select(rank, &t) - rank;
339 const uint64_t position = rank * l;
340 *next = t << l | get_bits(lower_bits, position + l, l);
341 return s << l | get_bits(lower_bits, position, l);
345 size_t size()
const {
return num_bits; }
349 return upper_bits.
bitCount() -
sizeof(upper_bits) * 8 + lower_bits.
bitCount() -
sizeof(lower_bits) * 8 + select_upper.
bitCount() -
sizeof(select_upper) * 8 + selectz_upper.
bitCount() -
350 sizeof(selectz_upper) * 8 +
sizeof(*
this) * 8;