rustc_index/
interval.rs
1use std::iter::Step;
2use std::marker::PhantomData;
3use std::ops::{Bound, Range, RangeBounds};
4
5use smallvec::SmallVec;
6
7use crate::idx::Idx;
8use crate::vec::IndexVec;
9
10#[cfg(test)]
11mod tests;
12
13#[derive(Debug, Clone)]
19pub struct IntervalSet<I> {
20 map: SmallVec<[(u32, u32); 2]>,
22 domain: usize,
23 _data: PhantomData<I>,
24}
25
26#[inline]
27fn inclusive_start<T: Idx>(range: impl RangeBounds<T>) -> u32 {
28 match range.start_bound() {
29 Bound::Included(start) => start.index() as u32,
30 Bound::Excluded(start) => start.index() as u32 + 1,
31 Bound::Unbounded => 0,
32 }
33}
34
35#[inline]
36fn inclusive_end<T: Idx>(domain: usize, range: impl RangeBounds<T>) -> Option<u32> {
37 let end = match range.end_bound() {
38 Bound::Included(end) => end.index() as u32,
39 Bound::Excluded(end) => end.index().checked_sub(1)? as u32,
40 Bound::Unbounded => domain.checked_sub(1)? as u32,
41 };
42 Some(end)
43}
44
45impl<I: Idx> IntervalSet<I> {
46 pub fn new(domain: usize) -> IntervalSet<I> {
47 IntervalSet { map: SmallVec::new(), domain, _data: PhantomData }
48 }
49
50 pub fn clear(&mut self) {
51 self.map.clear();
52 }
53
54 pub fn iter(&self) -> impl Iterator<Item = I> + '_
55 where
56 I: Step,
57 {
58 self.iter_intervals().flatten()
59 }
60
61 pub fn iter_intervals(&self) -> impl Iterator<Item = std::ops::Range<I>> + '_
63 where
64 I: Step,
65 {
66 self.map.iter().map(|&(start, end)| I::new(start as usize)..I::new(end as usize + 1))
67 }
68
69 pub fn insert(&mut self, point: I) -> bool {
71 self.insert_range(point..=point)
72 }
73
74 pub fn insert_range(&mut self, range: impl RangeBounds<I> + Clone) -> bool {
76 let start = inclusive_start(range.clone());
77 let Some(end) = inclusive_end(self.domain, range) else {
78 return false;
80 };
81 if start > end {
82 return false;
83 }
84
85 let next = self.map.partition_point(|r| r.0 <= end + 1);
91 let result = if let Some(right) = next.checked_sub(1) {
92 let (prev_start, prev_end) = self.map[right];
93 if prev_end + 1 >= start {
94 if start < prev_start {
97 let left = self.map.partition_point(|l| l.1 + 1 < start);
100 let min = std::cmp::min(self.map[left].0, start);
101 let max = std::cmp::max(prev_end, end);
102 self.map[right] = (min, max);
103 if left != right {
104 self.map.drain(left..right);
105 }
106 true
107 } else {
108 if end > prev_end {
115 self.map[right].1 = end;
116 true
117 } else {
118 false
119 }
120 }
121 } else {
122 self.map.insert(right + 1, (start, end));
124 true
125 }
126 } else {
127 if self.map.is_empty() {
128 self.map.push((start, end));
131 } else {
132 self.map.insert(next, (start, end));
133 }
134 true
135 };
136 debug_assert!(
137 self.check_invariants(),
138 "wrong intervals after insert {start:?}..={end:?} to {self:?}"
139 );
140 result
141 }
142
143 pub fn contains(&self, needle: I) -> bool {
144 let needle = needle.index() as u32;
145 let Some(last) = self.map.partition_point(|r| r.0 <= needle).checked_sub(1) else {
146 return false;
148 };
149 let (_, prev_end) = &self.map[last];
150 needle <= *prev_end
151 }
152
153 pub fn superset(&self, other: &IntervalSet<I>) -> bool
154 where
155 I: Step,
156 {
157 let mut sup_iter = self.iter_intervals();
158 let mut current = None;
159 let contains = |sup: Range<I>, sub: Range<I>, current: &mut Option<Range<I>>| {
160 if sup.end < sub.start {
161 None } else if sup.end >= sub.end && sup.start <= sub.start {
164 *current = Some(sup); Some(true)
166 } else {
167 Some(false)
168 }
169 };
170 other.iter_intervals().all(|sub| {
171 current
172 .take()
173 .and_then(|sup| contains(sup, sub.clone(), &mut current))
174 .or_else(|| sup_iter.find_map(|sup| contains(sup, sub.clone(), &mut current)))
175 .unwrap_or(false)
176 })
177 }
178
179 pub fn is_empty(&self) -> bool {
180 self.map.is_empty()
181 }
182
183 pub fn first_unset_in(&self, range: impl RangeBounds<I> + Clone) -> Option<I> {
185 let start = inclusive_start(range.clone());
186 let Some(end) = inclusive_end(self.domain, range) else {
187 return None;
189 };
190 if start > end {
191 return None;
192 }
193 let Some(last) = self.map.partition_point(|r| r.0 <= start).checked_sub(1) else {
194 return Some(I::new(start as usize));
196 };
197 let (_, prev_end) = self.map[last];
198 if start > prev_end {
199 Some(I::new(start as usize))
200 } else if prev_end < end {
201 Some(I::new(prev_end as usize + 1))
202 } else {
203 None
204 }
205 }
206
207 pub fn last_set_in(&self, range: impl RangeBounds<I> + Clone) -> Option<I> {
209 let start = inclusive_start(range.clone());
210 let Some(end) = inclusive_end(self.domain, range) else {
211 return None;
213 };
214 if start > end {
215 return None;
216 }
217 let Some(last) = self.map.partition_point(|r| r.0 <= end).checked_sub(1) else {
218 return None;
220 };
221 let (_, prev_end) = &self.map[last];
222 if start <= *prev_end { Some(I::new(std::cmp::min(*prev_end, end) as usize)) } else { None }
223 }
224
225 pub fn insert_all(&mut self) {
226 self.clear();
227 if let Some(end) = self.domain.checked_sub(1) {
228 self.map.push((0, end.try_into().unwrap()));
229 }
230 debug_assert!(self.check_invariants());
231 }
232
233 pub fn union(&mut self, other: &IntervalSet<I>) -> bool
234 where
235 I: Step,
236 {
237 assert_eq!(self.domain, other.domain);
238 if self.map.len() < other.map.len() {
239 let backup = self.clone();
240 self.map.clone_from(&other.map);
241 return self.union(&backup);
242 }
243
244 let mut did_insert = false;
245 for range in other.iter_intervals() {
246 did_insert |= self.insert_range(range);
247 }
248 debug_assert!(self.check_invariants());
249 did_insert
250 }
251
252 fn check_invariants(&self) -> bool {
254 let mut current: Option<u32> = None;
255 for (start, end) in &self.map {
256 if start > end || current.is_some_and(|x| x + 1 >= *start) {
257 return false;
258 }
259 current = Some(*end);
260 }
261 current.is_none_or(|x| x < self.domain as u32)
262 }
263}
264
265#[derive(Clone)]
271pub struct SparseIntervalMatrix<R, C>
272where
273 R: Idx,
274 C: Idx,
275{
276 rows: IndexVec<R, IntervalSet<C>>,
277 column_size: usize,
278}
279
280impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
281 pub fn new(column_size: usize) -> SparseIntervalMatrix<R, C> {
282 SparseIntervalMatrix { rows: IndexVec::new(), column_size }
283 }
284
285 pub fn rows(&self) -> impl Iterator<Item = R> {
286 self.rows.indices()
287 }
288
289 pub fn row(&self, row: R) -> Option<&IntervalSet<C>> {
290 self.rows.get(row)
291 }
292
293 fn ensure_row(&mut self, row: R) -> &mut IntervalSet<C> {
294 self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size))
295 }
296
297 pub fn union_row(&mut self, row: R, from: &IntervalSet<C>) -> bool
298 where
299 C: Step,
300 {
301 self.ensure_row(row).union(from)
302 }
303
304 pub fn union_rows(&mut self, read: R, write: R) -> bool
305 where
306 C: Step,
307 {
308 if read == write || self.rows.get(read).is_none() {
309 return false;
310 }
311 self.ensure_row(write);
312 let (read_row, write_row) = self.rows.pick2_mut(read, write);
313 write_row.union(read_row)
314 }
315
316 pub fn insert_all_into_row(&mut self, row: R) {
317 self.ensure_row(row).insert_all();
318 }
319
320 pub fn insert_range(&mut self, row: R, range: impl RangeBounds<C> + Clone) {
321 self.ensure_row(row).insert_range(range);
322 }
323
324 pub fn insert(&mut self, row: R, point: C) -> bool {
325 self.ensure_row(row).insert(point)
326 }
327
328 pub fn contains(&self, row: R, point: C) -> bool {
329 self.row(row).is_some_and(|r| r.contains(point))
330 }
331}