SparseDiagonalProduct.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5 //
6 // Eigen is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 3 of the License, or (at your option) any later version.
10 //
11 // Alternatively, you can redistribute it and/or
12 // modify it under the terms of the GNU General Public License as
13 // published by the Free Software Foundation; either version 2 of
14 // the License, or (at your option) any later version.
15 //
16 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License and a copy of the GNU General Public License along with
23 // Eigen. If not, see <http://www.gnu.org/licenses/>.
24 
25 #ifndef EIGEN_SPARSE_DIAGONAL_PRODUCT_H
26 #define EIGEN_SPARSE_DIAGONAL_PRODUCT_H
27 
28 namespace Eigen {
29 
30 // The product of a diagonal matrix with a sparse matrix can be easily
31 // implemented using expression template.
32 // We have two consider very different cases:
33 // 1 - diag * row-major sparse
34 // => each inner vector <=> scalar * sparse vector product
35 // => so we can reuse CwiseUnaryOp::InnerIterator
36 // 2 - diag * col-major sparse
37 // => each inner vector <=> densevector * sparse vector cwise product
38 // => again, we can reuse specialization of CwiseBinaryOp::InnerIterator
39 // for that particular case
40 // The two other cases are symmetric.
41 
42 namespace internal {
43 
44 template<typename Lhs, typename Rhs>
45 struct traits<SparseDiagonalProduct<Lhs, Rhs> >
46 {
47  typedef typename remove_all<Lhs>::type _Lhs;
48  typedef typename remove_all<Rhs>::type _Rhs;
49  typedef typename _Lhs::Scalar Scalar;
50  typedef typename promote_index_type<typename traits<Lhs>::Index,
51  typename traits<Rhs>::Index>::type Index;
52  typedef Sparse StorageKind;
53  typedef MatrixXpr XprKind;
54  enum {
55  RowsAtCompileTime = _Lhs::RowsAtCompileTime,
56  ColsAtCompileTime = _Rhs::ColsAtCompileTime,
57 
58  MaxRowsAtCompileTime = _Lhs::MaxRowsAtCompileTime,
59  MaxColsAtCompileTime = _Rhs::MaxColsAtCompileTime,
60 
61  SparseFlags = is_diagonal<_Lhs>::ret ? int(_Rhs::Flags) : int(_Lhs::Flags),
62  Flags = (SparseFlags&RowMajorBit),
63  CoeffReadCost = Dynamic
64  };
65 };
66 
68 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType, int RhsMode, int LhsMode>
69 class sparse_diagonal_product_inner_iterator_selector;
70 
71 } // end namespace internal
72 
73 template<typename Lhs, typename Rhs>
75  : public SparseMatrixBase<SparseDiagonalProduct<Lhs,Rhs> >,
76  internal::no_assignment_operator
77 {
78  typedef typename Lhs::Nested LhsNested;
79  typedef typename Rhs::Nested RhsNested;
80 
81  typedef typename internal::remove_all<LhsNested>::type _LhsNested;
82  typedef typename internal::remove_all<RhsNested>::type _RhsNested;
83 
84  enum {
85  LhsMode = internal::is_diagonal<_LhsNested>::ret ? internal::SDP_IsDiagonal
87  RhsMode = internal::is_diagonal<_RhsNested>::ret ? internal::SDP_IsDiagonal
88  : (_RhsNested::Flags&RowMajorBit) ? internal::SDP_IsSparseRowMajor : internal::SDP_IsSparseColMajor
89  };
90 
91  public:
92 
94 
95  typedef internal::sparse_diagonal_product_inner_iterator_selector
96  <_LhsNested,_RhsNested,SparseDiagonalProduct,LhsMode,RhsMode> InnerIterator;
97 
98  EIGEN_STRONG_INLINE SparseDiagonalProduct(const Lhs& lhs, const Rhs& rhs)
99  : m_lhs(lhs), m_rhs(rhs)
100  {
101  eigen_assert(lhs.cols() == rhs.rows() && "invalid sparse matrix * diagonal matrix product");
102  }
103 
104  EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); }
105  EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); }
106 
107  EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
108  EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
109 
110  protected:
111  LhsNested m_lhs;
112  RhsNested m_rhs;
113 };
114 
115 namespace internal {
116 
117 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
118 class sparse_diagonal_product_inner_iterator_selector
119 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseRowMajor>
120  : public CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,const Rhs>::InnerIterator
121 {
122  typedef typename CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,const Rhs>::InnerIterator Base;
123  typedef typename Lhs::Index Index;
124  public:
125  inline sparse_diagonal_product_inner_iterator_selector(
126  const SparseDiagonalProductType& expr, Index outer)
127  : Base(expr.rhs()*(expr.lhs().diagonal().coeff(outer)), outer)
128  {}
129 };
130 
131 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
132 class sparse_diagonal_product_inner_iterator_selector
133 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseColMajor>
134  : public CwiseBinaryOp<
135  scalar_product_op<typename Lhs::Scalar>,
136  SparseInnerVectorSet<Rhs,1>,
137  typename Lhs::DiagonalVectorType>::InnerIterator
138 {
139  typedef typename CwiseBinaryOp<
140  scalar_product_op<typename Lhs::Scalar>,
141  SparseInnerVectorSet<Rhs,1>,
142  typename Lhs::DiagonalVectorType>::InnerIterator Base;
143  typedef typename Lhs::Index Index;
144  public:
145  inline sparse_diagonal_product_inner_iterator_selector(
146  const SparseDiagonalProductType& expr, Index outer)
147  : Base(expr.rhs().innerVector(outer) .cwiseProduct(expr.lhs().diagonal()), 0)
148  {}
149 };
150 
151 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
152 class sparse_diagonal_product_inner_iterator_selector
153 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseColMajor,SDP_IsDiagonal>
154  : public CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,const Lhs>::InnerIterator
155 {
156  typedef typename CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,const Lhs>::InnerIterator Base;
157  typedef typename Lhs::Index Index;
158  public:
159  inline sparse_diagonal_product_inner_iterator_selector(
160  const SparseDiagonalProductType& expr, Index outer)
161  : Base(expr.lhs()*expr.rhs().diagonal().coeff(outer), outer)
162  {}
163 };
164 
165 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
166 class sparse_diagonal_product_inner_iterator_selector
167 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseRowMajor,SDP_IsDiagonal>
168  : public CwiseBinaryOp<
169  scalar_product_op<typename Rhs::Scalar>,
170  SparseInnerVectorSet<Lhs,1>,
171  Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator
172 {
173  typedef typename CwiseBinaryOp<
174  scalar_product_op<typename Rhs::Scalar>,
175  SparseInnerVectorSet<Lhs,1>,
176  Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator Base;
177  typedef typename Lhs::Index Index;
178  public:
179  inline sparse_diagonal_product_inner_iterator_selector(
180  const SparseDiagonalProductType& expr, Index outer)
181  : Base(expr.lhs().innerVector(outer) .cwiseProduct(expr.rhs().diagonal().transpose()), 0)
182  {}
183 };
184 
185 } // end namespace internal
186 
187 // SparseMatrixBase functions
188 
189 template<typename Derived>
190 template<typename OtherDerived>
191 const SparseDiagonalProduct<Derived,OtherDerived>
193 {
194  return SparseDiagonalProduct<Derived,OtherDerived>(this->derived(), other.derived());
195 }
196 
197 } // end namespace Eigen
198 
199 #endif // EIGEN_SPARSE_DIAGONAL_PRODUCT_H