diff --git a/src/bitmap/utils/chunk_iterator/mod.rs b/src/bitmap/utils/chunk_iterator/mod.rs index 26df6ee8273..b896b1a6662 100644 --- a/src/bitmap/utils/chunk_iterator/mod.rs +++ b/src/bitmap/utils/chunk_iterator/mod.rs @@ -31,11 +31,9 @@ pub struct BitChunks<'a, T: BitChunk> { /// writes `bytes` into `dst`. #[inline] fn copy_with_merge(dst: &mut T::Bytes, bytes: &[u8], bit_offset: usize) { - let mut last = bytes[bytes.len() - 1]; - last >>= bit_offset; - dst[0] = last; bytes .windows(2) + .chain(std::iter::once([bytes[bytes.len() - 1], 0].as_ref())) .take(std::mem::size_of::()) .enumerate() .for_each(|(i, w)| { @@ -340,4 +338,23 @@ mod tests { assert_eq!(iter.next(), None); assert_eq!(iter.remainder(), 0b1_1111_1111u64); } + + #[test] + fn remainder_2() { + // (i % 3 == 0) in bitmap + let input: &[u8] = &[ + 0b01001001, 0b10010010, 0b00100100, 0b01001001, 0b10010010, 0b00100100, 0b01001001, + 0b10010010, 0b00100100, 0b01001001, /* 73 */ + 0b10010010, /* 146 */ + 0b00100100, 0b00001001, + ]; + let offset = 10; // 8 + 2 + let length = 90; + + let mut iter = BitChunks::::new(input, offset, length); + let first: u64 = 0b0100100100100100100100100100100100100100100100100100100100100100; + assert_eq!(first, iter.next().unwrap()); + assert_eq!(iter.next(), None); + assert_eq!(iter.remainder(), 0b10010010010010010010010010u64); + } } diff --git a/src/bitmap/utils/mod.rs b/src/bitmap/utils/mod.rs index db284b28d76..538c193b0b2 100644 --- a/src/bitmap/utils/mod.rs +++ b/src/bitmap/utils/mod.rs @@ -65,6 +65,8 @@ pub fn bytes_for(bits: usize) -> usize { #[inline] pub fn null_count(slice: &[u8], offset: usize, len: usize) -> usize { + //return BitmapIter::new(slice, offset, len).filter(|x| !*x).count(); + // u64 results in optimal performance (verified via benches) let mut chunks = chunk_iterator::BitChunks::::new(slice, offset, len); @@ -138,4 +140,11 @@ mod tests { assert_eq!(null_count(input, 13, 2), 1); assert_eq!(null_count(input, 14, 2), 1); } + + #[test] + fn null_count_1() { + // offset = 10, len = 90 => remainder + let input: &[u8] = &[73, 146, 36, 73, 146, 36, 73, 146, 36, 73, 146, 36, 9]; + assert_eq!(null_count(input, 10, 90), 60); + } }