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