1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2011 Kolja Brix <brix@igpm.rwth-aachen.de>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2011 Andreas Platen <andiplaten@gmx.de>
67faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef KRONECKER_TENSOR_PRODUCT_H
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define KRONECKER_TENSOR_PRODUCT_H
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace Eigen {
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Scalar, int Options, typename Index> class SparseMatrix;
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*!
207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \brief Kronecker tensor product helper class for dense matrices
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * This class is the return value of kroneckerProduct(MatrixBase,
237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * MatrixBase). Use the function rather than construct this class
247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * directly to avoid specifying template prarameters.
257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *
267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \tparam Lhs  Type of the left-hand side, a matrix expression.
277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \tparam Rhs  Type of the rignt-hand side, a matrix expression.
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */
297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Lhs, typename Rhs>
307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezclass KroneckerProduct : public ReturnByValue<KroneckerProduct<Lhs,Rhs> >
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  private:
337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef ReturnByValue<KroneckerProduct> Base;
347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename Base::Scalar Scalar;
357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename Base::Index Index;
367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  public:
387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /*! \brief Constructor. */
397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    KroneckerProduct(const Lhs& A, const Rhs& B)
407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      : m_A(A), m_B(B)
417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {}
427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /*! \brief Evaluate the Kronecker tensor product. */
447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename Dest> void evalTo(Dest& dst) const;
457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    inline Index rows() const { return m_A.rows() * m_B.rows(); }
477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    inline Index cols() const { return m_A.cols() * m_B.cols(); }
487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Scalar coeff(Index row, Index col) const
507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return m_A.coeff(row / m_B.rows(), col / m_B.cols()) *
527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez             m_B.coeff(row % m_B.rows(), col % m_B.cols());
537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Scalar coeff(Index i) const
567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      EIGEN_STATIC_ASSERT_VECTOR_ONLY(KroneckerProduct);
587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return m_A.coeff(i / m_A.size()) * m_B.coeff(i % m_A.size());
597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  private:
627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typename Lhs::Nested m_A;
637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typename Rhs::Nested m_B;
647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez};
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*!
677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \brief Kronecker tensor product helper class for sparse matrices
687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *
697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * If at least one of the operands is a sparse matrix expression,
707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * then this class is returned and evaluates into a sparse matrix.
717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *
727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * This class is the return value of kroneckerProduct(EigenBase,
737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * EigenBase). Use the function rather than construct this class
747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * directly to avoid specifying template prarameters.
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \tparam Lhs  Type of the left-hand side, a matrix expression.
777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \tparam Rhs  Type of the rignt-hand side, a matrix expression.
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */
797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Lhs, typename Rhs>
807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezclass KroneckerProductSparse : public EigenBase<KroneckerProductSparse<Lhs,Rhs> >
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  private:
837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename internal::traits<KroneckerProductSparse>::Index Index;
847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  public:
867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /*! \brief Constructor. */
877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    KroneckerProductSparse(const Lhs& A, const Rhs& B)
887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      : m_A(A), m_B(B)
897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {}
907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /*! \brief Evaluate the Kronecker tensor product. */
927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename Dest> void evalTo(Dest& dst) const;
937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    inline Index rows() const { return m_A.rows() * m_B.rows(); }
957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    inline Index cols() const { return m_A.cols() * m_B.cols(); }
967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename Scalar, int Options, typename Index>
987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    operator SparseMatrix<Scalar, Options, Index>()
997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
1007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      SparseMatrix<Scalar, Options, Index> result;
1017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      evalTo(result.derived());
1027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return result;
1037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
1047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  private:
1067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typename Lhs::Nested m_A;
1077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typename Rhs::Nested m_B;
1087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez};
1097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Lhs, typename Rhs>
1117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Dest>
1127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezvoid KroneckerProduct<Lhs,Rhs>::evalTo(Dest& dst) const
1137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
1147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const int BlockRows = Rhs::RowsAtCompileTime,
1157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            BlockCols = Rhs::ColsAtCompileTime;
1167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const Index Br = m_B.rows(),
1177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez              Bc = m_B.cols();
1187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (Index i=0; i < m_A.rows(); ++i)
1197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (Index j=0; j < m_A.cols(); ++j)
1207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Block<Dest,BlockRows,BlockCols>(dst,i*Br,j*Bc,Br,Bc) = m_A.coeff(i,j) * m_B;
1217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}
1227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Lhs, typename Rhs>
1247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Dest>
1257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezvoid KroneckerProductSparse<Lhs,Rhs>::evalTo(Dest& dst) const
1267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
1277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const Index Br = m_B.rows(),
1287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez              Bc = m_B.cols();
1297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  dst.resize(rows(),cols());
1307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  dst.resizeNonZeros(0);
1317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  dst.reserve(m_A.nonZeros() * m_B.nonZeros());
1327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (Index kA=0; kA < m_A.outerSize(); ++kA)
134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
1357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (Index kB=0; kB < m_B.outerSize(); ++kB)
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
1377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      for (typename Lhs::InnerIterator itA(m_A,kA); itA; ++itA)
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
1397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        for (typename Rhs::InnerIterator itB(m_B,kB); itB; ++itB)
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
1417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          const Index i = itA.row() * Br + itB.row(),
1427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                      j = itA.col() * Bc + itB.col();
1437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          dst.insert(i,j) = itA.value() * itB.value();
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace internal {
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename _Lhs, typename _Rhs>
1537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezstruct traits<KroneckerProduct<_Lhs,_Rhs> >
1547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
1557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef typename remove_all<_Lhs>::type Lhs;
1567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef typename remove_all<_Rhs>::type Rhs;
1577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar;
1587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  enum {
1607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Rows = size_at_compile_time<traits<Lhs>::RowsAtCompileTime, traits<Rhs>::RowsAtCompileTime>::ret,
1617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Cols = size_at_compile_time<traits<Lhs>::ColsAtCompileTime, traits<Rhs>::ColsAtCompileTime>::ret,
1627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    MaxRows = size_at_compile_time<traits<Lhs>::MaxRowsAtCompileTime, traits<Rhs>::MaxRowsAtCompileTime>::ret,
1637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    MaxCols = size_at_compile_time<traits<Lhs>::MaxColsAtCompileTime, traits<Rhs>::MaxColsAtCompileTime>::ret,
1647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    CoeffReadCost = Lhs::CoeffReadCost + Rhs::CoeffReadCost + NumTraits<Scalar>::MulCost
1657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  };
1667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef Matrix<Scalar,Rows,Cols> ReturnType;
1687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez};
1697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename _Lhs, typename _Rhs>
1717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezstruct traits<KroneckerProductSparse<_Lhs,_Rhs> >
1727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
1737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef MatrixXpr XprKind;
1747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef typename remove_all<_Lhs>::type Lhs;
1757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef typename remove_all<_Rhs>::type Rhs;
1767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar;
1777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef typename promote_storage_type<typename traits<Lhs>::StorageKind, typename traits<Rhs>::StorageKind>::ret StorageKind;
1787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef typename promote_index_type<typename Lhs::Index, typename Rhs::Index>::type Index;
1797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  enum {
1817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    LhsFlags = Lhs::Flags,
1827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    RhsFlags = Rhs::Flags,
1837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    RowsAtCompileTime = size_at_compile_time<traits<Lhs>::RowsAtCompileTime, traits<Rhs>::RowsAtCompileTime>::ret,
1857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    ColsAtCompileTime = size_at_compile_time<traits<Lhs>::ColsAtCompileTime, traits<Rhs>::ColsAtCompileTime>::ret,
1867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    MaxRowsAtCompileTime = size_at_compile_time<traits<Lhs>::MaxRowsAtCompileTime, traits<Rhs>::MaxRowsAtCompileTime>::ret,
1877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    MaxColsAtCompileTime = size_at_compile_time<traits<Lhs>::MaxColsAtCompileTime, traits<Rhs>::MaxColsAtCompileTime>::ret,
1887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EvalToRowMajor = (LhsFlags & RhsFlags & RowMajorBit),
1907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
1917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Flags = ((LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
1937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          | EvalBeforeNestingBit | EvalBeforeAssigningBit,
1947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    CoeffReadCost = Dynamic
1957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  };
1967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez};
197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} // end namespace internal
199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*!
2017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \ingroup KroneckerProduct_Module
202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * Computes Kronecker tensor product of two dense matrices
204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
2057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \warning If you want to replace a matrix by its Kronecker product
2067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *          with some matrix, do \b NOT do this:
2077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \code
2087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * A = kroneckerProduct(A,B); // bug!!! caused by aliasing effect
2097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \endcode
2107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * instead, use eval() to work around this:
2117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \code
2127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * A = kroneckerProduct(A,B).eval();
2137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \endcode
214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * \param a  Dense matrix a
216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * \param b  Dense matrix b
2177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \return   Kronecker tensor product of a and b
218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */
2197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename A, typename B>
2207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos HernandezKroneckerProduct<A,B> kroneckerProduct(const MatrixBase<A>& a, const MatrixBase<B>& b)
221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
2227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  return KroneckerProduct<A, B>(a.derived(), b.derived());
223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*!
2267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \ingroup KroneckerProduct_Module
227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
2287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Computes Kronecker tensor product of two matrices, at least one of
2297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * which is sparse
230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
2317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param a  Dense/sparse matrix a
2327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param b  Dense/sparse matrix b
2337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \return   Kronecker tensor product of a and b, stored in a sparse
2347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *           matrix
235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath */
2367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename A, typename B>
2377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos HernandezKroneckerProductSparse<A,B> kroneckerProduct(const EigenBase<A>& a, const EigenBase<B>& b)
238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
2397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  return KroneckerProductSparse<A,B>(a.derived(), b.derived());
240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace Eigen
243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif // KRONECKER_TENSOR_PRODUCT_H
245