impl twos complement gadget

This commit is contained in:
collin 2020-07-10 19:14:59 -07:00
parent 5288134fd9
commit e9056cfd41
10 changed files with 107 additions and 14 deletions

View File

@ -2,6 +2,9 @@ use snarkos_errors::gadgets::SynthesisError;
#[derive(Debug, Error)]
pub enum IntegerError {
#[error("Negative zero")]
NegativeZero,
#[error("Integer overflow")]
Overflow,

View File

@ -11,7 +11,7 @@ use snarkos_models::{
},
};
/// Modular addition for a signed integer gadget
/// Addition for a signed integer gadget
pub trait Add<Rhs = Self>
where
Self: std::marker::Sized,

View File

@ -1,7 +1,7 @@
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
/// Modular division for a signed integer gadget
/// Division for a signed integer gadget
pub trait Div<Rhs = Self>
where
Self: std::marker::Sized,

View File

@ -8,6 +8,9 @@ pub use self::div::*;
pub mod mul;
pub use self::mul::*;
pub mod twos_complement;
pub use self::twos_complement::*;
pub mod pow;
pub use self::pow::*;

View File

@ -1,7 +1,7 @@
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
/// Modular multiplication for a signed integer gadget
/// Multiplication for a signed integer gadget
pub trait Mul<Rhs = Self>
where
Self: std::marker::Sized,

View File

@ -1,7 +1,7 @@
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
/// Modular exponentiation for a signed integer gadget
/// Exponentiation for a signed integer gadget
pub trait Pow<Rhs = Self>
where
Self: std::marker::Sized,

View File

@ -1,7 +1,7 @@
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
use crate::{errors::IntegerError, Int128, Int16, Int32, Int64, Int8};
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
/// Modular subtraction for a signed integer gadget
/// Subtraction for a signed integer gadget
pub trait Sub<Rhs = Self>
where
Self: std::marker::Sized,
@ -20,4 +20,4 @@ macro_rules! sub_int_impl {
)*)
}
sub_int_impl!(Int8 Int16 Int32 Int64);
sub_int_impl!(Int8 Int16 Int32 Int64 Int128);

View File

@ -0,0 +1,58 @@
use crate::{binary::RippleCarryAdder, errors::IntegerError, signed_integer::*};
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
/// Inverts the given number and adds 1 to the lsb of the result
pub trait TwosComplement
where
Self: std::marker::Sized,
{
#[must_use]
fn twos_comp<F: PrimeField, CS: ConstraintSystem<F>>(&self, cs: CS) -> Result<Self, IntegerError>;
}
macro_rules! twos_comp_int_impl {
($($gadget: ident)*) => ($(
impl TwosComplement for $gadget {
fn twos_comp<F: PrimeField, CS: ConstraintSystem<F>>(
&self,
mut cs: CS
) -> Result<Self, IntegerError> {
let value = match self.value {
Some(val) => {
match val.checked_neg() {
Some(val_neg) => Some(val_neg),
None => return Err(IntegerError::NegativeZero) // -0 should fail
}
}
None => None,
};
println!("val {}", value.unwrap());
// flip all bits
let flipped_bits = self.bits
.iter()
.map(|bit| bit.not())
.collect();
let flipped = Self {
bits: flipped_bits,
value,
};
// add one
let one = Self::one();
let mut bits = flipped.add_bits(cs.ns(|| format!("add one")), &one)?;
let _carry = bits.pop(); // we already accounted for overflow above
Ok(Self {
bits,
value,
})
}
}
)*)
}
twos_comp_int_impl!(Int8 Int16 Int32 Int64 Int128);

View File

@ -6,6 +6,8 @@ pub trait Int: Debug + Clone {
type IntegerType;
const SIZE: usize;
fn one() -> Self;
/// Returns true if all bits in this `Int` are constant
fn is_constant(&self) -> bool;
@ -13,8 +15,6 @@ pub trait Int: Debug + Clone {
fn result_is_constant(first: &Self, second: &Self) -> bool {
first.is_constant() && second.is_constant()
}
fn is_negative(&self) -> bool;
}
/// Implements the base struct for a signed integer gadget
@ -55,6 +55,10 @@ macro_rules! int_impl {
const SIZE: usize = $size;
fn one() -> Self {
Self::constant(1 as $type_)
}
fn is_constant(&self) -> bool {
let mut constant = true;
@ -69,10 +73,6 @@ macro_rules! int_impl {
constant
}
fn is_negative(&self) -> bool {
true
}
}
};
}

View File

@ -1,4 +1,7 @@
use leo_gadgets::{arithmetic::Add, Int8};
use leo_gadgets::{
arithmetic::{Add, Neg},
Int8,
};
use snarkos_models::{
curves::{One, Zero},
gadgets::{
@ -102,3 +105,29 @@ fn test_int8_add() {
assert!(!cs.is_satisfied());
}
}
#[test]
fn test_int8_neg_constants() {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
for _ in 0..1 {
let a: i8 = rng.gen();
println!("{}", a);
let a_bit = Int8::constant(a);
let r = a_bit.neg();
match a.checked_neg() {
Some(expected) => {
println!("result {}", expected);
let result = r.unwrap();
assert!(result.value == Some(expected));
check_all_constant_bits(expected, result);
}
None => assert!(r.is_none()),
}
}
}