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}