Home | History | Annotate | Download | only in test
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      5 // Copyright (C) 2010 Jitse Niesen <jitse (at) maths.leeds.ac.uk>
      6 //
      7 // This Source Code Form is subject to the terms of the Mozilla
      8 // Public License v. 2.0. If a copy of the MPL was not distributed
      9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     10 
     11 #include "main.h"
     12 #include <limits>
     13 #include <Eigen/Eigenvalues>
     14 #include <Eigen/LU>
     15 
     16 /* Check that two column vectors are approximately equal upto permutations,
     17    by checking that the k-th power sums are equal for k = 1, ..., vec1.rows() */
     18 template<typename VectorType>
     19 void verify_is_approx_upto_permutation(const VectorType& vec1, const VectorType& vec2)
     20 {
     21   typedef typename NumTraits<typename VectorType::Scalar>::Real RealScalar;
     22 
     23   VERIFY(vec1.cols() == 1);
     24   VERIFY(vec2.cols() == 1);
     25   VERIFY(vec1.rows() == vec2.rows());
     26   for (int k = 1; k <= vec1.rows(); ++k)
     27   {
     28     VERIFY_IS_APPROX(vec1.array().pow(RealScalar(k)).sum(), vec2.array().pow(RealScalar(k)).sum());
     29   }
     30 }
     31 
     32 
     33 template<typename MatrixType> void eigensolver(const MatrixType& m)
     34 {
     35   typedef typename MatrixType::Index Index;
     36   /* this test covers the following files:
     37      ComplexEigenSolver.h, and indirectly ComplexSchur.h
     38   */
     39   Index rows = m.rows();
     40   Index cols = m.cols();
     41 
     42   typedef typename MatrixType::Scalar Scalar;
     43   typedef typename NumTraits<Scalar>::Real RealScalar;
     44   typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
     45   typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
     46   typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
     47 
     48   MatrixType a = MatrixType::Random(rows,cols);
     49   MatrixType symmA =  a.adjoint() * a;
     50 
     51   ComplexEigenSolver<MatrixType> ei0(symmA);
     52   VERIFY_IS_EQUAL(ei0.info(), Success);
     53   VERIFY_IS_APPROX(symmA * ei0.eigenvectors(), ei0.eigenvectors() * ei0.eigenvalues().asDiagonal());
     54 
     55   ComplexEigenSolver<MatrixType> ei1(a);
     56   VERIFY_IS_EQUAL(ei1.info(), Success);
     57   VERIFY_IS_APPROX(a * ei1.eigenvectors(), ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
     58   // Note: If MatrixType is real then a.eigenvalues() uses EigenSolver and thus
     59   // another algorithm so results may differ slightly
     60   verify_is_approx_upto_permutation(a.eigenvalues(), ei1.eigenvalues());
     61 
     62   ComplexEigenSolver<MatrixType> eiNoEivecs(a, false);
     63   VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
     64   VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());
     65 
     66   // Regression test for issue #66
     67   MatrixType z = MatrixType::Zero(rows,cols);
     68   ComplexEigenSolver<MatrixType> eiz(z);
     69   VERIFY((eiz.eigenvalues().cwiseEqual(0)).all());
     70 
     71   MatrixType id = MatrixType::Identity(rows, cols);
     72   VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));
     73 
     74   if (rows > 1)
     75   {
     76     // Test matrix with NaN
     77     a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
     78     ComplexEigenSolver<MatrixType> eiNaN(a);
     79     VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
     80   }
     81 }
     82 
     83 template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
     84 {
     85   ComplexEigenSolver<MatrixType> eig;
     86   VERIFY_RAISES_ASSERT(eig.eigenvectors());
     87   VERIFY_RAISES_ASSERT(eig.eigenvalues());
     88 
     89   MatrixType a = MatrixType::Random(m.rows(),m.cols());
     90   eig.compute(a, false);
     91   VERIFY_RAISES_ASSERT(eig.eigenvectors());
     92 }
     93 
     94 void test_eigensolver_complex()
     95 {
     96   int s;
     97   for(int i = 0; i < g_repeat; i++) {
     98     CALL_SUBTEST_1( eigensolver(Matrix4cf()) );
     99     s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
    100     CALL_SUBTEST_2( eigensolver(MatrixXcd(s,s)) );
    101     CALL_SUBTEST_3( eigensolver(Matrix<std::complex<float>, 1, 1>()) );
    102     CALL_SUBTEST_4( eigensolver(Matrix3f()) );
    103   }
    104 
    105   CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4cf()) );
    106   s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
    107   CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXcd(s,s)) );
    108   CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<std::complex<float>, 1, 1>()) );
    109   CALL_SUBTEST_4( eigensolver_verify_assert(Matrix3f()) );
    110 
    111   // Test problem size constructors
    112   CALL_SUBTEST_5(ComplexEigenSolver<MatrixXf>(s));
    113 
    114   EIGEN_UNUSED_VARIABLE(s)
    115 }
    116