use broccoli::{
aabb::Aabb,
aabb::ManySwap,
build::TreeEmbryo,
Tree,
{
build::Sorter,
build::{DefaultSorter, NodeBuildResult, TreeBuildVisitor},
},
};
pub trait RayonBuildPar<'a, T: Aabb> {
fn par_new(bots: &'a mut [T]) -> Self;
}
impl<'a, T: Aabb + ManySwap> RayonBuildPar<'a, T> for Tree<'a, T>
where
T: Send,
T::Num: Send,
{
fn par_new(bots: &'a mut [T]) -> Self {
let (mut buffer, v) = TreeEmbryo::new(bots);
recurse_par(SEQ_FALLBACK_DEFAULT, &mut DefaultSorter, &mut buffer, v);
buffer.finish()
}
}
pub const SEQ_FALLBACK_DEFAULT: usize = 16;
pub fn recurse_par<'a, T: Aabb + ManySwap, S: Sorter<T> + Clone>(
num_seq_fallback: usize,
sorter: &mut S,
buffer: &mut TreeEmbryo<'a, T, T::Num>,
vistr: TreeBuildVisitor<'a, T>,
) where
S: Send,
T: Send,
T::Num: Send,
{
let NodeBuildResult { node, rest } = vistr.build_and_next();
if let Some([left, right]) = rest {
if node.get_min_elem() <= num_seq_fallback {
buffer.add(node.finish(sorter));
buffer.recurse(left, sorter);
buffer.recurse(right, sorter);
} else {
let mut s2 = sorter.clone();
let mut b2 = buffer.div();
rayon::join(
|| {
buffer.add(node.finish(sorter));
recurse_par(num_seq_fallback, sorter, buffer, left);
},
|| {
recurse_par(num_seq_fallback, &mut s2, &mut b2, right);
},
);
buffer.combine(b2);
}
} else {
buffer.add(node.finish(sorter));
}
}