You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
4.2 KiB

  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla
  7. // Public License v. 2.0. If a copy of the MPL was not distributed
  8. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. #include "matrix_functions.h"
  10. template <typename MatrixType, int IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
  11. struct generateTriangularMatrix;
  12. // for real matrices, make sure none of the eigenvalues are negative
  13. template <typename MatrixType>
  14. struct generateTriangularMatrix<MatrixType,0>
  15. {
  16. static void run(MatrixType& result, typename MatrixType::Index size)
  17. {
  18. result.resize(size, size);
  19. result.template triangularView<Upper>() = MatrixType::Random(size, size);
  20. for (typename MatrixType::Index i = 0; i < size; ++i)
  21. result.coeffRef(i,i) = std::abs(result.coeff(i,i));
  22. }
  23. };
  24. // for complex matrices, any matrix is fine
  25. template <typename MatrixType>
  26. struct generateTriangularMatrix<MatrixType,1>
  27. {
  28. static void run(MatrixType& result, typename MatrixType::Index size)
  29. {
  30. result.resize(size, size);
  31. result.template triangularView<Upper>() = MatrixType::Random(size, size);
  32. }
  33. };
  34. template<typename T>
  35. void test2dRotation(double tol)
  36. {
  37. Matrix<T,2,2> A, B, C;
  38. T angle, c, s;
  39. A << 0, 1, -1, 0;
  40. MatrixPower<Matrix<T,2,2> > Apow(A);
  41. for (int i=0; i<=20; ++i) {
  42. angle = pow(10, (i-10) / 5.);
  43. c = std::cos(angle);
  44. s = std::sin(angle);
  45. B << c, s, -s, c;
  46. C = Apow(std::ldexp(angle,1) / M_PI);
  47. std::cout << "test2dRotation: i = " << i << " error powerm = " << relerr(C,B) << '\n';
  48. VERIFY(C.isApprox(B, static_cast<T>(tol)));
  49. }
  50. }
  51. template<typename T>
  52. void test2dHyperbolicRotation(double tol)
  53. {
  54. Matrix<std::complex<T>,2,2> A, B, C;
  55. T angle, ch = std::cosh((T)1);
  56. std::complex<T> ish(0, std::sinh((T)1));
  57. A << ch, ish, -ish, ch;
  58. MatrixPower<Matrix<std::complex<T>,2,2> > Apow(A);
  59. for (int i=0; i<=20; ++i) {
  60. angle = std::ldexp(static_cast<T>(i-10), -1);
  61. ch = std::cosh(angle);
  62. ish = std::complex<T>(0, std::sinh(angle));
  63. B << ch, ish, -ish, ch;
  64. C = Apow(angle);
  65. std::cout << "test2dHyperbolicRotation: i = " << i << " error powerm = " << relerr(C,B) << '\n';
  66. VERIFY(C.isApprox(B, static_cast<T>(tol)));
  67. }
  68. }
  69. template<typename MatrixType>
  70. void testExponentLaws(const MatrixType& m, double tol)
  71. {
  72. typedef typename MatrixType::RealScalar RealScalar;
  73. MatrixType m1, m2, m3, m4, m5;
  74. RealScalar x, y;
  75. for (int i=0; i < g_repeat; ++i) {
  76. generateTestMatrix<MatrixType>::run(m1, m.rows());
  77. MatrixPower<MatrixType> mpow(m1);
  78. x = internal::random<RealScalar>();
  79. y = internal::random<RealScalar>();
  80. m2 = mpow(x);
  81. m3 = mpow(y);
  82. m4 = mpow(x+y);
  83. m5.noalias() = m2 * m3;
  84. VERIFY(m4.isApprox(m5, static_cast<RealScalar>(tol)));
  85. m4 = mpow(x*y);
  86. m5 = m2.pow(y);
  87. VERIFY(m4.isApprox(m5, static_cast<RealScalar>(tol)));
  88. m4 = (std::abs(x) * m1).pow(y);
  89. m5 = std::pow(std::abs(x), y) * m3;
  90. VERIFY(m4.isApprox(m5, static_cast<RealScalar>(tol)));
  91. }
  92. }
  93. typedef Matrix<double,3,3,RowMajor> Matrix3dRowMajor;
  94. typedef Matrix<long double,Dynamic,Dynamic> MatrixXe;
  95. void test_matrix_power()
  96. {
  97. CALL_SUBTEST_2(test2dRotation<double>(1e-13));
  98. CALL_SUBTEST_1(test2dRotation<float>(2e-5)); // was 1e-5, relaxed for clang 2.8 / linux / x86-64
  99. CALL_SUBTEST_9(test2dRotation<long double>(1e-13));
  100. CALL_SUBTEST_2(test2dHyperbolicRotation<double>(1e-14));
  101. CALL_SUBTEST_1(test2dHyperbolicRotation<float>(1e-5));
  102. CALL_SUBTEST_9(test2dHyperbolicRotation<long double>(1e-14));
  103. CALL_SUBTEST_2(testExponentLaws(Matrix2d(), 1e-13));
  104. CALL_SUBTEST_7(testExponentLaws(Matrix3dRowMajor(), 1e-13));
  105. CALL_SUBTEST_3(testExponentLaws(Matrix4cd(), 1e-13));
  106. CALL_SUBTEST_4(testExponentLaws(MatrixXd(8,8), 2e-12));
  107. CALL_SUBTEST_1(testExponentLaws(Matrix2f(), 1e-4));
  108. CALL_SUBTEST_5(testExponentLaws(Matrix3cf(), 1e-4));
  109. CALL_SUBTEST_8(testExponentLaws(Matrix4f(), 1e-4));
  110. CALL_SUBTEST_6(testExponentLaws(MatrixXf(2,2), 1e-3)); // see bug 614
  111. CALL_SUBTEST_9(testExponentLaws(MatrixXe(7,7), 1e-13));
  112. }