use crate::bound::Bound;
use crate::normalize::Finite;
use crate::normalize::Normalize;
use crate::raw_interval::RawInterval;
use std::iter::FusedIterator;
use std::ops::Range;
use std::ops::RangeFrom;
use std::ops::RangeFull;
use std::ops::RangeTo;
use std::ops::RangeToInclusive;
use std::ops::Sub;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Interval<T>(pub (crate) RawInterval<T>);
impl<T> Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
#[inline]
pub fn new(left: Bound<T>, right: Bound<T>) -> Self {
Interval(RawInterval::new(left, right).normalized())
}
#[inline]
pub fn empty() -> Self {
Interval(RawInterval::Empty)
}
#[inline]
pub fn point(point: T) -> Self {
Interval(RawInterval::Point(point))
}
#[inline]
pub fn open(left: T, right: T) -> Self {
Interval(RawInterval::open(left, right).normalized())
}
#[inline]
pub fn left_open(left: T, right: T) -> Self {
Interval(RawInterval::left_open(left, right).normalized())
}
#[inline]
pub fn right_open(left: T, right: T) -> Self {
Interval(RawInterval::right_open(left, right).normalized())
}
#[inline]
pub fn closed(left: T, right: T) -> Self {
Interval(RawInterval::closed(left, right).normalized())
}
#[inline]
pub fn left_closed(left: T, right: T) -> Self {
Self::right_open(left, right)
}
#[inline]
pub fn right_closed(left: T, right: T) -> Self {
Self::left_open(left, right)
}
#[inline]
pub fn unbounded_from(point: T) -> Self {
Interval(RawInterval::From(point).normalized())
}
#[inline]
pub fn unbounded_to(point: T) -> Self {
Interval(RawInterval::To(point).normalized())
}
#[inline]
pub fn unbounded_up_from(point: T) -> Self {
Interval(RawInterval::UpFrom(point).normalized())
}
#[inline]
pub fn unbounded_up_to(point: T) -> Self {
Interval(RawInterval::UpTo(point).normalized())
}
#[inline]
pub fn full() -> Self {
Interval(RawInterval::Full.normalized())
}
pub fn into_non_empty(self) -> Option<Self> {
if self.is_empty() {
None
} else {
Some(self)
}
}
#[inline]
pub fn lower_bound(&self) -> Option<Bound<T>> {
self.0.lower_bound()
}
#[inline]
pub fn upper_bound(&self) -> Option<Bound<T>> {
self.0.upper_bound()
}
#[inline]
pub fn infimum(&self) -> Option<T> {
self.0.infimum()
}
#[inline]
pub fn supremum(&self) -> Option<T> {
self.0.supremum()
}
pub fn size(&self) -> Option<T> where T: Sub<Output=T> {
match (self.infimum(), self.supremum()) {
(Some(l), Some(u)) => Some(u - l),
_ => None,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
match self.0 {
RawInterval::Empty => true,
_ => false,
}
}
#[inline]
pub fn is_degenerate(&self) -> bool {
match self.0 {
RawInterval::Point(_) => true,
_ => false,
}
}
#[inline]
pub fn is_proper(&self) -> bool {
match self.0 {
RawInterval::Empty => false,
RawInterval::Point(_) => false,
_ => true,
}
}
#[inline]
pub fn is_open(&self) -> bool {
match self.0 {
RawInterval::Point(_) => false,
RawInterval::Closed(_, _) => false,
_ => true,
}
}
#[inline]
pub fn is_left_open(&self) -> bool {
match self.0 {
RawInterval::LeftOpen(_, _) => true,
RawInterval::UpTo(_) => true,
RawInterval::To(_) => true,
RawInterval::Full => true,
_ => false,
}
}
#[inline]
pub fn is_right_open(&self) -> bool {
match self.0 {
RawInterval::RightOpen(_, _) => true,
RawInterval::UpFrom(_) => true,
RawInterval::From(_) => true,
RawInterval::Full => true,
_ => false,
}
}
#[inline]
pub fn is_half_open(&self) -> bool {
match self.0 {
RawInterval::Empty => false,
RawInterval::Point(_) => false,
RawInterval::Closed(_, _) => false,
_ => true,
}
}
#[inline]
pub fn is_closed(&self) -> bool {
match self.0 {
RawInterval::Empty => true,
RawInterval::Point(_) => true,
RawInterval::Closed(_, _) => true,
RawInterval::Full => true,
_ => false,
}
}
#[inline]
pub fn is_left_closed(&self) -> bool {
match self.0 {
RawInterval::Point(_) => true,
RawInterval::RightOpen(_, _) => true,
RawInterval::Closed(_, _) => true,
RawInterval::From(_) => true,
_ => false,
}
}
#[inline]
pub fn is_right_closed(&self) -> bool {
match self.0 {
RawInterval::Point(_) => true,
RawInterval::LeftOpen(_, _) => true,
RawInterval::Closed(_, _) => true,
RawInterval::To(_) => true,
_ => false,
}
}
#[inline]
pub fn is_half_closed(&self) -> bool {
match self.0 {
RawInterval::LeftOpen(_, _) => true,
RawInterval::RightOpen(_, _) => true,
RawInterval::To(_) => true,
RawInterval::From(_) => true,
_ => false,
}
}
#[inline]
pub fn is_bounded(&self) -> bool {
match self.0 {
RawInterval::UpTo(_) => false,
RawInterval::UpFrom(_) => false,
RawInterval::To(_) => false,
RawInterval::From(_) => false,
RawInterval::Full => false,
_ => true,
}
}
#[inline]
pub fn is_left_bounded(&self) -> bool {
match self.0 {
RawInterval::UpTo(_) => false,
RawInterval::To(_) => false,
RawInterval::Full => false,
_ => true,
}
}
#[inline]
pub fn is_right_bounded(&self) -> bool {
match self.0 {
RawInterval::UpFrom(_) => false,
RawInterval::From(_) => false,
RawInterval::Full => false,
_ => true,
}
}
#[inline]
pub fn is_half_bounded(&self) -> bool {
match self.0 {
RawInterval::UpTo(_) => true,
RawInterval::UpFrom(_) => true,
RawInterval::To(_) => true,
RawInterval::From(_) => true,
_ => false,
}
}
#[inline]
pub fn contains(&self, point: &T) -> bool {
self.0.contains(point)
}
pub fn intersects(&self, other: &Self) -> bool {
self.0.intersects(&other.0)
}
pub fn adjacent(&self, other: &Self) -> bool {
self.0.adjacent(&other.0)
}
pub fn complement(&self) -> impl Iterator<Item=Self> {
self.0
.complement()
.map(Normalize::normalized)
.map(Interval)
}
pub fn intersect(&self, other: &Self) -> Self {
self.0.intersect(&other.0).normalized().into()
}
pub fn union(&self, other: &Self) -> impl Iterator<Item=Self> {
self.0
.union(&other.0)
.map(Normalize::normalized)
.map(Interval)
}
pub fn minus(&self, other: &Self) -> impl Iterator<Item=Self> {
self.0
.minus(&other.0)
.map(Normalize::normalized)
.map(Interval)
}
pub fn enclose(&self, other: &Self) -> Self {
self.0.enclose(&other.0).normalized().into()
}
pub fn closure(&self) -> Self {
self.0.closure().normalized().into()
}
}
impl<T> From<RawInterval<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(raw_interval: RawInterval<T>) -> Self {
Interval(raw_interval.normalized())
}
}
impl<T> From<T> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(point: T) -> Self {
Interval(RawInterval::Point(point).normalized())
}
}
impl<T> From<Range<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(r: Range<T>) -> Self {
Interval(RawInterval::right_open(r.start, r.end).normalized())
}
}
impl<T> From<RangeFrom<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(r: RangeFrom<T>) -> Self {
Interval(RawInterval::From(r.start).normalized())
}
}
impl<T> From<RangeTo<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(r: RangeTo<T>) -> Self {
Interval(RawInterval::UpTo(r.end).normalized())
}
}
impl<T> From<RangeToInclusive<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(r: RangeToInclusive<T>) -> Self {
Interval(RawInterval::To(r.end).normalized())
}
}
impl<T> From<RangeFull> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(_r: RangeFull) -> Self {
Interval(RawInterval::Full.normalized())
}
}
impl<T> Default for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn default() -> Self {
Interval::empty()
}
}
impl<T> Interval<T> where T: Ord + Clone + Finite {
pub fn iter(&self) -> Iter<T> {
Iter {
inner: self.clone(),
}
}
}
impl<T> IntoIterator for Interval<T>
where T: Ord + Clone + Finite,
{
type Item = T;
type IntoIter = Iter<T>;
fn into_iter(self) -> Self::IntoIter {
Iter { inner: self }
}
}
#[derive(Debug)]
pub struct Iter<T> where T: Ord + Clone {
inner: Interval<T>,
}
impl<T> Iterator for Iter<T>
where T: Ord + Clone + Finite
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match self.inner.lower_bound() {
Some(Bound::Include(lb)) => {
self.inner = self.inner
.minus(&lb.clone().into())
.next()
.unwrap_or(Interval::empty());
Some(lb)
},
None => None,
_ => unreachable!("iter for Finite interval with open lower bound"),
}
}
}
impl<T> DoubleEndedIterator for Iter<T>
where T: Ord + Clone + Finite
{
fn next_back(&mut self) -> Option<Self::Item> {
match self.inner.upper_bound() {
Some(Bound::Include(ub)) => {
self.inner = self.inner
.minus(&ub.clone().into())
.next()
.unwrap_or(Interval::empty());
Some(ub)
},
None => None,
_ => unreachable!("iter for Finite interval with open upper bound"),
}
}
}
impl<T> FusedIterator for Iter<T>
where
T: Ord + Clone + Finite
{}