use super::decomp::cholesky::cholesky_factor;
use crate::core::errors::RustyQLibError;
pub fn cholesky(m: &[Vec<f64>]) -> Result<Vec<Vec<f64>>, RustyQLibError> {
for (i, row) in m.iter().enumerate() {
if (row[i] - 1.0).abs() > 1e-10 {
return Err(RustyQLibError::NumericalError(format!("diagonal element [{i}][{i}] must be 1")));
}
}
cholesky_factor(m)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn factorizes_and_rejects_correctly() {
let l = cholesky(&[vec![1.0, 0.5], vec![0.5, 1.0]]).unwrap();
assert!((l[1][0] - 0.5).abs() < 1e-12 && (l[1][1] - 0.75_f64.sqrt()).abs() < 1e-12);
assert!(cholesky(&[vec![1.0, 0.5], vec![0.4, 1.0]]).is_err());
assert!(cholesky(&[vec![2.0, 0.0], vec![0.0, 1.0]]).is_err());
assert!(cholesky(&[
vec![1.0, 0.9, -0.9],
vec![0.9, 1.0, 0.9],
vec![-0.9, 0.9, 1.0]
])
.is_err());
}
}