use alloc::vec::Vec;
use math::FieldElement;
use utils::{
ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, SliceReader,
};
use crate::EvaluationFrame;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct OodFrame {
trace_states: Vec<u8>,
quotient_states: Vec<u8>,
}
impl OodFrame {
pub fn set_trace_states<E>(&mut self, trace_ood_frame: &TraceOodFrame<E>)
where
E: FieldElement,
{
assert!(self.trace_states.is_empty(), "trace sates have already been set");
let main_and_aux_trace_states = trace_ood_frame.to_trace_states();
let frame_size: u8 = 2;
self.trace_states.write_u8(frame_size);
self.trace_states.write_many(&main_and_aux_trace_states);
}
pub fn set_quotient_states<E>(&mut self, quotients_ood_frame: &QuotientOodFrame<E>)
where
E: FieldElement,
{
assert!(self.quotient_states.is_empty(), "constraint evaluations have already been set");
let quotient_states = quotients_ood_frame.to_trace_states();
let frame_size: u8 = 2;
self.quotient_states.write_u8(frame_size);
self.quotient_states.write_many("ient_states);
}
pub fn parse<E: FieldElement>(
self,
main_trace_width: usize,
aux_trace_width: usize,
num_quotients: usize,
) -> Result<(TraceOodFrame<E>, QuotientOodFrame<E>), DeserializationError> {
assert!(main_trace_width > 0, "trace width cannot be zero");
assert!(num_quotients > 0, "number of evaluations cannot be zero");
let (trace_current_row, trace_next_row) = {
let mut reader = SliceReader::new(&self.trace_states);
let frame_size = reader.read_u8()? as usize;
assert_eq!(frame_size, 2);
let mut trace = reader.read_many((main_trace_width + aux_trace_width) * frame_size)?;
if reader.has_more_bytes() {
return Err(DeserializationError::UnconsumedBytes);
}
let next_row = trace.split_off(main_trace_width + aux_trace_width);
let current_row = trace;
(current_row, next_row)
};
let (quotients_current_row, quotients_next_row) = {
let mut reader = SliceReader::new(&self.quotient_states);
let frame_size = reader.read_u8()? as usize;
assert_eq!(frame_size, 2);
let mut quotients_evaluations = reader.read_many(num_quotients * frame_size)?;
if reader.has_more_bytes() {
return Err(DeserializationError::UnconsumedBytes);
}
let quotients_next_row = quotients_evaluations.split_off(num_quotients);
let quotients_current_row = quotients_evaluations;
(quotients_current_row, quotients_next_row)
};
Ok((
TraceOodFrame::new(trace_current_row, trace_next_row, main_trace_width),
QuotientOodFrame::new(quotients_current_row, quotients_next_row),
))
}
}
impl Serializable for OodFrame {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
target.write_u16(self.trace_states.len() as u16);
target.write_bytes(&self.trace_states);
target.write_u16(self.quotient_states.len() as u16);
target.write_bytes(&self.quotient_states)
}
fn get_size_hint(&self) -> usize {
self.trace_states.len() + self.quotient_states.len() + 4
}
}
impl Deserializable for OodFrame {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let num_trace_state_bytes = source.read_u16()? as usize;
let trace_states = source.read_vec(num_trace_state_bytes)?;
let num_constraint_evaluation_bytes = source.read_u16()? as usize;
let evaluations = source.read_vec(num_constraint_evaluation_bytes)?;
Ok(OodFrame {
trace_states,
quotient_states: evaluations,
})
}
}
pub struct TraceOodFrame<E: FieldElement> {
current_row: Vec<E>,
next_row: Vec<E>,
main_trace_width: usize,
}
impl<E: FieldElement> TraceOodFrame<E> {
pub fn new(current_row: Vec<E>, next_row: Vec<E>, main_trace_width: usize) -> Self {
assert_eq!(current_row.len(), next_row.len());
Self { current_row, next_row, main_trace_width }
}
pub fn num_columns(&self) -> usize {
self.current_row.len()
}
pub fn current_row(&self) -> &[E] {
&self.current_row
}
pub fn next_row(&self) -> &[E] {
&self.next_row
}
pub fn main_frame(&self) -> EvaluationFrame<E> {
let current = self.current_row[0..self.main_trace_width].to_vec();
let next = self.next_row[0..self.main_trace_width].to_vec();
EvaluationFrame::from_rows(current, next)
}
pub fn aux_frame(&self) -> Option<EvaluationFrame<E>> {
if self.has_aux_frame() {
let current = self.current_row[self.main_trace_width..].to_vec();
let next = self.next_row[self.main_trace_width..].to_vec();
Some(EvaluationFrame::from_rows(current, next))
} else {
None
}
}
fn has_aux_frame(&self) -> bool {
self.current_row.len() > self.main_trace_width
}
pub fn to_trace_states(&self) -> Vec<E> {
let mut main_and_aux_frame_states = Vec::new();
main_and_aux_frame_states.extend_from_slice(&self.current_row);
main_and_aux_frame_states.extend_from_slice(&self.next_row);
main_and_aux_frame_states
}
}
pub struct QuotientOodFrame<E: FieldElement> {
current_row: Vec<E>,
next_row: Vec<E>,
}
impl<E: FieldElement> QuotientOodFrame<E> {
pub fn new(current_row: Vec<E>, next_row: Vec<E>) -> Self {
assert_eq!(current_row.len(), next_row.len());
Self { current_row, next_row }
}
pub fn current_row(&self) -> &[E] {
&self.current_row
}
pub fn next_row(&self) -> &[E] {
&self.next_row
}
pub fn to_trace_states(&self) -> Vec<E> {
let mut quotients_frame_states = Vec::new();
quotients_frame_states.extend_from_slice(&self.current_row);
quotients_frame_states.extend_from_slice(&self.next_row);
quotients_frame_states
}
}
pub fn merge_ood_evaluations<E>(
trace_ood_frame: &TraceOodFrame<E>,
constraints_ood_frame: &QuotientOodFrame<E>,
) -> Vec<E>
where
E: FieldElement,
{
let mut current_row = trace_ood_frame.current_row().to_vec();
current_row.extend_from_slice(constraints_ood_frame.current_row());
let mut next_row = trace_ood_frame.next_row().to_vec();
next_row.extend_from_slice(constraints_ood_frame.next_row());
let mut ood_evals = current_row;
ood_evals.extend_from_slice(&next_row);
ood_evals
}