1use crate::bit_chunk_iterator::BitChunks;
21
22#[inline]
57pub fn compress(value: u64, mask: u64) -> u64 {
58 #[cfg(all(target_arch = "x86_64", target_feature = "bmi2"))]
59 {
60 unsafe { std::arch::x86_64::_pext_u64(value, mask) }
63 }
64
65 #[cfg(not(all(target_arch = "x86_64", target_feature = "bmi2")))]
66 {
67 let mut mask = mask;
68 let mut result = 0_u64;
69 let mut dest_bit = 1_u64;
70 while mask != 0 {
71 let rest = mask & (mask - 1);
74 let lowest = mask ^ rest;
75 let keep = ((value & lowest) != 0) as u64;
76 result |= dest_bit & keep.wrapping_neg();
77 dest_bit <<= 1;
78 mask = rest;
79 }
80 result
81 }
82}
83
84#[inline]
119pub fn expand(value: u64, mask: u64) -> u64 {
120 #[cfg(all(target_arch = "x86_64", target_feature = "bmi2"))]
121 {
122 unsafe { std::arch::x86_64::_pdep_u64(value, mask) }
125 }
126
127 #[cfg(not(all(target_arch = "x86_64", target_feature = "bmi2")))]
128 {
129 let mut value = value;
130 if value == 0 {
131 return 0;
132 }
133
134 let mut zeros = !mask;
135 if zeros.count_ones() <= 32 {
136 while zeros != 0 {
138 let lower = (1_u64 << zeros.trailing_zeros()) - 1;
139 value = (value & lower) | ((value & !lower) << 1);
140 zeros &= zeros - 1;
141 }
142 value
143 } else {
144 let mut output = 0;
145 let mut ones = mask;
146 while ones != 0 {
147 output |= (value & 1) << ones.trailing_zeros();
148 value >>= 1;
149 ones &= ones - 1;
150 }
151 output
152 }
153 }
154}
155
156#[inline]
162pub fn round_upto_multiple_of_64(num: usize) -> usize {
163 num.checked_next_multiple_of(64)
164 .expect("failed to round upto multiple of 64")
165}
166
167pub fn round_upto_power_of_2(num: usize, factor: usize) -> usize {
174 debug_assert!(factor > 0 && factor.is_power_of_two());
175 num.checked_add(factor - 1)
176 .expect("failed to round to next highest power of 2")
177 & !(factor - 1)
178}
179
180#[inline]
186pub fn get_bit(data: &[u8], i: usize) -> bool {
187 data[i / 8] & (1 << (i % 8)) != 0
188}
189
190#[inline]
197pub unsafe fn get_bit_raw(data: *const u8, i: usize) -> bool {
198 unsafe { (*data.add(i / 8) & (1 << (i % 8))) != 0 }
199}
200
201#[inline]
207pub fn set_bit(data: &mut [u8], i: usize) {
208 data[i / 8] |= 1 << (i % 8);
209}
210
211#[inline]
218pub unsafe fn set_bit_raw(data: *mut u8, i: usize) {
219 unsafe {
220 *data.add(i / 8) |= 1 << (i % 8);
221 }
222}
223
224#[inline]
230pub fn unset_bit(data: &mut [u8], i: usize) {
231 data[i / 8] &= !(1 << (i % 8));
232}
233
234#[inline]
241pub unsafe fn unset_bit_raw(data: *mut u8, i: usize) {
242 unsafe {
243 *data.add(i / 8) &= !(1 << (i % 8));
244 }
245}
246
247#[inline]
249pub fn ceil(value: usize, divisor: usize) -> usize {
250 value.div_ceil(divisor)
251}
252
253#[inline]
255pub(crate) fn read_u64(input: &[u8]) -> u64 {
256 let len = input.len().min(8);
257 let mut buf = [0_u8; 8];
258 buf[..len].copy_from_slice(input);
259 u64::from_le_bytes(buf)
260}
261
262#[inline]
280pub(crate) fn read_up_to_byte_from_offset(
281 slice: &[u8],
282 number_of_bits_to_read: usize,
283 bit_offset: usize,
284) -> u8 {
285 assert!(number_of_bits_to_read < 8, "can read up to 8 bits only");
286 assert!(bit_offset < 8, "bit offset must be less than 8");
287 assert_ne!(
288 number_of_bits_to_read, 0,
289 "number of bits to read must be greater than 0"
290 );
291 assert_ne!(slice.len(), 0, "slice must not be empty");
292
293 let number_of_bytes_to_read = ceil(number_of_bits_to_read + bit_offset, 8);
294
295 assert!(slice.len() >= number_of_bytes_to_read, "slice is too small");
297
298 let mut bits = slice[0] >> bit_offset;
299 for (i, &byte) in slice
300 .iter()
301 .take(number_of_bytes_to_read)
302 .enumerate()
303 .skip(1)
304 {
305 bits |= byte << (i * 8 - bit_offset);
306 }
307
308 bits & ((1 << number_of_bits_to_read) - 1)
309}
310
311pub fn apply_bitwise_binary_op<F>(
358 left: &mut [u8],
359 left_offset_in_bits: usize,
360 right: impl AsRef<[u8]>,
361 right_offset_in_bits: usize,
362 len_in_bits: usize,
363 mut op: F,
364) where
365 F: FnMut(u64, u64) -> u64,
366{
367 if len_in_bits == 0 {
368 return;
369 }
370
371 let bit_offset = left_offset_in_bits % 8;
373
374 let is_mutable_buffer_byte_aligned = bit_offset == 0;
375
376 if is_mutable_buffer_byte_aligned {
377 byte_aligned_bitwise_bin_op_helper(
378 left,
379 left_offset_in_bits,
380 right,
381 right_offset_in_bits,
382 len_in_bits,
383 op,
384 );
385 } else {
386 let bits_to_next_byte = (8 - bit_offset)
388 .min(len_in_bits);
391
392 {
393 let right_byte_offset = right_offset_in_bits / 8;
394
395 let right_first_byte = crate::util::bit_util::read_up_to_byte_from_offset(
397 &right.as_ref()[right_byte_offset..],
398 bits_to_next_byte,
399 right_offset_in_bits % 8,
401 );
402
403 align_to_byte(
404 left,
405 &mut |left| op(left, right_first_byte as u64),
407 left_offset_in_bits,
408 bits_to_next_byte,
409 );
410 }
411
412 let offset_in_bits = left_offset_in_bits + bits_to_next_byte;
413 let right_offset_in_bits = right_offset_in_bits + bits_to_next_byte;
414 let len_in_bits = len_in_bits.saturating_sub(bits_to_next_byte);
415
416 if len_in_bits == 0 {
417 return;
418 }
419
420 byte_aligned_bitwise_bin_op_helper(
422 left,
423 offset_in_bits,
424 right,
425 right_offset_in_bits,
426 len_in_bits,
427 op,
428 );
429 }
430}
431
432pub fn apply_bitwise_unary_op<F>(
472 buffer: &mut [u8],
473 offset_in_bits: usize,
474 len_in_bits: usize,
475 mut op: F,
476) where
477 F: FnMut(u64) -> u64,
478{
479 if len_in_bits == 0 {
480 return;
481 }
482
483 let left_bit_offset = offset_in_bits % 8;
485
486 let is_mutable_buffer_byte_aligned = left_bit_offset == 0;
487
488 if is_mutable_buffer_byte_aligned {
489 byte_aligned_bitwise_unary_op_helper(buffer, offset_in_bits, len_in_bits, op);
490 } else {
491 align_to_byte(buffer, &mut op, offset_in_bits, len_in_bits);
492
493 let bits_to_next_byte = 8 - left_bit_offset;
495
496 let offset_in_bits = offset_in_bits + bits_to_next_byte;
497 let len_in_bits = len_in_bits.saturating_sub(bits_to_next_byte);
498
499 if len_in_bits == 0 {
500 return;
501 }
502
503 byte_aligned_bitwise_unary_op_helper(buffer, offset_in_bits, len_in_bits, op);
505 }
506}
507
508#[inline]
522fn byte_aligned_bitwise_bin_op_helper<F>(
523 left: &mut [u8],
524 left_offset_in_bits: usize,
525 right: impl AsRef<[u8]>,
526 right_offset_in_bits: usize,
527 len_in_bits: usize,
528 mut op: F,
529) where
530 F: FnMut(u64, u64) -> u64,
531{
532 assert_eq!(
534 left_offset_in_bits % 8,
535 0,
536 "offset_in_bits must be byte aligned"
537 );
538
539 let (complete_u64_chunks, remainder_bytes) =
541 U64UnalignedSlice::split(left, left_offset_in_bits, len_in_bits);
542
543 let right_chunks = BitChunks::new(right.as_ref(), right_offset_in_bits, len_in_bits);
544 assert_eq!(
545 self::ceil(right_chunks.remainder_len(), 8),
546 remainder_bytes.len()
547 );
548
549 let right_chunks_iter = right_chunks.iter();
550 assert_eq!(right_chunks_iter.len(), complete_u64_chunks.len());
551
552 complete_u64_chunks.zip_modify(right_chunks_iter, &mut op);
554
555 if right_chunks.remainder_len() > 0 {
557 handle_mutable_buffer_remainder(
558 &mut op,
559 remainder_bytes,
560 right_chunks.remainder_bits(),
561 right_chunks.remainder_len(),
562 )
563 }
564}
565
566#[inline]
578fn byte_aligned_bitwise_unary_op_helper<F>(
579 buffer: &mut [u8],
580 offset_in_bits: usize,
581 len_in_bits: usize,
582 mut op: F,
583) where
584 F: FnMut(u64) -> u64,
585{
586 assert_eq!(offset_in_bits % 8, 0, "offset_in_bits must be byte aligned");
588
589 let remainder_len = len_in_bits % 64;
590
591 let (complete_u64_chunks, remainder_bytes) =
592 U64UnalignedSlice::split(buffer, offset_in_bits, len_in_bits);
593
594 assert_eq!(self::ceil(remainder_len, 8), remainder_bytes.len());
595
596 complete_u64_chunks.apply_unary_op(&mut op);
598
599 if remainder_len > 0 {
601 handle_mutable_buffer_remainder_unary(&mut op, remainder_bytes, remainder_len)
602 }
603}
604
605fn align_to_byte<F>(
619 buffer: &mut [u8],
620 op: &mut F,
621 offset_in_bits: usize,
622 remaining_len_in_bits: usize,
623) where
624 F: FnMut(u64) -> u64,
625{
626 let byte_offset = offset_in_bits / 8;
627 let bit_offset = offset_in_bits % 8;
628
629 debug_assert_ne!(bit_offset, 0, "offset_in_bits must not be byte aligned");
631
632 let first_byte: u8 = buffer[byte_offset];
634
635 let relevant_first_byte = first_byte >> bit_offset;
637
638 let result_first_byte = op(relevant_first_byte as u64) as u8;
640
641 let result_first_byte = result_first_byte << bit_offset;
643
644 let bits_in_this_byte = (8 - bit_offset).min(remaining_len_in_bits);
651 let write_mask = ((1u8 << bits_in_this_byte) - 1) << bit_offset;
652
653 let result_first_byte = (first_byte & !write_mask) | (result_first_byte & write_mask);
654
655 buffer[byte_offset] = result_first_byte;
657}
658
659struct U64UnalignedSlice<'a> {
671 ptr: *mut u64,
675
676 len: usize,
678
679 _marker: std::marker::PhantomData<&'a u8>,
681}
682
683impl<'a> U64UnalignedSlice<'a> {
684 fn split(
689 buffer: &'a mut [u8],
690 offset_in_bits: usize,
691 len_in_bits: usize,
692 ) -> (Self, &'a mut [u8]) {
693 let left_buffer_mut: &mut [u8] = {
695 let last_offset = self::ceil(offset_in_bits + len_in_bits, 8);
696 assert!(last_offset <= buffer.len());
697
698 let byte_offset = offset_in_bits / 8;
699
700 &mut buffer[byte_offset..last_offset]
701 };
702
703 let number_of_u64_we_can_fit = len_in_bits / (u64::BITS as usize);
704
705 let u64_len_in_bytes = number_of_u64_we_can_fit * size_of::<u64>();
707
708 assert!(u64_len_in_bytes <= left_buffer_mut.len());
709 let (bytes_for_u64, remainder) = left_buffer_mut.split_at_mut(u64_len_in_bytes);
710
711 #[expect(
712 clippy::cast_ptr_alignment,
713 reason = "`U64UnalignedSlice` only reads and writes through the unaligned methods"
714 )]
715 let ptr = bytes_for_u64.as_mut_ptr().cast::<u64>();
716
717 let this = Self {
718 ptr,
719 len: number_of_u64_we_can_fit,
720 _marker: std::marker::PhantomData,
721 };
722
723 (this, remainder)
724 }
725
726 fn len(&self) -> usize {
727 self.len
728 }
729
730 fn zip_modify(
733 mut self,
734 mut zip_iter: impl ExactSizeIterator<Item = u64>,
735 mut map: impl FnMut(u64, u64) -> u64,
736 ) {
737 assert_eq!(self.len, zip_iter.len());
738
739 if let Some(right) = zip_iter.next() {
744 unsafe {
747 self.apply_bin_op(right, &mut map);
748 }
749
750 }
752
753 for right in zip_iter {
754 self.ptr = unsafe { self.ptr.add(1) };
758
759 unsafe {
761 self.apply_bin_op(right, &mut map);
762 }
763
764 }
766 }
767
768 #[inline]
774 unsafe fn apply_bin_op(&mut self, right: u64, mut map: impl FnMut(u64, u64) -> u64) {
775 let current_input = unsafe {
778 self.ptr
779 .read_unaligned()
781 .to_le()
784 };
785
786 let combined = map(current_input, right);
787
788 unsafe { self.ptr.write_unaligned(combined) }
793 }
794
795 fn apply_unary_op(mut self, mut map: impl FnMut(u64) -> u64) {
797 if self.len == 0 {
798 return;
799 }
800
801 unsafe {
808 self.apply_bin_op(0, &mut |left, _| map(left));
810
811 }
813
814 for _ in 1..self.len {
815 self.ptr = unsafe { self.ptr.add(1) };
819
820 unsafe {
822 self.apply_bin_op(0, &mut |left, _| map(left));
824 }
825
826 }
828 }
829}
830
831#[inline]
844fn handle_mutable_buffer_remainder<F>(
845 op: &mut F,
846 start_remainder_mut_slice: &mut [u8],
847 right_remainder_bits: u64,
848 remainder_len: usize,
849) where
850 F: FnMut(u64, u64) -> u64,
851{
852 let left_remainder_bits = get_remainder_bits(start_remainder_mut_slice, remainder_len);
854
855 let rem = op(left_remainder_bits, right_remainder_bits);
857
858 set_remainder_bits(start_remainder_mut_slice, rem, remainder_len);
860}
861
862#[inline]
874fn set_remainder_bits(start_remainder_mut_slice: &mut [u8], rem: u64, remainder_len: usize) {
875 assert_ne!(
876 start_remainder_mut_slice.len(),
877 0,
878 "start_remainder_mut_slice must not be empty"
879 );
880 assert!(remainder_len < 64, "remainder_len must be less than 64");
881
882 assert_eq!(
885 start_remainder_mut_slice.len(),
886 self::ceil(remainder_len, 8),
887 "start_remainder_mut_slice length must be equal to ceil(remainder_len, 8)"
888 );
889
890 let rem = {
896 let current = start_remainder_mut_slice
901 .last()
902 .unwrap();
904
905 let current = (*current as u64) << ((start_remainder_mut_slice.len() - 1) * 8);
908
909 let inside_remainder_mask = (1 << remainder_len) - 1;
912 let outside_remainder_mask = !inside_remainder_mask;
915
916 let current = current & outside_remainder_mask;
918
919 let rem = rem & inside_remainder_mask;
921
922 current | rem
924 };
925
926 {
928 let remainder_bytes = start_remainder_mut_slice.len();
929
930 let rem = &rem.to_le_bytes()[0..remainder_bytes];
932
933 let src = rem.as_ptr();
937 unsafe {
941 std::ptr::copy_nonoverlapping(
942 src,
943 start_remainder_mut_slice.as_mut_ptr(),
944 remainder_bytes,
945 )
946 };
947 }
948}
949
950#[inline]
963fn get_remainder_bits(remainder: &[u8], remainder_len: usize) -> u64 {
964 assert!(remainder.len() < 64, "remainder_len must be less than 64");
965 assert_eq!(
966 remainder.len(),
967 self::ceil(remainder_len, 8),
968 "remainder and remainder len ceil must be the same"
969 );
970
971 let bits = remainder
972 .iter()
973 .enumerate()
974 .fold(0_u64, |acc, (index, &byte)| {
975 acc | ((byte as u64) << (index * 8))
976 });
977
978 bits & ((1 << remainder_len) - 1)
979}
980
981#[inline]
992fn handle_mutable_buffer_remainder_unary<F>(
993 op: &mut F,
994 start_remainder_mut: &mut [u8],
995 remainder_len: usize,
996) where
997 F: FnMut(u64) -> u64,
998{
999 let left_remainder_bits = get_remainder_bits(start_remainder_mut, remainder_len);
1001
1002 let rem = op(left_remainder_bits);
1004
1005 set_remainder_bits(start_remainder_mut, rem, remainder_len);
1007}
1008
1009#[cfg(test)]
1010mod tests {
1011 use std::collections::HashSet;
1012
1013 use super::*;
1014 use crate::bit_iterator::BitIterator;
1015 use crate::{BooleanBuffer, BooleanBufferBuilder, MutableBuffer};
1016 use rand::rngs::StdRng;
1017 use rand::{RngExt, SeedableRng};
1018
1019 #[test]
1020 fn test_compress() {
1021 fn reference(value: u64, mask: u64) -> u64 {
1024 (0..64)
1025 .filter(|&i| (mask >> i) & 1 == 1)
1026 .enumerate()
1027 .map(|(dest, i)| ((value >> i) & 1) << dest)
1028 .sum()
1029 }
1030
1031 assert_eq!(compress(0b1010, 0b1111), 0b1010);
1032 assert_eq!(compress(0b1010, 0b1010), 0b11);
1033 assert_eq!(compress(0b1010, 0b0101), 0);
1034 assert_eq!(compress(u64::MAX, 0), 0);
1035 assert_eq!(compress(0, u64::MAX), 0);
1036 assert_eq!(compress(u64::MAX, u64::MAX), u64::MAX);
1037
1038 let mut rng = StdRng::seed_from_u64(42);
1041 for _ in 0..1024 {
1042 let (value, mask): (u64, u64) = rng.random();
1043 assert_eq!(
1044 compress(value, mask),
1045 reference(value, mask),
1046 "value={value:#x} mask={mask:#x}"
1047 );
1048 }
1049 }
1050
1051 #[test]
1052 fn test_expand() {
1053 fn reference(values: u64, mask: u64) -> u64 {
1054 let mut expected = 0;
1055 let mut input_idx = 0;
1056 for output_idx in 0..64 {
1057 if mask & (1 << output_idx) != 0 {
1058 expected |= ((values >> input_idx) & 1) << output_idx;
1059 input_idx += 1;
1060 }
1061 }
1062 expected
1063 }
1064
1065 assert_eq!(expand(0b1010, 0b1111), 0b1010);
1066 assert_eq!(expand(0b11, 0b1010), 0b1010);
1067 assert_eq!(expand(u64::MAX, 0), 0);
1068 assert_eq!(expand(0, u64::MAX), 0);
1069 assert_eq!(expand(0, 0x5555_5555_5555_5555), 0);
1070 assert_eq!(expand(u64::MAX, u64::MAX), u64::MAX);
1071
1072 let mut rng = StdRng::seed_from_u64(0x2b7e_1516_28ae_d2a6);
1073
1074 for bit in 0..64 {
1076 for mask in [u64::MAX, !(1 << bit), 1 << bit, 0] {
1077 for _ in 0..16 {
1078 let values = rng.random::<u64>();
1079 assert_eq!(expand(values, mask), reference(values, mask), "{mask:#x}");
1080 }
1081 }
1082 }
1083
1084 for _ in 0..20_000 {
1087 let density = rng.random_range(0.0..=1.0);
1088 let mask = (0..64).fold(0_u64, |mask, bit| {
1089 mask | ((rng.random_bool(density) as u64) << bit)
1090 });
1091 let values = rng.random::<u64>();
1092 assert_eq!(expand(compress(values, mask), mask), values & mask);
1093 assert_eq!(expand(values, mask), reference(values, mask), "{mask:#x}");
1094 }
1095 }
1096
1097 #[test]
1098 fn test_round_upto_multiple_of_64() {
1099 assert_eq!(0, round_upto_multiple_of_64(0));
1100 assert_eq!(64, round_upto_multiple_of_64(1));
1101 assert_eq!(64, round_upto_multiple_of_64(63));
1102 assert_eq!(64, round_upto_multiple_of_64(64));
1103 assert_eq!(128, round_upto_multiple_of_64(65));
1104 assert_eq!(192, round_upto_multiple_of_64(129));
1105 }
1106
1107 #[test]
1108 #[should_panic(expected = "failed to round upto multiple of 64")]
1109 fn test_round_upto_multiple_of_64_panic() {
1110 let _ = round_upto_multiple_of_64(usize::MAX);
1111 }
1112
1113 #[test]
1114 #[should_panic(expected = "failed to round to next highest power of 2")]
1115 fn test_round_upto_panic() {
1116 let _ = round_upto_power_of_2(usize::MAX, 2);
1117 }
1118
1119 #[test]
1120 fn test_get_bit() {
1121 assert!(get_bit(&[0b00001101], 0));
1123 assert!(!get_bit(&[0b00001101], 1));
1124 assert!(get_bit(&[0b00001101], 2));
1125 assert!(get_bit(&[0b00001101], 3));
1126
1127 assert!(get_bit(&[0b01001001, 0b01010010], 0));
1129 assert!(!get_bit(&[0b01001001, 0b01010010], 1));
1130 assert!(!get_bit(&[0b01001001, 0b01010010], 2));
1131 assert!(get_bit(&[0b01001001, 0b01010010], 3));
1132 assert!(!get_bit(&[0b01001001, 0b01010010], 4));
1133 assert!(!get_bit(&[0b01001001, 0b01010010], 5));
1134 assert!(get_bit(&[0b01001001, 0b01010010], 6));
1135 assert!(!get_bit(&[0b01001001, 0b01010010], 7));
1136 assert!(!get_bit(&[0b01001001, 0b01010010], 8));
1137 assert!(get_bit(&[0b01001001, 0b01010010], 9));
1138 assert!(!get_bit(&[0b01001001, 0b01010010], 10));
1139 assert!(!get_bit(&[0b01001001, 0b01010010], 11));
1140 assert!(get_bit(&[0b01001001, 0b01010010], 12));
1141 assert!(!get_bit(&[0b01001001, 0b01010010], 13));
1142 assert!(get_bit(&[0b01001001, 0b01010010], 14));
1143 assert!(!get_bit(&[0b01001001, 0b01010010], 15));
1144 }
1145
1146 pub fn seedable_rng() -> StdRng {
1147 StdRng::seed_from_u64(42)
1148 }
1149
1150 #[test]
1151 fn test_get_bit_raw() {
1152 const NUM_BYTE: usize = 10;
1153 let mut buf = [0; NUM_BYTE];
1154 let mut expected = vec![];
1155 let mut rng = seedable_rng();
1156 for i in 0..8 * NUM_BYTE {
1157 let b = rng.random_bool(0.5);
1158 expected.push(b);
1159 if b {
1160 set_bit(&mut buf[..], i)
1161 }
1162 }
1163
1164 let raw_ptr = buf.as_ptr();
1165 for (i, b) in expected.iter().enumerate() {
1166 unsafe {
1167 assert_eq!(*b, get_bit_raw(raw_ptr, i));
1168 }
1169 }
1170 }
1171
1172 #[test]
1173 fn test_set_bit() {
1174 let mut b = [0b00000010];
1175 set_bit(&mut b, 0);
1176 assert_eq!([0b00000011], b);
1177 set_bit(&mut b, 1);
1178 assert_eq!([0b00000011], b);
1179 set_bit(&mut b, 7);
1180 assert_eq!([0b10000011], b);
1181 }
1182
1183 #[test]
1184 fn test_unset_bit() {
1185 let mut b = [0b11111101];
1186 unset_bit(&mut b, 0);
1187 assert_eq!([0b11111100], b);
1188 unset_bit(&mut b, 1);
1189 assert_eq!([0b11111100], b);
1190 unset_bit(&mut b, 7);
1191 assert_eq!([0b01111100], b);
1192 }
1193
1194 #[test]
1195 fn test_set_bit_raw() {
1196 const NUM_BYTE: usize = 10;
1197 let mut buf = vec![0; NUM_BYTE];
1198 let mut expected = vec![];
1199 let mut rng = seedable_rng();
1200 for i in 0..8 * NUM_BYTE {
1201 let b = rng.random_bool(0.5);
1202 expected.push(b);
1203 if b {
1204 unsafe {
1205 set_bit_raw(buf.as_mut_ptr(), i);
1206 }
1207 }
1208 }
1209
1210 let raw_ptr = buf.as_ptr();
1211 for (i, b) in expected.iter().enumerate() {
1212 unsafe {
1213 assert_eq!(*b, get_bit_raw(raw_ptr, i));
1214 }
1215 }
1216 }
1217
1218 #[test]
1219 fn test_unset_bit_raw() {
1220 const NUM_BYTE: usize = 10;
1221 let mut buf = vec![255; NUM_BYTE];
1222 let mut expected = vec![];
1223 let mut rng = seedable_rng();
1224 for i in 0..8 * NUM_BYTE {
1225 let b = rng.random_bool(0.5);
1226 expected.push(b);
1227 if !b {
1228 unsafe {
1229 unset_bit_raw(buf.as_mut_ptr(), i);
1230 }
1231 }
1232 }
1233
1234 let raw_ptr = buf.as_ptr();
1235 for (i, b) in expected.iter().enumerate() {
1236 unsafe {
1237 assert_eq!(*b, get_bit_raw(raw_ptr, i));
1238 }
1239 }
1240 }
1241
1242 #[test]
1243 fn test_get_set_bit_roundtrip() {
1244 const NUM_BYTES: usize = 10;
1245 const NUM_SETS: usize = 10;
1246
1247 let mut buffer: [u8; NUM_BYTES * 8] = [0; NUM_BYTES * 8];
1248 let mut v = HashSet::new();
1249 let mut rng = seedable_rng();
1250 for _ in 0..NUM_SETS {
1251 let offset = rng.random_range(0..8 * NUM_BYTES);
1252 v.insert(offset);
1253 set_bit(&mut buffer[..], offset);
1254 }
1255 for i in 0..NUM_BYTES * 8 {
1256 assert_eq!(v.contains(&i), get_bit(&buffer[..], i));
1257 }
1258 }
1259
1260 #[test]
1261 fn test_ceil() {
1262 assert_eq!(ceil(0, 1), 0);
1263 assert_eq!(ceil(1, 1), 1);
1264 assert_eq!(ceil(1, 2), 1);
1265 assert_eq!(ceil(1, 8), 1);
1266 assert_eq!(ceil(7, 8), 1);
1267 assert_eq!(ceil(8, 8), 1);
1268 assert_eq!(ceil(9, 8), 2);
1269 assert_eq!(ceil(9, 9), 1);
1270 assert_eq!(ceil(10000000000, 10), 1000000000);
1271 assert_eq!(ceil(10, 10000000000), 1);
1272 assert_eq!(ceil(10000000000, 1000000000), 10);
1273 }
1274
1275 #[test]
1276 fn test_read_up_to() {
1277 let all_ones = &[0b10111001, 0b10001100];
1278
1279 for (bit_offset, expected) in [
1280 (0, 0b00000001),
1281 (1, 0b00000000),
1282 (2, 0b00000000),
1283 (3, 0b00000001),
1284 (4, 0b00000001),
1285 (5, 0b00000001),
1286 (6, 0b00000000),
1287 (7, 0b00000001),
1288 ] {
1289 let result = read_up_to_byte_from_offset(all_ones, 1, bit_offset);
1290 assert_eq!(
1291 result, expected,
1292 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1293 );
1294 }
1295
1296 for (bit_offset, expected) in [
1297 (0, 0b00000001),
1298 (1, 0b00000000),
1299 (2, 0b00000010),
1300 (3, 0b00000011),
1301 (4, 0b00000011),
1302 (5, 0b00000001),
1303 (6, 0b00000010),
1304 (7, 0b00000001),
1305 ] {
1306 let result = read_up_to_byte_from_offset(all_ones, 2, bit_offset);
1307 assert_eq!(
1308 result, expected,
1309 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1310 );
1311 }
1312
1313 for (bit_offset, expected) in [
1314 (0, 0b00111001),
1315 (1, 0b00011100),
1316 (2, 0b00101110),
1317 (3, 0b00010111),
1318 (4, 0b00001011),
1319 (5, 0b00100101),
1320 (6, 0b00110010),
1321 (7, 0b00011001),
1322 ] {
1323 let result = read_up_to_byte_from_offset(all_ones, 6, bit_offset);
1324 assert_eq!(
1325 result, expected,
1326 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1327 );
1328 }
1329
1330 for (bit_offset, expected) in [
1331 (0, 0b00111001),
1332 (1, 0b01011100),
1333 (2, 0b00101110),
1334 (3, 0b00010111),
1335 (4, 0b01001011),
1336 (5, 0b01100101),
1337 (6, 0b00110010),
1338 (7, 0b00011001),
1339 ] {
1340 let result = read_up_to_byte_from_offset(all_ones, 7, bit_offset);
1341 assert_eq!(
1342 result, expected,
1343 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1344 );
1345 }
1346 }
1347
1348 fn test_mutable_buffer_bin_op_helper<F, G>(
1351 left_data: &[bool],
1352 right_data: &[bool],
1353 left_offset_in_bits: usize,
1354 right_offset_in_bits: usize,
1355 len_in_bits: usize,
1356 op: F,
1357 mut expected_op: G,
1358 ) where
1359 F: FnMut(u64, u64) -> u64,
1360 G: FnMut(bool, bool) -> bool,
1361 {
1362 let mut left_buffer = BooleanBufferBuilder::new(len_in_bits);
1363 left_buffer.append_slice(left_data);
1364 let right_buffer = BooleanBuffer::from(right_data);
1365
1366 let expected: Vec<bool> = left_data
1367 .iter()
1368 .skip(left_offset_in_bits)
1369 .zip(right_data.iter().skip(right_offset_in_bits))
1370 .take(len_in_bits)
1371 .map(|(l, r)| expected_op(*l, *r))
1372 .collect();
1373
1374 let before = left_buffer.as_slice().to_vec();
1375
1376 apply_bitwise_binary_op(
1377 left_buffer.as_slice_mut(),
1378 left_offset_in_bits,
1379 right_buffer.inner(),
1380 right_offset_in_bits,
1381 len_in_bits,
1382 op,
1383 );
1384
1385 let result: Vec<bool> =
1386 BitIterator::new(left_buffer.as_slice(), left_offset_in_bits, len_in_bits).collect();
1387
1388 assert_eq!(
1389 result, expected,
1390 "Failed with left_offset={left_offset_in_bits}, right_offset={right_offset_in_bits}, len={len_in_bits}"
1391 );
1392
1393 assert_bits_outside_range_preserved(
1394 &before,
1395 left_buffer.as_slice(),
1396 left_offset_in_bits,
1397 len_in_bits,
1398 &format!(
1399 "left_offset={left_offset_in_bits}, right_offset={right_offset_in_bits}, len={len_in_bits}"
1400 ),
1401 );
1402 }
1403
1404 fn assert_bits_outside_range_preserved(
1407 before: &[u8],
1408 after: &[u8],
1409 offset_in_bits: usize,
1410 len_in_bits: usize,
1411 context: &str,
1412 ) {
1413 assert_eq!(before.len(), after.len());
1414 for i in 0..before.len() * 8 {
1415 if i >= offset_in_bits && i < offset_in_bits + len_in_bits {
1416 continue;
1417 }
1418 assert_eq!(
1419 get_bit(before, i),
1420 get_bit(after, i),
1421 "bit {i} outside the requested range was modified ({context})"
1422 );
1423 }
1424 }
1425
1426 fn test_mutable_buffer_unary_op_helper<F, G>(
1429 data: &[bool],
1430 offset_in_bits: usize,
1431 len_in_bits: usize,
1432 op: F,
1433 mut expected_op: G,
1434 ) where
1435 F: FnMut(u64) -> u64,
1436 G: FnMut(bool) -> bool,
1437 {
1438 let mut buffer = BooleanBufferBuilder::new(len_in_bits);
1439 buffer.append_slice(data);
1440
1441 let expected: Vec<bool> = data
1442 .iter()
1443 .skip(offset_in_bits)
1444 .take(len_in_bits)
1445 .map(|b| expected_op(*b))
1446 .collect();
1447
1448 let before = buffer.as_slice().to_vec();
1449
1450 apply_bitwise_unary_op(buffer.as_slice_mut(), offset_in_bits, len_in_bits, op);
1451
1452 let result: Vec<bool> =
1453 BitIterator::new(buffer.as_slice(), offset_in_bits, len_in_bits).collect();
1454
1455 assert_eq!(
1456 result, expected,
1457 "Failed with offset={offset_in_bits}, len={len_in_bits}"
1458 );
1459
1460 assert_bits_outside_range_preserved(
1461 &before,
1462 buffer.as_slice(),
1463 offset_in_bits,
1464 len_in_bits,
1465 &format!("offset={offset_in_bits}, len={len_in_bits}"),
1466 );
1467 }
1468
1469 fn create_test_data(len: usize) -> (Vec<bool>, Vec<bool>) {
1471 let mut rng = rand::rng();
1472 let left: Vec<bool> = (0..len).map(|_| rng.random_bool(0.5)).collect();
1473 let right: Vec<bool> = (0..len).map(|_| rng.random_bool(0.5)).collect();
1474 (left, right)
1475 }
1476
1477 fn test_all_binary_ops(
1479 left_data: &[bool],
1480 right_data: &[bool],
1481 left_offset_in_bits: usize,
1482 right_offset_in_bits: usize,
1483 len_in_bits: usize,
1484 ) {
1485 test_mutable_buffer_bin_op_helper(
1487 left_data,
1488 right_data,
1489 left_offset_in_bits,
1490 right_offset_in_bits,
1491 len_in_bits,
1492 |a, b| a & b,
1493 |a, b| a & b,
1494 );
1495
1496 test_mutable_buffer_bin_op_helper(
1498 left_data,
1499 right_data,
1500 left_offset_in_bits,
1501 right_offset_in_bits,
1502 len_in_bits,
1503 |a, b| a | b,
1504 |a, b| a | b,
1505 );
1506
1507 test_mutable_buffer_bin_op_helper(
1509 left_data,
1510 right_data,
1511 left_offset_in_bits,
1512 right_offset_in_bits,
1513 len_in_bits,
1514 |a, b| a ^ b,
1515 |a, b| a ^ b,
1516 );
1517 }
1518
1519 #[test]
1522 fn test_binary_ops_less_than_byte() {
1523 let (left, right) = create_test_data(4);
1524 test_all_binary_ops(&left, &right, 0, 0, 4);
1525 }
1526
1527 #[test]
1528 fn test_binary_ops_less_than_byte_across_boundary() {
1529 let (left, right) = create_test_data(16);
1530 test_all_binary_ops(&left, &right, 6, 6, 4);
1531 }
1532
1533 #[test]
1534 fn test_binary_ops_exactly_byte() {
1535 let (left, right) = create_test_data(16);
1536 test_all_binary_ops(&left, &right, 0, 0, 8);
1537 }
1538
1539 #[test]
1540 fn test_binary_ops_more_than_byte_less_than_u64() {
1541 let (left, right) = create_test_data(64);
1542 test_all_binary_ops(&left, &right, 0, 0, 32);
1543 }
1544
1545 #[test]
1546 fn test_binary_ops_exactly_u64() {
1547 let (left, right) = create_test_data(180);
1548 test_all_binary_ops(&left, &right, 0, 0, 64);
1549 test_all_binary_ops(&left, &right, 64, 9, 64);
1550 test_all_binary_ops(&left, &right, 8, 100, 64);
1551 test_all_binary_ops(&left, &right, 1, 15, 64);
1552 test_all_binary_ops(&left, &right, 12, 10, 64);
1553 test_all_binary_ops(&left, &right, 180 - 64, 2, 64);
1554 }
1555
1556 #[test]
1557 fn test_binary_ops_more_than_u64_not_multiple() {
1558 let (left, right) = create_test_data(200);
1559 test_all_binary_ops(&left, &right, 0, 0, 100);
1560 }
1561
1562 #[test]
1563 fn test_binary_ops_exactly_multiple_u64() {
1564 let (left, right) = create_test_data(256);
1565 test_all_binary_ops(&left, &right, 0, 0, 128);
1566 }
1567
1568 #[test]
1569 fn test_binary_ops_more_than_multiple_u64() {
1570 let (left, right) = create_test_data(300);
1571 test_all_binary_ops(&left, &right, 0, 0, 200);
1572 }
1573
1574 #[test]
1575 fn test_binary_ops_byte_aligned_no_remainder() {
1576 let (left, right) = create_test_data(200);
1577 test_all_binary_ops(&left, &right, 0, 0, 128);
1578 }
1579
1580 #[test]
1581 fn test_binary_ops_byte_aligned_with_remainder() {
1582 let (left, right) = create_test_data(200);
1583 test_all_binary_ops(&left, &right, 0, 0, 100);
1584 }
1585
1586 #[test]
1587 fn test_binary_ops_not_byte_aligned_no_remainder() {
1588 let (left, right) = create_test_data(200);
1589 test_all_binary_ops(&left, &right, 3, 3, 128);
1590 }
1591
1592 #[test]
1593 fn test_binary_ops_not_byte_aligned_with_remainder() {
1594 let (left, right) = create_test_data(200);
1595 test_all_binary_ops(&left, &right, 5, 5, 100);
1596 }
1597
1598 #[test]
1599 fn test_binary_ops_different_offsets() {
1600 let (left, right) = create_test_data(200);
1601 test_all_binary_ops(&left, &right, 3, 7, 50);
1602 }
1603
1604 #[test]
1605 fn test_binary_ops_offsets_greater_than_8_less_than_64() {
1606 let (left, right) = create_test_data(200);
1607 test_all_binary_ops(&left, &right, 13, 27, 100);
1608 }
1609
1610 #[test]
1613 fn test_not_less_than_byte() {
1614 let data = vec![true, false, true, false];
1615 test_mutable_buffer_unary_op_helper(&data, 0, 4, |a| !a, |a| !a);
1616 }
1617
1618 #[test]
1619 fn test_not_less_than_byte_across_boundary() {
1620 let data: Vec<bool> = (0..16).map(|i| i % 2 == 0).collect();
1621 test_mutable_buffer_unary_op_helper(&data, 6, 4, |a| !a, |a| !a);
1622 }
1623
1624 #[test]
1625 fn test_not_exactly_byte() {
1626 let data: Vec<bool> = (0..16).map(|i| i % 2 == 0).collect();
1627 test_mutable_buffer_unary_op_helper(&data, 0, 8, |a| !a, |a| !a);
1628 }
1629
1630 #[test]
1631 fn test_not_more_than_byte_less_than_u64() {
1632 let data: Vec<bool> = (0..64).map(|i| i % 2 == 0).collect();
1633 test_mutable_buffer_unary_op_helper(&data, 0, 32, |a| !a, |a| !a);
1634 }
1635
1636 #[test]
1637 fn test_not_exactly_u64() {
1638 let data: Vec<bool> = (0..128).map(|i| i % 2 == 0).collect();
1639 test_mutable_buffer_unary_op_helper(&data, 0, 64, |a| !a, |a| !a);
1640 }
1641
1642 #[test]
1643 fn test_not_more_than_u64_not_multiple() {
1644 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1645 test_mutable_buffer_unary_op_helper(&data, 0, 100, |a| !a, |a| !a);
1646 }
1647
1648 #[test]
1649 fn test_not_exactly_multiple_u64() {
1650 let data: Vec<bool> = (0..256).map(|i| i % 2 == 0).collect();
1651 test_mutable_buffer_unary_op_helper(&data, 0, 128, |a| !a, |a| !a);
1652 }
1653
1654 #[test]
1655 fn test_not_more_than_multiple_u64() {
1656 let data: Vec<bool> = (0..300).map(|i| i % 2 == 0).collect();
1657 test_mutable_buffer_unary_op_helper(&data, 0, 200, |a| !a, |a| !a);
1658 }
1659
1660 #[test]
1661 fn test_not_byte_aligned_no_remainder() {
1662 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1663 test_mutable_buffer_unary_op_helper(&data, 0, 128, |a| !a, |a| !a);
1664 }
1665
1666 #[test]
1667 fn test_not_byte_aligned_with_remainder() {
1668 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1669 test_mutable_buffer_unary_op_helper(&data, 0, 100, |a| !a, |a| !a);
1670 }
1671
1672 #[test]
1673 fn test_not_not_byte_aligned_no_remainder() {
1674 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1675 test_mutable_buffer_unary_op_helper(&data, 3, 128, |a| !a, |a| !a);
1676 }
1677
1678 #[test]
1679 fn test_not_not_byte_aligned_with_remainder() {
1680 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1681 test_mutable_buffer_unary_op_helper(&data, 5, 100, |a| !a, |a| !a);
1682 }
1683
1684 #[test]
1687 fn test_empty_length() {
1688 let (left, right) = create_test_data(16);
1689 test_all_binary_ops(&left, &right, 0, 0, 0);
1690 }
1691
1692 #[test]
1693 fn test_single_bit() {
1694 let (left, right) = create_test_data(16);
1695 test_all_binary_ops(&left, &right, 0, 0, 1);
1696 }
1697
1698 #[test]
1699 fn test_single_bit_at_offset() {
1700 let (left, right) = create_test_data(16);
1701 test_all_binary_ops(&left, &right, 7, 7, 1);
1702 }
1703
1704 #[test]
1705 fn test_not_single_bit() {
1706 let data = vec![true, false, true, false];
1707 test_mutable_buffer_unary_op_helper(&data, 0, 1, |a| !a, |a| !a);
1708 }
1709
1710 #[test]
1711 fn test_not_empty_length() {
1712 let data = vec![true, false, true, false];
1713 test_mutable_buffer_unary_op_helper(&data, 0, 0, |a| !a, |a| !a);
1714 }
1715
1716 #[test]
1717 fn test_less_than_byte_unaligned_and_not_enough_bits() {
1718 let left_offset_in_bits = 2;
1719 let right_offset_in_bits = 4;
1720 let len_in_bits = 1;
1721
1722 let right = (0..8).map(|i| (i / 2) % 2 == 0).collect::<Vec<_>>();
1724 let left = (0..3).map(|i| i % 2 == 0).collect::<Vec<_>>();
1726 test_all_binary_ops(
1727 &left,
1728 &right,
1729 left_offset_in_bits,
1730 right_offset_in_bits,
1731 len_in_bits,
1732 );
1733 }
1734
1735 #[test]
1738 fn test_ops_ending_inside_the_first_partial_byte() {
1739 let (left, right) = create_test_data(32);
1740 for offset in 1..8 {
1741 for len in 1..=(8 - offset) {
1743 test_all_binary_ops(&left, &right, offset, offset, len);
1744 test_all_binary_ops(&left, &right, offset, (offset + 3) % 8, len);
1745 test_mutable_buffer_unary_op_helper(&left, offset, len, |a| !a, |a| !a);
1746 }
1747 }
1748 }
1749
1750 #[test]
1751 fn test_and_within_first_partial_byte_preserves_trailing_bits() {
1752 let mut left = vec![0b11111111u8, 0b11111111u8];
1753 let right = vec![0b00000000u8, 0b00000000u8];
1754 apply_bitwise_binary_op(&mut left, 1, &right, 0, 1, |a, b| a & b);
1756 assert_eq!(left, vec![0b11111101u8, 0b11111111u8]);
1757 }
1758
1759 #[test]
1760 fn test_not_within_first_partial_byte_preserves_trailing_bits() {
1761 let mut buffer = vec![0b00000000u8];
1762 apply_bitwise_unary_op(&mut buffer, 3, 2, |a| !a);
1764 assert_eq!(buffer, vec![0b00011000u8]);
1765 }
1766
1767 #[test]
1771 fn test_or_with_multi_byte_remainder_preserves_boundary_bits() {
1772 let mut left = vec![0b00000000u8, 0b00000000u8, 0b11110000u8];
1773 let right = vec![0b11111111u8, 0b11111111u8, 0b11111111u8];
1774 apply_bitwise_binary_op(&mut left, 0, &right, 0, 20, |a, b| a | b);
1776 assert_eq!(
1777 left,
1778 vec![0b11111111u8, 0b11111111u8, 0b11111111u8],
1779 "the boundary byte lost its out-of-range bits"
1780 );
1781 }
1782
1783 #[test]
1784 fn test_not_with_multi_byte_remainder_preserves_boundary_bits() {
1785 let mut buffer = vec![0b00000000u8, 0b00000000u8, 0b11111111u8];
1786 apply_bitwise_unary_op(&mut buffer, 0, 20, |a| !a);
1788 assert_eq!(
1789 buffer,
1790 vec![0b11111111u8, 0b11111111u8, 0b11110000u8],
1791 "the boundary byte lost its out-of-range bits"
1792 );
1793 }
1794
1795 #[test]
1796 fn test_bitwise_binary_op_offset_out_of_bounds() {
1797 let input = vec![0b10101010u8, 0b01010101u8];
1798 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_binary_op(
1801 buffer.as_slice_mut(),
1802 100, [0b11110000u8, 0b00001111u8],
1804 0,
1805 0,
1806 |a, b| a & b,
1807 );
1808 assert_eq!(buffer.as_slice(), &input);
1809 }
1810
1811 #[test]
1812 #[should_panic(expected = "assertion failed: last_offset <= buffer.len()")]
1813 fn test_bitwise_binary_op_length_out_of_bounds() {
1814 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&[0b10101010u8, 0b01010101u8]); apply_bitwise_binary_op(
1817 buffer.as_slice_mut(),
1818 0, [0b11110000u8, 0b00001111u8],
1820 0,
1821 100,
1822 |a, b| a & b,
1823 );
1824 assert_eq!(buffer.as_slice(), &[0b10101010u8, 0b01010101u8]);
1825 }
1826
1827 #[test]
1828 #[should_panic(expected = "offset + len out of bounds")]
1829 fn test_bitwise_binary_op_right_len_out_of_bounds() {
1830 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&[0b10101010u8, 0b01010101u8]); apply_bitwise_binary_op(
1833 buffer.as_slice_mut(),
1834 0, [0b11110000u8, 0b00001111u8],
1836 1000,
1837 16,
1838 |a, b| a & b,
1839 );
1840 assert_eq!(buffer.as_slice(), &[0b10101010u8, 0b01010101u8]);
1841 }
1842
1843 #[test]
1844 #[should_panic(expected = "the len is 2 but the index is 12")]
1845 fn test_bitwise_unary_op_offset_out_of_bounds() {
1846 let input = vec![0b10101010u8, 0b01010101u8];
1847 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_unary_op(
1850 buffer.as_slice_mut(),
1851 100, 8,
1853 |a| !a,
1854 );
1855 assert_eq!(buffer.as_slice(), &input);
1856 }
1857
1858 #[test]
1859 #[should_panic(expected = "assertion failed: last_offset <= buffer.len()")]
1860 fn test_bitwise_unary_op_length_out_of_bounds2() {
1861 let input = vec![0b10101010u8, 0b01010101u8];
1862 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_unary_op(
1865 buffer.as_slice_mut(),
1866 3, 100, |a| !a,
1869 );
1870 assert_eq!(buffer.as_slice(), &input);
1871 }
1872}