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}