radix_tools/
decomposition.rs1use 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}