radix_tools/
decomposition.rs

1use core::ops::{Div, Mul, Sub};
2
3pub struct RadixDecomposer<T> {
4    r: T,
5    q: T,
6}
7
8impl<T> RadixDecomposer<T> {
9    pub fn new(radix: T, num: T) -> RadixDecomposer<T> {
10        RadixDecomposer { r: radix, q: num }
11    }
12}
13
14impl<T> Iterator for RadixDecomposer<T>
15where
16    T: Copy + Div<Output = T> + Mul<Output = T> + Sub<Output = T>,
17{
18    type Item = T;
19
20    #[inline]
21    fn next(&mut self) -> Option<Self::Item> {
22        let curr = self.q;
23        self.q = self.q / self.r;
24        Some(curr - self.r * self.q)
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31    use crate::powers::*;
32
33    #[test]
34    fn radix2_decomp() {
35        const RADIX: u32 = 2;
36        let digits = vec![1, 0, 0, 1];
37        let value = Powers::<u32>::new(1, RADIX)
38            .zip(digits.iter())
39            .map(|(b, d)| b * d)
40            .sum();
41        let mut decomp = RadixDecomposer::<u32>::new(RADIX, value);
42        for digit in digits {
43            assert_eq!(Some(digit), decomp.next());
44        }
45    }
46
47    #[test]
48    fn radix3_decomp() {
49        const RADIX: u32 = 3;
50        let digits = vec![1, RADIX - 1, 0, 1];
51        let value = Powers::<u32>::new(1, RADIX)
52            .zip(digits.iter())
53            .map(|(b, d)| b * d)
54            .sum();
55        let mut decomp = RadixDecomposer::<u32>::new(RADIX, value);
56        for digit in digits {
57            assert_eq!(Some(digit), decomp.next());
58        }
59    }
60
61    #[test]
62    fn radix5_decomp() {
63        const RADIX: u32 = 5;
64        let digits = vec![1, RADIX - 1, 0, 1];
65        let value = Powers::<u32>::new(1, RADIX)
66            .zip(digits.iter())
67            .map(|(b, d)| b * d)
68            .sum();
69        let mut decomp = RadixDecomposer::<u32>::new(RADIX, value);
70        for digit in digits {
71            assert_eq!(Some(digit), decomp.next());
72        }
73    }
74}