SparsePermutation.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2012 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. #ifndef EIGEN_SPARSE_PERMUTATION_H
  10. #define EIGEN_SPARSE_PERMUTATION_H
  11. // This file implements sparse * permutation products
  12. namespace Eigen {
  13. namespace internal {
  14. template<typename ExpressionType, int Side, bool Transposed>
  15. struct permutation_matrix_product<ExpressionType, Side, Transposed, SparseShape>
  16. {
  17. typedef typename nested_eval<ExpressionType, 1>::type MatrixType;
  18. typedef typename remove_all<MatrixType>::type MatrixTypeCleaned;
  19. typedef typename MatrixTypeCleaned::Scalar Scalar;
  20. typedef typename MatrixTypeCleaned::StorageIndex StorageIndex;
  21. enum {
  22. SrcStorageOrder = MatrixTypeCleaned::Flags&RowMajorBit ? RowMajor : ColMajor,
  23. MoveOuter = SrcStorageOrder==RowMajor ? Side==OnTheLeft : Side==OnTheRight
  24. };
  25. typedef typename internal::conditional<MoveOuter,
  26. SparseMatrix<Scalar,SrcStorageOrder,StorageIndex>,
  27. SparseMatrix<Scalar,int(SrcStorageOrder)==RowMajor?ColMajor:RowMajor,StorageIndex> >::type ReturnType;
  28. template<typename Dest,typename PermutationType>
  29. static inline void run(Dest& dst, const PermutationType& perm, const ExpressionType& xpr)
  30. {
  31. MatrixType mat(xpr);
  32. if(MoveOuter)
  33. {
  34. SparseMatrix<Scalar,SrcStorageOrder,StorageIndex> tmp(mat.rows(), mat.cols());
  35. Matrix<StorageIndex,Dynamic,1> sizes(mat.outerSize());
  36. for(Index j=0; j<mat.outerSize(); ++j)
  37. {
  38. Index jp = perm.indices().coeff(j);
  39. sizes[((Side==OnTheLeft) ^ Transposed) ? jp : j] = StorageIndex(mat.innerVector(((Side==OnTheRight) ^ Transposed) ? jp : j).nonZeros());
  40. }
  41. tmp.reserve(sizes);
  42. for(Index j=0; j<mat.outerSize(); ++j)
  43. {
  44. Index jp = perm.indices().coeff(j);
  45. Index jsrc = ((Side==OnTheRight) ^ Transposed) ? jp : j;
  46. Index jdst = ((Side==OnTheLeft) ^ Transposed) ? jp : j;
  47. for(typename MatrixTypeCleaned::InnerIterator it(mat,jsrc); it; ++it)
  48. tmp.insertByOuterInner(jdst,it.index()) = it.value();
  49. }
  50. dst = tmp;
  51. }
  52. else
  53. {
  54. SparseMatrix<Scalar,int(SrcStorageOrder)==RowMajor?ColMajor:RowMajor,StorageIndex> tmp(mat.rows(), mat.cols());
  55. Matrix<StorageIndex,Dynamic,1> sizes(tmp.outerSize());
  56. sizes.setZero();
  57. PermutationMatrix<Dynamic,Dynamic,StorageIndex> perm_cpy;
  58. if((Side==OnTheLeft) ^ Transposed)
  59. perm_cpy = perm;
  60. else
  61. perm_cpy = perm.transpose();
  62. for(Index j=0; j<mat.outerSize(); ++j)
  63. for(typename MatrixTypeCleaned::InnerIterator it(mat,j); it; ++it)
  64. sizes[perm_cpy.indices().coeff(it.index())]++;
  65. tmp.reserve(sizes);
  66. for(Index j=0; j<mat.outerSize(); ++j)
  67. for(typename MatrixTypeCleaned::InnerIterator it(mat,j); it; ++it)
  68. tmp.insertByOuterInner(perm_cpy.indices().coeff(it.index()),j) = it.value();
  69. dst = tmp;
  70. }
  71. }
  72. };
  73. }
  74. namespace internal {
  75. template <int ProductTag> struct product_promote_storage_type<Sparse, PermutationStorage, ProductTag> { typedef Sparse ret; };
  76. template <int ProductTag> struct product_promote_storage_type<PermutationStorage, Sparse, ProductTag> { typedef Sparse ret; };
  77. // TODO, the following two overloads are only needed to define the right temporary type through
  78. // typename traits<permutation_sparse_matrix_product<Rhs,Lhs,OnTheRight,false> >::ReturnType
  79. // whereas it should be correctly handled by traits<Product<> >::PlainObject
  80. template<typename Lhs, typename Rhs, int ProductTag>
  81. struct product_evaluator<Product<Lhs, Rhs, AliasFreeProduct>, ProductTag, PermutationShape, SparseShape>
  82. : public evaluator<typename permutation_matrix_product<Rhs,OnTheLeft,false,SparseShape>::ReturnType>
  83. {
  84. typedef Product<Lhs, Rhs, AliasFreeProduct> XprType;
  85. typedef typename permutation_matrix_product<Rhs,OnTheLeft,false,SparseShape>::ReturnType PlainObject;
  86. typedef evaluator<PlainObject> Base;
  87. enum {
  88. Flags = Base::Flags | EvalBeforeNestingBit
  89. };
  90. explicit product_evaluator(const XprType& xpr)
  91. : m_result(xpr.rows(), xpr.cols())
  92. {
  93. ::new (static_cast<Base*>(this)) Base(m_result);
  94. generic_product_impl<Lhs, Rhs, PermutationShape, SparseShape, ProductTag>::evalTo(m_result, xpr.lhs(), xpr.rhs());
  95. }
  96. protected:
  97. PlainObject m_result;
  98. };
  99. template<typename Lhs, typename Rhs, int ProductTag>
  100. struct product_evaluator<Product<Lhs, Rhs, AliasFreeProduct>, ProductTag, SparseShape, PermutationShape >
  101. : public evaluator<typename permutation_matrix_product<Lhs,OnTheRight,false,SparseShape>::ReturnType>
  102. {
  103. typedef Product<Lhs, Rhs, AliasFreeProduct> XprType;
  104. typedef typename permutation_matrix_product<Lhs,OnTheRight,false,SparseShape>::ReturnType PlainObject;
  105. typedef evaluator<PlainObject> Base;
  106. enum {
  107. Flags = Base::Flags | EvalBeforeNestingBit
  108. };
  109. explicit product_evaluator(const XprType& xpr)
  110. : m_result(xpr.rows(), xpr.cols())
  111. {
  112. ::new (static_cast<Base*>(this)) Base(m_result);
  113. generic_product_impl<Lhs, Rhs, SparseShape, PermutationShape, ProductTag>::evalTo(m_result, xpr.lhs(), xpr.rhs());
  114. }
  115. protected:
  116. PlainObject m_result;
  117. };
  118. } // end namespace internal
  119. /** \returns the matrix with the permutation applied to the columns
  120. */
  121. template<typename SparseDerived, typename PermDerived>
  122. inline const Product<SparseDerived, PermDerived, AliasFreeProduct>
  123. operator*(const SparseMatrixBase<SparseDerived>& matrix, const PermutationBase<PermDerived>& perm)
  124. { return Product<SparseDerived, PermDerived, AliasFreeProduct>(matrix.derived(), perm.derived()); }
  125. /** \returns the matrix with the permutation applied to the rows
  126. */
  127. template<typename SparseDerived, typename PermDerived>
  128. inline const Product<PermDerived, SparseDerived, AliasFreeProduct>
  129. operator*( const PermutationBase<PermDerived>& perm, const SparseMatrixBase<SparseDerived>& matrix)
  130. { return Product<PermDerived, SparseDerived, AliasFreeProduct>(perm.derived(), matrix.derived()); }
  131. /** \returns the matrix with the inverse permutation applied to the columns.
  132. */
  133. template<typename SparseDerived, typename PermutationType>
  134. inline const Product<SparseDerived, Inverse<PermutationType>, AliasFreeProduct>
  135. operator*(const SparseMatrixBase<SparseDerived>& matrix, const InverseImpl<PermutationType, PermutationStorage>& tperm)
  136. {
  137. return Product<SparseDerived, Inverse<PermutationType>, AliasFreeProduct>(matrix.derived(), tperm.derived());
  138. }
  139. /** \returns the matrix with the inverse permutation applied to the rows.
  140. */
  141. template<typename SparseDerived, typename PermutationType>
  142. inline const Product<Inverse<PermutationType>, SparseDerived, AliasFreeProduct>
  143. operator*(const InverseImpl<PermutationType,PermutationStorage>& tperm, const SparseMatrixBase<SparseDerived>& matrix)
  144. {
  145. return Product<Inverse<PermutationType>, SparseDerived, AliasFreeProduct>(tperm.derived(), matrix.derived());
  146. }
  147. } // end namespace Eigen
  148. #endif // EIGEN_SPARSE_SELFADJOINTVIEW_H