#![allow(unused_results)]
use crate::bound::Bound;
use crate::raw_interval::RawInterval;
use crate::tine::Tine;
#[cfg(feature="serde")] use serde::Deserialize;
#[cfg(feature="serde")] use serde::Serialize;
use few::Few;
use std::collections::BTreeSet;
use std::collections::btree_set;
use std::iter::FromIterator;
#[repr(transparent)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature="serde", serde(transparent))]
#[cfg_attr(feature="serde",
serde(bound="for<'a> T: Ord + Serialize + Deserialize<'a> + Clone + 'a"))]
pub struct TineTree<T>(BTreeSet<Tine<T>>);
impl<T> TineTree<T> where T: Ord + Clone {
#[must_use]
pub fn new() -> Self {
Self(BTreeSet::new())
}
#[must_use]
pub fn from_raw_interval(interval: RawInterval<T>) -> Self {
Self(Tine::from_raw_interval(interval).collect())
}
#[inline]
pub fn lower_bound(&self) -> Option<Bound<T>> {
self.0.iter().next().cloned().map(Tine::into_inner)
}
#[inline]
pub fn upper_bound(&self) -> Option<Bound<T>> {
self.0.iter().next_back().cloned().map(Tine::into_inner)
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[must_use]
pub fn is_full(&self) -> bool {
self.0.iter().collect::<Vec<_>>() == [
&Tine::Lower(Bound::Infinite),
&Tine::Upper(Bound::Infinite)]
}
#[must_use]
pub fn contains(&self, point: &T) -> bool {
for interval in self.interval_iter() {
if interval.contains(point) {return true;}
}
false
}
#[allow(clippy::missing_panics_doc)]
#[must_use]
pub fn complement(&self) -> Self {
use Bound::*;
use Tine::*;
if self.0.is_empty() {
return RawInterval::Full.into();
}
let mut complement = Self::new();
let mut tine_iter = self.0.iter();
if self.0.len() == 1 {
let tine = tine_iter
.next()
.expect("nonempty TineTree")
.clone()
.invert();
debug_assert!(tine.is_point_exclude());
complement.0.insert(Lower(Infinite));
complement.0.insert(tine);
complement.0.insert(Upper(Infinite));
return complement;
}
match tine_iter.next() {
Some(&Lower(Infinite)) => {},
Some(tine) => {
complement.0.insert(Lower(Infinite));
complement.0.insert(tine.clone().invert());
},
_ => unreachable!("TineTree len > 1"),
}
match tine_iter.next_back() {
Some(&Upper(Infinite)) => {},
Some(tine) => {
complement.0.insert(Upper(Infinite));
complement.0.insert(tine.clone().invert());
},
_ => unreachable!("TineTree len > 0"),
}
for tine in tine_iter {
complement.0.insert(tine.clone().invert());
}
complement
}
#[must_use]
pub fn intersect(&self, other: &Self) -> Self {
let mut intersection = Self::new();
let self_intervals = self.interval_iter();
let mut other_intervals = other.interval_iter();
for self_interval in self_intervals {
'segment: loop {
if let Some(other_interval) = other_intervals.next() {
let i = self_interval.intersect(&other_interval);
if i.is_empty() {
break 'segment;
}
intersection.union_in_place(&i);
} else {
return intersection;
}
}
}
intersection
}
#[must_use]
pub fn union(&self, other: &Self) -> Self {
let mut union = self.clone();
for interval in other.interval_iter() {
union.union_in_place(&interval);
}
union
}
#[must_use]
pub fn minus(&self, other: &Self) -> Self {
let mut minus = self.clone();
for interval in other.interval_iter() {
minus.minus_in_place(&interval);
}
minus
}
#[allow(clippy::missing_panics_doc)]
#[must_use]
pub fn enclose(&self) -> RawInterval<T> {
if self.0.is_empty() {
return RawInterval::Empty;
}
let mut tine_iter = self.0.iter();
if self.0.len() == 1 {
let tine = tine_iter
.next()
.expect("nonempty TineTree");
debug_assert!(tine.is_point_include());
let pt = tine
.as_ref()
.expect("point Tine value")
.clone();
return RawInterval::Point(pt);
}
let lb = tine_iter
.next()
.expect("first tine with len > 1")
.clone()
.into_inner();
let ub = tine_iter
.next_back()
.expect("last tine with len > 1")
.clone()
.into_inner();
RawInterval::new(lb, ub)
}
#[must_use]
pub fn closure(&self) -> RawInterval<T> {
self.enclose().closure()
}
pub fn intersect_in_place(&mut self, interval: &RawInterval<T>) {
use Bound::*;
use Tine::*;
if self.0.is_empty() || interval.is_full() {return};
if interval.is_empty() {
*self = Self::new();
return;
}
if let RawInterval::Point(pt) = interval {
if self.contains(pt) {
*self = Self::from_raw_interval(interval.clone());
} else {
*self = Self::new();
}
return;
}
match Tine::from_raw_interval(interval.clone()) {
Few::Zero => {
*self = Self::new();
},
Few::One(Point(Include(p))) => {
if self.contains(&p) {
*self = Self::from_raw_interval(RawInterval::Point(p));
} else {
*self = Self::new();
}
},
Few::Two(l, u) => {
self.intersect_proper_interval(l, u);
},
Few::One(_) => unreachable!("invalid Tine from interval"),
}
}
fn intersect_proper_interval(&mut self, l: Tine<T>, u: Tine<T>) {
let mut ts = self.interior_split_for_proper_interval(&l, &u);
let merged_l = if ts[2].is_some() {
ts[2].take().and_then(|lower| lower.intersect(&l))
} else {
Some(l)
};
let merged_u = if ts[3].is_some() {
ts[3].take().and_then(|upper| upper.intersect(&u))
} else {
Some(u)
};
debug_assert!(merged_l
.as_ref()
.map_or(true, Tine::is_lower_bound));
debug_assert!(merged_u
.as_ref()
.map_or(true, Tine::is_upper_bound));
let open_before = ts[0]
.as_ref()
.is_some_and(Tine::is_lower_bound);
let closed_after = ts[5]
.as_ref()
.is_some_and(Tine::is_upper_bound);
let in_l = ts[1]
.as_ref()
.is_some_and(Tine::is_upper_bound);
let in_r = ts[4]
.as_ref()
.is_some_and(Tine::is_lower_bound);
match (open_before, merged_l, in_l, in_r, merged_u, closed_after) {
(_, Some(l), true, true, Some(u), _ ) |
(_, Some(l), false, false, Some(u), _ ) => {
self.0.insert(l);
self.0.insert(u);
},
(true, Some(l), true, false, _, false) => {
self.0.insert(l);
},
(false, _, false, true, Some(u), true) => {
self.0.insert(u);
},
(false, _, false, false, _, false) => {
},
_ => unreachable!("invalid bounds for intersection interval"),
}
}
pub fn union_in_place(&mut self, interval: &RawInterval<T>) {
if interval.is_full() {
*self = Self::from_raw_interval(RawInterval::Full);
return;
}
match Tine::from_raw_interval(interval.clone()) {
Few::Zero => (),
Few::One(p) => self.union_point_interval(p),
Few::Two(l, u) => self.union_proper_interval(l, u),
}
}
#[allow(clippy::cognitive_complexity)]
fn union_point_interval(&mut self, p: Tine<T>) {
let mut ts = self.exterior_split_for_point_interval(&p);
let p = if ts[1].is_some() {
if let Some(merged) = ts[1]
.take()
.and_then(|pt| pt.union(&p))
{
merged
} else {
return;
}
} else {
p
};
let open_before = ts[0]
.as_ref()
.is_some_and(Tine::is_lower_bound);
let closed_after = ts[2]
.as_ref()
.is_some_and(Tine::is_upper_bound);
match (open_before, closed_after) {
(true, true) => {
},
(true, false) => {
debug_assert!(!p.is_lower_bound());
self.0.insert(p);
},
(false, true) => {
debug_assert!(!p.is_upper_bound());
self.0.insert(p);
},
(false, false) => {
self.0.insert(p);
},
}
}
fn union_proper_interval(&mut self, l: Tine<T>, u: Tine<T>) {
let mut ts = self.exterior_split_for_proper_interval(&l, &u);
let merged_l = if ts[1].is_some() {
ts[1].take().and_then(|lower| lower.union(&l))
} else {
Some(l)
};
let merged_u = if ts[2].is_some() {
ts[2].take().and_then(|upper| upper.union(&u))
} else {
Some(u)
};
debug_assert!(merged_l
.as_ref()
.map_or(true, Tine::is_lower_bound));
debug_assert!(merged_u
.as_ref()
.map_or(true, Tine::is_upper_bound));
let open_before = ts[0]
.as_ref()
.is_some_and(Tine::is_lower_bound);
let closed_after = ts[3]
.as_ref()
.is_some_and(Tine::is_upper_bound);
match (open_before, merged_l, merged_u, closed_after) {
(true, Some(l), Some(u), true) => {
if l.is_upper_bound() {self.0.insert(l);}
if u.is_lower_bound() {self.0.insert(u);}
},
(true, Some(l), Some(u), false) => {
if l.is_upper_bound() {self.0.insert(l);}
debug_assert!(!u.is_lower_bound());
self.0.insert(u);
},
(false, Some(l), Some(u), true) => {
debug_assert!(!l.is_upper_bound());
self.0.insert(l);
if u.is_lower_bound() {self.0.insert(u);}
},
(false, Some(l), Some(u), false) => {
debug_assert!(!l.is_upper_bound());
self.0.insert(l);
debug_assert!(!u.is_lower_bound());
self.0.insert(u);
},
(true, Some(l), None, true) => {
if l.is_point_exclude() {self.0.insert(l);}
},
(false, Some(l), None, true) => {
debug_assert!(!l.is_upper_bound());
self.0.insert(l);
},
(true, None, Some(u), true) => {
if u.is_point_exclude() {self.0.insert(u);}
},
(true, None, Some(u), false) => {
debug_assert!(!u.is_lower_bound());
self.0.insert(u);
},
(true, None, None, true) => {
},
_ => unreachable!("invalid bounds for union interval"),
}
}
pub fn minus_in_place(&mut self, interval: &RawInterval<T>) {
if self.0.is_empty() || interval.is_empty() {return};
if interval.is_full() {
*self = Self::new();
return;
}
match Tine::from_raw_interval(interval.clone()) {
Few::Zero => (),
Few::One(p) => self.minus_point_interval(p),
Few::Two(l, u) => self.minus_proper_interval(l, u),
}
}
fn minus_point_interval(&mut self, p: Tine<T>) {
let mut ts = self.exterior_split_for_point_interval(&p);
let p = if ts[1].is_some() {
if let Some(merged) = ts[1]
.take()
.and_then(|pt| pt.minus(&p))
{
merged
} else {
return;
}
} else {
p
};
let open_before = ts[0]
.as_ref()
.is_some_and(Tine::is_lower_bound);
let closed_after = ts[2]
.as_ref()
.is_some_and(Tine::is_upper_bound);
match (open_before, closed_after) {
(true, true) => {
self.0.insert(p.invert());
},
(true, false) => {
debug_assert!(p.is_upper_bound());
self.0.insert(p);
},
(false, true) => {
debug_assert!(p.is_lower_bound());
self.0.insert(p);
},
(false, false) => {
},
}
}
#[allow(clippy::items_after_statements)]
fn minus_proper_interval(&mut self, l: Tine<T>, u: Tine<T>) {
let mut ts = self.exterior_split_for_proper_interval(&l, &u);
let merged_l = if ts[1].is_some() {
ts[1].take().and_then(|lower| lower.minus(&l))
} else {
Some(l)
};
let merged_u = if ts[2].is_some() {
ts[2].take().and_then(|upper| upper.minus(&u))
} else {
Some(u)
};
let open_before = ts[0]
.as_ref()
.is_some_and(Tine::is_lower_bound);
let closed_after = ts[3]
.as_ref()
.is_some_and(Tine::is_upper_bound);
use Bound::*;
use Tine::*;
match (open_before, merged_l, merged_u, closed_after) {
(true, Some(l), Some(u), true) => {
self.0.insert(if l.is_upper_bound() {l} else {l.invert()});
self.0.insert(if u.is_lower_bound() {u} else {u.invert()});
},
(true, Some(l), upper, false) => {
self.0.insert(if l.is_upper_bound() {l} else {l.invert()});
if let Some(Point(Include(p))) = upper {
self.0.insert(Point(Include(p)));
}
},
(false, lower, Some(u), true) => {
self.0.insert(if u.is_lower_bound() {u} else {u.invert()});
if let Some(Point(Include(p))) = lower {
self.0.insert(Point(Include(p)));
}
},
(false, Some(l), Some(u), false) => {
if l.is_point_include() { self.0.insert(l); }
if u.is_point_include() { self.0.insert(u); }
},
(false, Some(l), None, false) => {
if l.is_point_include() { self.0.insert(l); }
},
(false, None, Some(u), false) => {
if u.is_point_include() { self.0.insert(u); }
},
(false, None, None, false) => {
},
_ => unreachable!("invalid bounds for minus interval"),
}
}
fn interior_split_for_proper_interval(
&mut self,
lower: &Tine<T>,
upper: &Tine<T>)
-> [Option<Tine<T>>; 6]
{
debug_assert!(lower < upper);
let mut res = [None, None, None, None, None, None];
res[2] = self.0.take(lower);
res[3] = self.0.take(upper);
let mut center = self.0.split_off(lower);
let right_side = center.split_off(upper);
{
let mut backward = self.0.iter();
res[0] = backward.next_back().cloned();
let mut forward = center.iter();
res[1] = forward.next().cloned();
}
{
let mut backward = center.iter().rev();
res[4] = backward.next().cloned();
let mut forward = right_side.iter();
res[5] = forward.next().cloned();
}
debug_assert_eq!(res[1].is_some(), res[4].is_some());
self.0 = center;
res
}
fn exterior_split_for_point_interval(&mut self, tine: &Tine<T>)
-> [Option<Tine<T>>; 3]
{
let mut res = [None, None, None];
res[1] = self.0.take(tine);
let mut right_side = self.0.split_off(tine);
res[0] = self.0.iter().next_back().cloned();
res[2] = right_side.iter().next().cloned();
self.0.append(&mut right_side);
res
}
fn exterior_split_for_proper_interval(
&mut self,
lower: &Tine<T>,
upper: &Tine<T>)
-> [Option<Tine<T>>; 4]
{
let mut res = [None, None, None, None];
res[1] = self.0.take(lower);
res[2] = self.0.take(upper);
let mut center = self.0.split_off(lower);
{
let mut backward = self.0.iter();
res[0] = backward.next_back().cloned();
}
let mut right_side = center.split_off(upper);
{
let mut forward = right_side.iter();
res[3] = forward.next().cloned();
}
self.0.append(&mut right_side);
res
}
#[must_use]
pub fn interval_iter(&self) -> Iter<'_, T> {
Iter {
tine_iter: self.0.iter(),
saved_lower: None,
saved_upper: None,
}
}
}
impl<T> Default for TineTree<T> where T: Ord + Clone {
fn default() -> Self {
Self::new()
}
}
impl<T> From<RawInterval<T>> for TineTree<T> where T: Ord + Clone {
fn from(interval: RawInterval<T>) -> Self {
Self::from_raw_interval(interval)
}
}
impl<T, I> From<I> for TineTree<T>
where
T: Ord + Clone,
I: Iterator<Item=RawInterval<T>>
{
fn from(iter: I) -> Self {
let mut tine_tree = Self::new();
for interval in iter {
tine_tree.union_in_place(&interval);
}
tine_tree
}
}
impl<T> FromIterator<RawInterval<T>> for TineTree<T>
where T: Ord + Clone
{
fn from_iter<I>(iter: I) -> Self
where I: IntoIterator<Item=RawInterval<T>>
{
let mut tine_tree = Self::new();
for interval in iter {
tine_tree.union_in_place(&interval);
}
tine_tree
}
}
impl<T> IntoIterator for TineTree<T>
where T: Ord + Clone
{
type Item = RawInterval<T>;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
inner: self.0.into_iter(),
saved_lower: None,
saved_upper: None,
}
}
}
#[derive(Debug)]
pub struct IntoIter<T> {
inner: btree_set::IntoIter<Tine<T>>,
saved_lower: Option<Tine<T>>,
saved_upper: Option<Tine<T>>,
}
impl<T> Iterator for IntoIter<T> where T: Ord + Clone {
type Item = RawInterval<T>;
fn next(&mut self) -> Option<Self::Item> {
use Bound::*;
use Tine::*;
self.saved_lower
.take()
.or_else(|| self.inner.next())
.map(|lower| {
if let Point(Include(p)) = lower {
RawInterval::Point(p)
} else {
debug_assert!(lower.is_lower_bound());
let upper = self.inner.next()
.or_else(|| self.saved_upper.take())
.expect("interval is not partial");
if upper.is_point_exclude() {
self.saved_lower = Some(upper.clone());
}
debug_assert!(upper.is_upper_bound());
let lower = lower.into_inner();
let upper = upper.into_inner();
RawInterval::new(lower, upper)
}
})
}
}
impl<T> DoubleEndedIterator for IntoIter<T>
where T: Ord + Clone
{
fn next_back(&mut self) -> Option<Self::Item> {
use Bound::*;
use Tine::*;
self.saved_upper
.take()
.or_else(|| self.inner.next_back())
.map(|upper| {
if let Point(Include(p)) = upper {
RawInterval::Point(p)
} else {
debug_assert!(upper.is_upper_bound());
let lower = self.inner.next_back()
.or_else(|| self.saved_lower.take())
.expect("interval is not partial");
if lower.is_point_exclude() {
self.saved_lower = Some(lower.clone());
}
debug_assert!(lower.is_lower_bound());
let upper = upper.into_inner();
let lower = lower.into_inner();
RawInterval::new(lower, upper)
}
})
}
}
#[derive(Debug)]
pub struct Iter<'t, T> {
#[allow(clippy::struct_field_names)]
tine_iter: btree_set::Iter<'t, Tine<T>>,
saved_lower: Option<Tine<T>>,
saved_upper: Option<Tine<T>>,
}
impl<'t, T> Iterator for Iter<'t, T>
where T: Ord + Clone
{
type Item = RawInterval<T>;
fn next(&mut self) -> Option<Self::Item> {
use Bound::*;
use Tine::*;
self.saved_lower
.take()
.or_else(|| self.tine_iter.next().cloned())
.map(|lower| {
if let Point(Include(p)) = lower {
RawInterval::Point(p)
} else {
debug_assert!(lower.is_lower_bound());
let upper = self.tine_iter.next().cloned()
.or_else(|| self.saved_upper.take())
.expect("interval is not partial");
if upper.is_point_exclude() {
self.saved_lower = Some(upper.clone());
}
debug_assert!(upper.is_upper_bound());
let lower = lower.into_inner();
let upper = upper.into_inner();
RawInterval::new(lower, upper)
}
})
}
}
impl<'t, T> DoubleEndedIterator for Iter<'t, T>
where T: Ord + Clone
{
fn next_back(&mut self) -> Option<Self::Item> {
use Bound::*;
use Tine::*;
self.saved_upper
.take()
.or_else(|| self.tine_iter.next_back().cloned())
.map(|upper| {
if let Point(Include(p)) = upper {
RawInterval::Point(p)
} else {
debug_assert!(upper.is_upper_bound());
let lower = self.tine_iter.next_back().cloned()
.or_else(|| self.saved_lower.take())
.expect("interval is not partial");
if lower.is_point_exclude() {
self.saved_lower = Some(lower.clone());
}
debug_assert!(lower.is_lower_bound());
let upper = upper.into_inner();
let lower = lower.into_inner();
RawInterval::new(lower, upper)
}
})
}
}