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.

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