use super::*; /// A value that is composed of a relative and an absolute part. #[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] pub struct Rel { /// The relative part. pub rel: Ratio, /// The absolute part. pub abs: T, } impl Rel { /// The zero relative. pub fn zero() -> Self { Self { rel: Ratio::zero(), abs: T::zero() } } /// A relative with a ratio of `100%` and no absolute part. pub fn one() -> Self { Self { rel: Ratio::one(), abs: T::zero() } } /// Create a new relative from its parts. pub fn new(rel: Ratio, abs: T) -> Self { Self { rel, abs } } /// Whether both parts are zero. pub fn is_zero(self) -> bool { self.rel.is_zero() && self.abs == T::zero() } /// Whether the relative part is one and the absolute part is zero. pub fn is_one(self) -> bool { self.rel.is_one() && self.abs == T::zero() } /// Evaluate this relative to the given `whole`. pub fn relative_to(self, whole: T) -> T { self.rel.of(whole) + self.abs } /// Map the absolute part with `f`. pub fn map(self, f: F) -> Rel where F: FnOnce(T) -> U, U: Numeric, { Rel { rel: self.rel, abs: f(self.abs) } } } impl Rel { /// Try to divide two relative lengths. pub fn try_div(self, other: Self) -> Option { if self.rel.is_zero() && other.rel.is_zero() { self.abs.try_div(other.abs) } else if self.abs.is_zero() && other.abs.is_zero() { Some(self.rel / other.rel) } else { None } } } impl Debug for Rel { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match (self.rel.is_zero(), self.abs.is_zero()) { (false, false) => write!(f, "{:?} + {:?}", self.rel, self.abs), (false, true) => self.rel.fmt(f), (true, _) => self.abs.fmt(f), } } } impl From for Rel { fn from(abs: T) -> Self { Self { rel: Ratio::zero(), abs } } } impl From for Rel { fn from(rel: Ratio) -> Self { Self { rel, abs: T::zero() } } } impl PartialOrd for Rel { fn partial_cmp(&self, other: &Self) -> Option { if self.rel.is_zero() && other.rel.is_zero() { self.abs.partial_cmp(&other.abs) } else if self.abs.is_zero() && other.abs.is_zero() { self.rel.partial_cmp(&other.rel) } else { None } } } impl Neg for Rel { type Output = Self; fn neg(self) -> Self { Self { rel: -self.rel, abs: -self.abs } } } impl Add for Rel { type Output = Self; fn add(self, other: Self) -> Self::Output { Self { rel: self.rel + other.rel, abs: self.abs + other.abs, } } } impl Sub for Rel { type Output = Self; fn sub(self, other: Self) -> Self::Output { self + -other } } impl Mul for Rel { type Output = Self; fn mul(self, other: f64) -> Self::Output { Self { rel: self.rel * other, abs: self.abs * other } } } impl Mul> for f64 { type Output = Rel; fn mul(self, other: Rel) -> Self::Output { other * self } } impl Div for Rel { type Output = Self; fn div(self, other: f64) -> Self::Output { Self { rel: self.rel / other, abs: self.abs / other } } } impl AddAssign for Rel { fn add_assign(&mut self, other: Self) { self.rel += other.rel; self.abs += other.abs; } } impl SubAssign for Rel { fn sub_assign(&mut self, other: Self) { self.rel -= other.rel; self.abs -= other.abs; } } impl> MulAssign for Rel { fn mul_assign(&mut self, other: f64) { self.rel *= other; self.abs *= other; } } impl> DivAssign for Rel { fn div_assign(&mut self, other: f64) { self.rel /= other; self.abs /= other; } } impl Add for Ratio { type Output = Rel; fn add(self, other: T) -> Self::Output { Rel::from(self) + Rel::from(other) } } impl Add for Rel { type Output = Self; fn add(self, other: T) -> Self::Output { self + Rel::from(other) } } impl Add for Rel { type Output = Self; fn add(self, other: Ratio) -> Self::Output { self + Rel::from(other) } }