use alloc::{collections::BTreeMap, vec::Vec};
use super::{Assertion, BoundaryConstraint, ConstraintDivisor, ExtensionOf, FieldElement};
#[derive(Debug, Clone)]
pub struct BoundaryConstraintGroup<F, E>
where
F: FieldElement,
E: FieldElement<BaseField = F::BaseField> + ExtensionOf<F>,
{
constraints: Vec<BoundaryConstraint<F, E>>,
divisor: ConstraintDivisor<F::BaseField>,
}
impl<F, E> BoundaryConstraintGroup<F, E>
where
F: FieldElement,
E: FieldElement<BaseField = F::BaseField> + ExtensionOf<F>,
{
pub(super) fn new(divisor: ConstraintDivisor<F::BaseField>) -> Self {
BoundaryConstraintGroup { constraints: Vec::new(), divisor }
}
pub fn constraints(&self) -> &[BoundaryConstraint<F, E>] {
&self.constraints
}
pub fn divisor(&self) -> &ConstraintDivisor<F::BaseField> {
&self.divisor
}
pub(super) fn add(
&mut self,
assertion: Assertion<F>,
inv_g: F::BaseField,
twiddle_map: &mut BTreeMap<usize, Vec<F::BaseField>>,
composition_coefficients: E,
) {
self.constraints.push(BoundaryConstraint::new(
assertion,
inv_g,
twiddle_map,
composition_coefficients,
));
}
pub fn evaluate_at(&self, state: &[E], x: E) -> E {
let mut numerator = E::ZERO;
for constraint in self.constraints().iter() {
let trace_value = state[constraint.column()];
let evaluation = constraint.evaluate_at(x, trace_value);
numerator += evaluation * *constraint.cc();
}
let denominator = self.divisor.evaluate_at(x);
numerator / denominator
}
}