use super::*;
#[inline]
fn covered_from_change_points<I>(points: &[ChangePoint<I::CoordType>]) -> IntCOSet<I>
where
I: IntCO,
{
let mut out = Vec::new();
let mut start = None;
for p in points {
match (start, p.height_after) {
(None, h) if h > 0 => {
start = Some(p.at);
}
(Some(s), 0) => {
out.push(unsafe { I::new_unchecked(s, p.at) });
start = None;
}
_ => {}
}
}
debug_assert!(
start.is_none(),
"canonical stack change points must end at zero height"
);
unsafe { IntCOSet::new_unchecked(out) }
}
impl<I> IntCOStack<I>
where
I: IntCO,
{
#[inline]
pub fn change_points(&self) -> &[ChangePoint<I::CoordType>] {
&self.change_points
}
#[inline]
pub fn covered(&self) -> &IntCOSet<I> {
self.covered
.get_or_init(|| covered_from_change_points::<I>(&self.change_points))
}
#[inline]
pub fn height_stats(&self) -> HeightStats {
self.height_stats
}
#[inline]
pub fn height_at(&self, x: I::CoordType) -> usize {
let i = self.change_points.partition_point(|p| p.at <= x);
if i == 0 {
0
} else {
self.change_points[i - 1].height_after
}
}
}
#[cfg(test)]
mod tests_for_access;
#[cfg(test)]
mod tests_for_covered_from_change_points;