00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef EIGEN_COEFFBASED_PRODUCT_H
00012 #define EIGEN_COEFFBASED_PRODUCT_H
00013
00014 namespace Eigen {
00015
00016 namespace internal {
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
00098
00099
00100
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 }
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
00153
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
00172
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
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
00224
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
00233
00234
00235
00236
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 , Index , const Lhs& , const 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
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 , Index , const Lhs& , const 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
00341
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 , 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 , 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 , Index , 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
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 , Index , const Lhs& , const 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 , Index , const Lhs& , const 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 }
00473
00474 }
00475
00476 #endif // EIGEN_COEFFBASED_PRODUCT_H