use p3_field::{ExtensionField, Field};
use crate::air_builders::symbolic::{
symbolic_expression::SymbolicEvaluator,
symbolic_variable::{Entry, SymbolicVariable},
};
pub(super) struct ViewPair<T> {
pub(super) local: *const T,
pub(super) next: Option<*const T>,
}
impl<T> ViewPair<T> {
pub fn new(local: &[T], next: Option<&[T]>) -> Self {
Self {
local: local.as_ptr(),
next: next.map(|nxt| nxt.as_ptr()),
}
}
pub unsafe fn get(&self, row_offset: usize, column_idx: usize) -> &T {
match row_offset {
0 => &*self.local.add(column_idx),
1 => &*self.next.unwrap_unchecked().add(column_idx),
_ => panic!("row offset {row_offset} not supported"),
}
}
}
pub(super) struct ProverConstraintEvaluator<'a, F, EF> {
pub preprocessed: Option<ViewPair<EF>>,
pub partitioned_main: Vec<ViewPair<EF>>,
pub is_first_row: EF,
pub is_last_row: EF,
pub is_transition: EF,
pub public_values: &'a [F],
}
impl<F: Field, EF: ExtensionField<F>> SymbolicEvaluator<F, EF>
for ProverConstraintEvaluator<'_, F, EF>
{
fn eval_const(&self, c: F) -> EF {
c.into()
}
fn eval_is_first_row(&self) -> EF {
self.is_first_row
}
fn eval_is_last_row(&self) -> EF {
self.is_last_row
}
fn eval_is_transition(&self) -> EF {
self.is_transition
}
fn eval_var(&self, symbolic_var: SymbolicVariable<F>) -> EF {
let index = symbolic_var.index;
match symbolic_var.entry {
Entry::Preprocessed { offset } => unsafe {
*self
.preprocessed
.as_ref()
.unwrap_unchecked()
.get(offset, index)
},
Entry::Main { part_index, offset } => unsafe {
*self.partitioned_main[part_index].get(offset, index)
},
Entry::Public => unsafe { EF::from(*self.public_values.get_unchecked(index)) },
Entry::Challenge => unreachable!("challenge not supported"),
}
}
}