ndhistogram/value/
mean.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::{
    marker::PhantomData,
    ops::{AddAssign, Div, Mul},
};

use num_traits::{abs, Float, NumOps, One, Signed};

use crate::FillWith;

/// This ndhistogram bin value computes the mean of the data samples provided when
/// filling.
///
/// Mean has 3 type parameters:
/// - the type that is being averaged,
/// - the type of the output when calculating the mean and its uncertainty,
/// - the type that counts the number of fills.
///
/// This allows, for example, integers to be used when filling or counting,
/// but a floating point type to compute the mean.
/// In most cases, you will only need to specify the first type as
/// sensible defaults are set for the second two type parameters.
///
///
/// # Example
/// ```rust
/// use ndhistogram::{ndhistogram, Histogram, axis::Uniform, value::Mean};
///
/// # fn main() -> Result<(), ndhistogram::Error> {
/// // create a histogram and fill it with some values
/// let mut hist = ndhistogram!(Uniform::new(10, 0.0, 10.0)?; Mean<i32>);
/// hist.fill_with(&0.0, 1);
/// hist.fill_with(&0.0, 2);
/// hist.fill_with(&0.0, 3);
///
/// let mean = hist.value(&0.0);
/// assert_eq!(mean.unwrap().get(), 2.0); // should be the mean of [1,2,3]
/// Ok(()) }
/// ```
#[derive(Copy, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mean<T = f64, O = f64, C = u32> {
    sumw: T,
    sumw2: T,
    count: C,
    phantom_output_type: PhantomData<O>,
}

impl<C, T, O> Mean<T, O, C>
where
    O: From<T> + From<C> + NumOps + Signed + Copy,
    C: Copy,
    T: Copy,
{
    /// Factory method to create a Mean from a set of values.
    ///
    /// Usually this will not be used as a [Histogram](crate::Histogram) will
    /// be responsible for creating and filling values.
    pub fn new<I>(values: I) -> Self
    where
        I: IntoIterator<Item = T>,
        Self: FillWith<T> + Default,
    {
        let mut r = Self::default();
        values.into_iter().for_each(|it| r.fill_with(it));
        r
    }

    /// Get the current value of the mean.
    pub fn get(&self) -> O {
        self.mean()
    }

    /// Get the current value of the mean.
    pub fn mean(&self) -> <O as Div>::Output {
        O::from(self.sumw) / O::from(self.count)
    }

    /// Get the number of times the mean value has been filled.
    pub fn num_samples(&self) -> C {
        self.count
    }

    /// Compute the variance of the samples.
    pub fn variance_of_samples(&self) -> O {
        let mean = self.mean();
        let mean2 = mean * mean;
        let avgsum2 = O::from(self.sumw2) / O::from(self.count);
        abs(avgsum2 - mean2)
    }

    /// The square root of the variance of the samples.
    pub fn standard_deviation_of_samples(&self) -> O
    where
        O: Float,
    {
        self.variance_of_samples().sqrt()
    }

    /// The square of the standard error of the mean.
    pub fn variance_of_mean(&self) -> O {
        self.variance_of_samples() / O::from(self.count)
    }

    /// Compute the standard error of the mean.
    pub fn standard_error_of_mean(&self) -> O
    where
        O: Float,
    {
        self.variance_of_mean().sqrt()
    }
}

impl<T, C, O> FillWith<T> for Mean<T, O, C>
where
    T: Copy + AddAssign + Mul<Output = T>,
    C: AddAssign + One,
{
    #[inline]
    fn fill_with(&mut self, data: T) {
        self.sumw += data;
        self.sumw2 += data * data;
        self.count += C::one();
    }
}