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)]
|
#[derive(Debug, Error)]
|
||||||
pub enum IntegerError {
|
pub enum IntegerError {
|
||||||
|
#[error("Negative zero")]
|
||||||
|
NegativeZero,
|
||||||
|
|
||||||
#[error("Integer overflow")]
|
#[error("Integer overflow")]
|
||||||
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>
|
pub trait Add<Rhs = Self>
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized,
|
Self: std::marker::Sized,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
|
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
|
||||||
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
|
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>
|
pub trait Div<Rhs = Self>
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized,
|
Self: std::marker::Sized,
|
||||||
|
@ -8,6 +8,9 @@ pub use self::div::*;
|
|||||||
pub mod mul;
|
pub mod mul;
|
||||||
pub use self::mul::*;
|
pub use self::mul::*;
|
||||||
|
|
||||||
|
pub mod twos_complement;
|
||||||
|
pub use self::twos_complement::*;
|
||||||
|
|
||||||
pub mod pow;
|
pub mod pow;
|
||||||
pub use self::pow::*;
|
pub use self::pow::*;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
|
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
|
||||||
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
|
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>
|
pub trait Mul<Rhs = Self>
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized,
|
Self: std::marker::Sized,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
|
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
|
||||||
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
|
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>
|
pub trait Pow<Rhs = Self>
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized,
|
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};
|
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>
|
pub trait Sub<Rhs = Self>
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized,
|
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;
|
type IntegerType;
|
||||||
const SIZE: usize;
|
const SIZE: usize;
|
||||||
|
|
||||||
|
fn one() -> Self;
|
||||||
|
|
||||||
/// Returns true if all bits in this `Int` are constant
|
/// Returns true if all bits in this `Int` are constant
|
||||||
fn is_constant(&self) -> bool;
|
fn is_constant(&self) -> bool;
|
||||||
|
|
||||||
@ -13,8 +15,6 @@ pub trait Int: Debug + Clone {
|
|||||||
fn result_is_constant(first: &Self, second: &Self) -> bool {
|
fn result_is_constant(first: &Self, second: &Self) -> bool {
|
||||||
first.is_constant() && second.is_constant()
|
first.is_constant() && second.is_constant()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_negative(&self) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implements the base struct for a signed integer gadget
|
/// Implements the base struct for a signed integer gadget
|
||||||
@ -55,6 +55,10 @@ macro_rules! int_impl {
|
|||||||
|
|
||||||
const SIZE: usize = $size;
|
const SIZE: usize = $size;
|
||||||
|
|
||||||
|
fn one() -> Self {
|
||||||
|
Self::constant(1 as $type_)
|
||||||
|
}
|
||||||
|
|
||||||
fn is_constant(&self) -> bool {
|
fn is_constant(&self) -> bool {
|
||||||
let mut constant = true;
|
let mut constant = true;
|
||||||
|
|
||||||
@ -69,10 +73,6 @@ macro_rules! int_impl {
|
|||||||
|
|
||||||
constant
|
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::{
|
use snarkos_models::{
|
||||||
curves::{One, Zero},
|
curves::{One, Zero},
|
||||||
gadgets::{
|
gadgets::{
|
||||||
@ -102,3 +105,29 @@ fn test_int8_add() {
|
|||||||
assert!(!cs.is_satisfied());
|
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