Eigne Matrix Class Library
Dependents: Eigen_test Odometry_test AttitudeEstimation_usingTicker MPU9250_Quaternion_Binary_Serial ... more
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 Tue Jul 12 2022 17:46:50 by 1.7.2