use crate::domain::quantitative::NORMALIZATION_DOMAIN;
use crate::domain::{Quantitative, QuantitativeLimit};
use crate::Valuation;
use std::fmt::{Debug, Display, Formatter};
use std::ops::{Add, Sub};
#[derive(Debug, PartialEq)]
pub struct Numeric<'domain, T: QuantitativeLimit> {
domain: &'domain Quantitative<T>,
value: T,
}
#[derive(Debug, PartialEq)]
pub enum NumericError<T: QuantitativeLimit> {
OutsideRange { value: T, inf: T, sup: T },
}
impl<T: QuantitativeLimit + Display> Display for NumericError<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
use NumericError::*;
match &self {
OutsideRange { value, inf, sup } => {
write!(
f,
"Value should be in the range [{}-{}], provided {}.",
inf, sup, value
)
}
}
}
}
impl<'domain, T: QuantitativeLimit> Valuation for Numeric<'domain, T> {}
impl<
'domain,
T: QuantitativeLimit + Copy + Debug + Display + Into<f64> + Add<Output = T> + Sub<Output = T>,
> Numeric<'domain, T>
{
pub fn new(domain: &'domain Quantitative<T>, value: T) -> Result<Self, NumericError<T>> {
use NumericError::*;
if value < domain.inf() || value > domain.sup() {
Err(OutsideRange {
value,
inf: domain.inf(),
sup: domain.sup(),
})
} else {
Ok(Self { domain, value })
}
}
pub fn value(&self) -> T {
self.value
}
pub fn domain(&self) -> &'domain Quantitative<T> {
self.domain
}
pub fn normalize(&self) -> Numeric<f64> {
Numeric::<f64> {
value: (self.value.into() - self.domain.inf().into())
/ (self.domain.sup().into() - self.domain.inf().into()),
domain: &NORMALIZATION_DOMAIN,
}
}
pub fn neg(&self) -> Self {
Self {
domain: self.domain,
value: self.domain.sup() + self.domain.inf() - self.value(),
}
}
}