#[must_use]
#[inline]
pub fn t_statistic_to_d_prime(t: f64, n: usize) -> f64 {
if n == 0 {
return 0.0;
}
t / (n as f64).sqrt()
}
#[must_use]
#[inline]
pub fn t_statistic_to_cohens_d(t: f64, n1: usize, n2: usize) -> f64 {
let df = (n1 + n2).saturating_sub(2);
if df == 0 {
return 0.0;
}
2.0 * t / (df as f64).sqrt()
}
#[must_use]
#[inline]
pub fn variance_explained_to_reliability(proportion_explained: f64) -> f64 {
proportion_explained.clamp(0.0, 1.0)
}
#[must_use]
#[inline]
pub fn correlation_to_determination(r: f64) -> (f64, f64) {
let r_sq = r * r;
(r_sq, r_sq)
}
#[must_use]
#[inline]
pub fn loglog_regression_to_learning_rate(intercept: f64, slope: f64) -> (f64, f64) {
(intercept.exp(), -slope)
}
#[must_use]
#[inline]
pub fn smoothing_alpha_to_stability(alpha: f64) -> f64 {
if alpha <= 0.0 || !alpha.is_finite() {
return f64::MAX;
}
1.0 / alpha
}
#[must_use]
#[inline]
pub fn posterior_to_odds(posterior: f64) -> f64 {
if posterior >= 1.0 {
return f64::MAX;
}
if posterior <= 0.0 {
return 0.0;
}
posterior / (1.0 - posterior)
}
#[must_use]
#[inline]
pub fn logistic_coeff_to_odds_ratio(beta: f64) -> f64 {
beta.exp()
}
#[must_use]
#[inline]
pub fn variance_to_arousal(variance: f64, reference_variance: f64) -> f64 {
if reference_variance <= 0.0 || !reference_variance.is_finite() {
return 0.0;
}
(variance / reference_variance).clamp(0.0, 1.0)
}
#[must_use]
#[inline]
pub fn z_score_to_valence(z: f64) -> f64 {
z.tanh()
}
#[must_use]
#[inline]
pub fn f_statistic_to_eta_squared(f: f64, df_between: usize, df_within: usize) -> f64 {
if df_within == 0 || f <= 0.0 {
return 0.0;
}
let num = f * df_between as f64;
let denom = num + df_within as f64;
if denom < 1e-15 {
return 0.0;
}
(num / denom).clamp(0.0, 1.0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_t_to_d_prime() {
let d = t_statistic_to_d_prime(2.0, 100);
assert!((d - 0.2).abs() < 1e-10);
}
#[test]
fn test_t_to_d_prime_zero_n() {
assert!(t_statistic_to_d_prime(2.0, 0).abs() < 1e-10);
}
#[test]
fn test_t_to_cohens_d() {
let d = t_statistic_to_cohens_d(3.0, 30, 30);
assert!((d - 6.0 / 58.0_f64.sqrt()).abs() < 1e-10);
}
#[test]
fn test_variance_explained_clamps() {
assert!((variance_explained_to_reliability(0.85) - 0.85).abs() < 1e-10);
assert!((variance_explained_to_reliability(1.5) - 1.0).abs() < 1e-10);
assert!((variance_explained_to_reliability(-0.1) - 0.0).abs() < 1e-10);
}
#[test]
fn test_correlation_to_determination() {
let (r_sq, _) = correlation_to_determination(0.7);
assert!((r_sq - 0.49).abs() < 1e-10);
}
#[test]
fn test_loglog_to_learning_rate() {
let (a, b) = loglog_regression_to_learning_rate(10.0_f64.ln(), -0.3);
assert!((a - 10.0).abs() < 1e-6);
assert!((b - 0.3).abs() < 1e-10);
}
#[test]
fn test_smoothing_to_stability() {
assert!((smoothing_alpha_to_stability(0.1) - 10.0).abs() < 1e-10);
assert!((smoothing_alpha_to_stability(1.0) - 1.0).abs() < 1e-10);
}
#[test]
fn test_smoothing_to_stability_zero() {
assert_eq!(smoothing_alpha_to_stability(0.0), f64::MAX);
}
#[test]
fn test_posterior_to_odds() {
assert!((posterior_to_odds(0.75) - 3.0).abs() < 1e-10);
}
#[test]
fn test_posterior_to_odds_extremes() {
assert!(posterior_to_odds(0.0).abs() < 1e-10);
assert_eq!(posterior_to_odds(1.0), f64::MAX);
}
#[test]
fn test_logistic_coeff_to_odds_ratio() {
assert!((logistic_coeff_to_odds_ratio(0.0) - 1.0).abs() < 1e-10);
assert!((logistic_coeff_to_odds_ratio(2.0_f64.ln()) - 2.0).abs() < 1e-10);
}
#[test]
fn test_variance_to_arousal() {
assert!((variance_to_arousal(5.0, 10.0) - 0.5).abs() < 1e-10);
assert!((variance_to_arousal(20.0, 10.0) - 1.0).abs() < 1e-10); }
#[test]
fn test_z_score_to_valence() {
assert!(z_score_to_valence(0.0).abs() < 1e-10);
assert!(z_score_to_valence(3.0) > 0.9); assert!(z_score_to_valence(-3.0) < -0.9); }
#[test]
fn test_f_to_eta_squared() {
let eta = f_statistic_to_eta_squared(5.0, 2, 27);
assert!((eta - 10.0 / 37.0).abs() < 1e-10);
}
#[test]
fn test_f_to_eta_squared_zero() {
assert!(f_statistic_to_eta_squared(0.0, 2, 27).abs() < 1e-10);
}
}