@@ -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 ) ]
11051109pub 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