use ndarray::*; use ndarray_linalg::*; fn test_inv_random(n: usize, set_f: bool, rtol: A::Real) where A: Scalar + Lapack, { let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); let a: Array2 = random_using([n; 2].set_f(set_f), &mut rng); let identity = Array2::eye(n); assert_close_l2!(&a.inv().unwrap().dot(&a), &identity, rtol); assert_close_l2!( &a.factorize().unwrap().inv().unwrap().dot(&a), &identity, rtol ); assert_close_l2!( &a.clone().factorize_into().unwrap().inv().unwrap().dot(&a), &identity, rtol ); } fn test_inv_into_random(n: usize, set_f: bool, rtol: A::Real) where A: Scalar + Lapack, { let mut rng = rand_pcg::Mcg128Xsl64::new(0xcafef00dd15ea5e5); let a: Array2 = random_using([n; 2].set_f(set_f), &mut rng); let identity = Array2::eye(n); assert_close_l2!(&a.clone().inv_into().unwrap().dot(&a), &identity, rtol); assert_close_l2!( &a.factorize().unwrap().inv_into().unwrap().dot(&a), &identity, rtol ); assert_close_l2!( &a.clone() .factorize_into() .unwrap() .inv_into() .unwrap() .dot(&a), &identity, rtol ); } #[test] fn inv_empty() { test_inv_random::(0, false, 0.); test_inv_random::(0, false, 0.); test_inv_random::(0, false, 0.); test_inv_random::(0, false, 0.); } #[test] fn inv_random_float() { for n in 1..=8 { for &set_f in &[false, true] { test_inv_random::(n, set_f, 1e-3); test_inv_random::(n, set_f, 1e-9); } } } #[test] fn inv_random_complex() { for n in 1..=8 { for &set_f in &[false, true] { test_inv_random::(n, set_f, 1e-3); test_inv_random::(n, set_f, 1e-9); } } } #[test] fn inv_into_empty() { test_inv_into_random::(0, false, 0.); test_inv_into_random::(0, false, 0.); test_inv_into_random::(0, false, 0.); test_inv_into_random::(0, false, 0.); } #[test] fn inv_into_random_float() { for n in 1..=8 { for &set_f in &[false, true] { test_inv_into_random::(n, set_f, 1e-3); test_inv_into_random::(n, set_f, 1e-9); } } } #[test] fn inv_into_random_complex() { for n in 1..=8 { for &set_f in &[false, true] { test_inv_into_random::(n, set_f, 1e-3); test_inv_into_random::(n, set_f, 1e-9); } } } #[test] #[should_panic] fn inv_error() { // do not have inverse let a = Array::::zeros(9).into_shape((3, 3)).unwrap(); let a_inv = a.inv().unwrap(); println!("{:?}", a_inv); } #[test] fn inv_2x2() { // Related to issue #123 where this problem led to a wrongly computed inverse when using the // `openblas` backend. let a: Array2 = array!([1.0, 2.0], [3.0, 4.0]); let a_inv = a.inv().unwrap(); assert_close_l2!(&a_inv, &array!([-2.0, 1.0], [1.5, -0.5]), 1e-7); }