template<typename MatrixType> void generalized_eigensolver_real(const MatrixType& m) { typedef typename MatrixType::Index Index; /* this test covers the following files: GeneralizedEigenSolver.h */ Index rows = m.rows(); Index 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 b = MatrixType::Random(rows,cols); MatrixType a1 = MatrixType::Random(rows,cols); MatrixType b1 = MatrixType::Random(rows,cols); MatrixType spdA = a.adjoint() * a + a1.adjoint() * a1; MatrixType spdB = b.adjoint() * b + b1.adjoint() * b1; // lets compare to GeneralizedSelfAdjointEigenSolver GeneralizedSelfAdjointEigenSolver<MatrixType> symmEig(spdA, spdB); GeneralizedEigenSolver<MatrixType> eig(spdA, spdB); VERIFY_IS_EQUAL(eig.eigenvalues().imag().cwiseAbs().maxCoeff(), 0); VectorType realEigenvalues = eig.eigenvalues().real(); std::sort(realEigenvalues.data(), realEigenvalues.data()+realEigenvalues.size()); VERIFY_IS_APPROX(realEigenvalues, symmEig.eigenvalues()); }
template<typename MatrixType> void lu_invertible() { /* this test covers the following files: LU.h */ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar; int size = ei_random<int>(10,200); MatrixType m1(size, size), m2(size, size), m3(size, size); m1 = MatrixType::Random(size,size); if (ei_is_same_type<RealScalar,float>::ret) { // let's build a matrix more stable to inverse MatrixType a = MatrixType::Random(size,size*2); m1 += a * a.adjoint(); } LU<MatrixType> lu(m1); VERIFY(0 == lu.dimensionOfKernel()); VERIFY(size == lu.rank()); VERIFY(lu.isInjective()); VERIFY(lu.isSurjective()); VERIFY(lu.isInvertible()); VERIFY(lu.image().lu().isInvertible()); m3 = MatrixType::Random(size,size); lu.solve(m3, &m2); VERIFY_IS_APPROX(m3, m1*m2); VERIFY_IS_APPROX(m2, lu.inverse()*m3); m3 = MatrixType::Random(size,size); VERIFY(lu.solve(m3, &m2)); }
void dontalign(const MatrixType& m) { typedef typename MatrixType::Scalar Scalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType; Index rows = m.rows(); Index cols = m.cols(); MatrixType a = MatrixType::Random(rows,cols); SquareMatrixType square = SquareMatrixType::Random(rows,rows); VectorType v = VectorType::Random(rows); VERIFY_IS_APPROX(v, square * square.colPivHouseholderQr().solve(v)); square = square.inverse().eval(); a = square * a; square = square*square; v = square * v; v = a.adjoint() * v; VERIFY(square.determinant() != Scalar(0)); // bug 219: MapAligned() was giving an assert with EIGEN_DONT_ALIGN, because Map Flags were miscomputed Scalar* array = internal::aligned_new<Scalar>(rows); v = VectorType::MapAligned(array, rows); internal::aligned_delete(array, rows); }
template<typename MatrixType> void eigensolver(const MatrixType& m) { /* this test covers the following files: EigenSolver.h */ 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; // RealScalar largerEps = 10*test_precision<RealScalar>(); MatrixType a = MatrixType::Random(rows,cols); MatrixType a1 = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1; EigenSolver<MatrixType> ei0(symmA); VERIFY_IS_APPROX(symmA * ei0.pseudoEigenvectors(), ei0.pseudoEigenvectors() * ei0.pseudoEigenvalueMatrix()); VERIFY_IS_APPROX((symmA.template cast<Complex>()) * (ei0.pseudoEigenvectors().template cast<Complex>()), (ei0.pseudoEigenvectors().template cast<Complex>()) * (ei0.eigenvalues().asDiagonal())); EigenSolver<MatrixType> ei1(a); VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix()); VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(), ei1.eigenvectors() * ei1.eigenvalues().asDiagonal()); }
template<typename MatrixType> void qr(const MatrixType& m) { /* this test covers the following files: QR.h */ int rows = m.rows(); int cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> SquareMatrixType; typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType; MatrixType a = MatrixType::Random(rows,cols); QR<MatrixType> qrOfA(a); VERIFY_IS_APPROX(a, qrOfA.matrixQ() * qrOfA.matrixR()); VERIFY_IS_NOT_APPROX(a+MatrixType::Identity(rows, cols), qrOfA.matrixQ() * qrOfA.matrixR()); SquareMatrixType b = a.adjoint() * a; // check tridiagonalization Tridiagonalization<SquareMatrixType> tridiag(b); VERIFY_IS_APPROX(b, tridiag.matrixQ() * tridiag.matrixT() * tridiag.matrixQ().adjoint()); // check hessenberg decomposition HessenbergDecomposition<SquareMatrixType> hess(b); VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint()); VERIFY_IS_APPROX(tridiag.matrixT(), hess.matrixH()); b = SquareMatrixType::Random(cols,cols); hess.compute(b); VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint()); }
template<typename MatrixType> void svd(const MatrixType& m) { /* this test covers the following files: SVD.h */ int rows = m.rows(); int cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; MatrixType a = MatrixType::Random(rows,cols); Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> b = Matrix<Scalar, MatrixType::RowsAtCompileTime, 1>::Random(rows,1); Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> x(cols,1), x2(cols,1); RealScalar largerEps = test_precision<RealScalar>(); if (ei_is_same_type<RealScalar,float>::ret) largerEps = 1e-3f; { SVD<MatrixType> svd(a); MatrixType sigma = MatrixType::Zero(rows,cols); MatrixType matU = MatrixType::Zero(rows,rows); sigma.block(0,0,cols,cols) = svd.singularValues().asDiagonal(); matU.block(0,0,rows,cols) = svd.matrixU(); VERIFY_IS_APPROX(a, matU * sigma * svd.matrixV().transpose()); } if (rows==cols) { if (ei_is_same_type<RealScalar,float>::ret) { MatrixType a1 = MatrixType::Random(rows,cols); a += a * a.adjoint() + a1 * a1.adjoint(); } SVD<MatrixType> svd(a); svd.solve(b, &x); VERIFY_IS_APPROX(a * x,b); } if(rows==cols) { SVD<MatrixType> svd(a); MatrixType unitary, positive; svd.computeUnitaryPositive(&unitary, &positive); VERIFY_IS_APPROX(unitary * unitary.adjoint(), MatrixType::Identity(unitary.rows(),unitary.rows())); VERIFY_IS_APPROX(positive, positive.adjoint()); for(int i = 0; i < rows; i++) VERIFY(positive.diagonal()[i] >= 0); // cheap necessary (not sufficient) condition for positivity VERIFY_IS_APPROX(unitary*positive, a); svd.computePositiveUnitary(&positive, &unitary); VERIFY_IS_APPROX(unitary * unitary.adjoint(), MatrixType::Identity(unitary.rows(),unitary.rows())); VERIFY_IS_APPROX(positive, positive.adjoint()); for(int i = 0; i < rows; i++) VERIFY(positive.diagonal()[i] >= 0); // cheap necessary (not sufficient) condition for positivity VERIFY_IS_APPROX(positive*unitary, a); } }
template<typename MatrixType> void eigensolver(const MatrixType& m) { typedef typename MatrixType::Index Index; /* this test covers the following files: EigenSolver.h */ Index rows = m.rows(); Index cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; 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 a1 = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1; EigenSolver<MatrixType> ei0(symmA); VERIFY_IS_EQUAL(ei0.info(), Success); VERIFY_IS_APPROX(symmA * ei0.pseudoEigenvectors(), ei0.pseudoEigenvectors() * ei0.pseudoEigenvalueMatrix()); VERIFY_IS_APPROX((symmA.template cast<Complex>()) * (ei0.pseudoEigenvectors().template cast<Complex>()), (ei0.pseudoEigenvectors().template cast<Complex>()) * (ei0.eigenvalues().asDiagonal())); EigenSolver<MatrixType> ei1(a); VERIFY_IS_EQUAL(ei1.info(), Success); VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix()); VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(), ei1.eigenvectors() * ei1.eigenvalues().asDiagonal()); VERIFY_IS_APPROX(ei1.eigenvectors().colwise().norm(), RealVectorType::Ones(rows).transpose()); VERIFY_IS_APPROX(a.eigenvalues(), ei1.eigenvalues()); EigenSolver<MatrixType> ei2; ei2.setMaxIterations(RealSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a); VERIFY_IS_EQUAL(ei2.info(), Success); VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors()); VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues()); if (rows > 2) { ei2.setMaxIterations(1).compute(a); VERIFY_IS_EQUAL(ei2.info(), NoConvergence); VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1); } EigenSolver<MatrixType> eiNoEivecs(a, false); VERIFY_IS_EQUAL(eiNoEivecs.info(), Success); VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues()); VERIFY_IS_APPROX(ei1.pseudoEigenvalueMatrix(), eiNoEivecs.pseudoEigenvalueMatrix()); MatrixType id = MatrixType::Identity(rows, cols); VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1)); if (rows > 2) { // Test matrix with NaN a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN(); EigenSolver<MatrixType> eiNaN(a); VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence); } }
template<typename MatrixType> void eigensolver(const MatrixType& m) { typedef typename MatrixType::Index Index; /* this test covers the following files: ComplexEigenSolver.h, and indirectly ComplexSchur.h */ Index rows = m.rows(); Index cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; MatrixType a = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a; ComplexEigenSolver<MatrixType> ei0(symmA); VERIFY_IS_EQUAL(ei0.info(), Success); VERIFY_IS_APPROX(symmA * ei0.eigenvectors(), ei0.eigenvectors() * ei0.eigenvalues().asDiagonal()); ComplexEigenSolver<MatrixType> ei1(a); VERIFY_IS_EQUAL(ei1.info(), Success); VERIFY_IS_APPROX(a * ei1.eigenvectors(), ei1.eigenvectors() * ei1.eigenvalues().asDiagonal()); // Note: If MatrixType is real then a.eigenvalues() uses EigenSolver and thus // another algorithm so results may differ slightly verify_is_approx_upto_permutation(a.eigenvalues(), ei1.eigenvalues()); ComplexEigenSolver<MatrixType> ei2; ei2.setMaxIterations(ComplexSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a); VERIFY_IS_EQUAL(ei2.info(), Success); VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors()); VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues()); if (rows > 2) { ei2.setMaxIterations(1).compute(a); VERIFY_IS_EQUAL(ei2.info(), NoConvergence); VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1); } ComplexEigenSolver<MatrixType> eiNoEivecs(a, false); VERIFY_IS_EQUAL(eiNoEivecs.info(), Success); VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues()); // Regression test for issue #66 MatrixType z = MatrixType::Zero(rows,cols); ComplexEigenSolver<MatrixType> eiz(z); VERIFY((eiz.eigenvalues().cwiseEqual(0)).all()); MatrixType id = MatrixType::Identity(rows, cols); VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1)); if (rows > 1) { // Test matrix with NaN a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN(); ComplexEigenSolver<MatrixType> eiNaN(a); VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence); } }
template<typename MatrixType> void upperbidiag(const MatrixType& m) { const typename MatrixType::Index rows = m.rows(); const typename MatrixType::Index cols = m.cols(); typedef Matrix<typename MatrixType::RealScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> RealMatrixType; typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime> TransposeMatrixType; MatrixType a = MatrixType::Random(rows,cols); internal::UpperBidiagonalization<MatrixType> ubd(a); RealMatrixType b(rows, cols); b.setZero(); b.block(0,0,cols,cols) = ubd.bidiagonal(); MatrixType c = ubd.householderU() * b * ubd.householderV().adjoint(); VERIFY_IS_APPROX(a,c); TransposeMatrixType d = ubd.householderV() * b.adjoint() * ubd.householderU().adjoint(); VERIFY_IS_APPROX(a.adjoint(),d); }
__attribute__ ((noinline)) void benchLLT(const MatrixType& m) { int rows = m.rows(); int cols = m.cols(); double cost = 0; for (int j=0; j<rows; ++j) { int r = std::max(rows - j -1,0); cost += 2*(r*j+r+j); } int repeats = (REPEAT*1000)/(rows*rows); typedef typename MatrixType::Scalar Scalar; typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType; MatrixType a = MatrixType::Random(rows,cols); SquareMatrixType covMat = a * a.adjoint(); BenchTimer timerNoSqrt, timerSqrt; Scalar acc = 0; int r = internal::random<int>(0,covMat.rows()-1); int c = internal::random<int>(0,covMat.cols()-1); for (int t=0; t<TRIES; ++t) { timerNoSqrt.start(); for (int k=0; k<repeats; ++k) { LDLT<SquareMatrixType> cholnosqrt(covMat); acc += cholnosqrt.matrixL().coeff(r,c); } timerNoSqrt.stop(); } for (int t=0; t<TRIES; ++t) { timerSqrt.start(); for (int k=0; k<repeats; ++k) { LLT<SquareMatrixType> chol(covMat); acc += chol.matrixL().coeff(r,c); } timerSqrt.stop(); } if (MatrixType::RowsAtCompileTime==Dynamic) std::cout << "dyn "; else std::cout << "fixed "; std::cout << covMat.rows() << " \t" << (timerNoSqrt.best()) / repeats << "s " << "(" << 1e-9 * cost*repeats/timerNoSqrt.best() << " GFLOPS)\t" << (timerSqrt.best()) / repeats << "s " << "(" << 1e-9 * cost*repeats/timerSqrt.best() << " GFLOPS)\n"; #ifdef BENCH_GSL if (MatrixType::RowsAtCompileTime==Dynamic) { timerSqrt.reset(); gsl_matrix* gslCovMat = gsl_matrix_alloc(covMat.rows(),covMat.cols()); gsl_matrix* gslCopy = gsl_matrix_alloc(covMat.rows(),covMat.cols()); eiToGsl(covMat, &gslCovMat); for (int t=0; t<TRIES; ++t) { timerSqrt.start(); for (int k=0; k<repeats; ++k) { gsl_matrix_memcpy(gslCopy,gslCovMat); gsl_linalg_cholesky_decomp(gslCopy); acc += gsl_matrix_get(gslCopy,r,c); } timerSqrt.stop(); } std::cout << " | \t" << timerSqrt.value() * REPEAT / repeats << "s"; gsl_matrix_free(gslCovMat); } #endif std::cout << "\n"; // make sure the compiler does not optimize too much if (acc==123) std::cout << acc; }
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m) { typedef typename MatrixType::Index Index; /* this test covers the following files: EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h) */ Index rows = m.rows(); Index cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; RealScalar largerEps = 10*test_precision<RealScalar>(); MatrixType a = MatrixType::Random(rows,cols); MatrixType a1 = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1; MatrixType symmC = symmA; svd_fill_random(symmA,Symmetric); symmA.template triangularView<StrictlyUpper>().setZero(); symmC.template triangularView<StrictlyUpper>().setZero(); MatrixType b = MatrixType::Random(rows,cols); MatrixType b1 = MatrixType::Random(rows,cols); MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1; symmB.template triangularView<StrictlyUpper>().setZero(); CALL_SUBTEST( selfadjointeigensolver_essential_check(symmA) ); SelfAdjointEigenSolver<MatrixType> eiSymm(symmA); // generalized eigen pb GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmC, symmB); SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false); VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success); VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues()); // generalized eigen problem Ax = lBx eiSymmGen.compute(symmC, symmB,Ax_lBx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox( symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem BAx = lx eiSymmGen.compute(symmC, symmB,BAx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmB.template selfadjointView<Lower>() * (symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem ABx = lx eiSymmGen.compute(symmC, symmB,ABx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmC.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); eiSymm.compute(symmC); MatrixType sqrtSymmA = eiSymm.operatorSqrt(); VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA); VERIFY_IS_APPROX(sqrtSymmA, symmC.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt()); MatrixType id = MatrixType::Identity(rows, cols); VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1)); SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized; VERIFY_RAISES_ASSERT(eiSymmUninitialized.info()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); eiSymmUninitialized.compute(symmA, false); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); // test Tridiagonalization's methods Tridiagonalization<MatrixType> tridiag(symmC); VERIFY_IS_APPROX(tridiag.diagonal(), tridiag.matrixT().diagonal()); VERIFY_IS_APPROX(tridiag.subDiagonal(), tridiag.matrixT().template diagonal<-1>()); Matrix<RealScalar,Dynamic,Dynamic> T = tridiag.matrixT(); if(rows>1 && cols>1) { // FIXME check that upper and lower part are 0: //VERIFY(T.topRightCorner(rows-2, cols-2).template triangularView<Upper>().isZero()); } VERIFY_IS_APPROX(tridiag.diagonal(), T.diagonal()); VERIFY_IS_APPROX(tridiag.subDiagonal(), T.template diagonal<1>()); VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT().eval() * MatrixType(tridiag.matrixQ()).adjoint()); VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT() * tridiag.matrixQ().adjoint()); // Test computation of eigenvalues from tridiagonal matrix if(rows > 1) { SelfAdjointEigenSolver<MatrixType> eiSymmTridiag; eiSymmTridiag.computeFromTridiagonal(tridiag.matrixT().diagonal(), tridiag.matrixT().diagonal(-1), ComputeEigenvectors); VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmTridiag.eigenvalues()); VERIFY_IS_APPROX(tridiag.matrixT(), eiSymmTridiag.eigenvectors().real() * eiSymmTridiag.eigenvalues().asDiagonal() * eiSymmTridiag.eigenvectors().real().transpose()); } if (rows > 1) { // Test matrix with NaN symmC(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN(); SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmC); VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence); } }
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m) { typedef typename MatrixType::Index Index; /* this test covers the following files: EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h) */ Index rows = m.rows(); Index 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; RealScalar largerEps = 10*test_precision<RealScalar>(); MatrixType a = MatrixType::Random(rows,cols); MatrixType a1 = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1; symmA.template triangularView<StrictlyUpper>().setZero(); MatrixType b = MatrixType::Random(rows,cols); MatrixType b1 = MatrixType::Random(rows,cols); MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1; symmB.template triangularView<StrictlyUpper>().setZero(); SelfAdjointEigenSolver<MatrixType> eiSymm(symmA); // generalized eigen pb GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmA, symmB); #ifdef HAS_GSL if (internal::is_same<RealScalar,double>::value) { // restore symmA and symmB. symmA = MatrixType(symmA.template selfadjointView<Lower>()); symmB = MatrixType(symmB.template selfadjointView<Lower>()); 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(), largerEps)); // compare with eigen VERIFY_IS_APPROX(_eval, eiSymm.eigenvalues()); VERIFY_IS_APPROX(_evec.cwiseAbs(), eiSymm.eigenvectors().cwiseAbs()); // 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()), largerEps)); // compare with eigen MatrixType normalized_eivec = eiSymmGen.eigenvectors()*eiSymmGen.eigenvectors().colwise().norm().asDiagonal().inverse(); VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues()); VERIFY_IS_APPROX(_evec.cwiseAbs(), normalized_eivec.cwiseAbs()); Gsl::free(gSymmA); Gsl::free(gSymmB); GslTraits<RealScalar>::free(gEval); Gsl::free(gEvec); } #endif VERIFY_IS_EQUAL(eiSymm.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * eiSymm.eigenvectors()).isApprox( eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps)); VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues()); SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false); VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success); VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues()); // generalized eigen problem Ax = lBx eiSymmGen.compute(symmA, symmB,Ax_lBx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox( symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem BAx = lx eiSymmGen.compute(symmA, symmB,BAx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmB.template selfadjointView<Lower>() * (symmA.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem ABx = lx eiSymmGen.compute(symmA, symmB,ABx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); MatrixType sqrtSymmA = eiSymm.operatorSqrt(); VERIFY_IS_APPROX(MatrixType(symmA.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA); VERIFY_IS_APPROX(sqrtSymmA, symmA.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt()); MatrixType id = MatrixType::Identity(rows, cols); VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1)); SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized; VERIFY_RAISES_ASSERT(eiSymmUninitialized.info()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); eiSymmUninitialized.compute(symmA, false); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); // test Tridiagonalization's methods Tridiagonalization<MatrixType> tridiag(symmA); // FIXME tridiag.matrixQ().adjoint() does not work VERIFY_IS_APPROX(MatrixType(symmA.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT().eval() * MatrixType(tridiag.matrixQ()).adjoint()); if (rows > 1) { // Test matrix with NaN symmA(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN(); SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmA); VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence); } }
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m) { /* this test covers the following files: EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h) */ 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; RealScalar largerEps = 10*test_precision<RealScalar>(); MatrixType a = MatrixType::Random(rows,cols); MatrixType a1 = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1; MatrixType b = MatrixType::Random(rows,cols); MatrixType b1 = MatrixType::Random(rows,cols); MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1; SelfAdjointEigenSolver<MatrixType> eiSymm(symmA); // 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(), 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()), largerEps)); // compare with eigen MatrixType normalized_eivec = eiSymmGen.eigenvectors()*eiSymmGen.eigenvectors().colwise().norm().asDiagonal().inverse(); VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues()); VERIFY_IS_APPROX(_evec.cwiseAbs(), normalized_eivec.cwiseAbs()); Gsl::free(gSymmA); Gsl::free(gSymmB); GslTraits<RealScalar>::free(gEval); Gsl::free(gEvec); } #endif VERIFY((symmA * eiSymm.eigenvectors()).isApprox( eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps)); // generalized eigen problem Ax = lBx VERIFY((symmA * eiSymmGen.eigenvectors()).isApprox( symmB * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); MatrixType sqrtSymmA = eiSymm.operatorSqrt(); VERIFY_IS_APPROX(symmA, sqrtSymmA*sqrtSymmA); VERIFY_IS_APPROX(sqrtSymmA, symmA*eiSymm.operatorInverseSqrt()); }
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m) { typedef typename MatrixType::Index Index; /* this test covers the following files: EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h) */ Index rows = m.rows(); Index cols = m.cols(); typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits<Scalar>::Real RealScalar; RealScalar largerEps = 10*test_precision<RealScalar>(); MatrixType a = MatrixType::Random(rows,cols); MatrixType a1 = MatrixType::Random(rows,cols); MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1; MatrixType symmC = symmA; // randomly nullify some rows/columns { Index count = 1;//internal::random<Index>(-cols,cols); for(Index k=0; k<count; ++k) { Index i = internal::random<Index>(0,cols-1); symmA.row(i).setZero(); symmA.col(i).setZero(); } } symmA.template triangularView<StrictlyUpper>().setZero(); symmC.template triangularView<StrictlyUpper>().setZero(); MatrixType b = MatrixType::Random(rows,cols); MatrixType b1 = MatrixType::Random(rows,cols); MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1; symmB.template triangularView<StrictlyUpper>().setZero(); SelfAdjointEigenSolver<MatrixType> eiSymm(symmA); SelfAdjointEigenSolver<MatrixType> eiDirect; eiDirect.computeDirect(symmA); // generalized eigen pb GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmC, symmB); VERIFY_IS_EQUAL(eiSymm.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * eiSymm.eigenvectors()).isApprox( eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps)); VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues()); VERIFY_IS_EQUAL(eiDirect.info(), Success); VERIFY((symmA.template selfadjointView<Lower>() * eiDirect.eigenvectors()).isApprox( eiDirect.eigenvectors() * eiDirect.eigenvalues().asDiagonal(), largerEps)); VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiDirect.eigenvalues()); SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false); VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success); VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues()); // generalized eigen problem Ax = lBx eiSymmGen.compute(symmC, symmB,Ax_lBx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox( symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem BAx = lx eiSymmGen.compute(symmC, symmB,BAx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmB.template selfadjointView<Lower>() * (symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); // generalized eigen problem ABx = lx eiSymmGen.compute(symmC, symmB,ABx_lx); VERIFY_IS_EQUAL(eiSymmGen.info(), Success); VERIFY((symmC.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox( (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps)); eiSymm.compute(symmC); MatrixType sqrtSymmA = eiSymm.operatorSqrt(); VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA); VERIFY_IS_APPROX(sqrtSymmA, symmC.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt()); MatrixType id = MatrixType::Identity(rows, cols); VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1)); SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized; VERIFY_RAISES_ASSERT(eiSymmUninitialized.info()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); eiSymmUninitialized.compute(symmA, false); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); // test Tridiagonalization's methods Tridiagonalization<MatrixType> tridiag(symmC); // FIXME tridiag.matrixQ().adjoint() does not work VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT().eval() * MatrixType(tridiag.matrixQ()).adjoint()); if (rows > 1) { // Test matrix with NaN symmC(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN(); SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmC); VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence); } }