ellip_dev_utils/
stats.rs

1/*
2 * Ellip is licensed under The 3-Clause BSD, see LICENSE.
3 * Copyright 2025 Sira Pornsiriprasert <code@psira.me>
4 */
5
6pub struct Stats {
7    pub mean: f64,
8    pub median: f64,
9    pub variance: f64,
10    pub max: f64,
11    pub p99: f64,
12    pub n: usize,
13}
14
15impl Stats {
16    pub fn nan() -> Self {
17        return Stats {
18            mean: f64::NAN,
19            median: f64::NAN,
20            variance: f64::NAN,
21            max: f64::NAN,
22            p99: f64::NAN,
23            n: 0,
24        };
25    }
26
27    pub fn from_vec(v: &Vec<f64>) -> Self {
28        let mut valids: Vec<f64> = v
29            .iter()
30            .filter(|x| !x.is_nan() && x.is_finite())
31            .cloned()
32            .collect();
33
34        if valids.is_empty() {
35            return Self::nan();
36        }
37
38        valids.sort_by(|a, b| a.partial_cmp(b).unwrap());
39
40        let sum: f64 = valids.iter().sum();
41        let n = valids.len();
42        let mean = sum / n as f64;
43
44        // Calculate median
45        let median = if n % 2 == 0 {
46            (valids[n / 2 - 1] + valids[n / 2]) / 2.0
47        } else {
48            valids[n / 2]
49        };
50
51        // Calculate P99 error
52        let p99_pos = (n - 1) as f64 * 0.99;
53        let p99_pos_low = p99_pos.floor() as usize;
54        let p99_frac = p99_pos - p99_pos_low as f64;
55
56        let p99 = if p99_pos_low + 1 < n {
57            valids[p99_pos_low] * (1.0 - p99_frac) + valids[p99_pos_low + 1] * p99_frac
58        } else {
59            valids[n - 1]
60        };
61
62        // Calculate variance
63        let variance = valids
64            .iter()
65            .map(|x| {
66                let diff = mean - x;
67                diff * diff
68            })
69            .sum::<f64>()
70            / n as f64;
71
72        let max = *valids
73            .iter()
74            .max_by(|a, b| a.partial_cmp(b).unwrap())
75            .unwrap_or(&f64::NAN);
76
77        Stats {
78            mean,
79            median,
80            variance,
81            max,
82            p99,
83            n,
84        }
85    }
86}