Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / extern / Eigen2 / Eigen / src / Sparse / SparseDiagonalProduct.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra. Eigen itself is part of the KDE project.
3 //
4 // Copyright (C) 2009 Gael Guennebaud <g.gael@free.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 a diagonal matrix with a sparse matrix can be easily
29 // implemented using expression template. We have two very different cases:
30 // 1 - diag * row-major sparse
31 //     => each inner vector <=> scalar * sparse vector product
32 //     => so we can reuse CwiseUnaryOp::InnerIterator
33 // 2 - diag * col-major sparse
34 //     => each inner vector <=> densevector * sparse vector cwise product
35 //     => again, we can reuse specialization of CwiseBinaryOp::InnerIterator
36 //        for that particular case
37 // The two other cases are symmetric.
38
39 template<typename Lhs, typename Rhs>
40 struct ei_traits<SparseDiagonalProduct<Lhs, Rhs> > : ei_traits<SparseProduct<Lhs, Rhs, DiagonalProduct> >
41 {
42   typedef typename ei_cleantype<Lhs>::type _Lhs;
43   typedef typename ei_cleantype<Rhs>::type _Rhs;
44   enum {
45     SparseFlags = ((int(_Lhs::Flags)&Diagonal)==Diagonal) ? int(_Rhs::Flags) : int(_Lhs::Flags),
46     Flags = SparseBit | (SparseFlags&RowMajorBit)
47   };
48 };
49
50 enum {SDP_IsDiagonal, SDP_IsSparseRowMajor, SDP_IsSparseColMajor};
51 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType, int RhsMode, int LhsMode> 
52 class ei_sparse_diagonal_product_inner_iterator_selector;
53
54 template<typename LhsNested, typename RhsNested>
55 class SparseDiagonalProduct : public SparseMatrixBase<SparseDiagonalProduct<LhsNested,RhsNested> >, ei_no_assignment_operator
56 {
57     typedef typename ei_traits<SparseDiagonalProduct>::_LhsNested _LhsNested;
58     typedef typename ei_traits<SparseDiagonalProduct>::_RhsNested _RhsNested;
59     
60     enum {
61       LhsMode = (_LhsNested::Flags&Diagonal)==Diagonal ? SDP_IsDiagonal
62               : (_LhsNested::Flags&RowMajorBit) ? SDP_IsSparseRowMajor : SDP_IsSparseColMajor,
63       RhsMode = (_RhsNested::Flags&Diagonal)==Diagonal ? SDP_IsDiagonal
64               : (_RhsNested::Flags&RowMajorBit) ? SDP_IsSparseRowMajor : SDP_IsSparseColMajor
65     };
66
67   public:
68
69     EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseDiagonalProduct)
70     
71     typedef ei_sparse_diagonal_product_inner_iterator_selector
72                 <_LhsNested,_RhsNested,SparseDiagonalProduct,LhsMode,RhsMode> InnerIterator;
73
74     template<typename Lhs, typename Rhs>
75     EIGEN_STRONG_INLINE SparseDiagonalProduct(const Lhs& lhs, const Rhs& rhs)
76       : m_lhs(lhs), m_rhs(rhs)
77     {
78       ei_assert(lhs.cols() == rhs.rows() && "invalid sparse matrix * diagonal matrix product");
79     }
80
81     EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
82     EIGEN_STRONG_INLINE int cols() const { return m_rhs.cols(); }
83
84     EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
85     EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
86
87   protected:
88     LhsNested m_lhs;
89     RhsNested m_rhs;
90 };
91
92
93 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
94 class ei_sparse_diagonal_product_inner_iterator_selector
95 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseRowMajor>
96   : public SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Lhs::Scalar>,Rhs>::InnerIterator
97 {
98     typedef typename SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Lhs::Scalar>,Rhs>::InnerIterator Base;
99   public:
100     inline ei_sparse_diagonal_product_inner_iterator_selector(
101               const SparseDiagonalProductType& expr, int outer)
102       : Base(expr.rhs()*(expr.lhs().diagonal().coeff(outer)), outer)
103     {}
104 };
105
106 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
107 class ei_sparse_diagonal_product_inner_iterator_selector
108 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseColMajor>
109   : public SparseCwiseBinaryOp<
110       ei_scalar_product_op<typename Lhs::Scalar>,
111       SparseInnerVectorSet<Rhs,1>,
112       typename Lhs::_CoeffsVectorType>::InnerIterator
113 {
114     typedef typename SparseCwiseBinaryOp<
115       ei_scalar_product_op<typename Lhs::Scalar>,
116       SparseInnerVectorSet<Rhs,1>,
117       typename Lhs::_CoeffsVectorType>::InnerIterator Base;
118   public:
119     inline ei_sparse_diagonal_product_inner_iterator_selector(
120               const SparseDiagonalProductType& expr, int outer)
121       : Base(expr.rhs().innerVector(outer) .cwise()* expr.lhs().diagonal(), 0)
122     {}
123 };
124
125 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
126 class ei_sparse_diagonal_product_inner_iterator_selector
127 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseColMajor,SDP_IsDiagonal>
128   : public SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Rhs::Scalar>,Lhs>::InnerIterator
129 {
130     typedef typename SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Rhs::Scalar>,Lhs>::InnerIterator Base;
131   public:
132     inline ei_sparse_diagonal_product_inner_iterator_selector(
133               const SparseDiagonalProductType& expr, int outer)
134       : Base(expr.lhs()*expr.rhs().diagonal().coeff(outer), outer)
135     {}
136 };
137
138 template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
139 class ei_sparse_diagonal_product_inner_iterator_selector
140 <Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseRowMajor,SDP_IsDiagonal>
141   : public SparseCwiseBinaryOp<
142       ei_scalar_product_op<typename Rhs::Scalar>,
143       SparseInnerVectorSet<Lhs,1>,
144       NestByValue<Transpose<typename Rhs::_CoeffsVectorType> > >::InnerIterator
145 {
146     typedef typename SparseCwiseBinaryOp<
147       ei_scalar_product_op<typename Rhs::Scalar>,
148       SparseInnerVectorSet<Lhs,1>,
149       NestByValue<Transpose<typename Rhs::_CoeffsVectorType> > >::InnerIterator Base;
150   public:
151     inline ei_sparse_diagonal_product_inner_iterator_selector(
152               const SparseDiagonalProductType& expr, int outer)
153       : Base(expr.lhs().innerVector(outer) .cwise()* expr.rhs().diagonal().transpose().nestByValue(), 0)
154     {}
155 };
156
157 #endif // EIGEN_SPARSE_DIAGONAL_PRODUCT_H