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