2008-05-27 17:16:27 +08:00
|
|
|
// This file is part of Eigen, a lightweight C++ template library
|
2009-05-23 02:25:33 +08:00
|
|
|
// for linear algebra.
|
2008-05-27 17:16:27 +08:00
|
|
|
//
|
|
|
|
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
|
|
|
//
|
|
|
|
// Eigen is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 3 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// Alternatively, you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of
|
|
|
|
// the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License and a copy of the GNU General Public License along with
|
|
|
|
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include "main.h"
|
2009-09-04 15:23:38 +08:00
|
|
|
#include <Eigen/Eigenvalues>
|
2008-05-27 17:16:27 +08:00
|
|
|
|
2008-08-23 23:14:20 +08:00
|
|
|
#ifdef HAS_GSL
|
|
|
|
#include "gsl_helper.h"
|
|
|
|
#endif
|
|
|
|
|
2008-10-01 18:17:08 +08:00
|
|
|
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
|
2008-05-27 17:16:27 +08:00
|
|
|
{
|
|
|
|
/* this test covers the following files:
|
2008-06-04 02:04:36 +08:00
|
|
|
EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h)
|
2008-05-27 17:16:27 +08:00
|
|
|
*/
|
|
|
|
int rows = m.rows();
|
|
|
|
int cols = m.cols();
|
|
|
|
|
2008-08-23 23:14:20 +08:00
|
|
|
typedef typename MatrixType::Scalar Scalar;
|
|
|
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
|
|
|
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
|
|
|
typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
|
2008-05-27 17:16:27 +08:00
|
|
|
typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
|
|
|
|
|
2008-08-23 23:14:20 +08:00
|
|
|
RealScalar largerEps = 10*test_precision<RealScalar>();
|
|
|
|
|
2008-09-02 01:31:21 +08:00
|
|
|
MatrixType a = MatrixType::Random(rows,cols);
|
|
|
|
MatrixType a1 = MatrixType::Random(rows,cols);
|
2008-08-23 23:14:20 +08:00
|
|
|
MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
|
|
|
|
|
2008-09-02 01:31:21 +08:00
|
|
|
MatrixType b = MatrixType::Random(rows,cols);
|
|
|
|
MatrixType b1 = MatrixType::Random(rows,cols);
|
2008-08-23 23:14:20 +08:00
|
|
|
MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
|
2008-05-27 17:16:27 +08:00
|
|
|
|
2008-06-15 03:42:12 +08:00
|
|
|
SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
|
2008-08-23 23:14:20 +08:00
|
|
|
// generalized eigen pb
|
|
|
|
SelfAdjointEigenSolver<MatrixType> eiSymmGen(symmA, symmB);
|
|
|
|
|
|
|
|
#ifdef HAS_GSL
|
|
|
|
if (ei_is_same_type<RealScalar,double>::ret)
|
|
|
|
{
|
|
|
|
typedef GslTraits<Scalar> Gsl;
|
|
|
|
typename Gsl::Matrix gEvec=0, gSymmA=0, gSymmB=0;
|
|
|
|
typename GslTraits<RealScalar>::Vector gEval=0;
|
|
|
|
RealVectorType _eval;
|
|
|
|
MatrixType _evec;
|
|
|
|
convert<MatrixType>(symmA, gSymmA);
|
|
|
|
convert<MatrixType>(symmB, gSymmB);
|
|
|
|
convert<MatrixType>(symmA, gEvec);
|
|
|
|
gEval = GslTraits<RealScalar>::createVector(rows);
|
2008-10-01 18:17:08 +08:00
|
|
|
|
2008-08-23 23:14:20 +08:00
|
|
|
Gsl::eigen_symm(gSymmA, gEval, gEvec);
|
|
|
|
convert(gEval, _eval);
|
|
|
|
convert(gEvec, _evec);
|
2008-10-01 18:17:08 +08:00
|
|
|
|
2008-08-23 23:14:20 +08:00
|
|
|
// test gsl itself !
|
2009-06-29 03:27:37 +08:00
|
|
|
VERIFY((symmA * _evec).isApprox(_evec * _eval.asDiagonal(), largerEps));
|
2008-08-23 23:14:20 +08:00
|
|
|
|
|
|
|
// compare with eigen
|
|
|
|
VERIFY_IS_APPROX(_eval, eiSymm.eigenvalues());
|
2009-11-19 01:15:19 +08:00
|
|
|
VERIFY_IS_APPROX(_evec.cwiseAbs(), eiSymm.eigenvectors().cwiseAbs());
|
2008-08-23 23:14:20 +08:00
|
|
|
|
|
|
|
// generalized pb
|
|
|
|
Gsl::eigen_symm_gen(gSymmA, gSymmB, gEval, gEvec);
|
|
|
|
convert(gEval, _eval);
|
|
|
|
convert(gEvec, _evec);
|
|
|
|
// test GSL itself:
|
2009-06-29 03:27:37 +08:00
|
|
|
VERIFY((symmA * _evec).isApprox(symmB * (_evec * _eval.asDiagonal()), largerEps));
|
2008-08-23 23:14:20 +08:00
|
|
|
|
|
|
|
// compare with eigen
|
|
|
|
// std::cerr << _eval.transpose() << "\n" << eiSymmGen.eigenvalues().transpose() << "\n\n";
|
|
|
|
// std::cerr << _evec.format(6) << "\n\n" << eiSymmGen.eigenvectors().format(6) << "\n\n\n";
|
|
|
|
VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues());
|
2009-11-19 01:15:19 +08:00
|
|
|
VERIFY_IS_APPROX(_evec.cwiseAbs(), eiSymmGen.eigenvectors().cwiseAbs());
|
2008-08-23 23:14:20 +08:00
|
|
|
|
|
|
|
Gsl::free(gSymmA);
|
|
|
|
Gsl::free(gSymmB);
|
|
|
|
GslTraits<RealScalar>::free(gEval);
|
|
|
|
Gsl::free(gEvec);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
VERIFY((symmA * eiSymm.eigenvectors()).isApprox(
|
2009-06-29 03:27:37 +08:00
|
|
|
eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps));
|
2008-06-15 03:42:12 +08:00
|
|
|
|
|
|
|
// generalized eigen problem Ax = lBx
|
2008-08-23 23:14:20 +08:00
|
|
|
VERIFY((symmA * eiSymmGen.eigenvectors()).isApprox(
|
2009-06-29 03:27:37 +08:00
|
|
|
symmB * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
|
2008-05-27 17:16:27 +08:00
|
|
|
|
2008-12-19 22:15:32 +08:00
|
|
|
MatrixType sqrtSymmA = eiSymm.operatorSqrt();
|
2008-12-19 22:52:03 +08:00
|
|
|
VERIFY_IS_APPROX(symmA, sqrtSymmA*sqrtSymmA);
|
|
|
|
VERIFY_IS_APPROX(sqrtSymmA, symmA*eiSymm.operatorInverseSqrt());
|
2008-10-01 18:17:08 +08:00
|
|
|
}
|
2008-05-27 17:16:27 +08:00
|
|
|
|
2009-03-23 22:38:59 +08:00
|
|
|
void test_eigensolver_selfadjoint()
|
2008-05-27 17:16:27 +08:00
|
|
|
{
|
2008-08-23 23:14:20 +08:00
|
|
|
for(int i = 0; i < g_repeat; i++) {
|
2008-06-08 23:03:23 +08:00
|
|
|
// very important to test a 3x3 matrix since we provide a special path for it
|
2009-10-29 06:19:29 +08:00
|
|
|
CALL_SUBTEST_1( selfadjointeigensolver(Matrix3f()) );
|
|
|
|
CALL_SUBTEST_2( selfadjointeigensolver(Matrix4d()) );
|
|
|
|
CALL_SUBTEST_3( selfadjointeigensolver(MatrixXf(10,10)) );
|
|
|
|
CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(19,19)) );
|
|
|
|
CALL_SUBTEST_5( selfadjointeigensolver(MatrixXcd(17,17)) );
|
2008-10-01 18:17:08 +08:00
|
|
|
|
2009-03-23 22:38:59 +08:00
|
|
|
// some trivial but implementation-wise tricky cases
|
2009-10-29 06:19:29 +08:00
|
|
|
CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(1,1)) );
|
|
|
|
CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(2,2)) );
|
|
|
|
CALL_SUBTEST_6( selfadjointeigensolver(Matrix<double,1,1>()) );
|
|
|
|
CALL_SUBTEST_7( selfadjointeigensolver(Matrix<double,2,2>()) );
|
2008-05-27 17:16:27 +08:00
|
|
|
}
|
|
|
|
}
|
2008-10-03 21:22:54 +08:00
|
|
|
|