use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PrecisionLevel {
Low,
Moderate,
High,
Max,
}
impl PrecisionLevel {
pub fn factor(self) -> f64 {
match self {
PrecisionLevel::Low => 5.0,
PrecisionLevel::Moderate => 3.0,
PrecisionLevel::High => 1.5,
PrecisionLevel::Max => 1.0,
}
}
pub fn description(self) -> &'static str {
match self {
PrecisionLevel::Low => "Low (5× noise — easy, few samples)",
PrecisionLevel::Moderate => "Moderate (3× noise — balanced, typical)",
PrecisionLevel::High => "High (1.5× noise — challenging, many samples)",
PrecisionLevel::Max => "Maximum (1× noise — sensor-limited, theoretical)",
}
}
pub fn estimated_samples(self) -> usize {
match self {
PrecisionLevel::Low => 10,
PrecisionLevel::Moderate => 25,
PrecisionLevel::High => 60,
PrecisionLevel::Max => 200,
}
}
}
impl fmt::Display for PrecisionLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.description())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Feasibility {
Achievable,
Marginal,
Unachievable,
}
impl fmt::Display for Feasibility {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Feasibility::Achievable => write!(f, "Achievable"),
Feasibility::Marginal => write!(f, "Marginal (close to noise floor)"),
Feasibility::Unachievable => write!(f, "Unachievable (below noise floor)"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrecisionTierInfo {
pub level: PrecisionLevel,
pub absolute_tolerance: f64,
pub estimated_samples: usize,
pub feasibility: Feasibility,
}
impl fmt::Display for PrecisionTierInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:<10} ±{:.4} ~{:>3} samples [{}]",
format!("{:?}", self.level),
self.absolute_tolerance,
self.estimated_samples,
self.feasibility,
)
}
}
pub fn compute_precision_tiers(sigma_noise: f64) -> [PrecisionTierInfo; 4] {
let make_tier = |level: PrecisionLevel, feasibility: Feasibility| -> PrecisionTierInfo {
PrecisionTierInfo {
absolute_tolerance: sigma_noise * level.factor(),
estimated_samples: level.estimated_samples(),
level,
feasibility,
}
};
[
make_tier(PrecisionLevel::Low, Feasibility::Achievable),
make_tier(PrecisionLevel::Moderate, Feasibility::Achievable),
make_tier(PrecisionLevel::High, Feasibility::Achievable),
make_tier(PrecisionLevel::Max, Feasibility::Marginal),
]
}
#[cfg(test)]
mod tests {
use super::*;
const SIGMA: f64 = 0.008;
#[test]
fn test_precision_tier_low() {
let tiers = compute_precision_tiers(SIGMA);
assert!(
(tiers[0].absolute_tolerance - SIGMA * 5.0).abs() < 1e-10,
"Low tier factor 5.0"
);
assert_eq!(tiers[0].level, PrecisionLevel::Low);
}
#[test]
fn test_precision_tier_moderate() {
let tiers = compute_precision_tiers(SIGMA);
assert!(
(tiers[1].absolute_tolerance - SIGMA * 3.0).abs() < 1e-10,
"Moderate: 3.0 × 0.008 = 0.024"
);
assert_eq!(tiers[1].level, PrecisionLevel::Moderate);
}
#[test]
fn test_precision_tier_high() {
let tiers = compute_precision_tiers(SIGMA);
assert!(
(tiers[2].absolute_tolerance - SIGMA * 1.5).abs() < 1e-10,
"High tier factor 1.5"
);
assert_eq!(tiers[2].level, PrecisionLevel::High);
}
#[test]
fn test_precision_tier_max() {
let tiers = compute_precision_tiers(SIGMA);
assert!(
(tiers[3].absolute_tolerance - SIGMA * 1.0).abs() < 1e-10,
"Max tier factor 1.0"
);
assert_eq!(tiers[3].level, PrecisionLevel::Max);
}
#[test]
fn test_precision_tier_max_is_marginal() {
let tiers = compute_precision_tiers(SIGMA);
assert_eq!(
tiers[3].feasibility,
Feasibility::Marginal,
"Max tier is inherently marginal (at noise floor)"
);
}
#[test]
fn test_precision_tiers_are_monotonically_decreasing() {
let tiers = compute_precision_tiers(SIGMA);
for i in 0..3 {
assert!(
tiers[i].absolute_tolerance > tiers[i + 1].absolute_tolerance,
"Tiers should be ordered from loosest to tightest"
);
}
}
#[test]
fn test_precision_tier_estimated_samples() {
assert_eq!(PrecisionLevel::Low.estimated_samples(), 10);
assert_eq!(PrecisionLevel::Moderate.estimated_samples(), 25);
assert_eq!(PrecisionLevel::High.estimated_samples(), 60);
assert_eq!(PrecisionLevel::Max.estimated_samples(), 200);
}
#[test]
fn test_factor_values() {
assert!((PrecisionLevel::Low.factor() - 5.0).abs() < 1e-10);
assert!((PrecisionLevel::Moderate.factor() - 3.0).abs() < 1e-10);
assert!((PrecisionLevel::High.factor() - 1.5).abs() < 1e-10);
assert!((PrecisionLevel::Max.factor() - 1.0).abs() < 1e-10);
}
}