SDSL 3.0.3
Succinct Data Structure Library
Loading...
Searching...
No Matches
select_support_mcl.hpp
Go to the documentation of this file.
1// Copyright (c) 2016, the SDSL Project Authors. All rights reserved.
2// Please see the AUTHORS file for details. Use of this source code is governed
3// by a BSD license that can be found in the LICENSE file.
8#ifndef INCLUDED_SDSL_SELECT_SUPPORT_MCL
9#define INCLUDED_SDSL_SELECT_SUPPORT_MCL
10
11#include <algorithm>
12#include <assert.h>
13#include <iostream>
14#include <stdint.h>
15#include <string>
16
17#include <sdsl/bits.hpp>
18#include <sdsl/cereal.hpp>
19#include <sdsl/int_vector.hpp>
22#include <sdsl/util.hpp>
23
25namespace sdsl
26{
27
29
63template <uint8_t t_b = 1, uint8_t t_pat_len = 1>
65{
66private:
67 static_assert(t_b == 1u or t_b == 0u or t_b == 10u or t_b == 11u,
68 "select_support_mcl: bit pattern must be `0`,`1`,`10`, `01`, or `11`");
69 static_assert(t_pat_len == 1u or t_pat_len == 2u, "select_support_mcl: bit pattern length must be 1 or 2");
70
71public:
73 enum
74 {
75 bit_pat = t_b
76 };
77 enum
78 {
79 bit_pat_len = t_pat_len
80 };
81
82private:
83 uint32_t m_logn = 0, // \f$ log(size) \f$
84 m_logn2 = 0, // \f$ log^2(size) \f$
85 m_logn4 = 0; // \f$ log^4(size) \f$
86 // entry i of m_superblock equals the answer to select_1(B,i*4096)
87 int_vector<0> m_superblock;
88 int_vector<0> * m_longsuperblock = nullptr;
89 int_vector<0> * m_miniblock = nullptr;
90 size_type m_arg_cnt = 0;
91 void initData();
92 void init_fast(bit_vector const * v = nullptr);
93
94public:
95 explicit select_support_mcl(bit_vector const * v = nullptr);
99
100 void init_slow(bit_vector const * v = nullptr);
102 inline size_type select(size_type i) const;
105 size_type serialize(std::ostream & out, structure_tree_node * v = nullptr, std::string name = "") const;
106 void load(std::istream & in, bit_vector const * v = nullptr);
107 void set_vector(bit_vector const * v = nullptr);
109 template <typename archive_t>
110 void CEREAL_SAVE_FUNCTION_NAME(archive_t & ar) const;
112 template <typename archive_t>
113 void CEREAL_LOAD_FUNCTION_NAME(archive_t & ar);
116 bool operator==(select_support_mcl const & other) const noexcept;
117 bool operator!=(select_support_mcl const & other) const noexcept;
118};
119
120template <uint8_t t_b, uint8_t t_pat_len>
122{
123 if (t_pat_len > 1 or (vv != nullptr and vv->size() < 100000))
124 init_slow(vv);
125 else
126 init_fast(vv);
127 return;
128}
129
130template <uint8_t t_b, uint8_t t_pat_len>
132 select_support(ss.m_v),
133 m_logn(ss.m_logn),
134 m_logn2(ss.m_logn2),
135 m_logn4(ss.m_logn4),
136 m_superblock(ss.m_superblock),
137 m_arg_cnt(ss.m_arg_cnt)
138{
139 size_type sb = (m_arg_cnt + 4095) >> 12;
140 if (ss.m_longsuperblock != nullptr)
141 {
142 m_longsuperblock = new int_vector<0>[sb]; // copy longsuperblocks
143 for (size_type i = 0; i < sb; ++i)
144 {
145 m_longsuperblock[i] = ss.m_longsuperblock[i];
146 }
147 }
148 m_miniblock = nullptr;
149 if (ss.m_miniblock != nullptr)
150 {
151 m_miniblock = new int_vector<0>[sb]; // copy miniblocks
152 for (size_type i = 0; i < sb; ++i)
153 {
154 m_miniblock[i] = ss.m_miniblock[i];
155 }
156 }
157}
158
159template <uint8_t t_b, uint8_t t_pat_len>
164
165template <uint8_t t_b, uint8_t t_pat_len>
167{
168 if (this != &ss)
169 {
170 select_support_mcl tmp(ss);
171 *this = std::move(tmp);
172 }
173 return *this;
174}
175
176template <uint8_t t_b, uint8_t t_pat_len>
178{
179 if (this != &ss)
180 {
181 m_logn = ss.m_logn; // copy log n
182 m_logn2 = ss.m_logn2; // copy (logn)^2
183 m_logn4 = ss.m_logn4; // copy (logn)^4
184 m_superblock = std::move(ss.m_superblock); // move long superblock
185 m_arg_cnt = ss.m_arg_cnt; // copy count of 1-bits
186 m_v = ss.m_v; // copy pointer to the supported bit vector
187
188 delete[] m_longsuperblock;
189 m_longsuperblock = ss.m_longsuperblock;
190 ss.m_longsuperblock = nullptr;
191
192 delete[] m_miniblock;
193 m_miniblock = ss.m_miniblock;
194 ss.m_miniblock = nullptr;
195 }
196 return *this;
197}
198
199template <uint8_t t_b, uint8_t t_pat_len>
201{
202 delete[] m_longsuperblock;
203 delete[] m_miniblock;
204}
205
206template <uint8_t t_b, uint8_t t_pat_len>
208{
209 set_vector(v);
210 initData();
211 if (m_v == nullptr)
212 return;
213 // Count the number of arguments in the bit vector
215
216 const size_type SUPER_BLOCK_SIZE = 4096;
217
218 if (m_arg_cnt == 0) // if there are no arguments in the vector we are done...
219 return;
220
221 size_type sb = (m_arg_cnt + SUPER_BLOCK_SIZE - 1) / SUPER_BLOCK_SIZE; // number of superblocks
222 delete[] m_miniblock;
223 m_miniblock = new int_vector<0>[sb];
224
225 m_superblock = int_vector<0>(sb, 0, m_logn);
226
227 size_type arg_position[SUPER_BLOCK_SIZE], arg_cnt = 0;
228 size_type sb_cnt = 0;
229 for (size_type i = 0; i < v->size(); ++i)
230 {
232 {
233 arg_position[arg_cnt % SUPER_BLOCK_SIZE] = i;
234 assert(arg_position[arg_cnt % SUPER_BLOCK_SIZE] == i);
235 ++arg_cnt;
236 if (arg_cnt % SUPER_BLOCK_SIZE == 0 or arg_cnt == m_arg_cnt)
237 { //
238 assert(sb_cnt < sb);
239 m_superblock[sb_cnt] = arg_position[0];
240
241 size_type pos_diff = arg_position[(arg_cnt - 1) % SUPER_BLOCK_SIZE] - arg_position[0];
242 if (pos_diff > m_logn4)
243 { // longblock
244 if (m_longsuperblock == nullptr)
245 m_longsuperblock = new int_vector<0>[sb]; // create longsuperblock
246 m_longsuperblock[sb_cnt] =
247 int_vector<0>(SUPER_BLOCK_SIZE,
248 0,
249 bits::hi(arg_position[(arg_cnt - 1) % SUPER_BLOCK_SIZE]) + 1);
250
251 for (size_type j = 0; j <= (arg_cnt - 1) % SUPER_BLOCK_SIZE; ++j)
252 m_longsuperblock[sb_cnt][j] = arg_position[j]; // copy argument positions to longsuperblock
253 }
254 else
255 { // short block
256 m_miniblock[sb_cnt] = int_vector<0>(64, 0, bits::hi(pos_diff) + 1);
257 for (size_type j = 0; j <= (arg_cnt - 1) % SUPER_BLOCK_SIZE; j += 64)
258 {
259 m_miniblock[sb_cnt][j / 64] = arg_position[j] - arg_position[0];
260 }
261 }
262 ++sb_cnt;
263 }
264 }
265 }
266}
267
268template <uint8_t t_b, uint8_t t_pat_len>
270{
271 set_vector(v);
272 initData();
273 if (m_v == nullptr)
274 return;
275 // Count the number of arguments in the bit vector
277
278 const size_type SUPER_BLOCK_SIZE = 64 * 64;
279
280 if (m_arg_cnt == 0) // if there are no arguments in the vector we are done...
281 return;
282
283 // size_type sb = (m_arg_cnt+63+SUPER_BLOCK_SIZE-1)/SUPER_BLOCK_SIZE; // number of superblocks, add 63 as the
284 // last block could contain 63 uninitialized bits
285 size_type sb = (m_arg_cnt + SUPER_BLOCK_SIZE - 1) / SUPER_BLOCK_SIZE; // number of superblocks
286 delete[] m_miniblock;
287 m_miniblock = new int_vector<0>[sb];
288
289 m_superblock = int_vector<0>(sb, 0, m_logn); // TODO: hier koennte man logn noch optimieren...s
290
291 bit_vector::size_type arg_position[SUPER_BLOCK_SIZE];
292 uint64_t const * data = v->data();
293 uint64_t carry_new = 0;
294 size_type last_k64 = 1, sb_cnt = 0;
295 for (size_type i = 0, cnt_old = 0, cnt_new = 0, last_k64_sum = 1; i < (((v->bit_size() + 63) >> 6) << 6);
296 i += 64, ++data)
297 {
299 cnt_new = std::min(cnt_new,
300 m_arg_cnt); // For (0, 1), we may find nonexistent args in the padding after the bitvector.
301 if (cnt_new >= last_k64_sum)
302 {
303 arg_position[last_k64 - 1] =
304 i
306 last_k64_sum - cnt_old,
307 carry_new);
308 last_k64 += 64;
309 last_k64_sum += 64;
310
311 if (last_k64 == SUPER_BLOCK_SIZE + 1)
312 {
313 m_superblock[sb_cnt] = arg_position[0];
314 size_type pos_of_last_arg_in_the_block = arg_position[last_k64 - 65];
315
316 for (size_type ii = arg_position[last_k64 - 65] + 1, j = last_k64 - 65;
317 ii < v->size() and j < SUPER_BLOCK_SIZE;
318 ++ii)
320 {
321 pos_of_last_arg_in_the_block = ii;
322 ++j;
323 }
324 size_type pos_diff = pos_of_last_arg_in_the_block - arg_position[0];
325 if (pos_diff > m_logn4)
326 { // long block
327 if (m_longsuperblock == nullptr)
328 m_longsuperblock = new int_vector<0>[sb + 1]; // create longsuperblock
329 // GEANDERT am 2010-07-17 +1 nach pos_of_last_arg..
330 m_longsuperblock[sb_cnt] =
331 int_vector<0>(SUPER_BLOCK_SIZE, 0, bits::hi(pos_of_last_arg_in_the_block) + 1);
332 for (size_type j = arg_position[0], k = 0;
333 k < SUPER_BLOCK_SIZE and j <= pos_of_last_arg_in_the_block;
334 ++j)
336 {
337 if (k >= SUPER_BLOCK_SIZE)
338 {
339 for (size_type ii = 0; ii < SUPER_BLOCK_SIZE; ++ii)
340 {
341 std::cout << "(" << ii << "," << m_longsuperblock[sb_cnt][ii] << ") ";
342 }
343 std::cout << std::endl;
344 std::cout << "k=" << k << " SUPER_BLOCK_SIZE=" << SUPER_BLOCK_SIZE << std::endl;
345 std::cout << "pos_of_last_arg_in_the_block" << pos_of_last_arg_in_the_block
346 << std::endl;
347 std::cout.flush();
348 }
349 m_longsuperblock[sb_cnt][k++] = j;
350 }
351 }
352 else
353 {
354 m_miniblock[sb_cnt] = int_vector<0>(64, 0, bits::hi(pos_diff) + 1);
355 for (size_type j = 0; j < SUPER_BLOCK_SIZE; j += 64)
356 {
357 m_miniblock[sb_cnt][j / 64] = arg_position[j] - arg_position[0];
358 }
359 }
360 ++sb_cnt;
361 last_k64 = 1;
362 }
363 }
364 cnt_old = cnt_new;
365 }
366 // handle last block: append long superblock
367 if (last_k64 > 1)
368 {
369 if (m_longsuperblock == nullptr)
370 m_longsuperblock = new int_vector<0>[sb + 1]; // create longsuperblock
371 m_longsuperblock[sb_cnt] = int_vector<0>(SUPER_BLOCK_SIZE, 0, bits::hi(v->size() - 1) + 1);
372 for (size_type i = arg_position[0], k = 0; i < v->size(); ++i)
373 {
375 {
376 m_longsuperblock[sb_cnt][k++] = i;
377 }
378 }
379 ++sb_cnt;
380 }
381}
382
383template <uint8_t t_b, uint8_t t_pat_len>
385{
386 assert(i > 0 and i <= m_arg_cnt);
387
388 i = i - 1;
389 size_type sb_idx = i >> 12; // i/4096
390 size_type offset = i & 0xFFF; // i%4096
391 if (m_longsuperblock != nullptr and !m_longsuperblock[sb_idx].empty())
392 {
393 return m_longsuperblock[sb_idx][offset];
394 }
395 else
396 {
397 if ((offset & 0x3F) == 0)
398 {
399 assert(sb_idx < m_superblock.size());
400 assert((offset >> 6) < m_miniblock[sb_idx].size());
401 return m_superblock[sb_idx] + m_miniblock[sb_idx][offset >> 6 /*/64*/];
402 }
403 else
404 {
405 i = i - (sb_idx << 12) - ((offset >> 6) << 6);
406 // now i > 0 and i <= 64
407 assert(i > 0);
408 size_type pos = m_superblock[sb_idx] + m_miniblock[sb_idx][offset >> 6] + 1;
409
410 // now pos is the position from where we search for the ith argument
411 size_type word_pos = pos >> 6;
412 size_type word_off = pos & 0x3F;
413 uint64_t const * data = m_v->data() + word_pos;
414 uint64_t carry = select_support_trait<t_b, t_pat_len>::init_carry(data, word_pos);
416
417 if (args >= i)
418 {
419 return (word_pos << 6)
421 }
422 word_pos += 1;
423 size_type sum_args = args;
425 uint64_t old_carry = carry;
427 while (sum_args + args < i)
428 {
429 sum_args += args;
430 assert(data + 1 < m_v->data() + ((m_v->bit_size() + 63) >> 6));
431 old_carry = carry;
433 word_pos += 1;
434 }
435 return (word_pos << 6)
437 }
438 }
439}
440
441template <uint8_t t_b, uint8_t t_pat_len>
443{
444 return select(i);
445}
446
447template <uint8_t t_b, uint8_t t_pat_len>
449{
450 m_arg_cnt = 0;
451 if (nullptr == m_v)
452 {
453 m_logn = m_logn2 = m_logn4 = 0;
454 }
455 else
456 {
457 m_logn = bits::hi(((m_v->bit_size() + 63) >> 6) << 6) + 1; // TODO maybe it's better here to take a max(...,12)
458 m_logn2 = m_logn * m_logn;
459 m_logn4 = m_logn2 * m_logn2;
460 }
461 delete[] m_longsuperblock;
462 m_longsuperblock = nullptr;
463 delete[] m_miniblock;
464 m_miniblock = nullptr;
465}
466
467template <uint8_t t_b, uint8_t t_pat_len>
469{
470 m_v = v;
471}
472
473template <uint8_t t_b, uint8_t t_pat_len>
474auto select_support_mcl<t_b, t_pat_len>::serialize(std::ostream & out, structure_tree_node * v, std::string name) const
475 -> size_type
476{
477 structure_tree_node * child = structure_tree::add_child(v, name, util::class_name(*this));
478 size_type written_bytes = 0;
479 // write the number of 1-bits in the supported bit_vector
480 out.write((char *)&m_arg_cnt, sizeof(size_type) / sizeof(char));
481 written_bytes = sizeof(size_type) / sizeof(char);
482 // number of superblocks in the data structure
483 size_type sb = (m_arg_cnt + 4095) >> 12;
484
485 if (m_arg_cnt)
486 { // if there exists 1-bits to be supported
487 written_bytes += m_superblock.serialize(out, child, "superblock"); // serialize superblocks
488 bit_vector mini_or_long; // Helper vector: mini or long block?
489 if (m_longsuperblock != nullptr)
490 {
491 mini_or_long.resize(sb); // resize indicator bit_vector to the number of superblocks
492 for (size_type i = 0; i < sb; ++i)
493 mini_or_long[i] = !m_miniblock[i].empty();
494 }
495 written_bytes += mini_or_long.serialize(out, child, "mini_or_long");
496 size_type written_bytes_long = 0;
497 size_type written_bytes_mini = 0;
498 for (size_type i = 0; i < sb; ++i)
499 if (!mini_or_long.empty() and !mini_or_long[i])
500 {
501 written_bytes_long += m_longsuperblock[i].serialize(out);
502 }
503 else
504 {
505 written_bytes_mini += m_miniblock[i].serialize(out);
506 }
507 written_bytes += written_bytes_long;
508 written_bytes += written_bytes_mini;
509 structure_tree_node * child_long =
510 structure_tree::add_child(child, "longsuperblock", util::class_name(m_longsuperblock));
511 structure_tree::add_size(child_long, written_bytes_long);
512 structure_tree_node * child_mini =
513 structure_tree::add_child(child, "minisuperblock", util::class_name(m_miniblock));
514 structure_tree::add_size(child_mini, written_bytes_mini);
515 }
516 structure_tree::add_size(child, written_bytes);
517 return written_bytes;
518}
519
520template <uint8_t t_b, uint8_t t_pat_len>
521void select_support_mcl<t_b, t_pat_len>::load(std::istream & in, bit_vector const * v)
522{
523 set_vector(v);
524 initData();
525 // read the number of 1-bits in the supported bit_vector
526 in.read((char *)&m_arg_cnt, sizeof(size_type) / sizeof(char));
527 size_type sb = (m_arg_cnt + 4095) >> 12;
528
529 if (m_arg_cnt)
530 { // if there exists 1-bits to be supported
531 m_superblock.load(in); // load superblocks
532
533 delete[] m_miniblock;
534 m_miniblock = nullptr;
535 delete[] m_longsuperblock;
536 m_longsuperblock = nullptr;
537
538 bit_vector mini_or_long; // Helper vector: mini or long block?
539 mini_or_long.load(in); // Load the helper vector
540 m_miniblock = new int_vector<0>[sb]; // Create miniblock int_vector<0>
541 if (!mini_or_long.empty())
542 m_longsuperblock = new int_vector<0>[sb]; // Create longsuperblock int_vector<0>
543
544 for (size_type i = 0; i < sb; ++i)
545 if (!mini_or_long.empty() and not mini_or_long[i])
546 {
547 m_longsuperblock[i].load(in);
548 }
549 else
550 {
551 m_miniblock[i].load(in);
552 }
553 }
554}
555
556template <uint8_t t_b, uint8_t t_pat_len>
557template <typename archive_t>
559{
560 ar(CEREAL_NVP(m_arg_cnt));
561 ar(CEREAL_NVP(m_logn));
562 ar(CEREAL_NVP(m_logn2));
563 ar(CEREAL_NVP(m_logn4));
564 size_type sb = (m_arg_cnt + 4095) >> 12;
565 if (m_arg_cnt)
566 {
567 ar(CEREAL_NVP(m_superblock));
568 bit_vector mini_or_long;
569 if (m_longsuperblock != nullptr)
570 {
571 mini_or_long.resize(sb);
572 for (size_type i = 0; i < sb; ++i)
573 {
574 mini_or_long[i] = !m_miniblock[i].empty();
575 }
576 }
577 ar(CEREAL_NVP(mini_or_long));
578 for (size_type i = 0; i < sb; ++i)
579 {
580 if (!mini_or_long.empty() and !mini_or_long[i])
581 {
582 ar(CEREAL_NVP(m_longsuperblock[i]));
583 }
584 else
585 {
586 ar(CEREAL_NVP(m_miniblock[i]));
587 }
588 }
589 }
590}
591
592template <uint8_t t_b, uint8_t t_pat_len>
593template <typename archive_t>
595{
596 delete[] m_longsuperblock;
597 m_longsuperblock = nullptr;
598 delete[] m_miniblock;
599 m_miniblock = nullptr;
600
601 ar(CEREAL_NVP(m_arg_cnt));
602 ar(CEREAL_NVP(m_logn));
603 ar(CEREAL_NVP(m_logn2));
604 ar(CEREAL_NVP(m_logn4));
605
606 size_type sb = (m_arg_cnt + 4095) >> 12;
607
608 if (m_arg_cnt)
609 {
610 ar(CEREAL_NVP(m_superblock));
611
612 delete[] m_miniblock;
613 m_miniblock = nullptr;
614 delete[] m_longsuperblock;
615 m_longsuperblock = nullptr;
616
617 bit_vector mini_or_long;
618 ar(CEREAL_NVP(mini_or_long));
619 m_miniblock = new int_vector<0>[sb];
620
621 if (!mini_or_long.empty())
622 {
623 m_longsuperblock = new int_vector<0>[sb];
624 }
625
626 for (size_type i = 0; i < sb; ++i)
627 {
628 if (!mini_or_long.empty() and !mini_or_long[i])
629 {
630 ar(CEREAL_NVP(m_longsuperblock[i]));
631 }
632 else
633 {
634 ar(CEREAL_NVP(m_miniblock[i]));
635 }
636 }
637 }
638}
639
640template <uint8_t t_b, uint8_t t_pat_len>
642{
643 return (m_logn == other.m_logn) && (m_logn2 == other.m_logn2) && (m_logn4 == other.m_logn4)
644 && (m_superblock == other.m_superblock) && (m_arg_cnt == other.m_arg_cnt)
645 && ((m_longsuperblock == nullptr && other.m_longsuperblock == nullptr)
646 || (*m_longsuperblock == *other.m_longsuperblock))
647 && ((m_miniblock == other.m_miniblock) || (*m_miniblock == *other.m_miniblock));
648}
649
650template <uint8_t t_b, uint8_t t_pat_len>
652{
653 return !(*this == other);
654}
655} // namespace sdsl
656
657#endif
bits.hpp contains the sdsl::bits class.
cereal.hpp offers cereal support
#define CEREAL_NVP(X)
Definition cereal.hpp:31
uint64_t const * data() const noexcept
Pointer to the raw data of the int_vector.
bool empty() const noexcept
Equivalent to size() == 0.
int_vector_size_type size_type
size_type bit_size() const noexcept
The number of bits in the int_vector.
void load(std::istream &in)
Load the int_vector for a stream.
size_type size() const noexcept
The number of elements in the int_vector.
size_type serialize(std::ostream &out, structure_tree_node *v=nullptr, std::string name="") const
Serializes the int_vector to a stream.
void resize(const size_type size)
Resize the int_vector in terms of elements.
A class supporting constant time select queries.
select_support_mcl< t_b, t_pat_len > & operator=(select_support_mcl &&)
void init_slow(bit_vector const *v=nullptr)
void load(std::istream &in, bit_vector const *v=nullptr)
Load the select_support from an in file stream.
bool operator!=(select_support_mcl const &other) const noexcept
select_support_mcl(bit_vector const *v=nullptr)
select_support_mcl(select_support_mcl< t_b, t_pat_len > &&ss)
bool operator==(select_support_mcl const &other) const noexcept
size_type select(size_type i) const
Select function.
void set_vector(bit_vector const *v=nullptr)
This method sets the supported bit_vector.
select_support_mcl< t_b, t_pat_len > & operator=(select_support_mcl const &ss)
size_type operator()(size_type i) const
Alias for select(i).
size_type serialize(std::ostream &out, structure_tree_node *v=nullptr, std::string name="") const
Serialize the select_support to an out file stream.
void CEREAL_SAVE_FUNCTION_NAME(archive_t &ar) const
Serialise (save) via cereal.
select_support_mcl(select_support_mcl< t_b, t_pat_len > const &ss)
void CEREAL_LOAD_FUNCTION_NAME(archive_t &ar)
Serialise (load) via cereal.
The base class of classes supporting select queries for a sdsl::bit_vector in constant time.
bit_vector const * vv
int_vector< 1 >::size_type size_type
static structure_tree_node * add_child(structure_tree_node *v, std::string const &name, std::string const &type)
static void add_size(structure_tree_node *v, uint64_t value)
int_vector.hpp contains the sdsl::int_vector class.
Namespace for the succinct data structure library.
bool empty(range_type const &r)
Empty range check.
int_vector ::size_type size(range_type const &r)
Size of a range.
select_support.hpp contains classes that support a sdsl::bit_vector with constant time select informa...
static constexpr uint32_t hi(uint64_t x)
Position of the most significant set bit the 64-bit word x.
Definition bits.hpp:653
static uint64_t get_carry(uint64_t)
static size_type ith_arg_pos_in_the_word(uint64_t, size_type, uint64_t)
static uint64_t init_carry(uint64_t const *, size_type)
static size_type args_in_the_word(uint64_t, uint64_t &)
static bool found_arg(size_type, bit_vector const &)
static size_type ith_arg_pos_in_the_first_word(uint64_t, size_type, uint8_t, uint64_t)
static size_type args_in_the_first_word(uint64_t, uint8_t, uint64_t)
static size_type arg_cnt(bit_vector const &)
structure_tree.hpp contains a helper class which can represent the memory structure of a class.
util.hpp contains some helper methods for int_vector and other stuff like demangle class names.