Pixie
Loading...
Searching...
No Matches
pixie::rmq::HybridBTree< T, Compare, Index, LeafSize, Fanout, LeafSelectorKind > Class Template Reference

Hybrid B-tree RMQ with compact per-level selectors. More...

#include <hybrid_btree.h>

Inheritance diagram for pixie::rmq::HybridBTree< T, Compare, Index, LeafSize, Fanout, LeafSelectorKind >:
pixie::rmq::RmqBase< Impl, Value >

Public Types

using Self
 

Public Member Functions

 HybridBTree ()=default
 Construct an empty RMQ index.
 
 HybridBTree (const HybridBTree &)=default
 Copy an RMQ index while preserving its non-owning value span.
 
 HybridBTree (HybridBTree &&) noexcept=default
 Move an RMQ index while preserving selector and cache storage.
 
HybridBTreeoperator= (const HybridBTree &)=default
 Copy-assign an RMQ index and its cached metadata.
 
HybridBTreeoperator= (HybridBTree &&) noexcept=default
 Move-assign an RMQ index and its cached metadata.
 
 HybridBTree (std::span< const T > values, Compare compare=Compare())
 Build a hybrid B-tree RMQ index over values.
 
std::size_t size_impl () const
 Return the number of indexed values.
 
value_at_impl (std::size_t position) const
 Return the value at an indexed position.
 
std::size_t arg_min_impl (std::size_t left, std::size_t right) const
 Return the first minimum position in [left, right).
 
std::size_t top_sparse_block_size () const
 Return the current top sparse-table block width.
 
std::size_t top_sparse_block_count () const
 Return the current number of top sparse-table blocks.
 
std::size_t memory_usage_bytes_impl () const
 Return owned auxiliary memory usage in bytes.
 
- Public Member Functions inherited from pixie::rmq::RmqBase< Impl, Value >
std::size_t size () const
 Number of indexed values.
 
bool empty () const
 Whether the indexed array is empty.
 
std::size_t arg_min (std::size_t left, std::size_t right) const
 Return the first minimum position in [left, right).
 
Value range_min (std::size_t left, std::size_t right) const
 Return the minimum value in [left, right).
 
std::size_t memory_usage_bytes () const
 Return owned auxiliary memory usage in bytes when implemented.
 

Static Public Member Functions

static std::size_t top_sparse_block_size_for (std::size_t value_count)
 Return the top sparse-table block width chosen for a value count.
 
static std::size_t top_sparse_block_count_for (std::size_t value_count)
 Return the number of top sparse-table blocks for a value count.
 

Static Public Attributes

static constexpr bool kBpLeafSelector
 
static constexpr bool kMaskLeafSelector
 
static constexpr std::size_t npos = RmqBase<Self, T>::npos
 
static constexpr Index invalid_index = std::numeric_limits<Index>::max()
 
static constexpr std::size_t kLeafSize = LeafSize
 
static constexpr std::size_t kFanout = Fanout
 
static constexpr std::size_t kMiddleFanout = 192
 
static constexpr std::size_t kMinTopSparseBlockSize = 4096
 
static constexpr std::size_t kMaxTopSparseBlocks = std::size_t{1} << 14
 
- Static Public Attributes inherited from pixie::rmq::RmqBase< Impl, Value >
static constexpr std::size_t npos = std::numeric_limits<std::size_t>::max()
 Sentinel returned when no valid query answer exists.
 

Detailed Description

template<class T, class Compare = std::less<T>, class Index = std::size_t, std::size_t LeafSize = 496, std::size_t Fanout = 256, HybridBTreeLeafSelector LeafSelectorKind = HybridBTreeLeafSelector::PrefixSuffix>
class pixie::rmq::HybridBTree< T, Compare, Index, LeafSize, Fanout, LeafSelectorKind >

Hybrid B-tree RMQ with compact per-level selectors.

This is a static, non-owning value-RMQ index over an external value array. Values are split into leaves, leaves are grouped into a B-tree, and each node stores a selector over the minima of its immediate children. Query ranges use the library-wide half-open convention [left, right), invalid ranges return npos, and equal values resolve to the smaller original position.

The default low level uses 496-value prefix/suffix mask leaves. A leaf stores one bit for each prefix/suffix record position plus a 16-bit local-minimum offset in one 64-byte object. Prefix or suffix ranges can be answered from this mask; interior partial ranges fall back to a linear scan of the original values. The same implementation also supports 248-value mask leaves and 252-value BP leaves for controlled experiments.

Internal nodes use 192-way fanout. Their selector is a 512-bit local Cartesian-tree balanced-parentheses encoding over child minima: 384 BP bits, a 64-bit absolute subtree-minimum position, and 64 bits of zero-rank prefix metadata. Node minimum values are cached in a side vector so comparing candidates does not require repeatedly descending to leaves.

Wide queries first try a single coarse sparse table over original-value block minima. The sparse table uses at least 4096-value blocks and grows the block width when needed so the top layer has at most 2^14 blocks. If the padded block-cover candidate lies inside the query, it is returned immediately; on a miss, the sparse table answers the fully covered middle block range and the B-tree handles the two border ranges.

value array, n entries
|
+-- L0: leaves
| ceil(n / 496) nodes by default
| each leaf covers <=496 values and stores one 64-byte selector
|
+-- T: value-block sparse overlay
| block width >=4096 values, at most 2^14 blocks
| stores one original-value minimum position per sparse-table cell
|
+-- L1..Lm: internal levels
| fanout 192
| each node stores one 512-bit BP selector over child minima
Examples with default 496-value leaves:
n = 2^24:
33,826 leaves -> 177 internal nodes -> 1 root
n = 2^26:
135,301 leaves -> 705 internal nodes -> 4 internal nodes -> 1 root

Querying starts at the lowest node that covers both endpoint leaves. At each internal node, the selector is asked for the best child over the intersecting child-slot range. If that child is fully covered, or its stored subtree minimum lies inside the query, that candidate is final for the node. Otherwise only the affected border child is corrected recursively and compared with the middle full-child range. All comparisons use (value, position) semantics so traversal order cannot change tie-breaking.

Template Parameters
TValue type in the indexed array.
CompareStrict weak ordering used to choose minima.
IndexUnsigned integer type used for stored positions.
LeafSizeNumber of original values per leaf. This backend currently supports 252 with BP leaves and 248 or 496 with mask leaves.
FanoutTemplate parameter kept fixed at 256 for the current layout; internal tree nodes use fixed 192-way fanout.
LeafSelectorKindCompile-time low-level selector kind.

Member Typedef Documentation

◆ Self

template<class T, class Compare = std::less<T>, class Index = std::size_t, std::size_t LeafSize = 496, std::size_t Fanout = 256, HybridBTreeLeafSelector LeafSelectorKind = HybridBTreeLeafSelector::PrefixSuffix>
using pixie::rmq::HybridBTree< T, Compare, Index, LeafSize, Fanout, LeafSelectorKind >::Self
Initial value:

Constructor & Destructor Documentation

◆ HybridBTree()

template<class T, class Compare = std::less<T>, class Index = std::size_t, std::size_t LeafSize = 496, std::size_t Fanout = 256, HybridBTreeLeafSelector LeafSelectorKind = HybridBTreeLeafSelector::PrefixSuffix>
pixie::rmq::HybridBTree< T, Compare, Index, LeafSize, Fanout, LeafSelectorKind >::HybridBTree ( std::span< const T > values,
Compare compare = Compare() )
inlineexplicit

Build a hybrid B-tree RMQ index over values.

The values are not copied and must outlive this object. Equal values keep the smaller original position as the answer.

Parameters
valuesValues to index.
compareOrdering used to choose minima.
Exceptions
std::length_errorif Index cannot represent all positions.

Member Function Documentation

◆ arg_min_impl()

template<class T, class Compare = std::less<T>, class Index = std::size_t, std::size_t LeafSize = 496, std::size_t Fanout = 256, HybridBTreeLeafSelector LeafSelectorKind = HybridBTreeLeafSelector::PrefixSuffix>
std::size_t pixie::rmq::HybridBTree< T, Compare, Index, LeafSize, Fanout, LeafSelectorKind >::arg_min_impl ( std::size_t left,
std::size_t right ) const
inline

Return the first minimum position in [left, right).

Empty or invalid ranges return npos. Ties are reduced by comparing (value, position), so traversal order cannot change first-min semantics.

◆ memory_usage_bytes_impl()

template<class T, class Compare = std::less<T>, class Index = std::size_t, std::size_t LeafSize = 496, std::size_t Fanout = 256, HybridBTreeLeafSelector LeafSelectorKind = HybridBTreeLeafSelector::PrefixSuffix>
std::size_t pixie::rmq::HybridBTree< T, Compare, Index, LeafSize, Fanout, LeafSelectorKind >::memory_usage_bytes_impl ( ) const
inline

Return owned auxiliary memory usage in bytes.

Counts this RMQ object and all selector/metadata buffers. The external input values are not owned and are excluded.

Member Data Documentation

◆ kBpLeafSelector

template<class T, class Compare = std::less<T>, class Index = std::size_t, std::size_t LeafSize = 496, std::size_t Fanout = 256, HybridBTreeLeafSelector LeafSelectorKind = HybridBTreeLeafSelector::PrefixSuffix>
bool pixie::rmq::HybridBTree< T, Compare, Index, LeafSize, Fanout, LeafSelectorKind >::kBpLeafSelector
staticconstexpr
Initial value:
=
LeafSelectorKind == HybridBTreeLeafSelector::BP

◆ kMaskLeafSelector

template<class T, class Compare = std::less<T>, class Index = std::size_t, std::size_t LeafSize = 496, std::size_t Fanout = 256, HybridBTreeLeafSelector LeafSelectorKind = HybridBTreeLeafSelector::PrefixSuffix>
bool pixie::rmq::HybridBTree< T, Compare, Index, LeafSize, Fanout, LeafSelectorKind >::kMaskLeafSelector
staticconstexpr
Initial value:
=
LeafSelectorKind == HybridBTreeLeafSelector::PrefixSuffix

The documentation for this class was generated from the following file: