use crate::{Interval, bounds};
#[derive(Debug)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
pub enum PartitionError<B> {
IllFormedBounds(B),
}
impl<V: std::fmt::Debug + std::fmt::Display> std::fmt::Display for PartitionError<V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PartitionError::IllFormedBounds(bounds) => write!(
f, "The bounds {} are not well defined.", bounds
),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
pub struct SubInterval<V: PartialOrd> {
pub index: usize,
pub interval: Interval<bounds::Closed<V>, bounds::OpenOrClosed<V>>,
}
impl<V: PartialOrd + Clone> SubInterval<V> {
pub fn width(&self) -> V::Output
where
V: std::ops::Sub,
{
let right = match self.interval.right.clone() {
bounds::OpenOrClosed::Open(right) => right,
bounds::OpenOrClosed::Closed(right) => right,
};
right - self.interval.left.0.clone()
}
pub fn midpoint(&self) -> V
where
V: std::ops::Add<Output = V> + std::ops::Div<Output = V> + num_traits::One,
{
let two = V::one() + V::one();
let right = match self.interval.right.clone() {
bounds::OpenOrClosed::Open(right) => right,
bounds::OpenOrClosed::Closed(right) => right,
};
(self.interval.left.0.clone() + right) / two
}
}
pub trait Partition {
type Value: PartialOrd;
fn len(&self) -> usize;
fn index(&self, value: &Self::Value) -> Option<usize>;
fn subinterval(&self, k: usize) -> Option<SubInterval<Self::Value>>;
fn digitise(&self, value: &Self::Value) -> Option<SubInterval<Self::Value>> {
self.index(value).and_then(|k| self.subinterval(k))
}
}
mod declarative;
pub use self::declarative::Declarative;
mod uniform;
pub use self::uniform::Uniform;