allan_tools/
tau.rs

1use thiserror::Error;
2
3/// Lists all `TauAxis` known to the generator
4#[derive(Clone, Copy)]
5pub enum TauAxis {
6    Octave, // octave axis
7    Decade, // decade axis
8    All,    // full linear space
9}
10
11/// `TauAxis` related errors 
12#[derive(Error, Debug)]
13pub enum Error {
14    #[error("encountered non valid `tau` < 0 value")]
15    NegativeTauValue, 
16    #[error("encountered non valid `tau` == 0")]
17    NullTauValue, 
18    #[error("`tau` axis should only comprise increasing values")]
19    InvalidTauShape,
20}
21
22impl Default for TauAxis {
23    /// Builds a default `TauAxis` 
24    fn default() -> TauAxis {
25        TauAxis::Octave
26    }
27}
28
29/// Returns Ok() if given tau axis passes standard sanity checks
30pub fn tau_sanity_checks (taus: &Vec<f64>) -> Result<(), Error> {
31    for i in 0..taus.len() {
32        if taus[i] < 0.0_f64 {
33            return Err(Error::NegativeTauValue)
34        }
35
36        if taus[i] == 0.0_f64 {
37            return Err(Error::NullTauValue)
38        }
39
40        if i > 0 {
41            if taus[i] <= taus[i-1] {
42                return Err(Error::InvalidTauShape)
43            }
44        }
45    }
46    Ok(())
47}
48
49/// Generate log(base) `TauAxis`
50/// ranging from [tau_0: tau_m]
51fn log_n_tau_generator (tau_0: f64, tau_m: f64, base: f64) -> Vec<f64> {
52    let mut tau = tau_0; 
53    let mut ret: Vec<f64> = Vec::new();
54    while tau <= tau_m {
55        ret.push(tau);
56        tau *= base
57    }
58    ret
59}
60
61/// Generates `Log2` axis ranging from [tau_0: tau_m]
62fn log2_tau_generator (tau_0: f64, tau_m: f64) -> Vec<f64> { log_n_tau_generator(tau_0, tau_m, 2.0_f64) }
63/// Generates `Log10` axis ranging from [tau_0: tau_m]
64fn log10_tau_generator (tau_0: f64, tau_m: f64) -> Vec<f64> { log_n_tau_generator(tau_0, tau_m, 10.0_f64) }
65
66/// Crates `tau` axis [`tau_0`: `tau_m`]    
67/// `tau_0` is samling rate is standard use and adev calculations,   
68/// `tau_m` < 2^32 for TauAxis::All
69pub fn tau_generator (axis: TauAxis, tau_0: f64, tau_m: f64) -> Vec<f64> {
70    match axis {
71        TauAxis::Octave => log2_tau_generator(tau_0, tau_m),
72        TauAxis::Decade => log10_tau_generator(tau_0, tau_m),
73        TauAxis::All    => (tau_0 as u32..tau_m as u32)
74                        .map(f64::from)
75                            .collect(),
76    }
77}
78
79#[cfg(test)]
80    mod tests {
81    use super::*;
82
83    #[test]
84    /// Tests `Tau` generator
85    fn test_tau_generator() {
86        // Octave axis
87        let taus = tau_generator(TauAxis::Octave, 1.0_f64, 2.0_f64.powf(16.0));
88        for i in 0..taus.len() {
89            assert_eq!(taus[i], 2.0_f64.powf(i as f64))
90        }
91        // Decade axis
92        let taus = tau_generator(TauAxis::Decade, 1.0_f64, 10.0_f64.powf(16.0));
93        for i in 0..taus.len() {
94            assert_eq!(taus[i], 10.0_f64.powf(i as f64))
95        }
96        // Full axis
97        let taus = tau_generator(TauAxis::All, 1.0_f64, 1_000_000.0_f64);
98        for i in 0..taus.len() {
99            assert_eq!(taus[i], i as f64 +1.0)
100        }
101    }
102}