use super::measure::{Metric, Metrics};
use super::tier::{OptimizationBudget, TiePolicy};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Rejection {
Regressed(Metric),
NoImprovement,
}
#[must_use]
pub const fn epsilon_pct(budget: &OptimizationBudget, metric: Metric) -> u32 {
match metric {
Metric::EmittedSize => budget.emitted_size_epsilon_pct,
Metric::ReactiveEdge => budget.reactive_edge_epsilon_pct,
Metric::UpdatePath => budget.update_path_epsilon_pct,
}
}
pub fn judge(
before: Metrics,
after: Metrics,
budget: &OptimizationBudget,
) -> Result<(), Rejection> {
let mut improved = 0u32;
for metric in Metric::CHECK_ORDER {
let (was, now) = (before.get(metric), after.get(metric));
let allowed = was + was * u64::from(epsilon_pct(budget, metric)) / 100;
if now > allowed {
return Err(Rejection::Regressed(metric));
}
improved += u32::from(now < was);
}
let tie = improved == 0 && matches!(budget.tie_policy, TiePolicy::Reject);
if tie || improved < budget.required_improvements_min {
return Err(Rejection::NoImprovement);
}
Ok(())
}