Path: blob/main/crates/polars-arrow/src/bitmap/assign_ops.rs
6939 views
use super::utils::{BitChunk, BitChunkIterExact, BitChunksExact};1use crate::bitmap::{Bitmap, MutableBitmap};23/// Applies a function to every bit of this [`MutableBitmap`] in chunks4///5/// This function can be for operations like `!` to a [`MutableBitmap`].6pub fn unary_assign<T: BitChunk, F: Fn(T) -> T>(bitmap: &mut MutableBitmap, op: F) {7let mut chunks = bitmap.bitchunks_exact_mut::<T>();89chunks.by_ref().for_each(|chunk| {10let new_chunk: T = match (chunk as &[u8]).try_into() {11Ok(a) => T::from_ne_bytes(a),12Err(_) => unreachable!(),13};14let new_chunk = op(new_chunk);15chunk.copy_from_slice(new_chunk.to_ne_bytes().as_ref());16});1718if chunks.remainder().is_empty() {19return;20}21let mut new_remainder = T::zero().to_ne_bytes();22chunks23.remainder()24.iter()25.enumerate()26.for_each(|(index, b)| new_remainder[index] = *b);27new_remainder = op(T::from_ne_bytes(new_remainder)).to_ne_bytes();2829let len = chunks.remainder().len();30chunks31.remainder()32.copy_from_slice(&new_remainder.as_ref()[..len]);33}3435impl std::ops::Not for MutableBitmap {36type Output = Self;3738#[inline]39fn not(mut self) -> Self {40unary_assign(&mut self, |a: u64| !a);41self42}43}4445fn binary_assign_impl<I, T, F>(lhs: &mut MutableBitmap, mut rhs: I, op: F)46where47I: BitChunkIterExact<T>,48T: BitChunk,49F: Fn(T, T) -> T,50{51let mut lhs_chunks = lhs.bitchunks_exact_mut::<T>();5253lhs_chunks54.by_ref()55.zip(rhs.by_ref())56.for_each(|(lhs, rhs)| {57let new_chunk: T = match (lhs as &[u8]).try_into() {58Ok(a) => T::from_ne_bytes(a),59Err(_) => unreachable!(),60};61let new_chunk = op(new_chunk, rhs);62lhs.copy_from_slice(new_chunk.to_ne_bytes().as_ref());63});6465let rem_lhs = lhs_chunks.remainder();66let rem_rhs = rhs.remainder();67if rem_lhs.is_empty() {68return;69}70let mut new_remainder = T::zero().to_ne_bytes();71lhs_chunks72.remainder()73.iter()74.enumerate()75.for_each(|(index, b)| new_remainder[index] = *b);76new_remainder = op(T::from_ne_bytes(new_remainder), rem_rhs).to_ne_bytes();7778let len = lhs_chunks.remainder().len();79lhs_chunks80.remainder()81.copy_from_slice(&new_remainder.as_ref()[..len]);82}8384/// Apply a bitwise binary operation to a [`MutableBitmap`].85///86/// This function can be used for operations like `&=` to a [`MutableBitmap`].87/// # Panics88/// This function panics iff `lhs.len() != `rhs.len()`89pub fn binary_assign<T: BitChunk, F>(lhs: &mut MutableBitmap, rhs: &Bitmap, op: F)90where91F: Fn(T, T) -> T,92{93assert_eq!(lhs.len(), rhs.len());9495let (slice, offset, length) = rhs.as_slice();96if offset == 0 {97let iter = BitChunksExact::<T>::new(slice, length);98binary_assign_impl(lhs, iter, op)99} else {100let rhs_chunks = rhs.chunks::<T>();101binary_assign_impl(lhs, rhs_chunks, op)102}103}104105/// Apply a bitwise binary operation to a [`MutableBitmap`].106///107/// This function can be used for operations like `&=` to a [`MutableBitmap`].108/// # Panics109/// This function panics iff `lhs.len() != `rhs.len()`110pub fn binary_assign_mut<T: BitChunk, F>(lhs: &mut MutableBitmap, rhs: &MutableBitmap, op: F)111where112F: Fn(T, T) -> T,113{114assert_eq!(lhs.len(), rhs.len());115116let slice = rhs.as_slice();117let iter = BitChunksExact::<T>::new(slice, rhs.len());118binary_assign_impl(lhs, iter, op)119}120121#[inline]122/// Compute bitwise OR operation in-place123fn or_assign<T: BitChunk>(lhs: &mut MutableBitmap, rhs: &Bitmap) {124if rhs.unset_bits() == 0 {125assert_eq!(lhs.len(), rhs.len());126lhs.clear();127lhs.extend_constant(rhs.len(), true);128} else if rhs.unset_bits() == rhs.len() {129// bitmap remains130} else {131binary_assign(lhs, rhs, |x: T, y| x | y)132}133}134135#[inline]136/// Compute bitwise OR operation in-place137fn or_assign_mut<T: BitChunk>(lhs: &mut MutableBitmap, rhs: &MutableBitmap) {138if rhs.unset_bits() == 0 {139assert_eq!(lhs.len(), rhs.len());140lhs.clear();141lhs.extend_constant(rhs.len(), true);142} else if rhs.unset_bits() == rhs.len() {143// bitmap remains144} else {145binary_assign_mut(lhs, rhs, |x: T, y| x | y)146}147}148149impl<'a> std::ops::BitOrAssign<&'a MutableBitmap> for &mut MutableBitmap {150#[inline]151fn bitor_assign(&mut self, rhs: &'a MutableBitmap) {152or_assign_mut::<u64>(self, rhs)153}154}155156impl<'a> std::ops::BitOrAssign<&'a Bitmap> for &mut MutableBitmap {157#[inline]158fn bitor_assign(&mut self, rhs: &'a Bitmap) {159or_assign::<u64>(self, rhs)160}161}162163impl<'a> std::ops::BitOr<&'a Bitmap> for MutableBitmap {164type Output = Self;165166#[inline]167fn bitor(mut self, rhs: &'a Bitmap) -> Self {168or_assign::<u64>(&mut self, rhs);169self170}171}172173#[inline]174/// Compute bitwise `&` between `lhs` and `rhs`, assigning it to `lhs`175fn and_assign<T: BitChunk>(lhs: &mut MutableBitmap, rhs: &Bitmap) {176if rhs.unset_bits() == 0 {177// bitmap remains178}179if rhs.unset_bits() == rhs.len() {180assert_eq!(lhs.len(), rhs.len());181lhs.clear();182lhs.extend_constant(rhs.len(), false);183} else {184binary_assign(lhs, rhs, |x: T, y| x & y)185}186}187188impl<'a> std::ops::BitAndAssign<&'a Bitmap> for &mut MutableBitmap {189#[inline]190fn bitand_assign(&mut self, rhs: &'a Bitmap) {191and_assign::<u64>(self, rhs)192}193}194195impl<'a> std::ops::BitAnd<&'a Bitmap> for MutableBitmap {196type Output = Self;197198#[inline]199fn bitand(mut self, rhs: &'a Bitmap) -> Self {200and_assign::<u64>(&mut self, rhs);201self202}203}204205#[inline]206/// Compute bitwise XOR operation207fn xor_assign<T: BitChunk>(lhs: &mut MutableBitmap, rhs: &Bitmap) {208binary_assign(lhs, rhs, |x: T, y| x ^ y)209}210211impl<'a> std::ops::BitXorAssign<&'a Bitmap> for &mut MutableBitmap {212#[inline]213fn bitxor_assign(&mut self, rhs: &'a Bitmap) {214xor_assign::<u64>(self, rhs)215}216}217218impl<'a> std::ops::BitXor<&'a Bitmap> for MutableBitmap {219type Output = Self;220221#[inline]222fn bitxor(mut self, rhs: &'a Bitmap) -> Self {223xor_assign::<u64>(&mut self, rhs);224self225}226}227228229