concision_utils/stats/
summary.rs1use crate::Root;
6use core::iter::{Product, Sum};
7use ndarray::{ArrayBase, Data, Dimension};
8use num::traits::{FromPrimitive, Num, NumOps, Pow};
9
10pub trait SummaryStatistics
13where
14    Self::Item: FromPrimitive,
15    Self::Output: NumOps<Self::Item, Self::Output>,
16{
17    type Item;
18    type Output;
19    fn len(&self) -> usize;
21    fn product(&self) -> Self::Output;
23    fn sum(&self) -> Self::Output;
25    fn std(&self) -> Self::Output;
27    fn var(&self) -> Self::Output;
29
30    fn elems(&self) -> Self::Item {
32        Self::Item::from_usize(self.len()).unwrap()
33    }
34    fn is_empty(&self) -> bool {
36        self.len() == 0
37    }
38    fn mean(&self) -> Self::Output {
40        self.sum() / self.elems()
41    }
42}
43
44impl<T, I> SummaryStatistics for &I
48where
49    I: Clone + ExactSizeIterator<Item = T>,
50    T: Copy + FromPrimitive + Num + Pow<i32, Output = T> + Product + Root<Output = T> + Sum,
51{
52    type Item = T;
53    type Output = T;
54
55    fn len(&self) -> usize {
56        ExactSizeIterator::len(*self)
57    }
58
59    fn product(&self) -> Self::Output {
60        (*self).clone().product()
61    }
62
63    fn sum(&self) -> Self::Output {
64        (*self).clone().sum()
65    }
66
67    fn std(&self) -> Self::Output {
68        let mean = self.mean();
69        let sum = (*self).clone().map(|x| (x - mean).pow(2)).sum::<T>();
70        (sum / self.elems()).sqrt()
71    }
72
73    fn var(&self) -> Self::Output {
74        let mean = self.mean();
75        let sum = (*self).clone().map(|x| (x - mean).pow(2)).sum::<T>();
76        sum / self.elems()
77    }
78}
79
80macro_rules! impl_summary {
81    ($($T:ty),* $(,)?) => {
82        $(
83            impl_summary!(@impl $T);
84        )*
85    };
86    (@impl $T:ty) => {
87
88        impl<T> SummaryStatistics for $T
89        where
90            T: Copy + FromPrimitive + Num + Pow<i32, Output = T> + Product + Root<Output = T> + Sum,
91        {
92            type Item = T;
93            type Output = T;
94
95            fn len(&self) -> usize {
96                self.len()
97            }
98
99            fn product(&self) -> Self::Output {
100                self.iter().copied().product::<T>()
101            }
102
103            fn sum(&self) -> Self::Output {
104                self.iter().copied().sum::<T>()
105            }
106
107            fn std(&self) -> Self::Output {
108                let mean = self.mean();
109                let sum = self.iter().copied().map(|x| (x - mean).pow(2)).sum::<T>();
110                (sum / self.elems()).sqrt()
111            }
112
113            fn var(&self) -> Self::Output {
114                let mean = self.mean();
115                let sum = self.iter().copied().map(|x| (x - mean).pow(2)).sum::<T>();
116                sum / self.elems()
117            }
118        }
119    };
120}
121
122impl_summary!([T]);
123
124#[cfg(feature = "alloc")]
125impl_summary!(alloc::vec::Vec<T>);
126
127impl<A, S, D> SummaryStatistics for ArrayBase<S, D>
128where
129    A: Copy + FromPrimitive + Num + Pow<i32, Output = A> + Product + Root<Output = A> + Sum,
130    D: Dimension,
131    S: Data<Elem = A>,
132    for<'a> &'a A: Product,
133{
134    type Item = A;
135    type Output = A;
136
137    fn len(&self) -> usize {
138        self.len()
139    }
140
141    fn product(&self) -> Self::Output {
142        self.iter().copied().product::<A>()
143    }
144
145    fn sum(&self) -> Self::Output {
146        self.iter().copied().sum::<A>()
147    }
148
149    fn std(&self) -> Self::Output {
150        let mean = self.mean().unwrap_or_else(A::zero);
151        let sum = self.iter().copied().map(|x| (x - mean).pow(2)).sum::<A>();
152        (sum / self.elems()).sqrt()
153    }
154
155    fn var(&self) -> Self::Output {
156        let mean = self.mean().unwrap_or_else(A::zero);
157        let sum = self.iter().copied().map(|x| (x - mean).pow(2)).sum::<A>();
158        sum / self.elems()
159    }
160}