SparsePermutation.h 7.16 KB
Newer Older
Don Gagne's avatar
Don Gagne committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef EIGEN_SPARSE_PERMUTATION_H
#define EIGEN_SPARSE_PERMUTATION_H

// This file implements sparse * permutation products

namespace Eigen { 

namespace internal {

19 20
template<typename ExpressionType, int Side, bool Transposed>
struct permutation_matrix_product<ExpressionType, Side, Transposed, SparseShape>
Don Gagne's avatar
Don Gagne committed
21
{
22 23
    typedef typename nested_eval<ExpressionType, 1>::type MatrixType;
    typedef typename remove_all<MatrixType>::type MatrixTypeCleaned;
Don Gagne's avatar
Don Gagne committed
24

25 26
    typedef typename MatrixTypeCleaned::Scalar Scalar;
    typedef typename MatrixTypeCleaned::StorageIndex StorageIndex;
Don Gagne's avatar
Don Gagne committed
27 28

    enum {
29
      SrcStorageOrder = MatrixTypeCleaned::Flags&RowMajorBit ? RowMajor : ColMajor,
Don Gagne's avatar
Don Gagne committed
30 31
      MoveOuter = SrcStorageOrder==RowMajor ? Side==OnTheLeft : Side==OnTheRight
    };
32 33 34 35
    
    typedef typename internal::conditional<MoveOuter,
        SparseMatrix<Scalar,SrcStorageOrder,StorageIndex>,
        SparseMatrix<Scalar,int(SrcStorageOrder)==RowMajor?ColMajor:RowMajor,StorageIndex> >::type ReturnType;
Don Gagne's avatar
Don Gagne committed
36

37 38
    template<typename Dest,typename PermutationType>
    static inline void run(Dest& dst, const PermutationType& perm, const ExpressionType& xpr)
Don Gagne's avatar
Don Gagne committed
39
    {
40
      MatrixType mat(xpr);
Don Gagne's avatar
Don Gagne committed
41 42
      if(MoveOuter)
      {
43 44 45
        SparseMatrix<Scalar,SrcStorageOrder,StorageIndex> tmp(mat.rows(), mat.cols());
        Matrix<StorageIndex,Dynamic,1> sizes(mat.outerSize());
        for(Index j=0; j<mat.outerSize(); ++j)
Don Gagne's avatar
Don Gagne committed
46
        {
47 48
          Index jp = perm.indices().coeff(j);
          sizes[((Side==OnTheLeft) ^ Transposed) ? jp : j] = StorageIndex(mat.innerVector(((Side==OnTheRight) ^ Transposed) ? jp : j).nonZeros());
Don Gagne's avatar
Don Gagne committed
49 50
        }
        tmp.reserve(sizes);
51
        for(Index j=0; j<mat.outerSize(); ++j)
Don Gagne's avatar
Don Gagne committed
52
        {
53
          Index jp = perm.indices().coeff(j);
Don Gagne's avatar
Don Gagne committed
54 55
          Index jsrc = ((Side==OnTheRight) ^ Transposed) ? jp : j;
          Index jdst = ((Side==OnTheLeft) ^ Transposed) ? jp : j;
56
          for(typename MatrixTypeCleaned::InnerIterator it(mat,jsrc); it; ++it)
Don Gagne's avatar
Don Gagne committed
57 58 59 60 61 62
            tmp.insertByOuterInner(jdst,it.index()) = it.value();
        }
        dst = tmp;
      }
      else
      {
63 64
        SparseMatrix<Scalar,int(SrcStorageOrder)==RowMajor?ColMajor:RowMajor,StorageIndex> tmp(mat.rows(), mat.cols());
        Matrix<StorageIndex,Dynamic,1> sizes(tmp.outerSize());
Don Gagne's avatar
Don Gagne committed
65
        sizes.setZero();
66
        PermutationMatrix<Dynamic,Dynamic,StorageIndex> perm_cpy;
Don Gagne's avatar
Don Gagne committed
67
        if((Side==OnTheLeft) ^ Transposed)
68
          perm_cpy = perm;
Don Gagne's avatar
Don Gagne committed
69
        else
70
          perm_cpy = perm.transpose();
Don Gagne's avatar
Don Gagne committed
71

72 73 74
        for(Index j=0; j<mat.outerSize(); ++j)
          for(typename MatrixTypeCleaned::InnerIterator it(mat,j); it; ++it)
            sizes[perm_cpy.indices().coeff(it.index())]++;
Don Gagne's avatar
Don Gagne committed
75
        tmp.reserve(sizes);
76 77 78
        for(Index j=0; j<mat.outerSize(); ++j)
          for(typename MatrixTypeCleaned::InnerIterator it(mat,j); it; ++it)
            tmp.insertByOuterInner(perm_cpy.indices().coeff(it.index()),j) = it.value();
Don Gagne's avatar
Don Gagne committed
79 80 81 82 83 84 85
        dst = tmp;
      }
    }
};

}

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
namespace internal {

template <int ProductTag> struct product_promote_storage_type<Sparse,             PermutationStorage, ProductTag> { typedef Sparse ret; };
template <int ProductTag> struct product_promote_storage_type<PermutationStorage, Sparse,             ProductTag> { typedef Sparse ret; };

// TODO, the following two overloads are only needed to define the right temporary type through 
// typename traits<permutation_sparse_matrix_product<Rhs,Lhs,OnTheRight,false> >::ReturnType
// whereas it should be correctly handled by traits<Product<> >::PlainObject

template<typename Lhs, typename Rhs, int ProductTag>
struct product_evaluator<Product<Lhs, Rhs, AliasFreeProduct>, ProductTag, PermutationShape, SparseShape>
  : public evaluator<typename permutation_matrix_product<Rhs,OnTheLeft,false,SparseShape>::ReturnType>
{
  typedef Product<Lhs, Rhs, AliasFreeProduct> XprType;
  typedef typename permutation_matrix_product<Rhs,OnTheLeft,false,SparseShape>::ReturnType PlainObject;
  typedef evaluator<PlainObject> Base;

  enum {
    Flags = Base::Flags | EvalBeforeNestingBit
  };

  explicit product_evaluator(const XprType& xpr)
    : m_result(xpr.rows(), xpr.cols())
  {
    ::new (static_cast<Base*>(this)) Base(m_result);
    generic_product_impl<Lhs, Rhs, PermutationShape, SparseShape, ProductTag>::evalTo(m_result, xpr.lhs(), xpr.rhs());
  }
Don Gagne's avatar
Don Gagne committed
113

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
protected:
  PlainObject m_result;
};

template<typename Lhs, typename Rhs, int ProductTag>
struct product_evaluator<Product<Lhs, Rhs, AliasFreeProduct>, ProductTag, SparseShape, PermutationShape >
  : public evaluator<typename permutation_matrix_product<Lhs,OnTheRight,false,SparseShape>::ReturnType>
{
  typedef Product<Lhs, Rhs, AliasFreeProduct> XprType;
  typedef typename permutation_matrix_product<Lhs,OnTheRight,false,SparseShape>::ReturnType PlainObject;
  typedef evaluator<PlainObject> Base;

  enum {
    Flags = Base::Flags | EvalBeforeNestingBit
  };

  explicit product_evaluator(const XprType& xpr)
    : m_result(xpr.rows(), xpr.cols())
  {
    ::new (static_cast<Base*>(this)) Base(m_result);
    generic_product_impl<Lhs, Rhs, SparseShape, PermutationShape, ProductTag>::evalTo(m_result, xpr.lhs(), xpr.rhs());
  }

protected:
  PlainObject m_result;
};

} // end namespace internal
Don Gagne's avatar
Don Gagne committed
142 143 144 145

/** \returns the matrix with the permutation applied to the columns
  */
template<typename SparseDerived, typename PermDerived>
146
inline const Product<SparseDerived, PermDerived, AliasFreeProduct>
Don Gagne's avatar
Don Gagne committed
147
operator*(const SparseMatrixBase<SparseDerived>& matrix, const PermutationBase<PermDerived>& perm)
148
{ return Product<SparseDerived, PermDerived, AliasFreeProduct>(matrix.derived(), perm.derived()); }
Don Gagne's avatar
Don Gagne committed
149 150 151 152

/** \returns the matrix with the permutation applied to the rows
  */
template<typename SparseDerived, typename PermDerived>
153
inline const Product<PermDerived, SparseDerived, AliasFreeProduct>
Don Gagne's avatar
Don Gagne committed
154
operator*( const PermutationBase<PermDerived>& perm, const SparseMatrixBase<SparseDerived>& matrix)
155
{ return  Product<PermDerived, SparseDerived, AliasFreeProduct>(perm.derived(), matrix.derived()); }
Don Gagne's avatar
Don Gagne committed
156 157 158 159


/** \returns the matrix with the inverse permutation applied to the columns.
  */
160 161 162
template<typename SparseDerived, typename PermutationType>
inline const Product<SparseDerived, Inverse<PermutationType>, AliasFreeProduct>
operator*(const SparseMatrixBase<SparseDerived>& matrix, const InverseImpl<PermutationType, PermutationStorage>& tperm)
Don Gagne's avatar
Don Gagne committed
163
{
164
  return Product<SparseDerived, Inverse<PermutationType>, AliasFreeProduct>(matrix.derived(), tperm.derived());
Don Gagne's avatar
Don Gagne committed
165 166 167 168
}

/** \returns the matrix with the inverse permutation applied to the rows.
  */
169 170 171
template<typename SparseDerived, typename PermutationType>
inline const Product<Inverse<PermutationType>, SparseDerived, AliasFreeProduct>
operator*(const InverseImpl<PermutationType,PermutationStorage>& tperm, const SparseMatrixBase<SparseDerived>& matrix)
Don Gagne's avatar
Don Gagne committed
172
{
173
  return Product<Inverse<PermutationType>, SparseDerived, AliasFreeProduct>(tperm.derived(), matrix.derived());
Don Gagne's avatar
Don Gagne committed
174 175 176 177 178
}

} // end namespace Eigen

#endif // EIGEN_SPARSE_SELFADJOINTVIEW_H