Add ZeroOutGenerator

This commit is contained in:
wborgeaud 2021-06-25 15:11:49 +02:00
parent fd3fa739a6
commit beadce72fc
3 changed files with 158 additions and 24 deletions

View File

@ -146,7 +146,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.route_extension(addend_0, wire_addend_0);
self.route_extension(multiplicand_1, wire_multiplicand_1);
self.route_extension(addend_1, wire_addend_1);
self.route_extension(multiplicand_1, wire_multiplicand_1);
(wire_output_0, wire_output_1)
}

View File

@ -1,3 +1,5 @@
use std::ops::Range;
use crate::circuit_builder::CircuitBuilder;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, FieldExtension};
@ -207,10 +209,12 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// Add an `ArithmeticExtensionGate` to compute `q * y`.
let gate = self.add_gate(ArithmeticExtensionGate::new(), vec![F::ONE, F::ZERO]);
let multiplicand_0 =
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_multiplicand_0());
let multiplicand_0 = ExtensionTarget::from_range(
gate,
ArithmeticExtensionGate::<D>::wires_fixed_multiplicand(),
);
let multiplicand_1 =
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_multiplicand_1());
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_multiplicand_0());
let output =
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_output_0());
@ -219,33 +223,22 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
denominator: y,
quotient: multiplicand_0,
});
self.add_generator(ZeroOutGenerator {
gate_index: gate,
ranges: vec![
ArithmeticExtensionGate::<D>::wires_addend_0(),
ArithmeticExtensionGate::<D>::wires_multiplicand_1(),
ArithmeticExtensionGate::<D>::wires_addend_1(),
],
});
self.route_extension(y, multiplicand_1);
self.assert_equal_extension(output, x);
multiplicand_0
}
}
struct QuotientGenerator {
numerator: Target,
denominator: Target,
quotient: Target,
}
impl<F: Field> SimpleGenerator<F> for QuotientGenerator {
fn dependencies(&self) -> Vec<Target> {
vec![self.numerator, self.denominator]
}
fn run_once(&self, witness: &PartialWitness<F>) -> PartialWitness<F> {
let num = witness.get_target(self.numerator);
let den = witness.get_target(self.denominator);
PartialWitness::singleton_target(self.quotient, num / den)
}
}
struct QuotientGeneratorExtension<const D: usize> {
numerator: ExtensionTarget<D>,
denominator: ExtensionTarget<D>,
@ -270,6 +263,32 @@ impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for QuotientGeneratorE
quotient.to_basefield_array()[i],
);
}
pw
}
}
/// Generator used to zero out wires at a given gate index and ranges.
pub struct ZeroOutGenerator {
gate_index: usize,
ranges: Vec<Range<usize>>,
}
impl<F: Field> SimpleGenerator<F> for ZeroOutGenerator {
fn dependencies(&self) -> Vec<Target> {
Vec::new()
}
fn run_once(&self, _witness: &PartialWitness<F>) -> PartialWitness<F> {
let mut pw = PartialWitness::new();
for t in self
.ranges
.iter()
.flat_map(|r| Target::wires_from_range(self.gate_index, r.clone()))
{
pw.set_target(t, F::ZERO);
}
pw
}
}

View File

@ -1,8 +1,14 @@
use std::borrow::Borrow;
use crate::field::extension_field::Frobenius;
use crate::circuit_builder::CircuitBuilder;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, Frobenius};
use crate::field::field::Field;
use crate::gates::mul_extension::ArithmeticExtensionGate;
use crate::generator::SimpleGenerator;
use crate::polynomial::polynomial::PolynomialCoeffs;
use crate::target::Target;
use crate::witness::PartialWitness;
/// When verifying the composition polynomial in FRI we have to compute sums of the form
/// `(sum_0^k a^i * x_i)/d_0 + (sum_k^r a^i * y_i)/d_1`
@ -73,3 +79,113 @@ impl<F: Field> ReducingFactor<F> {
}
}
}
// #[derive(Debug, Copy, Clone)]
// pub struct ReducingFactorTarget<const D: usize> {
// base: ExtensionTarget<D>,
// count: u64,
// }
//
// impl<F: Extendable<D>, const D: usize> ReducingFactorTarget<D> {
// pub fn new(base: ExtensionTarget<D>) -> Self {
// Self { base, count: 0 }
// }
//
// fn mul(
// &mut self,
// x: ExtensionTarget<D>,
// builder: &mut CircuitBuilder<F, D>,
// ) -> ExtensionTarget<D> {
// self.count += 1;
// builder.mul_extension(self.base, x)
// }
//
// pub fn reduce(
// &mut self,
// iter: &[ExtensionTarget<D>], // Could probably work with a `DoubleEndedIterator` too.
// builder: &mut CircuitBuilder<F, D>,
// ) -> ExtensionTarget<D> {
// let l = iter.len();
// let padded_iter = if l % 2 == 0 {
// iter.to_vec()
// } else {
// [iter, &[builder.zero_extension()]].concat()
// };
// let half_length = padded_iter.len() / 2;
// let gates = (0..half_length)
// .map(|_| builder.add_gate(ArithmeticExtensionGate::new(), vec![F::ONE, F::ONE]))
// .collect::<Vec<_>>();
//
// struct ParallelReductionGenerator<'a, const D: usize> {
// base: ExtensionTarget<D>,
// padded_iter: &'a [ExtensionTarget<D>],
// gates: &'a [usize],
// half_length: usize,
// }
//
// impl<'a, F: Extendable<D>, const D: usize> SimpleGenerator<F>
// for ParallelReductionGenerator<'a, D>
// {
// fn dependencies(&self) -> Vec<Target> {
// self.padded_iter
// .iter()
// .flat_map(|ext| ext.to_target_array())
// .chain(self.base.to_target_array())
// .collect()
// }
//
// fn run_once(&self, witness: &PartialWitness<F>) -> PartialWitness<F> {
// let mut pw = PartialWitness::new();
// let base = witness.get_extension_target(self.base);
// let vs = self
// .padded_iter
// .iter()
// .map(|&ext| witness.get_extension_target(ext))
// .collect::<Vec<_>>();
// let first_half = &vs[..self.half_length];
// let intermediate_acc = base.reduce(first_half);
// }
// }
// }
//
// pub fn reduce_parallel(
// &mut self,
// iter0: impl DoubleEndedIterator<Item = impl Borrow<ExtensionTarget<D>>>,
// iter1: impl DoubleEndedIterator<Item = impl Borrow<ExtensionTarget<D>>>,
// builder: &mut CircuitBuilder<F, D>,
// ) -> (ExtensionTarget<D>, ExtensionTarget<D>) {
// iter.rev().fold(builder.zero_extension(), |acc, x| {
// builder.arithmetic_extension(F::ONE, F::ONE, self.base, acc, x)
// })
// }
//
// pub fn shift(
// &mut self,
// x: ExtensionTarget<D>,
// builder: &mut CircuitBuilder<F, D>,
// ) -> ExtensionTarget<D> {
// let tmp = self.base.exp(self.count) * x;
// self.count = 0;
// tmp
// }
//
// pub fn shift_poly(
// &mut self,
// p: &mut PolynomialCoeffs<ExtensionTarget<D>>,
// builder: &mut CircuitBuilder<F, D>,
// ) {
// *p *= self.base.exp(self.count);
// self.count = 0;
// }
//
// pub fn reset(&mut self) {
// self.count = 0;
// }
//
// pub fn repeated_frobenius(&self, count: usize, builder: &mut CircuitBuilder<F, D>) -> Self {
// Self {
// base: self.base.repeated_frobenius(count),
// count: self.count,
// }
// }
// }