use crate::versor::{HouseholderChain, HouseholderVersor};
pub struct CartanDieudonneDecomposer;
impl CartanDieudonneDecomposer {
pub fn decompose_orthogonal(matrix: &[f32], n: usize) -> HouseholderChain {
assert_eq!(matrix.len(), n * n, "Matrix size must equal n * n");
let mut a = matrix.to_vec();
let mut chain = HouseholderChain::new(n);
let mut intermediate_versors = Vec::new();
for j in 0..n {
let mut norm_sq = 0.0f32;
for i in j..n {
let val = a[i * n + j];
norm_sq += val * val;
}
let norm = norm_sq.sqrt();
if norm < 1e-12 {
continue;
}
let alpha = if a[j * n + j] >= 0.0 { -norm } else { norm };
let mut v = vec![0.0f32; n];
for i in j..n {
v[i] = a[i * n + j];
}
v[j] -= alpha;
let mut v_norm_sq = 0.0f32;
for i in j..n {
v_norm_sq += v[i] * v[i];
}
if v_norm_sq > 1e-12 {
let versor = HouseholderVersor::new(v);
for col in j..n {
let mut col_vec = vec![0.0f32; n];
for row in 0..n {
col_vec[row] = a[row * n + col];
}
versor.reflect_in_place(&mut col_vec);
for row in 0..n {
a[row * n + col] = col_vec[row];
}
}
intermediate_versors.push(versor);
}
}
for j in 0..n {
if a[j * n + j] < 0.0 {
let mut v_diag = vec![0.0f32; n];
v_diag[j] = 1.0;
chain.push(HouseholderVersor::new(v_diag));
}
}
for v in intermediate_versors.into_iter().rev() {
chain.push(v);
}
chain
}
}