GeneralProduct.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) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
00005 // Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
00006 //
00007 // This Source Code Form is subject to the terms of the Mozilla
00008 // Public License v. 2.0. If a copy of the MPL was not distributed
00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00010 
00011 #ifndef EIGEN_GENERAL_PRODUCT_H
00012 #define EIGEN_GENERAL_PRODUCT_H
00013 
00014 namespace Eigen { 
00015 
00035 template<typename Lhs, typename Rhs, int ProductType = internal::product_type<Lhs,Rhs>::value>
00036 class GeneralProduct;
00037 
00038 enum {
00039   Large = 2,
00040   Small = 3
00041 };
00042 
00043 namespace internal {
00044 
00045 template<int Rows, int Cols, int Depth> struct product_type_selector;
00046 
00047 template<int Size, int MaxSize> struct product_size_category
00048 {
00049   enum { is_large = MaxSize == Dynamic ||
00050                     Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD,
00051          value = is_large  ? Large
00052                : Size == 1 ? 1
00053                            : Small
00054   };
00055 };
00056 
00057 template<typename Lhs, typename Rhs> struct product_type
00058 {
00059   typedef typename remove_all<Lhs>::type _Lhs;
00060   typedef typename remove_all<Rhs>::type _Rhs;
00061   enum {
00062     MaxRows  = _Lhs::MaxRowsAtCompileTime,
00063     Rows  = _Lhs::RowsAtCompileTime,
00064     MaxCols  = _Rhs::MaxColsAtCompileTime,
00065     Cols  = _Rhs::ColsAtCompileTime,
00066     MaxDepth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::MaxColsAtCompileTime,
00067                                            _Rhs::MaxRowsAtCompileTime),
00068     Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime,
00069                                         _Rhs::RowsAtCompileTime),
00070     LargeThreshold = EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
00071   };
00072 
00073   // the splitting into different lines of code here, introducing the _select enums and the typedef below,
00074   // is to work around an internal compiler error with gcc 4.1 and 4.2.
00075 private:
00076   enum {
00077     rows_select = product_size_category<Rows,MaxRows>::value,
00078     cols_select = product_size_category<Cols,MaxCols>::value,
00079     depth_select = product_size_category<Depth,MaxDepth>::value
00080   };
00081   typedef product_type_selector<rows_select, cols_select, depth_select> selector;
00082 
00083 public:
00084   enum {
00085     value = selector::ret
00086   };
00087 #ifdef EIGEN_DEBUG_PRODUCT
00088   static void debug()
00089   {
00090       EIGEN_DEBUG_VAR(Rows);
00091       EIGEN_DEBUG_VAR(Cols);
00092       EIGEN_DEBUG_VAR(Depth);
00093       EIGEN_DEBUG_VAR(rows_select);
00094       EIGEN_DEBUG_VAR(cols_select);
00095       EIGEN_DEBUG_VAR(depth_select);
00096       EIGEN_DEBUG_VAR(value);
00097   }
00098 #endif
00099 };
00100 
00101 
00102 /* The following allows to select the kind of product at compile time
00103  * based on the three dimensions of the product.
00104  * This is a compile time mapping from {1,Small,Large}^3 -> {product types} */
00105 // FIXME I'm not sure the current mapping is the ideal one.
00106 template<int M, int N>  struct product_type_selector<M,N,1>              { enum { ret = OuterProduct }; };
00107 template<int Depth>     struct product_type_selector<1,    1,    Depth>  { enum { ret = InnerProduct }; };
00108 template<>              struct product_type_selector<1,    1,    1>      { enum { ret = InnerProduct }; };
00109 template<>              struct product_type_selector<Small,1,    Small>  { enum { ret = CoeffBasedProductMode }; };
00110 template<>              struct product_type_selector<1,    Small,Small>  { enum { ret = CoeffBasedProductMode }; };
00111 template<>              struct product_type_selector<Small,Small,Small>  { enum { ret = CoeffBasedProductMode }; };
00112 template<>              struct product_type_selector<Small, Small, 1>    { enum { ret = LazyCoeffBasedProductMode }; };
00113 template<>              struct product_type_selector<Small, Large, 1>    { enum { ret = LazyCoeffBasedProductMode }; };
00114 template<>              struct product_type_selector<Large, Small, 1>    { enum { ret = LazyCoeffBasedProductMode }; };
00115 template<>              struct product_type_selector<1,    Large,Small>  { enum { ret = CoeffBasedProductMode }; };
00116 template<>              struct product_type_selector<1,    Large,Large>  { enum { ret = GemvProduct }; };
00117 template<>              struct product_type_selector<1,    Small,Large>  { enum { ret = CoeffBasedProductMode }; };
00118 template<>              struct product_type_selector<Large,1,    Small>  { enum { ret = CoeffBasedProductMode }; };
00119 template<>              struct product_type_selector<Large,1,    Large>  { enum { ret = GemvProduct }; };
00120 template<>              struct product_type_selector<Small,1,    Large>  { enum { ret = CoeffBasedProductMode }; };
00121 template<>              struct product_type_selector<Small,Small,Large>  { enum { ret = GemmProduct }; };
00122 template<>              struct product_type_selector<Large,Small,Large>  { enum { ret = GemmProduct }; };
00123 template<>              struct product_type_selector<Small,Large,Large>  { enum { ret = GemmProduct }; };
00124 template<>              struct product_type_selector<Large,Large,Large>  { enum { ret = GemmProduct }; };
00125 template<>              struct product_type_selector<Large,Small,Small>  { enum { ret = GemmProduct }; };
00126 template<>              struct product_type_selector<Small,Large,Small>  { enum { ret = GemmProduct }; };
00127 template<>              struct product_type_selector<Large,Large,Small>  { enum { ret = GemmProduct }; };
00128 
00129 } // end namespace internal
00130 
00148 template<typename Lhs, typename Rhs, int ProductType>
00149 struct ProductReturnType
00150 {
00151   // TODO use the nested type to reduce instanciations ????
00152 //   typedef typename internal::nested<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
00153 //   typedef typename internal::nested<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
00154 
00155   typedef GeneralProduct<Lhs/*Nested*/, Rhs/*Nested*/, ProductType> Type;
00156 };
00157 
00158 template<typename Lhs, typename Rhs>
00159 struct ProductReturnType<Lhs,Rhs,CoeffBasedProductMode>
00160 {
00161   typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type LhsNested;
00162   typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type RhsNested;
00163   typedef CoeffBasedProduct<LhsNested, RhsNested, EvalBeforeAssigningBit | EvalBeforeNestingBit> Type;
00164 };
00165 
00166 template<typename Lhs, typename Rhs>
00167 struct ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode>
00168 {
00169   typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type LhsNested;
00170   typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type RhsNested;
00171   typedef CoeffBasedProduct<LhsNested, RhsNested, NestByRefBit> Type;
00172 };
00173 
00174 // this is a workaround for sun CC
00175 template<typename Lhs, typename Rhs>
00176 struct LazyProductReturnType : public ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode>
00177 {};
00178 
00179 /***********************************************************************
00180 *  Implementation of Inner Vector Vector Product
00181 ***********************************************************************/
00182 
00183 // FIXME : maybe the "inner product" could return a Scalar
00184 // instead of a 1x1 matrix ??
00185 // Pro: more natural for the user
00186 // Cons: this could be a problem if in a meta unrolled algorithm a matrix-matrix
00187 // product ends up to a row-vector times col-vector product... To tackle this use
00188 // case, we could have a specialization for Block<MatrixType,1,1> with: operator=(Scalar x);
00189 
00190 namespace internal {
00191 
00192 template<typename Lhs, typename Rhs>
00193 struct traits<GeneralProduct<Lhs,Rhs,InnerProduct> >
00194  : traits<Matrix<typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> >
00195 {};
00196 
00197 }
00198 
00199 template<typename Lhs, typename Rhs>
00200 class GeneralProduct<Lhs, Rhs, InnerProduct>
00201   : internal::no_assignment_operator,
00202     public Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1>
00203 {
00204     typedef Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> Base;
00205   public:
00206     GeneralProduct(const Lhs& lhs, const Rhs& rhs)
00207     {
00208       EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
00209         YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00210 
00211       Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
00212     }
00213 
00215     operator const typename Base::Scalar() const {
00216       return Base::coeff(0,0);
00217     }
00218 };
00219 
00220 /***********************************************************************
00221 *  Implementation of Outer Vector Vector Product
00222 ***********************************************************************/
00223 
00224 namespace internal {
00225 template<int StorageOrder> struct outer_product_selector;
00226 
00227 template<typename Lhs, typename Rhs>
00228 struct traits<GeneralProduct<Lhs,Rhs,OuterProduct> >
00229  : traits<ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs> >
00230 {};
00231 
00232 }
00233 
00234 template<typename Lhs, typename Rhs>
00235 class GeneralProduct<Lhs, Rhs, OuterProduct>
00236   : public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
00237 {
00238   public:
00239     EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
00240 
00241     GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
00242     {
00243       EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
00244         YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00245     }
00246 
00247     template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
00248     {
00249       internal::outer_product_selector<(int(Dest::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dest, alpha);
00250     }
00251 };
00252 
00253 namespace internal {
00254 
00255 template<> struct outer_product_selector<ColMajor> {
00256   template<typename ProductType, typename Dest>
00257   static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
00258     typedef typename Dest::Index Index;
00259     // FIXME make sure lhs is sequentially stored
00260     // FIXME not very good if rhs is real and lhs complex while alpha is real too
00261     const Index cols = dest.cols();
00262     for (Index j=0; j<cols; ++j)
00263       dest.col(j) += (alpha * prod.rhs().coeff(j)) * prod.lhs();
00264   }
00265 };
00266 
00267 template<> struct outer_product_selector<RowMajor> {
00268   template<typename ProductType, typename Dest>
00269   static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
00270     typedef typename Dest::Index Index;
00271     // FIXME make sure rhs is sequentially stored
00272     // FIXME not very good if lhs is real and rhs complex while alpha is real too
00273     const Index rows = dest.rows();
00274     for (Index i=0; i<rows; ++i)
00275       dest.row(i) += (alpha * prod.lhs().coeff(i)) * prod.rhs();
00276   }
00277 };
00278 
00279 } // end namespace internal
00280 
00281 /***********************************************************************
00282 *  Implementation of General Matrix Vector Product
00283 ***********************************************************************/
00284 
00285 /*  According to the shape/flags of the matrix we have to distinghish 3 different cases:
00286  *   1 - the matrix is col-major, BLAS compatible and M is large => call fast BLAS-like colmajor routine
00287  *   2 - the matrix is row-major, BLAS compatible and N is large => call fast BLAS-like rowmajor routine
00288  *   3 - all other cases are handled using a simple loop along the outer-storage direction.
00289  *  Therefore we need a lower level meta selector.
00290  *  Furthermore, if the matrix is the rhs, then the product has to be transposed.
00291  */
00292 namespace internal {
00293 
00294 template<typename Lhs, typename Rhs>
00295 struct traits<GeneralProduct<Lhs,Rhs,GemvProduct> >
00296  : traits<ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs> >
00297 {};
00298 
00299 template<int Side, int StorageOrder, bool BlasCompatible>
00300 struct gemv_selector;
00301 
00302 } // end namespace internal
00303 
00304 template<typename Lhs, typename Rhs>
00305 class GeneralProduct<Lhs, Rhs, GemvProduct>
00306   : public ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs>
00307 {
00308   public:
00309     EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
00310 
00311     typedef typename Lhs::Scalar LhsScalar;
00312     typedef typename Rhs::Scalar RhsScalar;
00313 
00314     GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
00315     {
00316 //       EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::Scalar, typename Rhs::Scalar>::value),
00317 //         YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00318     }
00319 
00320     enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight };
00321     typedef typename internal::conditional<int(Side)==OnTheRight,_LhsNested,_RhsNested>::type MatrixType;
00322 
00323     template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
00324     {
00325       eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols());
00326       internal::gemv_selector<Side,(int(MatrixType::Flags)&RowMajorBit) ? RowMajor : ColMajor,
00327                        bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)>::run(*this, dst, alpha);
00328     }
00329 };
00330 
00331 namespace internal {
00332 
00333 // The vector is on the left => transposition
00334 template<int StorageOrder, bool BlasCompatible>
00335 struct gemv_selector<OnTheLeft,StorageOrder,BlasCompatible>
00336 {
00337   template<typename ProductType, typename Dest>
00338   static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00339   {
00340     Transpose<Dest> destT(dest);
00341     enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor };
00342     gemv_selector<OnTheRight,OtherStorageOrder,BlasCompatible>
00343       ::run(GeneralProduct<Transpose<const typename ProductType::_RhsNested>,Transpose<const typename ProductType::_LhsNested>, GemvProduct>
00344         (prod.rhs().transpose(), prod.lhs().transpose()), destT, alpha);
00345   }
00346 };
00347 
00348 template<typename Scalar,int Size,int MaxSize,bool Cond> struct gemv_static_vector_if;
00349 
00350 template<typename Scalar,int Size,int MaxSize>
00351 struct gemv_static_vector_if<Scalar,Size,MaxSize,false>
00352 {
00353   EIGEN_STRONG_INLINE  Scalar* data() { eigen_internal_assert(false && "should never be called"); return 0; }
00354 };
00355 
00356 template<typename Scalar,int Size>
00357 struct gemv_static_vector_if<Scalar,Size,Dynamic,true>
00358 {
00359   EIGEN_STRONG_INLINE Scalar* data() { return 0; }
00360 };
00361 
00362 template<typename Scalar,int Size,int MaxSize>
00363 struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
00364 {
00365   #if EIGEN_ALIGN_STATICALLY
00366   internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data;
00367   EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; }
00368   #else
00369   // Some architectures cannot align on the stack,
00370   // => let's manually enforce alignment by allocating more data and return the address of the first aligned element.
00371   enum {
00372     ForceAlignment  = internal::packet_traits<Scalar>::Vectorizable,
00373     PacketSize      = internal::packet_traits<Scalar>::size
00374   };
00375   internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data;
00376   EIGEN_STRONG_INLINE Scalar* data() {
00377     return ForceAlignment
00378             ? reinterpret_cast<Scalar*>((reinterpret_cast<size_t>(m_data.array) & ~(size_t(15))) + 16)
00379             : m_data.array;
00380   }
00381   #endif
00382 };
00383 
00384 template<> struct gemv_selector<OnTheRight,ColMajor,true>
00385 {
00386   template<typename ProductType, typename Dest>
00387   static inline void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00388   {
00389     typedef typename ProductType::Index Index;
00390     typedef typename ProductType::LhsScalar   LhsScalar;
00391     typedef typename ProductType::RhsScalar   RhsScalar;
00392     typedef typename ProductType::Scalar      ResScalar;
00393     typedef typename ProductType::RealScalar  RealScalar;
00394     typedef typename ProductType::ActualLhsType ActualLhsType;
00395     typedef typename ProductType::ActualRhsType ActualRhsType;
00396     typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
00397     typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
00398     typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest;
00399 
00400     ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs());
00401     ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs());
00402 
00403     ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
00404                                   * RhsBlasTraits::extractScalarFactor(prod.rhs());
00405 
00406     enum {
00407       // FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
00408       // on, the other hand it is good for the cache to pack the vector anyways...
00409       EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1,
00410       ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
00411       MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal
00412     };
00413 
00414     gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
00415 
00416     bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0));
00417     bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
00418     
00419     RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
00420 
00421     ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
00422                                                   evalToDest ? dest.data() : static_dest.data());
00423     
00424     if(!evalToDest)
00425     {
00426       #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00427       int size = dest.size();
00428       EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00429       #endif
00430       if(!alphaIsCompatible)
00431       {
00432         MappedDest(actualDestPtr, dest.size()).setZero();
00433         compatibleAlpha = RhsScalar(1);
00434       }
00435       else
00436         MappedDest(actualDestPtr, dest.size()) = dest;
00437     }
00438 
00439     general_matrix_vector_product
00440       <Index,LhsScalar,ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
00441         actualLhs.rows(), actualLhs.cols(),
00442         actualLhs.data(), actualLhs.outerStride(),
00443         actualRhs.data(), actualRhs.innerStride(),
00444         actualDestPtr, 1,
00445         compatibleAlpha);
00446 
00447     if (!evalToDest)
00448     {
00449       if(!alphaIsCompatible)
00450         dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
00451       else
00452         dest = MappedDest(actualDestPtr, dest.size());
00453     }
00454   }
00455 };
00456 
00457 template<> struct gemv_selector<OnTheRight,RowMajor,true>
00458 {
00459   template<typename ProductType, typename Dest>
00460   static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00461   {
00462     typedef typename ProductType::LhsScalar LhsScalar;
00463     typedef typename ProductType::RhsScalar RhsScalar;
00464     typedef typename ProductType::Scalar    ResScalar;
00465     typedef typename ProductType::Index Index;
00466     typedef typename ProductType::ActualLhsType ActualLhsType;
00467     typedef typename ProductType::ActualRhsType ActualRhsType;
00468     typedef typename ProductType::_ActualRhsType _ActualRhsType;
00469     typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
00470     typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
00471 
00472     typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
00473     typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
00474 
00475     ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
00476                                   * RhsBlasTraits::extractScalarFactor(prod.rhs());
00477 
00478     enum {
00479       // FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
00480       // on, the other hand it is good for the cache to pack the vector anyways...
00481       DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1
00482     };
00483 
00484     gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
00485 
00486     ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(),
00487         DirectlyUseRhs ? const_cast<RhsScalar*>(actualRhs.data()) : static_rhs.data());
00488 
00489     if(!DirectlyUseRhs)
00490     {
00491       #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00492       int size = actualRhs.size();
00493       EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00494       #endif
00495       Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
00496     }
00497 
00498     general_matrix_vector_product
00499       <Index,LhsScalar,RowMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
00500         actualLhs.rows(), actualLhs.cols(),
00501         actualLhs.data(), actualLhs.outerStride(),
00502         actualRhsPtr, 1,
00503         dest.data(), dest.innerStride(),
00504         actualAlpha);
00505   }
00506 };
00507 
00508 template<> struct gemv_selector<OnTheRight,ColMajor,false>
00509 {
00510   template<typename ProductType, typename Dest>
00511   static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00512   {
00513     typedef typename Dest::Index Index;
00514     // TODO makes sure dest is sequentially stored in memory, otherwise use a temp
00515     const Index size = prod.rhs().rows();
00516     for(Index k=0; k<size; ++k)
00517       dest += (alpha*prod.rhs().coeff(k)) * prod.lhs().col(k);
00518   }
00519 };
00520 
00521 template<> struct gemv_selector<OnTheRight,RowMajor,false>
00522 {
00523   template<typename ProductType, typename Dest>
00524   static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00525   {
00526     typedef typename Dest::Index Index;
00527     // TODO makes sure rhs is sequentially stored in memory, otherwise use a temp
00528     const Index rows = prod.rows();
00529     for(Index i=0; i<rows; ++i)
00530       dest.coeffRef(i) += alpha * (prod.lhs().row(i).cwiseProduct(prod.rhs().transpose())).sum();
00531   }
00532 };
00533 
00534 } // end namespace internal
00535 
00536 /***************************************************************************
00537 * Implementation of matrix base methods
00538 ***************************************************************************/
00539 
00546 template<typename Derived>
00547 template<typename OtherDerived>
00548 inline const typename ProductReturnType<Derived, OtherDerived>::Type
00549 MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
00550 {
00551   // A note regarding the function declaration: In MSVC, this function will sometimes
00552   // not be inlined since DenseStorage is an unwindable object for dynamic
00553   // matrices and product types are holding a member to store the result.
00554   // Thus it does not help tagging this function with EIGEN_STRONG_INLINE.
00555   enum {
00556     ProductIsValid =  Derived::ColsAtCompileTime==Dynamic
00557                    || OtherDerived::RowsAtCompileTime==Dynamic
00558                    || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
00559     AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
00560     SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
00561   };
00562   // note to the lost user:
00563   //    * for a dot product use: v1.dot(v2)
00564   //    * for a coeff-wise product use: v1.cwiseProduct(v2)
00565   EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
00566     INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
00567   EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
00568     INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
00569   EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
00570 #ifdef EIGEN_DEBUG_PRODUCT
00571   internal::product_type<Derived,OtherDerived>::debug();
00572 #endif
00573   return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
00574 }
00575 
00587 template<typename Derived>
00588 template<typename OtherDerived>
00589 const typename LazyProductReturnType<Derived,OtherDerived>::Type
00590 MatrixBase<Derived>::lazyProduct(const MatrixBase<OtherDerived> &other) const
00591 {
00592   enum {
00593     ProductIsValid =  Derived::ColsAtCompileTime==Dynamic
00594                    || OtherDerived::RowsAtCompileTime==Dynamic
00595                    || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
00596     AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
00597     SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
00598   };
00599   // note to the lost user:
00600   //    * for a dot product use: v1.dot(v2)
00601   //    * for a coeff-wise product use: v1.cwiseProduct(v2)
00602   EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
00603     INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
00604   EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
00605     INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
00606   EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
00607 
00608   return typename LazyProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
00609 }
00610 
00611 } // end namespace Eigen
00612 
00613 #endif // EIGEN_PRODUCT_H


win_eigen
Author(s): Daniel Stonier
autogenerated on Wed Sep 16 2015 07:10:39