1use core::ops::{Add, Div, Mul, Neg, Not, Rem, Sub};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Rnum {
11 max: u64,
12 min: u64,
13
14 smax: i64,
15 smin: i64,
16 empty: bool,
17}
18
19impl Rnum {
20 const fn unknown() -> Self {
21 Self {
22 min: u64::MIN,
23 max: u64::MAX,
24 smin: i64::MIN,
25 smax: i64::MAX,
26 empty: false,
27 }
28 }
29
30 pub const fn new(min: u64, max: u64, smin: i64, smax: i64) -> Option<Self> {
32 if min <= max && smin <= smax {
33 Some(Self {
34 min,
35 max,
36 smin,
37 smax,
38 empty: false,
39 })
40 } else {
41 None
42 }
43 }
44
45 pub const fn from_value(value: u64) -> Self {
46 let signed = value as i64;
47 Self {
48 min: value,
49 max: value,
50 smin: signed,
51 smax: signed,
52 empty: false,
53 }
54 }
55
56 pub const fn unsigned_bounds(&self) -> (u64, u64) {
57 (self.min, self.max)
58 }
59
60 pub const fn signed_bounds(&self) -> (i64, i64) {
61 (self.smin, self.smax)
62 }
63
64 pub const fn is_const(&self) -> bool {
66 matches!((self.min_value(), self.max_value()), (Some(min), Some(max)) if min == max)
67 }
68
69 pub const fn value(&self) -> Option<u64> {
71 match self.extrema() {
72 Some((min, max)) if min == max => Some(min),
73 _ => None,
74 }
75 }
76
77 pub const fn is_defined(&self) -> bool {
79 self.has_value()
80 }
81
82 pub const fn contains_value(&self, value: u64) -> bool {
84 !self.empty
85 && self.min <= value
86 && value <= self.max
87 && self.smin <= value as i64
88 && (value as i64) <= self.smax
89 }
90
91 pub const fn union(&self, other: Self) -> Self {
93 if self.empty || !self.has_value() {
94 return other;
95 }
96 if other.empty || !other.has_value() {
97 return *self;
98 }
99 Self {
100 min: if self.min < other.min {
101 self.min
102 } else {
103 other.min
104 },
105 max: if self.max > other.max {
106 self.max
107 } else {
108 other.max
109 },
110 smin: if self.smin < other.smin {
111 self.smin
112 } else {
113 other.smin
114 },
115 smax: if self.smax > other.smax {
116 self.smax
117 } else {
118 other.smax
119 },
120 empty: false,
121 }
122 }
123
124 pub const fn intersection(&self, other: Self) -> Self {
126 if self.empty || other.empty {
127 return Self::empty();
128 }
129 let result = Self {
130 min: if self.min > other.min {
131 self.min
132 } else {
133 other.min
134 },
135 max: if self.max < other.max {
136 self.max
137 } else {
138 other.max
139 },
140 smin: if self.smin > other.smin {
141 self.smin
142 } else {
143 other.smin
144 },
145 smax: if self.smax < other.smax {
146 self.smax
147 } else {
148 other.smax
149 },
150 empty: false,
151 };
152 if result.min > result.max || result.smin > result.smax || !result.has_value() {
153 Self::empty()
154 } else {
155 result
156 }
157 }
158
159 pub const fn contains(&self, other: Self) -> bool {
161 !other.has_value()
162 || (self.has_value()
163 && self.min <= other.min
164 && other.max <= self.max
165 && self.smin <= other.smin
166 && other.smax <= self.smax)
167 }
168
169 pub const fn has_value(&self) -> bool {
170 self.extrema().is_some()
171 }
172
173 pub const fn min_value(&self) -> Option<u64> {
174 match self.extrema() {
175 Some((min, _)) => Some(min),
176 None => None,
177 }
178 }
179
180 pub const fn max_value(&self) -> Option<u64> {
181 match self.extrema() {
182 Some((_, max)) => Some(max),
183 None => None,
184 }
185 }
186
187 const fn extrema(&self) -> Option<(u64, u64)> {
188 if self.empty {
189 return None;
190 }
191 let mut result: Option<(u64, u64)> = None;
192
193 if self.smax >= 0 {
194 let low = (if self.smin > 0 { self.smin } else { 0 }) as u64;
195 let low = if low > self.min { low } else { self.min };
196 let high = self.smax as u64;
197 let high = if high < self.max { high } else { self.max };
198 if low <= high {
199 result = Some((low, high));
200 }
201 }
202 if self.smin < 0 {
203 let low = self.smin as u64;
204 let low = if low > self.min { low } else { self.min };
205 let signed_high = if self.smax < -1 { self.smax } else { -1 };
206 let high = signed_high as u64;
207 let high = if high < self.max { high } else { self.max };
208 if low <= high {
209 result = Some(match result {
210 Some((min, max)) => (
211 if min < low { min } else { low },
212 if max > high { max } else { high },
213 ),
214 None => (low, high),
215 });
216 }
217 }
218 result
219 }
220
221 const fn empty() -> Self {
222 Self {
223 min: 0,
224 max: 0,
225 smin: 0,
226 smax: 0,
227 empty: true,
228 }
229 }
230
231 const fn bounded(min: u64, max: u64, smin: i64, smax: i64) -> Self {
232 let result = Self {
233 min,
234 max,
235 smin,
236 smax,
237 empty: false,
238 };
239 if result.has_value() {
243 result
244 } else {
245 Self::unknown()
246 }
247 }
248
249 const fn signed_hull(min: u64, max: u64) -> (i64, i64) {
250 if max <= i64::MAX as u64 || min > i64::MAX as u64 {
251 (min as i64, max as i64)
252 } else {
253 (i64::MIN, i64::MAX)
254 }
255 }
256
257 pub const fn add(self, other: Self) -> Self {
258 if !self.has_value() || !other.has_value() {
259 return Self::empty();
260 }
261 let (min, max) = if self.max <= u64::MAX - other.max {
262 (self.min + other.min, self.max + other.max)
263 } else {
264 (u64::MIN, u64::MAX)
265 };
266 let signed_min = self.smin as i128 + other.smin as i128;
267 let signed_max = self.smax as i128 + other.smax as i128;
268 let (smin, smax) = if signed_min >= i64::MIN as i128 && signed_max <= i64::MAX as i128 {
269 (signed_min as i64, signed_max as i64)
270 } else {
271 (i64::MIN, i64::MAX)
272 };
273 Self::bounded(min, max, smin, smax)
274 }
275
276 pub const fn subtract(self, other: Self) -> Self {
277 if !self.has_value() || !other.has_value() {
278 return Self::empty();
279 }
280 let (min, max) = if self.min >= other.max {
281 (self.min - other.max, self.max - other.min)
282 } else {
283 (u64::MIN, u64::MAX)
284 };
285 let signed_min = self.smin as i128 - other.smax as i128;
286 let signed_max = self.smax as i128 - other.smin as i128;
287 let (smin, smax) = if signed_min >= i64::MIN as i128 && signed_max <= i64::MAX as i128 {
288 (signed_min as i64, signed_max as i64)
289 } else {
290 (i64::MIN, i64::MAX)
291 };
292 Self::bounded(min, max, smin, smax)
293 }
294
295 pub const fn negate(self) -> Self {
296 if !self.has_value() {
297 return Self::empty();
298 }
299 let (min, max) = if self.min == 0 && self.max == 0 {
300 (0, 0)
301 } else if self.min > 0 {
302 (self.max.wrapping_neg(), self.min.wrapping_neg())
303 } else {
304 (u64::MIN, u64::MAX)
305 };
306 let (smin, smax) = if self.smin != i64::MIN {
307 (-self.smax, -self.smin)
308 } else {
309 (i64::MIN, i64::MAX)
310 };
311 Self::bounded(min, max, smin, smax)
312 }
313
314 pub const fn bit_not(self) -> Self {
315 if !self.has_value() {
316 return Self::empty();
317 }
318 Self::bounded(!self.max, !self.min, !self.smax, !self.smin)
319 }
320
321 pub const fn multiply(self, other: Self) -> Self {
322 if !self.has_value() || !other.has_value() {
323 return Self::empty();
324 }
325 let (min, max) = if self.max == 0 || other.max <= u64::MAX / self.max {
326 (self.min * other.min, self.max * other.max)
327 } else {
328 (u64::MIN, u64::MAX)
329 };
330 let products = [
331 self.smin as i128 * other.smin as i128,
332 self.smin as i128 * other.smax as i128,
333 self.smax as i128 * other.smin as i128,
334 self.smax as i128 * other.smax as i128,
335 ];
336 let mut signed_min = products[0];
337 let mut signed_max = products[0];
338 let mut index = 1;
339 while index < products.len() {
340 if products[index] < signed_min {
341 signed_min = products[index];
342 }
343 if products[index] > signed_max {
344 signed_max = products[index];
345 }
346 index += 1;
347 }
348 let (smin, smax) = if signed_min >= i64::MIN as i128 && signed_max <= i64::MAX as i128 {
349 (signed_min as i64, signed_max as i64)
350 } else {
351 (i64::MIN, i64::MAX)
352 };
353 Self::bounded(min, max, smin, smax)
354 }
355
356 pub const fn checked_div(self, other: Self) -> Option<Self> {
357 if !self.has_value() || !other.has_value() {
358 return Some(Self::empty());
359 }
360 if other.max == 0 {
361 return None;
362 }
363 let least_divisor = if other.min == 0 { 1 } else { other.min };
364 let min = self.min / other.max;
365 let max = self.max / least_divisor;
366 let (smin, smax) = Self::signed_hull(min, max);
367 Some(Self::bounded(min, max, smin, smax))
368 }
369
370 pub const fn divide(self, other: Self) -> Self {
371 match self.checked_div(other) {
372 Some(result) => result,
373 None => Self::empty(),
374 }
375 }
376
377 pub const fn remainder(self, other: Self) -> Self {
378 if !self.has_value() || !other.has_value() {
379 return Self::empty();
380 }
381 if other.max == 0 {
382 return Self::empty();
383 }
384 let max = if self.max < other.max - 1 {
385 self.max
386 } else {
387 other.max - 1
388 };
389 let (smin, smax) = Self::signed_hull(0, max);
390 Self::bounded(0, max, smin, smax)
391 }
392}
393
394impl Default for Rnum {
395 fn default() -> Self {
397 Self::unknown()
398 }
399}
400
401impl Add for Rnum {
402 type Output = Rnum;
403 fn add(self, other: Self) -> Self {
404 Self::add(self, other)
405 }
406}
407
408impl Sub for Rnum {
409 type Output = Rnum;
410 fn sub(self, other: Self) -> Self {
411 self.subtract(other)
412 }
413}
414
415impl Neg for Rnum {
416 type Output = Rnum;
417 fn neg(self) -> Self {
418 self.negate()
419 }
420}
421
422impl Not for Rnum {
423 type Output = Rnum;
424 fn not(self) -> Self {
425 self.bit_not()
426 }
427}
428
429impl Mul for Rnum {
430 type Output = Rnum;
431 fn mul(self, other: Self) -> Self {
432 self.multiply(other)
433 }
434}
435
436impl Div for Rnum {
437 type Output = Rnum;
438 fn div(self, other: Self) -> Self {
439 self.divide(other)
440 }
441}
442
443impl Rem for Rnum {
444 type Output = Rnum;
445 fn rem(self, other: Self) -> Self {
446 self.remainder(other)
447 }
448}