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 30250d315 Implement Bit Operations for i256 (#3884)
30250d315 is described below

commit 30250d3158fffa284b793457c6952c0b36837510
Author: Raphael Taylor-Davies <[email protected]>
AuthorDate: Fri Mar 17 18:03:45 2023 +0000

    Implement Bit Operations for i256 (#3884)
    
    * Implement BitAnd, BitOr and BitXor for i256
    
    * Implement Shl and Shr for i256
    
    * Clippy
---
 arrow-buffer/src/bigint.rs | 102 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

diff --git a/arrow-buffer/src/bigint.rs b/arrow-buffer/src/bigint.rs
index 421a7bdd0..4b446e19b 100644
--- a/arrow-buffer/src/bigint.rs
+++ b/arrow-buffer/src/bigint.rs
@@ -18,6 +18,7 @@
 use num::cast::AsPrimitive;
 use num::{BigInt, FromPrimitive, Num, ToPrimitive};
 use std::cmp::Ordering;
+use std::ops::{BitAnd, BitOr, BitXor, Shl, Shr};
 
 /// A signed 256-bit integer
 #[allow(non_camel_case_types)]
@@ -492,6 +493,84 @@ impl std::ops::Neg for i256 {
     }
 }
 
+impl BitAnd for i256 {
+    type Output = i256;
+
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self::Output {
+        Self {
+            low: self.low & rhs.low,
+            high: self.high & rhs.high,
+        }
+    }
+}
+
+impl BitOr for i256 {
+    type Output = i256;
+
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        Self {
+            low: self.low | rhs.low,
+            high: self.high | rhs.high,
+        }
+    }
+}
+
+impl BitXor for i256 {
+    type Output = i256;
+
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self {
+            low: self.low ^ rhs.low,
+            high: self.high ^ rhs.high,
+        }
+    }
+}
+
+impl Shl<u8> for i256 {
+    type Output = i256;
+
+    #[inline]
+    fn shl(self, rhs: u8) -> Self::Output {
+        if rhs == 0 {
+            self
+        } else if rhs < 128 {
+            Self {
+                high: self.high << rhs | (self.low >> (128 - rhs)) as i128,
+                low: self.low << rhs,
+            }
+        } else {
+            Self {
+                high: (self.low << (rhs - 128)) as i128,
+                low: 0,
+            }
+        }
+    }
+}
+
+impl Shr<u8> for i256 {
+    type Output = i256;
+
+    #[inline]
+    fn shr(self, rhs: u8) -> Self::Output {
+        if rhs == 0 {
+            self
+        } else if rhs < 128 {
+            Self {
+                high: self.high >> rhs,
+                low: self.low >> rhs | ((self.high as u128) << (128 - rhs)),
+            }
+        } else {
+            Self {
+                high: self.high >> 127,
+                low: (self.high >> (rhs - 128)) as u128,
+            }
+        }
+    }
+}
+
 macro_rules! define_as_primitive {
     ($native_ty:ty) => {
         impl AsPrimitive<i256> for $native_ty {
@@ -684,6 +763,29 @@ mod tests {
                 ),
             }
         }
+
+        // Bit operations
+        let actual = il & ir;
+        let (expected, _) = i256::from_bigint_with_overflow(bl.clone() & 
br.clone());
+        assert_eq!(actual.to_string(), expected.to_string());
+
+        let actual = il | ir;
+        let (expected, _) = i256::from_bigint_with_overflow(bl.clone() | 
br.clone());
+        assert_eq!(actual.to_string(), expected.to_string());
+
+        let actual = il ^ ir;
+        let (expected, _) = i256::from_bigint_with_overflow(bl.clone() ^ br);
+        assert_eq!(actual.to_string(), expected.to_string());
+
+        for shift in [0_u8, 1, 4, 126, 128, 129, 254, 255] {
+            let actual = il << shift;
+            let (expected, _) = i256::from_bigint_with_overflow(bl.clone() << 
shift);
+            assert_eq!(actual.to_string(), expected.to_string());
+
+            let actual = il >> shift;
+            let (expected, _) = i256::from_bigint_with_overflow(bl.clone() >> 
shift);
+            assert_eq!(actual.to_string(), expected.to_string());
+        }
     }
 
     #[test]

Reply via email to