use crate::expression::{BinaryExpression, BooleanExpression};
use crate::field::Field;
use crate::gadget_builder::GadgetBuilder;
impl<F: Field> GadgetBuilder<F> {
pub fn bitwise_not(&mut self, x: &BinaryExpression<F>) -> BinaryExpression<F> {
let bits = x.bits.iter()
.map(|w| self.not(w))
.collect();
BinaryExpression { bits }
}
pub fn bitwise_and(
&mut self, x: &BinaryExpression<F>, y: &BinaryExpression<F>,
) -> BinaryExpression<F> {
assert_eq!(x.len(), y.len());
let l = x.len();
let bits = (0..l).map(|i|
self.and(&x.bits[i], &y.bits[i])
).collect();
BinaryExpression { bits }
}
pub fn bitwise_or(
&mut self, x: &BinaryExpression<F>, y: &BinaryExpression<F>,
) -> BinaryExpression<F> {
assert_eq!(x.len(), y.len());
let l = x.len();
let bits = (0..l).map(|i|
self.or(&x.bits[i], &y.bits[i])
).collect();
BinaryExpression { bits }
}
pub fn bitwise_xor<BE1, BE2>(
&mut self, x: &BinaryExpression<F>, y: &BinaryExpression<F>,
) -> BinaryExpression<F> {
assert_eq!(x.len(), y.len());
let l = x.len();
let bits = (0..l).map(|i|
self.xor(&x.bits[i], &y.bits[i])
).collect();
BinaryExpression { bits }
}
pub fn bitwise_rotate_inc_significance(
&mut self, x: &BinaryExpression<F>, n: usize,
) -> BinaryExpression<F> {
let l = x.len();
let bits = (0..l).map(|i| {
let from_idx = (l + i - n % l) % l;
x.bits[from_idx].clone()
}).collect();
BinaryExpression { bits }
}
pub fn bitwise_rotate_dec_significance(
&mut self, x: &BinaryExpression<F>, n: usize,
) -> BinaryExpression<F> {
let l = x.len();
let bits = (0..l).map(|i| {
let from_idx = (i + n) % l;
x.bits[from_idx].clone()
}).collect();
BinaryExpression { bits }
}
pub fn bitwise_shift_inc_significance(
&mut self, x: &BinaryExpression<F>, n: usize,
) -> BinaryExpression<F> {
let bits = (0..x.len()).map(|i| {
if i < n {
BooleanExpression::_false()
} else {
let from_idx = i - n;
x.bits[from_idx].clone()
}
}).collect();
BinaryExpression { bits }
}
pub fn bitwise_shift_dec_significance(
&mut self, x: &BinaryExpression<F>, n: usize,
) -> BinaryExpression<F> {
let l = x.len();
let bits = (0..l).map(|i| {
if i < l - n {
let from_idx = i + n;
x.bits[from_idx].clone()
} else {
BooleanExpression::_false()
}
}).collect();
BinaryExpression { bits }
}
}
#[cfg(test)]
mod tests {
use num::BigUint;
use crate::expression::BinaryExpression;
use crate::gadget_builder::GadgetBuilder;
use crate::test_util::F257;
#[test]
fn bitwise_not() {
let mut builder = GadgetBuilder::<F257>::new();
let x = builder.binary_wire(8);
let not_x = builder.bitwise_not(&BinaryExpression::from(&x));
let gadget = builder.build();
let mut values = binary_unsigned_values!(&x => &BigUint::from(0b00010011u32));
assert!(gadget.execute(&mut values));
assert_eq!(BigUint::from(0b11101100u32), not_x.evaluate(&values));
}
#[test]
fn bitwise_and() {
let mut builder = GadgetBuilder::<F257>::new();
let x = builder.binary_wire(8);
let y = builder.binary_wire(8);
let x_and_y = builder.bitwise_and(&BinaryExpression::from(&x), &BinaryExpression::from(&y));
let gadget = builder.build();
let mut values_0_0 = binary_unsigned_values!(
&x => &BigUint::from(0u32),
&y => &BigUint::from(0u32));
assert!(gadget.execute(&mut values_0_0));
assert_eq!(BigUint::from(0u32), x_and_y.evaluate(&values_0_0));
let mut values_255_0 = binary_unsigned_values!(
&x => &BigUint::from(0b11111111u32),
&y => &BigUint::from(0u32));
assert!(gadget.execute(&mut values_255_0));
assert_eq!(BigUint::from(0u32), x_and_y.evaluate(&values_255_0));
let mut values_255_255 = binary_unsigned_values!(
&x => &BigUint::from(0b11111111u32),
&y => &BigUint::from(0b11111111u32));
assert!(gadget.execute(&mut values_255_255));
assert_eq!(BigUint::from(0b11111111u32), x_and_y.evaluate(&values_255_255));
let mut values_11111100_00111111 = binary_unsigned_values!(
&x => &BigUint::from(0b11111100u32),
&y => &BigUint::from(0b00111111u32));
assert!(gadget.execute(&mut values_11111100_00111111));
assert_eq!(BigUint::from(0b00111100u32), x_and_y.evaluate(&values_11111100_00111111));
}
#[test]
fn bitwise_rotate_dec_significance() {
let mut builder = GadgetBuilder::<F257>::new();
let x = builder.binary_wire(8);
let x_rot = builder.bitwise_rotate_dec_significance(&BinaryExpression::from(&x), 3);
let gadget = builder.build();
let mut values_zero = binary_unsigned_values!(&x => &BigUint::from(0u32));
assert!(gadget.execute(&mut values_zero));
assert_eq!(BigUint::from(0u32), x_rot.evaluate(&values_zero));
let mut values_nonzero = binary_unsigned_values!(&x => &BigUint::from(0b00010011u32));
assert!(gadget.execute(&mut values_nonzero));
assert_eq!(BigUint::from(0b01100010u32), x_rot.evaluate(&values_nonzero));
}
#[test]
fn bitwise_rotate_dec_significance_multiple_wraps() {
let mut builder = GadgetBuilder::<F257>::new();
let x = builder.binary_wire(8);
let x_rot = builder.bitwise_rotate_dec_significance(&BinaryExpression::from(&x), 19);
let gadget = builder.build();
let mut values = binary_unsigned_values!(&x => &BigUint::from(0b00010011u32));
assert!(gadget.execute(&mut values));
assert_eq!(BigUint::from(0b01100010u32), x_rot.evaluate(&values));
}
}