use ndarray::{Array2, ArrayBase, Data, DataMut, Ix2, RawDataClone};
use num::Complex;
#[derive(Clone)]
pub struct QRDecomp {
pub q: Array2<Complex<f32>>,
pub r: Array2<Complex<f32>>,
}
impl QRDecomp {
pub fn new<S: Data<Elem = Complex<f32>> + RawDataClone + DataMut<Elem = Complex<f32>>>(
a: &ArrayBase<S, Ix2>,
) -> Option<Self> {
let s = a.shape();
let (m, n) = (s[0], s[1]);
let mut q = Array2::zeros((m, n));
let mut r = Array2::zeros((n, n));
for j in 0..n {
let mut v = a.row(j).to_owned();
for i in 0..j {
*r.get_mut((i, j)).unwrap() = q.row(i).dot(&v);
v = v - (*r.get((i, j)).unwrap() * q.row(i).to_owned());
}
*r.get_mut((j, j)).unwrap() = v.iter().map(|x| x.powu(2)).sum::<Complex<f32>>().sqrt();
q.row_mut(j)
.iter_mut()
.enumerate()
.for_each(|(i, x)| *x = *v.get(i).unwrap() / *r.get((j, j)).unwrap());
}
Some(Self { q, r })
}
pub fn to_tuple(self) -> (Array2<Complex<f32>>, Array2<Complex<f32>>) {
(self.q, self.r)
}
}