1pub trait RLE: Sized {
2 unsafe fn encode_unchecked(
18 input: &[Self; 1024],
19 rle_vals: &mut [Self; 1024],
20 rle_idxs: &mut [u16; 1024],
21 ) -> usize;
22
23 unsafe fn decode_unchecked<I>(
34 rle_vals: &[Self],
35 rle_idxs: &[I; 1024],
36 output: &mut [Self; 1024],
37 ) where
38 I: Copy + Into<usize>;
39}
40
41impl<T: PartialEq + Copy> RLE for T {
42 #[inline(never)]
43 unsafe fn encode_unchecked(
44 input: &[Self; 1024],
45 rle_vals: &mut [Self; 1024],
46 rle_idxs: &mut [u16; 1024],
47 ) -> usize {
48 let mut pos_val = 0u16;
49 let mut rle_val_idx = 0usize;
50
51 let mut prev_val = unsafe { *input.get_unchecked(0) };
52 unsafe { *rle_vals.get_unchecked_mut(rle_val_idx) = prev_val };
53 rle_val_idx += 1;
54 unsafe { *rle_idxs.get_unchecked_mut(0) = pos_val };
55
56 for i in 1..1024 {
57 let cur_val = unsafe { *input.get_unchecked(i) };
58 if cur_val != prev_val {
59 debug_assert!(rle_val_idx < rle_vals.len());
62 unsafe { *rle_vals.get_unchecked_mut(rle_val_idx) = cur_val };
63 rle_val_idx += 1;
64 pos_val += 1;
65 prev_val = cur_val;
66 }
67 unsafe { *rle_idxs.get_unchecked_mut(i) = pos_val };
68 }
69
70 rle_val_idx
71 }
72
73 #[inline(never)]
74 unsafe fn decode_unchecked<I>(
75 rle_vals: &[Self],
76 rle_idxs: &[I; 1024],
77 output: &mut [Self; 1024],
78 ) where
79 I: Copy + Into<usize>,
80 {
81 for (idx, output) in rle_idxs.iter().zip(output.iter_mut()) {
82 debug_assert!((*idx).into() < rle_vals.len());
83 *output = unsafe { *rle_vals.get_unchecked((*idx).into()) };
85 }
86 }
87}
88
89#[cfg(test)]
90mod test {
91 use super::*;
92
93 #[test]
94 fn test_rle_encode_unique_count() {
95 let input: [u32; 1024] = core::array::from_fn(|i| (i / 100 + 1) as u32);
96 let mut rle_vals = [0u32; 1024];
97 let mut rle_idxs = [0u16; 1024];
98
99 let unique_count = unsafe { u32::encode_unchecked(&input, &mut rle_vals, &mut rle_idxs) };
101
102 assert_eq!(unique_count, 11);
103 }
104
105 #[test]
106 fn test_rle_encode_values() {
107 let input: [u32; 1024] = core::array::from_fn(|i| (i / 100 + 1) as u32);
108 let mut rle_vals = [0u32; 1024];
109 let mut rle_idxs = [0u16; 1024];
110
111 let unique_count = unsafe { u32::encode_unchecked(&input, &mut rle_vals, &mut rle_idxs) };
113
114 for i in 0..unique_count {
116 assert_eq!(rle_vals[i], i as u32 + 1);
117 }
118 }
119
120 #[test]
121 fn test_rle_encode_index_groups() {
122 let input: [u32; 1024] = core::array::from_fn(|i| (i / 100 + 1) as u32);
123 let mut rle_vals = [0u32; 1024];
124 let mut rle_idxs = [0u16; 1024];
125
126 unsafe { u32::encode_unchecked(&input, &mut rle_vals, &mut rle_idxs) };
128
129 for i in 0..100 {
130 assert_eq!(rle_idxs[i], 0);
131 }
132
133 for i in 100..200 {
134 assert_eq!(rle_idxs[i], 1);
135 }
136
137 for i in 1000..1024 {
138 assert_eq!(rle_idxs[i], 10);
139 }
140 }
141
142 #[test]
143 fn test_rle_encode_single_value() {
144 let input = [42u16; 1024];
145 let mut rle_vals = [0u16; 1024];
146 let mut rle_idxs = [0u16; 1024];
147
148 let unique_count = unsafe { u16::encode_unchecked(&input, &mut rle_vals, &mut rle_idxs) };
150
151 assert_eq!(unique_count, 1);
152 assert_eq!(rle_vals[0], 42);
153
154 for &idx in &rle_idxs {
155 assert_eq!(idx, 0);
156 }
157 }
158
159 #[test]
160 fn test_rle_encode_all_different() {
161 let input: [u8; 1024] = core::array::from_fn(|i| (i % 256) as u8);
162
163 let mut rle_vals = [0u8; 1024];
164 let mut rle_idxs = [0u16; 1024];
165
166 let unique_count = unsafe { u8::encode_unchecked(&input, &mut rle_vals, &mut rle_idxs) };
168
169 assert_eq!(unique_count, 1024);
172 }
173
174 #[test]
175 fn test_rle_round_trip() {
176 let input: [u8; 1024] = core::array::from_fn(|i| (i % 256) as u8);
177
178 let mut rle_vals = [0u8; 1024];
179 let mut rle_idxs = [0u16; 1024];
180 let unique_count = unsafe { u8::encode_unchecked(&input, &mut rle_vals, &mut rle_idxs) };
182
183 let mut decoded = [0u8; 1024];
184 unsafe { u8::decode_unchecked(&rle_vals[..unique_count], &rle_idxs, &mut decoded) };
186 assert_eq!(input, decoded);
187 }
188}