use core::ops::Bound;
use crate::{Domain, GenericRange};
impl<T: Domain> GenericRange<T> {
#[must_use]
pub fn singleton(value: T) -> Self
where
T: Clone,
{
Self::new_with_bounds(Bound::Included(value.clone()), Bound::Included(value))
}
#[must_use]
pub fn is_singleton(&self) -> bool {
if self.is_empty() {
return false;
}
if <T as Domain>::DISCRETE {
match (&self.start, &self.end) {
(&Bound::Unbounded, _) | (_, &Bound::Unbounded) => false,
(&Bound::Included(ref x), &Bound::Excluded(ref y))
| (&Bound::Excluded(ref x), &Bound::Included(ref y)) => x < y && x.is_next_to(y),
(&Bound::Included(ref x), &Bound::Included(ref y)) => x == y,
(&Bound::Excluded(ref x), &Bound::Excluded(ref y)) => x.shares_neighbour_with(y),
}
} else {
match (&self.start, &self.end) {
(&Bound::Included(ref x), &Bound::Included(ref y)) => x == y,
_ => false,
}
}
}
}
impl<T: Domain + Clone> From<T> for GenericRange<T> {
#[must_use]
fn from(val: T) -> Self {
Self::singleton(val)
}
}
#[cfg(test)]
mod tests_discrete {
use core::ops::Bound;
use crate::GenericRange;
#[test]
fn in_ex() {
assert!(!GenericRange::from(1..1).is_singleton());
assert!(GenericRange::from(1..2).is_singleton());
assert!(!GenericRange::from(1..42).is_singleton());
}
#[test]
fn in_in() {
assert!(GenericRange::from(1..=1).is_singleton());
assert!(!GenericRange::from(1..=2).is_singleton());
assert!(!GenericRange::from(1..=42).is_singleton());
}
#[test]
fn unbound() {
assert!(!GenericRange::from(1..).is_singleton());
assert!(!GenericRange::from(..2).is_singleton());
assert!(!GenericRange::from(..=2).is_singleton());
let generic: GenericRange<usize> = GenericRange::from(..);
assert!(!generic.is_singleton());
assert!(!GenericRange::from((Bound::Excluded(1), Bound::Unbounded)).is_singleton());
}
#[test]
fn ex_ex() {
assert!(!GenericRange::from((Bound::Excluded(1), Bound::Excluded(1))).is_singleton());
assert!(!GenericRange::from((Bound::Excluded(1), Bound::Excluded(2))).is_singleton());
assert!(!GenericRange::from((Bound::Excluded(1), Bound::Excluded(42))).is_singleton());
}
#[test]
fn ex_in() {
assert!(!GenericRange::from((Bound::Excluded(1), Bound::Included(1))).is_singleton());
assert!(GenericRange::from((Bound::Excluded(1), Bound::Included(2))).is_singleton());
assert!(!GenericRange::from((Bound::Excluded(1), Bound::Included(42))).is_singleton());
}
}
#[cfg(all(test, feature = "noisy_float"))]
mod tests_continuous {
use core::ops::Bound;
use noisy_float::types::N64;
use crate::GenericRange;
#[test]
fn in_ex() {
let n64_1 = N64::new(1.);
let n64_2 = N64::new(2.);
let n64_42 = N64::new(42.);
assert!(!GenericRange::from(n64_1..n64_1).is_singleton());
assert!(!GenericRange::from(n64_1..n64_2).is_singleton());
assert!(!GenericRange::from(n64_1..n64_42).is_singleton());
}
#[test]
fn in_in() {
let n64_1 = N64::new(1.);
let n64_2 = N64::new(2.);
let n64_42 = N64::new(42.);
assert!(GenericRange::from(n64_1..=n64_1).is_singleton());
assert!(!GenericRange::from(n64_1..=n64_2).is_singleton());
assert!(!GenericRange::from(n64_1..=n64_42).is_singleton());
}
#[test]
fn unbound() {
let n64_1 = N64::new(1.);
let n64_2 = N64::new(2.);
assert!(!GenericRange::from(n64_1..).is_singleton());
assert!(!GenericRange::from(..n64_2).is_singleton());
assert!(!GenericRange::from(..=n64_2).is_singleton());
let generic: GenericRange<N64> = GenericRange::from(..);
assert!(!generic.is_singleton());
assert!(!GenericRange::from((Bound::Excluded(n64_1), Bound::Unbounded)).is_singleton());
}
#[test]
fn ex_ex() {
let n64_1 = N64::new(1.);
let n64_2 = N64::new(2.);
let n64_42 = N64::new(42.);
assert!(!GenericRange::from((Bound::Excluded(n64_1), Bound::Excluded(n64_1))).is_singleton());
assert!(!GenericRange::from((Bound::Excluded(n64_1), Bound::Excluded(n64_2))).is_singleton());
assert!(!GenericRange::from((Bound::Excluded(n64_1), Bound::Excluded(n64_42))).is_singleton());
}
#[test]
fn ex_in() {
let n64_1 = N64::new(1.);
let n64_2 = N64::new(2.);
let n64_42 = N64::new(42.);
assert!(!GenericRange::from((Bound::Excluded(n64_1), Bound::Included(n64_1))).is_singleton());
assert!(!GenericRange::from((Bound::Excluded(n64_1), Bound::Included(n64_2))).is_singleton());
assert!(!GenericRange::from((Bound::Excluded(n64_1), Bound::Included(n64_42))).is_singleton());
}
}