1use crate::ring::RingIterator;
2use crate::Ring;
3use core::ops::{Add, Div, Mul, Sub};
4
5#[derive(Debug)]
7pub struct Range<T> {
8 pub min: T,
10 pub max: T,
12}
13
14impl<T: PartialOrd> Range<T> {
15 pub fn new(min: T, max: T) -> Option<Self> {
17 if min <= max {
18 Some(Range { min, max })
19 } else {
20 None
21 }
22 }
23}
24
25pub trait FindRange<T> {
27 fn range(&self) -> Option<Range<T>>;
29}
30
31impl<T: PartialOrd + Copy + Default, const N: usize> FindRange<T> for Ring<T, N> {
32 fn range(&self) -> Option<Range<T>> {
33 if self.is_empty() {
34 return None;
35 }
36 let mut iter = self.iter();
37 let first = iter.next().unwrap(); let mut min_max = Range {
39 min: first,
40 max: first,
41 };
42 for el in iter {
43 if min_max.min.gt(&el) {
44 min_max.min = el;
45 }
46 if min_max.max.lt(&el) {
47 min_max.max = el;
48 }
49 }
50
51 Some(min_max)
52 }
53}
54
55#[derive(Debug)]
56pub struct RescaleIterator<'a, T, const N: usize> {
57 current: Range<T>,
58 desired: Range<T>,
59 ring_iter: RingIterator<'a, T, N>,
60}
61
62impl<
63 T: Copy
64 + Default
65 + PartialOrd
66 + Sub<Output = T>
67 + Add<Output = T>
68 + Mul<Output = T>
69 + Div<Output = T>
70 + Into<f64>,
71 const N: usize,
72 > Ring<T, N>
73{
74 pub fn rescaled_iter(&self, current: Range<T>, desired: Range<T>) -> RescaleIterator<T, N> {
77 RescaleIterator {
78 current,
79 desired,
80 ring_iter: self.iter(),
81 }
82 }
83}
84
85impl<
86 T: Copy
87 + Default
88 + PartialOrd
89 + Sub<Output = T>
90 + Add<Output = T>
91 + Mul<Output = T>
92 + Div<Output = T>
93 + Into<f64>,
94 const N: usize,
95 > Iterator for RescaleIterator<'_, T, N>
96{
97 type Item = f64;
98 fn next(&mut self) -> Option<Self::Item> {
101 self.ring_iter.next().map(|el| {
102 let mut zero_one =
103 (el.into() - self.current.min.into()) / (self.current.delta().into());
104 if zero_one.is_nan() {
105 zero_one = 0.5;
106 }
107 zero_one * self.desired.delta().into() + self.desired.min.into()
108 })
109 }
110}
111
112impl<T: Sub<Output = T> + Copy> Range<T> {
113 pub fn delta(&self) -> T {
115 self.max - self.min
116 }
117}
118
119#[cfg(test)]
120mod test {
121 use super::{FindRange, Range, Ring};
122 const RING_SIZE: usize = 128;
123
124 #[test]
125 pub fn test_range() {
126 let mut circ: Ring<i32, RING_SIZE> = Ring::new();
127 assert!(circ.range().is_none());
128 circ.append(0);
129 assert_eq!(circ.range().unwrap().min, 0);
130 assert_eq!(circ.range().unwrap().max, 0);
131 circ.append(1);
132 assert_eq!(circ.range().unwrap().min, 0);
133 assert_eq!(circ.range().unwrap().max, 1);
134 circ.append(-1);
135 assert_eq!(circ.range().unwrap().min, -1);
136 assert_eq!(circ.range().unwrap().max, 1);
137 for _ in 0..RING_SIZE {
138 circ.append(0);
139 }
140 assert_eq!(circ.range().unwrap().min, 0);
141 assert_eq!(circ.range().unwrap().max, 0);
142 }
143
144 #[test]
145 pub fn test_rescale() {
146 let mut circ: Ring<i16, RING_SIZE> = Ring::new();
147 circ.append(100i16);
148 circ.append(200);
149 circ.append(300);
150 let current = circ.range().unwrap();
151 let desired = Range { min: 20, max: 30 };
152 let mut rescaled = circ.rescaled_iter(current, desired);
153 assert_eq!(rescaled.next().map(|el| el as i16), Some(20i16));
154 assert_eq!(rescaled.next().map(|el| el as i16), Some(25i16));
155 assert_eq!(rescaled.next().map(|el| el as i16), Some(30i16));
156 assert_eq!(rescaled.next(), None);
157 }
158}