Merge pull request #181 from mir-protocol/push_to_8192

Final arithmetic optimization and recursive circuit with `<2^13` gates
This commit is contained in:
wborgeaud 2021-08-17 08:48:10 +02:00 committed by GitHub
commit 20cf073e2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 174 additions and 519 deletions

View File

@ -41,23 +41,14 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let coset_start = self.mul(start, x); let coset_start = self.mul(start, x);
// The answer is gotten by interpolating {(x*g^i, P(x*g^i))} and evaluating at beta. // The answer is gotten by interpolating {(x*g^i, P(x*g^i))} and evaluating at beta.
let g_powers = g let points = g
.powers() .powers()
.take(arity) .map(|y| {
.map(|y| self.constant(y)) let yc = self.constant(y);
self.mul(coset_start, yc)
})
.zip(evals)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut coset = Vec::new();
for i in 0..arity / 2 {
let res = self.mul_two(
coset_start,
g_powers[2 * i],
coset_start,
g_powers[2 * i + 1],
);
coset.push(res.0);
coset.push(res.1);
}
let points = coset.into_iter().zip(evals).collect::<Vec<_>>();
self.interpolate(&points, beta) self.interpolate(&points, beta)
} }
@ -100,7 +91,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// Size of the LDE domain. // Size of the LDE domain.
let n = proof.final_poly.len() << (total_arities + config.rate_bits); let n = proof.final_poly.len() << (total_arities + config.rate_bits);
challenger.observe_opening_set(&os); challenger.observe_opening_set(os);
// Scaling factor to combine polynomials. // Scaling factor to combine polynomials.
let alpha = challenger.get_extension_challenge(self); let alpha = challenger.get_extension_challenge(self);
@ -265,14 +256,11 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
precomputed_reduced_evals.slope, precomputed_reduced_evals.slope,
precomputed_reduced_evals.zs, precomputed_reduced_evals.zs,
); );
let (zs_numerator, vanish_zeta_right) = self.sub_two_extension( let zs_numerator = self.sub_extension(zs_composition_eval, interpol_val);
zs_composition_eval, let vanish_zeta_right =
interpol_val, self.sub_extension(subgroup_x, precomputed_reduced_evals.zeta_right);
subgroup_x, sum = alpha.shift(sum, self);
precomputed_reduced_evals.zeta_right, let zs_denominator = self.mul_extension(vanish_zeta, vanish_zeta_right);
);
let (mut sum, zs_denominator) =
alpha.shift_and_mul(sum, vanish_zeta, vanish_zeta_right, self);
sum = self.div_add_extension(zs_numerator, zs_denominator, sum); sum = self.div_add_extension(zs_numerator, zs_denominator, sum);
sum sum
@ -296,8 +284,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
// TODO: Do we need to range check `x_index` to a target smaller than `p`? // TODO: Do we need to range check `x_index` to a target smaller than `p`?
let x_index = challenger.get_challenge(self); let x_index = challenger.get_challenge(self);
let mut x_index_bits = self.low_bits(x_index, n_log, 64); let mut x_index_bits = self.low_bits(x_index, n_log, 64);
let cap_index = self let cap_index =
.le_sum(x_index_bits[x_index_bits.len() - common_data.config.cap_height..].into_iter()); self.le_sum(x_index_bits[x_index_bits.len() - common_data.config.cap_height..].iter());
with_context!( with_context!(
self, self,
"check FRI initial proof", "check FRI initial proof",
@ -317,19 +305,10 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let phi = self.exp_from_bits(phi, x_index_bits.iter().rev()); let phi = self.exp_from_bits(phi, x_index_bits.iter().rev());
let g_ext = self.convert_to_ext(g); let g_ext = self.convert_to_ext(g);
let phi_ext = self.convert_to_ext(phi); let phi_ext = self.convert_to_ext(phi);
let zero = self.zero_extension();
// `subgroup_x = g*phi, vanish_zeta = g*phi - zeta` // `subgroup_x = g*phi, vanish_zeta = g*phi - zeta`
let tmp = self.double_arithmetic_extension( let subgroup_x = self.mul(g, phi);
F::ONE, let vanish_zeta = self.mul_sub_extension(g_ext, phi_ext, zeta);
F::NEG_ONE, (subgroup_x, vanish_zeta)
g_ext,
phi_ext,
zero,
g_ext,
phi_ext,
zeta,
);
(tmp.0 .0[0], tmp.1)
}); });
// old_eval is the last derived evaluation; it will be checked for consistency with its // old_eval is the last derived evaluation; it will be checked for consistency with its
@ -369,7 +348,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
"infer evaluation using interpolation", "infer evaluation using interpolation",
self.compute_evaluation( self.compute_evaluation(
subgroup_x, subgroup_x,
&x_index_within_coset_bits, x_index_within_coset_bits,
arity_bits, arity_bits,
evals, evals,
betas[i], betas[i],
@ -409,7 +388,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
struct PrecomputedReducedEvalsTarget<const D: usize> { struct PrecomputedReducedEvalsTarget<const D: usize> {
pub single: ExtensionTarget<D>, pub single: ExtensionTarget<D>,
pub zs: ExtensionTarget<D>, pub zs: ExtensionTarget<D>,
pub zs_right: ExtensionTarget<D>,
/// Slope of the line from `(zeta, zs)` to `(zeta_right, zs_right)`. /// Slope of the line from `(zeta, zs)` to `(zeta_right, zs_right)`.
pub slope: ExtensionTarget<D>, pub slope: ExtensionTarget<D>,
pub zeta_right: ExtensionTarget<D>, pub zeta_right: ExtensionTarget<D>,
@ -440,12 +418,12 @@ impl<const D: usize> PrecomputedReducedEvalsTarget<D> {
let g = builder.constant_extension(F::Extension::primitive_root_of_unity(degree_log)); let g = builder.constant_extension(F::Extension::primitive_root_of_unity(degree_log));
let zeta_right = builder.mul_extension(g, zeta); let zeta_right = builder.mul_extension(g, zeta);
let (numerator, denominator) = builder.sub_two_extension(zs_right, zs, zeta_right, zeta); let numerator = builder.sub_extension(zs_right, zs);
let denominator = builder.sub_extension(zeta_right, zeta);
Self { Self {
single, single,
zs, zs,
zs_right,
slope: builder.div_extension(numerator, denominator), slope: builder.div_extension(numerator, denominator),
zeta_right, zeta_right,
} }

View File

@ -86,16 +86,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.arithmetic(F::ONE, x, y, F::ZERO, x) self.arithmetic(F::ONE, x, y, F::ZERO, x)
} }
/// Computes `x * y`.
pub fn mul_two(&mut self, a0: Target, b0: Target, a1: Target, b1: Target) -> (Target, Target) {
let a0_ext = self.convert_to_ext(a0);
let b0_ext = self.convert_to_ext(b0);
let a1_ext = self.convert_to_ext(a1);
let b1_ext = self.convert_to_ext(b1);
let res = self.mul_two_extension(a0_ext, b0_ext, a1_ext, b1_ext);
(res.0 .0[0], res.1 .0[0])
}
/// Multiply `n` `Target`s with `ceil(n/2) + 1` `ArithmeticExtensionGate`s. /// Multiply `n` `Target`s with `ceil(n/2) + 1` `ArithmeticExtensionGate`s.
pub fn mul_many(&mut self, terms: &[Target]) -> Target { pub fn mul_many(&mut self, terms: &[Target]) -> Target {
let terms_ext = terms let terms_ext = terms

View File

@ -1,12 +1,11 @@
use std::convert::TryInto; use std::convert::TryInto;
use itertools::Itertools;
use num::Integer; use num::Integer;
use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget};
use crate::field::extension_field::{Extendable, OEF}; use crate::field::extension_field::{Extendable, OEF};
use crate::field::field_types::Field; use crate::field::field_types::Field;
use crate::gates::arithmetic::ArithmeticExtensionGate; use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS};
use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::iop::witness::PartialWitness; use crate::iop::witness::PartialWitness;
@ -14,51 +13,28 @@ use crate::plonk::circuit_builder::CircuitBuilder;
use crate::util::bits_u64; use crate::util::bits_u64;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> { impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn double_arithmetic_extension( /// Finds the last available arithmetic gate with the given constants or add one if there aren't any.
&mut self, /// Returns `(g,i)` such that there is an arithmetic gate with the given constants at index
const_0: F, /// `g` and the gate's `i`-th operation is available.
const_1: F, fn find_arithmetic_gate(&mut self, const_0: F, const_1: F) -> (usize, usize) {
first_multiplicand_0: ExtensionTarget<D>, let (gate, i) = self
first_multiplicand_1: ExtensionTarget<D>, .free_arithmetic
first_addend: ExtensionTarget<D>, .get(&(const_0, const_1))
second_multiplicand_0: ExtensionTarget<D>, .copied()
second_multiplicand_1: ExtensionTarget<D>, .unwrap_or_else(|| {
second_addend: ExtensionTarget<D>, let gate = self.add_gate(ArithmeticExtensionGate, vec![const_0, const_1]);
) -> (ExtensionTarget<D>, ExtensionTarget<D>) { (gate, 0)
let gate = self.add_gate(ArithmeticExtensionGate, vec![const_0, const_1]); });
let wire_first_multiplicand_0 = ExtensionTarget::from_range( // Update `free_arithmetic` with new values.
gate, if i < NUM_ARITHMETIC_OPS - 1 {
ArithmeticExtensionGate::<D>::wires_first_multiplicand_0(), self.free_arithmetic
); .insert((const_0, const_1), (gate, i + 1));
let wire_first_multiplicand_1 = ExtensionTarget::from_range( } else {
gate, self.free_arithmetic.remove(&(const_0, const_1));
ArithmeticExtensionGate::<D>::wires_first_multiplicand_1(), }
);
let wire_first_addend =
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_first_addend());
let wire_second_multiplicand_0 = ExtensionTarget::from_range(
gate,
ArithmeticExtensionGate::<D>::wires_second_multiplicand_0(),
);
let wire_second_multiplicand_1 = ExtensionTarget::from_range(
gate,
ArithmeticExtensionGate::<D>::wires_second_multiplicand_1(),
);
let wire_second_addend =
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_second_addend());
let wire_first_output =
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_first_output());
let wire_second_output =
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_second_output());
self.route_extension(first_multiplicand_0, wire_first_multiplicand_0); (gate, i)
self.route_extension(first_multiplicand_1, wire_first_multiplicand_1);
self.route_extension(first_addend, wire_first_addend);
self.route_extension(second_multiplicand_0, wire_second_multiplicand_0);
self.route_extension(second_multiplicand_1, wire_second_multiplicand_1);
self.route_extension(second_addend, wire_second_addend);
(wire_first_output, wire_second_output)
} }
pub fn arithmetic_extension( pub fn arithmetic_extension(
@ -80,18 +56,23 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
return result; return result;
} }
let zero = self.zero_extension(); let (gate, i) = self.find_arithmetic_gate(const_0, const_1);
self.double_arithmetic_extension( let wires_multiplicand_0 = ExtensionTarget::from_range(
const_0, gate,
const_1, ArithmeticExtensionGate::<D>::wires_ith_multiplicand_0(i),
multiplicand_0, );
multiplicand_1, let wires_multiplicand_1 = ExtensionTarget::from_range(
addend, gate,
zero, ArithmeticExtensionGate::<D>::wires_ith_multiplicand_1(i),
zero, );
zero, let wires_addend =
) ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_ith_addend(i));
.0
self.route_extension(multiplicand_0, wires_multiplicand_0);
self.route_extension(multiplicand_1, wires_multiplicand_1);
self.route_extension(addend, wires_addend);
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_ith_output(i))
} }
/// Checks for special cases where the value of /// Checks for special cases where the value of
@ -172,21 +153,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pairs: Vec<(ExtensionTarget<D>, ExtensionTarget<D>)>, pairs: Vec<(ExtensionTarget<D>, ExtensionTarget<D>)>,
) -> ExtensionTarget<D> { ) -> ExtensionTarget<D> {
let mut acc = starting_acc; let mut acc = starting_acc;
for chunk in pairs.chunks_exact(2) { for (a, b) in pairs {
let (a0, b0) = chunk[0]; acc = self.arithmetic_extension(constant, F::ONE, a, b, acc);
let (a1, b1) = chunk[1];
let gate = self.num_gates();
let first_out = ExtensionTarget::from_range(
gate,
ArithmeticExtensionGate::<D>::wires_first_output(),
);
acc = self
.double_arithmetic_extension(constant, F::ONE, a0, b0, acc, a1, b1, first_out)
.1;
}
if pairs.len().is_odd() {
let n = pairs.len() - 1;
acc = self.arithmetic_extension(constant, F::ONE, pairs[n].0, pairs[n].1, acc);
} }
acc acc
} }
@ -200,38 +168,15 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.arithmetic_extension(F::ONE, F::ONE, one, a, b) self.arithmetic_extension(F::ONE, F::ONE, one, a, b)
} }
/// Returns `(a0+b0, a1+b1)`.
pub fn add_two_extension(
&mut self,
a0: ExtensionTarget<D>,
b0: ExtensionTarget<D>,
a1: ExtensionTarget<D>,
b1: ExtensionTarget<D>,
) -> (ExtensionTarget<D>, ExtensionTarget<D>) {
let one = self.one_extension();
self.double_arithmetic_extension(F::ONE, F::ONE, one, a0, b0, one, a1, b1)
}
pub fn add_ext_algebra( pub fn add_ext_algebra(
&mut self, &mut self,
a: ExtensionAlgebraTarget<D>, mut a: ExtensionAlgebraTarget<D>,
b: ExtensionAlgebraTarget<D>, b: ExtensionAlgebraTarget<D>,
) -> ExtensionAlgebraTarget<D> { ) -> ExtensionAlgebraTarget<D> {
// We run two additions in parallel. So `[a0,a1,a2,a3] + [b0,b1,b2,b3]` is computed with two for i in 0..D {
// `add_two_extension`, first `[a0,a1]+[b0,b1]` then `[a2,a3]+[b2,b3]`. a.0[i] = self.add_extension(a.0[i], b.0[i]);
let mut res = Vec::with_capacity(D);
// We need some extra logic if D is odd.
let d_even = D & (D ^ 1); // = 2 * (D/2)
for mut chunk in &(0..d_even).chunks(2) {
let i = chunk.next().unwrap();
let j = chunk.next().unwrap();
let (o0, o1) = self.add_two_extension(a.0[i], b.0[i], a.0[j], b.0[j]);
res.extend([o0, o1]);
} }
if D.is_odd() { a
res.push(self.add_extension(a.0[D - 1], b.0[D - 1]));
}
ExtensionAlgebraTarget(res.try_into().unwrap())
} }
/// Add 3 `ExtensionTarget`s with 1 `ArithmeticExtensionGate`s. /// Add 3 `ExtensionTarget`s with 1 `ArithmeticExtensionGate`s.
@ -274,35 +219,15 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.arithmetic_extension(F::ONE, F::NEG_ONE, one, a, b) self.arithmetic_extension(F::ONE, F::NEG_ONE, one, a, b)
} }
pub fn sub_two_extension(
&mut self,
a0: ExtensionTarget<D>,
b0: ExtensionTarget<D>,
a1: ExtensionTarget<D>,
b1: ExtensionTarget<D>,
) -> (ExtensionTarget<D>, ExtensionTarget<D>) {
let one = self.one_extension();
self.double_arithmetic_extension(F::ONE, F::NEG_ONE, one, a0, b0, one, a1, b1)
}
pub fn sub_ext_algebra( pub fn sub_ext_algebra(
&mut self, &mut self,
a: ExtensionAlgebraTarget<D>, mut a: ExtensionAlgebraTarget<D>,
b: ExtensionAlgebraTarget<D>, b: ExtensionAlgebraTarget<D>,
) -> ExtensionAlgebraTarget<D> { ) -> ExtensionAlgebraTarget<D> {
// See `add_ext_algebra`. for i in 0..D {
let mut res = Vec::with_capacity(D); a.0[i] = self.sub_extension(a.0[i], b.0[i]);
let d_even = D & (D ^ 1); // = 2 * (D/2)
for mut chunk in &(0..d_even).chunks(2) {
let i = chunk.next().unwrap();
let j = chunk.next().unwrap();
let (o0, o1) = self.sub_two_extension(a.0[i], b.0[i], a.0[j], b.0[j]);
res.extend([o0, o1]);
} }
if D.is_odd() { a
res.push(self.sub_extension(a.0[D - 1], b.0[D - 1]));
}
ExtensionAlgebraTarget(res.try_into().unwrap())
} }
pub fn mul_extension_with_const( pub fn mul_extension_with_const(
@ -312,17 +237,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
multiplicand_1: ExtensionTarget<D>, multiplicand_1: ExtensionTarget<D>,
) -> ExtensionTarget<D> { ) -> ExtensionTarget<D> {
let zero = self.zero_extension(); let zero = self.zero_extension();
self.double_arithmetic_extension( self.arithmetic_extension(const_0, F::ZERO, multiplicand_0, multiplicand_1, zero)
const_0,
F::ZERO,
multiplicand_0,
multiplicand_1,
zero,
zero,
zero,
zero,
)
.0
} }
pub fn mul_extension( pub fn mul_extension(
@ -333,18 +248,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.mul_extension_with_const(F::ONE, multiplicand_0, multiplicand_1) self.mul_extension_with_const(F::ONE, multiplicand_0, multiplicand_1)
} }
/// Returns `(a0*b0, a1*b1)`.
pub fn mul_two_extension(
&mut self,
a0: ExtensionTarget<D>,
b0: ExtensionTarget<D>,
a1: ExtensionTarget<D>,
b1: ExtensionTarget<D>,
) -> (ExtensionTarget<D>, ExtensionTarget<D>) {
let zero = self.zero_extension();
self.double_arithmetic_extension(F::ONE, F::ZERO, a0, b0, zero, a1, b1, zero)
}
/// Computes `x^2`. /// Computes `x^2`.
pub fn square_extension(&mut self, x: ExtensionTarget<D>) -> ExtensionTarget<D> { pub fn square_extension(&mut self, x: ExtensionTarget<D>) -> ExtensionTarget<D> {
self.mul_extension(x, x) self.mul_extension(x, x)
@ -402,12 +305,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
b: ExtensionTarget<D>, b: ExtensionTarget<D>,
c: ExtensionTarget<D>, c: ExtensionTarget<D>,
) -> ExtensionTarget<D> { ) -> ExtensionTarget<D> {
let zero = self.zero_extension(); let tmp = self.mul_extension(a, b);
let gate = self.num_gates(); self.mul_extension(tmp, c)
let first_out =
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_first_output());
self.double_arithmetic_extension(F::ONE, F::ZERO, a, b, zero, c, first_out, zero)
.1
} }
/// Multiply `n` `ExtensionTarget`s with `n/2` `ArithmeticExtensionGate`s. /// Multiply `n` `ExtensionTarget`s with `n/2` `ArithmeticExtensionGate`s.
@ -484,22 +383,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
b: ExtensionAlgebraTarget<D>, b: ExtensionAlgebraTarget<D>,
mut c: ExtensionAlgebraTarget<D>, mut c: ExtensionAlgebraTarget<D>,
) -> ExtensionAlgebraTarget<D> { ) -> ExtensionAlgebraTarget<D> {
for i in 0..D / 2 { for i in 0..D {
let res = self.double_arithmetic_extension( c.0[i] = self.mul_add_extension(a, b.0[i], c.0[i]);
F::ONE,
F::ONE,
a,
b.0[2 * i],
c.0[2 * i],
a,
b.0[2 * i + 1],
c.0[2 * i + 1],
);
c.0[2 * i] = res.0;
c.0[2 * i + 1] = res.1;
}
if D.is_odd() {
c.0[D - 1] = self.arithmetic_extension(F::ONE, F::ONE, a, b.0[D - 1], c.0[D - 1]);
} }
c c
} }
@ -571,7 +456,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
z: ExtensionTarget<D>, z: ExtensionTarget<D>,
) -> ExtensionTarget<D> { ) -> ExtensionTarget<D> {
let inv = self.add_virtual_extension_target(); let inv = self.add_virtual_extension_target();
let zero = self.zero_extension();
let one = self.one_extension(); let one = self.one_extension();
self.add_generator(QuotientGeneratorExtension { self.add_generator(QuotientGeneratorExtension {
numerator: one, numerator: one,
@ -580,11 +464,10 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}); });
// Enforce that x times its purported inverse equals 1. // Enforce that x times its purported inverse equals 1.
let (y_inv, res) = let y_inv = self.mul_extension(y, inv);
self.double_arithmetic_extension(F::ONE, F::ONE, y, inv, zero, x, inv, z);
self.assert_equal_extension(y_inv, one); self.assert_equal_extension(y_inv, one);
res self.mul_add_extension(x, inv, z)
} }
/// Computes `1 / x`. Results in an unsatisfiable instance if `x = 0`. /// Computes `1 / x`. Results in an unsatisfiable instance if `x = 0`.

View File

@ -5,29 +5,6 @@ use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> { impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Interpolate two points. No need for an `InterpolationGate` since the coefficients
/// of the linear interpolation polynomial can be easily computed with arithmetic operations.
pub fn interpolate2(
&mut self,
interpolation_points: [(ExtensionTarget<D>, ExtensionTarget<D>); 2],
evaluation_point: ExtensionTarget<D>,
) -> ExtensionTarget<D> {
// a0 -> a1
// b0 -> b1
// x -> a1 + (x-a0)*(b1-a1)/(b0-a0)
let (x_m_a0, b1_m_a1) = self.sub_two_extension(
evaluation_point,
interpolation_points[0].0,
interpolation_points[1].1,
interpolation_points[0].1,
);
let b0_m_a0 = self.sub_extension(interpolation_points[1].0, interpolation_points[0].0);
let quotient = self.div_extension(b1_m_a1, b0_m_a0);
self.mul_add_extension(x_m_a0, quotient, interpolation_points[0].1)
}
/// Interpolate a list of point/evaluation pairs at a given point. /// Interpolate a list of point/evaluation pairs at a given point.
/// Returns the evaluation of the interpolated polynomial at `evaluation_point`. /// Returns the evaluation of the interpolated polynomial at `evaluation_point`.
pub fn interpolate( pub fn interpolate(
@ -108,39 +85,4 @@ mod tests {
verify(proof, &data.verifier_only, &data.common) verify(proof, &data.verifier_only, &data.common)
} }
#[test]
fn test_interpolate2() -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
let config = CircuitConfig::large_zk_config();
let pw = PartialWitness::new(config.num_wires);
let mut builder = CircuitBuilder::<F, 4>::new(config);
let len = 2;
let points = (0..len)
.map(|_| (FF::rand(), FF::rand()))
.collect::<Vec<_>>();
let true_interpolant = interpolant(&points);
let z = FF::rand();
let true_eval = true_interpolant.eval(z);
let points_target = points
.iter()
.map(|&(p, v)| (builder.constant_extension(p), builder.constant_extension(v)))
.collect::<Vec<_>>();
let zt = builder.constant_extension(z);
let eval = builder.interpolate2(points_target.try_into().unwrap(), zt);
let true_eval_target = builder.constant_extension(true_eval);
builder.assert_equal_extension(eval, true_eval_target);
let data = builder.build();
let proof = data.prove(pw)?;
verify(proof, &data.verifier_only, &data.common)
}
} }

View File

@ -1,6 +1,5 @@
use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable; use crate::field::extension_field::Extendable;
use crate::gates::arithmetic::ArithmeticExtensionGate;
use crate::iop::target::{BoolTarget, Target}; use crate::iop::target::{BoolTarget, Target};
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
@ -25,12 +24,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
x: ExtensionTarget<D>, x: ExtensionTarget<D>,
y: ExtensionTarget<D>, y: ExtensionTarget<D>,
) -> ExtensionTarget<D> { ) -> ExtensionTarget<D> {
let gate = self.num_gates(); let tmp = self.mul_sub_extension(b, y, y);
// Holds `by - y`. self.mul_sub_extension(b, x, tmp)
let first_out =
ExtensionTarget::from_range(gate, ArithmeticExtensionGate::<D>::wires_first_output());
self.double_arithmetic_extension(F::ONE, F::NEG_ONE, b, y, y, b, x, first_out)
.1
} }
/// See `select_ext`. /// See `select_ext`.

View File

@ -10,34 +10,25 @@ use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
/// Number of arithmetic operations performed by an arithmetic gate.
pub const NUM_ARITHMETIC_OPS: usize = 4;
/// A gate which can a linear combination `c0*x*y+c1*z` twice with the same `x`. /// A gate which can a linear combination `c0*x*y+c1*z` twice with the same `x`.
#[derive(Debug)] #[derive(Debug)]
pub struct ArithmeticExtensionGate<const D: usize>; pub struct ArithmeticExtensionGate<const D: usize>;
impl<const D: usize> ArithmeticExtensionGate<D> { impl<const D: usize> ArithmeticExtensionGate<D> {
pub fn wires_first_multiplicand_0() -> Range<usize> { pub fn wires_ith_multiplicand_0(i: usize) -> Range<usize> {
0..D 4 * D * i..4 * D * i + D
} }
pub fn wires_first_multiplicand_1() -> Range<usize> { pub fn wires_ith_multiplicand_1(i: usize) -> Range<usize> {
D..2 * D 4 * D * i + D..4 * D * i + 2 * D
} }
pub fn wires_first_addend() -> Range<usize> { pub fn wires_ith_addend(i: usize) -> Range<usize> {
2 * D..3 * D 4 * D * i + 2 * D..4 * D * i + 3 * D
} }
pub fn wires_second_multiplicand_0() -> Range<usize> { pub fn wires_ith_output(i: usize) -> Range<usize> {
3 * D..4 * D 4 * D * i + 3 * D..4 * D * i + 4 * D
}
pub fn wires_second_multiplicand_1() -> Range<usize> {
4 * D..5 * D
}
pub fn wires_second_addend() -> Range<usize> {
5 * D..6 * D
}
pub fn wires_first_output() -> Range<usize> {
6 * D..7 * D
}
pub fn wires_second_output() -> Range<usize> {
7 * D..8 * D
} }
} }
@ -50,24 +41,18 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
let const_0 = vars.local_constants[0]; let const_0 = vars.local_constants[0];
let const_1 = vars.local_constants[1]; let const_1 = vars.local_constants[1];
let first_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_0()); let mut constraints = Vec::new();
let first_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_1()); for i in 0..NUM_ARITHMETIC_OPS {
let first_addend = vars.get_local_ext_algebra(Self::wires_first_addend()); let multiplicand_0 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_0(i));
let second_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_0()); let multiplicand_1 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_1(i));
let second_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_1()); let addend = vars.get_local_ext_algebra(Self::wires_ith_addend(i));
let second_addend = vars.get_local_ext_algebra(Self::wires_second_addend()); let output = vars.get_local_ext_algebra(Self::wires_ith_output(i));
let first_output = vars.get_local_ext_algebra(Self::wires_first_output()); let computed_output =
let second_output = vars.get_local_ext_algebra(Self::wires_second_output()); multiplicand_0 * multiplicand_1 * const_0.into() + addend * const_1.into();
let first_computed_output = first_multiplicand_0 * first_multiplicand_1 * const_0.into() constraints.extend((output - computed_output).to_basefield_array());
+ first_addend * const_1.into(); }
let second_computed_output = second_multiplicand_0 * second_multiplicand_1 * const_0.into()
+ second_addend * const_1.into();
let mut constraints = (first_output - first_computed_output)
.to_basefield_array()
.to_vec();
constraints.extend((second_output - second_computed_output).to_basefield_array());
constraints constraints
} }
@ -75,24 +60,18 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
let const_0 = vars.local_constants[0]; let const_0 = vars.local_constants[0];
let const_1 = vars.local_constants[1]; let const_1 = vars.local_constants[1];
let first_multiplicand_0 = vars.get_local_ext(Self::wires_first_multiplicand_0()); let mut constraints = Vec::new();
let first_multiplicand_1 = vars.get_local_ext(Self::wires_first_multiplicand_1()); for i in 0..NUM_ARITHMETIC_OPS {
let first_addend = vars.get_local_ext(Self::wires_first_addend()); let multiplicand_0 = vars.get_local_ext(Self::wires_ith_multiplicand_0(i));
let second_multiplicand_0 = vars.get_local_ext(Self::wires_second_multiplicand_0()); let multiplicand_1 = vars.get_local_ext(Self::wires_ith_multiplicand_1(i));
let second_multiplicand_1 = vars.get_local_ext(Self::wires_second_multiplicand_1()); let addend = vars.get_local_ext(Self::wires_ith_addend(i));
let second_addend = vars.get_local_ext(Self::wires_second_addend()); let output = vars.get_local_ext(Self::wires_ith_output(i));
let first_output = vars.get_local_ext(Self::wires_first_output()); let computed_output =
let second_output = vars.get_local_ext(Self::wires_second_output()); multiplicand_0 * multiplicand_1 * const_0.into() + addend * const_1.into();
let first_computed_output = first_multiplicand_0 * first_multiplicand_1 * const_0.into() constraints.extend((output - computed_output).to_basefield_array());
+ first_addend * const_1.into(); }
let second_computed_output = second_multiplicand_0 * second_multiplicand_1 * const_0.into()
+ second_addend * const_1.into();
let mut constraints = (first_output - first_computed_output)
.to_basefield_array()
.to_vec();
constraints.extend((second_output - second_computed_output).to_basefield_array());
constraints constraints
} }
@ -104,34 +83,23 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
let const_0 = vars.local_constants[0]; let const_0 = vars.local_constants[0];
let const_1 = vars.local_constants[1]; let const_1 = vars.local_constants[1];
let first_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_0()); let mut constraints = Vec::new();
let first_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_1()); for i in 0..NUM_ARITHMETIC_OPS {
let first_addend = vars.get_local_ext_algebra(Self::wires_first_addend()); let multiplicand_0 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_0(i));
let second_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_0()); let multiplicand_1 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_1(i));
let second_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_1()); let addend = vars.get_local_ext_algebra(Self::wires_ith_addend(i));
let second_addend = vars.get_local_ext_algebra(Self::wires_second_addend()); let output = vars.get_local_ext_algebra(Self::wires_ith_output(i));
let first_output = vars.get_local_ext_algebra(Self::wires_first_output()); let computed_output = {
let second_output = vars.get_local_ext_algebra(Self::wires_second_output()); let mul = builder.mul_ext_algebra(multiplicand_0, multiplicand_1);
let scaled_mul = builder.scalar_mul_ext_algebra(const_0, mul);
let scaled_addend = builder.scalar_mul_ext_algebra(const_1, addend);
builder.add_ext_algebra(scaled_mul, scaled_addend)
};
let first_computed_output = let diff = builder.sub_ext_algebra(output, computed_output);
builder.mul_ext_algebra(first_multiplicand_0, first_multiplicand_1); constraints.extend(diff.to_ext_target_array());
let first_computed_output = builder.scalar_mul_ext_algebra(const_0, first_computed_output); }
let first_scaled_addend = builder.scalar_mul_ext_algebra(const_1, first_addend);
let first_computed_output =
builder.add_ext_algebra(first_computed_output, first_scaled_addend);
let second_computed_output =
builder.mul_ext_algebra(second_multiplicand_0, second_multiplicand_1);
let second_computed_output =
builder.scalar_mul_ext_algebra(const_0, second_computed_output);
let second_scaled_addend = builder.scalar_mul_ext_algebra(const_1, second_addend);
let second_computed_output =
builder.add_ext_algebra(second_computed_output, second_scaled_addend);
let diff_0 = builder.sub_ext_algebra(first_output, first_computed_output);
let diff_1 = builder.sub_ext_algebra(second_output, second_computed_output);
let mut constraints = diff_0.to_ext_target_array().to_vec();
constraints.extend(diff_1.to_ext_target_array());
constraints constraints
} }
@ -140,21 +108,21 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
gate_index: usize, gate_index: usize,
local_constants: &[F], local_constants: &[F],
) -> Vec<Box<dyn WitnessGenerator<F>>> { ) -> Vec<Box<dyn WitnessGenerator<F>>> {
let gen0 = ArithmeticExtensionGenerator0 { (0..NUM_ARITHMETIC_OPS)
gate_index, .map(|i| {
const_0: local_constants[0], let g: Box<dyn WitnessGenerator<F>> = Box::new(ArithmeticExtensionGenerator {
const_1: local_constants[1], gate_index,
}; const_0: local_constants[0],
let gen1 = ArithmeticExtensionGenerator1 { const_1: local_constants[1],
gate_index, i,
const_0: local_constants[0], });
const_1: local_constants[1], g
}; })
vec![Box::new(gen0), Box::new(gen1)] .collect::<Vec<_>>()
} }
fn num_wires(&self) -> usize { fn num_wires(&self) -> usize {
8 * D NUM_ARITHMETIC_OPS * 4 * D
} }
fn num_constants(&self) -> usize { fn num_constants(&self) -> usize {
@ -166,27 +134,25 @@ impl<F: Extendable<D>, const D: usize> Gate<F, D> for ArithmeticExtensionGate<D>
} }
fn num_constraints(&self) -> usize { fn num_constraints(&self) -> usize {
2 * D NUM_ARITHMETIC_OPS * D
} }
} }
struct ArithmeticExtensionGenerator0<F: Extendable<D>, const D: usize> { #[derive(Clone)]
struct ArithmeticExtensionGenerator<F: Extendable<D>, const D: usize> {
gate_index: usize, gate_index: usize,
const_0: F, const_0: F,
const_1: F, const_1: F,
i: usize,
} }
struct ArithmeticExtensionGenerator1<F: Extendable<D>, const D: usize> { impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensionGenerator<F, D> {
gate_index: usize,
const_0: F,
const_1: F,
}
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensionGenerator0<F, D> {
fn dependencies(&self) -> Vec<Target> { fn dependencies(&self) -> Vec<Target> {
ArithmeticExtensionGate::<D>::wires_first_multiplicand_0() ArithmeticExtensionGate::<D>::wires_ith_multiplicand_0(self.i)
.chain(ArithmeticExtensionGate::<D>::wires_first_multiplicand_1()) .chain(ArithmeticExtensionGate::<D>::wires_ith_multiplicand_1(
.chain(ArithmeticExtensionGate::<D>::wires_first_addend()) self.i,
))
.chain(ArithmeticExtensionGate::<D>::wires_ith_addend(self.i))
.map(|i| Target::wire(self.gate_index, i)) .map(|i| Target::wire(self.gate_index, i))
.collect() .collect()
} }
@ -197,48 +163,17 @@ impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensio
witness.get_extension_target(t) witness.get_extension_target(t)
}; };
let multiplicand_0 = let multiplicand_0 = extract_extension(
extract_extension(ArithmeticExtensionGate::<D>::wires_first_multiplicand_0()); ArithmeticExtensionGate::<D>::wires_ith_multiplicand_0(self.i),
let multiplicand_1 =
extract_extension(ArithmeticExtensionGate::<D>::wires_first_multiplicand_1());
let addend = extract_extension(ArithmeticExtensionGate::<D>::wires_first_addend());
let output_target = ExtensionTarget::from_range(
self.gate_index,
ArithmeticExtensionGate::<D>::wires_first_output(),
); );
let multiplicand_1 = extract_extension(
let computed_output = ArithmeticExtensionGate::<D>::wires_ith_multiplicand_1(self.i),
multiplicand_0 * multiplicand_1 * self.const_0.into() + addend * self.const_1.into(); );
let addend = extract_extension(ArithmeticExtensionGate::<D>::wires_ith_addend(self.i));
out_buffer.set_extension_target(output_target, computed_output)
}
}
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for ArithmeticExtensionGenerator1<F, D> {
fn dependencies(&self) -> Vec<Target> {
ArithmeticExtensionGate::<D>::wires_second_multiplicand_0()
.chain(ArithmeticExtensionGate::<D>::wires_second_multiplicand_1())
.chain(ArithmeticExtensionGate::<D>::wires_second_addend())
.map(|i| Target::wire(self.gate_index, i))
.collect()
}
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
let extract_extension = |range: Range<usize>| -> F::Extension {
let t = ExtensionTarget::from_range(self.gate_index, range);
witness.get_extension_target(t)
};
let multiplicand_0 =
extract_extension(ArithmeticExtensionGate::<D>::wires_second_multiplicand_0());
let multiplicand_1 =
extract_extension(ArithmeticExtensionGate::<D>::wires_second_multiplicand_1());
let addend = extract_extension(ArithmeticExtensionGate::<D>::wires_second_addend());
let output_target = ExtensionTarget::from_range( let output_target = ExtensionTarget::from_range(
self.gate_index, self.gate_index,
ArithmeticExtensionGate::<D>::wires_second_output(), ArithmeticExtensionGate::<D>::wires_ith_output(self.i),
); );
let computed_output = let computed_output =

View File

@ -139,7 +139,7 @@ impl<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> for GMiMCGate<
for r in 0..R { for r in 0..R {
let active = r % W; let active = r % W;
let cubing_input = state[active] + addition_buffer + self.constants[r].into(); let cubing_input = state[active] + addition_buffer + self.constants[r];
let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)]; let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)];
constraints.push(cubing_input - cubing_input_wire); constraints.push(cubing_input - cubing_input_wire);
let f = cubing_input_wire.cube(); let f = cubing_input_wire.cube();
@ -160,8 +160,6 @@ impl<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> for GMiMCGate<
builder: &mut CircuitBuilder<F, D>, builder: &mut CircuitBuilder<F, D>,
vars: EvaluationTargets<D>, vars: EvaluationTargets<D>,
) -> Vec<ExtensionTarget<D>> { ) -> Vec<ExtensionTarget<D>> {
let one = builder.one_extension();
let neg_one = builder.neg_one_extension();
let mut constraints = Vec::with_capacity(self.num_constraints()); let mut constraints = Vec::with_capacity(self.num_constraints());
let swap = vars.local_wires[Self::WIRE_SWAP]; let swap = vars.local_wires[Self::WIRE_SWAP];
@ -197,18 +195,8 @@ impl<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> for GMiMCGate<
let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)]; let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)];
constraints.push(builder.sub_extension(cubing_input, cubing_input_wire)); constraints.push(builder.sub_extension(cubing_input, cubing_input_wire));
let f = builder.cube_extension(cubing_input_wire); let f = builder.cube_extension(cubing_input_wire);
// addition_buffer += f addition_buffer = builder.add_extension(addition_buffer, f);
// state[active] -= f state[active] = builder.sub_extension(state[active], f);
(addition_buffer, state[active]) = builder.double_arithmetic_extension(
F::ONE,
F::ONE,
one,
addition_buffer,
f,
neg_one,
f,
state[active],
);
} }
for i in 0..W { for i in 0..W {

View File

@ -1,4 +1,3 @@
use std::convert::identity;
use std::fmt::Debug; use std::fmt::Debug;
use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::target::ExtensionTarget;
@ -75,11 +74,6 @@ pub(crate) fn generate_partial_witness<F: Field>(
pending_generator_indices = next_pending_generator_indices; pending_generator_indices = next_pending_generator_indices;
} }
assert!(
generator_is_expired.into_iter().all(identity),
"Some generators weren't run."
);
} }
/// A generator participates in the generation of the witness. /// A generator participates in the generation of the witness.

View File

@ -60,6 +60,10 @@ pub struct CircuitBuilder<F: Extendable<D>, const D: usize> {
constants_to_targets: HashMap<F, Target>, constants_to_targets: HashMap<F, Target>,
targets_to_constants: HashMap<Target, F>, targets_to_constants: HashMap<Target, F>,
/// A map `(c0, c1) -> (g, i)` from constants `(c0,c1)` to an available arithmetic gate using
/// these constants with gate index `g` and already using `i` arithmetic operations.
pub(crate) free_arithmetic: HashMap<(F, F), (usize, usize)>,
} }
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> { impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
@ -76,6 +80,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
generators: Vec::new(), generators: Vec::new(),
constants_to_targets: HashMap::new(), constants_to_targets: HashMap::new(),
targets_to_constants: HashMap::new(), targets_to_constants: HashMap::new(),
free_arithmetic: HashMap::new(),
} }
} }

View File

@ -61,7 +61,7 @@ impl CircuitConfig {
pub(crate) fn large_config() -> Self { pub(crate) fn large_config() -> Self {
Self { Self {
num_wires: 126, num_wires: 126,
num_routed_wires: 33, num_routed_wires: 64,
security_bits: 128, security_bits: 128,
rate_bits: 3, rate_bits: 3,
num_challenges: 3, num_challenges: 3,
@ -78,6 +78,7 @@ impl CircuitConfig {
pub(crate) fn large_zk_config() -> Self { pub(crate) fn large_zk_config() -> Self {
CircuitConfig { CircuitConfig {
zero_knowledge: true, zero_knowledge: true,
cap_height: 1,
fri_config: FriConfig { fri_config: FriConfig {
proof_of_work_bits: 1, proof_of_work_bits: 1,
reduction_arity_bits: vec![1, 1, 1, 1], reduction_arity_bits: vec![1, 1, 1, 1],

View File

@ -37,7 +37,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.constants(&inner_common_data.circuit_digest.elements), self.constants(&inner_common_data.circuit_digest.elements),
); );
challenger.observe_hash(&digest); challenger.observe_hash(&digest);
challenger.observe_hash(&public_inputs_hash); challenger.observe_hash(public_inputs_hash);
challenger.observe_cap(&proof.wires_cap); challenger.observe_cap(&proof.wires_cap);
let betas = challenger.get_n_challenges(self, num_challenges); let betas = challenger.get_n_challenges(self, num_challenges);
@ -420,25 +420,25 @@ mod tests {
const D: usize = 4; const D: usize = 4;
let config = CircuitConfig { let config = CircuitConfig {
num_wires: 126, num_wires: 126,
num_routed_wires: 37, num_routed_wires: 64,
security_bits: 128, security_bits: 128,
rate_bits: 3, rate_bits: 3,
num_challenges: 3, num_challenges: 3,
zero_knowledge: false, zero_knowledge: false,
cap_height: 3, cap_height: 3,
fri_config: FriConfig { fri_config: FriConfig {
proof_of_work_bits: 1, proof_of_work_bits: 20,
reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], reduction_arity_bits: vec![3, 3, 3],
num_query_rounds: 40, num_query_rounds: 27,
}, },
}; };
let (proof_with_pis, vd, cd) = { let (proof_with_pis, vd, cd) = {
let (proof_with_pis, vd, cd) = { let (proof_with_pis, vd, cd) = {
let mut builder = CircuitBuilder::<F, D>::new(config.clone()); let mut builder = CircuitBuilder::<F, D>::new(config.clone());
let _two = builder.two(); let _two = builder.two();
let _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; let mut _two = builder.hash_n_to_hash(vec![_two], true).elements[0];
for _ in 0..10000 { for _ in 0..10000 {
let _two = builder.mul(_two, _two); _two = builder.mul(_two, _two);
} }
let data = builder.build(); let data = builder.build();
( (

View File

@ -1,5 +1,3 @@
use num::Integer;
use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable; use crate::field::extension_field::Extendable;
use crate::field::field_types::Field; use crate::field::field_types::Field;
@ -306,17 +304,8 @@ pub(crate) fn eval_vanishing_poly_recursively<F: Extendable<D>, const D: usize>(
// Holds `k[i] * x`. // Holds `k[i] * x`.
let mut s_ids = Vec::new(); let mut s_ids = Vec::new();
for j in 0..common_data.config.num_routed_wires / 2 { for j in 0..common_data.config.num_routed_wires {
let k_0 = builder.constant(common_data.k_is[2 * j]); let k = builder.constant(common_data.k_is[j]);
let k_0_ext = builder.convert_to_ext(k_0);
let k_1 = builder.constant(common_data.k_is[2 * j + 1]);
let k_1_ext = builder.convert_to_ext(k_1);
let tmp = builder.mul_two_extension(k_0_ext, x, k_1_ext, x);
s_ids.push(tmp.0);
s_ids.push(tmp.1);
}
if common_data.config.num_routed_wires.is_odd() {
let k = builder.constant(common_data.k_is[common_data.k_is.len() - 1]);
let k_ext = builder.convert_to_ext(k); let k_ext = builder.convert_to_ext(k);
s_ids.push(builder.mul_extension(k_ext, x)); s_ids.push(builder.mul_extension(k_ext, x));
} }

View File

@ -1,11 +1,8 @@
use std::borrow::Borrow; use std::borrow::Borrow;
use num::Integer;
use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::{Extendable, Frobenius}; use crate::field::extension_field::{Extendable, Frobenius};
use crate::field::field_types::Field; use crate::field::field_types::Field;
use crate::gates::arithmetic::ArithmeticExtensionGate;
use crate::gates::reducing::ReducingGate; use crate::gates::reducing::ReducingGate;
use crate::iop::target::Target; use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_builder::CircuitBuilder;
@ -164,40 +161,15 @@ impl<const D: usize> ReducingFactorTarget<D> {
where where
F: Extendable<D>, F: Extendable<D>,
{ {
let zero = builder.zero_extension();
let l = terms.len(); let l = terms.len();
self.count += l as u64; self.count += l as u64;
let mut terms_vec = terms.to_vec(); let mut terms_vec = terms.to_vec();
// If needed, we pad the original vector so that it has even length. let mut acc = terms_vec.pop().unwrap();
if terms_vec.len().is_odd() {
terms_vec.push(zero);
}
terms_vec.reverse(); terms_vec.reverse();
let mut acc = zero; for x in terms_vec {
for pair in terms_vec.chunks(2) { acc = builder.mul_add_extension(self.base, acc, x);
// We will route the output of the first arithmetic operation to the multiplicand of the
// second, i.e. we compute the following:
// out_0 = alpha acc + pair[0]
// acc' = out_1 = alpha out_0 + pair[1]
let gate = builder.num_gates();
let out_0 = ExtensionTarget::from_range(
gate,
ArithmeticExtensionGate::<D>::wires_first_output(),
);
acc = builder
.double_arithmetic_extension(
F::ONE,
F::ONE,
self.base,
acc,
pair[0],
self.base,
out_0,
pair[1],
)
.1;
} }
acc acc
} }
@ -215,23 +187,6 @@ impl<const D: usize> ReducingFactorTarget<D> {
builder.mul_extension(exp, x) builder.mul_extension(exp, x)
} }
/// Returns `(self.shift(x), a*b)`.
/// Used to take advantage of the second arithmetic operation in the `ArithmeticExtensionGate`.
pub fn shift_and_mul<F>(
&mut self,
x: ExtensionTarget<D>,
a: ExtensionTarget<D>,
b: ExtensionTarget<D>,
builder: &mut CircuitBuilder<F, D>,
) -> (ExtensionTarget<D>, ExtensionTarget<D>)
where
F: Extendable<D>,
{
let exp = builder.exp_u64_extension(self.base, self.count);
self.count = 0;
builder.mul_two_extension(exp, x, a, b)
}
pub fn reset(&mut self) { pub fn reset(&mut self) {
self.count = 0; self.count = 0;
} }