Remove GatePrefixes to avoid using a HashMap

This commit is contained in:
wborgeaud 2021-06-24 18:06:48 +02:00
parent b4258976b1
commit 54315d1735
4 changed files with 37 additions and 59 deletions

View File

@ -11,7 +11,7 @@ use crate::field::cosets::get_unique_coset_shifts;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::gates::constant::ConstantGate;
use crate::gates::gate::{GateInstance, GatePrefixes, GateRef};
use crate::gates::gate::{GateInstance, GateRef, PrefixedGate};
use crate::gates::gate_tree::Tree;
use crate::gates::noop::NoopGate;
use crate::generator::{CopyGenerator, WitnessGenerator};
@ -230,26 +230,24 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
fn constant_polys(&self, prefixes: &GatePrefixes<F, D>) -> Vec<PolynomialValues<F>> {
let num_constants = self
.gate_instances
fn constant_polys(&self, gates: &[PrefixedGate<F, D>]) -> Vec<PolynomialValues<F>> {
let num_constants = gates
.iter()
.map(|gate_inst| gate_inst.constants.len() + prefixes[&gate_inst.gate_type].len())
.map(|gate| gate.gate.0.num_constants() + gate.prefix.len())
.max()
.unwrap();
let constants_per_gate = self
.gate_instances
.iter()
.map(|gate_inst| {
.map(|gate| {
let prefix = &gates
.iter()
.find(|g| g.gate.0.id() == gate.gate_type.0.id())
.unwrap()
.prefix;
let mut prefixed_constants = Vec::new();
prefixed_constants.extend(prefixes[&gate_inst.gate_type].iter().map(|&b| {
if b {
F::ONE
} else {
F::ZERO
}
}));
prefixed_constants.extend_from_slice(&gate_inst.constants);
prefixed_constants.extend(prefix.iter().map(|&b| if b { F::ONE } else { F::ZERO }));
prefixed_constants.extend_from_slice(&gate.constants);
prefixed_constants.resize(num_constants, F::ZERO);
prefixed_constants
})
@ -297,9 +295,9 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let gates = self.gates.iter().cloned().collect();
let gate_tree = Tree::from_gates(gates);
let gate_prefixes = gate_tree.into();
let prefixed_gates = PrefixedGate::from_tree(gate_tree);
let constant_vecs = self.constant_polys(&gate_prefixes);
let constant_vecs = self.constant_polys(&prefixed_gates);
let constants_commitment = ListPolynomialCommitment::new(
constant_vecs.into_iter().map(|v| v.ifft()).collect(),
self.config.fri_config.rate_bits,
@ -348,8 +346,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let common = CommonCircuitData {
config: self.config,
degree_bits,
gates,
gate_prefixes,
gates: prefixed_gates,
num_gate_constraints,
k_is,
circuit_digest,

View File

@ -3,7 +3,7 @@ use anyhow::Result;
use crate::field::extension_field::Extendable;
use crate::field::field::Field;
use crate::fri::FriConfig;
use crate::gates::gate::{GatePrefixes, GateRef};
use crate::gates::gate::{GateRef, PrefixedGate};
use crate::generator::WitnessGenerator;
use crate::polynomial::commitment::ListPolynomialCommitment;
use crate::proof::{Hash, HashTarget, Proof};
@ -136,11 +136,8 @@ pub(crate) struct CommonCircuitData<F: Extendable<D>, const D: usize> {
pub(crate) degree_bits: usize,
/// The types of gates used in this circuit.
pub(crate) gates: Vec<GateRef<F, D>>,
/// The gate prefixes used to construct the selector polynomials.
pub(crate) gate_prefixes: GatePrefixes<F, D>,
/// The types of gates used in this circuit, along with their prefixes.
pub(crate) gates: Vec<PrefixedGate<F, D>>,
/// The largest number of constraints imposed by any gate.
pub(crate) num_gate_constraints: usize,
@ -169,7 +166,7 @@ impl<F: Extendable<D>, const D: usize> CommonCircuitData<F, D> {
pub fn constraint_degree(&self) -> usize {
self.gates
.iter()
.map(|g| g.0.degree())
.map(|g| g.gate.0.degree())
.max()
.expect("No gates?")
}

View File

@ -142,23 +142,17 @@ pub struct GateInstance<F: Extendable<D>, const D: usize> {
/// Map each gate to a boolean prefix used to construct the gate's selector polynomial.
#[derive(Debug, Clone)]
pub struct GatePrefixes<F: Extendable<D>, const D: usize> {
pub prefixes: HashMap<GateRef<F, D>, Vec<bool>>,
pub struct PrefixedGate<F: Extendable<D>, const D: usize> {
pub gate: GateRef<F, D>,
pub prefix: Vec<bool>,
}
impl<F: Extendable<D>, const D: usize> From<Tree<GateRef<F, D>>> for GatePrefixes<F, D> {
fn from(tree: Tree<GateRef<F, D>>) -> Self {
GatePrefixes {
prefixes: HashMap::from_iter(tree.traversal()),
}
}
}
impl<F: Extendable<D>, T: Borrow<GateRef<F, D>>, const D: usize> Index<T> for GatePrefixes<F, D> {
type Output = Vec<bool>;
fn index(&self, index: T) -> &Self::Output {
&self.prefixes[index.borrow()]
impl<F: Extendable<D>, const D: usize> PrefixedGate<F, D> {
pub fn from_tree(tree: Tree<GateRef<F, D>>) -> Vec<Self> {
tree.traversal()
.into_iter()
.map(|(gate, prefix)| PrefixedGate { gate, prefix })
.collect()
}
}

View File

@ -5,7 +5,7 @@ use crate::circuit_data::CommonCircuitData;
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::field::field::Field;
use crate::gates::gate::{GatePrefixes, GateRef};
use crate::gates::gate::{GateRef, PrefixedGate};
use crate::polynomial::commitment::SALT_SIZE;
use crate::polynomial::polynomial::PolynomialCoeffs;
use crate::target::Target;
@ -76,12 +76,8 @@ pub(crate) fn eval_vanishing_poly<F: Extendable<D>, const D: usize>(
gammas: &[F],
alphas: &[F],
) -> Vec<F::Extension> {
let constraint_terms = evaluate_gate_constraints(
&common_data.gates,
common_data.num_gate_constraints,
vars,
&common_data.gate_prefixes,
);
let constraint_terms =
evaluate_gate_constraints(&common_data.gates, common_data.num_gate_constraints, vars);
// The L_1(x) (Z(x) - 1) vanishing terms.
let mut vanishing_z_1_terms = Vec::new();
@ -129,12 +125,8 @@ pub(crate) fn eval_vanishing_poly_base<F: Extendable<D>, const D: usize>(
gammas: &[F],
alphas: &[F],
) -> Vec<F> {
let constraint_terms = evaluate_gate_constraints_base(
&common_data.gates,
common_data.num_gate_constraints,
vars,
&common_data.gate_prefixes,
);
let constraint_terms =
evaluate_gate_constraints_base(&common_data.gates, common_data.num_gate_constraints, vars);
// The L_1(x) (Z(x) - 1) vanishing terms.
let mut vanishing_z_1_terms = Vec::new();
@ -175,14 +167,13 @@ pub(crate) fn eval_vanishing_poly_base<F: Extendable<D>, const D: usize>(
/// strictly necessary, but it helps performance by ensuring that we allocate a vector with exactly
/// the capacity that we need.
pub fn evaluate_gate_constraints<F: Extendable<D>, const D: usize>(
gates: &[GateRef<F, D>],
gates: &[PrefixedGate<F, D>],
num_gate_constraints: usize,
vars: EvaluationVars<F, D>,
prefixes: &GatePrefixes<F, D>,
) -> Vec<F::Extension> {
let mut constraints = vec![F::Extension::ZERO; num_gate_constraints];
for gate in gates {
let gate_constraints = gate.0.eval_filtered(vars, &prefixes[gate]);
let gate_constraints = gate.gate.0.eval_filtered(vars, &gate.prefix);
for (i, c) in gate_constraints.into_iter().enumerate() {
debug_assert!(
i < num_gate_constraints,
@ -195,14 +186,13 @@ pub fn evaluate_gate_constraints<F: Extendable<D>, const D: usize>(
}
pub fn evaluate_gate_constraints_base<F: Extendable<D>, const D: usize>(
gates: &[GateRef<F, D>],
gates: &[PrefixedGate<F, D>],
num_gate_constraints: usize,
vars: EvaluationVarsBase<F>,
prefixes: &GatePrefixes<F, D>,
) -> Vec<F> {
let mut constraints = vec![F::ZERO; num_gate_constraints];
for gate in gates {
let gate_constraints = gate.0.eval_filtered_base(vars, &prefixes[gate]);
let gate_constraints = gate.gate.0.eval_filtered_base(vars, &gate.prefix);
for (i, c) in gate_constraints.into_iter().enumerate() {
debug_assert!(
i < num_gate_constraints,