Skip to content

Commit

Permalink
Implement Bit Operations for i256 (apache#3884)
Browse files Browse the repository at this point in the history
* Implement BitAnd, BitOr and BitXor for i256

* Implement Shl and Shr for i256

* Clippy
  • Loading branch information
tustvold authored and spebern committed Mar 25, 2023
1 parent 33f8881 commit ea2bd57
Showing 1 changed file with 102 additions and 0 deletions.
102 changes: 102 additions & 0 deletions arrow-buffer/src/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit ea2bd57

Please sign in to comment.