Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
CoeffBasedProduct.h
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-2010 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_COEFFBASED_PRODUCT_H 00012 #define EIGEN_COEFFBASED_PRODUCT_H 00013 00014 namespace Eigen { 00015 00016 namespace internal { 00017 00018 /********************************************************************************* 00019 * Coefficient based product implementation. 00020 * It is designed for the following use cases: 00021 * - small fixed sizes 00022 * - lazy products 00023 *********************************************************************************/ 00024 00025 /* Since the all the dimensions of the product are small, here we can rely 00026 * on the generic Assign mechanism to evaluate the product per coeff (or packet). 00027 * 00028 * Note that here the inner-loops should always be unrolled. 00029 */ 00030 00031 template<int Traversal, int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar> 00032 struct product_coeff_impl; 00033 00034 template<int StorageOrder, int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode> 00035 struct product_packet_impl; 00036 00037 template<typename LhsNested, typename RhsNested, int NestingFlags> 00038 struct traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> > 00039 { 00040 typedef MatrixXpr XprKind; 00041 typedef typename remove_all<LhsNested>::type _LhsNested; 00042 typedef typename remove_all<RhsNested>::type _RhsNested; 00043 typedef typename scalar_product_traits<typename _LhsNested::Scalar, typename _RhsNested::Scalar>::ReturnType Scalar; 00044 typedef typename promote_storage_type<typename traits<_LhsNested>::StorageKind, 00045 typename traits<_RhsNested>::StorageKind>::ret StorageKind; 00046 typedef typename promote_index_type<typename traits<_LhsNested>::Index, 00047 typename traits<_RhsNested>::Index>::type Index; 00048 00049 enum { 00050 LhsCoeffReadCost = _LhsNested::CoeffReadCost, 00051 RhsCoeffReadCost = _RhsNested::CoeffReadCost, 00052 LhsFlags = _LhsNested::Flags, 00053 RhsFlags = _RhsNested::Flags, 00054 00055 RowsAtCompileTime = _LhsNested::RowsAtCompileTime, 00056 ColsAtCompileTime = _RhsNested::ColsAtCompileTime, 00057 InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime), 00058 00059 MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime, 00060 MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime, 00061 00062 LhsRowMajor = LhsFlags & RowMajorBit, 00063 RhsRowMajor = RhsFlags & RowMajorBit, 00064 00065 SameType = is_same<typename _LhsNested::Scalar,typename _RhsNested::Scalar>::value, 00066 00067 CanVectorizeRhs = RhsRowMajor && (RhsFlags & PacketAccessBit) 00068 && (ColsAtCompileTime == Dynamic 00069 || ( (ColsAtCompileTime % packet_traits<Scalar>::size) == 0 00070 && (RhsFlags&AlignedBit) 00071 ) 00072 ), 00073 00074 CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit) 00075 && (RowsAtCompileTime == Dynamic 00076 || ( (RowsAtCompileTime % packet_traits<Scalar>::size) == 0 00077 && (LhsFlags&AlignedBit) 00078 ) 00079 ), 00080 00081 EvalToRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1 00082 : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0 00083 : (RhsRowMajor && !CanVectorizeLhs), 00084 00085 Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & ~RowMajorBit) 00086 | (EvalToRowMajor ? RowMajorBit : 0) 00087 | NestingFlags 00088 | (LhsFlags & RhsFlags & AlignedBit) 00089 // TODO enable vectorization for mixed types 00090 | (SameType && (CanVectorizeLhs || CanVectorizeRhs) ? PacketAccessBit : 0), 00091 00092 CoeffReadCost = InnerSize == Dynamic ? Dynamic 00093 : InnerSize == 0 ? 0 00094 : InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost) 00095 + (InnerSize - 1) * NumTraits<Scalar>::AddCost, 00096 00097 /* CanVectorizeInner deserves special explanation. It does not affect the product flags. It is not used outside 00098 * of Product. If the Product itself is not a packet-access expression, there is still a chance that the inner 00099 * loop of the product might be vectorized. This is the meaning of CanVectorizeInner. Since it doesn't affect 00100 * the Flags, it is safe to make this value depend on ActualPacketAccessBit, that doesn't affect the ABI. 00101 */ 00102 CanVectorizeInner = SameType 00103 && LhsRowMajor 00104 && (!RhsRowMajor) 00105 && (LhsFlags & RhsFlags & ActualPacketAccessBit) 00106 && (LhsFlags & RhsFlags & AlignedBit) 00107 && (InnerSize % packet_traits<Scalar>::size == 0) 00108 }; 00109 }; 00110 00111 } // end namespace internal 00112 00113 template<typename LhsNested, typename RhsNested, int NestingFlags> 00114 class CoeffBasedProduct 00115 : internal::no_assignment_operator, 00116 public MatrixBase<CoeffBasedProduct<LhsNested, RhsNested, NestingFlags> > 00117 { 00118 public: 00119 00120 typedef MatrixBase<CoeffBasedProduct> Base; 00121 EIGEN_DENSE_PUBLIC_INTERFACE(CoeffBasedProduct) 00122 typedef typename Base::PlainObject PlainObject; 00123 00124 private: 00125 00126 typedef typename internal::traits<CoeffBasedProduct>::_LhsNested _LhsNested; 00127 typedef typename internal::traits<CoeffBasedProduct>::_RhsNested _RhsNested; 00128 00129 enum { 00130 PacketSize = internal::packet_traits<Scalar>::size, 00131 InnerSize = internal::traits<CoeffBasedProduct>::InnerSize, 00132 Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT, 00133 CanVectorizeInner = internal::traits<CoeffBasedProduct>::CanVectorizeInner 00134 }; 00135 00136 typedef internal::product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal, 00137 Unroll ? InnerSize : Dynamic, 00138 _LhsNested, _RhsNested, Scalar> ScalarCoeffImpl; 00139 00140 typedef CoeffBasedProduct<LhsNested,RhsNested,NestByRefBit> LazyCoeffBasedProductType; 00141 00142 public: 00143 00144 inline CoeffBasedProduct(const CoeffBasedProduct& other) 00145 : Base(), m_lhs(other.m_lhs), m_rhs(other.m_rhs) 00146 {} 00147 00148 template<typename Lhs, typename Rhs> 00149 inline CoeffBasedProduct(const Lhs& lhs, const Rhs& rhs) 00150 : m_lhs(lhs), m_rhs(rhs) 00151 { 00152 // we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable. 00153 // We still allow to mix T and complex<T>. 00154 EIGEN_STATIC_ASSERT((internal::scalar_product_traits<typename Lhs::RealScalar, typename Rhs::RealScalar>::Defined), 00155 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) 00156 eigen_assert(lhs.cols() == rhs.rows() 00157 && "invalid matrix product" 00158 && "if you wanted a coeff-wise or a dot product use the respective explicit functions"); 00159 } 00160 00161 EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); } 00162 EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); } 00163 00164 EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const 00165 { 00166 Scalar res; 00167 ScalarCoeffImpl::run(row, col, m_lhs, m_rhs, res); 00168 return res; 00169 } 00170 00171 /* Allow index-based non-packet access. It is impossible though to allow index-based packed access, 00172 * which is why we don't set the LinearAccessBit. 00173 */ 00174 EIGEN_STRONG_INLINE const Scalar coeff(Index index) const 00175 { 00176 Scalar res; 00177 const Index row = RowsAtCompileTime == 1 ? 0 : index; 00178 const Index col = RowsAtCompileTime == 1 ? index : 0; 00179 ScalarCoeffImpl::run(row, col, m_lhs, m_rhs, res); 00180 return res; 00181 } 00182 00183 template<int LoadMode> 00184 EIGEN_STRONG_INLINE const PacketScalar packet(Index row, Index col) const 00185 { 00186 PacketScalar res; 00187 internal::product_packet_impl<Flags&RowMajorBit ? RowMajor : ColMajor, 00188 Unroll ? InnerSize : Dynamic, 00189 _LhsNested, _RhsNested, PacketScalar, LoadMode> 00190 ::run(row, col, m_lhs, m_rhs, res); 00191 return res; 00192 } 00193 00194 // Implicit conversion to the nested type (trigger the evaluation of the product) 00195 EIGEN_STRONG_INLINE operator const PlainObject& () const 00196 { 00197 m_result.lazyAssign(*this); 00198 return m_result; 00199 } 00200 00201 const _LhsNested& lhs() const { return m_lhs; } 00202 const _RhsNested& rhs() const { return m_rhs; } 00203 00204 const Diagonal<const LazyCoeffBasedProductType,0> diagonal() const 00205 { return reinterpret_cast<const LazyCoeffBasedProductType&>(*this); } 00206 00207 template<int DiagonalIndex> 00208 const Diagonal<const LazyCoeffBasedProductType,DiagonalIndex> diagonal() const 00209 { return reinterpret_cast<const LazyCoeffBasedProductType&>(*this); } 00210 00211 const Diagonal<const LazyCoeffBasedProductType,Dynamic> diagonal(Index index) const 00212 { return reinterpret_cast<const LazyCoeffBasedProductType&>(*this).diagonal(index); } 00213 00214 protected: 00215 typename internal::add_const_on_value_type<LhsNested>::type m_lhs; 00216 typename internal::add_const_on_value_type<RhsNested>::type m_rhs; 00217 00218 mutable PlainObject m_result; 00219 }; 00220 00221 namespace internal { 00222 00223 // here we need to overload the nested rule for products 00224 // such that the nested type is a const reference to a plain matrix 00225 template<typename Lhs, typename Rhs, int N, typename PlainObject> 00226 struct nested<CoeffBasedProduct<Lhs,Rhs,EvalBeforeNestingBit|EvalBeforeAssigningBit>, N, PlainObject> 00227 { 00228 typedef PlainObject const& type; 00229 }; 00230 00231 /*************************************************************************** 00232 * Normal product .coeff() implementation (with meta-unrolling) 00233 ***************************************************************************/ 00234 00235 /************************************** 00236 *** Scalar path - no vectorization *** 00237 **************************************/ 00238 00239 template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar> 00240 struct product_coeff_impl<DefaultTraversal, UnrollingIndex, Lhs, Rhs, RetScalar> 00241 { 00242 typedef typename Lhs::Index Index; 00243 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res) 00244 { 00245 product_coeff_impl<DefaultTraversal, UnrollingIndex-1, Lhs, Rhs, RetScalar>::run(row, col, lhs, rhs, res); 00246 res += lhs.coeff(row, UnrollingIndex-1) * rhs.coeff(UnrollingIndex-1, col); 00247 } 00248 }; 00249 00250 template<typename Lhs, typename Rhs, typename RetScalar> 00251 struct product_coeff_impl<DefaultTraversal, 1, Lhs, Rhs, RetScalar> 00252 { 00253 typedef typename Lhs::Index Index; 00254 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res) 00255 { 00256 res = lhs.coeff(row, 0) * rhs.coeff(0, col); 00257 } 00258 }; 00259 00260 template<typename Lhs, typename Rhs, typename RetScalar> 00261 struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar> 00262 { 00263 typedef typename Lhs::Index Index; 00264 static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, RetScalar &res) 00265 { 00266 res = RetScalar(0); 00267 } 00268 }; 00269 00270 template<typename Lhs, typename Rhs, typename RetScalar> 00271 struct product_coeff_impl<DefaultTraversal, Dynamic, Lhs, Rhs, RetScalar> 00272 { 00273 typedef typename Lhs::Index Index; 00274 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar& res) 00275 { 00276 res = (lhs.row(row).transpose().cwiseProduct( rhs.col(col) )).sum(); 00277 } 00278 }; 00279 00280 /******************************************* 00281 *** Scalar path with inner vectorization *** 00282 *******************************************/ 00283 00284 template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet> 00285 struct product_coeff_vectorized_unroller 00286 { 00287 typedef typename Lhs::Index Index; 00288 enum { PacketSize = packet_traits<typename Lhs::Scalar>::size }; 00289 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres) 00290 { 00291 product_coeff_vectorized_unroller<UnrollingIndex-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, pres); 00292 pres = padd(pres, pmul( lhs.template packet<Aligned>(row, UnrollingIndex) , rhs.template packet<Aligned>(UnrollingIndex, col) )); 00293 } 00294 }; 00295 00296 template<typename Lhs, typename Rhs, typename Packet> 00297 struct product_coeff_vectorized_unroller<0, Lhs, Rhs, Packet> 00298 { 00299 typedef typename Lhs::Index Index; 00300 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres) 00301 { 00302 pres = pmul(lhs.template packet<Aligned>(row, 0) , rhs.template packet<Aligned>(0, col)); 00303 } 00304 }; 00305 00306 template<typename Lhs, typename Rhs, typename RetScalar> 00307 struct product_coeff_impl<InnerVectorizedTraversal, 0, Lhs, Rhs, RetScalar> 00308 { 00309 typedef typename Lhs::Index Index; 00310 static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, RetScalar &res) 00311 { 00312 res = 0; 00313 } 00314 }; 00315 00316 template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar> 00317 struct product_coeff_impl<InnerVectorizedTraversal, UnrollingIndex, Lhs, Rhs, RetScalar> 00318 { 00319 typedef typename Lhs::PacketScalar Packet; 00320 typedef typename Lhs::Index Index; 00321 enum { PacketSize = packet_traits<typename Lhs::Scalar>::size }; 00322 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res) 00323 { 00324 Packet pres; 00325 product_coeff_vectorized_unroller<UnrollingIndex-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, pres); 00326 res = predux(pres); 00327 } 00328 }; 00329 00330 template<typename Lhs, typename Rhs, int LhsRows = Lhs::RowsAtCompileTime, int RhsCols = Rhs::ColsAtCompileTime> 00331 struct product_coeff_vectorized_dyn_selector 00332 { 00333 typedef typename Lhs::Index Index; 00334 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) 00335 { 00336 res = lhs.row(row).transpose().cwiseProduct(rhs.col(col)).sum(); 00337 } 00338 }; 00339 00340 // NOTE the 3 following specializations are because taking .col(0) on a vector is a bit slower 00341 // NOTE maybe they are now useless since we have a specialization for Block<Matrix> 00342 template<typename Lhs, typename Rhs, int RhsCols> 00343 struct product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,RhsCols> 00344 { 00345 typedef typename Lhs::Index Index; 00346 static EIGEN_STRONG_INLINE void run(Index /*row*/, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) 00347 { 00348 res = lhs.transpose().cwiseProduct(rhs.col(col)).sum(); 00349 } 00350 }; 00351 00352 template<typename Lhs, typename Rhs, int LhsRows> 00353 struct product_coeff_vectorized_dyn_selector<Lhs,Rhs,LhsRows,1> 00354 { 00355 typedef typename Lhs::Index Index; 00356 static EIGEN_STRONG_INLINE void run(Index row, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) 00357 { 00358 res = lhs.row(row).transpose().cwiseProduct(rhs).sum(); 00359 } 00360 }; 00361 00362 template<typename Lhs, typename Rhs> 00363 struct product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,1> 00364 { 00365 typedef typename Lhs::Index Index; 00366 static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) 00367 { 00368 res = lhs.transpose().cwiseProduct(rhs).sum(); 00369 } 00370 }; 00371 00372 template<typename Lhs, typename Rhs, typename RetScalar> 00373 struct product_coeff_impl<InnerVectorizedTraversal, Dynamic, Lhs, Rhs, RetScalar> 00374 { 00375 typedef typename Lhs::Index Index; 00376 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) 00377 { 00378 product_coeff_vectorized_dyn_selector<Lhs,Rhs>::run(row, col, lhs, rhs, res); 00379 } 00380 }; 00381 00382 /******************* 00383 *** Packet path *** 00384 *******************/ 00385 00386 template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode> 00387 struct product_packet_impl<RowMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode> 00388 { 00389 typedef typename Lhs::Index Index; 00390 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) 00391 { 00392 product_packet_impl<RowMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res); 00393 res = pmadd(pset1<Packet>(lhs.coeff(row, UnrollingIndex-1)), rhs.template packet<LoadMode>(UnrollingIndex-1, col), res); 00394 } 00395 }; 00396 00397 template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode> 00398 struct product_packet_impl<ColMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode> 00399 { 00400 typedef typename Lhs::Index Index; 00401 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) 00402 { 00403 product_packet_impl<ColMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res); 00404 res = pmadd(lhs.template packet<LoadMode>(row, UnrollingIndex-1), pset1<Packet>(rhs.coeff(UnrollingIndex-1, col)), res); 00405 } 00406 }; 00407 00408 template<typename Lhs, typename Rhs, typename Packet, int LoadMode> 00409 struct product_packet_impl<RowMajor, 1, Lhs, Rhs, Packet, LoadMode> 00410 { 00411 typedef typename Lhs::Index Index; 00412 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) 00413 { 00414 res = pmul(pset1<Packet>(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col)); 00415 } 00416 }; 00417 00418 template<typename Lhs, typename Rhs, typename Packet, int LoadMode> 00419 struct product_packet_impl<ColMajor, 1, Lhs, Rhs, Packet, LoadMode> 00420 { 00421 typedef typename Lhs::Index Index; 00422 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) 00423 { 00424 res = pmul(lhs.template packet<LoadMode>(row, 0), pset1<Packet>(rhs.coeff(0, col))); 00425 } 00426 }; 00427 00428 template<typename Lhs, typename Rhs, typename Packet, int LoadMode> 00429 struct product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode> 00430 { 00431 typedef typename Lhs::Index Index; 00432 static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Packet &res) 00433 { 00434 res = pset1<Packet>(0); 00435 } 00436 }; 00437 00438 template<typename Lhs, typename Rhs, typename Packet, int LoadMode> 00439 struct product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode> 00440 { 00441 typedef typename Lhs::Index Index; 00442 static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Packet &res) 00443 { 00444 res = pset1<Packet>(0); 00445 } 00446 }; 00447 00448 template<typename Lhs, typename Rhs, typename Packet, int LoadMode> 00449 struct product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode> 00450 { 00451 typedef typename Lhs::Index Index; 00452 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res) 00453 { 00454 res = pset1<Packet>(0); 00455 for(Index i = 0; i < lhs.cols(); ++i) 00456 res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode>(i, col), res); 00457 } 00458 }; 00459 00460 template<typename Lhs, typename Rhs, typename Packet, int LoadMode> 00461 struct product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode> 00462 { 00463 typedef typename Lhs::Index Index; 00464 static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res) 00465 { 00466 res = pset1<Packet>(0); 00467 for(Index i = 0; i < lhs.cols(); ++i) 00468 res = pmadd(lhs.template packet<LoadMode>(row, i), pset1<Packet>(rhs.coeff(i, col)), res); 00469 } 00470 }; 00471 00472 } // end namespace internal 00473 00474 } // end namespace Eigen 00475 00476 #endif // EIGEN_COEFFBASED_PRODUCT_H
Generated on Thu Nov 17 2022 22:01:27 by
1.7.2