@@ -8,6 +8,7 @@ pub struct ByteMask(pub [u64; 4]);
88
99impl ByteMask {
1010 pub const EMPTY : ByteMask = Self ( empty_mask ( ) ) ;
11+ pub const FULL : ByteMask = Self ( [ !0u64 ; 4 ] ) ;
1112
1213 /// Create a new empty ByteMask
1314 #[ inline]
@@ -90,7 +91,7 @@ impl ByteMask {
9091 }
9192
9293 /// Returns the bit in the mask corresponding to the next highest bit above `byte`, or `None`
93- /// if `byte` was the highest set bit in the mask
94+ /// if `byte` was at or above the highest set bit in the mask
9495 pub fn next_bit ( & self , byte : u8 ) -> Option < u8 > {
9596 if byte == 255 {
9697 return None
@@ -130,6 +131,48 @@ impl ByteMask {
130131 }
131132 None
132133 }
134+
135+ /// Returns the bit in the mask corresponding to the previous bit below `byte`, or `None`
136+ /// if `byte` was at or below the lowest set bit in the mask
137+ pub fn prev_bit ( & self , byte : u8 ) -> Option < u8 > {
138+ if byte == 0 {
139+ return None
140+ }
141+ let byte = byte - 1 ;
142+ let word_idx = byte >> 6 ;
143+ let mod_idx = byte & 0x3F ;
144+ let mut mask = !0u64 >> ( 63 - mod_idx) ;
145+ if word_idx == 3 {
146+ let cnt = ( self . 0 [ 3 ] & mask) . leading_zeros ( ) as u8 ;
147+ if cnt < 64 {
148+ return Some ( 255 - cnt)
149+ }
150+ mask = !0u64 ;
151+ }
152+ if word_idx > 1 {
153+ let cnt = ( self . 0 [ 2 ] & mask) . leading_zeros ( ) as u8 ;
154+ if cnt < 64 {
155+ return Some ( 191 - cnt)
156+ }
157+ if word_idx == 2 {
158+ mask = !0u64 ;
159+ }
160+ }
161+ if word_idx > 0 {
162+ let cnt = ( self . 0 [ 1 ] & mask) . leading_zeros ( ) as u8 ;
163+ if cnt < 64 {
164+ return Some ( 127 - cnt)
165+ }
166+ if word_idx == 1 {
167+ mask = !0u64 ;
168+ }
169+ }
170+ let cnt = ( self . 0 [ 0 ] & mask) . leading_zeros ( ) as u8 ;
171+ if cnt < 64 {
172+ return Some ( 63 - cnt)
173+ }
174+ None
175+ }
133176}
134177
135178impl core:: fmt:: Debug for ByteMask {
@@ -548,22 +591,41 @@ fn bit_utils_test() {
548591
549592#[ test]
550593fn next_bit_test ( ) {
551- let test_mask = ByteMask :: from ( [
552- 0b1010010010010010010010000000000000000000000000000000000000010101u64 ,
553- 0b0000000000000000000000000000000000000000100000000000000000000000u64 ,
554- 0b0000000000000000000000000000000000000000000000000000000000000000u64 ,
555- 0b1000000000000000000000000000010000000000000000000000000000000001u64 ,
556- ] ) ;
557- let set_bits: Vec < u8 > = ( 0 ..=255 ) . into_iter ( ) . filter ( |i| test_mask. test_bit ( * i) ) . collect ( ) ;
558-
559- let mut i = 0 ;
560- let mut cnt = test_mask. test_bit ( 0 ) as usize ;
561- while let Some ( next_bit) = test_mask. next_bit ( i) {
562- assert ! ( test_mask. test_bit( next_bit) ) ;
563- i = next_bit;
564- cnt += 1 ;
565- }
566- assert_eq ! ( cnt, set_bits. len( ) ) ;
594+ fn do_test ( test_mask : ByteMask ) {
595+ let set_bits: Vec < u8 > = ( 0 ..=255 ) . into_iter ( ) . filter ( |i| test_mask. test_bit ( * i) ) . collect ( ) ;
596+
597+ let mut i = 0 ;
598+ let mut cnt = test_mask. test_bit ( 0 ) as usize ;
599+ while let Some ( next_bit) = test_mask. next_bit ( i) {
600+ assert ! ( test_mask. test_bit( next_bit) ) ;
601+ i = next_bit;
602+ cnt += 1 ;
603+ }
604+ assert_eq ! ( cnt, set_bits. len( ) ) ;
605+
606+ let mut i = 255 ;
607+ let mut cnt = test_mask. test_bit ( 255 ) as usize ;
608+ while let Some ( prev_bit) = test_mask. prev_bit ( i) {
609+ assert ! ( test_mask. test_bit( prev_bit) ) ;
610+ i = prev_bit;
611+ cnt += 1 ;
612+ }
613+ assert_eq ! ( cnt, set_bits. len( ) ) ;
614+ }
615+
616+ // do_test(ByteMask::from([
617+ // 0b1010010010010010010010000000000000000000000000000000000000010101u64,
618+ // 0b0000000000000000000000000000000000000000100000000000000000000000u64,
619+ // 0b0000000000000000000000000000000000000000000000000000000000000000u64,
620+ // 0b1001000000000000000000000000000000000000000000000000000000000001u64,
621+ // ]));
622+ // do_test(ByteMask::from([
623+ // 0b0000000000000000000000000000000000000000000000000000000000000000u64,
624+ // 0b0000000000000000000000000000000000000000100000000000000000000000u64,
625+ // 0b0000000000000000000000000000000000000000000000000000000000000000u64,
626+ // 0b1001000000000000000000000000000000000000000000000000000000000001u64,
627+ // ]));
628+ do_test ( ByteMask :: from ( ByteMask :: FULL ) ) ;
567629}
568630
569631#[ test]
0 commit comments