mod swilk;
use std::iter::IntoIterator;
use ndarray::Array1;
use swilk::swilk;
use crate::{Computation, Error, Float};
pub fn shapiro_wilk<T: Float, I: IntoIterator<Item = T>>(data: I) -> Result<Computation<T>, Error> {
let data: Vec<T> = data.into_iter().collect();
let n = data.len();
if n < 3 {
return Err(Error::InsufficientSampleSize {
given: n,
needed: 3,
});
}
let mut a = Array1::<T>::zeros(n / 2);
let init = false;
let n1_in = -1;
let mut y_vec = data;
sort_if_parallel!(y_vec.as_mut_slice(), |a, b| a.partial_cmp(b).unwrap());
let mut y = Array1::from_vec(y_vec);
let median_val = y[n / 2];
y.mapv_inplace(|v| v - median_val);
let (w, pw, ifault) = swilk(&y.view(), a.view_mut(), init, n1_in);
if ifault != 0 {
return match ifault {
2 => Err(Error::ExcessiveSampleSize {
given: n,
needed: 5000,
}),
6 => Err(Error::ZeroRange),
_ => Err(Error::Other(format!("Internal error with ifault {ifault}"))),
};
}
let result = Computation {
statistic: w,
p_value: pw,
};
Ok(result)
}