00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "matrix_functions.h"
00011
00012 template <typename MatrixType, int IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
00013 struct generateTriangularMatrix;
00014
00015
00016 template <typename MatrixType>
00017 struct generateTriangularMatrix<MatrixType,0>
00018 {
00019 static void run(MatrixType& result, typename MatrixType::Index size)
00020 {
00021 result.resize(size, size);
00022 result.template triangularView<Upper>() = MatrixType::Random(size, size);
00023 for (typename MatrixType::Index i = 0; i < size; ++i)
00024 result.coeffRef(i,i) = std::abs(result.coeff(i,i));
00025 }
00026 };
00027
00028
00029 template <typename MatrixType>
00030 struct generateTriangularMatrix<MatrixType,1>
00031 {
00032 static void run(MatrixType& result, typename MatrixType::Index size)
00033 {
00034 result.resize(size, size);
00035 result.template triangularView<Upper>() = MatrixType::Random(size, size);
00036 }
00037 };
00038
00039 template<typename T>
00040 void test2dRotation(double tol)
00041 {
00042 Matrix<T,2,2> A, B, C;
00043 T angle, c, s;
00044
00045 A << 0, 1, -1, 0;
00046 MatrixPower<Matrix<T,2,2> > Apow(A);
00047
00048 for (int i=0; i<=20; ++i) {
00049 angle = pow(10, (i-10) / 5.);
00050 c = std::cos(angle);
00051 s = std::sin(angle);
00052 B << c, s, -s, c;
00053
00054 C = Apow(std::ldexp(angle,1) / M_PI);
00055 std::cout << "test2dRotation: i = " << i << " error powerm = " << relerr(C,B) << '\n';
00056 VERIFY(C.isApprox(B, static_cast<T>(tol)));
00057 }
00058 }
00059
00060 template<typename T>
00061 void test2dHyperbolicRotation(double tol)
00062 {
00063 Matrix<std::complex<T>,2,2> A, B, C;
00064 T angle, ch = std::cosh((T)1);
00065 std::complex<T> ish(0, std::sinh((T)1));
00066
00067 A << ch, ish, -ish, ch;
00068 MatrixPower<Matrix<std::complex<T>,2,2> > Apow(A);
00069
00070 for (int i=0; i<=20; ++i) {
00071 angle = std::ldexp(static_cast<T>(i-10), -1);
00072 ch = std::cosh(angle);
00073 ish = std::complex<T>(0, std::sinh(angle));
00074 B << ch, ish, -ish, ch;
00075
00076 C = Apow(angle);
00077 std::cout << "test2dHyperbolicRotation: i = " << i << " error powerm = " << relerr(C,B) << '\n';
00078 VERIFY(C.isApprox(B, static_cast<T>(tol)));
00079 }
00080 }
00081
00082 template<typename MatrixType>
00083 void testExponentLaws(const MatrixType& m, double tol)
00084 {
00085 typedef typename MatrixType::RealScalar RealScalar;
00086 MatrixType m1, m2, m3, m4, m5;
00087 RealScalar x, y;
00088
00089 for (int i=0; i < g_repeat; ++i) {
00090 generateTestMatrix<MatrixType>::run(m1, m.rows());
00091 MatrixPower<MatrixType> mpow(m1);
00092
00093 x = internal::random<RealScalar>();
00094 y = internal::random<RealScalar>();
00095 m2 = mpow(x);
00096 m3 = mpow(y);
00097
00098 m4 = mpow(x+y);
00099 m5.noalias() = m2 * m3;
00100 VERIFY(m4.isApprox(m5, static_cast<RealScalar>(tol)));
00101
00102 m4 = mpow(x*y);
00103 m5 = m2.pow(y);
00104 VERIFY(m4.isApprox(m5, static_cast<RealScalar>(tol)));
00105
00106 m4 = (std::abs(x) * m1).pow(y);
00107 m5 = std::pow(std::abs(x), y) * m3;
00108 VERIFY(m4.isApprox(m5, static_cast<RealScalar>(tol)));
00109 }
00110 }
00111
00112 typedef Matrix<double,3,3,RowMajor> Matrix3dRowMajor;
00113 typedef Matrix<long double,Dynamic,Dynamic> MatrixXe;
00114
00115 void test_matrix_power()
00116 {
00117 CALL_SUBTEST_2(test2dRotation<double>(1e-13));
00118 CALL_SUBTEST_1(test2dRotation<float>(2e-5));
00119 CALL_SUBTEST_9(test2dRotation<long double>(1e-13));
00120 CALL_SUBTEST_2(test2dHyperbolicRotation<double>(1e-14));
00121 CALL_SUBTEST_1(test2dHyperbolicRotation<float>(1e-5));
00122 CALL_SUBTEST_9(test2dHyperbolicRotation<long double>(1e-14));
00123
00124 CALL_SUBTEST_2(testExponentLaws(Matrix2d(), 1e-13));
00125 CALL_SUBTEST_7(testExponentLaws(Matrix3dRowMajor(), 1e-13));
00126 CALL_SUBTEST_3(testExponentLaws(Matrix4cd(), 1e-13));
00127 CALL_SUBTEST_4(testExponentLaws(MatrixXd(8,8), 2e-12));
00128 CALL_SUBTEST_1(testExponentLaws(Matrix2f(), 1e-4));
00129 CALL_SUBTEST_5(testExponentLaws(Matrix3cf(), 1e-4));
00130 CALL_SUBTEST_8(testExponentLaws(Matrix4f(), 1e-4));
00131 CALL_SUBTEST_6(testExponentLaws(MatrixXf(2,2), 1e-3));
00132 CALL_SUBTEST_9(testExponentLaws(MatrixXe(7,7), 1e-13));
00133 }