rs_stats/prob/std_dev.rs
1//! # Standard Deviation
2//!
3//! Population and sample standard deviation. See [`crate::prob::variance`]
4//! for the population-vs-sample convention; this module just takes
5//! `sqrt(variance)`.
6
7use crate::error::StatsResult;
8use crate::prob::variance::{variance_population, variance_sample};
9use num_traits::ToPrimitive;
10use std::fmt::Debug;
11
12/// Population standard deviation (`sqrt(variance_population)`).
13///
14/// Same as `numpy.std(data)` / `numpy.std(data, ddof=0)`.
15///
16/// # Examples
17/// ```
18/// use rs_stats::prob::std_dev_population;
19/// let s = std_dev_population(&[1.0, 2.0, 3.0, 4.0, 5.0]).unwrap();
20/// assert!((s - 2.0_f64.sqrt()).abs() < 1e-12);
21/// ```
22#[inline]
23pub fn std_dev_population<T>(data: &[T]) -> StatsResult<f64>
24where
25 T: ToPrimitive + Debug,
26{
27 variance_population(data).map(f64::sqrt)
28}
29
30/// Sample standard deviation (`sqrt(variance_sample)`).
31///
32/// Same as `numpy.std(data, ddof=1)` / `pandas.Series.std()`.
33///
34/// # Examples
35/// ```
36/// use rs_stats::prob::std_dev_sample;
37/// let s = std_dev_sample(&[1.0, 2.0, 3.0, 4.0, 5.0]).unwrap();
38/// assert!((s - 2.5_f64.sqrt()).abs() < 1e-12);
39/// ```
40#[inline]
41pub fn std_dev_sample<T>(data: &[T]) -> StatsResult<f64>
42where
43 T: ToPrimitive + Debug,
44{
45 variance_sample(data).map(f64::sqrt)
46}
47
48/// Population standard deviation — alias for [`std_dev_population`].
49///
50/// Kept for v2.x source-compatibility. Use [`std_dev_sample`] when you
51/// need the Bessel-corrected estimator.
52#[inline]
53pub fn std_dev<T>(data: &[T]) -> StatsResult<f64>
54where
55 T: ToPrimitive + Debug,
56{
57 std_dev_population(data)
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn population_matches_alias() {
66 let data = [1.0, 2.5, 3.0, 4.5, 5.0];
67 assert_eq!(std_dev(&data).unwrap(), std_dev_population(&data).unwrap());
68 }
69
70 #[test]
71 fn population_known_value() {
72 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
73 assert!((std_dev_population(&data).unwrap() - 2.0_f64.sqrt()).abs() < 1e-12);
74 }
75
76 #[test]
77 fn sample_known_value() {
78 let data = [1.0, 2.0, 3.0, 4.0, 5.0];
79 assert!((std_dev_sample(&data).unwrap() - 2.5_f64.sqrt()).abs() < 1e-12);
80 }
81}