eigensolver_selfadjoint.cpp File Reference
#include "main.h"
#include "svd_fill.h"
#include <limits>
#include <Eigen/Eigenvalues>
#include <Eigen/SparseCore>

Functions

template<typename MatrixType >
void selfadjointeigensolver_essential_check (const MatrixType &m)
 
template<typename MatrixType >
void selfadjointeigensolver (const MatrixType &m)
 
template<int >
void bug_854 ()
 
template<int >
void bug_1014 ()
 
template<int >
void bug_1225 ()
 
template<int >
void bug_1204 ()
 
 EIGEN_DECLARE_TEST (eigensolver_selfadjoint)
 

Function Documentation

◆ bug_1014()

template<int >
void bug_1014 ( )
201  {
202  Matrix3d m;
203  m << 0.11111111111111114658, 0, 0, 0, 0.11111111111111109107, 0, 0, 0, 0.11111111111111107719;
205 }
void selfadjointeigensolver_essential_check(const MatrixType &m)
Definition: eigensolver_selfadjoint.cpp:18
int * m
Definition: level2_cplx_impl.h:294

References m, and selfadjointeigensolver_essential_check().

◆ bug_1204()

template<int >
void bug_1204 ( )
219  {
220  SparseMatrix<double> A(2, 2);
221  A.setIdentity();
223 }
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:47
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
Computes eigenvalues and eigenvectors of selfadjoint matrices.
Definition: SelfAdjointEigenSolver.h:82

◆ bug_1225()

template<int >
void bug_1225 ( )
208  {
209  Matrix3d m1, m2;
210  m1.setRandom();
211  m1 = m1 * m1.transpose();
212  m2 = m1.triangularView<Upper>();
214  SelfAdjointEigenSolver<Matrix3d> eig2(m2.selfadjointView<Upper>());
215  VERIFY_IS_APPROX(eig1.eigenvalues(), eig2.eigenvalues());
216 }
Matrix3d m1
Definition: IOFormat.cpp:2
MatrixType m2(n_dims)
@ Upper
Definition: Constants.h:213
#define VERIFY_IS_APPROX(a, b)
Definition: integer_types.cpp:13

References Eigen::SelfAdjointEigenSolver< MatrixType_ >::eigenvalues(), m1, m2(), Eigen::Upper, and VERIFY_IS_APPROX.

◆ bug_854()

template<int >
void bug_854 ( )
194  {
195  Matrix3d m;
196  m << 850.961, 51.966, 0, 51.966, 254.841, 0, 0, 0, 0;
198 }

References m, and selfadjointeigensolver_essential_check().

◆ EIGEN_DECLARE_TEST()

EIGEN_DECLARE_TEST ( eigensolver_selfadjoint  )
225  {
226  int s = 0;
227  for (int i = 0; i < g_repeat; i++) {
228  // trivial test for 1x1 matrices:
231  CALL_SUBTEST_1(selfadjointeigensolver(Matrix<std::complex<double>, 1, 1>()));
232 
233  // very important to test 3x3 and 2x2 matrices since we provide special paths for them
242 
243  s = internal::random<int>(1, EIGEN_TEST_MAX_SIZE / 4);
247  CALL_SUBTEST_9(selfadjointeigensolver(Matrix<std::complex<double>, Dynamic, Dynamic, RowMajor>(s, s)));
249 
250  // some trivial but implementation-wise tricky cases
251  CALL_SUBTEST_4(selfadjointeigensolver(MatrixXd(1, 1)));
252  CALL_SUBTEST_4(selfadjointeigensolver(MatrixXd(2, 2)));
253  CALL_SUBTEST_5(selfadjointeigensolver(MatrixXcd(1, 1)));
254  CALL_SUBTEST_5(selfadjointeigensolver(MatrixXcd(2, 2)));
257  }
258 
259  CALL_SUBTEST_13(bug_854<0>());
260  CALL_SUBTEST_13(bug_1014<0>());
261  CALL_SUBTEST_13(bug_1204<0>());
262  CALL_SUBTEST_13(bug_1225<0>());
263 
264  // Test problem size constructors
265  s = internal::random<int>(1, EIGEN_TEST_MAX_SIZE / 4);
268 
270 }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
#define EIGEN_TEST_MAX_SIZE
Definition: boostmultiprec.cpp:16
Tridiagonal decomposition of a selfadjoint matrix.
Definition: Tridiagonalization.h:66
void selfadjointeigensolver(const MatrixType &m)
Definition: eigensolver_selfadjoint.cpp:65
@ RowMajor
Definition: Constants.h:320
RealScalar s
Definition: level1_cplx_impl.h:130
#define TEST_SET_BUT_UNUSED_VARIABLE(X)
Definition: main.h:139
static int g_repeat
Definition: main.h:191
const int Dynamic
Definition: Constants.h:25
#define CALL_SUBTEST_6(FUNC)
Definition: split_test_helper.h:34
#define CALL_SUBTEST_3(FUNC)
Definition: split_test_helper.h:16
#define CALL_SUBTEST_1(FUNC)
Definition: split_test_helper.h:4
#define CALL_SUBTEST_13(FUNC)
Definition: split_test_helper.h:76
#define CALL_SUBTEST_8(FUNC)
Definition: split_test_helper.h:46
#define CALL_SUBTEST_5(FUNC)
Definition: split_test_helper.h:28
#define CALL_SUBTEST_12(FUNC)
Definition: split_test_helper.h:70
#define CALL_SUBTEST_2(FUNC)
Definition: split_test_helper.h:10
#define CALL_SUBTEST_7(FUNC)
Definition: split_test_helper.h:40
#define CALL_SUBTEST_4(FUNC)
Definition: split_test_helper.h:22
#define CALL_SUBTEST_9(FUNC)
Definition: split_test_helper.h:52

References CALL_SUBTEST_1, CALL_SUBTEST_12, CALL_SUBTEST_13, CALL_SUBTEST_2, CALL_SUBTEST_3, CALL_SUBTEST_4, CALL_SUBTEST_5, CALL_SUBTEST_6, CALL_SUBTEST_7, CALL_SUBTEST_8, CALL_SUBTEST_9, Eigen::Dynamic, EIGEN_TEST_MAX_SIZE, Eigen::g_repeat, i, Eigen::RowMajor, s, selfadjointeigensolver(), and TEST_SET_BUT_UNUSED_VARIABLE.

◆ selfadjointeigensolver()

template<typename MatrixType >
void selfadjointeigensolver ( const MatrixType m)
65  {
66  /* this test covers the following files:
67  EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h)
68  */
69  Index rows = m.rows();
70  Index cols = m.cols();
71 
72  typedef typename MatrixType::Scalar Scalar;
73  typedef typename NumTraits<Scalar>::Real RealScalar;
74 
75  RealScalar largerEps = 10 * test_precision<RealScalar>();
76 
77  MatrixType a = MatrixType::Random(rows, cols);
78  MatrixType a1 = MatrixType::Random(rows, cols);
79  MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
80  MatrixType symmC = symmA;
81 
82  svd_fill_random(symmA, Symmetric);
83 
84  symmA.template triangularView<StrictlyUpper>().setZero();
85  symmC.template triangularView<StrictlyUpper>().setZero();
86 
87  MatrixType b = MatrixType::Random(rows, cols);
88  MatrixType b1 = MatrixType::Random(rows, cols);
89  MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
90  symmB.template triangularView<StrictlyUpper>().setZero();
91 
93 
95  // generalized eigen pb
96  GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmC, symmB);
97 
98  SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false);
99  VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success);
100  VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues());
101 
102  // generalized eigen problem Ax = lBx
103  eiSymmGen.compute(symmC, symmB, Ax_lBx);
104  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
105  VERIFY((symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())
106  .isApprox(symmB.template selfadjointView<Lower>() *
107  (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()),
108  largerEps));
109 
110  // generalized eigen problem BAx = lx
111  eiSymmGen.compute(symmC, symmB, BAx_lx);
112  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
113  VERIFY(
114  (symmB.template selfadjointView<Lower>() * (symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()))
115  .isApprox((eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
116 
117  // generalized eigen problem ABx = lx
118  eiSymmGen.compute(symmC, symmB, ABx_lx);
119  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
120  VERIFY(
121  (symmC.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()))
122  .isApprox((eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
123 
124  eiSymm.compute(symmC);
125  MatrixType sqrtSymmA = eiSymm.operatorSqrt();
126  VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), sqrtSymmA * sqrtSymmA);
127  VERIFY_IS_APPROX(sqrtSymmA, symmC.template selfadjointView<Lower>() * eiSymm.operatorInverseSqrt());
128 
129  MatrixType id = MatrixType::Identity(rows, cols);
130  VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1));
131 
132  SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized;
133  VERIFY_RAISES_ASSERT(eiSymmUninitialized.info());
134  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues());
135  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
136  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
137  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());
138 
139  eiSymmUninitialized.compute(symmA, false);
140  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
141  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
142  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());
143 
144  // test Tridiagonalization's methods
145  Tridiagonalization<MatrixType> tridiag(symmC);
146  VERIFY_IS_APPROX(tridiag.diagonal(), tridiag.matrixT().diagonal());
147  VERIFY_IS_APPROX(tridiag.subDiagonal(), tridiag.matrixT().template diagonal<-1>());
148  Matrix<RealScalar, Dynamic, Dynamic> T = tridiag.matrixT();
149  if (rows > 1 && cols > 1) {
150  // FIXME check that upper and lower part are 0:
151  // VERIFY(T.topRightCorner(rows-2, cols-2).template triangularView<Upper>().isZero());
152  }
153  VERIFY_IS_APPROX(tridiag.diagonal(), T.diagonal());
154  VERIFY_IS_APPROX(tridiag.subDiagonal(), T.template diagonal<1>());
155  VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()),
156  tridiag.matrixQ() * tridiag.matrixT().eval() * MatrixType(tridiag.matrixQ()).adjoint());
157  VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()),
158  tridiag.matrixQ() * tridiag.matrixT() * tridiag.matrixQ().adjoint());
159 
160  // Test computation of eigenvalues from tridiagonal matrix
161  if (rows > 1) {
163  eiSymmTridiag.computeFromTridiagonal(tridiag.matrixT().diagonal(), tridiag.matrixT().diagonal(-1),
165  VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmTridiag.eigenvalues());
166  VERIFY_IS_APPROX(tridiag.matrixT(), eiSymmTridiag.eigenvectors().real() * eiSymmTridiag.eigenvalues().asDiagonal() *
167  eiSymmTridiag.eigenvectors().real().transpose());
168  }
169 
170  if (rows > 1 && rows < 20) {
171  // Test matrix with NaN
172  symmC(0, 0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
173  SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmC);
174  VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence);
175  }
176 
177  // regression test for bug 1098
178  {
179  SelfAdjointEigenSolver<MatrixType> eig(a.adjoint() * a);
180  eig.compute(a.adjoint() * a);
181  }
182 
183  // regression test for bug 478
184  {
185  a.setZero();
187  VERIFY_IS_EQUAL(ei3.info(), Success);
188  VERIFY_IS_MUCH_SMALLER_THAN(ei3.eigenvalues().norm(), RealScalar(1));
189  VERIFY((ei3.eigenvectors().transpose() * ei3.eigenvectors().transpose()).eval().isIdentity());
190  }
191 }
int rows
Definition: Tutorial_commainit_02.cpp:1
int cols
Definition: Tutorial_commainit_02.cpp:1
Scalar * b
Definition: benchVecAdd.cpp:17
SCALAR Scalar
Definition: bench_gemm.cpp:45
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:46
MatrixXf MatrixType
Definition: benchmark-blocking-sizes.cpp:52
Computes eigenvalues and eigenvectors of the generalized selfadjoint eigen problem.
Definition: GeneralizedSelfAdjointEigenSolver.h:51
EIGEN_DEVICE_FUNC ComputationInfo info() const
Reports whether previous computation was successful.
Definition: SelfAdjointEigenSolver.h:356
SelfAdjointEigenSolver & computeFromTridiagonal(const RealVectorType &diag, const SubDiagonalType &subdiag, int options=ComputeEigenvectors)
Computes the eigen decomposition from a tridiagonal symmetric matrix.
Definition: SelfAdjointEigenSolver.h:455
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver & compute(const EigenBase< InputType > &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix.
EIGEN_DEVICE_FUNC MatrixType operatorSqrt() const
Computes the positive-definite square root of the matrix.
Definition: SelfAdjointEigenSolver.h:322
EIGEN_DEVICE_FUNC const EigenvectorsType & eigenvectors() const
Returns the eigenvectors of given matrix.
Definition: SelfAdjointEigenSolver.h:279
EIGEN_DEVICE_FUNC MatrixType operatorInverseSqrt() const
Computes the inverse square root of the matrix.
Definition: SelfAdjointEigenSolver.h:346
EIGEN_DEVICE_FUNC const RealVectorType & eigenvalues() const
Returns the eigenvalues of given matrix.
Definition: SelfAdjointEigenSolver.h:300
@ Symmetric
Definition: Constants.h:229
@ Success
Definition: Constants.h:440
@ NoConvergence
Definition: Constants.h:444
@ Ax_lBx
Definition: Constants.h:406
@ ComputeEigenvectors
Definition: Constants.h:401
@ BAx_lx
Definition: Constants.h:412
@ ABx_lx
Definition: Constants.h:409
const Scalar * a
Definition: level2_cplx_impl.h:32
#define VERIFY(a)
Definition: main.h:362
#define CALL_SUBTEST(FUNC)
Definition: main.h:382
#define VERIFY_IS_EQUAL(a, b)
Definition: main.h:367
#define VERIFY_IS_MUCH_SMALLER_THAN(a, b)
Definition: main.h:371
#define VERIFY_RAISES_ASSERT(a)
Definition: main.h:329
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:217
void svd_fill_random(MatrixType &m, int Option=0)
Definition: svd_fill.h:27

References a, Eigen::ABx_lx, Eigen::HouseholderSequence< VectorsType, CoeffsType, Side >::adjoint(), Eigen::Ax_lBx, b, Eigen::BAx_lx, CALL_SUBTEST, cols, Eigen::SelfAdjointEigenSolver< MatrixType_ >::compute(), Eigen::GeneralizedSelfAdjointEigenSolver< MatrixType_ >::compute(), Eigen::ComputeEigenvectors, Eigen::SelfAdjointEigenSolver< MatrixType_ >::computeFromTridiagonal(), Eigen::Tridiagonalization< MatrixType_ >::diagonal(), Eigen::SelfAdjointEigenSolver< MatrixType_ >::eigenvalues(), Eigen::SelfAdjointEigenSolver< MatrixType_ >::eigenvectors(), Eigen::SelfAdjointEigenSolver< MatrixType_ >::info(), m, Eigen::Tridiagonalization< MatrixType_ >::matrixQ(), Eigen::Tridiagonalization< MatrixType_ >::matrixT(), Eigen::NoConvergence, Eigen::SelfAdjointEigenSolver< MatrixType_ >::operatorInverseSqrt(), Eigen::SelfAdjointEigenSolver< MatrixType_ >::operatorSqrt(), rows, selfadjointeigensolver_essential_check(), Eigen::Tridiagonalization< MatrixType_ >::subDiagonal(), Eigen::Success, svd_fill_random(), Eigen::Symmetric, VERIFY, VERIFY_IS_APPROX, VERIFY_IS_EQUAL, VERIFY_IS_MUCH_SMALLER_THAN, and VERIFY_RAISES_ASSERT.

Referenced by EIGEN_DECLARE_TEST().

◆ selfadjointeigensolver_essential_check()

template<typename MatrixType >
void selfadjointeigensolver_essential_check ( const MatrixType m)
18  {
19  typedef typename MatrixType::Scalar Scalar;
20  typedef typename NumTraits<Scalar>::Real RealScalar;
21  RealScalar eival_eps =
22  numext::mini<RealScalar>(test_precision<RealScalar>(), NumTraits<Scalar>::dummy_precision() * 20000);
23 
25  VERIFY_IS_EQUAL(eiSymm.info(), Success);
26 
27  RealScalar scaling = m.cwiseAbs().maxCoeff();
28  RealScalar unitary_error_factor = RealScalar(16);
29 
30  if (scaling < (std::numeric_limits<RealScalar>::min)()) {
31  VERIFY(eiSymm.eigenvalues().cwiseAbs().maxCoeff() <= (std::numeric_limits<RealScalar>::min)());
32  } else {
33  VERIFY_IS_APPROX((m.template selfadjointView<Lower>() * eiSymm.eigenvectors()) / scaling,
34  (eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal()) / scaling);
35  }
36  VERIFY_IS_APPROX(m.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues());
37  VERIFY(eiSymm.eigenvectors().isUnitary(test_precision<RealScalar>() * unitary_error_factor));
38 
39  if (m.cols() <= 4) {
41  eiDirect.computeDirect(m);
42  VERIFY_IS_EQUAL(eiDirect.info(), Success);
43  if (!eiSymm.eigenvalues().isApprox(eiDirect.eigenvalues(), eival_eps)) {
44  std::cerr << "reference eigenvalues: " << eiSymm.eigenvalues().transpose() << "\n"
45  << "obtained eigenvalues: " << eiDirect.eigenvalues().transpose() << "\n"
46  << "diff: " << (eiSymm.eigenvalues() - eiDirect.eigenvalues()).transpose() << "\n"
47  << "error (eps): "
48  << (eiSymm.eigenvalues() - eiDirect.eigenvalues()).norm() / eiSymm.eigenvalues().norm() << " ("
49  << eival_eps << ")\n";
50  }
51  if (scaling < (std::numeric_limits<RealScalar>::min)()) {
52  VERIFY(eiDirect.eigenvalues().cwiseAbs().maxCoeff() <= (std::numeric_limits<RealScalar>::min)());
53  } else {
54  VERIFY_IS_APPROX(eiSymm.eigenvalues() / scaling, eiDirect.eigenvalues() / scaling);
55  VERIFY_IS_APPROX((m.template selfadjointView<Lower>() * eiDirect.eigenvectors()) / scaling,
56  (eiDirect.eigenvectors() * eiDirect.eigenvalues().asDiagonal()) / scaling);
57  VERIFY_IS_APPROX(m.template selfadjointView<Lower>().eigenvalues() / scaling, eiDirect.eigenvalues() / scaling);
58  }
59 
60  VERIFY(eiDirect.eigenvectors().isUnitary(test_precision<RealScalar>() * unitary_error_factor));
61  }
62 }
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver & computeDirect(const MatrixType &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix using a closed-form algorithm.
Definition: SelfAdjointEigenSolver.h:777
#define min(a, b)
Definition: datatypes.h:22
void transpose()
Definition: skew_symmetric_matrix3.cpp:135

References Eigen::SelfAdjointEigenSolver< MatrixType_ >::computeDirect(), Eigen::SelfAdjointEigenSolver< MatrixType_ >::eigenvalues(), Eigen::SelfAdjointEigenSolver< MatrixType_ >::eigenvectors(), Eigen::SelfAdjointEigenSolver< MatrixType_ >::info(), m, min, Eigen::Success, anonymous_namespace{skew_symmetric_matrix3.cpp}::transpose(), VERIFY, VERIFY_IS_APPROX, and VERIFY_IS_EQUAL.

Referenced by bug_1014(), bug_854(), and selfadjointeigensolver().