flow-gate-core 0.1.0

Pure-Rust implementation of the ISAC Gating-ML 2.0 gate evaluation engine — transforms, gates, and event matrices
Documentation
use crate::error::FlowGateError;
use crate::traits::Transform;

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct LinearTransform {
    pub t: f64,
    pub a: f64,
    span: f64,
    inv_span: f64,
}

impl LinearTransform {
    pub fn new(t: f64, a: f64) -> Result<Self, FlowGateError> {
        if !t.is_finite() || t <= 0.0 {
            return Err(FlowGateError::InvalidTransformParam(
                "Linear parameter T must be finite and > 0".to_string(),
            ));
        }
        if !a.is_finite() {
            return Err(FlowGateError::InvalidTransformParam(
                "Linear parameter A must be finite".to_string(),
            ));
        }
        let span = t + a;
        if !span.is_finite() || span <= 0.0 {
            return Err(FlowGateError::InvalidTransformParam(
                "Linear span (T + A) must be finite and > 0".to_string(),
            ));
        }
        if span.is_subnormal() {
            return Err(FlowGateError::InvalidTransformParam(
                "Linear span (T + A) is subnormal".to_string(),
            ));
        }
        Ok(Self {
            t,
            a,
            span,
            inv_span: 1.0 / span,
        })
    }
}

impl Transform for LinearTransform {
    fn apply(&self, value: f64) -> f64 {
        if !value.is_finite() {
            return f64::NAN;
        }
        (value + self.a) * self.inv_span
    }

    fn invert(&self, scaled: f64) -> f64 {
        if !scaled.is_finite() {
            return f64::NAN;
        }
        let value = scaled * self.span - self.a;
        if value.is_finite() {
            value
        } else {
            f64::NAN
        }
    }

    fn transform_id(&self) -> &str {
        "lin"
    }
}