Change backing type from f64 to generic T
This commit is contained in:
parent
57e084f53a
commit
8a6c67519a
|
@ -0,0 +1,30 @@
|
|||
use crate::Internal;
|
||||
use crate::Proportion;
|
||||
|
||||
pub trait Bounded {
|
||||
const MIN: Self;
|
||||
const MAX: Self;
|
||||
}
|
||||
|
||||
macro_rules! impl_bounded {
|
||||
($type:ty) => {
|
||||
impl Bounded for $type {
|
||||
const MIN: Self = <$type>::MIN;
|
||||
const MAX: Self = <$type>::MAX;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
impl_bounded!(u8);
|
||||
impl_bounded!(u16);
|
||||
impl_bounded!(u32);
|
||||
impl_bounded!(u64);
|
||||
impl_bounded!(u128);
|
||||
|
||||
impl<T: Internal> Proportion<T> {
|
||||
pub const MIN: Self = Proportion { value: T::MIN };
|
||||
pub const MAX: Self = Proportion { value: T::MAX };
|
||||
pub const ZERO: Self = Self::MIN;
|
||||
pub const ONE: Self = Self::MAX;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
use crate::Proportion;
|
||||
|
||||
impl Proportion {
|
||||
pub const MIN: Self = Proportion { value: 0.0 };
|
||||
pub const MAX: Self = Proportion { value: 1.0 };
|
||||
|
||||
pub const ZERO: Self = Self::MIN;
|
||||
pub const ONE: Self = Self::MAX;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
use crate::Proportion;
|
||||
|
||||
impl From<f64> for Proportion {
|
||||
fn from(value: f64) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for Proportion {
|
||||
fn from(value: f32) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
mod constants;
|
||||
mod conversions;
|
||||
mod bounds;
|
||||
mod operator_overloads;
|
||||
mod proportion;
|
||||
|
||||
pub use bounds::Bounded;
|
||||
pub use proportion::Proportion;
|
||||
|
||||
pub trait Internal: Bounded + PartialEq + PartialOrd + Eq + Ord + Copy + Clone + std::fmt::Debug {}
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
use crate::Proportion;
|
||||
|
||||
impl std::ops::Neg for Proportion {
|
||||
use crate::*;
|
||||
use std::ops::*;
|
||||
impl<T: Internal + Sub<Output = T>> Neg for Proportion<T> {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(mut self) -> Self::Output {
|
||||
self.value = 1.0 - self.value;
|
||||
self.value = T::MAX - self.value;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f64> for Proportion {
|
||||
type Output = f64;
|
||||
|
||||
fn mul(self, rhs: f64) -> f64 {
|
||||
impl<T: Internal + Mul<Output = T>> Mul<T> for Proportion<T> {
|
||||
type Output = T;
|
||||
fn mul(self, rhs: T) -> T {
|
||||
self.value * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<Proportion> for usize {
|
||||
type Output = usize;
|
||||
|
||||
fn mul(self, rhs: Proportion) -> usize {
|
||||
let lhs = self as f64;
|
||||
(lhs * rhs.value).round() as usize
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,83 +1,60 @@
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Proportion {
|
||||
pub(crate) value: f64,
|
||||
use crate::Internal;
|
||||
use std::{cmp::*, ops::*};
|
||||
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Proportion<T: Internal> {
|
||||
pub(crate) value: T,
|
||||
}
|
||||
|
||||
impl Proportion {
|
||||
pub fn new<T: Into<f64>>(value: T) -> Self {
|
||||
let mut new = Self {
|
||||
value: value.into(),
|
||||
};
|
||||
new.clamp_to_bounds();
|
||||
new
|
||||
impl<T: Internal> Proportion<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
Self { value }
|
||||
}
|
||||
|
||||
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 set(&mut self, new_value: T) {
|
||||
self.value = new_value;
|
||||
}
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.value.abs() < f64::EPSILON
|
||||
self.value == T::MIN
|
||||
}
|
||||
|
||||
pub fn is_one(&self) -> bool {
|
||||
(self.value - 1.0).abs() < f64::EPSILON
|
||||
self.value == T::MAX }
|
||||
|
||||
}
|
||||
|
||||
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 {
|
||||
impl<T: Internal> AsRef<T> for Proportion<T> {
|
||||
fn as_ref(&self) -> &T {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Proportion {
|
||||
type Target = f64;
|
||||
fn deref(&self) -> &f64 {
|
||||
impl<T: Internal> Deref for Proportion<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
&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> {
|
||||
impl<T: Internal> PartialOrd for Proportion<T> {
|
||||
fn partial_cmp(&self, other: &Proportion<T>) -> Option<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()
|
||||
impl<T: Internal> Ord for Proportion<T> {
|
||||
fn cmp(&self, other: &Proportion<T>) -> Ordering {
|
||||
self.value.cmp(&other.value)
|
||||
}
|
||||
}
|
||||
impl<T: Internal> PartialEq for Proportion<T> {
|
||||
fn eq(&self, other: &Proportion<T>) -> bool {
|
||||
self.value.eq(&other.value)
|
||||
}
|
||||
}
|
||||
impl<T: Internal> Eq for Proportion<T> {}
|
||||
|
||||
impl<T: Internal> std::fmt::Debug for Proportion<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
write!(f, "Proportion {{ {:?} / {:?} }}", self.value, Self::MAX)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue