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