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]