entrenar/train/tui/
buffer.rs1#[derive(Debug, Clone)]
9pub struct MetricsBuffer {
10 data: Vec<f32>,
11 capacity: usize,
12 write_idx: usize,
13 len: usize,
14}
15
16impl MetricsBuffer {
17 pub fn new(capacity: usize) -> Self {
19 Self { data: vec![0.0; capacity], capacity, write_idx: 0, len: 0 }
20 }
21
22 pub fn push(&mut self, value: f32) {
24 self.data[self.write_idx] = value;
25 self.write_idx = (self.write_idx + 1) % self.capacity;
26 if self.len < self.capacity {
27 self.len += 1;
28 }
29 }
30
31 pub fn len(&self) -> usize {
33 self.len
34 }
35
36 pub fn is_empty(&self) -> bool {
38 self.len == 0
39 }
40
41 pub fn capacity(&self) -> usize {
43 self.capacity
44 }
45
46 pub fn last_n(&self, n: usize) -> Vec<f32> {
48 let n = n.min(self.len);
49 if n == 0 {
50 return Vec::new();
51 }
52
53 let mut result = Vec::with_capacity(n);
54 let start_idx = if self.len == self.capacity {
55 (self.write_idx + self.capacity - n) % self.capacity
56 } else {
57 self.len.saturating_sub(n)
58 };
59
60 for i in 0..n {
61 let idx = (start_idx + i) % self.capacity;
62 result.push(self.data[idx]);
63 }
64 result
65 }
66
67 pub fn values(&self) -> Vec<f32> {
69 self.last_n(self.len)
70 }
71
72 pub fn last(&self) -> Option<f32> {
74 if self.len == 0 {
75 None
76 } else {
77 let idx = (self.write_idx + self.capacity - 1) % self.capacity;
78 Some(self.data[idx])
79 }
80 }
81
82 pub fn min(&self) -> Option<f32> {
84 if self.len == 0 {
85 return None;
86 }
87 self.values().into_iter().reduce(f32::min)
88 }
89
90 pub fn max(&self) -> Option<f32> {
92 if self.len == 0 {
93 return None;
94 }
95 self.values().into_iter().reduce(f32::max)
96 }
97
98 pub fn mean(&self) -> Option<f32> {
100 if self.len == 0 {
101 return None;
102 }
103 let sum: f32 = self.values().iter().sum();
104 Some(sum / self.len as f32)
105 }
106
107 pub fn clear(&mut self) {
109 self.write_idx = 0;
110 self.len = 0;
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_metrics_buffer_new() {
120 let buf = MetricsBuffer::new(10);
121 assert_eq!(buf.capacity(), 10);
122 assert_eq!(buf.len(), 0);
123 assert!(buf.is_empty());
124 }
125
126 #[test]
127 fn test_metrics_buffer_push() {
128 let mut buf = MetricsBuffer::new(5);
129 buf.push(1.0);
130 buf.push(2.0);
131 buf.push(3.0);
132
133 assert_eq!(buf.len(), 3);
134 assert_eq!(buf.values(), vec![1.0, 2.0, 3.0]);
135 }
136
137 #[test]
138 fn test_metrics_buffer_wraparound() {
139 let mut buf = MetricsBuffer::new(3);
140 buf.push(1.0);
141 buf.push(2.0);
142 buf.push(3.0);
143 buf.push(4.0); buf.push(5.0); assert_eq!(buf.len(), 3);
147 assert_eq!(buf.values(), vec![3.0, 4.0, 5.0]);
148 }
149
150 #[test]
151 fn test_metrics_buffer_last_n() {
152 let mut buf = MetricsBuffer::new(10);
153 for i in 0..10 {
154 buf.push(i as f32);
155 }
156
157 assert_eq!(buf.last_n(3), vec![7.0, 8.0, 9.0]);
158 assert_eq!(buf.last_n(1), vec![9.0]);
159 assert_eq!(buf.last_n(0), Vec::<f32>::new());
160 }
161
162 #[test]
163 fn test_metrics_buffer_last() {
164 let mut buf = MetricsBuffer::new(5);
165 assert_eq!(buf.last(), None);
166
167 buf.push(1.0);
168 assert_eq!(buf.last(), Some(1.0));
169
170 buf.push(2.0);
171 assert_eq!(buf.last(), Some(2.0));
172 }
173
174 #[test]
175 fn test_metrics_buffer_min_max_mean() {
176 let mut buf = MetricsBuffer::new(10);
177 assert_eq!(buf.min(), None);
178 assert_eq!(buf.max(), None);
179 assert_eq!(buf.mean(), None);
180
181 buf.push(1.0);
182 buf.push(5.0);
183 buf.push(3.0);
184
185 assert_eq!(buf.min(), Some(1.0));
186 assert_eq!(buf.max(), Some(5.0));
187 assert_eq!(buf.mean(), Some(3.0));
188 }
189
190 #[test]
191 fn test_metrics_buffer_clear() {
192 let mut buf = MetricsBuffer::new(5);
193 buf.push(1.0);
194 buf.push(2.0);
195 buf.clear();
196
197 assert!(buf.is_empty());
198 assert_eq!(buf.len(), 0);
199 }
200
201 #[test]
202 fn test_metrics_buffer_last_n_wraparound() {
203 let mut buf = MetricsBuffer::new(4);
204 for i in 0..6 {
205 buf.push(i as f32);
206 }
207 assert_eq!(buf.last_n(2), vec![4.0, 5.0]);
210 assert_eq!(buf.last_n(4), vec![2.0, 3.0, 4.0, 5.0]);
211 }
212
213 #[test]
214 fn test_metrics_buffer_last_n_more_than_len() {
215 let mut buf = MetricsBuffer::new(10);
216 buf.push(1.0);
217 buf.push(2.0);
218
219 assert_eq!(buf.last_n(5), vec![1.0, 2.0]);
220 }
221}