use std::ops::ControlFlow;
pub(crate) trait JoinTree {
type Bounds: Copy;
fn join_num_items(&self) -> usize;
fn join_num_nodes(&self) -> usize;
fn join_node_size(&self) -> usize;
fn join_level_count(&self) -> usize;
fn join_level_bound(&self, level: usize) -> usize;
fn join_bounds(&self, pos: usize) -> Self::Bounds;
fn join_index(&self, pos: usize) -> usize;
fn bounds_overlap(a: Self::Bounds, b: Self::Bounds) -> bool;
fn bounds_contain(outer: Self::Bounds, inner: Self::Bounds) -> bool;
}
#[inline]
fn leaf_range<T: JoinTree>(tree: &T, pos: usize, level: usize) -> (usize, usize) {
let mut start = pos;
for _ in 0..level {
start = tree.join_index(start);
}
let end = if pos + 1 < tree.join_level_bound(level) {
let mut end = pos + 1;
for _ in 0..level {
end = tree.join_index(end);
}
end
} else {
tree.join_num_items()
};
(start, end)
}
#[inline]
#[allow(clippy::too_many_arguments)]
fn expand_pair<R, T, U, F>(
a: &T,
b: &U,
a_pos: usize,
a_level: usize,
b_pos: usize,
b_level: usize,
stack: &mut Vec<(usize, usize, usize, usize)>,
visitor: &mut F,
) -> ControlFlow<R>
where
T: JoinTree,
U: JoinTree<Bounds = T::Bounds>,
F: FnMut(usize, usize) -> ControlFlow<R>,
{
if a_level >= b_level {
debug_assert!(a_level > 0);
let child_level = a_level - 1;
let start = a.join_index(a_pos);
let end = (start + a.join_node_size()).min(a.join_level_bound(child_level));
let b_bounds = b.join_bounds(b_pos);
for pos in start..end {
let bounds = a.join_bounds(pos);
if !T::bounds_overlap(bounds, b_bounds) {
continue;
}
if child_level == 0 {
if b_level == 0 {
visitor(a.join_index(pos), b.join_index(b_pos))?;
} else if T::bounds_contain(bounds, b_bounds) {
let item_a = a.join_index(pos);
let (s, e) = leaf_range(b, b_pos, b_level);
for b_leaf in s..e {
visitor(item_a, b.join_index(b_leaf))?;
}
} else {
stack.push((pos, 0, b_pos, b_level));
}
} else if b_level == 0 && T::bounds_contain(b_bounds, bounds) {
let item_b = b.join_index(b_pos);
let (s, e) = leaf_range(a, pos, child_level);
for a_leaf in s..e {
visitor(a.join_index(a_leaf), item_b)?;
}
} else {
stack.push((pos, child_level, b_pos, b_level));
}
}
} else {
let child_level = b_level - 1;
let start = b.join_index(b_pos);
let end = (start + b.join_node_size()).min(b.join_level_bound(child_level));
let a_bounds = a.join_bounds(a_pos);
for pos in start..end {
let bounds = b.join_bounds(pos);
if !T::bounds_overlap(a_bounds, bounds) {
continue;
}
if child_level == 0 {
if a_level == 0 {
visitor(a.join_index(a_pos), b.join_index(pos))?;
} else if T::bounds_contain(bounds, a_bounds) {
let item_b = b.join_index(pos);
let (s, e) = leaf_range(a, a_pos, a_level);
for a_leaf in s..e {
visitor(a.join_index(a_leaf), item_b)?;
}
} else {
stack.push((a_pos, a_level, pos, 0));
}
} else if a_level == 0 && T::bounds_contain(a_bounds, bounds) {
let item_a = a.join_index(a_pos);
let (s, e) = leaf_range(b, pos, child_level);
for b_leaf in s..e {
visitor(item_a, b.join_index(b_leaf))?;
}
} else {
stack.push((a_pos, a_level, pos, child_level));
}
}
}
ControlFlow::Continue(())
}
pub(crate) fn join_core<R, T, U, F>(a: &T, b: &U, mut visitor: F) -> ControlFlow<R>
where
T: JoinTree,
U: JoinTree<Bounds = T::Bounds>,
F: FnMut(usize, usize) -> ControlFlow<R>,
{
if a.join_num_items() == 0 || b.join_num_items() == 0 {
return ControlFlow::Continue(());
}
let mut a_pos = a.join_num_nodes() - 1;
let mut a_level = a.join_level_count() - 1;
let mut b_pos = b.join_num_nodes() - 1;
let mut b_level = b.join_level_count() - 1;
if !T::bounds_overlap(a.join_bounds(a_pos), b.join_bounds(b_pos)) {
return ControlFlow::Continue(());
}
let mut stack: Vec<(usize, usize, usize, usize)> = Vec::with_capacity(64);
loop {
expand_pair(
a,
b,
a_pos,
a_level,
b_pos,
b_level,
&mut stack,
&mut visitor,
)?;
match stack.pop() {
Some((ap, al, bp, bl)) => {
a_pos = ap;
a_level = al;
b_pos = bp;
b_level = bl;
}
None => return ControlFlow::Continue(()),
}
}
}
pub(crate) fn self_join_core<R, T, F>(tree: &T, mut visitor: F) -> ControlFlow<R>
where
T: JoinTree,
F: FnMut(usize, usize) -> ControlFlow<R>,
{
if tree.join_num_items() < 2 {
return ControlFlow::Continue(());
}
let mut a_pos = tree.join_num_nodes() - 1;
let mut a_level = tree.join_level_count() - 1;
let mut b_pos = a_pos;
let mut b_level = a_level;
let mut stack: Vec<(usize, usize, usize, usize)> = Vec::with_capacity(64);
loop {
if a_pos == b_pos && a_level == b_level {
debug_assert!(a_level > 0);
let child_level = a_level - 1;
let start = tree.join_index(a_pos);
let end = (start + tree.join_node_size()).min(tree.join_level_bound(child_level));
for i in start..end {
let bounds_i = tree.join_bounds(i);
if child_level > 0 {
stack.push((i, child_level, i, child_level));
}
for j in (i + 1)..end {
if !T::bounds_overlap(bounds_i, tree.join_bounds(j)) {
continue;
}
if child_level == 0 {
visitor(tree.join_index(i), tree.join_index(j))?;
} else {
stack.push((i, child_level, j, child_level));
}
}
}
} else {
expand_pair(
tree,
tree,
a_pos,
a_level,
b_pos,
b_level,
&mut stack,
&mut visitor,
)?;
}
match stack.pop() {
Some((ap, al, bp, bl)) => {
a_pos = ap;
a_level = al;
b_pos = bp;
b_level = bl;
}
None => return ControlFlow::Continue(()),
}
}
}