ndhistogram/value/
mean.rs

1use std::{
2    marker::PhantomData,
3    ops::{AddAssign, Div, Mul},
4};
5
6use num_traits::{abs, Float, NumOps, One, Signed};
7
8use crate::FillWith;
9
10/// This ndhistogram bin value computes the mean of the data samples provided when
11/// filling.
12///
13/// Mean has 3 type parameters:
14/// - the type that is being averaged,
15/// - the type of the output when calculating the mean and its uncertainty,
16/// - the type that counts the number of fills.
17///
18/// This allows, for example, integers to be used when filling or counting,
19/// but a floating point type to compute the mean.
20/// In most cases, you will only need to specify the first type as
21/// sensible defaults are set for the second two type parameters.
22///
23///
24/// # Example
25/// ```rust
26/// use ndhistogram::{ndhistogram, Histogram, axis::Uniform, value::Mean};
27///
28/// # fn main() -> Result<(), ndhistogram::Error> {
29/// // create a histogram and fill it with some values
30/// let mut hist = ndhistogram!(Uniform::new(10, 0.0, 10.0)?; Mean<i32>);
31/// hist.fill_with(&0.0, 1);
32/// hist.fill_with(&0.0, 2);
33/// hist.fill_with(&0.0, 3);
34///
35/// let mean = hist.value(&0.0);
36/// assert_eq!(mean.unwrap().get(), 2.0); // should be the mean of [1,2,3]
37/// Ok(()) }
38/// ```
39#[derive(Copy, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
40#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
41pub struct Mean<T = f64, O = f64, C = u32> {
42    sumw: T,
43    sumw2: T,
44    count: C,
45    phantom_output_type: PhantomData<O>,
46}
47
48impl<C, T, O> Mean<T, O, C>
49where
50    O: From<T> + From<C> + NumOps + Signed + Copy,
51    C: Copy,
52    T: Copy,
53{
54    /// Factory method to create a Mean from a set of values.
55    ///
56    /// Usually this will not be used as a [Histogram](crate::Histogram) will
57    /// be responsible for creating and filling values.
58    pub fn new<I>(values: I) -> Self
59    where
60        I: IntoIterator<Item = T>,
61        Self: FillWith<T> + Default,
62    {
63        let mut r = Self::default();
64        values.into_iter().for_each(|it| r.fill_with(it));
65        r
66    }
67
68    /// Get the current value of the mean.
69    pub fn get(&self) -> O {
70        self.mean()
71    }
72
73    /// Get the current value of the mean.
74    pub fn mean(&self) -> <O as Div>::Output {
75        O::from(self.sumw) / O::from(self.count)
76    }
77
78    /// Get the number of times the mean value has been filled.
79    pub fn num_samples(&self) -> C {
80        self.count
81    }
82
83    /// Compute the variance of the samples.
84    pub fn variance_of_samples(&self) -> O {
85        let mean = self.mean();
86        let mean2 = mean * mean;
87        let avgsum2 = O::from(self.sumw2) / O::from(self.count);
88        abs(avgsum2 - mean2)
89    }
90
91    /// The square root of the variance of the samples.
92    pub fn standard_deviation_of_samples(&self) -> O
93    where
94        O: Float,
95    {
96        self.variance_of_samples().sqrt()
97    }
98
99    /// The square of the standard error of the mean.
100    pub fn variance_of_mean(&self) -> O {
101        self.variance_of_samples() / O::from(self.count)
102    }
103
104    /// Compute the standard error of the mean.
105    pub fn standard_error_of_mean(&self) -> O
106    where
107        O: Float,
108    {
109        self.variance_of_mean().sqrt()
110    }
111}
112
113impl<T, C, O> FillWith<T> for Mean<T, O, C>
114where
115    T: Copy + AddAssign + Mul<Output = T>,
116    C: AddAssign + One,
117{
118    #[inline]
119    fn fill_with(&mut self, data: T) {
120        self.sumw += data;
121        self.sumw2 += data * data;
122        self.count += C::one();
123    }
124}