summaryrefslogtreecommitdiff
path: root/src/proportion.rs
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2023-12-24 21:07:11 +1300
committerBen Bridle <bridle.benjamin@gmail.com>2023-12-24 21:07:11 +1300
commit291bb4de2a2e5940fbebd8d400f35c1fc3b0c7a2 (patch)
tree57fc89b43b72779f8192fac890a983ad94c9f6d1 /src/proportion.rs
downloadproportion-main.zip
First commitHEADv1.0.0main
Diffstat (limited to 'src/proportion.rs')
-rw-r--r--src/proportion.rs107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/proportion.rs b/src/proportion.rs
new file mode 100644
index 0000000..aa8d1ae
--- /dev/null
+++ b/src/proportion.rs
@@ -0,0 +1,107 @@
+use crate::*;
+
+#[derive(Copy, Clone)]
+pub struct Proportion<T: Internal> {
+ pub(crate) value: T,
+}
+
+impl<I: Internal> Proportion<I> {
+ pub fn new(value: I) -> Self {
+ Self { value: value.clamp() }
+ }
+
+ pub const MIN: Self = Proportion {
+ value: <I as Internal>::MIN,
+ };
+ pub const MAX: Self = Proportion {
+ value: <I as Internal>::MAX,
+ };
+ pub const ZERO: Self = Self::MIN;
+ pub const ONE: Self = Self::MAX;
+
+ pub fn set(&mut self, new_value: I) {
+ self.value = new_value.clamp();
+ }
+
+ pub fn is_min(&self) -> bool {
+ self.value == I::MIN
+ }
+ pub fn is_max(&self) -> bool {
+ self.value == I::MAX
+ }
+
+ pub fn is_zero(&self) -> bool {
+ self.is_min()
+ }
+ pub fn is_one(&self) -> bool {
+ self.is_max()
+ }
+
+ pub fn as_u8(&self) -> u8 {
+ self.value.as_u8()
+ }
+ pub fn as_f32(&self) -> f32 {
+ self.value.as_f32()
+ }
+ pub fn as_f64(&self) -> f64 {
+ self.value.as_f64()
+ }
+
+ pub fn invert(&self) -> Self {
+ Self {
+ value: I::MAX - self.value,
+ }
+ }
+
+ pub fn value(&self) -> I {
+ self.value
+ }
+}
+
+macro_rules! impl_mul {
+ ($type:ty, $method:ident) => {
+ impl<I: Internal> std::ops::Mul<Proportion<I>> for $type {
+ type Output = $type;
+ fn mul(self, proportion: Proportion<I>) -> $type {
+ proportion.value.$method(self)
+ }
+ }
+ impl<I: Internal> std::ops::Mul<$type> for Proportion<I> {
+ type Output = $type;
+ fn mul(self, value: $type) -> $type {
+ self.value.$method(value)
+ }
+ }
+ impl<I: Internal> std::ops::Mul<&Proportion<I>> for $type {
+ type Output = $type;
+ fn mul(self, proportion: &Proportion<I>) -> $type {
+ proportion.value.$method(self)
+ }
+ }
+ impl<I: Internal> std::ops::Mul<$type> for &Proportion<I> {
+ type Output = $type;
+ fn mul(self, value: $type) -> $type {
+ self.value.$method(value)
+ }
+ }
+ };
+}
+
+impl_mul!(u8, mul_u8);
+impl_mul!(u16, mul_u16);
+impl_mul!(u32, mul_u32);
+impl_mul!(f32, mul_f32);
+impl_mul!(f64, mul_f64);
+
+use std::fmt::{Debug, Display, Formatter};
+
+impl<T: Internal> Debug for Proportion<T> {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
+ write!(f, "Proportion {{ {:.2} }}", self.as_f32())
+ }
+}
+impl<T: Internal> Display for Proportion<T> {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
+ write!(f, "{:.2}", self.as_f32())
+ }
+}