@@ -4,7 +4,7 @@ use std::fmt;
44use std:: iter;
55use std:: marker:: PhantomData ;
66use std:: mem;
7- use std:: ops:: { BitAnd , BitAndAssign , BitOrAssign , Not , Range , Shl } ;
7+ use std:: ops:: { BitAnd , BitAndAssign , BitOrAssign , Bound , Not , Range , RangeBounds , Shl } ;
88use std:: slice;
99
1010use rustc_macros:: { Decodable , Encodable } ;
@@ -22,6 +22,29 @@ pub trait BitRelations<Rhs> {
2222 fn intersect ( & mut self , other : & Rhs ) -> bool ;
2323}
2424
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+
2548macro_rules! bit_relations_inherent_impls {
2649 ( ) => {
2750 /// Sets `self = self | other` and returns `true` if `self` changed
@@ -151,6 +174,33 @@ impl<T: Idx> BitSet<T> {
151174 new_word != word
152175 }
153176
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+
154204 /// Sets all bits to true.
155205 pub fn insert_all ( & mut self ) {
156206 for word in & mut self . words {
@@ -227,6 +277,36 @@ impl<T: Idx> BitSet<T> {
227277 not_already
228278 }
229279
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+
230310 bit_relations_inherent_impls ! { }
231311}
232312
@@ -635,6 +715,16 @@ impl<T: Idx> SparseBitSet<T> {
635715 self . elems . iter ( )
636716 }
637717
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+
638728 bit_relations_inherent_impls ! { }
639729}
640730
@@ -709,6 +799,16 @@ impl<T: Idx> HybridBitSet<T> {
709799 }
710800 }
711801
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+
712812 pub fn insert ( & mut self , elem : T ) -> bool {
713813 // No need to check `elem` against `self.domain_size` here because all
714814 // the match cases check it, one way or another.
@@ -734,6 +834,41 @@ impl<T: Idx> HybridBitSet<T> {
734834 }
735835 }
736836
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+
737872 pub fn insert_all ( & mut self ) {
738873 let domain_size = self . domain_size ( ) ;
739874 match self {
@@ -1205,6 +1340,11 @@ fn word_index_and_mask<T: Idx>(elem: T) -> (usize, Word) {
12051340 ( word_index, mask)
12061341}
12071342
1343+ #[ inline]
1344+ fn max_bit ( word : Word ) -> usize {
1345+ WORD_BITS - 1 - word. leading_zeros ( ) as usize
1346+ }
1347+
12081348/// Integral type used to represent the bit set.
12091349pub trait FiniteBitSetTy :
12101350 BitAnd < Output = Self >
0 commit comments