Home | History | Annotate | Download | only in KroneckerProduct
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2011 Kolja Brix <brix (at) igpm.rwth-aachen.de>
      5 // Copyright (C) 2011 Andreas Platen <andiplaten (at) gmx.de>
      6 //
      7 // This Source Code Form is subject to the terms of the Mozilla
      8 // Public License v. 2.0. If a copy of the MPL was not distributed
      9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     10 
     11 
     12 #ifndef KRONECKER_TENSOR_PRODUCT_H
     13 #define KRONECKER_TENSOR_PRODUCT_H
     14 
     15 
     16 namespace Eigen {
     17 
     18 namespace internal {
     19 
     20 /*!
     21  * Kronecker tensor product helper function for dense matrices
     22  *
     23  * \param A   Dense matrix A
     24  * \param B   Dense matrix B
     25  * \param AB_ Kronecker tensor product of A and B
     26  */
     27 template<typename Derived_A, typename Derived_B, typename Derived_AB>
     28 void kroneckerProduct_full(const Derived_A& A, const Derived_B& B, Derived_AB & AB)
     29 {
     30   const unsigned int Ar = A.rows(),
     31                      Ac = A.cols(),
     32                      Br = B.rows(),
     33                      Bc = B.cols();
     34   for (unsigned int i=0; i<Ar; ++i)
     35     for (unsigned int j=0; j<Ac; ++j)
     36       AB.block(i*Br,j*Bc,Br,Bc) = A(i,j)*B;
     37 }
     38 
     39 
     40 /*!
     41  * Kronecker tensor product helper function for matrices, where at least one is sparse
     42  *
     43  * \param A   Matrix A
     44  * \param B   Matrix B
     45  * \param AB_ Kronecker tensor product of A and B
     46  */
     47 template<typename Derived_A, typename Derived_B, typename Derived_AB>
     48 void kroneckerProduct_sparse(const Derived_A &A, const Derived_B &B, Derived_AB &AB)
     49 {
     50   const unsigned int Ar = A.rows(),
     51                      Ac = A.cols(),
     52                      Br = B.rows(),
     53                      Bc = B.cols();
     54   AB.resize(Ar*Br,Ac*Bc);
     55   AB.resizeNonZeros(0);
     56   AB.reserve(A.nonZeros()*B.nonZeros());
     57 
     58   for (int kA=0; kA<A.outerSize(); ++kA)
     59   {
     60     for (int kB=0; kB<B.outerSize(); ++kB)
     61     {
     62       for (typename Derived_A::InnerIterator itA(A,kA); itA; ++itA)
     63       {
     64         for (typename Derived_B::InnerIterator itB(B,kB); itB; ++itB)
     65         {
     66           const unsigned int iA = itA.row(),
     67                              jA = itA.col(),
     68                              iB = itB.row(),
     69                              jB = itB.col(),
     70                              i  = iA*Br + iB,
     71                              j  = jA*Bc + jB;
     72           AB.insert(i,j) = itA.value() * itB.value();
     73         }
     74       }
     75     }
     76   }
     77 }
     78 
     79 } // end namespace internal
     80 
     81 
     82 
     83 /*!
     84  * Computes Kronecker tensor product of two dense matrices
     85  *
     86  * \param a  Dense matrix a
     87  * \param b  Dense matrix b
     88  * \param c  Kronecker tensor product of a and b
     89  */
     90 template<typename A,typename B,typename CScalar,int CRows,int CCols, int COptions, int CMaxRows, int CMaxCols>
     91 void kroneckerProduct(const MatrixBase<A>& a, const MatrixBase<B>& b, Matrix<CScalar,CRows,CCols,COptions,CMaxRows,CMaxCols>& c)
     92 {
     93   c.resize(a.rows()*b.rows(),a.cols()*b.cols());
     94   internal::kroneckerProduct_full(a.derived(), b.derived(), c);
     95 }
     96 
     97 /*!
     98  * Computes Kronecker tensor product of two dense matrices
     99  *
    100  * Remark: this function uses the const cast hack and has been
    101  *         implemented to make the function call possible, where the
    102  *         output matrix is a submatrix, e.g.
    103  *           kroneckerProduct(A,B,AB.block(2,5,6,6));
    104  *
    105  * \param a  Dense matrix a
    106  * \param b  Dense matrix b
    107  * \param c  Kronecker tensor product of a and b
    108  */
    109 template<typename A,typename B,typename C>
    110 void kroneckerProduct(const MatrixBase<A>& a, const MatrixBase<B>& b, MatrixBase<C> const & c_)
    111 {
    112   MatrixBase<C>& c = const_cast<MatrixBase<C>& >(c_);
    113   internal::kroneckerProduct_full(a.derived(), b.derived(), c.derived());
    114 }
    115 
    116 /*!
    117  * Computes Kronecker tensor product of a dense and a sparse matrix
    118  *
    119  * \param a  Dense matrix a
    120  * \param b  Sparse matrix b
    121  * \param c  Kronecker tensor product of a and b
    122  */
    123 template<typename A,typename B,typename C>
    124 void kroneckerProduct(const MatrixBase<A>& a, const SparseMatrixBase<B>& b, SparseMatrixBase<C>& c)
    125 {
    126   internal::kroneckerProduct_sparse(a.derived(), b.derived(), c.derived());
    127 }
    128 
    129 /*!
    130  * Computes Kronecker tensor product of a sparse and a dense matrix
    131  *
    132  * \param a  Sparse matrix a
    133  * \param b  Dense matrix b
    134  * \param c  Kronecker tensor product of a and b
    135  */
    136 template<typename A,typename B,typename C>
    137 void kroneckerProduct(const SparseMatrixBase<A>& a, const MatrixBase<B>& b, SparseMatrixBase<C>& c)
    138 {
    139   internal::kroneckerProduct_sparse(a.derived(), b.derived(), c.derived());
    140 }
    141 
    142 /*!
    143  * Computes Kronecker tensor product of two sparse matrices
    144  *
    145  * \param a  Sparse matrix a
    146  * \param b  Sparse matrix b
    147  * \param c  Kronecker tensor product of a and b
    148  */
    149 template<typename A,typename B,typename C>
    150 void kroneckerProduct(const SparseMatrixBase<A>& a, const SparseMatrixBase<B>& b, SparseMatrixBase<C>& c)
    151 {
    152   internal::kroneckerProduct_sparse(a.derived(), b.derived(), c.derived());
    153 }
    154 
    155 } // end namespace Eigen
    156 
    157 #endif // KRONECKER_TENSOR_PRODUCT_H
    158