use crate::query_result::QueryResult;
use super::descriptive::calculate_std_dev;
use super::types::ConfidenceInterval;
pub(super) fn calculate_confidence_interval(
values: &[f64],
confidence_level: f64,
) -> ConfidenceInterval {
if values.is_empty() {
return ConfidenceInterval {
estimate: 0.0,
lower_bound: 0.0,
upper_bound: 0.0,
confidence: confidence_level,
};
}
let n = values.len() as f64;
let mean = values.iter().sum::<f64>() / n;
let std_dev = calculate_std_dev(values, mean);
let std_error = std_dev / n.sqrt();
let critical_value = if n >= 30.0 {
if confidence_level >= 0.99 {
2.576
} else if confidence_level >= 0.95 {
1.96
} else {
1.645 }
} else {
let df = (n - 1.0).max(1.0);
if confidence_level >= 0.99 {
2.576 + 3.0 / df
} else if confidence_level >= 0.95 {
1.96 + 2.0 / df
} else {
1.645 + 1.5 / df
}
};
let margin = critical_value * std_error;
ConfidenceInterval {
estimate: mean,
lower_bound: mean - margin,
upper_bound: mean + margin,
confidence: confidence_level,
}
}
pub(super) fn value_confidence_interval(
result: &QueryResult,
confidence_level: f64,
) -> ConfidenceInterval {
let values: Vec<f64> = result
.matches
.as_ref()
.map(|m_vec| {
m_vec
.iter()
.map(|m| m.confidence) .collect()
})
.unwrap_or_default();
calculate_confidence_interval(&values, confidence_level)
}
pub(super) fn match_rate_confidence_interval(
matches: usize,
total: usize,
confidence_level: f64,
) -> ConfidenceInterval {
if total == 0 {
return ConfidenceInterval {
estimate: 0.0,
lower_bound: 0.0,
upper_bound: 0.0,
confidence: confidence_level,
};
}
let p = matches as f64 / total as f64;
let n = total as f64;
let z = if confidence_level >= 0.99 {
2.576
} else if confidence_level >= 0.95 {
1.96
} else {
1.645
};
let z_sq = z * z;
let denominator = 1.0 + z_sq / n;
let center = (p + z_sq / (2.0 * n)) / denominator;
let margin = z * (p * (1.0 - p) / n + z_sq / (4.0 * n * n)).sqrt() / denominator;
ConfidenceInterval {
estimate: p,
lower_bound: (center - margin).max(0.0),
upper_bound: (center + margin).min(1.0),
confidence: confidence_level,
}
}