#![allow(clippy::excessive_precision)]
use fdars_core::matrix::FdMatrix;
const FANOVA_N_PERM: usize = 199;
const FANOVA_GLOBAL_STATISTIC: f64 = 42.36027574578335;
const FANOVA_P_VALUE_SEED42: f64 = 0.11;
const FANOVA_P_VALUE_SEED7: f64 = 0.105;
fn fanova_fixture() -> (FdMatrix, Vec<usize>) {
let n = 6usize;
let m = 5usize;
let mut cm = vec![0.0f64; n * m];
for j in 0..m {
let t = j as f64 / (m - 1) as f64;
for i in 0..n {
let g = if i < 3 { 0.0 } else { 1.5 };
let v = (t * (i as f64 + 1.0)).sin() + g + 0.1 * (i as f64) * t;
cm[i + j * n] = v;
}
}
let data = FdMatrix::from_column_major(cm, n, m).unwrap();
let groups = vec![0usize, 0, 0, 1, 1, 1];
(data, groups)
}
#[test]
fn fanova_seeded_seed42_bit_identical() {
use fdars_core::function_on_scalar::fanova_seeded;
let (data, groups) = fanova_fixture();
let r = fanova_seeded(&data, &groups, FANOVA_N_PERM, 42).unwrap();
assert_eq!(r.global_statistic, FANOVA_GLOBAL_STATISTIC);
assert_eq!(r.p_value, FANOVA_P_VALUE_SEED42);
assert_eq!(r.n_perm, FANOVA_N_PERM);
}
#[test]
fn fanova_seeded_different_seed_changes_pvalue_not_statistic() {
use fdars_core::function_on_scalar::fanova_seeded;
let (data, groups) = fanova_fixture();
let r7 = fanova_seeded(&data, &groups, FANOVA_N_PERM, 7).unwrap();
assert_eq!(r7.global_statistic, FANOVA_GLOBAL_STATISTIC);
assert_eq!(r7.p_value, FANOVA_P_VALUE_SEED7);
assert_ne!(r7.p_value, FANOVA_P_VALUE_SEED42);
}
use fdars_core::Dim;
fn dispatch_fixture(n: usize, m: usize) -> FdMatrix {
let mut cm = vec![0.0f64; n * m];
for j in 0..m {
let t = j as f64 / (m as f64 - 1.0);
for i in 0..n {
cm[i + j * n] = (t * std::f64::consts::PI).sin() + 0.05 * i as f64;
}
}
FdMatrix::from_column_major(cm, n, m).unwrap()
}
fn assert_valid_depth_vec(vec: &[f64], n_obs: usize) {
assert_eq!(vec.len(), n_obs, "depth vector length must equal n_obs");
for &d in vec {
assert!(
(0.0..=1.0).contains(&d),
"depth value {d} out of [0, 1] range"
);
}
}
#[test]
fn dispatch_modal_equals_1d() {
use fdars_core::depth::modal;
let data = dispatch_fixture(6, 12);
let h = 0.5;
let unified_one = modal(&data, &data, h, Dim::One);
let unified_two = modal(&data, &data, h, Dim::Two);
assert_eq!(unified_one, unified_two);
}
#[test]
fn dispatch_fraiman_muniz_equals_1d() {
use fdars_core::depth::fraiman_muniz;
let data = dispatch_fixture(6, 12);
for scale in [true, false] {
let unified_two = fraiman_muniz(&data, &data, scale, Dim::Two);
let unified_one = fraiman_muniz(&data, &data, scale, Dim::One);
assert_eq!(unified_two, unified_one);
}
}
#[test]
fn dispatch_mean_equals_1d() {
use fdars_core::fdata::mean;
let data = dispatch_fixture(6, 12);
let unified_one = mean(&data, Dim::One);
let unified_two = mean(&data, Dim::Two);
assert_eq!(unified_one, unified_two);
}
#[test]
fn dispatch_random_projection_is_valid() {
use fdars_core::depth::random_projection;
let data = dispatch_fixture(6, 12);
let got = random_projection(&data, &data, 20, Dim::One);
assert_valid_depth_vec(&got, data.nrows());
let got_two = random_projection(&data, &data, 20, Dim::Two);
assert_valid_depth_vec(&got_two, data.nrows());
}
#[test]
fn dispatch_random_tukey_is_valid() {
use fdars_core::depth::random_tukey;
let data = dispatch_fixture(6, 12);
let got = random_tukey(&data, &data, 20, Dim::Two);
assert_valid_depth_vec(&got, data.nrows());
let got_one = random_tukey(&data, &data, 20, Dim::One);
assert_valid_depth_vec(&got_one, data.nrows());
}