Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "main.h"
00011 #include <unsupported/Eigen/MatrixFunctions>
00012
00013
00014
00015 #define VERIFY_IS_APPROX_ABS(a, b) VERIFY(test_isApprox_abs(a, b))
00016
00017 template<typename Type1, typename Type2>
00018 inline bool test_isApprox_abs(const Type1& a, const Type2& b)
00019 {
00020 return ((a-b).array().abs() < test_precision<typename Type1::RealScalar>()).all();
00021 }
00022
00023
00024
00025 template<typename MatrixType>
00026 MatrixType randomMatrixWithRealEivals(const typename MatrixType::Index size)
00027 {
00028 typedef typename MatrixType::Index Index;
00029 typedef typename MatrixType::Scalar Scalar;
00030 typedef typename MatrixType::RealScalar RealScalar;
00031 MatrixType diag = MatrixType::Zero(size, size);
00032 for (Index i = 0; i < size; ++i) {
00033 diag(i, i) = Scalar(RealScalar(internal::random<int>(0,2)))
00034 + internal::random<Scalar>() * Scalar(RealScalar(0.01));
00035 }
00036 MatrixType A = MatrixType::Random(size, size);
00037 HouseholderQR<MatrixType> QRofA(A);
00038 return QRofA.householderQ().inverse() * diag * QRofA.householderQ();
00039 }
00040
00041 template <typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
00042 struct randomMatrixWithImagEivals
00043 {
00044
00045 static MatrixType run(const typename MatrixType::Index size);
00046 };
00047
00048
00049 template<typename MatrixType>
00050 struct randomMatrixWithImagEivals<MatrixType, 0>
00051 {
00052 static MatrixType run(const typename MatrixType::Index size)
00053 {
00054 typedef typename MatrixType::Index Index;
00055 typedef typename MatrixType::Scalar Scalar;
00056 MatrixType diag = MatrixType::Zero(size, size);
00057 Index i = 0;
00058 while (i < size) {
00059 Index randomInt = internal::random<Index>(-1, 1);
00060 if (randomInt == 0 || i == size-1) {
00061 diag(i, i) = internal::random<Scalar>() * Scalar(0.01);
00062 ++i;
00063 } else {
00064 Scalar alpha = Scalar(randomInt) + internal::random<Scalar>() * Scalar(0.01);
00065 diag(i, i+1) = alpha;
00066 diag(i+1, i) = -alpha;
00067 i += 2;
00068 }
00069 }
00070 MatrixType A = MatrixType::Random(size, size);
00071 HouseholderQR<MatrixType> QRofA(A);
00072 return QRofA.householderQ().inverse() * diag * QRofA.householderQ();
00073 }
00074 };
00075
00076
00077 template<typename MatrixType>
00078 struct randomMatrixWithImagEivals<MatrixType, 1>
00079 {
00080 static MatrixType run(const typename MatrixType::Index size)
00081 {
00082 typedef typename MatrixType::Index Index;
00083 typedef typename MatrixType::Scalar Scalar;
00084 typedef typename MatrixType::RealScalar RealScalar;
00085 const Scalar imagUnit(0, 1);
00086 MatrixType diag = MatrixType::Zero(size, size);
00087 for (Index i = 0; i < size; ++i) {
00088 diag(i, i) = Scalar(RealScalar(internal::random<Index>(-1, 1))) * imagUnit
00089 + internal::random<Scalar>() * Scalar(RealScalar(0.01));
00090 }
00091 MatrixType A = MatrixType::Random(size, size);
00092 HouseholderQR<MatrixType> QRofA(A);
00093 return QRofA.householderQ().inverse() * diag * QRofA.householderQ();
00094 }
00095 };
00096
00097
00098 template<typename MatrixType>
00099 void testMatrixExponential(const MatrixType& A)
00100 {
00101 typedef typename internal::traits<MatrixType>::Scalar Scalar;
00102 typedef typename NumTraits<Scalar>::Real RealScalar;
00103 typedef std::complex<RealScalar> ComplexScalar;
00104
00105 VERIFY_IS_APPROX(A.exp(), A.matrixFunction(StdStemFunctions<ComplexScalar>::exp));
00106 }
00107
00108 template<typename MatrixType>
00109 void testMatrixLogarithm(const MatrixType& A)
00110 {
00111 typedef typename internal::traits<MatrixType>::Scalar Scalar;
00112 typedef typename NumTraits<Scalar>::Real RealScalar;
00113
00114 MatrixType scaledA;
00115 RealScalar maxImagPartOfSpectrum = A.eigenvalues().imag().cwiseAbs().maxCoeff();
00116 if (maxImagPartOfSpectrum >= 0.9 * M_PI)
00117 scaledA = A * 0.9 * M_PI / maxImagPartOfSpectrum;
00118 else
00119 scaledA = A;
00120
00121
00122 MatrixType expA = scaledA.exp();
00123 MatrixType logExpA = expA.log();
00124 VERIFY_IS_APPROX(logExpA, scaledA);
00125 }
00126
00127 template<typename MatrixType>
00128 void testHyperbolicFunctions(const MatrixType& A)
00129 {
00130
00131
00132 VERIFY_IS_APPROX_ABS(A.sinh(), (A.exp() - (-A).exp()) / 2);
00133 VERIFY_IS_APPROX_ABS(A.cosh(), (A.exp() + (-A).exp()) / 2);
00134 }
00135
00136 template<typename MatrixType>
00137 void testGonioFunctions(const MatrixType& A)
00138 {
00139 typedef typename MatrixType::Scalar Scalar;
00140 typedef typename NumTraits<Scalar>::Real RealScalar;
00141 typedef std::complex<RealScalar> ComplexScalar;
00142 typedef Matrix<ComplexScalar, MatrixType::RowsAtCompileTime,
00143 MatrixType::ColsAtCompileTime, MatrixType::Options> ComplexMatrix;
00144
00145 ComplexScalar imagUnit(0,1);
00146 ComplexScalar two(2,0);
00147
00148 ComplexMatrix Ac = A.template cast<ComplexScalar>();
00149
00150 ComplexMatrix exp_iA = (imagUnit * Ac).exp();
00151 ComplexMatrix exp_miA = (-imagUnit * Ac).exp();
00152
00153 ComplexMatrix sinAc = A.sin().template cast<ComplexScalar>();
00154 VERIFY_IS_APPROX_ABS(sinAc, (exp_iA - exp_miA) / (two*imagUnit));
00155
00156 ComplexMatrix cosAc = A.cos().template cast<ComplexScalar>();
00157 VERIFY_IS_APPROX_ABS(cosAc, (exp_iA + exp_miA) / 2);
00158 }
00159
00160 template<typename MatrixType>
00161 void testMatrix(const MatrixType& A)
00162 {
00163 testMatrixExponential(A);
00164 testMatrixLogarithm(A);
00165 testHyperbolicFunctions(A);
00166 testGonioFunctions(A);
00167 }
00168
00169 template<typename MatrixType>
00170 void testMatrixType(const MatrixType& m)
00171 {
00172
00173
00174 typedef typename MatrixType::Index Index;
00175
00176 const Index size = m.rows();
00177 for (int i = 0; i < g_repeat; i++) {
00178 testMatrix(MatrixType::Random(size, size).eval());
00179 testMatrix(randomMatrixWithRealEivals<MatrixType>(size));
00180 testMatrix(randomMatrixWithImagEivals<MatrixType>::run(size));
00181 }
00182 }
00183
00184 void test_matrix_function()
00185 {
00186 CALL_SUBTEST_1(testMatrixType(Matrix<float,1,1>()));
00187 CALL_SUBTEST_2(testMatrixType(Matrix3cf()));
00188 CALL_SUBTEST_3(testMatrixType(MatrixXf(8,8)));
00189 CALL_SUBTEST_4(testMatrixType(Matrix2d()));
00190 CALL_SUBTEST_5(testMatrixType(Matrix<double,5,5,RowMajor>()));
00191 CALL_SUBTEST_6(testMatrixType(Matrix4cd()));
00192 CALL_SUBTEST_7(testMatrixType(MatrixXd(13,13)));
00193 }