use crate::Time;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct NumSet(Vec<(Time, Time)>);
impl NumSet {
#[inline(always)]
pub(super) fn empty() -> Self {
Self(Vec::new())
}
#[inline(always)]
fn _full() -> Self {
Self(vec![(0, Time::MAX)])
}
#[inline(always)]
pub(super) fn from_range(lower_bound: Time, upper_bound: Time) -> Self {
assert!(lower_bound <= upper_bound);
Self(vec![(lower_bound, upper_bound)])
}
#[inline(always)]
pub(super) fn contains(&self, t: Time) -> bool {
match self.0.binary_search_by_key(&t, |&(t, _)| t) {
Ok(_) => true,
Err(i) if i > 0 => self.0[i - 1].1 >= t,
_ => false,
}
}
#[inline(always)]
fn _contains_interval(&self, lower_bound: Time, upper_bound: Time) -> bool {
assert!(lower_bound <= upper_bound);
match self.0.binary_search_by_key(&lower_bound, |&(t, _)| t) {
Ok(i) => self.0[i].1 >= upper_bound,
Err(i) if i > 0 => self.0[i - 1].1 >= upper_bound,
_ => false,
}
}
#[inline(always)]
pub(super) fn contains_unbounded_interval(&self, lower_bound: Time) -> bool {
self.0
.last()
.is_some_and(|&(l, u)| l <= lower_bound && u == Time::MAX)
}
pub(super) fn add_interval(&mut self, lower_bound: Time, upper_bound: Time) {
assert!(lower_bound <= upper_bound);
let len = self.0.len();
match self
.0
.binary_search_by_key(&lower_bound.saturating_sub(1), |&(_, t)| t)
{
Ok(i) => {
let tail = self.0.split_off(i);
match tail.binary_search_by_key(&upper_bound.saturating_add(1), |&(t, _)| t) {
Ok(j) => {
self.0.push((tail[0].0, tail[j].1));
self.0.extend_from_slice(&tail[j + 1..]);
}
Err(j) => {
if j == 0 {
self.0.push((tail[0].0, upper_bound));
} else {
self.0.push((tail[0].0, upper_bound.max(tail[j - 1].1)));
}
self.0.extend_from_slice(&tail[j..]);
}
}
}
Err(i) => {
let tail = self.0.split_off(i);
match tail.binary_search_by_key(&upper_bound.saturating_add(1), |&(t, _)| t) {
Ok(j) => {
if i == len {
self.0.push((lower_bound, tail[j].1));
} else {
self.0.push((lower_bound.min(tail[i].0), tail[j].1));
}
self.0.extend_from_slice(&tail[j + 1..]);
}
Err(j) => {
if i == len {
if j == 0 {
self.0.push((lower_bound, upper_bound));
} else {
self.0.push((lower_bound, upper_bound.max(tail[j - 1].1)));
}
} else if j == 0 {
self.0.push((lower_bound.min(tail[0].0), upper_bound));
} else {
self.0
.push((lower_bound.min(tail[0].0), upper_bound.max(tail[j - 1].1)));
}
self.0.extend_from_slice(&tail[j..]);
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_interval_1() {
let mut set = NumSet::empty();
set.add_interval(0, 1);
assert_eq!(set, NumSet(vec![(0, 1)]));
let mut set = NumSet::empty();
set.add_interval(1, 1);
assert_eq!(set, NumSet(vec![(1, 1)]));
let mut set = NumSet::empty();
set.add_interval(1, Time::MAX);
assert_eq!(set, NumSet(vec![(1, Time::MAX)]));
}
#[test]
fn add_interval_2() {
let mut set = NumSet::_full();
set.add_interval(0, 1);
assert_eq!(set, NumSet::_full());
set.add_interval(1, 1);
assert_eq!(set, NumSet::_full());
set.add_interval(1, Time::MAX);
assert_eq!(set, NumSet::_full());
}
#[test]
fn add_interval_3() {
let mut set = NumSet::from_range(5, 10);
set.add_interval(0, 1);
assert_eq!(set, NumSet(vec![(0, 1), (5, 10)]));
let mut set = NumSet::from_range(5, 10);
set.add_interval(12, 13);
assert_eq!(set, NumSet(vec![(5, 10), (12, 13)]));
let mut set = NumSet::from_range(5, 10);
set.add_interval(7, 8);
assert_eq!(set, NumSet(vec![(5, 10)]));
let mut set = NumSet::from_range(5, 10);
set.add_interval(3, 12);
assert_eq!(set, NumSet(vec![(3, 12)]));
}
#[test]
fn add_interval_4() {
let mut set = NumSet::from_range(5, 10);
set.add_interval(0, 5);
assert_eq!(set, NumSet(vec![(0, 10)]));
let mut set = NumSet::from_range(5, 10);
set.add_interval(0, 4);
assert_eq!(set, NumSet(vec![(0, 10)]));
let mut set = NumSet::from_range(5, 10);
set.add_interval(10, 15);
assert_eq!(set, NumSet(vec![(5, 15)]));
let mut set = NumSet::from_range(5, 10);
set.add_interval(11, 15);
assert_eq!(set, NumSet(vec![(5, 15)]));
}
}