Teh first one
[mldemos:kalians-mldemos.git] / _AlgorithmsPlugins / KPCA / Eigen / src / Sparse / SparseDiagonalProduct.h
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 // The product of a diagonal matrix with a sparse matrix can be easily
29 // implemented using expression template.
30 // We have two consider very different cases:
31 // 1 - diag * row-major sparse
32 //     => each inner vector <=> scalar * sparse vector product
33 //     => so we can reuse CwiseUnaryOp::InnerIterator
34 // 2 - diag * col-major sparse
35 //     => each inner vector <=> densevector * sparse vector cwise product
36 //     => again, we can reuse specialization of CwiseBinaryOp::InnerIterator
37 //        for that particular case
38 // The two other cases are symmetric.
39
40 namespace internal {
41
42 template<typename Lhs, typename Rhs>
43 struct traits<SparseDiagonalProduct<Lhs, Rhs> >
44 {
45   typedef typename remove_all<Lhs>::type _Lhs;
46   typedef typename remove_all<Rhs>::type _Rhs;
47   typedef typename _Lhs::Scalar Scalar;
48   typedef typename promote_index_type<typename traits<Lhs>::Index,
49                                          typename traits<Rhs>::Index>::type Index;
50   typedef Sparse StorageKind;
51   typedef MatrixXpr XprKind;
52   enum {
53     RowsAtCompileTime = _Lhs::RowsAtCompileTime,
54     ColsAtCompileTime = _Rhs::ColsAtCompileTime,
55
56     MaxRowsAtCompileTime = _Lhs::MaxRowsAtCompileTime,
57     MaxColsAtCompileTime = _Rhs::MaxColsAtCompileTime,
58
59     SparseFlags = is_diagonal<_Lhs>::ret ? int(_Rhs::Flags) : int(_Lhs::Flags),
60     Flags = (SparseFlags&RowMajorBit),
61     CoeffReadCost = Dynamic
62   };
63 };
64
65 enum {SDP_IsDiagonal, SDP_IsSparseRowMajor, SDP_IsSparseColMajor};
66 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType, int RhsMode, int LhsMode>
67 class sparse_diagonal_product_inner_iterator_selector;
68
69 } // end namespace internal
70
71 template<typename Lhs, typename Rhs>
72 class SparseDiagonalProduct
73   : public SparseMatrixBase<SparseDiagonalProduct<Lhs,Rhs> >,
74     internal::no_assignment_operator
75 {
76     typedef typename Lhs::Nested LhsNested;
77     typedef typename Rhs::Nested RhsNested;
78
79     typedef typename internal::remove_all<LhsNested>::type _LhsNested;
80     typedef typename internal::remove_all<RhsNested>::type _RhsNested;
81
82     enum {
83       LhsMode = internal::is_diagonal<_LhsNested>::ret ? internal::SDP_IsDiagonal
84               : (_LhsNested::Flags&RowMajorBit) ? internal::SDP_IsSparseRowMajor : internal::SDP_IsSparseColMajor,
85       RhsMode = internal::is_diagonal<_RhsNested>::ret ? internal::SDP_IsDiagonal
86               : (_RhsNested::Flags&RowMajorBit) ? internal::SDP_IsSparseRowMajor : internal::SDP_IsSparseColMajor
87     };
88
89   public:
90
91     EIGEN_SPARSE_PUBLIC_INTERFACE(SparseDiagonalProduct)
92
93     typedef internal::sparse_diagonal_product_inner_iterator_selector
94                 <_LhsNested,_RhsNested,SparseDiagonalProduct,LhsMode,RhsMode> InnerIterator;
95
96     EIGEN_STRONG_INLINE SparseDiagonalProduct(const Lhs& lhs, const Rhs& rhs)
97       : m_lhs(lhs), m_rhs(rhs)
98     {
99       eigen_assert(lhs.cols() == rhs.rows() && "invalid sparse matrix * diagonal matrix product");
100     }
101
102     EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); }
103     EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); }
104
105     EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
106     EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
107
108   protected:
109     LhsNested m_lhs;
110     RhsNested m_rhs;
111 };
112
113 namespace internal {
114
115 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
116 class sparse_diagonal_product_inner_iterator_selector
117 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseRowMajor>
118   : public CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,const Rhs>::InnerIterator
119 {
120     typedef typename CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,const Rhs>::InnerIterator Base;
121     typedef typename Lhs::Index Index;
122   public:
123     inline sparse_diagonal_product_inner_iterator_selector(
124               const SparseDiagonalProductType& expr, Index outer)
125       : Base(expr.rhs()*(expr.lhs().diagonal().coeff(outer)), outer)
126     {}
127 };
128
129 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
130 class sparse_diagonal_product_inner_iterator_selector
131 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseColMajor>
132   : public CwiseBinaryOp<
133       scalar_product_op<typename Lhs::Scalar>,
134       SparseInnerVectorSet<Rhs,1>,
135       typename Lhs::DiagonalVectorType>::InnerIterator
136 {
137     typedef typename CwiseBinaryOp<
138       scalar_product_op<typename Lhs::Scalar>,
139       SparseInnerVectorSet<Rhs,1>,
140       typename Lhs::DiagonalVectorType>::InnerIterator Base;
141     typedef typename Lhs::Index Index;
142   public:
143     inline sparse_diagonal_product_inner_iterator_selector(
144               const SparseDiagonalProductType& expr, Index outer)
145       : Base(expr.rhs().innerVector(outer) .cwiseProduct(expr.lhs().diagonal()), 0)
146     {}
147 };
148
149 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
150 class sparse_diagonal_product_inner_iterator_selector
151 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseColMajor,SDP_IsDiagonal>
152   : public CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,const Lhs>::InnerIterator
153 {
154     typedef typename CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,const Lhs>::InnerIterator Base;
155     typedef typename Lhs::Index Index;
156   public:
157     inline sparse_diagonal_product_inner_iterator_selector(
158               const SparseDiagonalProductType& expr, Index outer)
159       : Base(expr.lhs()*expr.rhs().diagonal().coeff(outer), outer)
160     {}
161 };
162
163 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
164 class sparse_diagonal_product_inner_iterator_selector
165 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseRowMajor,SDP_IsDiagonal>
166   : public CwiseBinaryOp<
167       scalar_product_op<typename Rhs::Scalar>,
168       SparseInnerVectorSet<Lhs,1>,
169       Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator
170 {
171     typedef typename CwiseBinaryOp<
172       scalar_product_op<typename Rhs::Scalar>,
173       SparseInnerVectorSet<Lhs,1>,
174       Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator Base;
175     typedef typename Lhs::Index Index;
176   public:
177     inline sparse_diagonal_product_inner_iterator_selector(
178               const SparseDiagonalProductType& expr, Index outer)
179       : Base(expr.lhs().innerVector(outer) .cwiseProduct(expr.rhs().diagonal().transpose()), 0)
180     {}
181 };
182
183 } // end namespace internal
184
185 // SparseMatrixBase functions
186
187 template<typename Derived>
188 template<typename OtherDerived>
189 const SparseDiagonalProduct<Derived,OtherDerived>
190 SparseMatrixBase<Derived>::operator*(const DiagonalBase<OtherDerived> &other) const
191 {
192   return SparseDiagonalProduct<Derived,OtherDerived>(this->derived(), other.derived());
193 }
194
195 #endif // EIGEN_SPARSE_DIAGONAL_PRODUCT_H