use crate::{
matrix::{ColumnIter, MultiColumnIter},
Matrix,
};
use math::{log2, FieldElement, StarkField};
use utils::collections::Vec;
pub struct TracePolyTable<E: FieldElement> {
main_segment_polys: Matrix<E::BaseField>,
aux_segment_polys: Vec<Matrix<E>>,
}
impl<E: FieldElement> TracePolyTable<E> {
pub fn new(main_trace_polys: Matrix<E::BaseField>) -> Self {
Self {
main_segment_polys: main_trace_polys,
aux_segment_polys: Vec::new(),
}
}
pub fn add_aux_segment(&mut self, aux_segment_polys: Matrix<E>) {
assert_eq!(
self.main_segment_polys.num_rows(),
aux_segment_polys.num_rows(),
"polynomials in auxiliary segment must be of the same size as in the main segment"
);
self.aux_segment_polys.push(aux_segment_polys);
}
pub fn poly_size(&self) -> usize {
self.main_segment_polys.num_rows()
}
pub fn evaluate_at(&self, x: E) -> Vec<E> {
let mut result = self.main_segment_polys.evaluate_columns_at(x);
for aux_polys in self.aux_segment_polys.iter() {
result.append(&mut aux_polys.evaluate_columns_at(x));
}
result
}
pub fn get_ood_frame(&self, z: E) -> Vec<Vec<E>> {
let g = E::from(E::BaseField::get_root_of_unity(log2(self.poly_size())));
vec![self.evaluate_at(z), self.evaluate_at(z * g)]
}
pub fn main_trace_polys(&self) -> ColumnIter<E::BaseField> {
self.main_segment_polys.columns()
}
pub fn aux_trace_polys(&self) -> MultiColumnIter<E> {
MultiColumnIter::new(self.aux_segment_polys.as_slice())
}
#[cfg(test)]
pub fn num_main_trace_polys(&self) -> usize {
self.main_segment_polys.num_cols()
}
#[cfg(test)]
pub fn get_main_trace_poly(&self, idx: usize) -> &[E::BaseField] {
&self.main_segment_polys.get_column(idx)
}
}