Simple flat dynamic bit vector for use as a leaf for a dynamic b-tree bit vector.
More...
|
| leaf (uint64_t capacity, uint64_t *data) |
| Leaf constructor. More...
|
|
bool | at (const uint32_t i) const |
| Get the value of the ith element in the leaf. More...
|
|
uint32_t | p_sum () const |
| Getter for p_sum_.
|
|
uint32_t | size () const |
| Getter for size_.
|
|
void | insert (const uint64_t i, const bool x) |
| Insert x into position i. More...
|
|
bool | remove (const uint64_t i) |
| Remove the ith bit from the leaf. More...
|
|
int | set (const uint64_t i, const bool x) |
| Set the ith bit to x. More...
|
|
uint32_t | rank (const uint64_t n) const |
| Number of 1-bits up to position n. More...
|
|
uint32_t | rank (const uint64_t n, const uint64_t offset) const |
| Number of 1-bits up to position n from position offset. More...
|
|
uint32_t | select (const uint32_t x) const |
| Index of the xth 1-bit in the data structure. More...
|
|
uint32_t | select (const uint32_t x, uint32_t pos, uint32_t pop) const |
| Index of the xth 1-bit in the data structure starting at pos with pop More...
|
|
uint64_t | bits_size () const |
| Size of the leaf and associated data in bits.
|
|
bool | need_realloc () const |
| Determine if reallocation / splitting is required prior to additional insertion of new elements. More...
|
|
uint32_t | capacity () const |
| Size of the leaf-associated data storage in 64-bit words. More...
|
|
void | capacity (uint32_t cap) |
| Set the size of the leaf-associated data storage. More...
|
|
void | set_data_ptr (uint64_t *ptr) |
| Sets the pointer to the leaf-associated data storage. More...
|
|
uint64_t * | data () |
| Provides access to raw leaf-associated data. More...
|
|
void | clear_first (uint64_t elems) |
| Remove the fist "elems" elements from the leaf. More...
|
|
void | transfer_append (leaf *other, uint64_t elems) |
| Move "elems" elements from the start of "other" to the end of "this". More...
|
|
void | clear_last (uint64_t elems) |
| Remove the last "elems" elements from the leaf. More...
|
|
void | transfer_prepend (leaf *other, uint64_t elems) |
| Move "elems" elements from the end of "other" to the start of "this". More...
|
|
void | append_all (leaf *other) |
| Copy all elements from (the start of) "other" to the end of "this". More...
|
|
void | commit () |
| Commit and clear the Insert/Remove buffer for the leaf. More...
|
|
uint64_t | validate () const |
| Ensure that the leaf is in a valid state. More...
|
|
void | print (bool internal_only) const |
| Output data stored in the leaf as json. More...
|
|
template<uint8_t buffer_size, bool avx = true>
class bv::leaf< buffer_size, avx >
Simple flat dynamic bit vector for use as a leaf for a dynamic b-tree bit vector.
The leaf is not usable as fully featured bit vector by itself since the leaf cannot reallocate itself when full. The leaf requires a parent structure (like bv::bit_vector or bv::node) to manage reallocations and rebalancing.
Practical limitations
The maximum leaf size for a buffered leaf without risking undefined behaviour is \(2^{24} - 1\) due to buffer elements storing reference indexes in 24-bits of 32-bit integers. The practical upper limit of leaf size due to performance concerns is no more than \(2^{20}\) and optimal leaf size is likely to be closer to the \(2^{12}\) to \(2^{15}\) range.
Maximum leaf size can't in effect be non-divisible by 64, since 64-bit integers are used for storage and a leaf "will use" all available words fully before indicating that a reallocation is necessary, triggering limit checks.
The maximum buffer size is 63 due to storing the information on buffer usage with 6 bits of an 8-bit word, with 2 bits reserved for other purposes. This could easily be "fixed", but testing indicates that bigger buffer sizes are unlikely to be of practical use.
- Template Parameters
-
Size | of insertion/removal buffer. |
Use | avx population counts for rank operations. |
template<uint8_t buffer_size, bool avx = true>
void bv::leaf< buffer_size, avx >::append_all |
( |
leaf< buffer_size, avx > * |
other | ) |
|
|
inline |
Copy all elements from (the start of) "other" to the end of "this".
Intended for merging leaves.
Will not ensure sufficient capacity for merge.
Will ensure that the buffers are empty for both leaves.
Will now clear elements from "other" as it is assumed that "other" will be deallocated .
- Parameters
-
other | Pointer to next leaf. |
template<uint8_t buffer_size, bool avx = true>
bool bv::leaf< buffer_size, avx >::buffer_value |
( |
uint32_t |
e | ) |
const |
|
inlineprotected |
Extract the value of a buffer element.
The First bit (lsb) of a 23-bit buffer element contains the value of the element.
I.e. if bv[i]
is 1
, then the buffer created for remove(i)
will have a lsb with value 1.
- Parameters
-
e | Buffer element to extract value from. |
- Returns
- Boolean value indicating the value of the element referred to by the buffer.
template<uint8_t buffer_size, bool avx = true>
void bv::leaf< buffer_size, avx >::commit |
( |
| ) |
|
|
inline |
Commit and clear the Insert/Remove buffer for the leaf.
Intended for clearing a full buffer before insertion or removal, and for ensuring an empty buffer before transfer operations.
Slightly complicated but linear time function for committing all buffered operations to the underlying data.
template<uint8_t buffer_size, bool avx = true>
void bv::leaf< buffer_size, avx >::insert |
( |
const uint64_t |
i, |
|
|
const bool |
x |
|
) |
| |
|
inline |
Insert x into position i.
The leaf cannot reallocate so inserting into a full leaf is undefined behaviour.
If the the buffer is not full or the insertion is appending a new element, the operation can be considered constant time. If the buffer is full and the insertion is not appending, the operations will be linear in the leaf size.
- Parameters
-
i | Insertion index |
x | Value to insert |
template<uint8_t buffer_size, bool avx = true>
bool bv::leaf< buffer_size, avx >::remove |
( |
const uint64_t |
i | ) |
|
|
inline |
Remove the ith bit from the leaf.
No implicit balancing is possible in leaves without a managing parent (bv::bit_vector or bv::node).
If the the buffer is not full the operation can be considered constant time. If the buffer is full, the operations will be linear in the leaf size.
- Parameters
-
- Returns
- Value of removed element.
template<uint8_t buffer_size, bool avx = true>
void bv::leaf< buffer_size, avx >::transfer_append |
( |
leaf< buffer_size, avx > * |
other, |
|
|
uint64_t |
elems |
|
) |
| |
|
inline |
Move "elems" elements from the start of "other" to the end of "this".
Will not ensure sufficient capacity for the copy target.
The operation will ensure that the buffers of both leaves are cleared before transferring elements. Elements are first copied, after which, elements are cleared from the sibling with other->clear_first(elems)
.
- Parameters
-
other | Pointer to the next sibling. |
elems | Number of elements to transfer. |
template<uint8_t buffer_size, bool avx = true>
void bv::leaf< buffer_size, avx >::transfer_prepend |
( |
leaf< buffer_size, avx > * |
other, |
|
|
uint64_t |
elems |
|
) |
| |
|
inline |
Move "elems" elements from the end of "other" to the start of "this".
Will not ensure sufficient capacity for the copy target.
The operation will ensure that the buffers of both leaves are cleared before transferring elements. Elements are first copied, after which, elements are cleared from the sibling with other->clear_last(elems)
.
- Parameters
-
other | Pointer to the previous sibling. |
elems | Number of elements to transfer. |
template<uint8_t buffer_size, bool avx = true>
uint64_t bv::leaf< buffer_size, avx >::validate |
( |
| ) |
const |
|
inline |
Ensure that the leaf is in a valid state.
Will use assertions to check that the actual stored data agrees with stored metadata. Will not in any way that the leaf is in the correct state given the preceding sequence of operations, just that the leaf is in a state that is valid for a leaf.
If the compiler flag -DNDEBUG
is given, this function will do nothing and may be completely optimized out by an optimizing compiler.
- Returns
- 1 for calculating the number of nodes in the tree.