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.

117 lines
4.4 KiB

  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@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. using namespace std;
  11. template<typename MatrixType> void permutationmatrices(const MatrixType& m)
  12. {
  13. typedef typename MatrixType::Index Index;
  14. typedef typename MatrixType::Scalar Scalar;
  15. typedef typename MatrixType::RealScalar RealScalar;
  16. enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime,
  17. Options = MatrixType::Options };
  18. typedef PermutationMatrix<Rows> LeftPermutationType;
  19. typedef Matrix<int, Rows, 1> LeftPermutationVectorType;
  20. typedef Map<LeftPermutationType> MapLeftPerm;
  21. typedef PermutationMatrix<Cols> RightPermutationType;
  22. typedef Matrix<int, Cols, 1> RightPermutationVectorType;
  23. typedef Map<RightPermutationType> MapRightPerm;
  24. Index rows = m.rows();
  25. Index cols = m.cols();
  26. MatrixType m_original = MatrixType::Random(rows,cols);
  27. LeftPermutationVectorType lv;
  28. randomPermutationVector(lv, rows);
  29. LeftPermutationType lp(lv);
  30. RightPermutationVectorType rv;
  31. randomPermutationVector(rv, cols);
  32. RightPermutationType rp(rv);
  33. MatrixType m_permuted = lp * m_original * rp;
  34. for (int i=0; i<rows; i++)
  35. for (int j=0; j<cols; j++)
  36. VERIFY_IS_APPROX(m_permuted(lv(i),j), m_original(i,rv(j)));
  37. Matrix<Scalar,Rows,Rows> lm(lp);
  38. Matrix<Scalar,Cols,Cols> rm(rp);
  39. VERIFY_IS_APPROX(m_permuted, lm*m_original*rm);
  40. VERIFY_IS_APPROX(lp.inverse()*m_permuted*rp.inverse(), m_original);
  41. VERIFY_IS_APPROX(lv.asPermutation().inverse()*m_permuted*rv.asPermutation().inverse(), m_original);
  42. VERIFY_IS_APPROX(MapLeftPerm(lv.data(),lv.size()).inverse()*m_permuted*MapRightPerm(rv.data(),rv.size()).inverse(), m_original);
  43. VERIFY((lp*lp.inverse()).toDenseMatrix().isIdentity());
  44. VERIFY((lv.asPermutation()*lv.asPermutation().inverse()).toDenseMatrix().isIdentity());
  45. VERIFY((MapLeftPerm(lv.data(),lv.size())*MapLeftPerm(lv.data(),lv.size()).inverse()).toDenseMatrix().isIdentity());
  46. LeftPermutationVectorType lv2;
  47. randomPermutationVector(lv2, rows);
  48. LeftPermutationType lp2(lv2);
  49. Matrix<Scalar,Rows,Rows> lm2(lp2);
  50. VERIFY_IS_APPROX((lp*lp2).toDenseMatrix().template cast<Scalar>(), lm*lm2);
  51. VERIFY_IS_APPROX((lv.asPermutation()*lv2.asPermutation()).toDenseMatrix().template cast<Scalar>(), lm*lm2);
  52. VERIFY_IS_APPROX((MapLeftPerm(lv.data(),lv.size())*MapLeftPerm(lv2.data(),lv2.size())).toDenseMatrix().template cast<Scalar>(), lm*lm2);
  53. LeftPermutationType identityp;
  54. identityp.setIdentity(rows);
  55. VERIFY_IS_APPROX(m_original, identityp*m_original);
  56. // check inplace permutations
  57. m_permuted = m_original;
  58. m_permuted = lp.inverse() * m_permuted;
  59. VERIFY_IS_APPROX(m_permuted, lp.inverse()*m_original);
  60. m_permuted = m_original;
  61. m_permuted = m_permuted * rp.inverse();
  62. VERIFY_IS_APPROX(m_permuted, m_original*rp.inverse());
  63. m_permuted = m_original;
  64. m_permuted = lp * m_permuted;
  65. VERIFY_IS_APPROX(m_permuted, lp*m_original);
  66. m_permuted = m_original;
  67. m_permuted = m_permuted * rp;
  68. VERIFY_IS_APPROX(m_permuted, m_original*rp);
  69. if(rows>1 && cols>1)
  70. {
  71. lp2 = lp;
  72. Index i = internal::random<Index>(0, rows-1);
  73. Index j;
  74. do j = internal::random<Index>(0, rows-1); while(j==i);
  75. lp2.applyTranspositionOnTheLeft(i, j);
  76. lm = lp;
  77. lm.row(i).swap(lm.row(j));
  78. VERIFY_IS_APPROX(lm, lp2.toDenseMatrix().template cast<Scalar>());
  79. RightPermutationType rp2 = rp;
  80. i = internal::random<Index>(0, cols-1);
  81. do j = internal::random<Index>(0, cols-1); while(j==i);
  82. rp2.applyTranspositionOnTheRight(i, j);
  83. rm = rp;
  84. rm.col(i).swap(rm.col(j));
  85. VERIFY_IS_APPROX(rm, rp2.toDenseMatrix().template cast<Scalar>());
  86. }
  87. }
  88. void test_permutationmatrices()
  89. {
  90. for(int i = 0; i < g_repeat; i++) {
  91. CALL_SUBTEST_1( permutationmatrices(Matrix<float, 1, 1>()) );
  92. CALL_SUBTEST_2( permutationmatrices(Matrix3f()) );
  93. CALL_SUBTEST_3( permutationmatrices(Matrix<double,3,3,RowMajor>()) );
  94. CALL_SUBTEST_4( permutationmatrices(Matrix4d()) );
  95. CALL_SUBTEST_5( permutationmatrices(Matrix<double,40,60>()) );
  96. CALL_SUBTEST_6( permutationmatrices(Matrix<double,Dynamic,Dynamic,RowMajor>(20, 30)) );
  97. CALL_SUBTEST_7( permutationmatrices(MatrixXcf(15, 10)) );
  98. }
  99. }