You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by tu...@apache.org on 2023/04/02 16:05:08 UTC

[arrow-rs] branch master updated: feat: add the implementation BitXor to BooleanBuffer (#3997)

This is an automated email from the ASF dual-hosted git repository.

tustvold pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/master by this push:
     new ecd44fd4c feat: add the implementation BitXor to BooleanBuffer (#3997)
ecd44fd4c is described below

commit ecd44fd4cd1ab65533979983791d5ef524a2eac6
Author: Igor Izvekov <iz...@mail.ru>
AuthorDate: Sun Apr 2 19:05:01 2023 +0300

    feat: add the implementation BitXor to BooleanBuffer (#3997)
    
    * feat: add the implementation BitXor to BooleanBuffer
    
    * feat: add tests to "BooleanBuffer" for BitAnd, BitOr, BitXor, Not
---
 arrow-buffer/src/buffer/boolean.rs | 87 +++++++++++++++++++++++++++++++++++++-
 arrow-buffer/src/buffer/ops.rs     | 25 +++++++++++
 2 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/arrow-buffer/src/buffer/boolean.rs b/arrow-buffer/src/buffer/boolean.rs
index c89cfb332..2202e46d2 100644
--- a/arrow-buffer/src/buffer/boolean.rs
+++ b/arrow-buffer/src/buffer/boolean.rs
@@ -18,9 +18,10 @@
 use crate::bit_chunk_iterator::BitChunks;
 use crate::bit_iterator::{BitIndexIterator, BitIterator, BitSliceIterator};
 use crate::{
-    bit_util, buffer_bin_and, buffer_bin_or, buffer_unary_not, Buffer, MutableBuffer,
+    bit_util, buffer_bin_and, buffer_bin_or, buffer_bin_xor, buffer_unary_not, Buffer,
+    MutableBuffer,
 };
-use std::ops::{BitAnd, BitOr, Not};
+use std::ops::{BitAnd, BitOr, BitXor, Not};
 
 /// A slice-able [`Buffer`] containing bit-packed booleans
 #[derive(Debug, Clone, Eq)]
@@ -236,6 +237,25 @@ impl BitOr<&BooleanBuffer> for &BooleanBuffer {
     }
 }
 
+impl BitXor<&BooleanBuffer> for &BooleanBuffer {
+    type Output = BooleanBuffer;
+
+    fn bitxor(self, rhs: &BooleanBuffer) -> Self::Output {
+        assert_eq!(self.len, rhs.len);
+        BooleanBuffer {
+            buffer: buffer_bin_xor(
+                &self.buffer,
+                self.offset,
+                &rhs.buffer,
+                rhs.offset,
+                self.len,
+            ),
+            offset: 0,
+            len: self.len,
+        }
+    }
+}
+
 impl<'a> IntoIterator for &'a BooleanBuffer {
     type Item = bool;
     type IntoIter = BitIterator<'a>;
@@ -244,3 +264,66 @@ impl<'a> IntoIterator for &'a BooleanBuffer {
         BitIterator::new(self.values(), self.offset, self.len)
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_bitand() {
+        let offset = 0;
+        let len = 40;
+
+        let buf1 = Buffer::from(&[0, 1, 1, 0, 0]);
+        let boolean_buf1 = &BooleanBuffer::new(buf1, offset, len);
+
+        let buf2 = Buffer::from(&[0, 1, 1, 1, 0]);
+        let boolean_buf2 = &BooleanBuffer::new(buf2, offset, len);
+
+        let expected = BooleanBuffer::new(Buffer::from(&[0, 1, 1, 0, 0]), offset, len);
+        assert_eq!(boolean_buf1 & boolean_buf2, expected);
+    }
+
+    #[test]
+    fn test_bitor() {
+        let offset = 0;
+        let len = 40;
+
+        let buf1 = Buffer::from(&[0, 1, 1, 0, 0]);
+        let boolean_buf1 = &BooleanBuffer::new(buf1, offset, len);
+
+        let buf2 = Buffer::from(&[0, 1, 1, 1, 0]);
+        let boolean_buf2 = &BooleanBuffer::new(buf2, offset, len);
+
+        let expected = BooleanBuffer::new(Buffer::from(&[0, 1, 1, 1, 0]), offset, len);
+        assert_eq!(boolean_buf1 | boolean_buf2, expected);
+    }
+
+    #[test]
+    fn test_bitxor() {
+        let offset = 0;
+        let len = 40;
+
+        let buf1 = Buffer::from(&[0, 1, 1, 0, 0]);
+        let boolean_buf1 = &BooleanBuffer::new(buf1, offset, len);
+
+        let buf2 = Buffer::from(&[0, 1, 1, 1, 0]);
+        let boolean_buf2 = &BooleanBuffer::new(buf2, offset, len);
+
+        let expected = BooleanBuffer::new(Buffer::from(&[0, 0, 0, 1, 0]), offset, len);
+        assert_eq!(boolean_buf1 ^ boolean_buf2, expected);
+    }
+
+    #[test]
+    fn test_not() {
+        let offset = 0;
+        let len = 40;
+
+        let buf = Buffer::from(&[0, 1, 1, 0, 0]);
+        let boolean_buf = &BooleanBuffer::new(buf, offset, len);
+
+        let expected =
+            BooleanBuffer::new(Buffer::from(&[255, 254, 254, 255, 255]), offset, len);
+        assert_eq!(!boolean_buf, expected);
+    }
+}
diff --git a/arrow-buffer/src/buffer/ops.rs b/arrow-buffer/src/buffer/ops.rs
index 87dc5c003..eccff6280 100644
--- a/arrow-buffer/src/buffer/ops.rs
+++ b/arrow-buffer/src/buffer/ops.rs
@@ -125,6 +125,8 @@ where
     result.into()
 }
 
+/// Apply a bitwise and to two inputs and return the result as a Buffer.
+/// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits.
 pub fn buffer_bin_and(
     left: &Buffer,
     left_offset_in_bits: usize,
@@ -142,6 +144,8 @@ pub fn buffer_bin_and(
     )
 }
 
+/// Apply a bitwise or to two inputs and return the result as a Buffer.
+/// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits.
 pub fn buffer_bin_or(
     left: &Buffer,
     left_offset_in_bits: usize,
@@ -159,6 +163,27 @@ pub fn buffer_bin_or(
     )
 }
 
+/// Apply a bitwise xor to two inputs and return the result as a Buffer.
+/// The inputs are treated as bitmaps, meaning that offsets and length are specified in number of bits.
+pub fn buffer_bin_xor(
+    left: &Buffer,
+    left_offset_in_bits: usize,
+    right: &Buffer,
+    right_offset_in_bits: usize,
+    len_in_bits: usize,
+) -> Buffer {
+    bitwise_bin_op_helper(
+        left,
+        left_offset_in_bits,
+        right,
+        right_offset_in_bits,
+        len_in_bits,
+        |a, b| a ^ b,
+    )
+}
+
+/// Apply a bitwise not to one input and return the result as a Buffer.
+/// The input is treated as a bitmap, meaning that offset and length are specified in number of bits.
 pub fn buffer_unary_not(
     left: &Buffer,
     offset_in_bits: usize,