use crate::{stack::STACK_TOP_SIZE, StackTopState};
use super::{Felt, StarkField};
use winter_utils::collections::Vec;
#[derive(Debug, Clone, Default)]
pub struct ProgramOutputs {
stack: Vec<u64>,
overflow_addrs: Vec<u64>,
}
impl ProgramOutputs {
pub fn new(stack: Vec<u64>, overflow_addrs: Vec<u64>) -> Self {
debug_assert!(
are_valid_elements(&stack),
"stack outputs contain values that are not valid field elements",
);
debug_assert!(
are_valid_elements(&overflow_addrs),
"overflow address outputs contain values that are not valid field elements",
);
Self {
stack,
overflow_addrs,
}
}
pub fn from_elements(stack: Vec<Felt>, overflow_addrs: Vec<Felt>) -> Self {
let stack = stack.iter().map(|&v| v.as_int()).collect::<Vec<_>>();
let overflow_addrs = overflow_addrs
.iter()
.map(|&v| v.as_int())
.collect::<Vec<_>>();
Self {
stack,
overflow_addrs,
}
}
pub fn stack(&self) -> &[u64] {
&self.stack
}
pub fn stack_outputs(&self, num_outputs: usize) -> &[u64] {
if num_outputs < self.stack.len() {
return &self.stack[..num_outputs];
}
&self.stack
}
pub fn stack_top(&self) -> StackTopState {
self.stack
.iter()
.take(STACK_TOP_SIZE)
.map(|v| Felt::new(*v))
.collect::<Vec<_>>()
.try_into()
.expect("failed to convert vector to array")
}
pub fn overflow_addrs(&self) -> &[u64] {
&self.overflow_addrs
}
pub fn has_overflow(&self) -> bool {
!self.overflow_addrs.is_empty()
}
pub fn overflow_prev(&self) -> Felt {
Felt::new(self.overflow_addrs[0])
}
pub fn stack_overflow(&self) -> Vec<(Felt, Felt)> {
let mut overflow = Vec::with_capacity(self.overflow_addrs.len() - 1);
for (addr, val) in self
.overflow_addrs
.iter()
.skip(1)
.zip(self.stack.iter().skip(STACK_TOP_SIZE).rev())
{
overflow.push((Felt::new(*addr), Felt::new(*val)));
}
overflow
}
pub fn stack_mut(&mut self) -> &mut [u64] {
&mut self.stack
}
}
fn are_valid_elements(outputs: &[u64]) -> bool {
for val in outputs {
if *val >= Felt::MODULUS {
return false;
}
}
true
}