simple_sum_average/
lib.rs1use core::ops::{Add, AddAssign};
2
3#[derive(Debug, Default)]
4pub struct SimpleSumAverage<T: Default, Count: Default = usize> {
5 sum: T,
6 count: Count
7}
8
9impl<T: Add<Output = T> + Default, Count: Add<u8, Output = Count> + Default> Add<T> for SimpleSumAverage<T, Count> {
10 type Output = Self;
11 fn add(self, rhs: T) -> Self {
12 Self {
13 sum: self.sum + rhs,
14 count: self.count + 1
15 }
16 }
17}
18
19impl<T: Add<Output = T> + Default + Copy, Count: Add<Count, Output = Count> + Default + Copy + From<u8>> AddAssign<T> for SimpleSumAverage<T, Count> {
20 fn add_assign(&mut self, rhs: T) {
21 self.sum = self.sum + rhs;
22 self.count = self.count + 1.into();
23 }
24}
25
26impl<T: Add<Output = T> + Default, Count: Add<Output = Count> + Default> Add<Self> for SimpleSumAverage<T, Count> {
27 type Output = Self;
28 fn add(self, rhs: Self) -> Self {
29 Self {
30 sum: self.sum + rhs.sum,
31 count: self.count + rhs.count
32 }
33 }
34}
35
36macro_rules! implement {
37 ($t:ty,$count:ty) => {
38 impl SimpleSumAverage<$t, $count> {
39 pub fn take_mean(&mut self) -> $t {
40 let result = match self.count {
41 0 => 0 as $t,
42 count => self.sum / (count as $t)
43 };
44 self.sum = 0 as $t;
45 self.count = 0 as $count;
46 result
47 }
48 }
49 }
50}
51
52implement!(i8, usize);
53implement!(i16, usize);
54implement!(i32, usize);
55implement!(i64, usize);
56implement!(i128, usize);
57implement!(u8, usize);
58implement!(u16, usize);
59implement!(u32, usize);
60implement!(u64, usize);
61implement!(u128, usize);
62
63implement!(i8, u8);
64implement!(i16, u8);
65implement!(i32, u8);
66implement!(i64, u8);
67implement!(i128, u8);
68implement!(u8, u8);
69implement!(u16, u8);
70implement!(u32, u8);
71implement!(u64, u8);
72implement!(u128, u8);
73
74macro_rules! implement_float {
75 ($t:ty,$count:ty) => {
76 impl SimpleSumAverage<$t, $count> {
77 pub fn take_mean(&mut self) -> $t {
78 let result = self.sum / (self.count as $t);
79 self.sum = 0 as $t;
80 self.count = 0 as $count;
81 result
82 }
83 }
84 }
85}
86
87implement_float!(f32, usize);
88implement_float!(f64, usize);
89implement_float!(f32, u8);
90implement_float!(f64, u8);
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_basic_f32() {
98 let mut accumulator = SimpleSumAverage::<f32>::default();
99 accumulator += 1.0;
100 accumulator += 1.0;
101 accumulator += 1.0;
102 accumulator += 1.0;
103 accumulator += 1.0;
104 assert_eq!(accumulator.sum, 5.0);
105 assert_eq!(accumulator.count, 5);
106 let average = accumulator.take_mean();
107 assert_eq!(average, 1.0);
108 assert_eq!(accumulator.sum, 0.0);
109 assert_eq!(accumulator.count, 0);
110 }
111
112 #[test]
113 fn test_basic_f32_u8() {
114 let mut accumulator = SimpleSumAverage::<f32, u8>::default();
115 accumulator += 1.0;
116 accumulator += 1.0;
117 accumulator += 1.0;
118 accumulator += 1.0;
119 accumulator += 1.0;
120 assert_eq!(accumulator.sum, 5.0);
121 assert_eq!(accumulator.count, 5);
122 let average = accumulator.take_mean();
123 assert_eq!(average, 1.0);
124 assert_eq!(accumulator.sum, 0.0);
125 assert_eq!(accumulator.count, 0);
126 }
127
128 #[test]
129 fn test_realworld_f32_u8() {
130 let mut accumulator = SimpleSumAverage::<f32, u8>::default();
131 accumulator += 82.3;
132 accumulator += 82.1;
133 accumulator += 82.9;
134 accumulator += 81.7;
135 accumulator += 83.1;
136 accumulator += 82.0;
137 accumulator += 81.8;
138 accumulator += 82.1;
139 accumulator += 82.2;
140 accumulator += 82.4;
141 let average = accumulator.take_mean();
142 assert_eq!(average, 82.26);
143 }
144
145 #[test]
146 fn test_f32_zero() {
147 let mut accumulator = SimpleSumAverage::<f32>::default();
148 accumulator += 10.0;
149 accumulator.count = 0;
150 let average = accumulator.take_mean();
151 assert_eq!(average, f32::INFINITY);
152 }
153
154 #[test]
155 fn test_u16_zero() {
156 let mut accumulator = SimpleSumAverage::<u16>::default();
157 let average = accumulator.take_mean();
158 assert_eq!(average, 0);
159 }
160}