1use num_traits::{FromPrimitive, Num, ToPrimitive};
2
3#[derive(Debug, Default, PartialEq, Eq)]
19pub struct MipMap1D<T: Num + ToPrimitive + FromPrimitive> {
20 data: Vec<Vec<T>>,
21}
22
23impl<T: Num + ToPrimitive + FromPrimitive + Copy> MipMap1D<T> {
24 pub fn new(source: Vec<T>) -> Self {
25 let mut data = vec![source.clone()];
26 let mut current = source;
27
28 while current.len() > 1 {
29 let mipmap = Self::downsample(¤t);
30 current.clone_from(&mipmap);
31 data.push(mipmap);
32 }
33
34 Self { data }
35 }
36
37 pub fn num_levels(&self) -> usize {
40 self.data.len()
41 }
42
43 pub fn get_level(&self, level: usize) -> Option<&Vec<T>> {
47 if level >= self.num_levels() {
48 return None;
49 }
50
51 Some(&self.data[level])
52 }
53
54 fn downsample(source: &[T]) -> Vec<T> {
57 source
58 .chunks(2)
59 .map(|pair| match pair.len() {
60 1 => pair[0],
61 2 => T::from_f64((pair[0] + pair[1]).to_f64().unwrap() / 2.0).unwrap(),
62 _ => panic!("Unsound condition"),
63 })
64 .collect()
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn test_correct_downsample_ints() {
74 let data = vec![2, 4, 6, 8];
75 assert_eq!(MipMap1D::downsample(&data), vec![3, 7]);
76 }
77
78 #[test]
79 fn test_uneven_downsample() {
80 let data = vec![2, 4, 6, 8, 9];
81 assert_eq!(MipMap1D::downsample(&data), vec![3, 7, 9]);
82 }
83
84 #[test]
85 fn test_uneven_mipmap() {
86 let data = vec![2, 4, 6, 8, 9];
87 let target = vec![vec![2, 4, 6, 8, 9], vec![3, 7, 9], vec![5, 9], vec![7]];
88 let mipmap = MipMap1D::new(data);
89 assert_eq!(mipmap.data, target);
90 }
91
92 #[test]
93 fn test_mipmap_levels() {
94 let data = vec![2, 4, 6, 8, 9];
95 let target = [vec![2, 4, 6, 8, 9], vec![3, 7, 9], vec![5, 9], vec![7]];
96 let mipmap = MipMap1D::new(data);
97
98 assert_eq!(mipmap.num_levels(), target.len());
99 for (level, target_item) in target.iter().enumerate() {
100 let res = mipmap.get_level(level);
101 assert!(res.is_some());
102 let res = res.unwrap();
103
104 assert_eq!(*res, *target_item)
105 }
106 }
107
108 #[test]
109 fn test_fails_on_nonexistent_level() {
110 let data = vec![2, 4, 6, 8, 9];
111 let mipmap = MipMap1D::new(data);
112
113 assert_eq!(mipmap.get_level(mipmap.num_levels()), None);
114 }
115}