use num_traits::{Float, Signed};
#[derive(Debug, Default, Clone, Copy)]
pub struct Positive<T>(T);
impl<T> From<T> for Positive<T>
where
T: Signed,
{
fn from(value: T) -> Self {
Self(value.abs())
}
}
impl<T> Positive<T> {
pub fn into_inner(self) -> T {
self.0
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct Tolerance<T> {
pub relative: Positive<T>,
pub absolute: Positive<T>,
}
pub trait IsClose {
type Tolerance;
fn is_close(&self, rhs: &Self, tolerance: &Self::Tolerance) -> bool;
}
impl<T> IsClose for T
where
T: Float,
{
type Tolerance = Tolerance<T>;
fn is_close(&self, rhs: &Self, tolerance: &Self::Tolerance) -> bool {
(*self - *rhs).abs()
<= Self::max(
tolerance.relative.0 * Self::max(self.abs(), rhs.abs()),
tolerance.absolute.0,
)
}
}