This commit is contained in:
chaos 2024-11-22 20:16:40 +00:00
parent 6148b1cddd
commit 22c388c09b
7 changed files with 410 additions and 377 deletions

View file

@ -1,5 +1,3 @@
use std::ops::{Add, Mul};
use super::Estimation;
#[derive(Default, PartialEq, Debug, Clone)]
@ -9,221 +7,5 @@ pub struct Dose {
pub estimation: Estimation,
}
impl Add for Dose {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
self + &rhs
}
}
impl Add for &Dose {
type Output = Dose;
fn add(self, rhs: Self) -> Self::Output {
self.clone() + rhs
}
}
impl Add<Dose> for &Dose {
type Output = Dose;
fn add(self, lhs: Dose) -> Self::Output {
lhs + self
}
}
impl Add<&Dose> for Dose {
type Output = Self;
fn add(self, rhs: &Self) -> Self::Output {
let contains_unknown = self.contains_unknown || rhs.contains_unknown;
let estimation = match self.estimation + &rhs.estimation {
Estimation::Precise => {
if contains_unknown {
Estimation::Estimate
} else {
Estimation::Precise
}
}
value => value,
};
Dose {
value: self.value + rhs.value,
contains_unknown,
estimation,
}
}
}
impl Mul for Dose {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self * &rhs
}
}
impl Mul for &Dose {
type Output = Dose;
fn mul(self, rhs: Self) -> Self::Output {
self.clone() * rhs
}
}
impl Mul<Dose> for &Dose {
type Output = Dose;
fn mul(self, lhs: Dose) -> Self::Output {
lhs * self
}
}
impl Mul<&Dose> for Dose {
type Output = Self;
fn mul(self, rhs: &Self) -> Self::Output {
let contains_unknown = self.contains_unknown || rhs.contains_unknown;
let estimation = match self.estimation * &rhs.estimation {
Estimation::Precise => {
if contains_unknown {
Estimation::Estimate
} else {
Estimation::Precise
}
}
value => value,
};
Dose {
value: self.value * rhs.value,
contains_unknown,
estimation,
}
}
}
#[cfg(test)]
mod tests {
use super::{Dose, Estimation};
#[test]
fn add() {
let lhs = Dose {
value: 10.0,
..Dose::default()
};
let rhs = Dose {
value: 10.0,
..Dose::default()
};
let result = Dose {
value: 20.0,
..Dose::default()
};
assert_eq!(lhs.clone() + rhs.clone(), result);
assert_eq!(lhs.clone() + &rhs.clone(), result);
assert_eq!(&lhs.clone() + rhs.clone(), result);
assert_eq!(&lhs.clone() + &rhs.clone(), result);
}
#[test]
fn add_with_estimate() {
assert_eq!(
Dose {
value: 10.0,
..Dose::default()
} + Dose {
value: 10.0,
estimation: Estimation::Estimate,
..Dose::default()
},
Dose {
value: 20.0,
estimation: Estimation::Estimate,
..Dose::default()
}
);
}
#[test]
fn add_with_unknown() {
assert_eq!(
Dose {
value: 10.0,
..Dose::default()
} + Dose {
value: 10.0,
contains_unknown: true,
..Dose::default()
},
Dose {
value: 20.0,
contains_unknown: true,
estimation: Estimation::Estimate
}
);
}
#[test]
fn mul() {
let lhs = Dose {
value: 10.0,
..Dose::default()
};
let rhs = Dose {
value: 10.0,
..Dose::default()
};
let result = Dose {
value: 100.0,
..Dose::default()
};
assert_eq!(lhs.clone() * rhs.clone(), result);
assert_eq!(lhs.clone() * &rhs.clone(), result);
assert_eq!(&lhs.clone() * rhs.clone(), result);
assert_eq!(&lhs.clone() * &rhs.clone(), result);
}
#[test]
fn mul_with_estimate() {
assert_eq!(
Dose {
value: 10.0,
..Dose::default()
} * Dose {
value: 10.0,
estimation: Estimation::Estimate,
..Dose::default()
},
Dose {
value: 100.0,
estimation: Estimation::Estimate,
..Dose::default()
}
);
}
#[test]
fn mul_with_unknown() {
assert_eq!(
Dose {
value: 10.0,
..Dose::default()
} * Dose {
value: 10.0,
contains_unknown: true,
..Dose::default()
},
Dose {
value: 100.0,
contains_unknown: true,
estimation: Estimation::Estimate
}
);
}
}
mod add;
mod multiply;

View file

@ -0,0 +1,115 @@
use super::{Dose, Estimation};
use std::ops::Add;
impl Add for Dose {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
self + &rhs
}
}
impl Add for &Dose {
type Output = Dose;
fn add(self, rhs: Self) -> Self::Output {
self.clone() + rhs
}
}
impl Add<Dose> for &Dose {
type Output = Dose;
fn add(self, lhs: Dose) -> Self::Output {
lhs + self
}
}
impl Add<&Dose> for Dose {
type Output = Self;
fn add(self, rhs: &Self) -> Self::Output {
let contains_unknown = self.contains_unknown || rhs.contains_unknown;
let estimation = match self.estimation + &rhs.estimation {
Estimation::Precise => {
if contains_unknown {
Estimation::Estimate
} else {
Estimation::Precise
}
}
value => value,
};
Dose {
value: self.value + rhs.value,
contains_unknown,
estimation,
}
}
}
#[cfg(test)]
mod tests {
use super::{Dose, Estimation};
#[test]
fn add() {
let lhs = Dose {
value: 10.0,
..Dose::default()
};
let rhs = Dose {
value: 10.0,
..Dose::default()
};
let result = Dose {
value: 20.0,
..Dose::default()
};
assert_eq!(lhs.clone() + rhs.clone(), result);
assert_eq!(lhs.clone() + &rhs.clone(), result);
assert_eq!(&lhs.clone() + rhs.clone(), result);
assert_eq!(&lhs.clone() + &rhs.clone(), result);
}
#[test]
fn add_with_estimate() {
assert_eq!(
Dose {
value: 10.0,
..Dose::default()
} + Dose {
value: 10.0,
estimation: Estimation::Estimate,
..Dose::default()
},
Dose {
value: 20.0,
estimation: Estimation::Estimate,
..Dose::default()
}
);
}
#[test]
fn add_with_unknown() {
assert_eq!(
Dose {
value: 10.0,
..Dose::default()
} + Dose {
value: 10.0,
contains_unknown: true,
..Dose::default()
},
Dose {
value: 20.0,
contains_unknown: true,
estimation: Estimation::Estimate
}
);
}
}

View file

@ -0,0 +1,115 @@
use super::{Dose, Estimation};
use std::ops::Mul;
impl Mul for Dose {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self * &rhs
}
}
impl Mul for &Dose {
type Output = Dose;
fn mul(self, rhs: Self) -> Self::Output {
self.clone() * rhs
}
}
impl Mul<Dose> for &Dose {
type Output = Dose;
fn mul(self, lhs: Dose) -> Self::Output {
lhs * self
}
}
impl Mul<&Dose> for Dose {
type Output = Self;
fn mul(self, rhs: &Self) -> Self::Output {
let contains_unknown = self.contains_unknown || rhs.contains_unknown;
let estimation = match self.estimation * &rhs.estimation {
Estimation::Precise => {
if contains_unknown {
Estimation::Estimate
} else {
Estimation::Precise
}
}
value => value,
};
Dose {
value: self.value * rhs.value,
contains_unknown,
estimation,
}
}
}
#[cfg(test)]
mod tests {
use super::{Dose, Estimation};
#[test]
fn mul() {
let lhs = Dose {
value: 10.0,
..Dose::default()
};
let rhs = Dose {
value: 10.0,
..Dose::default()
};
let result = Dose {
value: 100.0,
..Dose::default()
};
assert_eq!(lhs.clone() * rhs.clone(), result);
assert_eq!(lhs.clone() * &rhs.clone(), result);
assert_eq!(&lhs.clone() * rhs.clone(), result);
assert_eq!(&lhs.clone() * &rhs.clone(), result);
}
#[test]
fn mul_with_estimate() {
assert_eq!(
Dose {
value: 10.0,
..Dose::default()
} * Dose {
value: 10.0,
estimation: Estimation::Estimate,
..Dose::default()
},
Dose {
value: 100.0,
estimation: Estimation::Estimate,
..Dose::default()
}
);
}
#[test]
fn mul_with_unknown() {
assert_eq!(
Dose {
value: 10.0,
..Dose::default()
} * Dose {
value: 10.0,
contains_unknown: true,
..Dose::default()
},
Dose {
value: 100.0,
contains_unknown: true,
estimation: Estimation::Estimate
}
);
}
}

View file

@ -1,4 +1,3 @@
use std::ops::{Add, Mul};
#[derive(PartialEq, Debug, Copy, Clone, Default)]
pub enum Estimation {
@ -14,159 +13,6 @@ pub struct StandardDeviation {
pub deviation: f64,
}
impl Estimation {
pub fn is_precise(&self) -> bool {
matches!(self, Estimation::Precise)
}
pub fn is_estimate(&self) -> bool {
!matches!(self, Estimation::Precise)
}
pub fn is_standard_deviation(&self) -> bool {
matches!(self, Estimation::StandardDeviation(_))
}
}
impl Add<&Estimation> for Estimation {
type Output = Self;
fn add(self, rhs: &Self) -> Self::Output {
match (self, rhs) {
(Estimation::StandardDeviation(lhs), Estimation::StandardDeviation(rhs)) => {
Estimation::StandardDeviation(StandardDeviation {
expectation: lhs.expectation + rhs.expectation,
deviation: lhs.deviation + rhs.deviation,
})
}
(Estimation::StandardDeviation(deviation), _) => {
Estimation::StandardDeviation(deviation)
}
(_, Estimation::StandardDeviation(deviation)) => {
Estimation::StandardDeviation(*deviation)
}
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
}
}
}
impl Mul<&Estimation> for Estimation {
type Output = Self;
fn mul(self, rhs: &Self) -> Self::Output {
match (self, rhs) {
(Estimation::StandardDeviation(lhs), Estimation::StandardDeviation(rhs)) => {
let lhs_sum = lhs.deviation.powi(2) + lhs.expectation.powi(2);
let rhs_sum = rhs.deviation.powi(2) + rhs.expectation.powi(2);
let expectations = lhs.expectation.powi(2) * rhs.expectation.powi(2);
let product_variance = (lhs_sum * rhs_sum) - expectations;
if product_variance > 0.0000001 {
let deviation = product_variance.sqrt();
let expectation = lhs.expectation * rhs.expectation;
Estimation::StandardDeviation(StandardDeviation {
expectation,
deviation: deviation.round(),
})
} else {
Estimation::Estimate
}
}
(Estimation::StandardDeviation(deviation), _) => {
Estimation::StandardDeviation(deviation)
}
(_, Estimation::StandardDeviation(deviation)) => {
Estimation::StandardDeviation(*deviation)
}
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
}
}
}
#[cfg(test)]
mod tests {
use super::{Estimation::*, StandardDeviation as Deviation};
#[test]
fn is() {
let deviation = StandardDeviation(Deviation::default());
assert!(Precise.is_precise());
assert!(!Precise.is_estimate());
assert!(!Precise.is_standard_deviation());
assert!(!Estimate.is_precise());
assert!(Estimate.is_estimate());
assert!(!Estimate.is_standard_deviation());
assert!(!deviation.is_precise());
assert!(deviation.is_estimate());
assert!(deviation.is_standard_deviation());
}
#[test]
fn add() {
let deviation = StandardDeviation(Deviation {
expectation: 10.0,
deviation: 10.0,
});
assert_eq!(Precise + &Precise, Precise);
assert_eq!(Precise + &Estimate, Estimate);
assert_eq!(Precise + &deviation, deviation);
assert_eq!(Estimate + &Precise, Estimate);
assert_eq!(Estimate + &Estimate, Estimate);
assert_eq!(Estimate + &deviation, deviation);
assert_eq!(deviation + &Precise, deviation);
assert_eq!(deviation + &Estimate, deviation);
assert_eq!(
deviation + &deviation,
StandardDeviation(Deviation {
expectation: 20.0,
deviation: 20.0,
})
);
}
#[test]
fn mul() {
let deviation = StandardDeviation(Deviation {
expectation: 10.0,
deviation: 10.0,
});
assert_eq!(Precise * &Precise, Precise);
assert_eq!(Precise * &Estimate, Estimate);
assert_eq!(Precise * &deviation, deviation);
assert_eq!(Estimate * &Precise, Estimate);
assert_eq!(Estimate * &Estimate, Estimate);
assert_eq!(Estimate * &deviation, deviation);
assert_eq!(deviation * &Precise, deviation);
assert_eq!(deviation * &Estimate, deviation);
assert_eq!(
deviation * &deviation,
StandardDeviation(Deviation {
expectation: 100.0,
deviation: 173.0,
})
);
assert_eq!(
StandardDeviation(Deviation {
expectation: 100.0,
deviation: 0.0,
}) * &StandardDeviation(Deviation {
expectation: 100.0,
deviation: 0.0,
}),
Estimate
)
}
}
mod add;
mod multiply;
mod is;

View file

@ -0,0 +1,57 @@
use std::ops::Add;
use super::{Estimation, StandardDeviation};
impl Add<&Estimation> for Estimation {
type Output = Self;
fn add(self, rhs: &Self) -> Self::Output {
match (self, rhs) {
(Estimation::StandardDeviation(lhs), Estimation::StandardDeviation(rhs)) => {
Estimation::StandardDeviation(StandardDeviation {
expectation: lhs.expectation + rhs.expectation,
deviation: lhs.deviation + rhs.deviation,
})
}
(Estimation::StandardDeviation(deviation), _) => {
Estimation::StandardDeviation(deviation)
}
(_, Estimation::StandardDeviation(deviation)) => {
Estimation::StandardDeviation(*deviation)
}
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
}
}
}
#[cfg(test)]
mod tests {
use super::{Estimation::*, StandardDeviation as Deviation};
#[test]
fn add() {
let deviation = StandardDeviation(Deviation {
expectation: 10.0,
deviation: 10.0,
});
assert_eq!(Precise + &Precise, Precise);
assert_eq!(Precise + &Estimate, Estimate);
assert_eq!(Precise + &deviation, deviation);
assert_eq!(Estimate + &Precise, Estimate);
assert_eq!(Estimate + &Estimate, Estimate);
assert_eq!(Estimate + &deviation, deviation);
assert_eq!(deviation + &Precise, deviation);
assert_eq!(deviation + &Estimate, deviation);
assert_eq!(
deviation + &deviation,
StandardDeviation(Deviation {
expectation: 20.0,
deviation: 20.0,
})
);
}
}

View file

@ -0,0 +1,36 @@
use super::Estimation;
impl Estimation {
pub fn is_precise(&self) -> bool {
matches!(self, Estimation::Precise)
}
pub fn is_estimate(&self) -> bool {
!matches!(self, Estimation::Precise)
}
pub fn is_standard_deviation(&self) -> bool {
matches!(self, Estimation::StandardDeviation(_))
}
}
#[cfg(test)]
mod tests {
use super::Estimation::*;
use crate::types::StandardDeviation as Deviation;
#[test]
fn is() {
let deviation = StandardDeviation(Deviation::default());
assert!(Precise.is_precise());
assert!(!Precise.is_estimate());
assert!(!Precise.is_standard_deviation());
assert!(!Estimate.is_precise());
assert!(Estimate.is_estimate());
assert!(!Estimate.is_standard_deviation());
assert!(!deviation.is_precise());
assert!(deviation.is_estimate());
assert!(deviation.is_standard_deviation());
}
}

View file

@ -0,0 +1,82 @@
use std::ops::Mul;
use super::{Estimation, StandardDeviation};
impl Mul<&Estimation> for Estimation {
type Output = Self;
fn mul(self, rhs: &Self) -> Self::Output {
match (self, rhs) {
(Estimation::StandardDeviation(lhs), Estimation::StandardDeviation(rhs)) => {
let lhs_sum = lhs.deviation.powi(2) + lhs.expectation.powi(2);
let rhs_sum = rhs.deviation.powi(2) + rhs.expectation.powi(2);
let expectations = lhs.expectation.powi(2) * rhs.expectation.powi(2);
let product_variance = (lhs_sum * rhs_sum) - expectations;
if product_variance > 0.0000001 {
let deviation = product_variance.sqrt();
let expectation = lhs.expectation * rhs.expectation;
Estimation::StandardDeviation(StandardDeviation {
expectation,
deviation: deviation.round(),
})
} else {
Estimation::Estimate
}
}
(Estimation::StandardDeviation(deviation), _) => {
Estimation::StandardDeviation(deviation)
}
(_, Estimation::StandardDeviation(deviation)) => {
Estimation::StandardDeviation(*deviation)
}
(Estimation::Estimate, _) | (_, Estimation::Estimate) => Estimation::Estimate,
(Estimation::Precise, Estimation::Precise) => Estimation::Precise,
}
}
}
#[cfg(test)]
mod tests {
use super::{Estimation::*, StandardDeviation as Deviation};
#[test]
fn multiply() {
let deviation = StandardDeviation(Deviation {
expectation: 10.0,
deviation: 10.0,
});
assert_eq!(Precise * &Precise, Precise);
assert_eq!(Precise * &Estimate, Estimate);
assert_eq!(Precise * &deviation, deviation);
assert_eq!(Estimate * &Precise, Estimate);
assert_eq!(Estimate * &Estimate, Estimate);
assert_eq!(Estimate * &deviation, deviation);
assert_eq!(deviation * &Precise, deviation);
assert_eq!(deviation * &Estimate, deviation);
assert_eq!(
deviation * &deviation,
StandardDeviation(Deviation {
expectation: 100.0,
deviation: 173.0,
})
);
assert_eq!(
StandardDeviation(Deviation {
expectation: 100.0,
deviation: 0.0,
}) * &StandardDeviation(Deviation {
expectation: 100.0,
deviation: 0.0,
}),
Estimate
)
}
}