@@ -4,7 +4,7 @@ use std::fmt;
4
4
use std:: iter;
5
5
use std:: marker:: PhantomData ;
6
6
use std:: mem;
7
- use std:: ops:: { BitAnd , BitAndAssign , BitOrAssign , Not , Range , Shl } ;
7
+ use std:: ops:: { BitAnd , BitAndAssign , BitOrAssign , Bound , Not , Range , RangeBounds , Shl } ;
8
8
use std:: slice;
9
9
10
10
use rustc_macros:: { Decodable , Encodable } ;
@@ -22,6 +22,29 @@ pub trait BitRelations<Rhs> {
22
22
fn intersect ( & mut self , other : & Rhs ) -> bool ;
23
23
}
24
24
25
+ #[ inline]
26
+ fn inclusive_start_end < T : Idx > (
27
+ range : impl RangeBounds < T > ,
28
+ domain : usize ,
29
+ ) -> Option < ( usize , usize ) > {
30
+ // Both start and end are inclusive.
31
+ let start = match range. start_bound ( ) . cloned ( ) {
32
+ Bound :: Included ( start) => start. index ( ) ,
33
+ Bound :: Excluded ( start) => start. index ( ) + 1 ,
34
+ Bound :: Unbounded => 0 ,
35
+ } ;
36
+ let end = match range. end_bound ( ) . cloned ( ) {
37
+ Bound :: Included ( end) => end. index ( ) ,
38
+ Bound :: Excluded ( end) => end. index ( ) . checked_sub ( 1 ) ?,
39
+ Bound :: Unbounded => domain - 1 ,
40
+ } ;
41
+ assert ! ( end < domain) ;
42
+ if start > end {
43
+ return None ;
44
+ }
45
+ Some ( ( start, end) )
46
+ }
47
+
25
48
macro_rules! bit_relations_inherent_impls {
26
49
( ) => {
27
50
/// Sets `self = self | other` and returns `true` if `self` changed
@@ -151,6 +174,33 @@ impl<T: Idx> BitSet<T> {
151
174
new_word != word
152
175
}
153
176
177
+ #[ inline]
178
+ pub fn insert_range ( & mut self , elems : impl RangeBounds < T > ) {
179
+ let Some ( ( start, end) ) = inclusive_start_end ( elems, self . domain_size ) else {
180
+ return ;
181
+ } ;
182
+
183
+ let ( start_word_index, start_mask) = word_index_and_mask ( start) ;
184
+ let ( end_word_index, end_mask) = word_index_and_mask ( end) ;
185
+
186
+ // Set all words in between start and end (exclusively of both).
187
+ for word_index in ( start_word_index + 1 ) ..end_word_index {
188
+ self . words [ word_index] = !0 ;
189
+ }
190
+
191
+ if start_word_index != end_word_index {
192
+ // Start and end are in different words, so we handle each in turn.
193
+ //
194
+ // We set all leading bits. This includes the start_mask bit.
195
+ self . words [ start_word_index] |= !( start_mask - 1 ) ;
196
+ // And all trailing bits (i.e. from 0..=end) in the end word,
197
+ // including the end.
198
+ self . words [ end_word_index] |= end_mask | end_mask - 1 ;
199
+ } else {
200
+ self . words [ start_word_index] |= end_mask | ( end_mask - start_mask) ;
201
+ }
202
+ }
203
+
154
204
/// Sets all bits to true.
155
205
pub fn insert_all ( & mut self ) {
156
206
for word in & mut self . words {
@@ -227,6 +277,36 @@ impl<T: Idx> BitSet<T> {
227
277
not_already
228
278
}
229
279
280
+ fn last_set_in ( & self , range : impl RangeBounds < T > ) -> Option < T > {
281
+ let ( start, end) = inclusive_start_end ( range, self . domain_size ) ?;
282
+ let ( start_word_index, _) = word_index_and_mask ( start) ;
283
+ let ( end_word_index, end_mask) = word_index_and_mask ( end) ;
284
+
285
+ let end_word = self . words [ end_word_index] & ( end_mask | ( end_mask - 1 ) ) ;
286
+ if end_word != 0 {
287
+ let pos = max_bit ( end_word) + WORD_BITS * end_word_index;
288
+ if start <= pos {
289
+ return Some ( T :: new ( pos) ) ;
290
+ }
291
+ }
292
+
293
+ // We exclude end_word_index from the range here, because we don't want
294
+ // to limit ourselves to *just* the last word: the bits set it in may be
295
+ // after `end`, so it may not work out.
296
+ if let Some ( offset) =
297
+ self . words [ start_word_index..end_word_index] . iter ( ) . rposition ( |& w| w != 0 )
298
+ {
299
+ let word_idx = start_word_index + offset;
300
+ let start_word = self . words [ word_idx] ;
301
+ let pos = max_bit ( start_word) + WORD_BITS * word_idx;
302
+ if start <= pos {
303
+ return Some ( T :: new ( pos) ) ;
304
+ }
305
+ }
306
+
307
+ None
308
+ }
309
+
230
310
bit_relations_inherent_impls ! { }
231
311
}
232
312
@@ -635,6 +715,16 @@ impl<T: Idx> SparseBitSet<T> {
635
715
self . elems . iter ( )
636
716
}
637
717
718
+ fn last_set_in ( & self , range : impl RangeBounds < T > ) -> Option < T > {
719
+ let mut last_leq = None ;
720
+ for e in self . iter ( ) {
721
+ if range. contains ( e) {
722
+ last_leq = Some ( * e) ;
723
+ }
724
+ }
725
+ last_leq
726
+ }
727
+
638
728
bit_relations_inherent_impls ! { }
639
729
}
640
730
@@ -709,6 +799,16 @@ impl<T: Idx> HybridBitSet<T> {
709
799
}
710
800
}
711
801
802
+ /// Returns the previous element present in the bitset from `elem`,
803
+ /// inclusively of elem. That is, will return `Some(elem)` if elem is in the
804
+ /// bitset.
805
+ pub fn last_set_in ( & self , range : impl RangeBounds < T > ) -> Option < T > {
806
+ match self {
807
+ HybridBitSet :: Sparse ( sparse) => sparse. last_set_in ( range) ,
808
+ HybridBitSet :: Dense ( dense) => dense. last_set_in ( range) ,
809
+ }
810
+ }
811
+
712
812
pub fn insert ( & mut self , elem : T ) -> bool {
713
813
// No need to check `elem` against `self.domain_size` here because all
714
814
// the match cases check it, one way or another.
@@ -734,6 +834,41 @@ impl<T: Idx> HybridBitSet<T> {
734
834
}
735
835
}
736
836
837
+ pub fn insert_range ( & mut self , elems : impl RangeBounds < T > ) {
838
+ // No need to check `elem` against `self.domain_size` here because all
839
+ // the match cases check it, one way or another.
840
+ let start = match elems. start_bound ( ) . cloned ( ) {
841
+ Bound :: Included ( start) => start. index ( ) ,
842
+ Bound :: Excluded ( start) => start. index ( ) + 1 ,
843
+ Bound :: Unbounded => 0 ,
844
+ } ;
845
+ let end = match elems. end_bound ( ) . cloned ( ) {
846
+ Bound :: Included ( end) => end. index ( ) + 1 ,
847
+ Bound :: Excluded ( end) => end. index ( ) ,
848
+ Bound :: Unbounded => self . domain_size ( ) - 1 ,
849
+ } ;
850
+ let len = if let Some ( l) = end. checked_sub ( start) {
851
+ l
852
+ } else {
853
+ return ;
854
+ } ;
855
+ match self {
856
+ HybridBitSet :: Sparse ( sparse) if sparse. len ( ) + len < SPARSE_MAX => {
857
+ // The set is sparse and has space for `elems`.
858
+ for elem in start..end {
859
+ sparse. insert ( T :: new ( elem) ) ;
860
+ }
861
+ }
862
+ HybridBitSet :: Sparse ( sparse) => {
863
+ // The set is sparse and full. Convert to a dense set.
864
+ let mut dense = sparse. to_dense ( ) ;
865
+ dense. insert_range ( elems) ;
866
+ * self = HybridBitSet :: Dense ( dense) ;
867
+ }
868
+ HybridBitSet :: Dense ( dense) => dense. insert_range ( elems) ,
869
+ }
870
+ }
871
+
737
872
pub fn insert_all ( & mut self ) {
738
873
let domain_size = self . domain_size ( ) ;
739
874
match self {
@@ -1205,6 +1340,11 @@ fn word_index_and_mask<T: Idx>(elem: T) -> (usize, Word) {
1205
1340
( word_index, mask)
1206
1341
}
1207
1342
1343
+ #[ inline]
1344
+ fn max_bit ( word : Word ) -> usize {
1345
+ WORD_BITS - 1 - word. leading_zeros ( ) as usize
1346
+ }
1347
+
1208
1348
/// Integral type used to represent the bit set.
1209
1349
pub trait FiniteBitSetTy :
1210
1350
BitAnd < Output = Self >
0 commit comments