use ndarray::*; use ndarray_linalg::{krylov::*, *}; fn over(rtol: A::Real) { const N: usize = 4; let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); let a: Array2 = random_using((N, N * 2), &mut rng); // Terminate let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Terminate); let a_sub = a.slice(s![.., 0..N]); let qc: Array2 = conjugate(&q); assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol; "Check Q^H Q = I"); assert_close_l2!(&q.dot(&r), &a_sub, rtol; "Check A = QR"); // Skip let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Skip); let a_sub = a.slice(s![.., 0..N]); let qc: Array2 = conjugate(&q); assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol); assert_close_l2!(&q.dot(&r), &a_sub, rtol); // Full let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Full); let qc: Array2 = conjugate(&q); assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol); assert_close_l2!(&q.dot(&r), &a, rtol); } #[test] fn over_f32() { over::(1e-5); } #[test] fn over_f64() { over::(1e-9); } #[test] fn over_c32() { over::(1e-5); } #[test] fn over_c64() { over::(1e-9); } fn full(rtol: A::Real) { const N: usize = 5; let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); let a: Array2 = random_using((N, N), &mut rng); let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Terminate); let qc: Array2 = conjugate(&q); assert_close_l2!(&qc.dot(&q), &Array::eye(N), rtol; "Check Q^H Q = I"); assert_close_l2!(&q.dot(&r), &a, rtol; "Check A = QR"); } #[test] fn full_f32() { full::(1e-5); } #[test] fn full_f64() { full::(1e-9); } #[test] fn full_c32() { full::(1e-5); } #[test] fn full_c64() { full::(1e-9); } fn half(rtol: A::Real) { const N: usize = 4; let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); let a: Array2 = random_using((N, N / 2), &mut rng); let (q, r) = householder(a.axis_iter(Axis(1)), N, rtol, Strategy::Terminate); let qc: Array2 = conjugate(&q); assert_close_l2!(&qc.dot(&q), &Array::eye(N / 2), rtol; "Check Q^H Q = I"); assert_close_l2!(&q.dot(&r), &a, rtol; "Check A = QR"); } #[test] fn half_f32() { half::(1e-5); } #[test] fn half_f64() { half::(1e-9); } #[test] fn half_c32() { half::(1e-5); } #[test] fn half_c64() { half::(1e-9); }