mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-22 11:17:37 +03:00
impl twos complement gadget
This commit is contained in:
parent
5288134fd9
commit
e9056cfd41
@ -2,6 +2,9 @@ use snarkos_errors::gadgets::SynthesisError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum IntegerError {
|
||||
#[error("Negative zero")]
|
||||
NegativeZero,
|
||||
|
||||
#[error("Integer overflow")]
|
||||
Overflow,
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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::*;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
58
gadgets/src/signed_integer/arithmetic/twos_complement.rs
Normal file
58
gadgets/src/signed_integer/arithmetic/twos_complement.rs
Normal 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);
|
@ -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
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user