1use core::ops::{Add, BitAnd, BitOr, BitXor, Not, Shl, Shr};
2
3#[derive(Copy, Clone, PartialEq, Eq, Debug)]
21pub struct Tnum {
22 value: u64,
23 mask: u64,
24 empty: bool,
25}
26
27impl Tnum {
28 pub const fn empty() -> Self {
30 Self {
31 value: 0,
32 mask: 0,
33 empty: true,
34 }
35 }
36
37 pub const fn from_parts(value: u64, mask: u64) -> Self {
42 Self {
43 value: value & !mask,
44 mask,
45 empty: false,
46 }
47 }
48
49 pub const fn from_value(value: u64) -> Self {
50 Self {
51 value,
52 mask: 0,
53 empty: false,
54 }
55 }
56
57 pub const fn parts(&self) -> Option<(u64, u64)> {
59 if self.empty {
60 None
61 } else {
62 Some((self.value, self.mask))
63 }
64 }
65
66 pub const fn is_const(&self) -> bool {
67 !self.empty && self.mask == 0
68 }
69
70 pub const fn value(&self) -> Option<u64> {
71 if self.is_const() {
72 Some(self.value)
73 } else {
74 None
75 }
76 }
77
78 pub const fn contains_value(&self, value: u64) -> bool {
80 !self.empty && value & !self.mask == self.value
81 }
82
83 pub const fn union(self, other: Self) -> Self {
85 if self.empty {
86 return other;
87 }
88 if other.empty {
89 return self;
90 }
91 let differing = self.value ^ other.value;
92 let mask = self.mask | other.mask | differing;
93 Self::from_parts(self.value, mask)
94 }
95
96 pub const fn intersection(self, other: Self) -> Self {
98 if self.empty || other.empty {
99 return Self::empty();
100 }
101 let conflicting = (self.value ^ other.value) & !(self.mask | other.mask);
102 if conflicting != 0 {
103 Self::empty()
104 } else {
105 Self::from_parts(self.value | other.value, self.mask & other.mask)
106 }
107 }
108
109 pub const fn is_defined(&self) -> bool {
110 !self.empty
111 }
112
113 pub const fn contains(&self, other: Self) -> bool {
115 other.empty
116 || (!self.empty
117 && other.mask & !self.mask == 0
118 && other.value & !self.mask == self.value)
119 }
120
121 pub const fn has_value(&self) -> bool {
122 !self.empty
123 }
124
125 pub const fn min_value(&self) -> Option<u64> {
126 if self.empty {
127 None
128 } else {
129 Some(self.value)
130 }
131 }
132
133 pub const fn max_value(&self) -> Option<u64> {
134 if self.empty {
135 None
136 } else {
137 Some(self.value | self.mask)
138 }
139 }
140
141 pub const fn unsigned_bounds(&self) -> (u64, u64) {
142 (self.value, self.value | self.mask)
143 }
144
145 pub const fn signed_bounds(&self) -> (i64, i64) {
146 const SIGN: u64 = 1 << 63;
147 if self.mask & SIGN != 0 {
148 (
149 (self.value | SIGN) as i64,
150 ((self.value | self.mask) & !SIGN) as i64,
151 )
152 } else {
153 (self.value as i64, (self.value | self.mask) as i64)
154 }
155 }
156
157 pub const fn bit_not(self) -> Self {
158 if self.empty {
159 return self;
160 }
161 Self {
162 value: !self.value & !self.mask,
163 mask: self.mask,
164 empty: false,
165 }
166 }
167
168 pub const fn bit_or(self, other: Self) -> Self {
169 if self.empty || other.empty {
170 return Self::empty();
171 }
172 let value = self.value | other.value;
173 let mask = (self.mask | other.mask) & !value;
174 Self {
175 value,
176 mask,
177 empty: false,
178 }
179 }
180
181 pub const fn bit_and(self, other: Self) -> Self {
182 if self.empty || other.empty {
183 return Self::empty();
184 }
185 let value = self.value & other.value;
186 let may_be_one = (self.value | self.mask) & (other.value | other.mask);
187 Self::from_parts(value, may_be_one & !value)
188 }
189
190 pub const fn bit_xor(self, other: Self) -> Self {
191 if self.empty || other.empty {
192 return Self::empty();
193 }
194 Self::from_parts(self.value ^ other.value, self.mask | other.mask)
195 }
196
197 pub const fn shift_left(self, shift: u8) -> Self {
198 if self.empty {
199 return self;
200 }
201 let shift = (shift as u32) % 64;
202 Self {
203 value: self.value.wrapping_shl(shift),
204 mask: self.mask.wrapping_shl(shift),
205 empty: false,
206 }
207 }
208
209 pub const fn shift_right(self, shift: u8) -> Self {
210 if self.empty {
211 return self;
212 }
213 let shift = (shift as u32) % 64;
214 Self {
215 value: self.value.wrapping_shr(shift),
216 mask: self.mask.wrapping_shr(shift),
217 empty: false,
218 }
219 }
220
221 pub const fn add(self, other: Self) -> Self {
222 if self.empty || other.empty {
223 return Self::empty();
224 }
225 let mask_sum = self.mask.wrapping_add(other.mask);
226 let value_sum = self.value.wrapping_add(other.value);
227 let sigma = mask_sum.wrapping_add(value_sum);
228 let carry_changes = sigma ^ value_sum;
229 let mask = carry_changes | self.mask | other.mask;
230 Self::from_parts(value_sum, mask)
231 }
232}
233
234impl Default for Tnum {
235 fn default() -> Self {
237 Self {
238 value: 0,
239 mask: !0,
240 empty: false,
241 }
242 }
243}
244
245impl Not for Tnum {
246 type Output = Tnum;
247 fn not(self) -> Self {
248 self.bit_not()
249 }
250}
251
252impl BitOr for Tnum {
253 type Output = Tnum;
254 fn bitor(self, other: Self) -> Self {
255 self.bit_or(other)
256 }
257}
258
259impl BitAnd for Tnum {
260 type Output = Tnum;
261 fn bitand(self, other: Self) -> Self {
262 self.bit_and(other)
263 }
264}
265
266impl BitXor for Tnum {
267 type Output = Tnum;
268 fn bitxor(self, other: Self) -> Self {
269 self.bit_xor(other)
270 }
271}
272
273impl Shl<u8> for Tnum {
274 type Output = Tnum;
275 fn shl(self, shift: u8) -> Self {
276 self.shift_left(shift)
277 }
278}
279
280impl Shr<u8> for Tnum {
281 type Output = Tnum;
282 fn shr(self, shift: u8) -> Self {
283 self.shift_right(shift)
284 }
285}
286
287impl Add for Tnum {
288 type Output = Tnum;
289 fn add(self, other: Self) -> Self::Output {
290 self.add(other)
291 }
292}
293
294