remove $Id: tags after discussion on the mailign list: http://markmail.org/message...
[blender.git] / extern / Eigen3 / Eigen / src / Core / ProductBase.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2009-2010 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_PRODUCTBASE_H
26 #define EIGEN_PRODUCTBASE_H
27
28 /** \class ProductBase
29   * \ingroup Core_Module
30   *
31   */
32
33 namespace internal {
34 template<typename Derived, typename _Lhs, typename _Rhs>
35 struct traits<ProductBase<Derived,_Lhs,_Rhs> >
36 {
37   typedef MatrixXpr XprKind;
38   typedef typename remove_all<_Lhs>::type Lhs;
39   typedef typename remove_all<_Rhs>::type Rhs;
40   typedef typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar;
41   typedef typename promote_storage_type<typename traits<Lhs>::StorageKind,
42                                            typename traits<Rhs>::StorageKind>::ret StorageKind;
43   typedef typename promote_index_type<typename traits<Lhs>::Index,
44                                          typename traits<Rhs>::Index>::type Index;
45   enum {
46     RowsAtCompileTime = traits<Lhs>::RowsAtCompileTime,
47     ColsAtCompileTime = traits<Rhs>::ColsAtCompileTime,
48     MaxRowsAtCompileTime = traits<Lhs>::MaxRowsAtCompileTime,
49     MaxColsAtCompileTime = traits<Rhs>::MaxColsAtCompileTime,
50     Flags = (MaxRowsAtCompileTime==1 ? RowMajorBit : 0)
51           | EvalBeforeNestingBit | EvalBeforeAssigningBit | NestByRefBit,
52                   // Note that EvalBeforeNestingBit and NestByRefBit
53                   // are not used in practice because nested is overloaded for products
54     CoeffReadCost = 0 // FIXME why is it needed ?
55   };
56 };
57 }
58
59 #define EIGEN_PRODUCT_PUBLIC_INTERFACE(Derived) \
60   typedef ProductBase<Derived, Lhs, Rhs > Base; \
61   EIGEN_DENSE_PUBLIC_INTERFACE(Derived) \
62   typedef typename Base::LhsNested LhsNested; \
63   typedef typename Base::_LhsNested _LhsNested; \
64   typedef typename Base::LhsBlasTraits LhsBlasTraits; \
65   typedef typename Base::ActualLhsType ActualLhsType; \
66   typedef typename Base::_ActualLhsType _ActualLhsType; \
67   typedef typename Base::RhsNested RhsNested; \
68   typedef typename Base::_RhsNested _RhsNested; \
69   typedef typename Base::RhsBlasTraits RhsBlasTraits; \
70   typedef typename Base::ActualRhsType ActualRhsType; \
71   typedef typename Base::_ActualRhsType _ActualRhsType; \
72   using Base::m_lhs; \
73   using Base::m_rhs;
74
75 template<typename Derived, typename Lhs, typename Rhs>
76 class ProductBase : public MatrixBase<Derived>
77 {
78   public:
79     typedef MatrixBase<Derived> Base;
80     EIGEN_DENSE_PUBLIC_INTERFACE(ProductBase)
81     
82     typedef typename Lhs::Nested LhsNested;
83     typedef typename internal::remove_all<LhsNested>::type _LhsNested;
84     typedef internal::blas_traits<_LhsNested> LhsBlasTraits;
85     typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType;
86     typedef typename internal::remove_all<ActualLhsType>::type _ActualLhsType;
87     typedef typename internal::traits<Lhs>::Scalar LhsScalar;
88
89     typedef typename Rhs::Nested RhsNested;
90     typedef typename internal::remove_all<RhsNested>::type _RhsNested;
91     typedef internal::blas_traits<_RhsNested> RhsBlasTraits;
92     typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
93     typedef typename internal::remove_all<ActualRhsType>::type _ActualRhsType;
94     typedef typename internal::traits<Rhs>::Scalar RhsScalar;
95
96     // Diagonal of a product: no need to evaluate the arguments because they are going to be evaluated only once
97     typedef CoeffBasedProduct<LhsNested, RhsNested, 0> FullyLazyCoeffBaseProductType;
98
99   public:
100
101     typedef typename Base::PlainObject PlainObject;
102
103     ProductBase(const Lhs& lhs, const Rhs& rhs)
104       : m_lhs(lhs), m_rhs(rhs)
105     {
106       eigen_assert(lhs.cols() == rhs.rows()
107         && "invalid matrix product"
108         && "if you wanted a coeff-wise or a dot product use the respective explicit functions");
109     }
110
111     inline Index rows() const { return m_lhs.rows(); }
112     inline Index cols() const { return m_rhs.cols(); }
113
114     template<typename Dest>
115     inline void evalTo(Dest& dst) const { dst.setZero(); scaleAndAddTo(dst,Scalar(1)); }
116
117     template<typename Dest>
118     inline void addTo(Dest& dst) const { scaleAndAddTo(dst,1); }
119
120     template<typename Dest>
121     inline void subTo(Dest& dst) const { scaleAndAddTo(dst,-1); }
122
123     template<typename Dest>
124     inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { derived().scaleAndAddTo(dst,alpha); }
125
126     const _LhsNested& lhs() const { return m_lhs; }
127     const _RhsNested& rhs() const { return m_rhs; }
128
129     // Implicit conversion to the nested type (trigger the evaluation of the product)
130     operator const PlainObject& () const
131     {
132       m_result.resize(m_lhs.rows(), m_rhs.cols());
133       derived().evalTo(m_result);
134       return m_result;
135     }
136
137     const Diagonal<const FullyLazyCoeffBaseProductType,0> diagonal() const
138     { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); }
139
140     template<int Index>
141     const Diagonal<FullyLazyCoeffBaseProductType,Index> diagonal() const
142     { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); }
143
144     const Diagonal<FullyLazyCoeffBaseProductType,Dynamic> diagonal(Index index) const
145     { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); }
146
147     // restrict coeff accessors to 1x1 expressions. No need to care about mutators here since this isnt a Lvalue expression
148     typename Base::CoeffReturnType coeff(Index row, Index col) const
149     {
150 #ifdef EIGEN2_SUPPORT
151       return lhs().row(row).cwiseProduct(rhs().col(col).transpose()).sum();
152 #else
153       EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
154       eigen_assert(this->rows() == 1 && this->cols() == 1);
155       return derived().coeff(row,col);
156 #endif
157     }
158
159     typename Base::CoeffReturnType coeff(Index i) const
160     {
161       EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
162       eigen_assert(this->rows() == 1 && this->cols() == 1);
163       return derived().coeff(i);
164     }
165
166     const Scalar& coeffRef(Index row, Index col) const
167     {
168       EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
169       eigen_assert(this->rows() == 1 && this->cols() == 1);
170       return derived().coeffRef(row,col);
171     }
172
173     const Scalar& coeffRef(Index i) const
174     {
175       EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
176       eigen_assert(this->rows() == 1 && this->cols() == 1);
177       return derived().coeffRef(i);
178     }
179
180   protected:
181
182     const LhsNested m_lhs;
183     const RhsNested m_rhs;
184
185     mutable PlainObject m_result;
186 };
187
188 // here we need to overload the nested rule for products
189 // such that the nested type is a const reference to a plain matrix
190 namespace internal {
191 template<typename Lhs, typename Rhs, int Mode, int N, typename PlainObject>
192 struct nested<GeneralProduct<Lhs,Rhs,Mode>, N, PlainObject>
193 {
194   typedef PlainObject const& type;
195 };
196 }
197
198 template<typename NestedProduct>
199 class ScaledProduct;
200
201 // Note that these two operator* functions are not defined as member
202 // functions of ProductBase, because, otherwise we would have to
203 // define all overloads defined in MatrixBase. Furthermore, Using
204 // "using Base::operator*" would not work with MSVC.
205 //
206 // Also note that here we accept any compatible scalar types
207 template<typename Derived,typename Lhs,typename Rhs>
208 const ScaledProduct<Derived>
209 operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::Scalar x)
210 { return ScaledProduct<Derived>(prod.derived(), x); }
211
212 template<typename Derived,typename Lhs,typename Rhs>
213 typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
214                       const ScaledProduct<Derived> >::type
215 operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::RealScalar x)
216 { return ScaledProduct<Derived>(prod.derived(), x); }
217
218
219 template<typename Derived,typename Lhs,typename Rhs>
220 const ScaledProduct<Derived>
221 operator*(typename Derived::Scalar x,const ProductBase<Derived,Lhs,Rhs>& prod)
222 { return ScaledProduct<Derived>(prod.derived(), x); }
223
224 template<typename Derived,typename Lhs,typename Rhs>
225 typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
226                       const ScaledProduct<Derived> >::type
227 operator*(typename Derived::RealScalar x,const ProductBase<Derived,Lhs,Rhs>& prod)
228 { return ScaledProduct<Derived>(prod.derived(), x); }
229
230 namespace internal {
231 template<typename NestedProduct>
232 struct traits<ScaledProduct<NestedProduct> >
233  : traits<ProductBase<ScaledProduct<NestedProduct>,
234                          typename NestedProduct::_LhsNested,
235                          typename NestedProduct::_RhsNested> >
236 {
237   typedef typename traits<NestedProduct>::StorageKind StorageKind;
238 };
239 }
240
241 template<typename NestedProduct>
242 class ScaledProduct
243   : public ProductBase<ScaledProduct<NestedProduct>,
244                        typename NestedProduct::_LhsNested,
245                        typename NestedProduct::_RhsNested>
246 {
247   public:
248     typedef ProductBase<ScaledProduct<NestedProduct>,
249                        typename NestedProduct::_LhsNested,
250                        typename NestedProduct::_RhsNested> Base;
251     typedef typename Base::Scalar Scalar;
252     typedef typename Base::PlainObject PlainObject;
253 //     EIGEN_PRODUCT_PUBLIC_INTERFACE(ScaledProduct)
254
255     ScaledProduct(const NestedProduct& prod, Scalar x)
256     : Base(prod.lhs(),prod.rhs()), m_prod(prod), m_alpha(x) {}
257
258     template<typename Dest>
259     inline void evalTo(Dest& dst) const { dst.setZero(); scaleAndAddTo(dst,m_alpha); }
260
261     template<typename Dest>
262     inline void addTo(Dest& dst) const { scaleAndAddTo(dst,m_alpha); }
263
264     template<typename Dest>
265     inline void subTo(Dest& dst) const { scaleAndAddTo(dst,-m_alpha); }
266
267     template<typename Dest>
268     inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { m_prod.derived().scaleAndAddTo(dst,alpha); }
269
270     const Scalar& alpha() const { return m_alpha; }
271     
272   protected:
273     const NestedProduct& m_prod;
274     Scalar m_alpha;
275 };
276
277 /** \internal
278   * Overloaded to perform an efficient C = (A*B).lazy() */
279 template<typename Derived>
280 template<typename ProductDerived, typename Lhs, typename Rhs>
281 Derived& MatrixBase<Derived>::lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other)
282 {
283   other.derived().evalTo(derived());
284   return derived();
285 }
286
287
288 #endif // EIGEN_PRODUCTBASE_H