use crate::{
algebra::{
abstr::{Field, Scalar},
linear::matrix::{General, HessenbergDec, HessenbergDecomposition, UpperHessenberg},
},
elementary::Power,
};
impl<T> HessenbergDecomposition<T> for General<T>
where
T: Field + Scalar + Power,
{
fn dec_hessenberg(&self) -> HessenbergDec<T> {
let (m, n): (usize, usize) = self.dim();
debug_assert_eq!(
m, n,
"Unable to compute the hessenberg decomposition of a non-square matrix"
);
debug_assert_ne!(
m, 0,
"Unable to compute the hessenberg decomposition of an empty matrix."
);
let (m, n): (usize, usize) = self.dim();
let mut self_data = self.clone().data;
let n_i32: i32 = n as i32;
let mut tau: Vec<T> = vec![T::zero(); n - 1];
let mut info: i32 = 0;
let lwork: i32 = T::xgehrd_work_size(
n_i32,
1,
n_i32,
&mut self_data[..],
n_i32,
tau.as_mut(),
&mut info,
);
debug_assert_eq!(0, info);
let mut work_xgehrd: Vec<T> = vec![T::zero(); lwork as usize];
T::xgehrd(
n_i32,
1,
n_i32,
&mut self_data[..],
n_i32,
tau.as_mut(),
&mut work_xgehrd[..],
lwork,
&mut info,
);
debug_assert_eq!(0, info);
let h: General<T> = General::new(n, n, self_data.clone()).h();
let mut q = self_data;
let mut info: i32 = 0;
let lwork: i32 =
T::xorghr_work_size(n_i32, 1, n_i32, &mut q[..], n_i32, tau.as_mut(), &mut info);
let mut work_xorghr = vec![T::zero(); lwork as usize];
debug_assert_eq!(0, info);
T::xorghr(
n_i32,
1,
n_i32,
&mut q[..],
n_i32,
&tau[..],
&mut work_xorghr[..],
lwork,
&mut info,
);
debug_assert_eq!(0, info);
HessenbergDec::new(General::new(m, n, q), UpperHessenberg::new(h))
}
}
impl<T> General<T>
where
T: Field + Scalar + Power,
{
fn h(mut self) -> Self {
let (m, _n) = self.dim();
for i in 2..m {
for k in 0..(i - 1) {
self[[i, k]] = T::zero();
}
}
self
}
}