blob: 5cf842d6d2bd83c150b154dc17a8ab6b70d7a695 [file] [log] [blame]
Brian Silverman72890c22015-09-19 14:37:37 -04001// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_NO_ASSERTION_CHECKING
11#define EIGEN_NO_ASSERTION_CHECKING
12#endif
13
Austin Schuh189376f2018-12-20 22:11:15 +110014#define TEST_ENABLE_TEMPORARY_TRACKING
Brian Silverman72890c22015-09-19 14:37:37 -040015
16#include "main.h"
17#include <Eigen/Cholesky>
18#include <Eigen/QR>
19
Austin Schuh189376f2018-12-20 22:11:15 +110020template<typename MatrixType, int UpLo>
21typename MatrixType::RealScalar matrix_l1_norm(const MatrixType& m) {
22 if(m.cols()==0) return typename MatrixType::RealScalar(0);
23 MatrixType symm = m.template selfadjointView<UpLo>();
24 return symm.cwiseAbs().colwise().sum().maxCoeff();
25}
Brian Silverman72890c22015-09-19 14:37:37 -040026
27template<typename MatrixType,template <typename,int> class CholType> void test_chol_update(const MatrixType& symm)
28{
29 typedef typename MatrixType::Scalar Scalar;
30 typedef typename MatrixType::RealScalar RealScalar;
31 typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
32
33 MatrixType symmLo = symm.template triangularView<Lower>();
34 MatrixType symmUp = symm.template triangularView<Upper>();
35 MatrixType symmCpy = symm;
36
37 CholType<MatrixType,Lower> chollo(symmLo);
38 CholType<MatrixType,Upper> cholup(symmUp);
39
40 for (int k=0; k<10; ++k)
41 {
42 VectorType vec = VectorType::Random(symm.rows());
43 RealScalar sigma = internal::random<RealScalar>();
44 symmCpy += sigma * vec * vec.adjoint();
45
46 // we are doing some downdates, so it might be the case that the matrix is not SPD anymore
47 CholType<MatrixType,Lower> chol(symmCpy);
48 if(chol.info()!=Success)
49 break;
50
51 chollo.rankUpdate(vec, sigma);
52 VERIFY_IS_APPROX(symmCpy, chollo.reconstructedMatrix());
53
54 cholup.rankUpdate(vec, sigma);
55 VERIFY_IS_APPROX(symmCpy, cholup.reconstructedMatrix());
56 }
57}
58
59template<typename MatrixType> void cholesky(const MatrixType& m)
60{
Brian Silverman72890c22015-09-19 14:37:37 -040061 /* this test covers the following files:
62 LLT.h LDLT.h
63 */
64 Index rows = m.rows();
65 Index cols = m.cols();
66
67 typedef typename MatrixType::Scalar Scalar;
68 typedef typename NumTraits<Scalar>::Real RealScalar;
69 typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
70 typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
71
72 MatrixType a0 = MatrixType::Random(rows,cols);
73 VectorType vecB = VectorType::Random(rows), vecX(rows);
74 MatrixType matB = MatrixType::Random(rows,cols), matX(rows,cols);
75 SquareMatrixType symm = a0 * a0.adjoint();
76 // let's make sure the matrix is not singular or near singular
77 for (int k=0; k<3; ++k)
78 {
79 MatrixType a1 = MatrixType::Random(rows,cols);
80 symm += a1 * a1.adjoint();
81 }
82
Brian Silverman72890c22015-09-19 14:37:37 -040083 {
84 SquareMatrixType symmUp = symm.template triangularView<Upper>();
85 SquareMatrixType symmLo = symm.template triangularView<Lower>();
Austin Schuh189376f2018-12-20 22:11:15 +110086
Brian Silverman72890c22015-09-19 14:37:37 -040087 LLT<SquareMatrixType,Lower> chollo(symmLo);
88 VERIFY_IS_APPROX(symm, chollo.reconstructedMatrix());
89 vecX = chollo.solve(vecB);
90 VERIFY_IS_APPROX(symm * vecX, vecB);
91 matX = chollo.solve(matB);
92 VERIFY_IS_APPROX(symm * matX, matB);
93
Austin Schuh189376f2018-12-20 22:11:15 +110094 const MatrixType symmLo_inverse = chollo.solve(MatrixType::Identity(rows,cols));
95 RealScalar rcond = (RealScalar(1) / matrix_l1_norm<MatrixType, Lower>(symmLo)) /
96 matrix_l1_norm<MatrixType, Lower>(symmLo_inverse);
97 RealScalar rcond_est = chollo.rcond();
98 // Verify that the estimated condition number is within a factor of 10 of the
99 // truth.
100 VERIFY(rcond_est >= rcond / 10 && rcond_est <= rcond * 10);
101
Brian Silverman72890c22015-09-19 14:37:37 -0400102 // test the upper mode
103 LLT<SquareMatrixType,Upper> cholup(symmUp);
104 VERIFY_IS_APPROX(symm, cholup.reconstructedMatrix());
105 vecX = cholup.solve(vecB);
106 VERIFY_IS_APPROX(symm * vecX, vecB);
107 matX = cholup.solve(matB);
108 VERIFY_IS_APPROX(symm * matX, matB);
109
Austin Schuh189376f2018-12-20 22:11:15 +1100110 // Verify that the estimated condition number is within a factor of 10 of the
111 // truth.
112 const MatrixType symmUp_inverse = cholup.solve(MatrixType::Identity(rows,cols));
113 rcond = (RealScalar(1) / matrix_l1_norm<MatrixType, Upper>(symmUp)) /
114 matrix_l1_norm<MatrixType, Upper>(symmUp_inverse);
115 rcond_est = cholup.rcond();
116 VERIFY(rcond_est >= rcond / 10 && rcond_est <= rcond * 10);
117
118
Brian Silverman72890c22015-09-19 14:37:37 -0400119 MatrixType neg = -symmLo;
120 chollo.compute(neg);
Austin Schuh189376f2018-12-20 22:11:15 +1100121 VERIFY(neg.size()==0 || chollo.info()==NumericalIssue);
Brian Silverman72890c22015-09-19 14:37:37 -0400122
123 VERIFY_IS_APPROX(MatrixType(chollo.matrixL().transpose().conjugate()), MatrixType(chollo.matrixU()));
124 VERIFY_IS_APPROX(MatrixType(chollo.matrixU().transpose().conjugate()), MatrixType(chollo.matrixL()));
125 VERIFY_IS_APPROX(MatrixType(cholup.matrixL().transpose().conjugate()), MatrixType(cholup.matrixU()));
126 VERIFY_IS_APPROX(MatrixType(cholup.matrixU().transpose().conjugate()), MatrixType(cholup.matrixL()));
Austin Schuh189376f2018-12-20 22:11:15 +1100127
Brian Silverman72890c22015-09-19 14:37:37 -0400128 // test some special use cases of SelfCwiseBinaryOp:
129 MatrixType m1 = MatrixType::Random(rows,cols), m2(rows,cols);
130 m2 = m1;
131 m2 += symmLo.template selfadjointView<Lower>().llt().solve(matB);
132 VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
133 m2 = m1;
134 m2 -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
135 VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
136 m2 = m1;
137 m2.noalias() += symmLo.template selfadjointView<Lower>().llt().solve(matB);
138 VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
139 m2 = m1;
140 m2.noalias() -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
141 VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
142 }
143
144 // LDLT
145 {
146 int sign = internal::random<int>()%2 ? 1 : -1;
147
148 if(sign == -1)
149 {
150 symm = -symm; // test a negative matrix
151 }
152
153 SquareMatrixType symmUp = symm.template triangularView<Upper>();
154 SquareMatrixType symmLo = symm.template triangularView<Lower>();
155
156 LDLT<SquareMatrixType,Lower> ldltlo(symmLo);
Austin Schuh189376f2018-12-20 22:11:15 +1100157 VERIFY(ldltlo.info()==Success);
Brian Silverman72890c22015-09-19 14:37:37 -0400158 VERIFY_IS_APPROX(symm, ldltlo.reconstructedMatrix());
159 vecX = ldltlo.solve(vecB);
160 VERIFY_IS_APPROX(symm * vecX, vecB);
161 matX = ldltlo.solve(matB);
162 VERIFY_IS_APPROX(symm * matX, matB);
163
Austin Schuh189376f2018-12-20 22:11:15 +1100164 const MatrixType symmLo_inverse = ldltlo.solve(MatrixType::Identity(rows,cols));
165 RealScalar rcond = (RealScalar(1) / matrix_l1_norm<MatrixType, Lower>(symmLo)) /
166 matrix_l1_norm<MatrixType, Lower>(symmLo_inverse);
167 RealScalar rcond_est = ldltlo.rcond();
168 // Verify that the estimated condition number is within a factor of 10 of the
169 // truth.
170 VERIFY(rcond_est >= rcond / 10 && rcond_est <= rcond * 10);
171
172
Brian Silverman72890c22015-09-19 14:37:37 -0400173 LDLT<SquareMatrixType,Upper> ldltup(symmUp);
Austin Schuh189376f2018-12-20 22:11:15 +1100174 VERIFY(ldltup.info()==Success);
Brian Silverman72890c22015-09-19 14:37:37 -0400175 VERIFY_IS_APPROX(symm, ldltup.reconstructedMatrix());
176 vecX = ldltup.solve(vecB);
177 VERIFY_IS_APPROX(symm * vecX, vecB);
178 matX = ldltup.solve(matB);
179 VERIFY_IS_APPROX(symm * matX, matB);
180
Austin Schuh189376f2018-12-20 22:11:15 +1100181 // Verify that the estimated condition number is within a factor of 10 of the
182 // truth.
183 const MatrixType symmUp_inverse = ldltup.solve(MatrixType::Identity(rows,cols));
184 rcond = (RealScalar(1) / matrix_l1_norm<MatrixType, Upper>(symmUp)) /
185 matrix_l1_norm<MatrixType, Upper>(symmUp_inverse);
186 rcond_est = ldltup.rcond();
187 VERIFY(rcond_est >= rcond / 10 && rcond_est <= rcond * 10);
188
Brian Silverman72890c22015-09-19 14:37:37 -0400189 VERIFY_IS_APPROX(MatrixType(ldltlo.matrixL().transpose().conjugate()), MatrixType(ldltlo.matrixU()));
190 VERIFY_IS_APPROX(MatrixType(ldltlo.matrixU().transpose().conjugate()), MatrixType(ldltlo.matrixL()));
191 VERIFY_IS_APPROX(MatrixType(ldltup.matrixL().transpose().conjugate()), MatrixType(ldltup.matrixU()));
192 VERIFY_IS_APPROX(MatrixType(ldltup.matrixU().transpose().conjugate()), MatrixType(ldltup.matrixL()));
193
194 if(MatrixType::RowsAtCompileTime==Dynamic)
195 {
196 // note : each inplace permutation requires a small temporary vector (mask)
197
198 // check inplace solve
199 matX = matB;
200 VERIFY_EVALUATION_COUNT(matX = ldltlo.solve(matX), 0);
201 VERIFY_IS_APPROX(matX, ldltlo.solve(matB).eval());
202
203
204 matX = matB;
205 VERIFY_EVALUATION_COUNT(matX = ldltup.solve(matX), 0);
206 VERIFY_IS_APPROX(matX, ldltup.solve(matB).eval());
207 }
208
209 // restore
210 if(sign == -1)
211 symm = -symm;
212
213 // check matrices coming from linear constraints with Lagrange multipliers
214 if(rows>=3)
215 {
216 SquareMatrixType A = symm;
Austin Schuh189376f2018-12-20 22:11:15 +1100217 Index c = internal::random<Index>(0,rows-2);
Brian Silverman72890c22015-09-19 14:37:37 -0400218 A.bottomRightCorner(c,c).setZero();
219 // Make sure a solution exists:
220 vecX.setRandom();
221 vecB = A * vecX;
222 vecX.setZero();
223 ldltlo.compute(A);
224 VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
225 vecX = ldltlo.solve(vecB);
226 VERIFY_IS_APPROX(A * vecX, vecB);
227 }
Austin Schuh189376f2018-12-20 22:11:15 +1100228
Brian Silverman72890c22015-09-19 14:37:37 -0400229 // check non-full rank matrices
230 if(rows>=3)
231 {
Austin Schuh189376f2018-12-20 22:11:15 +1100232 Index r = internal::random<Index>(1,rows-1);
Brian Silverman72890c22015-09-19 14:37:37 -0400233 Matrix<Scalar,Dynamic,Dynamic> a = Matrix<Scalar,Dynamic,Dynamic>::Random(rows,r);
234 SquareMatrixType A = a * a.adjoint();
235 // Make sure a solution exists:
236 vecX.setRandom();
237 vecB = A * vecX;
238 vecX.setZero();
239 ldltlo.compute(A);
240 VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
241 vecX = ldltlo.solve(vecB);
242 VERIFY_IS_APPROX(A * vecX, vecB);
243 }
Austin Schuh189376f2018-12-20 22:11:15 +1100244
Brian Silverman72890c22015-09-19 14:37:37 -0400245 // check matrices with a wide spectrum
246 if(rows>=3)
247 {
Austin Schuh189376f2018-12-20 22:11:15 +1100248 using std::pow;
249 using std::sqrt;
Brian Silverman72890c22015-09-19 14:37:37 -0400250 RealScalar s = (std::min)(16,std::numeric_limits<RealScalar>::max_exponent10/8);
251 Matrix<Scalar,Dynamic,Dynamic> a = Matrix<Scalar,Dynamic,Dynamic>::Random(rows,rows);
252 Matrix<RealScalar,Dynamic,1> d = Matrix<RealScalar,Dynamic,1>::Random(rows);
Austin Schuh189376f2018-12-20 22:11:15 +1100253 for(Index k=0; k<rows; ++k)
254 d(k) = d(k)*pow(RealScalar(10),internal::random<RealScalar>(-s,s));
Brian Silverman72890c22015-09-19 14:37:37 -0400255 SquareMatrixType A = a * d.asDiagonal() * a.adjoint();
256 // Make sure a solution exists:
257 vecX.setRandom();
258 vecB = A * vecX;
259 vecX.setZero();
260 ldltlo.compute(A);
261 VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
262 vecX = ldltlo.solve(vecB);
Austin Schuh189376f2018-12-20 22:11:15 +1100263
264 if(ldltlo.vectorD().real().cwiseAbs().minCoeff()>RealScalar(0))
265 {
266 VERIFY_IS_APPROX(A * vecX,vecB);
267 }
268 else
269 {
270 RealScalar large_tol = sqrt(test_precision<RealScalar>());
271 VERIFY((A * vecX).isApprox(vecB, large_tol));
272
273 ++g_test_level;
274 VERIFY_IS_APPROX(A * vecX,vecB);
275 --g_test_level;
276 }
Brian Silverman72890c22015-09-19 14:37:37 -0400277 }
278 }
279
280 // update/downdate
281 CALL_SUBTEST(( test_chol_update<SquareMatrixType,LLT>(symm) ));
282 CALL_SUBTEST(( test_chol_update<SquareMatrixType,LDLT>(symm) ));
283}
284
285template<typename MatrixType> void cholesky_cplx(const MatrixType& m)
286{
287 // classic test
288 cholesky(m);
289
290 // test mixing real/scalar types
291
Brian Silverman72890c22015-09-19 14:37:37 -0400292 Index rows = m.rows();
293 Index cols = m.cols();
294
295 typedef typename MatrixType::Scalar Scalar;
296 typedef typename NumTraits<Scalar>::Real RealScalar;
297 typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> RealMatrixType;
298 typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
299
300 RealMatrixType a0 = RealMatrixType::Random(rows,cols);
301 VectorType vecB = VectorType::Random(rows), vecX(rows);
302 MatrixType matB = MatrixType::Random(rows,cols), matX(rows,cols);
303 RealMatrixType symm = a0 * a0.adjoint();
304 // let's make sure the matrix is not singular or near singular
305 for (int k=0; k<3; ++k)
306 {
307 RealMatrixType a1 = RealMatrixType::Random(rows,cols);
308 symm += a1 * a1.adjoint();
309 }
310
311 {
312 RealMatrixType symmLo = symm.template triangularView<Lower>();
313
314 LLT<RealMatrixType,Lower> chollo(symmLo);
315 VERIFY_IS_APPROX(symm, chollo.reconstructedMatrix());
316 vecX = chollo.solve(vecB);
317 VERIFY_IS_APPROX(symm * vecX, vecB);
318// matX = chollo.solve(matB);
319// VERIFY_IS_APPROX(symm * matX, matB);
320 }
321
322 // LDLT
323 {
324 int sign = internal::random<int>()%2 ? 1 : -1;
325
326 if(sign == -1)
327 {
328 symm = -symm; // test a negative matrix
329 }
330
331 RealMatrixType symmLo = symm.template triangularView<Lower>();
332
333 LDLT<RealMatrixType,Lower> ldltlo(symmLo);
Austin Schuh189376f2018-12-20 22:11:15 +1100334 VERIFY(ldltlo.info()==Success);
Brian Silverman72890c22015-09-19 14:37:37 -0400335 VERIFY_IS_APPROX(symm, ldltlo.reconstructedMatrix());
336 vecX = ldltlo.solve(vecB);
337 VERIFY_IS_APPROX(symm * vecX, vecB);
338// matX = ldltlo.solve(matB);
339// VERIFY_IS_APPROX(symm * matX, matB);
340 }
341}
342
343// regression test for bug 241
344template<typename MatrixType> void cholesky_bug241(const MatrixType& m)
345{
346 eigen_assert(m.rows() == 2 && m.cols() == 2);
347
348 typedef typename MatrixType::Scalar Scalar;
349 typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
350
351 MatrixType matA;
352 matA << 1, 1, 1, 1;
353 VectorType vecB;
354 vecB << 1, 1;
355 VectorType vecX = matA.ldlt().solve(vecB);
356 VERIFY_IS_APPROX(matA * vecX, vecB);
357}
358
359// LDLT is not guaranteed to work for indefinite matrices, but happens to work fine if matrix is diagonal.
Austin Schuh189376f2018-12-20 22:11:15 +1100360// This test checks that LDLT reports correctly that matrix is indefinite.
Brian Silverman72890c22015-09-19 14:37:37 -0400361// See http://forum.kde.org/viewtopic.php?f=74&t=106942 and bug 736
362template<typename MatrixType> void cholesky_definiteness(const MatrixType& m)
363{
364 eigen_assert(m.rows() == 2 && m.cols() == 2);
365 MatrixType mat;
366 LDLT<MatrixType> ldlt(2);
Austin Schuh189376f2018-12-20 22:11:15 +1100367
Brian Silverman72890c22015-09-19 14:37:37 -0400368 {
369 mat << 1, 0, 0, -1;
370 ldlt.compute(mat);
Austin Schuh189376f2018-12-20 22:11:15 +1100371 VERIFY(ldlt.info()==Success);
Brian Silverman72890c22015-09-19 14:37:37 -0400372 VERIFY(!ldlt.isNegative());
373 VERIFY(!ldlt.isPositive());
Austin Schuh189376f2018-12-20 22:11:15 +1100374 VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
Brian Silverman72890c22015-09-19 14:37:37 -0400375 }
376 {
377 mat << 1, 2, 2, 1;
378 ldlt.compute(mat);
Austin Schuh189376f2018-12-20 22:11:15 +1100379 VERIFY(ldlt.info()==Success);
Brian Silverman72890c22015-09-19 14:37:37 -0400380 VERIFY(!ldlt.isNegative());
381 VERIFY(!ldlt.isPositive());
Austin Schuh189376f2018-12-20 22:11:15 +1100382 VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
Brian Silverman72890c22015-09-19 14:37:37 -0400383 }
384 {
385 mat << 0, 0, 0, 0;
386 ldlt.compute(mat);
Austin Schuh189376f2018-12-20 22:11:15 +1100387 VERIFY(ldlt.info()==Success);
Brian Silverman72890c22015-09-19 14:37:37 -0400388 VERIFY(ldlt.isNegative());
389 VERIFY(ldlt.isPositive());
Austin Schuh189376f2018-12-20 22:11:15 +1100390 VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
Brian Silverman72890c22015-09-19 14:37:37 -0400391 }
392 {
393 mat << 0, 0, 0, 1;
394 ldlt.compute(mat);
Austin Schuh189376f2018-12-20 22:11:15 +1100395 VERIFY(ldlt.info()==Success);
Brian Silverman72890c22015-09-19 14:37:37 -0400396 VERIFY(!ldlt.isNegative());
397 VERIFY(ldlt.isPositive());
Austin Schuh189376f2018-12-20 22:11:15 +1100398 VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
Brian Silverman72890c22015-09-19 14:37:37 -0400399 }
400 {
401 mat << -1, 0, 0, 0;
402 ldlt.compute(mat);
Austin Schuh189376f2018-12-20 22:11:15 +1100403 VERIFY(ldlt.info()==Success);
Brian Silverman72890c22015-09-19 14:37:37 -0400404 VERIFY(ldlt.isNegative());
405 VERIFY(!ldlt.isPositive());
Austin Schuh189376f2018-12-20 22:11:15 +1100406 VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
407 }
408}
409
410template<typename>
411void cholesky_faillure_cases()
412{
413 MatrixXd mat;
414 LDLT<MatrixXd> ldlt;
415
416 {
417 mat.resize(2,2);
418 mat << 0, 1, 1, 0;
419 ldlt.compute(mat);
420 VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
421 VERIFY(ldlt.info()==NumericalIssue);
422 }
423#if (!EIGEN_ARCH_i386) || defined(EIGEN_VECTORIZE_SSE2)
424 {
425 mat.resize(3,3);
426 mat << -1, -3, 3,
427 -3, -8.9999999999999999999, 1,
428 3, 1, 0;
429 ldlt.compute(mat);
430 VERIFY(ldlt.info()==NumericalIssue);
431 VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
432 }
433#endif
434 {
435 mat.resize(3,3);
436 mat << 1, 2, 3,
437 2, 4, 1,
438 3, 1, 0;
439 ldlt.compute(mat);
440 VERIFY(ldlt.info()==NumericalIssue);
441 VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
442 }
443
444 {
445 mat.resize(8,8);
446 mat << 0.1, 0, -0.1, 0, 0, 0, 1, 0,
447 0, 4.24667, 0, 2.00333, 0, 0, 0, 0,
448 -0.1, 0, 0.2, 0, -0.1, 0, 0, 0,
449 0, 2.00333, 0, 8.49333, 0, 2.00333, 0, 0,
450 0, 0, -0.1, 0, 0.1, 0, 0, 1,
451 0, 0, 0, 2.00333, 0, 4.24667, 0, 0,
452 1, 0, 0, 0, 0, 0, 0, 0,
453 0, 0, 0, 0, 1, 0, 0, 0;
454 ldlt.compute(mat);
455 VERIFY(ldlt.info()==NumericalIssue);
456 VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
457 }
458
459 // bug 1479
460 {
461 mat.resize(4,4);
462 mat << 1, 2, 0, 1,
463 2, 4, 0, 2,
464 0, 0, 0, 1,
465 1, 2, 1, 1;
466 ldlt.compute(mat);
467 VERIFY(ldlt.info()==NumericalIssue);
468 VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
Brian Silverman72890c22015-09-19 14:37:37 -0400469 }
470}
471
472template<typename MatrixType> void cholesky_verify_assert()
473{
474 MatrixType tmp;
475
476 LLT<MatrixType> llt;
477 VERIFY_RAISES_ASSERT(llt.matrixL())
478 VERIFY_RAISES_ASSERT(llt.matrixU())
479 VERIFY_RAISES_ASSERT(llt.solve(tmp))
480 VERIFY_RAISES_ASSERT(llt.solveInPlace(&tmp))
481
482 LDLT<MatrixType> ldlt;
483 VERIFY_RAISES_ASSERT(ldlt.matrixL())
484 VERIFY_RAISES_ASSERT(ldlt.permutationP())
485 VERIFY_RAISES_ASSERT(ldlt.vectorD())
486 VERIFY_RAISES_ASSERT(ldlt.isPositive())
487 VERIFY_RAISES_ASSERT(ldlt.isNegative())
488 VERIFY_RAISES_ASSERT(ldlt.solve(tmp))
489 VERIFY_RAISES_ASSERT(ldlt.solveInPlace(&tmp))
490}
491
492void test_cholesky()
493{
494 int s = 0;
495 for(int i = 0; i < g_repeat; i++) {
496 CALL_SUBTEST_1( cholesky(Matrix<double,1,1>()) );
497 CALL_SUBTEST_3( cholesky(Matrix2d()) );
498 CALL_SUBTEST_3( cholesky_bug241(Matrix2d()) );
499 CALL_SUBTEST_3( cholesky_definiteness(Matrix2d()) );
500 CALL_SUBTEST_4( cholesky(Matrix3f()) );
501 CALL_SUBTEST_5( cholesky(Matrix4d()) );
Austin Schuh189376f2018-12-20 22:11:15 +1100502
Brian Silverman72890c22015-09-19 14:37:37 -0400503 s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
504 CALL_SUBTEST_2( cholesky(MatrixXd(s,s)) );
Austin Schuh189376f2018-12-20 22:11:15 +1100505 TEST_SET_BUT_UNUSED_VARIABLE(s)
506
Brian Silverman72890c22015-09-19 14:37:37 -0400507 s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
508 CALL_SUBTEST_6( cholesky_cplx(MatrixXcd(s,s)) );
Austin Schuh189376f2018-12-20 22:11:15 +1100509 TEST_SET_BUT_UNUSED_VARIABLE(s)
Brian Silverman72890c22015-09-19 14:37:37 -0400510 }
Austin Schuh189376f2018-12-20 22:11:15 +1100511 // empty matrix, regression test for Bug 785:
512 CALL_SUBTEST_2( cholesky(MatrixXd(0,0)) );
513
514 // This does not work yet:
515 // CALL_SUBTEST_2( cholesky(Matrix<double,0,0>()) );
Brian Silverman72890c22015-09-19 14:37:37 -0400516
517 CALL_SUBTEST_4( cholesky_verify_assert<Matrix3f>() );
518 CALL_SUBTEST_7( cholesky_verify_assert<Matrix3d>() );
519 CALL_SUBTEST_8( cholesky_verify_assert<MatrixXf>() );
520 CALL_SUBTEST_2( cholesky_verify_assert<MatrixXd>() );
521
522 // Test problem size constructors
523 CALL_SUBTEST_9( LLT<MatrixXf>(10) );
524 CALL_SUBTEST_9( LDLT<MatrixXf>(10) );
Austin Schuh189376f2018-12-20 22:11:15 +1100525
526 CALL_SUBTEST_2( cholesky_faillure_cases<void>() );
527
Brian Silverman72890c22015-09-19 14:37:37 -0400528 TEST_SET_BUT_UNUSED_VARIABLE(nb_temporaries)
529}