#![doc(
html_logo_url = "https://raw.githubusercontent.com/tiby312/broccoli-project/master/assets/logo.png",
html_favicon_url = "https://raw.githubusercontent.com/tiby312/broccoli-project/master/assets/logo.png"
)]
#![forbid(unsafe_code)]
#[cfg(doctest)]
mod test_readme {
macro_rules! external_doc_test {
($x:expr) => {
#[doc = $x]
extern "C" {}
};
}
external_doc_test!(include_str!("../../README.md"));
}
#[macro_use]
extern crate alloc;
pub use axgeom;
pub mod build;
pub mod node;
pub mod aabb;
use aabb::pin::AabbPin;
use aabb::pin::AabbPinIter;
use aabb::pin::*;
use aabb::*;
use axgeom::*;
use build::*;
use node::*;
#[cfg(test)]
mod tests;
pub mod assert;
pub mod queries;
use assert::Assert;
use assert::Naive;
pub use axgeom::rect;
#[inline(always)]
#[must_use]
pub fn bbox<N, T>(rect: axgeom::Rect<N>, inner: T) -> BBox<N, T> {
BBox::new(rect, inner)
}
#[inline(always)]
#[must_use]
pub fn bbox_mut<N, T>(rect: axgeom::Rect<N>, inner: &mut T) -> BBoxMut<N, T> {
BBoxMut::new(rect, inner)
}
#[derive(Clone)]
pub struct TreeData<N: Num> {
nodes: Vec<NodeData<N>>,
}
#[macro_export]
macro_rules! unpack {
( $( $x:ident ),* ) => {
$(
let mut $x = $x.unpack_inner();
)*
};
}
#[macro_export]
macro_rules! from_cached_key {
( $x:ident ,$y:expr,$z:expr) => {
let mut $x = $crate::Cached::new_by_cached_key($y, $z);
let mut $x = $x.build();
};
}
pub struct Cached<'a, N, T> {
rects: Vec<BBoxMut<'a, N, T>>,
}
impl<'a, N: Num, T> Cached<'a, N, T> {
pub fn build<'b>(&'b mut self) -> Tree<'b, BBoxMut<'a, N, T>> {
Tree::new(&mut self.rects)
}
pub fn new_by_cached_key(
a: &'a mut [T],
mut key: impl FnMut(&T) -> Rect<N>,
) -> Cached<'a, N, T> {
let rects = a.iter_mut().map(|a| BBoxMut::new(key(a), a)).collect();
Cached { rects }
}
}
pub struct Tree<'a, T: Aabb> {
nodes: Box<[Node<'a, T, T::Num>]>,
}
impl<'a, T: Aabb + 'a> Tree<'a, T> {
pub fn from_nodes(nodes: Vec<Node<'a, T, T::Num>>) -> Self {
Tree {
nodes: nodes.into_boxed_slice(),
}
}
pub fn into_nodes(self) -> Vec<Node<'a, T, T::Num>> {
self.nodes.into_vec()
}
pub fn get_tree_data(&self) -> TreeData<T::Num> {
let nodes = self.nodes.iter().map(|x| x.as_data()).collect();
TreeData { nodes }
}
pub fn from_tree_data(bots: &'a mut [T], data: &TreeData<T::Num>) -> Self {
let mut last = Some(bots);
let nodes = data
.nodes
.iter()
.map(|x| {
let (range, rest) = last.take().unwrap().split_at_mut(x.range);
last = Some(rest);
Node {
range: AabbPin::from_mut(range),
cont: x.cont,
div: x.div,
min_elem: x.min_elem,
}
})
.collect();
assert!(last.unwrap().is_empty());
Tree { nodes }
}
pub fn new(bots: &'a mut [T]) -> Self
where
T: ManySwap,
{
let (mut e, v) = TreeEmbryo::new(bots);
e.recurse(v, &mut DefaultSorter);
e.finish()
}
#[inline(always)]
pub fn vistr_mut(&mut self) -> VistrMutPin<Node<'a, T, T::Num>> {
let tree = compt::dfs_order::CompleteTreeMut::from_preorder_mut(&mut self.nodes).unwrap();
VistrMutPin::new(tree.vistr_mut())
}
#[inline(always)]
pub fn vistr(&self) -> Vistr<Node<'a, T, T::Num>> {
let tree = compt::dfs_order::CompleteTree::from_preorder(&self.nodes).unwrap();
tree.vistr()
}
#[must_use]
#[inline(always)]
pub fn num_levels(&self) -> usize {
compt::dfs_order::CompleteTree::from_preorder(&self.nodes)
.unwrap()
.get_height()
}
#[must_use]
#[inline(always)]
pub fn num_nodes(&self) -> usize {
self.nodes.len()
}
#[must_use]
#[inline(always)]
pub fn get_nodes(&self) -> &[Node<'a, T, T::Num>] {
&self.nodes
}
#[must_use]
#[inline(always)]
pub fn get_nodes_mut(&mut self) -> AabbPin<&mut [Node<'a, T, T::Num>]> {
AabbPin::from_mut(&mut self.nodes)
}
}
pub mod num_level {
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_num_nodes() {
assert_eq!(num_nodes(1), 01);
assert_eq!(num_nodes(2), 03);
assert_eq!(num_nodes(3), 07);
assert_eq!(num_nodes(4), 15);
}
}
pub const fn num_nodes(num_levels: usize) -> usize {
assert!(num_levels >= 1);
2usize.rotate_left((num_levels - 1) as u32) - 1
}
pub const DEFAULT_NUMBER_ELEM_PER_NODE: usize = 80;
#[must_use]
pub fn default(num_elements: usize) -> usize {
with_num_elem_in_leaf(num_elements, DEFAULT_NUMBER_ELEM_PER_NODE)
}
#[must_use]
pub const fn with_num_elem_in_leaf(num_elements: usize, num_elem_leaf: usize) -> usize {
#[must_use]
const fn log_2(x: u64) -> u64 {
const fn num_bits<T>() -> usize {
core::mem::size_of::<T>() * 8
}
num_bits::<u64>() as u64 - x.leading_zeros() as u64 - 1
}
if num_elements <= num_elem_leaf {
1
} else {
let (num_bots, num_per_node) = (num_elements as u64, num_elem_leaf as u64);
let a = num_bots / num_per_node;
let a = log_2(a);
let k = (((a / 2) * 2) + 1) as usize;
assert!(k % 2 == 1);
assert!(k >= 1);
k
}
}
}