flow_gate_core/transform/
logarithmic.rs1use 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}