mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
* bug fixes in: Dot, generalized eigen problem, singular matrix detetection in Cholesky
* fix all numerical instabilies in the unit tests, now all tests can be run 2000 times with almost zero failures.
This commit is contained in:
@@ -25,6 +25,10 @@
|
||||
#include "main.h"
|
||||
#include <Eigen/QR>
|
||||
|
||||
#ifdef HAS_GSL
|
||||
#include "gsl_helper.h"
|
||||
#endif
|
||||
|
||||
template<typename MatrixType> void eigensolver(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
@@ -33,19 +37,76 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
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;
|
||||
typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
|
||||
|
||||
MatrixType a = MatrixType::Random(rows,cols);
|
||||
MatrixType symmA = a.adjoint() * a;
|
||||
RealScalar largerEps = 10*test_precision<RealScalar>();
|
||||
|
||||
MatrixType a = test_random_matrix<MatrixType>(rows,cols);
|
||||
MatrixType a1 = test_random_matrix<MatrixType>(rows,cols);
|
||||
MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
|
||||
|
||||
MatrixType b = test_random_matrix<MatrixType>(rows,cols);
|
||||
MatrixType b1 = test_random_matrix<MatrixType>(rows,cols);
|
||||
MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
|
||||
|
||||
SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
|
||||
VERIFY_IS_APPROX(symmA * eiSymm.eigenvectors(), (eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal().eval()));
|
||||
// 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);
|
||||
|
||||
Gsl::eigen_symm(gSymmA, gEval, gEvec);
|
||||
convert(gEval, _eval);
|
||||
convert(gEvec, _evec);
|
||||
|
||||
// test gsl itself !
|
||||
VERIFY((symmA * _evec).isApprox(_evec * _eval.asDiagonal().eval(), largerEps));
|
||||
|
||||
// compare with eigen
|
||||
VERIFY_IS_APPROX(_eval, eiSymm.eigenvalues());
|
||||
VERIFY_IS_APPROX(_evec.cwise().abs(), eiSymm.eigenvectors().cwise().abs());
|
||||
|
||||
// generalized pb
|
||||
Gsl::eigen_symm_gen(gSymmA, gSymmB, gEval, gEvec);
|
||||
convert(gEval, _eval);
|
||||
convert(gEvec, _evec);
|
||||
// test GSL itself:
|
||||
VERIFY((symmA * _evec).isApprox(symmB * (_evec * _eval.asDiagonal().eval()), largerEps));
|
||||
|
||||
// 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());
|
||||
VERIFY_IS_APPROX(_evec.cwise().abs(), eiSymmGen.eigenvectors().cwise().abs());
|
||||
|
||||
Gsl::free(gSymmA);
|
||||
Gsl::free(gSymmB);
|
||||
GslTraits<RealScalar>::free(gEval);
|
||||
Gsl::free(gEvec);
|
||||
}
|
||||
#endif
|
||||
|
||||
VERIFY((symmA * eiSymm.eigenvectors()).isApprox(
|
||||
eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal().eval(), largerEps));
|
||||
|
||||
// generalized eigen problem Ax = lBx
|
||||
MatrixType b = MatrixType::Random(rows,cols);
|
||||
MatrixType symmB = b.adjoint() * b;
|
||||
eiSymm.compute(symmA,symmB);
|
||||
VERIFY_IS_APPROX(symmA * eiSymm.eigenvectors(), symmB * (eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal().eval()));
|
||||
VERIFY((symmA * eiSymmGen.eigenvectors()).isApprox(
|
||||
symmB * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal().eval()), largerEps));
|
||||
|
||||
// EigenSolver<MatrixType> eiNotSymmButSymm(covMat);
|
||||
// VERIFY_IS_APPROX((covMat.template cast<Complex>()) * (eiNotSymmButSymm.eigenvectors().template cast<Complex>()),
|
||||
@@ -59,12 +120,12 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
|
||||
|
||||
void test_eigensolver()
|
||||
{
|
||||
for(int i = 0; i < 1; i++) {
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
// very important to test a 3x3 matrix since we provide a special path for it
|
||||
CALL_SUBTEST( eigensolver(Matrix3f()) );
|
||||
CALL_SUBTEST( eigensolver(Matrix4d()) );
|
||||
CALL_SUBTEST( eigensolver(MatrixXf(7,7)) );
|
||||
CALL_SUBTEST( eigensolver(MatrixXcd(6,6)) );
|
||||
CALL_SUBTEST( eigensolver(MatrixXcf(3,3)) );
|
||||
CALL_SUBTEST( eigensolver(MatrixXcd(5,5)) );
|
||||
CALL_SUBTEST( eigensolver(MatrixXd(19,19)) );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user