Skip to main content

int_interval/
i16.rs

1// -----------------------------------------------------------------------------
2// @generated by xtask/codegen (signed)
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 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 I16CO {
26    start: i16,
27    end_excl: i16,
28}
29
30// ------------------------------------------------------------
31// low-level api: construction / accessors / predicates
32// ------------------------------------------------------------
33mod construction_accessors_predicates {
34
35    use super::*;
36
37    impl I16CO {
38        #[inline]
39        pub const fn try_new(start: i16, end_excl: i16) -> 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: i16, end_excl: i16) -> Self {
49            debug_assert!(start < end_excl);
50            Self { start, end_excl }
51        }
52
53        #[inline]
54        pub const fn start(self) -> i16 {
55            self.start
56        }
57
58        #[inline]
59        pub const fn end_excl(self) -> i16 {
60            self.end_excl
61        }
62
63        #[inline]
64        pub const fn end_incl(self) -> i16 {
65            // i16_low_bound =< start < end_excl
66            self.end_excl - 1
67        }
68
69        #[inline]
70        pub const fn len(self) -> u16 {
71            (self.end_excl - self.start) as u16
72        }
73
74        #[inline]
75        pub const fn contains(self, x: i16) -> bool {
76            self.start <= x && x < self.end_excl
77        }
78
79        #[inline]
80        pub const fn iter(self) -> core::ops::Range<i16> {
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}
100// ------------------------------------------------------------
101// interval algebra api: intersection / convex_hull / between / union / difference / symmetric_difference
102// ------------------------------------------------------------
103
104mod interval_algebra {
105
106    use super::*;
107
108    impl I16CO {
109        /// Returns the intersection of two intervals.
110        ///
111        /// If the intervals do not overlap, returns `None`.
112        #[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        /// Returns the convex hull (smallest interval containing both) of two intervals.
130        ///
131        /// Always returns a valid `I16CO`.
132        #[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        /// Returns the interval strictly between two intervals.
150        ///
151        /// If the intervals are contiguous or overlap, returns `None`.
152        #[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        /// Returns the union of two intervals.
164        ///
165        /// - If intervals are contiguous or overlapping, returns `One` containing the merged interval.
166        /// - Otherwise, returns `Two` containing both intervals in ascending order.
167        #[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        /// Returns the difference of two intervals (self - other).
179        ///
180        /// - If no overlap, returns `One(self)`.
181        /// - If partial overlap, returns `One` or `Two` depending on remaining segments.
182        /// - If fully contained, returns `Zero`.
183        #[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        /// Returns the symmetric difference of two intervals.
201        ///
202        /// Equivalent to `(self - other) ∪ (other - self)`.
203        /// - If intervals do not overlap, returns `Two(self, other)` in order.
204        /// - If intervals partially overlap, returns remaining non-overlapping segments as `One` or `Two`.
205        #[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
231// ------------------------------------------------------------
232// Module: Minkowski arithmetic for I16CO
233// Provides checked Minkowski operations for intervals
234// ------------------------------------------------------------
235
236pub mod minkowski {
237    use super::I16CO;
238
239    // --------------------------------------------------------
240    // Interval-to-interval Minkowski operations
241    // --------------------------------------------------------
242    impl I16CO {
243        /// Minkowski addition: [a_start, a_end) + [b_start, b_end)
244        #[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        /// Minkowski subtraction: [a_start, a_end) - [b_start, b_end)
259        #[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        /// Minkowski multiplication: [a_start, a_end) * [b_start, b_end)
274        #[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        /// Minkowski division: [a_start, a_end) / [b_start, b_end)
306        #[inline]
307        pub const fn minkowski_div(self, other: Self) -> Option<Self> {
308            if other.start <= 0 && other.end_incl() >= 0 {
309                return None; // 避免除零
310            }
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    // --------------------------------------------------------
343    // Interval-to-scalar Minkowski operations
344    // --------------------------------------------------------
345    impl I16CO {
346        /// Add a scalar to an interval: [start, end) + n
347        #[inline]
348        pub const fn minkowski_add_n(self, n: i16) -> 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        /// Subtract a scalar from an interval: [start, end) - n
359        #[inline]
360        pub const fn minkowski_sub_n(self, n: i16) -> 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        /// Multiply an interval by a scalar: [start, end) * n
371        #[inline]
372        pub const fn minkowski_mul_n(self, n: i16) -> 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        /// Divide an interval by a scalar: [start, end) / n
392        #[inline]
393        pub const fn minkowski_div_n(self, n: i16) -> Option<Self> {
394            match n {
395                0 => None, // 避免除零
396                _ => 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}