use alloc::{collections::BTreeMap, vec::Vec};
use math::{fft, polynom};
use super::{Assertion, ExtensionOf, FieldElement};
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct BoundaryConstraint<F, E>
where
F: FieldElement,
E: FieldElement<BaseField = F::BaseField> + ExtensionOf<F>,
{
column: usize,
poly: Vec<F>,
poly_offset: (usize, F::BaseField),
cc: E,
}
impl<F, E> BoundaryConstraint<F, E>
where
F: FieldElement,
E: FieldElement<BaseField = F::BaseField> + ExtensionOf<F>,
{
pub(super) fn new(
assertion: Assertion<F>,
inv_g: F::BaseField,
twiddle_map: &mut BTreeMap<usize, Vec<F::BaseField>>,
composition_coefficient: E,
) -> Self {
let mut poly_offset = (0, F::BaseField::ONE);
let mut poly = assertion.values;
if poly.len() > 1 {
let inv_twiddles = twiddle_map
.entry(poly.len())
.or_insert_with(|| fft::get_inv_twiddles(poly.len()));
fft::interpolate_poly(&mut poly, inv_twiddles);
if assertion.first_step != 0 {
let x_offset = inv_g.exp((assertion.first_step as u64).into());
poly_offset = (assertion.first_step, x_offset);
}
}
BoundaryConstraint {
column: assertion.column,
poly,
poly_offset,
cc: composition_coefficient,
}
}
pub fn column(&self) -> usize {
self.column
}
pub fn poly(&self) -> &[F] {
&self.poly
}
pub fn poly_offset(&self) -> (usize, F::BaseField) {
self.poly_offset
}
pub fn cc(&self) -> &E {
&self.cc
}
pub fn evaluate_at(&self, x: E, trace_value: E) -> E {
let assertion_value = if self.poly.len() == 1 {
E::from(self.poly[0])
} else {
let x = x * E::from(self.poly_offset.1);
polynom::eval(&self.poly, x)
};
trace_value - assertion_value
}
}