impl sub for int types

This commit is contained in:
collin 2020-07-10 19:34:20 -07:00
parent e9056cfd41
commit 35cf68c01d
3 changed files with 73 additions and 23 deletions

View File

@ -1,4 +1,4 @@
use crate::{errors::IntegerError, Int128, Int16, Int32, Int64, Int8};
use crate::{errors::IntegerError, Add, Int128, Int16, Int32, Int64, Int8, TwosComplement};
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
/// Subtraction for a signed integer gadget
@ -7,14 +7,18 @@ where
Self: std::marker::Sized,
{
#[must_use]
fn sub<F: PrimeField, CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<(), IntegerError>;
fn sub<F: PrimeField, CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, IntegerError>;
}
macro_rules! sub_int_impl {
($($t:ty)*) => ($(
impl Sub for $t {
fn sub<F: PrimeField, CS: ConstraintSystem<F>>(&self, _cs: CS, _other: &Self) -> Result<(), IntegerError> {
Ok(())
fn sub<F: PrimeField, CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self) -> Result<Self, IntegerError> {
// Evaluate the two's complement of the subtrahend
let s = other.twos_comp(cs.ns(|| format!("complement")))?;
// Add minuend + subtrahend
self.add(cs.ns(|| format!("add_complement")), &s)
}
}
)*)

View File

@ -27,7 +27,6 @@ macro_rules! twos_comp_int_impl {
}
None => None,
};
println!("val {}", value.unwrap());
// flip all bits
let flipped_bits = self.bits

View File

@ -1,7 +1,4 @@
use leo_gadgets::{
arithmetic::{Add, Neg},
Int8,
};
use leo_gadgets::{arithmetic::*, Int8};
use snarkos_models::{
curves::{One, Zero},
gadgets::{
@ -107,27 +104,77 @@ fn test_int8_add() {
}
#[test]
fn test_int8_neg_constants() {
fn test_int8_sub_constants() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1 {
let a: i8 = rng.gen();
for _ in 0..1000 {
let mut cs = TestConstraintSystem::<Fr>::new();
println!("{}", a);
let a: i8 = rng.gen();
let b: i8 = rng.gen();
if b.checked_neg().is_none() {
// negate with overflows will fail: -128
continue;
}
let expected = match a.checked_sub(b) {
// subtract with overflow will fail: -0
Some(valid) => valid,
None => continue,
};
let a_bit = Int8::constant(a);
let b_bit = Int8::constant(b);
let r = a_bit.neg();
let r = a_bit.sub(cs.ns(|| "subtraction"), &b_bit).unwrap();
match a.checked_neg() {
Some(expected) => {
println!("result {}", expected);
let result = r.unwrap();
assert!(result.value == Some(expected));
assert!(r.value == Some(expected));
check_all_constant_bits(expected, result);
}
None => assert!(r.is_none()),
}
check_all_constant_bits(expected, r);
}
}
#[test]
fn test_int8_sub() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1000 {
let mut cs = TestConstraintSystem::<Fr>::new();
let a: i8 = rng.gen();
let b: i8 = rng.gen();
if b.checked_neg().is_none() {
// negate with overflows will fail: -128
continue;
}
let expected = match a.checked_sub(b) {
// subtract with overflow will fail: -0
Some(valid) => valid,
None => continue,
};
let a_bit = Int8::alloc(cs.ns(|| "a_bit"), || Ok(a)).unwrap();
let b_bit = Int8::alloc(cs.ns(|| "b_bit"), || Ok(b)).unwrap();
let r = a_bit.sub(cs.ns(|| "subtraction"), &b_bit).unwrap();
assert!(cs.is_satisfied());
assert!(r.value == Some(expected));
check_all_allocated_bits(expected, r);
// Flip a bit_gadget and see if the subtraction constraint still works
if cs
.get("subtraction/add_complement/result bit_gadget 0/boolean")
.is_zero()
{
cs.set("subtraction/add_complement/result bit_gadget 0/boolean", Fr::one());
} else {
cs.set("subtraction/add_complement/result bit_gadget 0/boolean", Fr::zero());
}
assert!(!cs.is_satisfied());
}
}