Skip to main content

flow_gate_core/transform/
logarithmic.rs

1use crate::error::FlowGateError;
2use crate::traits::Transform;
3
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub struct LogarithmicTransform {
6    pub t: f64,
7    pub m: f64,
8    log10_t: f64,
9    inv_m: f64,
10}
11
12impl LogarithmicTransform {
13    pub fn new(t: f64, m: f64) -> Result<Self, FlowGateError> {
14        if !t.is_finite() || t <= 0.0 {
15            return Err(FlowGateError::InvalidTransformParam(
16                "Logarithmic parameter T must be finite and > 0".to_string(),
17            ));
18        }
19        if !m.is_finite() || m <= 0.0 {
20            return Err(FlowGateError::InvalidTransformParam(
21                "Logarithmic parameter M must be finite and > 0".to_string(),
22            ));
23        }
24        Ok(Self {
25            t,
26            m,
27            log10_t: t.log10(),
28            inv_m: 1.0 / m,
29        })
30    }
31}
32
33impl Transform for LogarithmicTransform {
34    fn apply(&self, value: f64) -> f64 {
35        if !value.is_finite() || value <= 0.0 {
36            return f64::NAN;
37        }
38        (value.log10() - self.log10_t) * self.inv_m + 1.0
39    }
40
41    fn invert(&self, scaled: f64) -> f64 {
42        if !scaled.is_finite() {
43            return f64::NAN;
44        }
45        let value = self.t * 10.0_f64.powf((scaled - 1.0) * self.m);
46        if value.is_finite() {
47            value
48        } else {
49            f64::NAN
50        }
51    }
52
53    fn transform_id(&self) -> &str {
54        "log"
55    }
56}