#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub enum Calibration {
#[default]
None,
Linear {
constant: f64,
slope: f64,
},
}
impl Calibration {
pub fn linear(constant: f64, slope: f64) -> Self {
Calibration::Linear { constant, slope }
}
pub fn apply(self, x: f64) -> f64 {
match self {
Calibration::None => x,
Calibration::Linear { constant, slope } => constant + slope * x,
}
}
pub fn slope(self) -> f64 {
match self {
Calibration::None => 1.0,
Calibration::Linear { slope, .. } => slope,
}
}
pub fn is_affine(self) -> bool {
true
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn none_is_identity_with_unit_slope() {
let c = Calibration::None;
assert_eq!(c.apply(0.0), 0.0);
assert_eq!(c.apply(7.5), 7.5);
assert_eq!(c.slope(), 1.0);
assert!(c.is_affine());
}
#[test]
fn linear_applies_intercept_and_slope() {
let c = Calibration::linear(2.0, 0.5);
assert_eq!(c.apply(0.0), 2.0); assert_eq!(c.apply(4.0), 4.0); assert_eq!(c.apply(-2.0), 1.0); assert_eq!(c.slope(), 0.5);
assert!(c.is_affine());
}
#[test]
fn default_is_no_calibration() {
assert_eq!(Calibration::default(), Calibration::None);
}
}