This commit is contained in:
wborgeaud 2021-11-22 21:20:44 +01:00
parent fa29db1dcb
commit 172fdd3d89
8 changed files with 33 additions and 31 deletions

View File

@ -160,6 +160,7 @@ impl<F: OEF<D>, const D: usize> PolynomialCoeffsAlgebra<F, D> {
.fold(ExtensionAlgebra::ZERO, |acc, &c| acc * x + c)
}
/// Evaluate the polynomial at a point given its powers. The first power is the point itself, not 1.
pub fn eval_with_powers(&self, powers: &[ExtensionAlgebra<F, D>]) -> ExtensionAlgebra<F, D> {
debug_assert_eq!(self.coeffs.len(), powers.len() + 1);
let acc = self.coeffs[0];
@ -176,6 +177,7 @@ impl<F: OEF<D>, const D: usize> PolynomialCoeffsAlgebra<F, D> {
.fold(ExtensionAlgebra::ZERO, |acc, &c| acc.scalar_mul(x) + c)
}
/// Evaluate the polynomial at a point given its powers. The first power is the point itself, not 1.
pub fn eval_base_with_powers(&self, powers: &[F]) -> ExtensionAlgebra<F, D> {
debug_assert_eq!(self.coeffs.len(), powers.len() + 1);
let acc = self.coeffs[0];

View File

@ -46,7 +46,9 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let coset_start = self.mul(start, x);
// The answer is gotten by interpolating {(x*g^i, P(x*g^i))} and evaluating at beta.
if 1 << arity_bits > common_data.quotient_degree_factor {
// `HighDegreeInterpolationGate` has degree `arity`, so we use the low-degree gate if
// the arity is too large.
if arity > common_data.quotient_degree_factor {
self.interpolate_coset::<LowDegreeInterpolationGate<F, D>>(
arity_bits,
coset_start,
@ -66,19 +68,28 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Make sure we have enough wires and routed wires to do the FRI checks efficiently. This check
/// isn't required -- without it we'd get errors elsewhere in the stack -- but just gives more
/// helpful errors.
fn check_recursion_config(&self, max_fri_arity_bits: usize) {
fn check_recursion_config(
&self,
max_fri_arity_bits: usize,
common_data: &CommonCircuitData<F, D>,
) {
let random_access = RandomAccessGate::<F, D>::new_from_config(
&self.config,
max_fri_arity_bits.max(self.config.cap_height),
);
let interpolation_gate = HighDegreeInterpolationGate::<F, D>::new(max_fri_arity_bits);
let (interpolation_wires, interpolation_routed_wires) =
if 1 << max_fri_arity_bits > common_data.quotient_degree_factor {
let gate = LowDegreeInterpolationGate::<F, D>::new(max_fri_arity_bits);
(gate.num_wires(), gate.num_routed_wires())
} else {
let gate = HighDegreeInterpolationGate::<F, D>::new(max_fri_arity_bits);
(gate.num_wires(), gate.num_routed_wires())
};
let min_wires = random_access
.num_wires()
.max(interpolation_gate.num_wires());
let min_wires = random_access.num_wires().max(interpolation_wires);
let min_routed_wires = random_access
.num_routed_wires()
.max(interpolation_gate.num_routed_wires());
.max(interpolation_routed_wires);
assert!(
self.config.num_wires >= min_wires,
@ -125,7 +136,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let config = &common_data.config;
if let Some(max_arity_bits) = common_data.fri_params.max_arity_bits() {
self.check_recursion_config(max_arity_bits);
self.check_recursion_config(max_arity_bits, common_data);
}
debug_assert_eq!(

View File

@ -7,6 +7,9 @@ use crate::gates::gate::Gate;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
/// Trait for gates which interpolate a polynomial, whose points are a (base field) coset of the multiplicative subgroup
/// with the given size, and whose values are extension field elements, given by input wires.
/// Outputs the evaluation of the interpolant at a given (extension field) evaluation point.
pub(crate) trait InterpolationGate<F: RichField + Extendable<D>, const D: usize>:
Gate<F, D> + Copy
{

View File

@ -64,6 +64,8 @@ impl<const D: usize> PolynomialCoeffsExtAlgebraTarget<D> {
}
acc
}
/// Evaluate the polynomial at a point given its powers. The first power is the point itself, not 1.
pub fn eval_with_powers<F>(
&self,
builder: &mut CircuitBuilder<F, D>,
@ -78,10 +80,5 @@ impl<const D: usize> PolynomialCoeffsExtAlgebraTarget<D> {
.iter()
.zip(powers)
.fold(acc, |acc, (&x, &c)| builder.mul_add_ext_algebra(c, x, acc))
// let mut acc = builder.zero_ext_algebra();
// for &c in self.0.iter().rev() {
// acc = builder.mul_add_ext_algebra(point, acc, c);
// }
// acc
}
}

View File

@ -17,9 +17,8 @@ use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use crate::polynomial::polynomial::PolynomialCoeffs;
/// Interpolates a polynomial, whose points are a (base field) coset of the multiplicative subgroup
/// with the given size, and whose values are extension field elements, given by input wires.
/// Outputs the evaluation of the interpolant at a given (extension field) evaluation point.
/// Interpolation gate with constraints of degree at most `1<<subgroup_bits`.
/// `eval_unfiltered_recursively` uses less gates than `LowDegreeInterpolationGate`.
#[derive(Copy, Clone, Debug)]
pub(crate) struct HighDegreeInterpolationGate<F: RichField + Extendable<D>, const D: usize> {
pub subgroup_bits: usize,

View File

@ -17,9 +17,8 @@ use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use crate::polynomial::polynomial::PolynomialCoeffs;
/// Interpolates a polynomial, whose points are a (base field) coset of the multiplicative subgroup
/// with the given size, and whose values are extension field elements, given by input wires.
/// Outputs the evaluation of the interpolant at a given (extension field) evaluation point.
/// Interpolation gate with constraints of degree 2.
/// `eval_unfiltered_recursively` uses more gates than `HighDegreeInterpolationGate`.
#[derive(Copy, Clone, Debug)]
pub(crate) struct LowDegreeInterpolationGate<F: RichField + Extendable<D>, const D: usize> {
pub subgroup_bits: usize,
@ -344,7 +343,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LowDegreeInter
fn num_constraints(&self) -> usize {
// `num_points * D` constraints to check for consistency between the coefficients and the
// point-value pairs, plus `D` constraints for the evaluation value, plus `(D+1)*(num_points-2)`
// to check power constraints for evaluation point and wire shift.
// to check power constraints for evaluation point and shift.
self.num_points() * D + D + (D + 1) * (self.num_points() - 2)
}
}

View File

@ -66,17 +66,6 @@ pub(crate) fn prove<F: RichField + Extendable<D>, const D: usize>(
.collect()
);
// let rows = (0..degree)
// .map(|i| wires_values.iter().map(|w| w.values[i]).collect::<Vec<_>>())
// .collect::<Vec<_>>();
// for (i, r) in rows.iter().enumerate() {
// let c = rows.iter().filter(|&x| x == r).count();
// let s = prover_data.instances[i].gate_ref.0.id();
// if c > 1 && !s.starts_with("Noop") {
// println!("{} {} {}", prover_data.instances[i].gate_ref.0.id(), i, c);
// }
// }
let wires_commitment = timed!(
timing,
"compute wires commitment",

View File

@ -120,6 +120,7 @@ impl<F: Field> PolynomialCoeffs<F> {
.fold(F::ZERO, |acc, &c| acc * x + c)
}
/// Evaluate the polynomial at a point given its powers. The first power is the point itself, not 1.
pub fn eval_with_powers(&self, powers: &[F]) -> F {
debug_assert_eq!(self.coeffs.len(), powers.len() + 1);
let acc = self.coeffs[0];
@ -139,6 +140,7 @@ impl<F: Field> PolynomialCoeffs<F> {
.fold(F::ZERO, |acc, &c| acc.scalar_mul(x) + c)
}
/// Evaluate the polynomial at a point given its powers. The first power is the point itself, not 1.
pub fn eval_base_with_powers<const D: usize>(&self, powers: &[F::BaseField]) -> F
where
F: FieldExtension<D>,