mod breusch_pagan;
mod durbin_watson;
mod jarque_bera;
mod qq_plot_data;
mod standardized;
mod studentized;
mod white_test;
pub use breusch_pagan::{breusch_pagan, BreuschPagan};
pub use durbin_watson::durbin_watson;
pub use jarque_bera::{jarque_bera, JarqueBera};
pub use qq_plot_data::qq_plot_data;
pub use standardized::standardized_residuals;
pub use studentized::{externally_studentized_residuals, internally_studentized_residuals};
pub use white_test::{white_test, WhiteTest};
use statrs::distribution::{ChiSquared, ContinuousCDF};
use crate::linalg::{aux_r_squared, dmatrix_from_rows, dvector_from_slice};
use crate::OlsFit;
pub(crate) fn non_intercept_columns(fit: &OlsFit) -> Vec<usize> {
(0..fit.n_parameters())
.filter(|&j| fit.intercept_column() != Some(j))
.collect()
}
pub(crate) fn lm_heteroskedasticity_test(
n: usize,
regressors: &[Vec<f64>],
target: &[f64],
) -> (f64, usize, f64) {
let q = regressors.len();
if q == 0 || q + 1 >= n {
return (f64::NAN, q, f64::NAN);
}
let mut data = Vec::with_capacity(n * (q + 1));
for i in 0..n {
data.push(1.0);
for reg in regressors {
data.push(reg[i]);
}
}
let design = dmatrix_from_rows(n, q + 1, &data);
let target_dv = dvector_from_slice(target);
let r2 = aux_r_squared(&design, &target_dv).unwrap_or(0.0);
let lm = n as f64 * r2;
let p_value = match ChiSquared::new(q as f64) {
Ok(dist) if lm.is_finite() && lm >= 0.0 && q > 0 => 1.0 - dist.cdf(lm),
_ => f64::NAN,
};
(lm, q, p_value)
}