use itertools::Itertools;
use crate::core::air::{Component, Components};
use crate::core::fields::m31::BaseField;
use crate::core::fields::qm31::SecureField;
use crate::core::pcs::TreeVec;
use crate::core::ColumnVec;
use crate::prover::air::accumulation::DomainEvaluationAccumulator;
use crate::prover::backend::Backend;
use crate::prover::poly::circle::{CircleEvaluation, CirclePoly, SecureCirclePoly};
use crate::prover::poly::BitReversedOrder;
pub trait ComponentProver<B: Backend>: Component {
fn evaluate_constraint_quotients_on_domain(
&self,
trace: &Trace<'_, B>,
evaluation_accumulator: &mut DomainEvaluationAccumulator<B>,
);
}
pub struct Trace<'a, B: Backend> {
pub polys: TreeVec<ColumnVec<&'a CirclePoly<B>>>,
pub evals: TreeVec<ColumnVec<&'a CircleEvaluation<B, BaseField, BitReversedOrder>>>,
}
pub struct ComponentProvers<'a, B: Backend> {
pub components: Vec<&'a dyn ComponentProver<B>>,
pub n_preprocessed_columns: usize,
}
impl<B: Backend> ComponentProvers<'_, B> {
pub fn components(&self) -> Components<'_> {
Components {
components: self
.components
.iter()
.map(|c| *c as &dyn Component)
.collect_vec(),
n_preprocessed_columns: self.n_preprocessed_columns,
}
}
pub fn compute_composition_polynomial(
&self,
random_coeff: SecureField,
trace: &Trace<'_, B>,
) -> SecureCirclePoly<B> {
let total_constraints: usize = self.components.iter().map(|c| c.n_constraints()).sum();
let mut accumulator = DomainEvaluationAccumulator::new(
random_coeff,
self.components().composition_log_degree_bound(),
total_constraints,
);
for component in &self.components {
component.evaluate_constraint_quotients_on_domain(trace, &mut accumulator)
}
accumulator.finalize()
}
}