dsfb_database/grammar/envelope.rs
1//! Drift / slew envelope semantics.
2//!
3//! The DSFB-native interpretation of *drift* is the EMA-smoothed residual
4//! magnitude `s_k = ρ s_k + (1−ρ)|r_k|`; *slew* is the instantaneous
5//! residual magnitude `|r_k|`. An envelope is a deterministic threshold band
6//! over both: when `s_k > drift_threshold` we are in the drift phase; when
7//! additionally `|r_k| > slew_threshold` we are at a boundary breach.
8//!
9//! These are the same definitions used in the `dsfb-semiconductor` and
10//! `dsfb-oil-gas` companion crates; we restate them here for clarity rather
11//! than re-import to avoid a cross-crate coupling that would make
12//! `dsfb-database` harder to publish independently.
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum Envelope {
16 /// Below drift threshold; residual is within the noise envelope.
17 Stable,
18 /// EMA over drift threshold; persistent low-amplitude excursion.
19 Drift,
20 /// Slew over slew threshold; an instantaneous boundary breach.
21 Boundary,
22}
23
24pub fn classify(ema: f64, instant: f64, drift_threshold: f64, slew_threshold: f64) -> Envelope {
25 let abs_e = ema.abs();
26 let abs_i = instant.abs();
27 if abs_i >= slew_threshold {
28 Envelope::Boundary
29 } else if abs_e >= drift_threshold {
30 Envelope::Drift
31 } else {
32 Envelope::Stable
33 }
34}