mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-13 06:43:01 +03:00
impl cond select gadget for int types
This commit is contained in:
parent
35cf68c01d
commit
615c3a763a
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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")))?;
|
||||
|
@ -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::*;
|
||||
|
68
gadgets/src/signed_integer/utilities/select.rs
Normal file
68
gadgets/src/signed_integer/utilities/select.rs
Normal 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);
|
23
gadgets/src/signed_integer/utilities/sign_extend.rs
Normal file
23
gadgets/src/signed_integer/utilities/sign_extend.rs
Normal 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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user