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.

158 lines
5.6 KiB

  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra. Eigen itself is part of the KDE project.
  3. //
  4. // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@gmail.com>
  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 "main.h"
  10. template<typename MatrixType> void triangular(const MatrixType& m)
  11. {
  12. typedef typename MatrixType::Scalar Scalar;
  13. typedef typename NumTraits<Scalar>::Real RealScalar;
  14. typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  15. RealScalar largerEps = 10*test_precision<RealScalar>();
  16. int rows = m.rows();
  17. int cols = m.cols();
  18. MatrixType m1 = MatrixType::Random(rows, cols),
  19. m2 = MatrixType::Random(rows, cols),
  20. m3(rows, cols),
  21. m4(rows, cols),
  22. r1(rows, cols),
  23. r2(rows, cols),
  24. mzero = MatrixType::Zero(rows, cols),
  25. mones = MatrixType::Ones(rows, cols),
  26. identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
  27. ::Identity(rows, rows),
  28. square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
  29. ::Random(rows, rows);
  30. VectorType v1 = VectorType::Random(rows),
  31. v2 = VectorType::Random(rows),
  32. vzero = VectorType::Zero(rows);
  33. MatrixType m1up = m1.template part<Eigen::UpperTriangular>();
  34. MatrixType m2up = m2.template part<Eigen::UpperTriangular>();
  35. if (rows*cols>1)
  36. {
  37. VERIFY(m1up.isUpperTriangular());
  38. VERIFY(m2up.transpose().isLowerTriangular());
  39. VERIFY(!m2.isLowerTriangular());
  40. }
  41. // VERIFY_IS_APPROX(m1up.transpose() * m2, m1.upper().transpose().lower() * m2);
  42. // test overloaded operator+=
  43. r1.setZero();
  44. r2.setZero();
  45. r1.template part<Eigen::UpperTriangular>() += m1;
  46. r2 += m1up;
  47. VERIFY_IS_APPROX(r1,r2);
  48. // test overloaded operator=
  49. m1.setZero();
  50. m1.template part<Eigen::UpperTriangular>() = (m2.transpose() * m2).lazy();
  51. m3 = m2.transpose() * m2;
  52. VERIFY_IS_APPROX(m3.template part<Eigen::LowerTriangular>().transpose(), m1);
  53. // test overloaded operator=
  54. m1.setZero();
  55. m1.template part<Eigen::LowerTriangular>() = (m2.transpose() * m2).lazy();
  56. VERIFY_IS_APPROX(m3.template part<Eigen::LowerTriangular>(), m1);
  57. VERIFY_IS_APPROX(m3.template part<Diagonal>(), m3.diagonal().asDiagonal());
  58. m1 = MatrixType::Random(rows, cols);
  59. for (int i=0; i<rows; ++i)
  60. while (ei_abs2(m1(i,i))<1e-3) m1(i,i) = ei_random<Scalar>();
  61. Transpose<MatrixType> trm4(m4);
  62. // test back and forward subsitution
  63. m3 = m1.template part<Eigen::LowerTriangular>();
  64. VERIFY(m3.template marked<Eigen::LowerTriangular>().solveTriangular(m3).cwise().abs().isIdentity(test_precision<RealScalar>()));
  65. VERIFY(m3.transpose().template marked<Eigen::UpperTriangular>()
  66. .solveTriangular(m3.transpose()).cwise().abs().isIdentity(test_precision<RealScalar>()));
  67. // check M * inv(L) using in place API
  68. m4 = m3;
  69. m3.transpose().template marked<Eigen::UpperTriangular>().solveTriangularInPlace(trm4);
  70. VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>()));
  71. m3 = m1.template part<Eigen::UpperTriangular>();
  72. VERIFY(m3.template marked<Eigen::UpperTriangular>().solveTriangular(m3).cwise().abs().isIdentity(test_precision<RealScalar>()));
  73. VERIFY(m3.transpose().template marked<Eigen::LowerTriangular>()
  74. .solveTriangular(m3.transpose()).cwise().abs().isIdentity(test_precision<RealScalar>()));
  75. // check M * inv(U) using in place API
  76. m4 = m3;
  77. m3.transpose().template marked<Eigen::LowerTriangular>().solveTriangularInPlace(trm4);
  78. VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>()));
  79. m3 = m1.template part<Eigen::UpperTriangular>();
  80. VERIFY(m2.isApprox(m3 * (m3.template marked<Eigen::UpperTriangular>().solveTriangular(m2)), largerEps));
  81. m3 = m1.template part<Eigen::LowerTriangular>();
  82. VERIFY(m2.isApprox(m3 * (m3.template marked<Eigen::LowerTriangular>().solveTriangular(m2)), largerEps));
  83. VERIFY((m1.template part<Eigen::UpperTriangular>() * m2.template part<Eigen::UpperTriangular>()).isUpperTriangular());
  84. // test swap
  85. m1.setOnes();
  86. m2.setZero();
  87. m2.template part<Eigen::UpperTriangular>().swap(m1);
  88. m3.setZero();
  89. m3.template part<Eigen::UpperTriangular>().setOnes();
  90. VERIFY_IS_APPROX(m2,m3);
  91. }
  92. void selfadjoint()
  93. {
  94. Matrix2i m;
  95. m << 1, 2,
  96. 3, 4;
  97. Matrix2i m1 = Matrix2i::Zero();
  98. m1.part<SelfAdjoint>() = m;
  99. Matrix2i ref1;
  100. ref1 << 1, 2,
  101. 2, 4;
  102. VERIFY(m1 == ref1);
  103. Matrix2i m2 = Matrix2i::Zero();
  104. m2.part<SelfAdjoint>() = m.part<UpperTriangular>();
  105. Matrix2i ref2;
  106. ref2 << 1, 2,
  107. 2, 4;
  108. VERIFY(m2 == ref2);
  109. Matrix2i m3 = Matrix2i::Zero();
  110. m3.part<SelfAdjoint>() = m.part<LowerTriangular>();
  111. Matrix2i ref3;
  112. ref3 << 1, 0,
  113. 0, 4;
  114. VERIFY(m3 == ref3);
  115. // example inspired from bug 159
  116. int array[] = {1, 2, 3, 4};
  117. Matrix2i::Map(array).part<SelfAdjoint>() = Matrix2i::Random().part<LowerTriangular>();
  118. std::cout << "hello\n" << array << std::endl;
  119. }
  120. void test_eigen2_triangular()
  121. {
  122. CALL_SUBTEST_8( selfadjoint() );
  123. for(int i = 0; i < g_repeat ; i++) {
  124. CALL_SUBTEST_1( triangular(Matrix<float, 1, 1>()) );
  125. CALL_SUBTEST_2( triangular(Matrix<float, 2, 2>()) );
  126. CALL_SUBTEST_3( triangular(Matrix3d()) );
  127. CALL_SUBTEST_4( triangular(MatrixXcf(4, 4)) );
  128. CALL_SUBTEST_5( triangular(Matrix<std::complex<float>,8, 8>()) );
  129. CALL_SUBTEST_6( triangular(MatrixXd(17,17)) );
  130. CALL_SUBTEST_7( triangular(Matrix<float,Dynamic,Dynamic,RowMajor>(5, 5)) );
  131. }
  132. }