1use crate::res::{OneTwo, ZeroOneTwo};
8
9#[cfg(test)]
10mod between_tests;
11#[cfg(test)]
12mod convex_hull_tests;
13#[cfg(test)]
14mod difference_tests;
15#[cfg(test)]
16mod intersection_tests;
17#[cfg(test)]
18mod minkowski_tests;
19#[cfg(test)]
20mod symmetric_difference_tests;
21#[cfg(test)]
22mod union_tests;
23
24#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
25pub struct I128CO {
26 start: i128,
27 end_excl: i128,
28}
29
30mod construction_accessors_predicates {
34
35 use super::*;
36
37 impl I128CO {
38 #[inline]
39 pub const fn try_new(start: i128, end_excl: i128) -> Option<Self> {
40 if start < end_excl {
41 Some(Self { start, end_excl })
42 } else {
43 None
44 }
45 }
46
47 #[inline]
48 pub(super) const fn new_unchecked(start: i128, end_excl: i128) -> Self {
49 debug_assert!(start < end_excl);
50 Self { start, end_excl }
51 }
52
53 #[inline]
54 pub const fn start(self) -> i128 {
55 self.start
56 }
57
58 #[inline]
59 pub const fn end_excl(self) -> i128 {
60 self.end_excl
61 }
62
63 #[inline]
64 pub const fn end_incl(self) -> i128 {
65 self.end_excl - 1
67 }
68
69 #[inline]
70 pub const fn len(self) -> u128 {
71 (self.end_excl - self.start) as u128
72 }
73
74 #[inline]
75 pub const fn contains(self, x: i128) -> bool {
76 self.start <= x && x < self.end_excl
77 }
78
79 #[inline]
80 pub const fn iter(self) -> core::ops::Range<i128> {
81 self.start..self.end_excl
82 }
83
84 #[inline]
85 pub const fn intersects(self, other: Self) -> bool {
86 !(self.end_excl <= other.start || other.end_excl <= self.start)
87 }
88
89 #[inline]
90 pub const fn is_adjacent(self, other: Self) -> bool {
91 self.end_excl == other.start || other.end_excl == self.start
92 }
93
94 #[inline]
95 pub const fn is_contiguous_with(self, other: Self) -> bool {
96 self.intersects(other) || self.is_adjacent(other)
97 }
98 }
99}
100mod interval_algebra {
105
106 use super::*;
107
108 impl I128CO {
109 #[inline]
113 pub const fn intersection(self, other: Self) -> Option<Self> {
114 let start = if self.start >= other.start {
115 self.start
116 } else {
117 other.start
118 };
119
120 let end_excl = if self.end_excl <= other.end_excl {
121 self.end_excl
122 } else {
123 other.end_excl
124 };
125
126 Self::try_new(start, end_excl)
127 }
128
129 #[inline]
133 pub const fn convex_hull(self, other: Self) -> Self {
134 let start = if self.start <= other.start {
135 self.start
136 } else {
137 other.start
138 };
139
140 let end_excl = if self.end_excl >= other.end_excl {
141 self.end_excl
142 } else {
143 other.end_excl
144 };
145
146 Self { start, end_excl }
147 }
148
149 #[inline]
153 pub const fn between(self, other: Self) -> Option<Self> {
154 let (left, right) = if self.start <= other.start {
155 (self, other)
156 } else {
157 (other, self)
158 };
159
160 Self::try_new(left.end_excl, right.start)
161 }
162
163 #[inline]
168 pub const fn union(self, other: Self) -> OneTwo<Self> {
169 if self.is_contiguous_with(other) {
170 OneTwo::One(self.convex_hull(other))
171 } else if self.start <= other.start {
172 OneTwo::Two(self, other)
173 } else {
174 OneTwo::Two(other, self)
175 }
176 }
177
178 #[inline]
184 pub const fn difference(self, other: Self) -> ZeroOneTwo<Self> {
185 match self.intersection(other) {
186 None => ZeroOneTwo::One(self),
187 Some(inter) => {
188 let left = Self::try_new(self.start, inter.start);
189 let right = Self::try_new(inter.end_excl, self.end_excl);
190
191 match (left, right) {
192 (None, None) => ZeroOneTwo::Zero,
193 (Some(x), None) | (None, Some(x)) => ZeroOneTwo::One(x),
194 (Some(x), Some(y)) => ZeroOneTwo::Two(x, y),
195 }
196 }
197 }
198 }
199
200 #[inline]
206 pub const fn symmetric_difference(self, other: Self) -> ZeroOneTwo<Self> {
207 match self.intersection(other) {
208 None => {
209 if self.start <= other.start {
210 ZeroOneTwo::Two(self, other)
211 } else {
212 ZeroOneTwo::Two(other, self)
213 }
214 }
215 Some(inter) => {
216 let hull = self.convex_hull(other);
217 let left = Self::try_new(hull.start, inter.start);
218 let right = Self::try_new(inter.end_excl, hull.end_excl);
219
220 match (left, right) {
221 (None, None) => ZeroOneTwo::Zero,
222 (Some(x), None) | (None, Some(x)) => ZeroOneTwo::One(x),
223 (Some(x), Some(y)) => ZeroOneTwo::Two(x, y),
224 }
225 }
226 }
227 }
228 }
229}
230
231pub mod minkowski {
237 use super::I128CO;
238
239 impl I128CO {
243 #[inline]
245 pub const fn minkowski_add(self, other: Self) -> Option<Self> {
246 match self.start.checked_add(other.start) {
247 Some(start) => match self.end_incl().checked_add(other.end_incl()) {
248 Some(end_incl) => match end_incl.checked_add(1) {
249 Some(end_excl) => Some(Self::new_unchecked(start, end_excl)),
250 None => None,
251 },
252 None => None,
253 },
254 None => None,
255 }
256 }
257
258 #[inline]
260 pub const fn minkowski_sub(self, other: Self) -> Option<Self> {
261 match self.start.checked_sub(other.end_incl()) {
262 Some(start) => match self.end_incl().checked_sub(other.start) {
263 Some(end_incl) => match end_incl.checked_add(1) {
264 Some(end_excl) => Some(Self::new_unchecked(start, end_excl)),
265 None => None,
266 },
267 None => None,
268 },
269 None => None,
270 }
271 }
272
273 #[inline]
275 pub const fn minkowski_mul(self, other: Self) -> Option<Self> {
276 let a = self.start;
277 let b = self.end_incl();
278 let c = other.start;
279 let d = other.end_incl();
280
281 match a.checked_mul(c) {
282 Some(p1) => match a.checked_mul(d) {
283 Some(p2) => match b.checked_mul(c) {
284 Some(p3) => match b.checked_mul(d) {
285 Some(p4) => {
286 let (min1, max1) = if p1 < p2 { (p1, p2) } else { (p2, p1) };
287 let (min2, max2) = if p3 < p4 { (p3, p4) } else { (p4, p3) };
288 let min = if min1 < min2 { min1 } else { min2 };
289 let max = if max1 > max2 { max1 } else { max2 };
290 match max.checked_add(1) {
291 Some(end_excl) => Some(Self::new_unchecked(min, end_excl)),
292 None => None,
293 }
294 }
295 None => None,
296 },
297 None => None,
298 },
299 None => None,
300 },
301 None => None,
302 }
303 }
304
305 #[inline]
307 pub const fn minkowski_div(self, other: Self) -> Option<Self> {
308 if other.start <= 0 && other.end_incl() >= 0 {
309 return None; }
311
312 let a = self.start;
313 let b = self.end_incl();
314 let c = other.start;
315 let d = other.end_incl();
316
317 match a.checked_div(c) {
318 Some(p1) => match a.checked_div(d) {
319 Some(p2) => match b.checked_div(c) {
320 Some(p3) => match b.checked_div(d) {
321 Some(p4) => {
322 let (min1, max1) = if p1 < p2 { (p1, p2) } else { (p2, p1) };
323 let (min2, max2) = if p3 < p4 { (p3, p4) } else { (p4, p3) };
324 let min = if min1 < min2 { min1 } else { min2 };
325 let max = if max1 > max2 { max1 } else { max2 };
326 match max.checked_add(1) {
327 Some(end_excl) => Some(Self::new_unchecked(min, end_excl)),
328 None => None,
329 }
330 }
331 None => None,
332 },
333 None => None,
334 },
335 None => None,
336 },
337 None => None,
338 }
339 }
340 }
341
342 impl I128CO {
346 #[inline]
348 pub const fn minkowski_add_n(self, n: i128) -> Option<Self> {
349 match self.start.checked_add(n) {
350 Some(start) => match self.end_excl.checked_add(n) {
351 Some(end_excl) => Some(Self::new_unchecked(start, end_excl)),
352 None => None,
353 },
354 None => None,
355 }
356 }
357
358 #[inline]
360 pub const fn minkowski_sub_n(self, n: i128) -> Option<Self> {
361 match self.start.checked_sub(n) {
362 Some(start) => match self.end_excl.checked_sub(n) {
363 Some(end_excl) => Some(Self::new_unchecked(start, end_excl)),
364 None => None,
365 },
366 None => None,
367 }
368 }
369
370 #[inline]
372 pub const fn minkowski_mul_n(self, n: i128) -> Option<Self> {
373 match self.start.checked_mul(n) {
374 Some(a) => match self.end_incl().checked_mul(n) {
375 Some(b) => {
376 let (min, max) = match a < b {
377 true => (a, b),
378 false => (b, a),
379 };
380 match max.checked_add(1) {
381 Some(end_excl) => Some(Self::new_unchecked(min, end_excl)),
382 None => None,
383 }
384 }
385 None => None,
386 },
387 None => None,
388 }
389 }
390
391 #[inline]
393 pub const fn minkowski_div_n(self, n: i128) -> Option<Self> {
394 match n {
395 0 => None, _ => match self.start.checked_div(n) {
397 Some(a) => match self.end_incl().checked_div(n) {
398 Some(b) => {
399 let (min, max) = match a < b {
400 true => (a, b),
401 false => (b, a),
402 };
403 match max.checked_add(1) {
404 Some(end_excl) => Some(Self::new_unchecked(min, end_excl)),
405 None => None,
406 }
407 }
408 None => None,
409 },
410 None => None,
411 },
412 }
413 }
414 }
415}