use crate::numeric::{Domain, LibZero};
use core::ops::Add;
use crate::{Interval, IntervalSet};
use super::Measurement;
pub trait Count {
type Output;
fn count(&self) -> Measurement<Self::Output>;
}
pub trait Countable: Domain {
type Output;
fn count_inclusive(left: &Self, right: &Self) -> Option<Self::Output>;
}
#[macro_export]
macro_rules! default_countable_impl {
($t_in_out:ty) => {
impl $crate::measure::Countable for $t_in_out {
type Output = $t_in_out;
fn count_inclusive(left: &Self, right: &Self) -> Option<Self::Output> {
if let Some(upper) = right.try_adjacent($crate::Side::Right) {
return Some(upper - left.clone());
}
if let Some(lower) = left.try_adjacent($crate::Side::Left) {
return Some(right.clone() - lower);
}
panic!("Countable type overflow; or Domain adjacent not implemented for Countable type.");
}
}
}
}
default_countable_impl!(u8);
default_countable_impl!(u16);
default_countable_impl!(u32);
default_countable_impl!(u64);
default_countable_impl!(u128);
default_countable_impl!(usize);
default_countable_impl!(i8);
default_countable_impl!(i16);
default_countable_impl!(i32);
default_countable_impl!(i64);
default_countable_impl!(i128);
default_countable_impl!(isize);
impl<T> Count for Interval<T>
where
T: Countable,
T::Output: LibZero,
{
type Output = T::Output;
fn count(&self) -> Measurement<Self::Output> {
self.0.count()
}
}
impl<T, Out> Count for IntervalSet<T>
where
T: Countable<Output = Out>,
Out: LibZero + Clone + Add<Out, Output = Out>,
{
type Output = Out;
fn count(&self) -> Measurement<Self::Output> {
self.intervals()
.iter()
.map(|subset| subset.count())
.fold(Measurement::Finite(Out::new_zero()), |accum, item| {
accum + item
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_count() {
}
}