Skip to main content

int_interval/
u64.rs

1// -----------------------------------------------------------------------------
2// @generated by xtask/codegen
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 symmetric_difference_tests;
19#[cfg(test)]
20mod union_tests;
21
22#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
23pub struct U64CO {
24    start: u64,
25    end_excl: u64,
26}
27
28// ------------------------------------------------------------
29// low-level api: construction / accessors / predicates
30// ------------------------------------------------------------
31
32impl U64CO {
33    #[inline]
34    pub const fn try_new(start: u64, end_excl: u64) -> Option<Self> {
35        if start < end_excl {
36            Some(Self { start, end_excl })
37        } else {
38            None
39        }
40    }
41
42    #[inline]
43    pub const fn new_unchecked(start: u64, end_excl: u64) -> Self {
44        debug_assert!(start < end_excl);
45        Self { start, end_excl }
46    }
47
48    #[inline]
49    pub const fn start(self) -> u64 {
50        self.start
51    }
52
53    #[inline]
54    pub const fn end_excl(self) -> u64 {
55        self.end_excl
56    }
57
58    #[inline]
59    pub const fn len(self) -> u64 {
60        self.end_excl - self.start
61    }
62
63    #[inline]
64    pub const fn contains(self, x: u64) -> bool {
65        self.start <= x && x < self.end_excl
66    }
67
68    #[inline]
69    pub const fn iter(self) -> core::ops::Range<u64> {
70        self.start..self.end_excl
71    }
72
73    #[inline]
74    pub const fn intersects(self, other: Self) -> bool {
75        !(self.end_excl <= other.start || other.end_excl <= self.start)
76    }
77
78    #[inline]
79    pub const fn is_adjacent(self, other: Self) -> bool {
80        self.end_excl == other.start || other.end_excl == self.start
81    }
82
83    #[inline]
84    pub const fn is_contiguous_with(self, other: Self) -> bool {
85        self.intersects(other) || self.is_adjacent(other)
86    }
87}
88
89// ------------------------------------------------------------
90// high-level api: interval algebra
91// ------------------------------------------------------------
92
93impl U64CO {
94    #[inline]
95    pub const fn intersection(self, other: Self) -> Option<Self> {
96        let start = if self.start >= other.start {
97            self.start
98        } else {
99            other.start
100        };
101
102        let end_excl = if self.end_excl <= other.end_excl {
103            self.end_excl
104        } else {
105            other.end_excl
106        };
107
108        Self::try_new(start, end_excl)
109    }
110}
111
112impl U64CO {
113    #[inline]
114    pub const fn convex_hull(self, other: Self) -> Self {
115        let start = if self.start <= other.start {
116            self.start
117        } else {
118            other.start
119        };
120
121        let end_excl = if self.end_excl >= other.end_excl {
122            self.end_excl
123        } else {
124            other.end_excl
125        };
126
127        Self { start, end_excl }
128    }
129}
130
131impl U64CO {
132    #[inline]
133    pub const fn between(self, other: Self) -> Option<Self> {
134        let (left, right) = if self.start <= other.start {
135            (self, other)
136        } else {
137            (other, self)
138        };
139
140        Self::try_new(left.end_excl, right.start)
141    }
142}
143
144impl U64CO {
145    #[inline]
146    pub const fn union(self, other: Self) -> OneTwo<Self> {
147        if self.is_contiguous_with(other) {
148            OneTwo::One(self.convex_hull(other))
149        } else if self.start <= other.start {
150            OneTwo::Two(self, other)
151        } else {
152            OneTwo::Two(other, self)
153        }
154    }
155}
156
157impl U64CO {
158    #[inline]
159    pub const fn difference(self, other: Self) -> ZeroOneTwo<Self> {
160        match self.intersection(other) {
161            None => ZeroOneTwo::One(self),
162            Some(inter) => {
163                let left = Self::try_new(self.start, inter.start);
164                let right = Self::try_new(inter.end_excl, self.end_excl);
165
166                match (left, right) {
167                    (None, None) => ZeroOneTwo::Zero,
168                    (Some(x), None) | (None, Some(x)) => ZeroOneTwo::One(x),
169                    (Some(x), Some(y)) => ZeroOneTwo::Two(x, y),
170                }
171            }
172        }
173    }
174}
175
176impl U64CO {
177    #[inline]
178    pub const fn symmetric_difference(self, other: Self) -> ZeroOneTwo<Self> {
179        match self.intersection(other) {
180            None => {
181                if self.start <= other.start {
182                    ZeroOneTwo::Two(self, other)
183                } else {
184                    ZeroOneTwo::Two(other, self)
185                }
186            }
187            Some(inter) => {
188                let hull = self.convex_hull(other);
189                let left = Self::try_new(hull.start, inter.start);
190                let right = Self::try_new(inter.end_excl, hull.end_excl);
191
192                match (left, right) {
193                    (None, None) => ZeroOneTwo::Zero,
194                    (Some(x), None) | (None, Some(x)) => ZeroOneTwo::One(x),
195                    (Some(x), Some(y)) => ZeroOneTwo::Two(x, y),
196                }
197            }
198        }
199    }
200}