use crate::{ConfidenceLevel, ValidationError, validate_probability};
use num_traits::{Float, FromPrimitive, ToPrimitive};
use std::fmt;
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct SignificanceLevel<T>(T);
impl<T: ToPrimitive> fmt::Display for SignificanceLevel<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let percent = self.0.to_f64().ok_or(fmt::Error)? * 100.0;
match f.precision() {
Some(p) => write!(f, "{percent:.p$}%"),
None => write!(f, "{percent:.1}%"),
}
}
}
macro_rules! impl_significance_constants {
($t:ty) => {
impl SignificanceLevel<$t> {
pub const SL10: Self = Self(0.10);
pub const SL05: Self = Self(0.05);
pub const SL025: Self = Self(0.025);
pub const SL01: Self = Self(0.01);
pub const SL001: Self = Self(0.001);
}
};
}
impl_significance_constants!(f32);
impl_significance_constants!(f64);
impl<T> SignificanceLevel<T> {
pub fn into_inner(self) -> T {
self.0
}
}
impl<T: Float> SignificanceLevel<T> {
pub fn new(probability: T) -> Result<Self, ValidationError> {
let probability = validate_probability(probability)?;
Ok(Self(probability))
}
}
impl<T: Float + FromPrimitive + ToPrimitive> SignificanceLevel<T> {
pub fn from_percent(percentage: T) -> Result<Self, ValidationError> {
let level = validate_probability(percentage / T::from_f64(100.0).unwrap())?;
Ok(Self(level))
}
pub fn confidence(self) -> ConfidenceLevel<T> {
ConfidenceLevel::new(T::one() - self.0).unwrap() }
}
impl<T: ToPrimitive> SignificanceLevel<T> {
pub fn to_f64(self) -> Option<SignificanceLevel<f64>> {
self.0.to_f64().map(SignificanceLevel)
}
pub fn to_f32(self) -> Option<SignificanceLevel<f32>> {
self.0.to_f32().map(SignificanceLevel)
}
}
impl<T: Float> From<SignificanceLevel<T>> for ConfidenceLevel<T> {
fn from(significance_level: SignificanceLevel<T>) -> Self {
ConfidenceLevel::new(T::one() - significance_level.0).unwrap() }
}