@@ -287,17 +287,32 @@ impl<T: Idx> ToString for BitSet<T> {
287
287
}
288
288
289
289
pub struct BitIter < ' a , T : Idx > {
290
- cur : Option < ( Word , usize ) > ,
291
- iter : iter:: Enumerate < slice:: Iter < ' a , Word > > ,
290
+ /// A copy of the current word, but with any already-visited bits cleared.
291
+ /// (This lets us use `trailing_zeros()` to find the next set bit.) When it
292
+ /// is reduced to 0, we move onto the next word.
293
+ word : Word ,
294
+
295
+ /// The offset (measured in bits) of the current word.
296
+ offset : usize ,
297
+
298
+ /// Underlying iterator over the words.
299
+ iter : slice:: Iter < ' a , Word > ,
300
+
292
301
marker : PhantomData < T >
293
302
}
294
303
295
304
impl < ' a , T : Idx > BitIter < ' a , T > {
296
305
#[ inline]
297
306
fn new ( words : & ' a [ Word ] ) -> BitIter < ' a , T > {
307
+ // We initialize `word` and `offset` to degenerate values. On the first
308
+ // call to `next()` we will fall through to getting the first word from
309
+ // `iter`, which sets `word` to the first word (if there is one) and
310
+ // `offset` to 0. Doing it this way saves us from having to maintain
311
+ // additional state about whether we have started.
298
312
BitIter {
299
- cur : None ,
300
- iter : words. iter ( ) . enumerate ( ) ,
313
+ word : 0 ,
314
+ offset : std:: usize:: MAX - ( WORD_BITS - 1 ) ,
315
+ iter : words. iter ( ) ,
301
316
marker : PhantomData ,
302
317
}
303
318
}
@@ -307,17 +322,20 @@ impl<'a, T: Idx> Iterator for BitIter<'a, T> {
307
322
type Item = T ;
308
323
fn next ( & mut self ) -> Option < T > {
309
324
loop {
310
- if let Some ( ( ref mut word, offset ) ) = self . cur {
311
- let bit_pos = word . trailing_zeros ( ) as usize ;
312
- if bit_pos != WORD_BITS {
313
- let bit = 1 << bit_pos ;
314
- * word ^= bit ;
315
- return Some ( T :: new ( bit_pos + offset ) )
316
- }
325
+ if self . word != 0 {
326
+ // Get the position of the next set bit in the current word,
327
+ // then clear the bit.
328
+ let bit_pos = self . word . trailing_zeros ( ) as usize ;
329
+ let bit = 1 << bit_pos ;
330
+ self . word ^= bit ;
331
+ return Some ( T :: new ( bit_pos + self . offset ) )
317
332
}
318
333
319
- let ( i, word) = self . iter . next ( ) ?;
320
- self . cur = Some ( ( * word, WORD_BITS * i) ) ;
334
+ // Move onto the next word. `wrapping_add()` is needed to handle
335
+ // the degenerate initial value given to `offset` in `new()`.
336
+ let word = self . iter . next ( ) ?;
337
+ self . word = * word;
338
+ self . offset = self . offset . wrapping_add ( WORD_BITS ) ;
321
339
}
322
340
}
323
341
}
0 commit comments