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 as f64 * 0.99;
53        let p99_pos_low = p99_pos as usize;
54        let p99_frac = p99_pos - p99_pos_low as f64;
55        let p99 = if p99_pos_low + 1 < n {
56            valids[p99_pos_low] * (1.0 - p99_frac) + valids[p99_pos_low + 1] * p99_frac
57        } else {
58            valids[p99_pos_low]
59        };
60
61        // Calculate variance
62        let variance = valids
63            .iter()
64            .map(|x| {
65                let diff = mean - x;
66                diff * diff
67            })
68            .sum::<f64>()
69            / n as f64;
70
71        let max = *valids
72            .iter()
73            .max_by(|a, b| a.partial_cmp(b).unwrap())
74            .unwrap_or(&f64::NAN);
75
76        Stats {
77            mean,
78            median,
79            variance,
80            max,
81            p99,
82            n,
83        }
84    }
85}