1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library
2*bf2c3715SXin Li // for linear algebra.
3*bf2c3715SXin Li //
4*bf2c3715SXin Li // Copyright (C) 2016 Gael Guennebaud <[email protected]>
5*bf2c3715SXin Li //
6*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
7*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
8*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9*bf2c3715SXin Li
10*bf2c3715SXin Li #include "main.h"
11*bf2c3715SXin Li #include <Eigen/LU>
12*bf2c3715SXin Li #include <Eigen/Cholesky>
13*bf2c3715SXin Li #include <Eigen/QR>
14*bf2c3715SXin Li
15*bf2c3715SXin Li // This file test inplace decomposition through Ref<>, as supported by Cholesky, LU, and QR decompositions.
16*bf2c3715SXin Li
inplace(bool square=false,bool SPD=false)17*bf2c3715SXin Li template<typename DecType,typename MatrixType> void inplace(bool square = false, bool SPD = false)
18*bf2c3715SXin Li {
19*bf2c3715SXin Li typedef typename MatrixType::Scalar Scalar;
20*bf2c3715SXin Li typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> RhsType;
21*bf2c3715SXin Li typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> ResType;
22*bf2c3715SXin Li
23*bf2c3715SXin Li Index rows = MatrixType::RowsAtCompileTime==Dynamic ? internal::random<Index>(2,EIGEN_TEST_MAX_SIZE/2) : Index(MatrixType::RowsAtCompileTime);
24*bf2c3715SXin Li Index cols = MatrixType::ColsAtCompileTime==Dynamic ? (square?rows:internal::random<Index>(2,rows)) : Index(MatrixType::ColsAtCompileTime);
25*bf2c3715SXin Li
26*bf2c3715SXin Li MatrixType A = MatrixType::Random(rows,cols);
27*bf2c3715SXin Li RhsType b = RhsType::Random(rows);
28*bf2c3715SXin Li ResType x(cols);
29*bf2c3715SXin Li
30*bf2c3715SXin Li if(SPD)
31*bf2c3715SXin Li {
32*bf2c3715SXin Li assert(square);
33*bf2c3715SXin Li A.topRows(cols) = A.topRows(cols).adjoint() * A.topRows(cols);
34*bf2c3715SXin Li A.diagonal().array() += 1e-3;
35*bf2c3715SXin Li }
36*bf2c3715SXin Li
37*bf2c3715SXin Li MatrixType A0 = A;
38*bf2c3715SXin Li MatrixType A1 = A;
39*bf2c3715SXin Li
40*bf2c3715SXin Li DecType dec(A);
41*bf2c3715SXin Li
42*bf2c3715SXin Li // Check that the content of A has been modified
43*bf2c3715SXin Li VERIFY_IS_NOT_APPROX( A, A0 );
44*bf2c3715SXin Li
45*bf2c3715SXin Li // Check that the decomposition is correct:
46*bf2c3715SXin Li if(rows==cols)
47*bf2c3715SXin Li {
48*bf2c3715SXin Li VERIFY_IS_APPROX( A0 * (x = dec.solve(b)), b );
49*bf2c3715SXin Li }
50*bf2c3715SXin Li else
51*bf2c3715SXin Li {
52*bf2c3715SXin Li VERIFY_IS_APPROX( A0.transpose() * A0 * (x = dec.solve(b)), A0.transpose() * b );
53*bf2c3715SXin Li }
54*bf2c3715SXin Li
55*bf2c3715SXin Li // Check that modifying A breaks the current dec:
56*bf2c3715SXin Li A.setRandom();
57*bf2c3715SXin Li if(rows==cols)
58*bf2c3715SXin Li {
59*bf2c3715SXin Li VERIFY_IS_NOT_APPROX( A0 * (x = dec.solve(b)), b );
60*bf2c3715SXin Li }
61*bf2c3715SXin Li else
62*bf2c3715SXin Li {
63*bf2c3715SXin Li VERIFY_IS_NOT_APPROX( A0.transpose() * A0 * (x = dec.solve(b)), A0.transpose() * b );
64*bf2c3715SXin Li }
65*bf2c3715SXin Li
66*bf2c3715SXin Li // Check that calling compute(A1) does not modify A1:
67*bf2c3715SXin Li A = A0;
68*bf2c3715SXin Li dec.compute(A1);
69*bf2c3715SXin Li VERIFY_IS_EQUAL(A0,A1);
70*bf2c3715SXin Li VERIFY_IS_NOT_APPROX( A, A0 );
71*bf2c3715SXin Li if(rows==cols)
72*bf2c3715SXin Li {
73*bf2c3715SXin Li VERIFY_IS_APPROX( A0 * (x = dec.solve(b)), b );
74*bf2c3715SXin Li }
75*bf2c3715SXin Li else
76*bf2c3715SXin Li {
77*bf2c3715SXin Li VERIFY_IS_APPROX( A0.transpose() * A0 * (x = dec.solve(b)), A0.transpose() * b );
78*bf2c3715SXin Li }
79*bf2c3715SXin Li }
80*bf2c3715SXin Li
81*bf2c3715SXin Li
EIGEN_DECLARE_TEST(inplace_decomposition)82*bf2c3715SXin Li EIGEN_DECLARE_TEST(inplace_decomposition)
83*bf2c3715SXin Li {
84*bf2c3715SXin Li EIGEN_UNUSED typedef Matrix<double,4,3> Matrix43d;
85*bf2c3715SXin Li for(int i = 0; i < g_repeat; i++) {
86*bf2c3715SXin Li CALL_SUBTEST_1(( inplace<LLT<Ref<MatrixXd> >, MatrixXd>(true,true) ));
87*bf2c3715SXin Li CALL_SUBTEST_1(( inplace<LLT<Ref<Matrix4d> >, Matrix4d>(true,true) ));
88*bf2c3715SXin Li
89*bf2c3715SXin Li CALL_SUBTEST_2(( inplace<LDLT<Ref<MatrixXd> >, MatrixXd>(true,true) ));
90*bf2c3715SXin Li CALL_SUBTEST_2(( inplace<LDLT<Ref<Matrix4d> >, Matrix4d>(true,true) ));
91*bf2c3715SXin Li
92*bf2c3715SXin Li CALL_SUBTEST_3(( inplace<PartialPivLU<Ref<MatrixXd> >, MatrixXd>(true,false) ));
93*bf2c3715SXin Li CALL_SUBTEST_3(( inplace<PartialPivLU<Ref<Matrix4d> >, Matrix4d>(true,false) ));
94*bf2c3715SXin Li
95*bf2c3715SXin Li CALL_SUBTEST_4(( inplace<FullPivLU<Ref<MatrixXd> >, MatrixXd>(true,false) ));
96*bf2c3715SXin Li CALL_SUBTEST_4(( inplace<FullPivLU<Ref<Matrix4d> >, Matrix4d>(true,false) ));
97*bf2c3715SXin Li
98*bf2c3715SXin Li CALL_SUBTEST_5(( inplace<HouseholderQR<Ref<MatrixXd> >, MatrixXd>(false,false) ));
99*bf2c3715SXin Li CALL_SUBTEST_5(( inplace<HouseholderQR<Ref<Matrix43d> >, Matrix43d>(false,false) ));
100*bf2c3715SXin Li
101*bf2c3715SXin Li CALL_SUBTEST_6(( inplace<ColPivHouseholderQR<Ref<MatrixXd> >, MatrixXd>(false,false) ));
102*bf2c3715SXin Li CALL_SUBTEST_6(( inplace<ColPivHouseholderQR<Ref<Matrix43d> >, Matrix43d>(false,false) ));
103*bf2c3715SXin Li
104*bf2c3715SXin Li CALL_SUBTEST_7(( inplace<FullPivHouseholderQR<Ref<MatrixXd> >, MatrixXd>(false,false) ));
105*bf2c3715SXin Li CALL_SUBTEST_7(( inplace<FullPivHouseholderQR<Ref<Matrix43d> >, Matrix43d>(false,false) ));
106*bf2c3715SXin Li
107*bf2c3715SXin Li CALL_SUBTEST_8(( inplace<CompleteOrthogonalDecomposition<Ref<MatrixXd> >, MatrixXd>(false,false) ));
108*bf2c3715SXin Li CALL_SUBTEST_8(( inplace<CompleteOrthogonalDecomposition<Ref<Matrix43d> >, Matrix43d>(false,false) ));
109*bf2c3715SXin Li }
110*bf2c3715SXin Li }
111