use alloc::vec::Vec;
use core::cmp;
use super::{super::super::ProofOptions, MIN_CYCLE_LENGTH};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TransitionConstraintDegree {
base: usize,
cycles: Vec<usize>,
}
impl TransitionConstraintDegree {
pub fn new(degree: usize) -> Self {
assert!(degree > 0, "transition constraint degree must be at least one, but was zero");
TransitionConstraintDegree { base: degree, cycles: vec![] }
}
pub fn with_cycles(base_degree: usize, cycles: Vec<usize>) -> Self {
assert!(
base_degree > 0,
"transition constraint degree must be at least one, but was zero"
);
for (i, &cycle) in cycles.iter().enumerate() {
assert!(
cycle >= MIN_CYCLE_LENGTH,
"cycle length must be at least {MIN_CYCLE_LENGTH}, but was {cycle} for cycle {i}"
);
assert!(
cycle.is_power_of_two(),
"cycle length must be a power of two, but was {cycle} for cycle {i}"
);
}
TransitionConstraintDegree { base: base_degree, cycles }
}
pub fn get_evaluation_degree(&self, trace_length: usize) -> usize {
let mut result = self.base * (trace_length - 1);
for cycle_length in self.cycles.iter() {
result += (trace_length / cycle_length) * (cycle_length - 1);
}
result
}
pub fn min_blowup_factor(&self) -> usize {
let degree_bound = self.base + self.cycles.len() - 1;
cmp::max(degree_bound.next_power_of_two(), ProofOptions::MIN_BLOWUP_FACTOR)
}
}