vers_vecs/trees/bp/mod.rs
1//! A succinct tree data structure backed by the balanced parenthesis representation.
2//! The tree supports navigation operations between parent, child, and sibling nodes in `O(log n)`
3//! time, as well as subtree size, level-order, and ancestor queries in `O(log n)` time.
4//! The tree is succinct (ideally sublinear space overhead) and pointer-less.
5
6use crate::bit_vec::fast_rs_vec::SelectIntoIter;
7use crate::trees::mmt::MinMaxTree;
8use crate::trees::{IsAncestor, LevelTree, SubtreeSize, Tree};
9use crate::{BitVec, RsVec};
10use std::cmp::{max, min};
11use std::iter::FusedIterator;
12
13/// The default block size for the tree, used in several const generics
14const DEFAULT_BLOCK_SIZE: usize = 512;
15
16const OPEN_PAREN: u64 = 1;
17const CLOSE_PAREN: u64 = 0;
18
19mod builder;
20// re-export the builders toplevel
21pub use builder::BpBuilder;
22
23#[cfg_attr(feature = "bp_u16_lookup", path = "lookup_table.rs")]
24#[cfg_attr(not(feature = "bp_u16_lookup"), path = "lookup_bitwise.rs")]
25mod lookup;
26use lookup::{process_block_bwd, process_block_fwd, LOOKUP_BLOCK_SIZE};
27
28/// A succinct tree data structure based on balanced parenthesis expressions.
29/// A tree with `n` nodes is encoded in a bit vector using `2n` bits plus the rank/select overhead
30/// of the [`RsVec`] implementation.
31/// Additionally, a small pointerless heap data structure stores
32/// additional meta information required to perform most tree operations.
33///
34/// The tree is thus pointer-less and succinct.
35/// It supports tree navigation operations between parent, child, and sibling nodes, both in
36/// depth-first search order and in level order.
37/// All operations run in `O(log n)` time with small overheads.
38///
39/// ## Lookup Table
40/// The tree internally uses a lookup table for subqueries on blocks of bits.
41/// The lookup table requires 4 KiB of memory and is compiled into the binary.
42/// If the `bp_u16_lookup` feature is enabled, a larger lookup table is used, which requires 128 KiB of
43/// memory, but answers queries faster.
44///
45/// ## Block Size
46/// The tree has a block size of 512 bits by default, which can be changed by setting the
47/// `BLOCK_SIZE` generic parameter.
48/// This block size is expected to be a good choice for most applications,
49/// as it will fit a cache line.
50///
51/// If you want to tune the parameter,
52/// the block size should be chosen based on the expected size of the tree and the available memory.
53/// Smaller block sizes increase the size of the supporting data structure but reduce the time
54/// complexity of some operations by a constant amount.
55/// Larger block sizes are best combined with the `bp_u16_lookup` feature to keep the query time
56/// low.
57/// In any case, benchmarking for the specific use case is recommended for tuning.
58///
59/// ## Unbalanced Parentheses
60/// The tree is implemented in a way to theoretically support unbalanced parenthesis expressions
61/// (which encode invalid trees) without panicking.
62/// However, some operations may behave erratically if the parenthesis expression isn't balanced.
63/// Generally, operations specify if they require a balanced tree.
64///
65/// The results of the operations are unspecified,
66/// meaning no guarantees are made about the stability of the results across versions
67/// (except the operations not panicking).
68/// However, for research purposes, this behavior can be useful and should yield expected results
69/// in most cases.
70///
71/// Only the basic operations like [`fwd_search`] and [`bwd_search`],
72/// as well as the tree navigation operations
73/// (defined by the traits [`Tree`], [`IsAncestor`], [`LevelTree`], and [`SubtreeSize`]),
74/// are included in this guarantee.
75/// Additional operations like iterators may panic if the tree is unbalanced (this is documented per
76/// operation).
77///
78/// # Examples
79///
80/// The high-level approach to building a tree is to use the [`BpBuilder`] to construct the tree
81/// using depth-first traversal of all its nodes.
82/// ```rust
83/// use vers_vecs::{BitVec, BpBuilder, BpTree, TreeBuilder, Tree};
84///
85/// let mut builder = BpBuilder::<512>::new();
86///
87/// // build the tree by depth-first traversal
88/// builder.enter_node();
89/// builder.enter_node();
90/// builder.enter_node();
91/// builder.leave_node();
92/// builder.enter_node();
93/// builder.leave_node();
94/// builder.leave_node();
95/// builder.enter_node();
96/// builder.leave_node();
97/// builder.leave_node();
98///
99/// let tree = builder.build().unwrap();
100/// let root = tree.root().unwrap();
101/// assert_eq!(root, 0);
102/// assert_eq!(tree.first_child(root), Some(1));
103/// assert_eq!(tree.next_sibling(1), Some(7));
104/// assert_eq!(tree.next_sibling(7), None);
105///
106/// assert_eq!(root, 0);
107/// assert_eq!(tree.depth(2), 2);
108/// assert_eq!(tree.depth(7), 1);
109/// ```
110///
111/// Alternatively, the tree can be constructed from a [`BitVec`] containing the parenthesis
112/// expression directly.
113/// This is also how trees with unbalanced parenthesis expressions can be constructed.
114///
115/// ```rust
116/// use vers_vecs::{BitVec, BpTree, Tree};
117/// let bv = BitVec::pack_sequence_u8(&[0b1101_0111, 0b0010_0100], 8);
118/// let tree = BpTree::<4>::from_bit_vector(bv);
119///
120/// let nodes = tree.dfs_iter().collect::<Vec<_>>();
121/// assert_eq!(nodes, vec![0, 1, 2, 4, 6, 7, 10, 13]);
122/// ```
123///
124/// [`RsVec`]: RsVec
125/// [`fwd_search`]: BpTree::fwd_search
126/// [`bwd_search`]: BpTree::bwd_search
127/// [`Tree`]: Tree
128/// [`IsAncestor`]: IsAncestor
129/// [`LevelTree`]: LevelTree
130/// [`SubtreeSize`]: SubtreeSize
131/// [`BpBuilder`]: BpBuilder
132/// [`BitVec`]: BitVec
133#[derive(Clone, Debug)]
134#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
135#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemSize, mem_dbg::MemDbg))]
136pub struct BpTree<const BLOCK_SIZE: usize = DEFAULT_BLOCK_SIZE> {
137 vec: RsVec,
138 min_max_tree: MinMaxTree,
139}
140
141impl<const BLOCK_SIZE: usize> BpTree<BLOCK_SIZE> {
142 /// Construct a new `BpTree` from a given bit vector.
143 #[must_use]
144 pub fn from_bit_vector(bv: BitVec) -> Self {
145 let min_max_tree = MinMaxTree::excess_tree(&bv, BLOCK_SIZE);
146 let vec = bv.into();
147 Self { vec, min_max_tree }
148 }
149
150 /// Search for a position where the excess relative to the starting `index` is `relative_excess`.
151 /// Returns `None` if no such position exists.
152 /// The initial position is never considered in the search.
153 /// Searches forward in the bit vector.
154 ///
155 /// # Arguments
156 /// - `index`: The starting index.
157 /// - `relative_excess`: The desired relative excess value.
158 pub fn fwd_search(&self, index: usize, mut relative_excess: i64) -> Option<usize> {
159 // check for greater than or equal length minus one, because the last element
160 // won't ever have a result from fwd_search
161 if index >= (self.vec.len() - 1) {
162 return None;
163 }
164
165 let block_index = (index + 1) / BLOCK_SIZE;
166 self.fwd_search_block(index, block_index, &mut relative_excess)
167 .map_or_else(
168 |()| {
169 // find the block that contains the desired relative excess
170 let block = self.min_max_tree.fwd_search(block_index, relative_excess);
171
172 // check the result block for the exact position
173 block.and_then(|(block, mut relative_excess)| {
174 self.fwd_search_block(block * BLOCK_SIZE - 1, block, &mut relative_excess)
175 .ok()
176 })
177 },
178 Some,
179 )
180 }
181
182 /// Perform the forward search within one block. If this doesn't yield a result, the caller must
183 /// continue the search in the min-max-tree.
184 ///
185 /// Returns Ok(index) if an index with the desired relative excess is found, or None(excess)
186 /// with the excess at the end of the current block if no index with the desired relative excess
187 /// is found.
188 #[inline(always)]
189 fn fwd_search_block(
190 &self,
191 start_index: usize,
192 block_index: usize,
193 relative_excess: &mut i64,
194 ) -> Result<usize, ()> {
195 let block_boundary = min((block_index + 1) * BLOCK_SIZE, self.vec.len());
196
197 // the boundary at which we can start with table lookups
198 let lookup_boundary = min(
199 (start_index + 1).div_ceil(LOOKUP_BLOCK_SIZE as usize) * LOOKUP_BLOCK_SIZE as usize,
200 block_boundary,
201 );
202 for i in start_index + 1..lookup_boundary {
203 let bit = self.vec.get_unchecked(i);
204 *relative_excess -= if bit == 1 { 1 } else { -1 };
205
206 if *relative_excess == 0 {
207 return Ok(i);
208 }
209 }
210
211 // the boundary up to which we can use table lookups
212 let upper_lookup_boundary = max(
213 lookup_boundary,
214 (block_boundary / LOOKUP_BLOCK_SIZE as usize) * LOOKUP_BLOCK_SIZE as usize,
215 );
216
217 for i in (lookup_boundary..upper_lookup_boundary).step_by(LOOKUP_BLOCK_SIZE as usize) {
218 if let Ok(idx) = process_block_fwd(
219 self.vec
220 .get_bits_unchecked(i, LOOKUP_BLOCK_SIZE as usize)
221 .try_into()
222 .unwrap(),
223 relative_excess,
224 ) {
225 return Ok(i + idx as usize);
226 }
227 }
228
229 // if the upper_lookup_boundary isn't the block_boundary (which happens in non-full blocks, i.e. the last
230 // block in the vector)
231 for i in upper_lookup_boundary..block_boundary {
232 let bit = self.vec.get_unchecked(i);
233 *relative_excess -= if bit == 1 { 1 } else { -1 };
234
235 if *relative_excess == 0 {
236 return Ok(i);
237 }
238 }
239
240 Err(())
241 }
242
243 /// Search for a position where the excess relative to the starting `index` is `relative_excess`.
244 /// Returns `None` if no such position exists.
245 /// The initial position is never considered in the search.
246 /// Searches backward in the bit vector.
247 ///
248 /// # Arguments
249 /// - `index`: The starting index.
250 /// - `relative_excess`: The desired relative excess value.
251 pub fn bwd_search(&self, index: usize, mut relative_excess: i64) -> Option<usize> {
252 if index >= self.vec.len() {
253 return None;
254 }
255
256 // if the index is 0, we cant have a valid result anyway, and this would overflow the
257 // subtraction below, so we report None
258 if index == 0 {
259 return None;
260 }
261
262 // calculate the block we start searching in. It starts at index - 1, so we don't accidentally
263 // search the mM tree and immediately find `index` as the position
264 let block_index = (index - 1) / BLOCK_SIZE;
265
266 // check the current block
267 self.bwd_search_block(index, block_index, &mut relative_excess)
268 .map_or_else(
269 |()| {
270 // find the block that contains the desired relative excess
271 let block = self.min_max_tree.bwd_search(block_index, relative_excess);
272
273 // check the result block for the exact position
274 block.and_then(|(block, mut relative_excess)| {
275 self.bwd_search_block((block + 1) * BLOCK_SIZE, block, &mut relative_excess)
276 .ok()
277 })
278 },
279 Some,
280 )
281 }
282
283 /// Perform the backward search within one block. If this doesn't yield a result, the caller must
284 /// continue the search in the min-max-tree.
285 ///
286 /// Returns Ok(index) if an index with the desired relative excess is found, or None(excess)
287 /// with the excess at the end of the current block if no index with the desired relative excess
288 /// is found.
289 #[inline(always)]
290 fn bwd_search_block(
291 &self,
292 start_index: usize,
293 block_index: usize,
294 relative_excess: &mut i64,
295 ) -> Result<usize, ()> {
296 let block_boundary = min(block_index * BLOCK_SIZE, self.vec.len());
297
298 // the boundary at which we can start with table lookups
299 let lookup_boundary = max(
300 ((start_index - 1) / LOOKUP_BLOCK_SIZE as usize) * LOOKUP_BLOCK_SIZE as usize,
301 block_boundary,
302 );
303 for i in (lookup_boundary..start_index).rev() {
304 let bit = self.vec.get_unchecked(i);
305 *relative_excess += if bit == 1 { 1 } else { -1 };
306
307 if *relative_excess == 0 {
308 return Ok(i);
309 }
310 }
311
312 for i in (block_boundary..lookup_boundary)
313 .step_by(LOOKUP_BLOCK_SIZE as usize)
314 .rev()
315 {
316 if let Ok(idx) = process_block_bwd(
317 self.vec
318 .get_bits_unchecked(i, LOOKUP_BLOCK_SIZE as usize)
319 .try_into()
320 .unwrap(),
321 relative_excess,
322 ) {
323 return Ok(i + idx as usize);
324 }
325 }
326
327 Err(())
328 }
329
330 /// Find the position of the matching closing parenthesis for the opening parenthesis at `index`.
331 /// If the bit at `index` is not an opening parenthesis, the result is meaningless.
332 /// If there is no matching closing parenthesis, `None` is returned.
333 #[must_use]
334 pub fn close(&self, index: usize) -> Option<usize> {
335 if index >= self.vec.len() {
336 return None;
337 }
338
339 self.fwd_search(index, -1)
340 }
341
342 /// Find the position of the matching opening parenthesis for the closing parenthesis at `index`.
343 /// If the bit at `index` is not a closing parenthesis, the result is meaningless.
344 /// If there is no matching opening parenthesis, `None` is returned.
345 #[must_use]
346 pub fn open(&self, index: usize) -> Option<usize> {
347 if index >= self.vec.len() {
348 return None;
349 }
350
351 self.bwd_search(index, -1)
352 }
353
354 /// Find the position of the opening parenthesis that encloses the position `index`.
355 /// This works regardless of whether the bit at `index` is an opening or closing parenthesis.
356 /// If there is no enclosing parenthesis, `None` is returned.
357 #[must_use]
358 pub fn enclose(&self, index: usize) -> Option<usize> {
359 if index >= self.vec.len() {
360 return None;
361 }
362
363 self.bwd_search(
364 index,
365 if self.vec.get_unchecked(index) == 1 {
366 -1
367 } else {
368 -2
369 },
370 )
371 }
372
373 /// Get the excess of open parentheses up to and including the position `index`.
374 /// The excess is the number of open parentheses minus the number of closing parentheses.
375 /// If `index` is out of bounds, the total excess of the parentheses expression is returned.
376 #[must_use]
377 pub fn excess(&self, index: usize) -> i64 {
378 debug_assert!(index < self.vec.len(), "Index out of bounds");
379 self.vec.rank1(index + 1) as i64 - self.vec.rank0(index + 1) as i64
380 }
381
382 /// Iterate over the nodes of the tree.
383 /// The iterator yields the nodes in depth-first (pre-)order.
384 /// This method is an alias for [`dfs_iter`].
385 ///
386 /// If the tree is unbalanced, the iterator returns the node handles in the order they appear in
387 /// the parenthesis expression, and it will return handles that don't have a matching closing
388 /// parenthesis.
389 ///
390 /// [`dfs_iter`]: BpTree::dfs_iter
391 pub fn iter(
392 &self,
393 ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
394 self.dfs_iter()
395 }
396
397 /// Iterate over the nodes of the tree in depth-first (pre-)order.
398 /// This is the most efficient way to iterate over all nodes of the tree.
399 ///
400 /// If the tree is unbalanced, the iterator returns the node handles in the order they appear in
401 /// the parenthesis expression, and it will return handles that don't have a matching closing
402 /// parenthesis.
403 pub fn dfs_iter(
404 &self,
405 ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
406 self.vec.iter1()
407 }
408
409 /// Iterate over the nodes of a valid tree in depth-first (post-)order.
410 /// This is slower than the pre-order iteration.
411 ///
412 /// # Panics
413 /// The iterator may panic at any point if the parenthesis expression is unbalanced.
414 pub fn dfs_post_iter(
415 &self,
416 ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
417 self.vec.iter0().map(|n| self.open(n).unwrap())
418 }
419
420 /// Iterate over a subtree rooted at `node` in depth-first (pre-)order.
421 /// The iteration starts with the node itself.
422 ///
423 /// Calling this method on an invalid node handle, or an unbalanced parenthesis expression,
424 /// will produce an iterator over an unspecified subset of nodes.
425 pub fn subtree_iter(
426 &self,
427 node: <BpTree<BLOCK_SIZE> as Tree>::NodeHandle,
428 ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
429 debug_assert!(
430 self.vec.get(node) == Some(OPEN_PAREN),
431 "Node handle is invalid"
432 );
433
434 let index = self.vec.rank1(node);
435 let close = self.close(node).unwrap_or(node);
436 let subtree_size = self.vec.rank1(close) - index;
437
438 self.vec.iter1().skip(index).take(subtree_size)
439 }
440
441 /// Iterate over a subtree rooted at `node` in depth-first (post-)order.
442 /// This is slower than the pre-order iteration.
443 /// The iteration ends with the node itself.
444 ///
445 /// # Panics
446 /// Calling this method on an invalid node handle, or an unbalanced parenthesis expression,
447 /// will produce an iterator over an unspecified subset of nodes, or panic either during
448 /// construction or iteration.
449 pub fn subtree_post_iter(
450 &self,
451 node: <BpTree<BLOCK_SIZE> as Tree>::NodeHandle,
452 ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
453 debug_assert!(
454 self.vec.get(node) == Some(OPEN_PAREN),
455 "Node handle is invalid"
456 );
457
458 let index = self.vec.rank0(node);
459 let close = self.close(node).unwrap_or(node);
460 let subtree_size = self.vec.rank0(close) + 1 - index;
461
462 self.vec
463 .iter0()
464 .skip(index)
465 .take(subtree_size)
466 .map(|n| self.open(n).unwrap())
467 }
468
469 /// Iterate over the children of a node in the tree.
470 /// The iterator yields the children in the order they appear in the parenthesis expression.
471 /// If the node is a leaf, the iterator is empty.
472 /// If the node is not a valid node handle, or the tree is unbalanced,
473 /// the iterator will produce an unspecified subset of the tree's nodes.
474 pub fn children(
475 &self,
476 node: <BpTree<BLOCK_SIZE> as Tree>::NodeHandle,
477 ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
478 debug_assert!(
479 self.vec.get(node) == Some(OPEN_PAREN),
480 "Node handle is invalid"
481 );
482
483 ChildrenIter::<BLOCK_SIZE, true>::new(self, node)
484 }
485
486 /// Iterate over the children of a node in the tree in reverse order.
487 /// The iterator yields the children in the reverse order they appear in the parenthesis expression.
488 /// If the node is a leaf, the iterator is empty.
489 /// If the node is not a valid node handle, or the tree is unbalanced,
490 /// the iterator will produce an unspecified subset of the tree's nodes.
491 pub fn rev_children(
492 &self,
493 node: <BpTree<BLOCK_SIZE> as Tree>::NodeHandle,
494 ) -> impl Iterator<Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle> + use<'_, BLOCK_SIZE> {
495 debug_assert!(
496 self.vec.get(node) == Some(OPEN_PAREN),
497 "Node handle is invalid"
498 );
499
500 ChildrenIter::<BLOCK_SIZE, false>::new(self, node)
501 }
502
503 /// Transform the tree into a [`RsVec`] containing the balanced parenthesis expression.
504 /// This consumes the tree and returns the underlying bit vector with the rank and select
505 /// support structure.
506 /// The remaining min-max-tree support structure of the `BpTree` is discarded.
507 /// Since the tree is innately immutable, this is the only way to access the underlying bit
508 /// vector for potential modification.
509 /// Modification requires turning the `RsVec` back into a `BitVec`, discarding the rank and select
510 /// support structure, however.
511 ///
512 /// # Examples
513 /// ```rust
514 /// use vers_vecs::{BitVec, RsVec, BpTree, Tree};
515 ///
516 /// let bv = BitVec::pack_sequence_u8(&[0b1101_0111, 0b0010_0100], 8);
517 /// let tree = BpTree::<4>::from_bit_vector(bv);
518 /// assert_eq!(tree.size(), 8);
519 ///
520 /// let rs_vec = tree.into_parentheses_vec();
521 /// let mut bv = rs_vec.into_bit_vec();
522 ///
523 /// bv.flip_bit(15);
524 /// bv.append_bits(0, 2);
525 /// let tree = BpTree::<4>::from_bit_vector(bv);
526 /// assert_eq!(tree.size(), 9);
527 /// ```
528 #[must_use]
529 pub fn into_parentheses_vec(self) -> RsVec {
530 self.vec
531 }
532
533 /// Returns the number of bytes used on the heap for this tree. This does not include
534 /// allocated space that is not used (e.g. by the allocation behavior of `Vec`).
535 #[must_use]
536 pub fn heap_size(&self) -> usize {
537 self.vec.heap_size() + self.min_max_tree.heap_size()
538 }
539}
540
541impl<const BLOCK_SIZE: usize> Tree for BpTree<BLOCK_SIZE> {
542 type NodeHandle = usize;
543
544 fn root(&self) -> Option<Self::NodeHandle> {
545 if self.vec.is_empty() {
546 None
547 } else {
548 Some(0)
549 }
550 }
551
552 fn parent(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
553 debug_assert!(
554 self.vec.get(node) == Some(OPEN_PAREN),
555 "Node handle is invalid"
556 );
557
558 self.enclose(node)
559 }
560
561 fn first_child(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
562 debug_assert!(
563 self.vec.get(node) == Some(OPEN_PAREN),
564 "Node handle is invalid"
565 );
566
567 if let Some(bit) = self.vec.get(node + 1) {
568 if bit == OPEN_PAREN {
569 return Some(node + 1);
570 }
571 }
572
573 None
574 }
575
576 fn next_sibling(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
577 debug_assert!(
578 self.vec.get(node) == Some(OPEN_PAREN),
579 "Node handle is invalid"
580 );
581 self.close(node).and_then(|i| {
582 self.vec
583 .get(i + 1)
584 .and_then(|bit| if bit == OPEN_PAREN { Some(i + 1) } else { None })
585 })
586 }
587
588 fn previous_sibling(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
589 debug_assert!(
590 self.vec.get(node) == Some(OPEN_PAREN),
591 "Node handle is invalid"
592 );
593 if node == 0 {
594 None
595 } else {
596 self.vec.get(node - 1).and_then(|bit| {
597 if bit == CLOSE_PAREN {
598 self.open(node - 1)
599 } else {
600 None
601 }
602 })
603 }
604 }
605
606 fn last_child(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
607 debug_assert!(
608 self.vec.get(node) == Some(OPEN_PAREN),
609 "Node handle is invalid"
610 );
611 self.vec.get(node + 1).and_then(|bit| {
612 if bit == OPEN_PAREN {
613 if let Some(i) = self.close(node) {
614 self.open(i - 1)
615 } else {
616 None
617 }
618 } else {
619 None
620 }
621 })
622 }
623
624 fn node_index(&self, node: Self::NodeHandle) -> usize {
625 debug_assert!(
626 self.vec.get(node) == Some(OPEN_PAREN),
627 "Node handle is invalid"
628 );
629 self.vec.rank1(node)
630 }
631
632 fn node_handle(&self, index: usize) -> Self::NodeHandle {
633 self.vec.select1(index)
634 }
635
636 fn is_leaf(&self, node: Self::NodeHandle) -> bool {
637 debug_assert!(
638 self.vec.get(node) == Some(OPEN_PAREN),
639 "Node handle is invalid"
640 );
641 self.vec.get(node + 1) == Some(CLOSE_PAREN)
642 }
643
644 fn depth(&self, node: Self::NodeHandle) -> u64 {
645 debug_assert!(
646 self.vec.get(node) == Some(OPEN_PAREN),
647 "Node handle is invalid"
648 );
649 let excess: u64 = self.excess(node).try_into().unwrap_or(0);
650 excess.saturating_sub(1)
651 }
652
653 fn size(&self) -> usize {
654 self.vec.rank1(self.vec.len())
655 }
656
657 fn is_empty(&self) -> bool {
658 self.vec.is_empty()
659 }
660}
661
662impl<const BLOCK_SIZE: usize> IsAncestor for BpTree<BLOCK_SIZE> {
663 fn is_ancestor(
664 &self,
665 ancestor: Self::NodeHandle,
666 descendant: Self::NodeHandle,
667 ) -> Option<bool> {
668 debug_assert!(
669 self.vec.get(ancestor) == Some(OPEN_PAREN),
670 "Node handle is invalid"
671 );
672 debug_assert!(
673 self.vec.get(descendant) == Some(OPEN_PAREN),
674 "Node handle is invalid"
675 );
676
677 self.close(ancestor)
678 .map(|closing| ancestor <= descendant && descendant < closing)
679 }
680}
681
682impl<const BLOCK_SIZE: usize> LevelTree for BpTree<BLOCK_SIZE> {
683 fn level_ancestor(&self, node: Self::NodeHandle, level: u64) -> Option<Self::NodeHandle> {
684 if level == 0 {
685 return Some(node);
686 }
687
688 #[allow(clippy::cast_possible_wrap)]
689 // if the level exceeds 2^63, we accept that the result is wrong
690 self.bwd_search(node, -(level as i64))
691 }
692
693 fn level_next(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
694 self.fwd_search(self.close(node)?, 1)
695 }
696
697 fn level_prev(&self, node: Self::NodeHandle) -> Option<Self::NodeHandle> {
698 self.open(self.bwd_search(node, 1)?)
699 }
700
701 fn level_leftmost(&self, level: u64) -> Option<Self::NodeHandle> {
702 // fwd_search doesn't support returning the input position
703 if level == 0 {
704 return Some(0);
705 }
706
707 #[allow(clippy::cast_possible_wrap)]
708 // if the level exceeds 2^63, we accept that the result is wrong
709 self.fwd_search(0, level as i64)
710 }
711
712 fn level_rightmost(&self, level: u64) -> Option<Self::NodeHandle> {
713 #[allow(clippy::cast_possible_wrap)]
714 // if the level exceeds 2^63, we accept that the result is wrong
715 self.open(self.bwd_search(self.size() * 2 - 1, level as i64)?)
716 }
717}
718
719impl<const BLOCK_SIZE: usize> SubtreeSize for BpTree<BLOCK_SIZE> {
720 fn subtree_size(&self, node: Self::NodeHandle) -> Option<usize> {
721 debug_assert!(
722 self.vec.get(node) == Some(OPEN_PAREN),
723 "Node handle is invalid"
724 );
725
726 self.close(node)
727 .map(|c| self.vec.rank1(c) - self.vec.rank1(node))
728 }
729}
730
731impl<const BLOCK_SIZE: usize> IntoIterator for BpTree<BLOCK_SIZE> {
732 type Item = <BpTree<BLOCK_SIZE> as Tree>::NodeHandle;
733 type IntoIter = SelectIntoIter<false>;
734
735 fn into_iter(self) -> Self::IntoIter {
736 self.vec.into_iter1()
737 }
738}
739
740impl<const BLOCK_SIZE: usize> From<BitVec> for BpTree<BLOCK_SIZE> {
741 fn from(bv: BitVec) -> Self {
742 Self::from_bit_vector(bv)
743 }
744}
745
746impl<const BLOCK_SIZE: usize> From<BpTree<BLOCK_SIZE>> for BitVec {
747 fn from(value: BpTree<BLOCK_SIZE>) -> Self {
748 value.into_parentheses_vec().into_bit_vec()
749 }
750}
751
752impl<const BLOCK_SIZE: usize> From<BpTree<BLOCK_SIZE>> for RsVec {
753 fn from(value: BpTree<BLOCK_SIZE>) -> Self {
754 value.into_parentheses_vec()
755 }
756}
757
758/// An iterator over the children of a node.
759/// Calls to `next` return the next child node handle in the order they appear in the parenthesis
760/// expression.
761struct ChildrenIter<'a, const BLOCK_SIZE: usize, const FORWARD: bool> {
762 tree: &'a BpTree<BLOCK_SIZE>,
763 current_sibling: Option<usize>,
764}
765
766impl<'a, const BLOCK_SIZE: usize, const FORWARD: bool> ChildrenIter<'a, BLOCK_SIZE, FORWARD> {
767 fn new(tree: &'a BpTree<BLOCK_SIZE>, node: usize) -> Self {
768 Self {
769 tree,
770 current_sibling: if FORWARD {
771 tree.first_child(node)
772 } else {
773 tree.last_child(node)
774 },
775 }
776 }
777}
778
779impl<const BLOCK_SIZE: usize, const FORWARD: bool> Iterator
780 for ChildrenIter<'_, BLOCK_SIZE, FORWARD>
781{
782 type Item = usize;
783
784 fn next(&mut self) -> Option<Self::Item> {
785 let current = self.current_sibling?;
786 let next = if FORWARD {
787 self.tree.next_sibling(current)
788 } else {
789 self.tree.previous_sibling(current)
790 };
791 self.current_sibling = next;
792 Some(current)
793 }
794}
795
796impl<const BLOCK_SIZE: usize, const FORWARD: bool> FusedIterator
797 for ChildrenIter<'_, BLOCK_SIZE, FORWARD>
798{
799}
800
801#[cfg(test)]
802mod tests;