#![doc = include_str!("../examples/aok.rs")]
use crate::core::{AltHyp, Ci, HypTestResult};
pub trait AokFloat {
type Value;
fn aok(self) -> Self::Value;
}
impl<E> AokFloat for Result<f64, E> {
type Value = f64;
fn aok(self) -> Self::Value {
self.unwrap_or(f64::NAN)
}
}
pub trait AokBasicStats {
type Value: AokBasicStatsValue;
fn aok(self) -> Self::Value;
}
pub trait AokBasicStatsValue {
fn aok_fallback() -> Self;
fn is_tainted(&self) -> bool;
fn is_untainted(&self) -> bool {
!self.is_tainted()
}
}
impl<T, E> AokBasicStats for Result<T, E>
where
T: AokBasicStatsValue,
{
type Value = T;
fn aok(self) -> Self::Value {
self.unwrap_or_else(|_| T::aok_fallback())
}
}
impl AokBasicStatsValue for HypTestResult {
fn aok_fallback() -> Self {
HypTestResult::new(f64::NAN, f64::NAN, AltHyp::Ne)
}
fn is_tainted(&self) -> bool {
self.p().is_nan() || self.alpha().is_nan()
}
}
impl AokBasicStatsValue for Ci {
fn aok_fallback() -> Self {
Ci(f64::NAN, f64::NAN)
}
fn is_tainted(&self) -> bool {
self.0.is_nan() || self.1.is_nan()
}
}
#[cfg(test)]
#[cfg(feature = "normal")]
mod test {
use crate::aok::AokBasicStats;
mod another {
use std::{
error::Error,
fmt::{Debug, Display},
};
#[derive(Debug)]
pub struct AnotherError;
impl Display for AnotherError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self, f)
}
}
impl Error for AnotherError {}
#[derive(Debug)]
pub struct X {
pub x: f64,
}
impl X {
pub fn new(x: f64) -> Self {
X { x }
}
pub fn div(self, y: f64) -> Result<Self, AnotherError> {
if y != 0. {
Ok(X::new(self.x / y))
} else {
Err(AnotherError)
}
}
}
pub trait AokFloat {
type Output;
fn aok(self) -> Self::Output;
}
impl<E> AokFloat for Result<f64, E> {
type Output = f64;
fn aok(self) -> Self::Output {
self.unwrap_or(f64::NAN)
}
}
pub trait AokAnother {
type Output: AokAnotherFallback;
fn aok(self) -> Self::Output;
}
pub trait AokAnotherFallback {
fn aok_fallback() -> Self;
}
impl<T, E> AokAnother for Result<T, E>
where
T: AokAnotherFallback,
{
type Output = T;
fn aok(self) -> Self::Output {
self.unwrap_or_else(|_| T::aok_fallback())
}
}
impl AokAnotherFallback for X {
fn aok_fallback() -> Self {
X { x: f64::NAN }
}
}
}
#[test]
fn test_aok() {
use crate::{
core::{AltHyp, SampleMoments},
normal::{welch_alt_hyp_ci, welch_p},
};
let x = [14., 15., 15., 15., 16., 18., 22., 23., 24., 25., 25.];
let y = [
10., 12., 14., 15., 18., 22., 24., 27., 31., 33., 34., 34., 34.,
];
let moments_x = SampleMoments::from_slice(&x);
let moments_y = SampleMoments::from_slice(&y);
let alt_hyp = AltHyp::Gt;
{
use crate::aok::AokFloat;
{
println!("*** Ok scenario:");
let alpha = 0.05;
let p = welch_p(&moments_x, &moments_y, alt_hyp).aok();
println!("p={p}");
let ci = welch_alt_hyp_ci(&moments_x, &moments_y, alt_hyp, alpha).aok();
println!("ci={ci:?}");
assert!(p.is_finite());
assert!(ci.0.is_finite());
}
{
println!("*** Err scenario:");
let alpha = 1.0;
let p = welch_p(&moments_x, &SampleMoments::default(), alt_hyp).aok();
println!("p={p}");
let ci = welch_alt_hyp_ci(&moments_x, &moments_y, alt_hyp, alpha).aok();
println!("ci={ci:?}");
assert!(p.is_nan());
assert!(ci.0.is_nan());
}
}
{
use another::{AokAnother, AokFloat, X};
{
println!("*** Ok scenario:");
let alpha = 0.05;
let p = welch_p(&moments_x, &moments_y, alt_hyp).aok();
println!("p={p}");
let ci = welch_alt_hyp_ci(&moments_x, &moments_y, alt_hyp, alpha).aok();
println!("ci={ci:?}");
let x = X::new(1.);
let y = x.div(2.).aok();
println!("y={y:?}");
assert!(p.is_finite());
assert!(ci.0.is_finite());
assert!(y.x.is_finite());
}
{
println!("*** Err scenario:");
let alpha = 1.0;
let p = welch_p(&moments_x, &SampleMoments::default(), alt_hyp).aok();
println!("p={p}");
let ci = welch_alt_hyp_ci(&moments_x, &moments_y, alt_hyp, alpha).aok();
println!("ci={ci:?}");
let x = X::new(1.);
let y = x.div(0.).aok();
println!("y={y:?}");
assert!(p.is_nan());
assert!(ci.0.is_nan());
assert!(y.x.is_nan());
}
}
}
}