faer/linalg/cholesky/bunch_kaufman/
mod.rs1#![allow(missing_docs)]
6
7pub mod factor;
8pub mod solve;
9
10pub mod inverse;
11pub mod reconstruct;
12
13#[cfg(test)]
14mod tests {
15 use super::factor::PivotingStrategy;
16 use super::*;
17 use crate::internal_prelude::*;
18 use crate::stats::prelude::*;
19 use crate::{assert, c64};
20 use dyn_stack::MemBuffer;
21 use factor::LbltParams;
22 use std::vec;
23
24 #[test]
25 fn test_real() {
26 let rng = &mut StdRng::seed_from_u64(0);
27
28 for n in [3, 6, 19, 100, 421] {
29 let a = CwiseMatDistribution {
30 nrows: n,
31 ncols: n,
32 dist: StandardNormal,
33 }
34 .rand::<Mat<f64>>(rng);
35
36 let a = &a + a.adjoint();
37 let rhs = CwiseMatDistribution {
38 nrows: n,
39 ncols: 2,
40 dist: StandardNormal,
41 }
42 .rand::<Mat<f64>>(rng);
43
44 let mut ldl = a.clone();
45 let mut subdiag = Diag::<f64>::zeros(n);
46
47 let mut perm = vec![0usize; n];
48 let mut perm_inv = vec![0; n];
49
50 let params = Default::default();
51 let mut mem = MemBuffer::new(factor::cholesky_in_place_scratch::<usize, f64>(n, Par::Seq, params));
52 let (_, perm) = factor::cholesky_in_place(
53 ldl.as_mut(),
54 subdiag.as_mut(),
55 &mut perm,
56 &mut perm_inv,
57 Par::Seq,
58 MemStack::new(&mut mem),
59 params,
60 );
61
62 let mut mem = MemBuffer::new(solve::solve_in_place_scratch::<usize, f64>(n, rhs.ncols(), Par::Seq));
63 let mut x = rhs.clone();
64 solve::solve_in_place_with_conj(
65 ldl.as_ref(),
66 ldl.diagonal(),
67 subdiag.as_ref(),
68 Conj::No,
69 perm.rb(),
70 x.as_mut(),
71 Par::Seq,
72 MemStack::new(&mut mem),
73 );
74
75 let err = &a * &x - &rhs;
76 let mut max = 0.0;
77 zip!(err.as_ref()).for_each(|unzip!(err)| {
78 let err = err.abs();
79 if err > max {
80 max = err
81 }
82 });
83 assert!(max < 1e-9);
84 }
85 }
86
87 #[test]
88 fn test_cplx() {
89 let rng = &mut StdRng::seed_from_u64(0);
90
91 for n in [2, 3, 6, 19, 100, 421] {
92 let distribution = ComplexDistribution::new(StandardNormal, StandardNormal);
93 let a = CwiseMatDistribution {
94 nrows: n,
95 ncols: n,
96 dist: distribution,
97 }
98 .rand::<Mat<c64>>(rng);
99
100 let A = &a + a.adjoint();
101 let rhs = CwiseMatDistribution {
102 nrows: n,
103 ncols: 2,
104 dist: distribution,
105 }
106 .rand::<Mat<c64>>(rng);
107
108 for pivoting in [
109 PivotingStrategy::Partial,
110 PivotingStrategy::PartialDiag,
111 PivotingStrategy::Rook,
112 PivotingStrategy::RookDiag,
113 PivotingStrategy::Full,
114 ] {
115 let mut ldl = A.clone();
116 let mut subdiag = Diag::<c64>::zeros(n);
117
118 let mut perm = vec![0usize; n];
119 let mut perm_inv = vec![0; n];
120
121 let params = LbltParams {
122 pivoting,
123 blocksize: 4,
124 ..auto!(c64)
125 };
126 let mut mem = MemBuffer::new(factor::cholesky_in_place_scratch::<usize, c64>(n, Par::Seq, params.into()));
127 let (_, perm) = factor::cholesky_in_place(
128 ldl.as_mut(),
129 subdiag.as_mut(),
130 &mut perm,
131 &mut perm_inv,
132 Par::Seq,
133 MemStack::new(&mut mem),
134 params.into(),
135 );
136
137 let mut x = rhs.clone();
138 let mut mem = MemBuffer::new(solve::solve_in_place_scratch::<usize, c64>(n, rhs.ncols(), Par::Seq));
139 solve::solve_in_place_with_conj(
140 ldl.as_ref(),
141 ldl.diagonal(),
142 subdiag.as_ref(),
143 Conj::Yes,
144 perm.rb(),
145 x.as_mut(),
146 Par::Seq,
147 MemStack::new(&mut mem),
148 );
149
150 let err = A.conjugate() * &x - &rhs;
151 let mut max = 0.0;
152 zip!(err.as_ref()).for_each(|unzip!(err)| {
153 let err = abs(err);
154 if err > max {
155 max = err
156 }
157 });
158 for i in 0..n {
159 assert!(ldl[(i, i)].im == 0.0);
160 }
161 assert!(max < 1e-9);
162 }
163 }
164 }
165}