Skip to main content

int_interval/
u16.rs

1// -----------------------------------------------------------------------------
2// @generated by xtask/codegen (unsigned)
3// DO NOT EDIT MANUALLY.
4// Changes will be overwritten.
5// -----------------------------------------------------------------------------
6
7use 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 U16CO {
28    start: u16,
29    end_excl: u16,
30}
31
32// ------------------------------------------------------------
33// low-level api: construction / accessors / predicates
34// ------------------------------------------------------------
35
36mod construction_accessors_predicates {
37
38    use super::*;
39
40    impl U16CO {
41        #[inline]
42        pub const fn try_new(start: u16, end_excl: u16) -> 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: u16, end_excl: u16) -> Self {
52            debug_assert!(start < end_excl);
53            Self { start, end_excl }
54        }
55
56        #[inline]
57        pub const fn start(self) -> u16 {
58            self.start
59        }
60
61        #[inline]
62        pub const fn end_excl(self) -> u16 {
63            self.end_excl
64        }
65
66        #[inline]
67        pub const fn end_incl(self) -> u16 {
68            // u16_low_bound =< start < end_excl
69            self.end_excl - 1
70        }
71
72        #[inline]
73        pub const fn len(self) -> u16 {
74            self.end_excl - self.start
75        }
76
77        #[inline]
78        pub const fn contains(self, x: u16) -> bool {
79            self.start <= x && x < self.end_excl
80        }
81
82        #[inline]
83        pub const fn iter(self) -> core::ops::Range<u16> {
84            self.start..self.end_excl
85        }
86
87        #[inline]
88        pub const fn to_range(self) -> core::ops::Range<u16> {
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
109// ------------------------------------------------------------
110// interval algebra api: intersection / convex_hull / between / union / difference / symmetric_difference
111// ------------------------------------------------------------
112
113mod interval_algebra {
114
115    use super::*;
116
117    impl U16CO {
118        /// Returns the intersection of two intervals.
119        ///
120        /// If the intervals do not overlap, returns `None`.
121        #[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        /// Returns the convex hull (smallest interval containing both) of two intervals.
139        ///
140        /// Always returns a valid `U16CO`.
141        #[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        /// Returns the interval strictly between two intervals.
159        ///
160        /// If the intervals are contiguous or overlap, returns `None`.
161        #[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        /// Returns the union of two intervals.
173        ///
174        /// - If intervals are contiguous or overlapping, returns `One` containing the merged interval.
175        /// - Otherwise, returns `Two` containing both intervals in ascending order.
176        #[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        /// Returns the difference of two intervals (self - other).
188        ///
189        /// - If no overlap, returns `One(self)`.
190        /// - If partial overlap, returns `One` or `Two` depending on remaining segments.
191        /// - If fully contained, returns `Zero`.
192        #[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        /// Returns the symmetric difference of two intervals.
210        ///
211        /// Equivalent to `(self - other) ∪ (other - self)`.
212        /// - If intervals do not overlap, returns `Two(self, other)` in order.
213        /// - If intervals partially overlap, returns remaining non-overlapping segments as `One` or `Two`.
214        #[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
240// ------------------------------------------------------------
241// Module: Minkowski arithmetic for U16CO
242// Provides checked and saturating Minkowski operations
243// ------------------------------------------------------------
244
245pub mod minkowski {
246    use super::*;
247
248    pub mod checked {
249        use super::*;
250
251        // --------------------------------------------------------
252        // Interval-to-interval Minkowski operations
253        // --------------------------------------------------------
254        impl U16CO {
255            /// Minkowski addition: [a_start, a_end) + [b_start, b_end)
256            #[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            /// Minkowski subtraction: [a_start, a_end) - [b_start, b_end)
268            #[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            /// Minkowski multiplication: [a_start, a_end) * [b_start, b_end)
280            #[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            /// Minkowski division: [a_start, a_end) / [b_start, b_end)
295            #[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        // --------------------------------------------------------
315        // Interval-to-scalar Minkowski operations
316        // --------------------------------------------------------
317        impl U16CO {
318            /// Add a scalar to an interval: [start, end) + n
319            #[inline]
320            pub const fn checked_minkowski_add_n(self, n: u16) -> 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            /// Subtract a scalar from an interval: [start, end) - n
331            #[inline]
332            pub const fn checked_minkowski_sub_n(self, n: u16) -> 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            /// Multiply an interval by a scalar: [start, end) * n
343            #[inline]
344            pub const fn checked_minkowski_mul_n(self, n: u16) -> 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            /// Divide an interval by a scalar: [start, end) / n
358            #[inline]
359            pub const fn checked_minkowski_div_n(self, n: u16) -> 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        // --------------------------------------------------------
378        // Interval-to-interval Minkowski operations
379        // --------------------------------------------------------
380        impl U16CO {
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        // --------------------------------------------------------
417        // Interval-to-scalar Minkowski operations
418        // --------------------------------------------------------
419        impl U16CO {
420            /// Saturating add scalar: [start, end) + n
421            #[inline]
422            pub const fn saturating_minkowski_add_n(self, n: u16) -> 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            /// Saturating sub scalar: [start, end) - n
429            #[inline]
430            pub const fn saturating_minkowski_sub_n(self, n: u16) -> 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            /// Saturating mul scalar: [start, end) * n
437            #[inline]
438            pub const fn saturating_minkowski_mul_n(self, n: u16) -> 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            /// Saturating div scalar: [start, end) / n
446            #[inline]
447            pub const fn saturating_minkowski_div_n(self, n: u16) -> 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}