Create a new [`BooleanBuffer`] by applying the bitwise operation `op` to the relevant bits from two input buffers. This function is faster than applying the operation bit by bit as it processes input buffers in chunks of 64 bits (8 bytes) at a time # Notes: `op` takes two `u64` inputs and produces one `u64` output. `op` must only apply bitwise operations on the relevant bits; the input `u64` val
(
left: impl AsRef<[u8]>,
left_offset_in_bits: usize,
right: impl AsRef<[u8]>,
right_offset_in_bits: usize,
len_in_bits: usize,
mut op: F,
)
| 330 | /// } |
| 331 | /// ``` |
| 332 | pub fn from_bitwise_binary_op<F>( |
| 333 | left: impl AsRef<[u8]>, |
| 334 | left_offset_in_bits: usize, |
| 335 | right: impl AsRef<[u8]>, |
| 336 | right_offset_in_bits: usize, |
| 337 | len_in_bits: usize, |
| 338 | mut op: F, |
| 339 | ) -> Self |
| 340 | where |
| 341 | F: FnMut(u64, u64) -> u64, |
| 342 | { |
| 343 | let left = left.as_ref(); |
| 344 | let right = right.as_ref(); |
| 345 | |
| 346 | // When both offsets share the same sub-64-bit alignment, we can |
| 347 | // align both to 64-bit boundaries and zip u64s directly, |
| 348 | // avoiding BitChunks bit-shifting entirely. |
| 349 | if left_offset_in_bits % 64 == right_offset_in_bits % 64 { |
| 350 | let bit_offset = left_offset_in_bits % 64; |
| 351 | let left_end = left_offset_in_bits + len_in_bits; |
| 352 | let right_end = right_offset_in_bits + len_in_bits; |
| 353 | |
| 354 | let left_aligned = left_offset_in_bits & !63; |
| 355 | let right_aligned = right_offset_in_bits & !63; |
| 356 | |
| 357 | let left_end_bytes = (bit_util::ceil(left_end, 64) * 8).min(left.len()); |
| 358 | let right_end_bytes = (bit_util::ceil(right_end, 64) * 8).min(right.len()); |
| 359 | |
| 360 | let left_slice = &left[left_aligned / 8..left_end_bytes]; |
| 361 | let right_slice = &right[right_aligned / 8..right_end_bytes]; |
| 362 | |
| 363 | let (lp, left_u64s, ls) = unsafe { left_slice.align_to::<u64>() }; |
| 364 | let (rp, right_u64s, rs) = unsafe { right_slice.align_to::<u64>() }; |
| 365 | |
| 366 | match (lp, ls, rp, rs) { |
| 367 | ([], [], [], []) => { |
| 368 | let result_u64s: Vec<u64> = left_u64s |
| 369 | .iter() |
| 370 | .zip(right_u64s.iter()) |
| 371 | .map(|(l, r)| op(*l, *r)) |
| 372 | .collect(); |
| 373 | return BooleanBuffer::new(result_u64s.into(), bit_offset, len_in_bits); |
| 374 | } |
| 375 | ([], left_suf, [], right_suf) => { |
| 376 | let left_iter = left_u64s |
| 377 | .iter() |
| 378 | .cloned() |
| 379 | .chain((!left_suf.is_empty()).then(|| read_u64(left_suf))); |
| 380 | let right_iter = right_u64s |
| 381 | .iter() |
| 382 | .cloned() |
| 383 | .chain((!right_suf.is_empty()).then(|| read_u64(right_suf))); |
| 384 | let result_u64s: Vec<u64> = |
| 385 | left_iter.zip(right_iter).map(|(l, r)| op(l, r)).collect(); |
| 386 | return BooleanBuffer::new(result_u64s.into(), bit_offset, len_in_bits); |
| 387 | } |
| 388 | _ => {} |
| 389 | } |
nothing calls this directly
no test coverage detected