use super::{ComputeScope, Level, Partitioning, Space};
use crate::Axis;
#[derive(Clone, Debug)]
pub(crate) struct Path {
base: usize,
root: Partitioning,
levels: Vec<Level>,
}
impl Path {
pub(crate) fn new(base: usize, root: Partitioning, levels: Vec<Level>) -> Self {
Path { base, root, levels }
}
pub(crate) fn depth(&self) -> usize {
self.base + self.levels.len()
}
pub(crate) fn base(&self) -> usize {
self.base
}
pub(crate) fn len(&self) -> usize {
self.levels.len()
}
pub(crate) fn level(&self, i: usize) -> &Level {
&self.levels[i]
}
pub(crate) fn space_at(&self, i: usize) -> Space {
self.root.space().leaf(&self.levels[..i])
}
pub(crate) fn child(&self) -> Space {
self.root.space().leaf(&self.levels)
}
pub(crate) fn next(&self) -> Level {
let depth = self.depth();
let levels = self.root.levels();
assert!(
depth < levels.len(),
"this region sits {depth} levels down a partitioning of {} levels, so there is no \
level below it to iterate; a walk of the kernel's own says `over`",
levels.len()
);
levels[depth].clone()
}
pub(crate) fn scope(&self) -> ComputeScope {
self.root.levels()[..self.base]
.iter()
.chain(&self.levels)
.filter_map(|level| level.coverage().scope())
.min()
.unwrap_or(ComputeScope::Cube)
}
pub(crate) fn root_levels(&self) -> Vec<Level> {
self.root.levels().to_vec()
}
pub(crate) fn planes_per_cube(&self) -> usize {
self.root.planes_per_cube() as usize
}
pub(crate) fn planes_along(&self, along: impl Fn(Axis) -> bool) -> Vec<(Axis, usize)> {
let mut handed = self.root.space().clone();
let mut planes = Vec::new();
for level in self.root.levels() {
let scope = level.coverage().scope();
for axis in level.axes() {
if !(scope.and_then(ComputeScope::planes).is_some()
&& level.distributes(axis)
&& along(axis))
{
continue;
}
assert!(
scope == Some(ComputeScope::Plane),
"{axis:?} is split across the cube's plane groups, and nothing merges what \
plane groups hold of the same box yet; deal each group a box of its own"
);
let count = level.instances_along(&handed, axis).unwrap_or_else(|| {
panic!(
"{axis:?} is split across the cube's planes at a count only the launch \
knows, so the planes holding the same box cannot be counted"
)
});
planes.push((axis, count));
}
handed = level.child(&handed);
}
planes
}
pub(crate) fn at_bottom(&self) -> bool {
self.depth() == self.root.levels().len()
}
pub(crate) fn below(&self, level: Level) -> Path {
let mut levels = self.levels.clone();
levels.push(level);
Path::new(self.base, self.root.clone(), levels)
}
}