1use crate::res::{OneTwo, ZeroOneTwo};
8
9#[cfg(test)]
10mod between_tests;
11#[cfg(test)]
12mod checked_minkowski_tests;
13#[cfg(test)]
14mod convex_hull_tests;
15#[cfg(test)]
16mod difference_tests;
17#[cfg(test)]
18mod intersection_tests;
19#[cfg(test)]
20mod saturating_minkowski_tests;
21#[cfg(test)]
22mod symmetric_difference_tests;
23#[cfg(test)]
24mod union_tests;
25
26#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
27pub struct U128CO {
28 start: u128,
29 end_excl: u128,
30}
31
32mod construction_accessors_predicates {
37
38 use super::*;
39
40 impl U128CO {
41 #[inline]
42 pub const fn try_new(start: u128, end_excl: u128) -> Option<Self> {
43 if start < end_excl {
44 Some(Self { start, end_excl })
45 } else {
46 None
47 }
48 }
49
50 #[inline]
51 pub(super) const fn new_unchecked(start: u128, end_excl: u128) -> Self {
52 debug_assert!(start < end_excl);
53 Self { start, end_excl }
54 }
55
56 #[inline]
57 pub const fn start(self) -> u128 {
58 self.start
59 }
60
61 #[inline]
62 pub const fn end_excl(self) -> u128 {
63 self.end_excl
64 }
65
66 #[inline]
67 pub const fn end_incl(self) -> u128 {
68 self.end_excl - 1
70 }
71
72 #[inline]
73 pub const fn len(self) -> u128 {
74 self.end_excl - self.start
75 }
76
77 #[inline]
78 pub const fn contains(self, x: u128) -> bool {
79 self.start <= x && x < self.end_excl
80 }
81
82 #[inline]
83 pub const fn iter(self) -> core::ops::Range<u128> {
84 self.start..self.end_excl
85 }
86
87 #[inline]
88 pub const fn to_range(self) -> core::ops::Range<u128> {
89 self.start..self.end_excl
90 }
91
92 #[inline]
93 pub const fn intersects(self, other: Self) -> bool {
94 !(self.end_excl <= other.start || other.end_excl <= self.start)
95 }
96
97 #[inline]
98 pub const fn is_adjacent(self, other: Self) -> bool {
99 self.end_excl == other.start || other.end_excl == self.start
100 }
101
102 #[inline]
103 pub const fn is_contiguous_with(self, other: Self) -> bool {
104 self.intersects(other) || self.is_adjacent(other)
105 }
106 }
107}
108
109mod interval_algebra {
114
115 use super::*;
116
117 impl U128CO {
118 #[inline]
122 pub const fn intersection(self, other: Self) -> Option<Self> {
123 let start = if self.start >= other.start {
124 self.start
125 } else {
126 other.start
127 };
128
129 let end_excl = if self.end_excl <= other.end_excl {
130 self.end_excl
131 } else {
132 other.end_excl
133 };
134
135 Self::try_new(start, end_excl)
136 }
137
138 #[inline]
142 pub const fn convex_hull(self, other: Self) -> Self {
143 let start = if self.start <= other.start {
144 self.start
145 } else {
146 other.start
147 };
148
149 let end_excl = if self.end_excl >= other.end_excl {
150 self.end_excl
151 } else {
152 other.end_excl
153 };
154
155 Self { start, end_excl }
156 }
157
158 #[inline]
162 pub const fn between(self, other: Self) -> Option<Self> {
163 let (left, right) = if self.start <= other.start {
164 (self, other)
165 } else {
166 (other, self)
167 };
168
169 Self::try_new(left.end_excl, right.start)
170 }
171
172 #[inline]
177 pub const fn union(self, other: Self) -> OneTwo<Self> {
178 if self.is_contiguous_with(other) {
179 OneTwo::One(self.convex_hull(other))
180 } else if self.start <= other.start {
181 OneTwo::Two(self, other)
182 } else {
183 OneTwo::Two(other, self)
184 }
185 }
186
187 #[inline]
193 pub const fn difference(self, other: Self) -> ZeroOneTwo<Self> {
194 match self.intersection(other) {
195 None => ZeroOneTwo::One(self),
196 Some(inter) => {
197 let left = Self::try_new(self.start, inter.start);
198 let right = Self::try_new(inter.end_excl, self.end_excl);
199
200 match (left, right) {
201 (None, None) => ZeroOneTwo::Zero,
202 (Some(x), None) | (None, Some(x)) => ZeroOneTwo::One(x),
203 (Some(x), Some(y)) => ZeroOneTwo::Two(x, y),
204 }
205 }
206 }
207 }
208
209 #[inline]
215 pub const fn symmetric_difference(self, other: Self) -> ZeroOneTwo<Self> {
216 match self.intersection(other) {
217 None => {
218 if self.start <= other.start {
219 ZeroOneTwo::Two(self, other)
220 } else {
221 ZeroOneTwo::Two(other, self)
222 }
223 }
224 Some(inter) => {
225 let hull = self.convex_hull(other);
226 let left = Self::try_new(hull.start, inter.start);
227 let right = Self::try_new(inter.end_excl, hull.end_excl);
228
229 match (left, right) {
230 (None, None) => ZeroOneTwo::Zero,
231 (Some(x), None) | (None, Some(x)) => ZeroOneTwo::One(x),
232 (Some(x), Some(y)) => ZeroOneTwo::Two(x, y),
233 }
234 }
235 }
236 }
237 }
238}
239
240pub mod minkowski {
246 use super::*;
247
248 pub mod checked {
249 use super::*;
250
251 impl U128CO {
255 #[inline]
257 pub const fn checked_minkowski_add(self, other: Self) -> Option<Self> {
258 let Some(start) = self.start.checked_add(other.start) else {
259 return None;
260 };
261 let Some(end_excl) = self.end_excl.checked_add(other.end_incl()) else {
262 return None;
263 };
264 Some(Self::new_unchecked(start, end_excl))
265 }
266
267 #[inline]
269 pub const fn checked_minkowski_sub(self, other: Self) -> Option<Self> {
270 let Some(start) = self.start.checked_sub(other.end_incl()) else {
271 return None;
272 };
273 let Some(end_excl) = self.end_excl.checked_sub(other.start) else {
274 return None;
275 };
276 Some(Self::new_unchecked(start, end_excl))
277 }
278
279 #[inline]
281 pub const fn checked_minkowski_mul(self, other: Self) -> Option<Self> {
282 let Some(start) = self.start.checked_mul(other.start) else {
283 return None;
284 };
285 let Some(end_incl) = self.end_incl().checked_mul(other.end_incl()) else {
286 return None;
287 };
288 let Some(end_excl) = end_incl.checked_add(1) else {
289 return None;
290 };
291 Some(Self::new_unchecked(start, end_excl))
292 }
293
294 #[inline]
296 pub const fn checked_minkowski_div(self, other: Self) -> Option<Self> {
297 if other.start == 0 {
298 return None;
299 }
300
301 let Some(start) = self.start.checked_div(other.end_incl()) else {
302 return None;
303 };
304 let Some(end_incl) = self.end_incl().checked_div(other.start) else {
305 return None;
306 };
307 let Some(end_excl) = end_incl.checked_add(1) else {
308 return None;
309 };
310 Some(Self::new_unchecked(start, end_excl))
311 }
312 }
313
314 impl U128CO {
318 #[inline]
320 pub const fn checked_minkowski_add_n(self, n: u128) -> Option<Self> {
321 let Some(start) = self.start.checked_add(n) else {
322 return None;
323 };
324 let Some(end_excl) = self.end_excl.checked_add(n) else {
325 return None;
326 };
327 Some(Self::new_unchecked(start, end_excl))
328 }
329
330 #[inline]
332 pub const fn checked_minkowski_sub_n(self, n: u128) -> Option<Self> {
333 let Some(start) = self.start.checked_sub(n) else {
334 return None;
335 };
336 let Some(end_excl) = self.end_excl.checked_sub(n) else {
337 return None;
338 };
339 Some(Self::new_unchecked(start, end_excl))
340 }
341
342 #[inline]
344 pub const fn checked_minkowski_mul_n(self, n: u128) -> Option<Self> {
345 let Some(start) = self.start.checked_mul(n) else {
346 return None;
347 };
348 let Some(end_incl) = self.end_incl().checked_mul(n) else {
349 return None;
350 };
351 let Some(end_excl) = end_incl.checked_add(1) else {
352 return None;
353 };
354 Some(Self::new_unchecked(start, end_excl))
355 }
356
357 #[inline]
359 pub const fn checked_minkowski_div_n(self, n: u128) -> Option<Self> {
360 if n == 0 {
361 return None;
362 }
363
364 let start = self.start / n;
365 let end_incl = self.end_incl() / n;
366 let Some(end_excl) = end_incl.checked_add(1) else {
367 return None;
368 };
369 Some(Self::new_unchecked(start, end_excl))
370 }
371 }
372 }
373
374 pub mod saturating {
375 use super::*;
376
377 impl U128CO {
381 #[inline]
382 pub const fn saturating_minkowski_add(self, other: Self) -> Option<Self> {
383 let start = self.start.saturating_add(other.start);
384 let end_excl = self.end_excl.saturating_add(other.end_incl());
385 Self::try_new(start, end_excl)
386 }
387
388 #[inline]
389 pub const fn saturating_minkowski_sub(self, other: Self) -> Option<Self> {
390 let start = self.start.saturating_sub(other.end_incl());
391 let end_excl = self.end_excl.saturating_sub(other.start);
392 Self::try_new(start, end_excl)
393 }
394
395 #[inline]
396 pub const fn saturating_minkowski_mul(self, other: Self) -> Option<Self> {
397 let start = self.start.saturating_mul(other.start);
398 let end_incl = self.end_incl().saturating_mul(other.end_incl());
399 let end_excl = end_incl.saturating_add(1);
400 Self::try_new(start, end_excl)
401 }
402
403 #[inline]
404 pub const fn saturating_minkowski_div(self, other: Self) -> Option<Self> {
405 if other.start == 0 {
406 return None;
407 }
408
409 let start = self.start / other.end_incl();
410 let end_incl = self.end_incl() / other.start;
411 let end_excl = end_incl.saturating_add(1);
412 Self::try_new(start, end_excl)
413 }
414 }
415
416 impl U128CO {
420 #[inline]
422 pub const fn saturating_minkowski_add_n(self, n: u128) -> Option<Self> {
423 let start = self.start.saturating_add(n);
424 let end_excl = self.end_excl.saturating_add(n);
425 Self::try_new(start, end_excl)
426 }
427
428 #[inline]
430 pub const fn saturating_minkowski_sub_n(self, n: u128) -> Option<Self> {
431 let start = self.start.saturating_sub(n);
432 let end_excl = self.end_excl.saturating_sub(n);
433 Self::try_new(start, end_excl)
434 }
435
436 #[inline]
438 pub const fn saturating_minkowski_mul_n(self, n: u128) -> Option<Self> {
439 let start = self.start.saturating_mul(n);
440 let end_incl = self.end_incl().saturating_mul(n);
441 let end_excl = end_incl.saturating_add(1);
442 Self::try_new(start, end_excl)
443 }
444
445 #[inline]
447 pub const fn saturating_minkowski_div_n(self, n: u128) -> Option<Self> {
448 if n == 0 {
449 return None;
450 }
451
452 let start = self.start / n;
453 let end_incl = self.end_incl() / n;
454 let end_excl = end_incl.saturating_add(1);
455 Self::try_new(start, end_excl)
456 }
457 }
458 }
459}