u144/
lib.rs

1#![no_std]
2use uints::{u128_new, u16_new, Common, Lsb0Array, Number};
3
4#[derive(Debug, PartialEq, PartialOrd, Default)]
5pub struct U144 {
6    pub hi: u128,
7    pub lo: u16,
8}
9
10impl U144 {
11    pub const fn new(hi: u128, lo: u16) -> Self {
12        Self { hi, lo }
13    }
14}
15
16impl Common for U144 {
17    const ZERO: U144 = U144 { hi: 0, lo: 0 };
18    const ONE: U144 = U144 { hi: 0, lo: 1 };
19    const MAX: U144 = U144 {
20        hi: u128::MAX,
21        lo: u16::MAX,
22    };
23    const BITS: u8 = 144;
24    type Array = [u8; 18];
25    fn leading_zeros(&self) -> u8 {
26        match self.hi.leading_zeros() {
27            128 => self.lo.leading_zeros() as u8 + 128,
28            value => value as u8,
29        }
30    }
31    fn trailing_zeros(&self) -> u8 {
32        match self.lo.trailing_zeros() {
33            16 => self.hi.trailing_zeros() as u8 + 16,
34            value => value as u8,
35        }
36    }
37    fn count_ones(&self) -> u8 {
38        (self.hi.count_ones() + self.lo.count_ones()) as u8
39    }
40}
41
42impl Lsb0Array for U144 {
43    fn lsb0_array(&self) -> [u8; 18] {
44        let lo = u16_new(self.lo);
45        let hi = u128_new(self.hi);
46        [
47            lo[0],
48            lo[1],
49            hi[0][0][0][0],
50            hi[0][0][0][1],
51            hi[0][0][1][0],
52            hi[0][0][1][1],
53            hi[0][1][0][0],
54            hi[0][1][0][1],
55            hi[0][1][1][0],
56            hi[0][1][1][1],
57            hi[1][0][0][0],
58            hi[1][0][0][1],
59            hi[1][0][1][0],
60            hi[1][0][1][1],
61            hi[1][1][0][0],
62            hi[1][1][0][1],
63            hi[1][1][1][0],
64            hi[1][1][1][1],
65        ]
66    }
67}
68
69impl Number for U144 {
70    fn add(&mut self, value: u32) {
71        let lo = self.lo as u32 + value;
72        self.hi += (lo >> 16) as u128;
73        self.lo = lo as u16;
74    }
75    fn subtract(&mut self, value: u8) {
76        self.add(0x10000 - value as u32);
77        self.hi -= 1;
78    }
79    fn unset(&mut self, i: u8) {
80        if i < 16 {
81            self.lo &= !(1 << i);
82        } else {
83            self.hi &= !(1 << (i - 16));
84        }
85    }
86    fn set(&mut self, i: u8) {
87        if i < 16 {
88            self.lo |= 1 << i;
89        } else {
90            self.hi |= 1 << (i - 16);
91        }
92    }
93    fn is_set(&self, i: u8) -> bool {
94        if i < 16 {
95            (self.lo >> i) & 1 != 0
96        } else {
97            (self.hi >> (i - 16)) & 1 != 0
98        }
99    }
100    fn mask(&mut self, m: u8) -> u8 {
101        let result = self.lo & m as u16;
102        self.lo &= u16::MAX - m as u16;
103        result as u8
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110    #[test]
111    fn log2_test() {
112        assert_eq!(U144::new(0, 1).log2(), 0);
113        assert_eq!(U144::new(0, 4).log2(), 2);
114        assert_eq!(U144::new(1, 0).log2(), 16);
115    }
116    #[test]
117    fn leading_zeros() {
118        assert_eq!(U144::default().leading_zeros(), 144);
119        assert_eq!(U144::new(u128::MAX, 0).leading_zeros(), 0);
120        assert_eq!(U144::new(1, 0).leading_zeros(), 127);
121        assert_eq!(U144::new(0, 1).leading_zeros(), 143);
122        assert_eq!(U144::new(0, 0x8000).leading_zeros(), 128);
123    }
124    #[test]
125    fn ord() {
126        assert_eq!(U144::new(7, 0) < U144::new(0, 7), false);
127        assert_eq!(U144::new(0, 0) < U144::new(0, 0), false);
128        assert_eq!(U144::new(3, 7) < U144::new(3, 7), false);
129        assert_eq!(U144::new(0, 0) < U144::new(0, 1), true);
130        assert_eq!(U144::new(3, 7) < U144::new(3, 8), true);
131        assert_eq!(U144::new(3, 7) < U144::new(4, 0), true);
132    }
133    #[test]
134    fn add() {
135        let mut v = U144::default();
136        v.add(0xFFFF);
137        v.add(0xFFFF);
138        assert_eq!(v.hi, 1);
139        assert_eq!(v.lo, 0xFFFE);
140        v.add(1);
141        assert_eq!(v.hi, 1);
142        assert_eq!(v.lo, 0xFFFF);
143        v.add(1);
144        assert_eq!(v.hi, 2);
145        assert_eq!(v.lo, 0);
146    }
147    #[test]
148    fn subtract() {
149        let mut v = U144::new(0x10, 0x0);
150        v.subtract(0xFF);
151        assert_eq!(v.hi, 0xF);
152        assert_eq!(v.lo, 0xFF01);
153        v.subtract(1);
154        assert_eq!(v.hi, 0xF);
155        assert_eq!(v.lo, 0xFF00);
156    }
157    #[test]
158    fn set() {
159        let mut v = U144::default();
160        v.set(0);
161        assert_eq!(v.hi, 0);
162        assert_eq!(v.lo, 1);
163        v.set(15);
164        assert_eq!(v.hi, 0);
165        assert_eq!(v.lo, 0x8001);
166        v.set(16);
167        assert_eq!(v.hi, 1);
168        assert_eq!(v.lo, 0x8001);
169        v.set(32);
170        assert_eq!(v.hi, 0x10001);
171        assert_eq!(v.lo, 0x8001);
172    }
173    #[test]
174    fn trailing_zeros() {
175        assert_eq!(U144::new(0x56, 0x100).trailing_zeros(), 8);
176        assert_eq!(U144::new(0x56, 0).trailing_zeros(), 17);
177        assert_eq!(U144::default().trailing_zeros(), 144);
178    }
179    #[test]
180    fn count_ones() {
181        assert_eq!(U144::new(0x56, 0x100).count_ones(), 5);
182        assert_eq!(U144::new(0x56, 0).count_ones(), 4);
183        assert_eq!(U144::default().count_ones(), 0);
184    }
185}