00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00074
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
00103
00104
00105
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 }
00130
00148 template<typename Lhs, typename Rhs, int ProductType>
00149 struct ProductReturnType
00150 {
00151
00152
00153
00154
00155 typedef GeneralProduct<Lhs, Rhs, 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
00175 template<typename Lhs, typename Rhs>
00176 struct LazyProductReturnType : public ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode>
00177 {};
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
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
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
00260
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
00272
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 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
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 }
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
00317
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
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
00370
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
00408
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
00480
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
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
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 }
00535
00536
00537
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
00552
00553
00554
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
00563
00564
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
00600
00601
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 }
00612
00613 #endif // EIGEN_PRODUCT_H