perf: reduce allocations in AllocGadget::{alloc, alloc_input}

Signed-off-by: ljedrz <ljedrz@gmail.com>
This commit is contained in:
ljedrz 2020-10-22 12:53:12 +02:00
parent 55d0f2e340
commit 63f80c0472

View File

@ -16,7 +16,7 @@
use crate::{Int, Int128, Int16, Int32, Int64, Int8}; use crate::{Int, Int128, Int16, Int32, Int64, Int8};
use core::borrow::Borrow; use core::{borrow::Borrow, iter};
use snarkos_errors::gadgets::SynthesisError; use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{ use snarkos_models::{
curves::Field, curves::Field,
@ -29,6 +29,21 @@ use snarkos_models::{
}, },
}; };
fn create_value<T: Borrow<bool>, I: IntoIterator<Item = Option<T>>, F: Field, CS: ConstraintSystem<F>>(
cs: &mut CS,
iter: I,
) -> Result<Vec<Boolean>, SynthesisError> {
iter.into_iter()
.enumerate()
.map(|(i, v)| {
Ok(Boolean::from(AllocatedBit::alloc(
&mut cs.ns(|| format!("allocated bit_gadget {}", i)),
|| v.ok_or(SynthesisError::AssignmentMissing),
)?))
})
.collect()
}
macro_rules! alloc_int_impl { macro_rules! alloc_int_impl {
($($gadget: ident)*) => ($( ($($gadget: ident)*) => ($(
impl<F: Field> AllocGadget<<$gadget as Int>::IntegerType, F> for $gadget { impl<F: Field> AllocGadget<<$gadget as Int>::IntegerType, F> for $gadget {
@ -41,30 +56,21 @@ macro_rules! alloc_int_impl {
value_gen: Fn, value_gen: Fn,
) -> Result<Self, SynthesisError> { ) -> Result<Self, SynthesisError> {
let value = value_gen().map(|val| *val.borrow()); let value = value_gen().map(|val| *val.borrow());
let values = match value {
let bits = match value {
Ok(mut val) => { Ok(mut val) => {
let mut v = Vec::with_capacity(<$gadget as Int>::SIZE); let mut v = Vec::with_capacity(<$gadget as Int>::SIZE);
for _ in 0..<$gadget as Int>::SIZE { for _ in 0..<$gadget as Int>::SIZE {
v.push(Some(val & 1 == 1)); v.push(Some(val & 1 == 1));
val >>= 1; val >>= 1;
} }
create_value(&mut cs, v)
v
} }
_ => vec![None; <$gadget as Int>::SIZE], Err(_) => {
}; let i = iter::repeat(None::<bool>).take(<$gadget as Int>::SIZE);
create_value(&mut cs, i)
let bits = values },
.into_iter() }?;
.enumerate()
.map(|(i, v)| {
Ok(Boolean::from(AllocatedBit::alloc(
&mut cs.ns(|| format!("allocated bit_gadget {}", i)),
|| v.ok_or(SynthesisError::AssignmentMissing),
)?))
})
.collect::<Result<Vec<_>, SynthesisError>>()?;
Ok(Self { Ok(Self {
bits, bits,
@ -81,30 +87,21 @@ macro_rules! alloc_int_impl {
value_gen: Fn, value_gen: Fn,
) -> Result<Self, SynthesisError> { ) -> Result<Self, SynthesisError> {
let value = value_gen().map(|val| *val.borrow()); let value = value_gen().map(|val| *val.borrow());
let values = match value {
let bits = match value {
Ok(mut val) => { Ok(mut val) => {
let mut v = Vec::with_capacity(<$gadget as Int>::SIZE); let mut v = Vec::with_capacity(<$gadget as Int>::SIZE);
for _ in 0..<$gadget as Int>::SIZE { for _ in 0..<$gadget as Int>::SIZE {
v.push(Some(val & 1 == 1)); v.push(Some(val & 1 == 1));
val >>= 1; val >>= 1;
} }
create_value(&mut cs, v)
v
} }
_ => vec![None; <$gadget as Int>::SIZE], Err(_) => {
}; let i = iter::repeat(None::<bool>).take(<$gadget as Int>::SIZE);
create_value(&mut cs, i)
let bits = values },
.into_iter() }?;
.enumerate()
.map(|(i, v)| {
Ok(Boolean::from(AllocatedBit::alloc(
&mut cs.ns(|| format!("allocated bit_gadget {}", i)),
|| v.ok_or(SynthesisError::AssignmentMissing),
)?))
})
.collect::<Result<Vec<_>, SynthesisError>>()?;
Ok(Self { Ok(Self {
bits, bits,