1
1
use std:: iter:: Step ;
2
2
use std:: marker:: PhantomData ;
3
- use std:: ops:: Bound ;
4
3
use std:: ops:: RangeBounds ;
4
+ use std:: ops:: { Bound , Range } ;
5
5
6
6
use crate :: vec:: Idx ;
7
7
use crate :: vec:: IndexVec ;
@@ -11,6 +11,10 @@ use smallvec::SmallVec;
11
11
mod tests;
12
12
13
13
/// Stores a set of intervals on the indices.
14
+ ///
15
+ /// The elements in `map` are sorted and non-adjacent, which means
16
+ /// the second value of the previous element is *greater* than the
17
+ /// first value of the following element.
14
18
#[ derive( Debug , Clone ) ]
15
19
pub struct IntervalSet < I > {
16
20
// Start, end
@@ -84,7 +88,7 @@ impl<I: Idx> IntervalSet<I> {
84
88
// continue to the next range. We're looking here for the first
85
89
// range which starts *non-adjacently* to our end.
86
90
let next = self . map . partition_point ( |r| r. 0 <= end + 1 ) ;
87
- if let Some ( right) = next. checked_sub ( 1 ) {
91
+ let result = if let Some ( right) = next. checked_sub ( 1 ) {
88
92
let ( prev_start, prev_end) = self . map [ right] ;
89
93
if prev_end + 1 >= start {
90
94
// If the start for the inserted range is adjacent to the
@@ -99,25 +103,25 @@ impl<I: Idx> IntervalSet<I> {
99
103
if left != right {
100
104
self . map . drain ( left..right) ;
101
105
}
102
- return true ;
106
+ true
103
107
} else {
104
108
// We overlap with the previous range, increase it to
105
109
// include us.
106
110
//
107
111
// Make sure we're actually going to *increase* it though --
108
112
// it may be that end is just inside the previously existing
109
113
// set.
110
- return if end > prev_end {
114
+ if end > prev_end {
111
115
self . map [ right] . 1 = end;
112
116
true
113
117
} else {
114
118
false
115
- } ;
119
+ }
116
120
}
117
121
} else {
118
122
// Otherwise, we don't overlap, so just insert
119
123
self . map . insert ( right + 1 , ( start, end) ) ;
120
- return true ;
124
+ true
121
125
}
122
126
} else {
123
127
if self . map . is_empty ( ) {
@@ -127,8 +131,16 @@ impl<I: Idx> IntervalSet<I> {
127
131
} else {
128
132
self . map . insert ( next, ( start, end) ) ;
129
133
}
130
- return true ;
131
- }
134
+ true
135
+ } ;
136
+ debug_assert ! (
137
+ self . check_invariants( ) ,
138
+ "wrong intervals after insert {:?}..={:?} to {:?}" ,
139
+ start,
140
+ end,
141
+ self
142
+ ) ;
143
+ result
132
144
}
133
145
134
146
pub fn contains ( & self , needle : I ) -> bool {
@@ -145,9 +157,26 @@ impl<I: Idx> IntervalSet<I> {
145
157
where
146
158
I : Step ,
147
159
{
148
- // FIXME: Performance here is probably not great. We will be doing a lot
149
- // of pointless tree traversals.
150
- other. iter ( ) . all ( |elem| self . contains ( elem) )
160
+ let mut sup_iter = self . iter_intervals ( ) ;
161
+ let mut current = None ;
162
+ let contains = |sup : Range < I > , sub : Range < I > , current : & mut Option < Range < I > > | {
163
+ if sup. end < sub. start {
164
+ // if `sup.end == sub.start`, the next sup doesn't contain `sub.start`
165
+ None // continue to the next sup
166
+ } else if sup. end >= sub. end && sup. start <= sub. start {
167
+ * current = Some ( sup) ; // save the current sup
168
+ Some ( true )
169
+ } else {
170
+ Some ( false )
171
+ }
172
+ } ;
173
+ other. iter_intervals ( ) . all ( |sub| {
174
+ current
175
+ . take ( )
176
+ . and_then ( |sup| contains ( sup, sub. clone ( ) , & mut current) )
177
+ . or_else ( || sup_iter. find_map ( |sup| contains ( sup, sub. clone ( ) , & mut current) ) )
178
+ . unwrap_or ( false )
179
+ } )
151
180
}
152
181
153
182
pub fn is_empty ( & self ) -> bool {
@@ -174,7 +203,10 @@ impl<I: Idx> IntervalSet<I> {
174
203
175
204
pub fn insert_all ( & mut self ) {
176
205
self . clear ( ) ;
177
- self . map . push ( ( 0 , self . domain . try_into ( ) . unwrap ( ) ) ) ;
206
+ if let Some ( end) = self . domain . checked_sub ( 1 ) {
207
+ self . map . push ( ( 0 , end. try_into ( ) . unwrap ( ) ) ) ;
208
+ }
209
+ debug_assert ! ( self . check_invariants( ) ) ;
178
210
}
179
211
180
212
pub fn union ( & mut self , other : & IntervalSet < I > ) -> bool
@@ -186,8 +218,21 @@ impl<I: Idx> IntervalSet<I> {
186
218
for range in other. iter_intervals ( ) {
187
219
did_insert |= self . insert_range ( range) ;
188
220
}
221
+ debug_assert ! ( self . check_invariants( ) ) ;
189
222
did_insert
190
223
}
224
+
225
+ // Check the intervals are valid, sorted and non-adjacent
226
+ fn check_invariants ( & self ) -> bool {
227
+ let mut current: Option < u32 > = None ;
228
+ for ( start, end) in & self . map {
229
+ if start > end || current. map_or ( false , |x| x + 1 >= * start) {
230
+ return false ;
231
+ }
232
+ current = Some ( * end) ;
233
+ }
234
+ current. map_or ( true , |x| x < self . domain as u32 )
235
+ }
191
236
}
192
237
193
238
/// This data structure optimizes for cases where the stored bits in each row
0 commit comments