proportion/src/proportion.rs

84 lines
1.8 KiB
Rust

#[derive(Copy, Clone, Debug)]
pub struct Proportion {
pub(crate) value: f64,
}
impl Proportion {
pub fn new<T: Into<f64>>(value: T) -> Self {
let mut new = Self {
value: value.into(),
};
new.clamp_to_bounds();
new
}
pub fn from_fraction<T: Into<f64>>(numerator: T, denominator: T) -> Self {
let denominator = denominator.into();
if denominator == 0.0 {
return Self::MAX;
}
let numerator = numerator.into();
Self::new(numerator / denominator)
}
pub fn value(&self) -> f64 {
self.value
}
pub fn set<T: Into<f64>>(&mut self, new_value: T) {
self.value = new_value.into();
self.clamp_to_bounds();
}
pub fn is_zero(&self) -> bool {
self.value.abs() < f64::EPSILON
}
pub fn is_one(&self) -> bool {
(self.value - 1.0).abs() < f64::EPSILON
}
fn clamp_to_bounds(&mut self) {
self.value = if self.value > 1.0 {
1.0
} else if self.value < 0.0 {
0.0
} else {
self.value
}
}
}
impl AsRef<f64> for Proportion {
fn as_ref(&self) -> &f64 {
&self.value
}
}
impl std::ops::Deref for Proportion {
type Target = f64;
fn deref(&self) -> &f64 {
&self.value
}
}
impl std::cmp::PartialEq for Proportion {
fn eq(&self, other: &Proportion) -> bool {
self.value == other.value
}
}
impl std::cmp::PartialOrd for Proportion {
fn partial_cmp(&self, other: &Proportion) -> Option<std::cmp::Ordering> {
self.value.partial_cmp(&other.value)
}
}
impl std::cmp::Eq for Proportion {}
impl std::cmp::Ord for Proportion {
fn cmp(&self, other: &Proportion) -> std::cmp::Ordering {
self.partial_cmp(&other).unwrap()
}
}