intervalsets 0.1.0-alpha.2

The intervalsets crate provides bounded and unbounded intervals implemented as sets with all the associated set operations.
Documentation
use crate::numeric::Domain;
use crate::ops::{Contains, Intersects};
use crate::util::commutative_predicate_impl;
use crate::Side;

use super::{BoundCase, Finite, HalfBounded};

impl<T: Domain> Intersects<Self> for Finite<T> {
    fn intersects(&self, rhs: &Self) -> bool {
        self.map_or::<bool>(false, |l1, r1| {
            rhs.map_or::<bool>(false, |l2, r2| {
                l1.contains(Side::Left, r2.value())
                    && l2.contains(Side::Left, r1.value())
                    && r1.contains(Side::Right, l1.value())
                    && r2.contains(Side::Right, l1.value())
            })
        })
    }
}

impl<T: Domain> Intersects<Finite<T>> for HalfBounded<T> {
    fn intersects(&self, rhs: &Finite<T>) -> bool {
        rhs.map_or(false, |left, right| {
            self.contains(left.value()) || self.contains(right.value())
        })
    }
}

impl<T: Domain> Intersects<Self> for HalfBounded<T> {
    fn intersects(&self, rhs: &Self) -> bool {
        self.contains(rhs.bound.value()) || rhs.contains(self.bound.value())
    }
}

impl<T: Domain> Intersects<Finite<T>> for BoundCase<T> {
    fn intersects(&self, rhs: &Finite<T>) -> bool {
        match self {
            Self::Finite(lhs) => lhs.intersects(rhs),
            Self::Half(lhs) => lhs.intersects(rhs),
            Self::Unbounded => *rhs != Finite::Empty,
        }
    }
}

impl<T: Domain> Intersects<HalfBounded<T>> for BoundCase<T> {
    fn intersects(&self, rhs: &HalfBounded<T>) -> bool {
        match self {
            Self::Finite(lhs) => rhs.intersects(lhs),
            Self::Half(lhs) => lhs.intersects(rhs),
            Self::Unbounded => true,
        }
    }
}

impl<T: Domain> Intersects<Self> for BoundCase<T> {
    fn intersects(&self, rhs: &Self) -> bool {
        match self {
            Self::Finite(lhs) => rhs.intersects(lhs),
            Self::Half(lhs) => rhs.intersects(lhs),
            Self::Unbounded => *rhs != Finite::Empty.into(),
        }
    }
}

commutative_predicate_impl!(Intersects, intersects, Finite<T>, HalfBounded<T>);
commutative_predicate_impl!(Intersects, intersects, Finite<T>, BoundCase<T>);
commutative_predicate_impl!(Intersects, intersects, HalfBounded<T>, BoundCase<T>);