use core::{fmt::Debug, ops::Add};
pub trait Measure: Debug + PartialOrd + Add<Self, Output = Self> + Default + Clone {}
impl<M> Measure for M where M: Debug + PartialOrd + Add<M, Output = M> + Default + Clone {}
pub trait FloatMeasure: Measure + Copy {
fn zero() -> Self;
fn infinite() -> Self;
}
impl FloatMeasure for f32 {
fn zero() -> Self {
0.
}
fn infinite() -> Self {
1. / 0.
}
}
impl FloatMeasure for f64 {
fn zero() -> Self {
0.
}
fn infinite() -> Self {
1. / 0.
}
}
pub trait BoundedMeasure: Measure + std::ops::Sub<Self, Output = Self> {
fn min() -> Self;
fn max() -> Self;
fn overflowing_add(self, rhs: Self) -> (Self, bool);
}
macro_rules! impl_bounded_measure_integer(
( $( $t:ident ),* ) => {
$(
impl BoundedMeasure for $t {
fn min() -> Self {
std::$t::MIN
}
fn max() -> Self {
std::$t::MAX
}
fn overflowing_add(self, rhs: Self) -> (Self, bool) {
self.overflowing_add(rhs)
}
}
)*
};
);
impl_bounded_measure_integer!(
u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
);
macro_rules! impl_bounded_measure_float(
( $( $t:ident ),* ) => {
$(
impl BoundedMeasure for $t {
fn min() -> Self {
std::$t::MIN
}
fn max() -> Self {
std::$t::MAX
}
fn overflowing_add(self, rhs: Self) -> (Self, bool) {
let overflow = self > Self::default() && rhs > Self::default() && self > std::$t::MAX - rhs;
let underflow = !overflow && self < Self::default() && rhs < Self::default() && self < std::$t::MIN - rhs;
(self + rhs, overflow || underflow)
}
}
)*
};
);
impl_bounded_measure_float!(f32, f64);
pub trait UnitMeasure:
Measure
+ std::ops::Sub<Self, Output = Self>
+ std::ops::Mul<Self, Output = Self>
+ std::ops::Div<Self, Output = Self>
+ std::iter::Sum
{
fn zero() -> Self;
fn one() -> Self;
fn from_usize(nb: usize) -> Self;
fn default_tol() -> Self;
}
macro_rules! impl_unit_measure(
( $( $t:ident ),* )=> {
$(
impl UnitMeasure for $t {
fn zero() -> Self {
0 as $t
}
fn one() -> Self {
1 as $t
}
fn from_usize(nb: usize) -> Self {
nb as $t
}
fn default_tol() -> Self {
1e-6 as $t
}
}
)*
}
);
impl_unit_measure!(f32, f64);
pub trait PositiveMeasure: Measure + Copy {
fn zero() -> Self;
fn max() -> Self;
}
macro_rules! impl_positive_measure(
( $( $t:ident ),* )=> {
$(
impl PositiveMeasure for $t {
fn zero() -> Self {
0 as $t
}
fn max() -> Self {
std::$t::MAX
}
}
)*
}
);
impl_positive_measure!(u8, u16, u32, u64, u128, usize, f32, f64);