Skip to content

Commit d7e9aec

Browse files
committed
Cut down lots of repetitive, and not very informative, comments.
This stuff mostly dates from when I was trying to get my head around what such iterators should be. Some of the comments are of negligible use; some are so blindingly obvious that I'm not sure why I ever put them in!
1 parent f9372b4 commit d7e9aec

File tree

1 file changed

+4
-25
lines changed

1 file changed

+4
-25
lines changed

src/lib.rs

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,10 @@ impl<'a, T: Debug + PrimInt> IntoIterator for &'a Vob<T> {
11011101
}
11021102
}
11031103

1104+
// In all of the iterators below, we try to optimise what we expect to be the common cases (all
1105+
// bits set or all bits unset) with the general case (random bit patterns). We assume that
1106+
// `leading_zeros` and `trailing_zeros` have efficient implementations on most CPUs.
1107+
11041108
#[derive(Clone)]
11051109
pub struct IterSetBits<'a, T: 'a> {
11061110
vob: &'a Vob<T>,
@@ -1113,24 +1117,15 @@ impl<T: Debug + PrimInt> Iterator for IterSetBits<'_, T> {
11131117
fn next(&mut self) -> Option<usize> {
11141118
debug_assert!(self.range.end <= self.vob.len);
11151119
if let Some(i) = self.range.next() {
1116-
// This is a long, but fairly fast, way of finding out what the next set bit is. The
1117-
// basic problem is that we have no idea where the next set bit is -- but different
1118-
// patterns of set bits are most efficiently handled by different code paths. This code
1119-
// is thus a compromise: we prioritise two special cases (all bits set; all bits unset)
1120-
// for efficiency, and try and make the other possible cases reasonably fast.
11211120
let mut b = block_offset::<T>(i);
11221121
let mut v = self.vob.vec[b];
1123-
// If all bits are set, we don't need to do any complicated checks.
11241122
if v == T::max_value() {
11251123
return Some(i);
11261124
}
1127-
// At this point we've got a block which might or might not have some bits set. We now
1128-
// fall back to the general case.
11291125
let mut i_off = i % bits_per_block::<T>();
11301126
loop {
11311127
let tz = (v >> i_off).trailing_zeros() as usize;
11321128
if tz < bits_per_block::<T>() {
1133-
// There is a bit set after i_off in the block.
11341129
let bs = b * bits_per_block::<T>() + i_off + tz;
11351130
self.range.start = bs + 1;
11361131
if bs >= self.range.end {
@@ -1140,7 +1135,6 @@ impl<T: Debug + PrimInt> Iterator for IterSetBits<'_, T> {
11401135
}
11411136
b += 1;
11421137
if b == blocks_required::<T>(self.range.end) {
1143-
// We've exhausted the iterator.
11441138
self.range.start = self.range.end;
11451139
break;
11461140
}
@@ -1161,12 +1155,9 @@ impl<T: Debug + PrimInt> DoubleEndedIterator for IterSetBits<'_, T> {
11611155
if let Some(i) = self.range.next_back() {
11621156
let mut b = block_offset::<T>(i);
11631157
let mut v = self.vob.vec[b];
1164-
// If all bits are set, we don't need to do any complicated checks.
11651158
if v == T::max_value() {
11661159
return Some(i);
11671160
}
1168-
// At this point we've got a block which might or might not have some bits set. We now
1169-
// fall back to the general case.
11701161
let mut i_off = i % bits_per_block::<T>();
11711162
loop {
11721163
let lz = (v << (bits_per_block::<T>() - 1 - i_off)).leading_zeros() as usize;
@@ -1179,7 +1170,6 @@ impl<T: Debug + PrimInt> DoubleEndedIterator for IterSetBits<'_, T> {
11791170
return Some(bs);
11801171
}
11811172
if b == block_offset::<T>(self.range.start) {
1182-
// We've exhausted the iterator.
11831173
self.range.start = self.range.end;
11841174
break;
11851175
}
@@ -1204,19 +1194,11 @@ impl<T: Debug + PrimInt> Iterator for IterUnsetBits<'_, T> {
12041194
fn next(&mut self) -> Option<usize> {
12051195
debug_assert!(self.range.end <= self.vob.len);
12061196
if let Some(i) = self.range.next() {
1207-
// This is a long, but fairly fast, way of finding out what the next usset bit is. The
1208-
// basic problem is that we have no idea where the next set bit is -- but different
1209-
// patterns of set bits are most efficiently handled by different code paths. This code
1210-
// is thus a compromise: we prioritise two special cases (all bits set; all bits unset)
1211-
// for efficiency, and try and make the other possible cases reasonably fast.
12121197
let mut b = block_offset::<T>(i);
12131198
let mut v = self.vob.vec[b];
1214-
// If no bits are set, we don't need to do any complicated checks.
12151199
if v == T::zero() {
12161200
return Some(i);
12171201
}
1218-
// At this point we've got a block which might or might not have some bits unset. We
1219-
// now fall back to the general case.
12201202
let mut i_off = i % bits_per_block::<T>();
12211203
loop {
12221204
let tz = (!v >> i_off).trailing_zeros() as usize;
@@ -1225,15 +1207,12 @@ impl<T: Debug + PrimInt> Iterator for IterUnsetBits<'_, T> {
12251207
let bs = b * bits_per_block::<T>() + i_off + tz;
12261208
self.range.start = bs + 1;
12271209
if bs >= self.range.end {
1228-
// The unset bit is after the range we're looking for, so we've reached
1229-
// the end of the iterator.
12301210
break;
12311211
}
12321212
return Some(bs);
12331213
}
12341214
b += 1;
12351215
if b == blocks_required::<T>(self.range.end) {
1236-
// We've exhausted the iterator.
12371216
self.range.start = self.range.end;
12381217
break;
12391218
}

0 commit comments

Comments
 (0)