impl cond select gadget for int types

This commit is contained in:
collin 2020-07-10 21:13:19 -07:00
parent 35cf68c01d
commit 615c3a763a
6 changed files with 149 additions and 8 deletions

View File

@ -19,6 +19,29 @@ where
) -> Result<Vec<Boolean>, SynthesisError>;
}
// Generic impl
impl RippleCarryAdder for &[Boolean] {
fn add_bits<F: PrimeField, CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
other: &Self,
) -> Result<Vec<Boolean>, SynthesisError> {
let mut result = vec![];
let mut carry = Boolean::constant(false);
for (i, (a, b)) in self.iter().zip(other.iter()).enumerate() {
let (sum, next) = Boolean::add(cs.ns(|| format!("rpc {}", i)), a, b, &carry)?;
carry = next;
result.push(sum);
}
// append the carry bit to the end
result.push(carry);
Ok(result)
}
}
macro_rules! rpc_impl {
($($gadget: ident)*) => ($(
impl RippleCarryAdder for $gadget {

View File

@ -1,7 +1,13 @@
use crate::{errors::IntegerError, Int16, Int32, Int64, Int8};
use snarkos_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
use crate::{binary::RippleCarryAdder, errors::IntegerError, sign_extend::SignExtend, Int, Int16, Int32, Int64, Int8};
use snarkos_models::{
curves::PrimeField,
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
};
/// Multiplication for a signed integer gadget
/// 1. Sign extend both integers to double precision.
/// 2. Compute double and add.
/// 3. Truncate to original bit size.
pub trait Mul<Rhs = Self>
where
Self: std::marker::Sized,
@ -11,13 +17,28 @@ where
}
macro_rules! mul_int_impl {
($($t:ty)*) => ($(
impl Mul for $t {
fn mul<F: PrimeField, CS: ConstraintSystem<F>>(&self, _cs: CS, _other: &Self) -> Result<(), IntegerError> {
($($gadget: ident)*) => ($(
impl Mul for $gadget {
fn mul<F: PrimeField, CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<(), IntegerError> {
// let is_constant = Boolean::constant(Self::result_is_constant(&self, &other));
// let constant_result = Self::constant(0 as <$gadget as Int>::)
//
// let double = <$gadget as Int>::SIZE * 2;
//
// let a = Boolean::sign_extend(&self.bits, double);
// let b = Boolean::sign_extend(&other.bits, double);
//
// let result =
//
// for bit in b.iter() {
//
// }
Ok(())
}
}
)*)
}
mul_int_impl!(Int8 Int16 Int32 Int64);
// mul_int_impl!(Int8 Int16 Int32 Int64);
mul_int_impl!(Int8);

View File

@ -11,8 +11,8 @@ where
}
macro_rules! sub_int_impl {
($($t:ty)*) => ($(
impl Sub for $t {
($($gadget: ident)*) => ($(
impl Sub for $gadget {
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")))?;

View File

@ -1,3 +1,9 @@
#[macro_use]
pub mod alloc;
pub use self::alloc::*;
pub mod select;
pub use self::select::*;
pub mod sign_extend;
pub use self::sign_extend::*;

View File

@ -0,0 +1,68 @@
use crate::signed_integer::*;
use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{
curves::PrimeField,
gadgets::{
r1cs::{Assignment, ConstraintSystem},
utilities::{alloc::AllocGadget, boolean::Boolean, eq::EqGadget, select::CondSelectGadget},
},
};
macro_rules! select_int_impl {
($($gadget: ident)*) => ($(
impl<F: PrimeField> CondSelectGadget<F> for $gadget {
fn conditionally_select<CS: ConstraintSystem<F>> (
mut cs: CS,
cond: &Boolean,
first: &Self,
second: &Self,
) -> Result<Self, SynthesisError> {
if let Boolean::Constant(cond) = *cond {
if cond {
Ok(first.clone())
} else {
Ok(second.clone())
}
} else {
let result_val = cond.get_value().and_then(|c| {
if c {
first.value
} else {
second.value
}
});
let result = Self::alloc(cs.ns(|| "cond_select_result"), || result_val.get().map(|v| v))?;
let expected_bits = first
.bits
.iter()
.zip(&second.bits)
.enumerate()
.map(|(i, (a, b))| {
Boolean::conditionally_select(
&mut cs.ns(|| format!("{}_cond_select_{}", <$gadget as Int>::SIZE, i)),
cond,
a,
b,
).unwrap()
})
.collect::<Vec<Boolean>>();
for (i, (actual, expected)) in result.bits.iter().zip(expected_bits.iter()).enumerate() {
actual.enforce_equal(&mut cs.ns(|| format!("selected_result_bit_{}", i)), expected)?;
}
Ok(result)
}
}
fn cost() -> usize {
unimplemented!();
}
}
)*)
}
select_int_impl!(Int8 Int16 Int32 Int64 Int128);

View File

@ -0,0 +1,23 @@
use snarkos_models::gadgets::utilities::boolean::Boolean;
/// Sign extends an array of bits to the desired length.
/// Least significant bit first
pub trait SignExtend
where
Self: std::marker::Sized,
{
#[must_use]
fn sign_extend(bits: &[Self], length: usize) -> Vec<Self>;
}
impl SignExtend for Boolean {
fn sign_extend(bits: &[Boolean], length: usize) -> Vec<Self> {
let msb = bits.last().expect("empty bit list");
let mut extension = vec![msb.clone(); length];
let mut result = Vec::from(bits);
result.append(&mut extension);
result
}
}