Skip to content

Commit

Permalink
Implementation of bitwise operations between BigInteger
Browse files Browse the repository at this point in the history
  • Loading branch information
hdvanegasm committed Dec 13, 2023
1 parent ee0a407 commit 8edec2b
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
63 changes: 63 additions & 0 deletions ff/src/biginteger/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign};

use crate::{
bits::{BitIteratorBE, BitIteratorLE},
const_for, UniformRand,
Expand Down Expand Up @@ -681,6 +683,61 @@ impl<const N: usize> From<BigInt<N>> for BigUint {
}
}

// ===================================
// Bitwise operators
// ===================================

impl<const N: usize> BitXorAssign for BigInt<N> {
fn bitxor_assign(&mut self, rhs: Self) {
for i in 0..N {
self.0[i] ^= rhs.0[i];
}
}
}

impl<const N: usize> BitXor for BigInt<N> {
type Output = Self;

fn bitxor(mut self, rhs: Self) -> Self::Output {
self ^= rhs;
self
}
}

impl<const N: usize> BitAndAssign for BigInt<N> {
fn bitand_assign(&mut self, rhs: Self) {
for i in 0..N {
self.0[i] &= rhs.0[i];
}
}
}

impl<const N: usize> BitAnd for BigInt<N> {
type Output = Self;

fn bitand(mut self, rhs: Self) -> Self::Output {
self &= rhs;
self
}
}

impl<const N: usize> BitOrAssign for BigInt<N> {
fn bitor_assign(&mut self, rhs: Self) {
for i in 0..N {
self.0[i] |= rhs.0[i];
}
}
}

impl<const N: usize> BitOr for BigInt<N> {
type Output = Self;

fn bitor(mut self, rhs: Self) -> Self::Output {
self |= rhs;
self
}
}

/// Compute the signed modulo operation on a u64 representation, returning the result.
/// If n % modulus > modulus / 2, return modulus - n
/// # Example
Expand Down Expand Up @@ -737,6 +794,12 @@ pub trait BigInteger:
+ From<u8>
+ TryFrom<BigUint, Error = ()>
+ Into<BigUint>
+ BitXorAssign<Self>
+ BitXor<Self>
+ BitAndAssign<Self>
+ BitAnd<Self>
+ BitOrAssign<Self>
+ BitOr<Self>
{
/// Number of 64-bit limbs representing `Self`.
const NUM_LIMBS: usize;
Expand Down
45 changes: 44 additions & 1 deletion ff/src/biginteger/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{biginteger::BigInteger, UniformRand};
use crate::{biginteger::BigInteger, BigInt, UniformRand};
use num_bigint::BigUint;

// Test elementary math operations for BigInteger.
Expand Down Expand Up @@ -51,6 +51,48 @@ fn biginteger_arithmetic_test<B: BigInteger>(a: B, b: B, zero: B) {
assert_eq!(a_mul2, a_plus_a);
}

// Test for BigInt's bitwise operations
fn biginteger_bitwise_ops_test<B: BigInteger>() {
// Test XOR
// a xor a = 0
let a: BigInt<4> = BigInt::from(4_u64);
let a_clone = a.clone();
assert_eq!(a ^ a_clone, BigInt::from(0_u64));

// Testing a xor b xor b
let a: BigInt<4> = BigInt::from(4_u64);
let b = BigInt::from(5_u64);
let b_clone = b.clone();
let xor_ab = a ^ b;
assert_eq!(xor_ab ^ b_clone, BigInt::from(4_u64));

// Test OR
// 1 or 1 = 1
let a: BigInt<4> = BigInt::from(1_u64);
let a_clone = a.clone();
assert_eq!(a | a_clone, BigInt::from(1_u64));

// Testing a or b or b
let a: BigInt<4> = BigInt::from(4_u64);
let b = BigInt::from(5_u64);
let b_clone = b.clone();
let or_ab = a | b;
assert_eq!(or_ab | b_clone, BigInt::from(5_u64));

// Test AND
// a and a = a
let a: BigInt<4> = BigInt::from(2_u64);
let a_clone = a.clone();
assert_eq!(a & a_clone, BigInt::from(2_u64));

// Testing a and a and b.
let a: BigInt<4> = BigInt::from(4_u64);
let b = BigInt::from(5_u64);
let b_clone = b.clone();
let and_ab = a & b;
assert_eq!(and_ab & b_clone, BigInt::from(4_u64));
}

// Test correctness of BigInteger's bit values
fn biginteger_bits_test<B: BigInteger>() {
let mut one = B::from(1u64);
Expand Down Expand Up @@ -93,6 +135,7 @@ fn test_biginteger<B: BigInteger>(zero: B) {
biginteger_arithmetic_test(a, b, zero);
biginteger_bits_test::<B>();
biginteger_conversion_test::<B>();
biginteger_bitwise_ops_test::<B>()
}

#[test]
Expand Down

0 comments on commit 8edec2b

Please sign in to comment.