irox_stats/
decay.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2023 IROX Contributors
3
4//!
5//! Exponential Half-lifes and Decays
6
7use core::f64::consts::LN_2;
8use core::time::Duration;
9#[allow(unused_imports)]
10use irox_tools::f64::FloatExt;
11
12///
13/// The half-life is defined as the duration required for a particular quantity to drop to 50% of the
14/// original value.
15#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
16pub struct HalfLife(Duration);
17
18///
19/// Average length of time that a particular item remains in the set.  (Tau)
20#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
21pub struct MeanLifetime(Duration);
22
23///
24/// Exponential Decay Rate Constant (1/Tau)
25#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
26pub struct DecayConstant(Duration);
27
28impl From<Duration> for HalfLife {
29    fn from(value: Duration) -> Self {
30        Self(value)
31    }
32}
33impl From<Duration> for DecayConstant {
34    fn from(value: Duration) -> Self {
35        Self(value)
36    }
37}
38impl From<Duration> for MeanLifetime {
39    fn from(value: Duration) -> Self {
40        Self(value)
41    }
42}
43
44impl From<MeanLifetime> for DecayConstant {
45    fn from(value: MeanLifetime) -> Self {
46        let var = 1.0 / value.0.as_secs_f64();
47        DecayConstant(Duration::from_secs_f64(var))
48    }
49}
50
51impl From<DecayConstant> for MeanLifetime {
52    fn from(value: DecayConstant) -> Self {
53        let var = 1.0 / value.0.as_secs_f64();
54        MeanLifetime(Duration::from_secs_f64(var))
55    }
56}
57
58impl From<DecayConstant> for HalfLife {
59    fn from(value: DecayConstant) -> Self {
60        let var = value.0.as_secs_f64();
61        HalfLife(Duration::from_secs_f64(LN_2 / var))
62    }
63}
64
65impl From<MeanLifetime> for HalfLife {
66    fn from(value: MeanLifetime) -> Self {
67        let var = value.0.as_secs_f64();
68        HalfLife(Duration::from_secs_f64(var * LN_2))
69    }
70}
71
72impl MeanLifetime {
73    pub fn decay_factor_at(&self, time: &Duration) -> f64 {
74        (-time.as_secs_f64() / self.0.as_secs_f64()).exp()
75    }
76}
77
78impl HalfLife {
79    pub fn decay_factor_at(&self, time: &Duration) -> f64 {
80        2.0_f64.powf(-time.as_secs_f64() / self.0.as_secs_f64())
81    }
82}