faer/linalg/qr/no_pivoting/
inverse.rs1use crate::assert;
2use crate::internal_prelude::*;
3
4pub fn inverse_scratch<T: ComplexField>(dim: usize, blocksize: usize, par: Par) -> StackReq {
5 _ = par;
6 linalg::householder::apply_block_householder_sequence_transpose_on_the_right_in_place_scratch::<T>(dim, blocksize, dim)
7}
8
9#[track_caller]
10pub fn inverse<T: ComplexField>(
11 out: MatMut<'_, T>,
12 Q_basis: MatRef<'_, T>,
13 Q_coeff: MatRef<'_, T>,
14 R: MatRef<'_, T>,
15 par: Par,
16 stack: &mut MemStack,
17) {
18 let n = Q_basis.ncols();
22 let blocksize = Q_coeff.nrows();
23 assert!(all(
24 blocksize > 0,
25 Q_basis.nrows() == n,
26 Q_basis.ncols() == n,
27 Q_coeff.ncols() == n,
28 R.nrows() == n,
29 R.ncols() == n,
30 out.nrows() == n,
31 out.ncols() == n,
32 ));
33
34 let mut out = out;
35 out.fill(zero());
36 linalg::triangular_inverse::invert_upper_triangular(out.rb_mut(), R, par);
37
38 linalg::householder::apply_block_householder_sequence_transpose_on_the_right_in_place_with_conj(
39 Q_basis,
40 Q_coeff,
41 Conj::Yes,
42 out.rb_mut(),
43 par,
44 stack,
45 );
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use crate::assert;
52 use crate::stats::prelude::*;
53 use crate::utils::approx::*;
54 use dyn_stack::MemBuffer;
55 use linalg::qr::no_pivoting::*;
56
57 #[test]
58 fn test_inverse() {
59 let rng = &mut StdRng::seed_from_u64(0);
60 let n = 50;
61 let A = CwiseMatDistribution {
62 nrows: n,
63 ncols: n,
64 dist: ComplexDistribution::new(StandardNormal, StandardNormal),
65 }
66 .rand::<Mat<c64>>(rng);
67
68 let mut QR = A.to_owned();
69 let mut Q_coeff = Mat::zeros(4, n);
70
71 factor::qr_in_place(
72 QR.as_mut(),
73 Q_coeff.as_mut(),
74 Par::Seq,
75 MemStack::new(&mut { MemBuffer::new(factor::qr_in_place_scratch::<c64>(n, n, 4, Par::Seq, default())) }),
76 default(),
77 );
78
79 let approx_eq = CwiseMat(ApproxEq::eps() * (n as f64));
80
81 let mut A_inv = Mat::zeros(n, n);
82 inverse::inverse(
83 A_inv.as_mut(),
84 QR.as_ref(),
85 Q_coeff.as_ref(),
86 QR.as_ref(),
87 Par::Seq,
88 MemStack::new(&mut MemBuffer::new(inverse::inverse_scratch::<c64>(n, 4, Par::Seq))),
89 );
90
91 assert!(A_inv * A ~ Mat::identity(n, n));
92 }
93}