use russell_lab::*;
fn main() -> Result<(), StrError> {
#[rustfmt::skip]
let data = [
[ 0.35, 0.45, -0.14, -0.17],
[ 0.09, 0.07, -0.54, 0.35],
[-0.44, -0.33, -0.03, 0.17],
[ 0.25, -0.32, -0.13, 0.11],
];
let mut a = Matrix::from(&data);
let m = a.nrow();
let mut l_real = Vector::new(m);
let mut l_imag = Vector::new(m);
let mut u_real = Matrix::new(m, m);
let mut u_imag = Matrix::new(m, m);
let mut v_real = Matrix::new(m, m);
let mut v_imag = Matrix::new(m, m);
mat_eigen_lr(
&mut l_real,
&mut l_imag,
&mut u_real,
&mut u_imag,
&mut v_real,
&mut v_imag,
&mut a,
)?;
#[rustfmt::skip]
let lambda_real_correct = &[
7.994821225862098e-01,
-9.941245329507467e-02,
-9.941245329507467e-02,
-1.006572159960587e-01,
];
#[rustfmt::skip]
let lambda_imag_correct = &[
0.0,
4.007924719897546e-01,
-4.007924719897546e-01,
0.0,
];
vec_approx_eq(&l_real, lambda_real_correct, 1e-14);
vec_approx_eq(&l_imag, lambda_imag_correct, 1e-14);
let a = ComplexMatrix::from(&data);
let mut v = ComplexMatrix::new(m, m);
let mut d = ComplexVector::new(m);
complex_mat_zip(&mut v, &v_real, &v_imag)?;
complex_vec_zip(&mut d, &l_real, &l_imag)?;
let lam = ComplexMatrix::diagonal(d.as_data());
let mut a_v = ComplexMatrix::new(m, m);
let mut v_l = ComplexMatrix::new(m, m);
let mut err = ComplexMatrix::filled(m, m, cpx!(f64::MAX, f64::MAX));
let one = cpx!(1.0, 0.0);
let m_one = cpx!(-1.0, 0.0);
let zero = cpx!(0.0, 0.0);
complex_mat_mat_mul(&mut a_v, one, &a, &v, zero)?;
complex_mat_mat_mul(&mut v_l, one, &v, &lam, zero)?;
complex_mat_add(&mut err, one, &a_v, m_one, &v_l)?;
approx_eq(complex_mat_norm(&err, Norm::Max), 0.0, 1e-14);
Ok(())
}