OSVR-Core
KroneckerTensorProduct.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2011 Kolja Brix <brix@igpm.rwth-aachen.de>
5 // Copyright (C) 2011 Andreas Platen <andiplaten@gmx.de>
6 // Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
7 //
8 // This Source Code Form is subject to the terms of the Mozilla
9 // Public License v. 2.0. If a copy of the MPL was not distributed
10 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 
12 #ifndef KRONECKER_TENSOR_PRODUCT_H
13 #define KRONECKER_TENSOR_PRODUCT_H
14 
15 namespace Eigen {
16 
17 template<typename Scalar, int Options, typename Index> class SparseMatrix;
18 
29 template<typename Lhs, typename Rhs>
30 class KroneckerProduct : public ReturnByValue<KroneckerProduct<Lhs,Rhs> >
31 {
32  private:
34  typedef typename Base::Scalar Scalar;
35  typedef typename Base::Index Index;
36 
37  public:
39  KroneckerProduct(const Lhs& A, const Rhs& B)
40  : m_A(A), m_B(B)
41  {}
42 
44  template<typename Dest> void evalTo(Dest& dst) const;
45 
46  inline Index rows() const { return m_A.rows() * m_B.rows(); }
47  inline Index cols() const { return m_A.cols() * m_B.cols(); }
48 
49  Scalar coeff(Index row, Index col) const
50  {
51  return m_A.coeff(row / m_B.rows(), col / m_B.cols()) *
52  m_B.coeff(row % m_B.rows(), col % m_B.cols());
53  }
54 
55  Scalar coeff(Index i) const
56  {
57  EIGEN_STATIC_ASSERT_VECTOR_ONLY(KroneckerProduct);
58  return m_A.coeff(i / m_A.size()) * m_B.coeff(i % m_A.size());
59  }
60 
61  private:
62  typename Lhs::Nested m_A;
63  typename Rhs::Nested m_B;
64 };
65 
79 template<typename Lhs, typename Rhs>
80 class KroneckerProductSparse : public EigenBase<KroneckerProductSparse<Lhs,Rhs> >
81 {
82  private:
84 
85  public:
87  KroneckerProductSparse(const Lhs& A, const Rhs& B)
88  : m_A(A), m_B(B)
89  {}
90 
92  template<typename Dest> void evalTo(Dest& dst) const;
93 
94  inline Index rows() const { return m_A.rows() * m_B.rows(); }
95  inline Index cols() const { return m_A.cols() * m_B.cols(); }
96 
97  template<typename Scalar, int Options, typename Index>
99  {
101  evalTo(result.derived());
102  return result;
103  }
104 
105  private:
106  typename Lhs::Nested m_A;
107  typename Rhs::Nested m_B;
108 };
109 
110 template<typename Lhs, typename Rhs>
111 template<typename Dest>
113 {
114  const int BlockRows = Rhs::RowsAtCompileTime,
115  BlockCols = Rhs::ColsAtCompileTime;
116  const Index Br = m_B.rows(),
117  Bc = m_B.cols();
118  for (Index i=0; i < m_A.rows(); ++i)
119  for (Index j=0; j < m_A.cols(); ++j)
120  Block<Dest,BlockRows,BlockCols>(dst,i*Br,j*Bc,Br,Bc) = m_A.coeff(i,j) * m_B;
121 }
122 
123 template<typename Lhs, typename Rhs>
124 template<typename Dest>
126 {
127  const Index Br = m_B.rows(),
128  Bc = m_B.cols();
129  dst.resize(rows(),cols());
130  dst.resizeNonZeros(0);
131  dst.reserve(m_A.nonZeros() * m_B.nonZeros());
132 
133  for (Index kA=0; kA < m_A.outerSize(); ++kA)
134  {
135  for (Index kB=0; kB < m_B.outerSize(); ++kB)
136  {
137  for (typename Lhs::InnerIterator itA(m_A,kA); itA; ++itA)
138  {
139  for (typename Rhs::InnerIterator itB(m_B,kB); itB; ++itB)
140  {
141  const Index i = itA.row() * Br + itB.row(),
142  j = itA.col() * Bc + itB.col();
143  dst.insert(i,j) = itA.value() * itB.value();
144  }
145  }
146  }
147  }
148 }
149 
150 namespace internal {
151 
152 template<typename _Lhs, typename _Rhs>
153 struct traits<KroneckerProduct<_Lhs,_Rhs> >
154 {
155  typedef typename remove_all<_Lhs>::type Lhs;
156  typedef typename remove_all<_Rhs>::type Rhs;
158 
159  enum {
164  CoeffReadCost = Lhs::CoeffReadCost + Rhs::CoeffReadCost + NumTraits<Scalar>::MulCost
165  };
166 
168 };
169 
170 template<typename _Lhs, typename _Rhs>
171 struct traits<KroneckerProductSparse<_Lhs,_Rhs> >
172 {
173  typedef MatrixXpr XprKind;
174  typedef typename remove_all<_Lhs>::type Lhs;
175  typedef typename remove_all<_Rhs>::type Rhs;
177  typedef typename promote_storage_type<typename traits<Lhs>::StorageKind, typename traits<Rhs>::StorageKind>::ret StorageKind;
179 
180  enum {
181  LhsFlags = Lhs::Flags,
182  RhsFlags = Rhs::Flags,
183 
188 
189  EvalToRowMajor = (LhsFlags & RhsFlags & RowMajorBit),
190  RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
191 
192  Flags = ((LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
194  CoeffReadCost = Dynamic
195  };
196 };
197 
198 } // end namespace internal
199 
219 template<typename A, typename B>
221 {
222  return KroneckerProduct<A, B>(a.derived(), b.derived());
223 }
224 
236 template<typename A, typename B>
238 {
240 }
241 
242 } // end namespace Eigen
243 
244 #endif // KRONECKER_TENSOR_PRODUCT_H
A versatible sparse matrix representation.
Definition: SparseMatrix.h:85
Definition: XprHelper.h:402
iterative scaling algorithm to equilibrate rows and column norms in matrices
Definition: TestIMU_Common.h:87
Holds information about the various numeric (i.e.
Definition: NumTraits.h:88
Definition: Meta.h:29
Derived & derived()
Definition: EigenBase.h:34
void evalTo(Dest &dst) const
Evaluate the Kronecker tensor product.
Definition: KroneckerTensorProduct.h:112
const unsigned int RowMajorBit
for a matrix, this means that the storage order is row-major.
Definition: Constants.h:53
Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor Matrix...
Definition: EigenBase.h:26
The type used to identify a matrix expression.
Definition: Constants.h:431
Definition: ReturnByValue.h:50
KroneckerProductSparse(const Lhs &A, const Rhs &B)
Constructor.
Definition: KroneckerTensorProduct.h:87
const unsigned int EvalBeforeAssigningBit
means the expression should be evaluated before any assignment
Definition: Constants.h:63
Definition: BandTriangularSolver.h:13
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:103
KroneckerProduct(const Lhs &A, const Rhs &B)
Constructor.
Definition: KroneckerTensorProduct.h:39
const int Dynamic
This value means that a positive quantity (e.g., a size) is not known at compile-time, and that instead the value is stored in some runtime variable.
Definition: Constants.h:21
KroneckerProduct< A, B > kroneckerProduct(const MatrixBase< A > &a, const MatrixBase< B > &b)
Definition: KroneckerTensorProduct.h:220
const unsigned int EvalBeforeNestingBit
means the expression should be evaluated by the calling expression
Definition: Constants.h:58
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:127
void evalTo(Dest &dst) const
Evaluate the Kronecker tensor product.
Definition: KroneckerTensorProduct.h:125
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48
Definition: ForwardDeclarations.h:17
Kronecker tensor product helper class for dense matrices.
Definition: KroneckerTensorProduct.h:30
Definition: XprHelper.h:161
double Scalar
Common scalar type.
Definition: FlexibleKalmanBase.h:48
Kronecker tensor product helper class for sparse matrices.
Definition: KroneckerTensorProduct.h:80