ProductBase.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_PRODUCTBASE_H
00011 #define EIGEN_PRODUCTBASE_H
00012 
00013 namespace Eigen { 
00014 
00020 namespace internal {
00021 template<typename Derived, typename _Lhs, typename _Rhs>
00022 struct traits<ProductBase<Derived,_Lhs,_Rhs> >
00023 {
00024   typedef MatrixXpr XprKind;
00025   typedef typename remove_all<_Lhs>::type Lhs;
00026   typedef typename remove_all<_Rhs>::type Rhs;
00027   typedef typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar;
00028   typedef typename promote_storage_type<typename traits<Lhs>::StorageKind,
00029                                            typename traits<Rhs>::StorageKind>::ret StorageKind;
00030   typedef typename promote_index_type<typename traits<Lhs>::Index,
00031                                          typename traits<Rhs>::Index>::type Index;
00032   enum {
00033     RowsAtCompileTime = traits<Lhs>::RowsAtCompileTime,
00034     ColsAtCompileTime = traits<Rhs>::ColsAtCompileTime,
00035     MaxRowsAtCompileTime = traits<Lhs>::MaxRowsAtCompileTime,
00036     MaxColsAtCompileTime = traits<Rhs>::MaxColsAtCompileTime,
00037     Flags = (MaxRowsAtCompileTime==1 ? RowMajorBit : 0)
00038           | EvalBeforeNestingBit | EvalBeforeAssigningBit | NestByRefBit,
00039                   // Note that EvalBeforeNestingBit and NestByRefBit
00040                   // are not used in practice because nested is overloaded for products
00041     CoeffReadCost = 0 // FIXME why is it needed ?
00042   };
00043 };
00044 }
00045 
00046 #define EIGEN_PRODUCT_PUBLIC_INTERFACE(Derived) \
00047   typedef ProductBase<Derived, Lhs, Rhs > Base; \
00048   EIGEN_DENSE_PUBLIC_INTERFACE(Derived) \
00049   typedef typename Base::LhsNested LhsNested; \
00050   typedef typename Base::_LhsNested _LhsNested; \
00051   typedef typename Base::LhsBlasTraits LhsBlasTraits; \
00052   typedef typename Base::ActualLhsType ActualLhsType; \
00053   typedef typename Base::_ActualLhsType _ActualLhsType; \
00054   typedef typename Base::RhsNested RhsNested; \
00055   typedef typename Base::_RhsNested _RhsNested; \
00056   typedef typename Base::RhsBlasTraits RhsBlasTraits; \
00057   typedef typename Base::ActualRhsType ActualRhsType; \
00058   typedef typename Base::_ActualRhsType _ActualRhsType; \
00059   using Base::m_lhs; \
00060   using Base::m_rhs;
00061 
00062 template<typename Derived, typename Lhs, typename Rhs>
00063 class ProductBase : public MatrixBase<Derived>
00064 {
00065   public:
00066     typedef MatrixBase<Derived> Base;
00067     EIGEN_DENSE_PUBLIC_INTERFACE(ProductBase)
00068     
00069     typedef typename Lhs::Nested LhsNested;
00070     typedef typename internal::remove_all<LhsNested>::type _LhsNested;
00071     typedef internal::blas_traits<_LhsNested> LhsBlasTraits;
00072     typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType;
00073     typedef typename internal::remove_all<ActualLhsType>::type _ActualLhsType;
00074     typedef typename internal::traits<Lhs>::Scalar LhsScalar;
00075 
00076     typedef typename Rhs::Nested RhsNested;
00077     typedef typename internal::remove_all<RhsNested>::type _RhsNested;
00078     typedef internal::blas_traits<_RhsNested> RhsBlasTraits;
00079     typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
00080     typedef typename internal::remove_all<ActualRhsType>::type _ActualRhsType;
00081     typedef typename internal::traits<Rhs>::Scalar RhsScalar;
00082 
00083     // Diagonal of a product: no need to evaluate the arguments because they are going to be evaluated only once
00084     typedef CoeffBasedProduct<LhsNested, RhsNested, 0> FullyLazyCoeffBaseProductType;
00085 
00086   public:
00087 
00088     typedef typename Base::PlainObject PlainObject;
00089 
00090     ProductBase(const Lhs& a_lhs, const Rhs& a_rhs)
00091       : m_lhs(a_lhs), m_rhs(a_rhs)
00092     {
00093       eigen_assert(a_lhs.cols() == a_rhs.rows()
00094         && "invalid matrix product"
00095         && "if you wanted a coeff-wise or a dot product use the respective explicit functions");
00096     }
00097 
00098     inline Index rows() const { return m_lhs.rows(); }
00099     inline Index cols() const { return m_rhs.cols(); }
00100 
00101     template<typename Dest>
00102     inline void evalTo(Dest& dst) const { dst.setZero(); scaleAndAddTo(dst,Scalar(1)); }
00103 
00104     template<typename Dest>
00105     inline void addTo(Dest& dst) const { scaleAndAddTo(dst,Scalar(1)); }
00106 
00107     template<typename Dest>
00108     inline void subTo(Dest& dst) const { scaleAndAddTo(dst,Scalar(-1)); }
00109 
00110     template<typename Dest>
00111     inline void scaleAndAddTo(Dest& dst, const Scalar& alpha) const { derived().scaleAndAddTo(dst,alpha); }
00112 
00113     const _LhsNested& lhs() const { return m_lhs; }
00114     const _RhsNested& rhs() const { return m_rhs; }
00115 
00116     // Implicit conversion to the nested type (trigger the evaluation of the product)
00117     operator const PlainObject& () const
00118     {
00119       m_result.resize(m_lhs.rows(), m_rhs.cols());
00120       derived().evalTo(m_result);
00121       return m_result;
00122     }
00123 
00124     const Diagonal<const FullyLazyCoeffBaseProductType,0> diagonal() const
00125     { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); }
00126 
00127     template<int Index>
00128     const Diagonal<FullyLazyCoeffBaseProductType,Index> diagonal() const
00129     { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); }
00130 
00131     const Diagonal<FullyLazyCoeffBaseProductType,Dynamic> diagonal(Index index) const
00132     { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); }
00133 
00134     // restrict coeff accessors to 1x1 expressions. No need to care about mutators here since this isnt a Lvalue expression
00135     typename Base::CoeffReturnType coeff(Index row, Index col) const
00136     {
00137 #ifdef EIGEN2_SUPPORT
00138       return lhs().row(row).cwiseProduct(rhs().col(col).transpose()).sum();
00139 #else
00140       EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
00141       eigen_assert(this->rows() == 1 && this->cols() == 1);
00142       Matrix<Scalar,1,1> result = *this;
00143       return result.coeff(row,col);
00144 #endif
00145     }
00146 
00147     typename Base::CoeffReturnType coeff(Index i) const
00148     {
00149       EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
00150       eigen_assert(this->rows() == 1 && this->cols() == 1);
00151       Matrix<Scalar,1,1> result = *this;
00152       return result.coeff(i);
00153     }
00154 
00155     const Scalar& coeffRef(Index row, Index col) const
00156     {
00157       EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
00158       eigen_assert(this->rows() == 1 && this->cols() == 1);
00159       return derived().coeffRef(row,col);
00160     }
00161 
00162     const Scalar& coeffRef(Index i) const
00163     {
00164       EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
00165       eigen_assert(this->rows() == 1 && this->cols() == 1);
00166       return derived().coeffRef(i);
00167     }
00168 
00169   protected:
00170 
00171     LhsNested m_lhs;
00172     RhsNested m_rhs;
00173 
00174     mutable PlainObject m_result;
00175 };
00176 
00177 // here we need to overload the nested rule for products
00178 // such that the nested type is a const reference to a plain matrix
00179 namespace internal {
00180 template<typename Lhs, typename Rhs, int Mode, int N, typename PlainObject>
00181 struct nested<GeneralProduct<Lhs,Rhs,Mode>, N, PlainObject>
00182 {
00183   typedef PlainObject const& type;
00184 };
00185 }
00186 
00187 template<typename NestedProduct>
00188 class ScaledProduct;
00189 
00190 // Note that these two operator* functions are not defined as member
00191 // functions of ProductBase, because, otherwise we would have to
00192 // define all overloads defined in MatrixBase. Furthermore, Using
00193 // "using Base::operator*" would not work with MSVC.
00194 //
00195 // Also note that here we accept any compatible scalar types
00196 template<typename Derived,typename Lhs,typename Rhs>
00197 const ScaledProduct<Derived>
00198 operator*(const ProductBase<Derived,Lhs,Rhs>& prod, const typename Derived::Scalar& x)
00199 { return ScaledProduct<Derived>(prod.derived(), x); }
00200 
00201 template<typename Derived,typename Lhs,typename Rhs>
00202 typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
00203                       const ScaledProduct<Derived> >::type
00204 operator*(const ProductBase<Derived,Lhs,Rhs>& prod, const typename Derived::RealScalar& x)
00205 { return ScaledProduct<Derived>(prod.derived(), x); }
00206 
00207 
00208 template<typename Derived,typename Lhs,typename Rhs>
00209 const ScaledProduct<Derived>
00210 operator*(const typename Derived::Scalar& x,const ProductBase<Derived,Lhs,Rhs>& prod)
00211 { return ScaledProduct<Derived>(prod.derived(), x); }
00212 
00213 template<typename Derived,typename Lhs,typename Rhs>
00214 typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
00215                       const ScaledProduct<Derived> >::type
00216 operator*(const typename Derived::RealScalar& x,const ProductBase<Derived,Lhs,Rhs>& prod)
00217 { return ScaledProduct<Derived>(prod.derived(), x); }
00218 
00219 namespace internal {
00220 template<typename NestedProduct>
00221 struct traits<ScaledProduct<NestedProduct> >
00222  : traits<ProductBase<ScaledProduct<NestedProduct>,
00223                          typename NestedProduct::_LhsNested,
00224                          typename NestedProduct::_RhsNested> >
00225 {
00226   typedef typename traits<NestedProduct>::StorageKind StorageKind;
00227 };
00228 }
00229 
00230 template<typename NestedProduct>
00231 class ScaledProduct
00232   : public ProductBase<ScaledProduct<NestedProduct>,
00233                        typename NestedProduct::_LhsNested,
00234                        typename NestedProduct::_RhsNested>
00235 {
00236   public:
00237     typedef ProductBase<ScaledProduct<NestedProduct>,
00238                        typename NestedProduct::_LhsNested,
00239                        typename NestedProduct::_RhsNested> Base;
00240     typedef typename Base::Scalar Scalar;
00241     typedef typename Base::PlainObject PlainObject;
00242 //     EIGEN_PRODUCT_PUBLIC_INTERFACE(ScaledProduct)
00243 
00244     ScaledProduct(const NestedProduct& prod, const Scalar& x)
00245     : Base(prod.lhs(),prod.rhs()), m_prod(prod), m_alpha(x) {}
00246 
00247     template<typename Dest>
00248     inline void evalTo(Dest& dst) const { dst.setZero(); scaleAndAddTo(dst, Scalar(1)); }
00249 
00250     template<typename Dest>
00251     inline void addTo(Dest& dst) const { scaleAndAddTo(dst, Scalar(1)); }
00252 
00253     template<typename Dest>
00254     inline void subTo(Dest& dst) const { scaleAndAddTo(dst, Scalar(-1)); }
00255 
00256     template<typename Dest>
00257     inline void scaleAndAddTo(Dest& dst, const Scalar& a_alpha) const { m_prod.derived().scaleAndAddTo(dst,a_alpha * m_alpha); }
00258 
00259     const Scalar& alpha() const { return m_alpha; }
00260     
00261   protected:
00262     const NestedProduct& m_prod;
00263     Scalar m_alpha;
00264 };
00265 
00268 template<typename Derived>
00269 template<typename ProductDerived, typename Lhs, typename Rhs>
00270 Derived& MatrixBase<Derived>::lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other)
00271 {
00272   other.derived().evalTo(derived());
00273   return derived();
00274 }
00275 
00276 } // end namespace Eigen
00277 
00278 #endif // EIGEN_PRODUCTBASE_H


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Thu Aug 27 2015 11:59:50