TriangularMatrixVector.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 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_TRIANGULARMATRIXVECTOR_H
00011 #define EIGEN_TRIANGULARMATRIXVECTOR_H
00012 
00013 namespace Eigen { 
00014 
00015 namespace internal {
00016 
00017 template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs, int StorageOrder, int Version=Specialized>
00018 struct triangular_matrix_vector_product;
00019 
00020 template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs, int Version>
00021 struct triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,ColMajor,Version>
00022 {
00023   typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
00024   enum {
00025     IsLower = ((Mode&Lower)==Lower),
00026     HasUnitDiag = (Mode & UnitDiag)==UnitDiag,
00027     HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag
00028   };
00029   static EIGEN_DONT_INLINE  void run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
00030                                      const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha);
00031 };
00032 
00033 template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs, int Version>
00034 EIGEN_DONT_INLINE void triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,ColMajor,Version>
00035   ::run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
00036         const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha)
00037   {
00038     static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
00039     Index size = (std::min)(_rows,_cols);
00040     Index rows = IsLower ? _rows : (std::min)(_rows,_cols);
00041     Index cols = IsLower ? (std::min)(_rows,_cols) : _cols;
00042 
00043     typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,ColMajor>, 0, OuterStride<> > LhsMap;
00044     const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride));
00045     typename conj_expr_if<ConjLhs,LhsMap>::type cjLhs(lhs);
00046     
00047     typedef Map<const Matrix<RhsScalar,Dynamic,1>, 0, InnerStride<> > RhsMap;
00048     const RhsMap rhs(_rhs,cols,InnerStride<>(rhsIncr));
00049     typename conj_expr_if<ConjRhs,RhsMap>::type cjRhs(rhs);
00050 
00051     typedef Map<Matrix<ResScalar,Dynamic,1> > ResMap;
00052     ResMap res(_res,rows);
00053 
00054     for (Index pi=0; pi<size; pi+=PanelWidth)
00055     {
00056       Index actualPanelWidth = (std::min)(PanelWidth, size-pi);
00057       for (Index k=0; k<actualPanelWidth; ++k)
00058       {
00059         Index i = pi + k;
00060         Index s = IsLower ? ((HasUnitDiag||HasZeroDiag) ? i+1 : i ) : pi;
00061         Index r = IsLower ? actualPanelWidth-k : k+1;
00062         if ((!(HasUnitDiag||HasZeroDiag)) || (--r)>0)
00063           res.segment(s,r) += (alpha * cjRhs.coeff(i)) * cjLhs.col(i).segment(s,r);
00064         if (HasUnitDiag)
00065           res.coeffRef(i) += alpha * cjRhs.coeff(i);
00066       }
00067       Index r = IsLower ? rows - pi - actualPanelWidth : pi;
00068       if (r>0)
00069       {
00070         Index s = IsLower ? pi+actualPanelWidth : 0;
00071         general_matrix_vector_product<Index,LhsScalar,ColMajor,ConjLhs,RhsScalar,ConjRhs,BuiltIn>::run(
00072             r, actualPanelWidth,
00073             &lhs.coeffRef(s,pi), lhsStride,
00074             &rhs.coeffRef(pi), rhsIncr,
00075             &res.coeffRef(s), resIncr, alpha);
00076       }
00077     }
00078     if((!IsLower) && cols>size)
00079     {
00080       general_matrix_vector_product<Index,LhsScalar,ColMajor,ConjLhs,RhsScalar,ConjRhs>::run(
00081           rows, cols-size,
00082           &lhs.coeffRef(0,size), lhsStride,
00083           &rhs.coeffRef(size), rhsIncr,
00084           _res, resIncr, alpha);
00085     }
00086   }
00087 
00088 template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs,int Version>
00089 struct triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,RowMajor,Version>
00090 {
00091   typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
00092   enum {
00093     IsLower = ((Mode&Lower)==Lower),
00094     HasUnitDiag = (Mode & UnitDiag)==UnitDiag,
00095     HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag
00096   };
00097   static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
00098                                     const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha);
00099 };
00100 
00101 template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs,int Version>
00102 EIGEN_DONT_INLINE void triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,RowMajor,Version>
00103   ::run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
00104         const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha)
00105   {
00106     static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
00107     Index diagSize = (std::min)(_rows,_cols);
00108     Index rows = IsLower ? _rows : diagSize;
00109     Index cols = IsLower ? diagSize : _cols;
00110 
00111     typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,RowMajor>, 0, OuterStride<> > LhsMap;
00112     const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride));
00113     typename conj_expr_if<ConjLhs,LhsMap>::type cjLhs(lhs);
00114 
00115     typedef Map<const Matrix<RhsScalar,Dynamic,1> > RhsMap;
00116     const RhsMap rhs(_rhs,cols);
00117     typename conj_expr_if<ConjRhs,RhsMap>::type cjRhs(rhs);
00118 
00119     typedef Map<Matrix<ResScalar,Dynamic,1>, 0, InnerStride<> > ResMap;
00120     ResMap res(_res,rows,InnerStride<>(resIncr));
00121     
00122     for (Index pi=0; pi<diagSize; pi+=PanelWidth)
00123     {
00124       Index actualPanelWidth = (std::min)(PanelWidth, diagSize-pi);
00125       for (Index k=0; k<actualPanelWidth; ++k)
00126       {
00127         Index i = pi + k;
00128         Index s = IsLower ? pi  : ((HasUnitDiag||HasZeroDiag) ? i+1 : i);
00129         Index r = IsLower ? k+1 : actualPanelWidth-k;
00130         if ((!(HasUnitDiag||HasZeroDiag)) || (--r)>0)
00131           res.coeffRef(i) += alpha * (cjLhs.row(i).segment(s,r).cwiseProduct(cjRhs.segment(s,r).transpose())).sum();
00132         if (HasUnitDiag)
00133           res.coeffRef(i) += alpha * cjRhs.coeff(i);
00134       }
00135       Index r = IsLower ? pi : cols - pi - actualPanelWidth;
00136       if (r>0)
00137       {
00138         Index s = IsLower ? 0 : pi + actualPanelWidth;
00139         general_matrix_vector_product<Index,LhsScalar,RowMajor,ConjLhs,RhsScalar,ConjRhs,BuiltIn>::run(
00140             actualPanelWidth, r,
00141             &lhs.coeffRef(pi,s), lhsStride,
00142             &rhs.coeffRef(s), rhsIncr,
00143             &res.coeffRef(pi), resIncr, alpha);
00144       }
00145     }
00146     if(IsLower && rows>diagSize)
00147     {
00148       general_matrix_vector_product<Index,LhsScalar,RowMajor,ConjLhs,RhsScalar,ConjRhs>::run(
00149             rows-diagSize, cols,
00150             &lhs.coeffRef(diagSize,0), lhsStride,
00151             &rhs.coeffRef(0), rhsIncr,
00152             &res.coeffRef(diagSize), resIncr, alpha);
00153     }
00154   }
00155 
00156 /***************************************************************************
00157 * Wrapper to product_triangular_vector
00158 ***************************************************************************/
00159 
00160 template<int Mode, bool LhsIsTriangular, typename Lhs, typename Rhs>
00161 struct traits<TriangularProduct<Mode,LhsIsTriangular,Lhs,false,Rhs,true> >
00162  : traits<ProductBase<TriangularProduct<Mode,LhsIsTriangular,Lhs,false,Rhs,true>, Lhs, Rhs> >
00163 {};
00164 
00165 template<int Mode, bool LhsIsTriangular, typename Lhs, typename Rhs>
00166 struct traits<TriangularProduct<Mode,LhsIsTriangular,Lhs,true,Rhs,false> >
00167  : traits<ProductBase<TriangularProduct<Mode,LhsIsTriangular,Lhs,true,Rhs,false>, Lhs, Rhs> >
00168 {};
00169 
00170 
00171 template<int StorageOrder>
00172 struct trmv_selector;
00173 
00174 } // end namespace internal
00175 
00176 template<int Mode, typename Lhs, typename Rhs>
00177 struct TriangularProduct<Mode,true,Lhs,false,Rhs,true>
00178   : public ProductBase<TriangularProduct<Mode,true,Lhs,false,Rhs,true>, Lhs, Rhs >
00179 {
00180   EIGEN_PRODUCT_PUBLIC_INTERFACE(TriangularProduct)
00181 
00182   TriangularProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
00183 
00184   template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
00185   {
00186     eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
00187   
00188     internal::trmv_selector<(int(internal::traits<Lhs>::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dst, alpha);
00189   }
00190 };
00191 
00192 template<int Mode, typename Lhs, typename Rhs>
00193 struct TriangularProduct<Mode,false,Lhs,true,Rhs,false>
00194   : public ProductBase<TriangularProduct<Mode,false,Lhs,true,Rhs,false>, Lhs, Rhs >
00195 {
00196   EIGEN_PRODUCT_PUBLIC_INTERFACE(TriangularProduct)
00197 
00198   TriangularProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
00199 
00200   template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
00201   {
00202     eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
00203 
00204     typedef TriangularProduct<(Mode & (UnitDiag|ZeroDiag)) | ((Mode & Lower) ? Upper : Lower),true,Transpose<const Rhs>,false,Transpose<const Lhs>,true> TriangularProductTranspose;
00205     Transpose<Dest> dstT(dst);
00206     internal::trmv_selector<(int(internal::traits<Rhs>::Flags)&RowMajorBit) ? ColMajor : RowMajor>::run(
00207       TriangularProductTranspose(m_rhs.transpose(),m_lhs.transpose()), dstT, alpha);
00208   }
00209 };
00210 
00211 namespace internal {
00212 
00213 // TODO: find a way to factorize this piece of code with gemv_selector since the logic is exactly the same.
00214   
00215 template<> struct trmv_selector<ColMajor>
00216 {
00217   template<int Mode, typename Lhs, typename Rhs, typename Dest>
00218   static void run(const TriangularProduct<Mode,true,Lhs,false,Rhs,true>& prod, Dest& dest, const typename TriangularProduct<Mode,true,Lhs,false,Rhs,true>::Scalar& alpha)
00219   {
00220     typedef TriangularProduct<Mode,true,Lhs,false,Rhs,true> ProductType;
00221     typedef typename ProductType::Index Index;
00222     typedef typename ProductType::LhsScalar   LhsScalar;
00223     typedef typename ProductType::RhsScalar   RhsScalar;
00224     typedef typename ProductType::Scalar      ResScalar;
00225     typedef typename ProductType::RealScalar  RealScalar;
00226     typedef typename ProductType::ActualLhsType ActualLhsType;
00227     typedef typename ProductType::ActualRhsType ActualRhsType;
00228     typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
00229     typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
00230     typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest;
00231 
00232     typename internal::add_const_on_value_type<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
00233     typename internal::add_const_on_value_type<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
00234 
00235     ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
00236                                   * RhsBlasTraits::extractScalarFactor(prod.rhs());
00237 
00238     enum {
00239       // FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
00240       // on, the other hand it is good for the cache to pack the vector anyways...
00241       EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1,
00242       ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
00243       MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal
00244     };
00245 
00246     gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
00247 
00248     bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
00249     bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
00250     
00251     RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
00252 
00253     ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
00254                                                   evalToDest ? dest.data() : static_dest.data());
00255 
00256     if(!evalToDest)
00257     {
00258       #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00259       Index size = dest.size();
00260       EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00261       #endif
00262       if(!alphaIsCompatible)
00263       {
00264         MappedDest(actualDestPtr, dest.size()).setZero();
00265         compatibleAlpha = RhsScalar(1);
00266       }
00267       else
00268         MappedDest(actualDestPtr, dest.size()) = dest;
00269     }
00270     
00271     internal::triangular_matrix_vector_product
00272       <Index,Mode,
00273        LhsScalar, LhsBlasTraits::NeedToConjugate,
00274        RhsScalar, RhsBlasTraits::NeedToConjugate,
00275        ColMajor>
00276       ::run(actualLhs.rows(),actualLhs.cols(),
00277             actualLhs.data(),actualLhs.outerStride(),
00278             actualRhs.data(),actualRhs.innerStride(),
00279             actualDestPtr,1,compatibleAlpha);
00280 
00281     if (!evalToDest)
00282     {
00283       if(!alphaIsCompatible)
00284         dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
00285       else
00286         dest = MappedDest(actualDestPtr, dest.size());
00287     }
00288   }
00289 };
00290 
00291 template<> struct trmv_selector<RowMajor>
00292 {
00293   template<int Mode, typename Lhs, typename Rhs, typename Dest>
00294   static void run(const TriangularProduct<Mode,true,Lhs,false,Rhs,true>& prod, Dest& dest, const typename TriangularProduct<Mode,true,Lhs,false,Rhs,true>::Scalar& alpha)
00295   {
00296     typedef TriangularProduct<Mode,true,Lhs,false,Rhs,true> ProductType;
00297     typedef typename ProductType::LhsScalar LhsScalar;
00298     typedef typename ProductType::RhsScalar RhsScalar;
00299     typedef typename ProductType::Scalar    ResScalar;
00300     typedef typename ProductType::Index Index;
00301     typedef typename ProductType::ActualLhsType ActualLhsType;
00302     typedef typename ProductType::ActualRhsType ActualRhsType;
00303     typedef typename ProductType::_ActualRhsType _ActualRhsType;
00304     typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
00305     typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
00306 
00307     typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
00308     typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
00309 
00310     ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
00311                                   * RhsBlasTraits::extractScalarFactor(prod.rhs());
00312 
00313     enum {
00314       DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1
00315     };
00316 
00317     gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
00318 
00319     ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(),
00320         DirectlyUseRhs ? const_cast<RhsScalar*>(actualRhs.data()) : static_rhs.data());
00321 
00322     if(!DirectlyUseRhs)
00323     {
00324       #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00325       int size = actualRhs.size();
00326       EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00327       #endif
00328       Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
00329     }
00330     
00331     internal::triangular_matrix_vector_product
00332       <Index,Mode,
00333        LhsScalar, LhsBlasTraits::NeedToConjugate,
00334        RhsScalar, RhsBlasTraits::NeedToConjugate,
00335        RowMajor>
00336       ::run(actualLhs.rows(),actualLhs.cols(),
00337             actualLhs.data(),actualLhs.outerStride(),
00338             actualRhsPtr,1,
00339             dest.data(),dest.innerStride(),
00340             actualAlpha);
00341   }
00342 };
00343 
00344 } // end namespace internal
00345 
00346 } // end namespace Eigen
00347 
00348 #endif // EIGEN_TRIANGULARMATRIXVECTOR_H


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Thu Aug 27 2015 12:01:17