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.

235 lines
8.4 KiB

  1. // This file is triangularView of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
  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_square(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. typename MatrixType::Index rows = m.rows();
  17. typename MatrixType::Index 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. VectorType v2 = VectorType::Random(rows);
  25. MatrixType m1up = m1.template triangularView<Upper>();
  26. MatrixType m2up = m2.template triangularView<Upper>();
  27. if (rows*cols>1)
  28. {
  29. VERIFY(m1up.isUpperTriangular());
  30. VERIFY(m2up.transpose().isLowerTriangular());
  31. VERIFY(!m2.isLowerTriangular());
  32. }
  33. // VERIFY_IS_APPROX(m1up.transpose() * m2, m1.upper().transpose().lower() * m2);
  34. // test overloaded operator+=
  35. r1.setZero();
  36. r2.setZero();
  37. r1.template triangularView<Upper>() += m1;
  38. r2 += m1up;
  39. VERIFY_IS_APPROX(r1,r2);
  40. // test overloaded operator=
  41. m1.setZero();
  42. m1.template triangularView<Upper>() = m2.transpose() + m2;
  43. m3 = m2.transpose() + m2;
  44. VERIFY_IS_APPROX(m3.template triangularView<Lower>().transpose().toDenseMatrix(), m1);
  45. // test overloaded operator=
  46. m1.setZero();
  47. m1.template triangularView<Lower>() = m2.transpose() + m2;
  48. VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);
  49. VERIFY_IS_APPROX(m3.template triangularView<Lower>().conjugate().toDenseMatrix(),
  50. m3.conjugate().template triangularView<Lower>().toDenseMatrix());
  51. m1 = MatrixType::Random(rows, cols);
  52. for (int i=0; i<rows; ++i)
  53. while (internal::abs2(m1(i,i))<1e-1) m1(i,i) = internal::random<Scalar>();
  54. Transpose<MatrixType> trm4(m4);
  55. // test back and forward subsitution with a vector as the rhs
  56. m3 = m1.template triangularView<Upper>();
  57. VERIFY(v2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(v2)), largerEps));
  58. m3 = m1.template triangularView<Lower>();
  59. VERIFY(v2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(v2)), largerEps));
  60. m3 = m1.template triangularView<Upper>();
  61. VERIFY(v2.isApprox(m3 * (m1.template triangularView<Upper>().solve(v2)), largerEps));
  62. m3 = m1.template triangularView<Lower>();
  63. VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(v2)), largerEps));
  64. // test back and forward subsitution with a matrix as the rhs
  65. m3 = m1.template triangularView<Upper>();
  66. VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(m2)), largerEps));
  67. m3 = m1.template triangularView<Lower>();
  68. VERIFY(m2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(m2)), largerEps));
  69. m3 = m1.template triangularView<Upper>();
  70. VERIFY(m2.isApprox(m3 * (m1.template triangularView<Upper>().solve(m2)), largerEps));
  71. m3 = m1.template triangularView<Lower>();
  72. VERIFY(m2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(m2)), largerEps));
  73. // check M * inv(L) using in place API
  74. m4 = m3;
  75. m1.transpose().template triangularView<Eigen::Upper>().solveInPlace(trm4);
  76. VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Lower>(), m3);
  77. // check M * inv(U) using in place API
  78. m3 = m1.template triangularView<Upper>();
  79. m4 = m3;
  80. m3.transpose().template triangularView<Eigen::Lower>().solveInPlace(trm4);
  81. VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Upper>(), m3);
  82. // check solve with unit diagonal
  83. m3 = m1.template triangularView<UnitUpper>();
  84. VERIFY(m2.isApprox(m3 * (m1.template triangularView<UnitUpper>().solve(m2)), largerEps));
  85. // VERIFY(( m1.template triangularView<Upper>()
  86. // * m2.template triangularView<Upper>()).isUpperTriangular());
  87. // test swap
  88. m1.setOnes();
  89. m2.setZero();
  90. m2.template triangularView<Upper>().swap(m1);
  91. m3.setZero();
  92. m3.template triangularView<Upper>().setOnes();
  93. VERIFY_IS_APPROX(m2,m3);
  94. }
  95. template<typename MatrixType> void triangular_rect(const MatrixType& m)
  96. {
  97. typedef const typename MatrixType::Index Index;
  98. typedef typename MatrixType::Scalar Scalar;
  99. typedef typename NumTraits<Scalar>::Real RealScalar;
  100. enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
  101. typedef Matrix<Scalar, Rows, 1> VectorType;
  102. typedef Matrix<Scalar, Rows, Rows> RMatrixType;
  103. Index rows = m.rows();
  104. Index cols = m.cols();
  105. MatrixType m1 = MatrixType::Random(rows, cols),
  106. m2 = MatrixType::Random(rows, cols),
  107. m3(rows, cols),
  108. m4(rows, cols),
  109. r1(rows, cols),
  110. r2(rows, cols);
  111. MatrixType m1up = m1.template triangularView<Upper>();
  112. MatrixType m2up = m2.template triangularView<Upper>();
  113. if (rows>1 && cols>1)
  114. {
  115. VERIFY(m1up.isUpperTriangular());
  116. VERIFY(m2up.transpose().isLowerTriangular());
  117. VERIFY(!m2.isLowerTriangular());
  118. }
  119. // test overloaded operator+=
  120. r1.setZero();
  121. r2.setZero();
  122. r1.template triangularView<Upper>() += m1;
  123. r2 += m1up;
  124. VERIFY_IS_APPROX(r1,r2);
  125. // test overloaded operator=
  126. m1.setZero();
  127. m1.template triangularView<Upper>() = 3 * m2;
  128. m3 = 3 * m2;
  129. VERIFY_IS_APPROX(m3.template triangularView<Upper>().toDenseMatrix(), m1);
  130. m1.setZero();
  131. m1.template triangularView<Lower>() = 3 * m2;
  132. VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);
  133. m1.setZero();
  134. m1.template triangularView<StrictlyUpper>() = 3 * m2;
  135. VERIFY_IS_APPROX(m3.template triangularView<StrictlyUpper>().toDenseMatrix(), m1);
  136. m1.setZero();
  137. m1.template triangularView<StrictlyLower>() = 3 * m2;
  138. VERIFY_IS_APPROX(m3.template triangularView<StrictlyLower>().toDenseMatrix(), m1);
  139. m1.setRandom();
  140. m2 = m1.template triangularView<Upper>();
  141. VERIFY(m2.isUpperTriangular());
  142. VERIFY(!m2.isLowerTriangular());
  143. m2 = m1.template triangularView<StrictlyUpper>();
  144. VERIFY(m2.isUpperTriangular());
  145. VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  146. m2 = m1.template triangularView<UnitUpper>();
  147. VERIFY(m2.isUpperTriangular());
  148. m2.diagonal().array() -= Scalar(1);
  149. VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  150. m2 = m1.template triangularView<Lower>();
  151. VERIFY(m2.isLowerTriangular());
  152. VERIFY(!m2.isUpperTriangular());
  153. m2 = m1.template triangularView<StrictlyLower>();
  154. VERIFY(m2.isLowerTriangular());
  155. VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  156. m2 = m1.template triangularView<UnitLower>();
  157. VERIFY(m2.isLowerTriangular());
  158. m2.diagonal().array() -= Scalar(1);
  159. VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  160. // test swap
  161. m1.setOnes();
  162. m2.setZero();
  163. m2.template triangularView<Upper>().swap(m1);
  164. m3.setZero();
  165. m3.template triangularView<Upper>().setOnes();
  166. VERIFY_IS_APPROX(m2,m3);
  167. }
  168. void bug_159()
  169. {
  170. Matrix3d m = Matrix3d::Random().triangularView<Lower>();
  171. EIGEN_UNUSED_VARIABLE(m)
  172. }
  173. void test_triangular()
  174. {
  175. int maxsize = (std::min)(EIGEN_TEST_MAX_SIZE,20);
  176. for(int i = 0; i < g_repeat ; i++)
  177. {
  178. int r = internal::random<int>(2,maxsize); EIGEN_UNUSED_VARIABLE(r);
  179. int c = internal::random<int>(2,maxsize); EIGEN_UNUSED_VARIABLE(c);
  180. CALL_SUBTEST_1( triangular_square(Matrix<float, 1, 1>()) );
  181. CALL_SUBTEST_2( triangular_square(Matrix<float, 2, 2>()) );
  182. CALL_SUBTEST_3( triangular_square(Matrix3d()) );
  183. CALL_SUBTEST_4( triangular_square(Matrix<std::complex<float>,8, 8>()) );
  184. CALL_SUBTEST_5( triangular_square(MatrixXcd(r,r)) );
  185. CALL_SUBTEST_6( triangular_square(Matrix<float,Dynamic,Dynamic,RowMajor>(r, r)) );
  186. CALL_SUBTEST_7( triangular_rect(Matrix<float, 4, 5>()) );
  187. CALL_SUBTEST_8( triangular_rect(Matrix<double, 6, 2>()) );
  188. CALL_SUBTEST_9( triangular_rect(MatrixXcf(r, c)) );
  189. CALL_SUBTEST_5( triangular_rect(MatrixXcd(r, c)) );
  190. CALL_SUBTEST_6( triangular_rect(Matrix<float,Dynamic,Dynamic,RowMajor>(r, c)) );
  191. }
  192. CALL_SUBTEST_1( bug_159() );
  193. }