use super::{Felt, FieldElement, StarkField, Vec, Word};
use crate::{
trace::{AuxColumnBuilder, LookupTableRow},
Matrix,
};
#[derive(Debug, Clone, Default)]
pub struct AuxTraceBuilder {
pub(super) sibling_hints: Vec<(u32, SiblingTableUpdate)>,
pub(super) sibling_rows: Vec<SiblingTableRow>,
}
impl AuxTraceBuilder {
pub fn build_aux_columns<E: FieldElement<BaseField = Felt>>(
&self,
main_trace: &Matrix<Felt>,
rand_elements: &[E],
) -> Vec<Vec<E>> {
let p1 = self.build_aux_column(main_trace, rand_elements);
vec![p1]
}
pub fn sibling_added(&mut self, step: u32, index: Felt, sibling: Word) {
let row_index = self.sibling_rows.len();
let update = SiblingTableUpdate::SiblingAdded(row_index as u32);
self.sibling_hints.push((step, update));
self.sibling_rows.push(SiblingTableRow::new(index, sibling));
}
pub fn sibling_removed(&mut self, step: u32, row_offset: usize) {
let row_index = self.sibling_rows.len() - row_offset - 1;
let update = SiblingTableUpdate::SiblingRemoved(row_index as u32);
self.sibling_hints.push((step, update));
}
}
impl AuxColumnBuilder<SiblingTableUpdate, SiblingTableRow, u32> for AuxTraceBuilder {
fn get_table_rows(&self) -> &[SiblingTableRow] {
&self.sibling_rows
}
fn get_table_hints(&self) -> &[(u32, SiblingTableUpdate)] {
&self.sibling_hints
}
fn get_multiplicand<E: FieldElement<BaseField = Felt>>(
&self,
hint: SiblingTableUpdate,
row_values: &[E],
inv_row_values: &[E],
) -> E {
match hint {
SiblingTableUpdate::SiblingAdded(inserted_row_idx) => {
row_values[inserted_row_idx as usize]
}
SiblingTableUpdate::SiblingRemoved(removed_row_idx) => {
inv_row_values[removed_row_idx as usize]
}
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SiblingTableUpdate {
SiblingAdded(u32),
SiblingRemoved(u32),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct SiblingTableRow {
index: Felt,
sibling: Word,
}
impl SiblingTableRow {
pub fn new(index: Felt, sibling: Word) -> Self {
Self { index, sibling }
}
}
impl LookupTableRow for SiblingTableRow {
fn to_value<E: FieldElement<BaseField = Felt>>(
&self,
_main_trace: &Matrix<Felt>,
alphas: &[E],
) -> E {
let lsb = self.index.as_int() & 1;
if lsb == 0 {
alphas[0]
+ alphas[3].mul_base(self.index)
+ alphas[12].mul_base(self.sibling[0])
+ alphas[13].mul_base(self.sibling[1])
+ alphas[14].mul_base(self.sibling[2])
+ alphas[15].mul_base(self.sibling[3])
} else {
alphas[0]
+ alphas[3].mul_base(self.index)
+ alphas[8].mul_base(self.sibling[0])
+ alphas[9].mul_base(self.sibling[1])
+ alphas[10].mul_base(self.sibling[2])
+ alphas[11].mul_base(self.sibling[3])
}
}
}