00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef EIGEN_PRODUCT_H
00027 #define EIGEN_PRODUCT_H
00028
00048 template<typename Lhs, typename Rhs, int ProductType = internal::product_type<Lhs,Rhs>::value>
00049 class GeneralProduct;
00050
00051 enum {
00052 Large = 2,
00053 Small = 3
00054 };
00055
00056 namespace internal {
00057
00058 template<int Rows, int Cols, int Depth> struct product_type_selector;
00059
00060 template<int Size, int MaxSize> struct product_size_category
00061 {
00062 enum { is_large = MaxSize == Dynamic ||
00063 Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD,
00064 value = is_large ? Large
00065 : Size == 1 ? 1
00066 : Small
00067 };
00068 };
00069
00070 template<typename Lhs, typename Rhs> struct product_type
00071 {
00072 typedef typename remove_all<Lhs>::type _Lhs;
00073 typedef typename remove_all<Rhs>::type _Rhs;
00074 enum {
00075 MaxRows = _Lhs::MaxRowsAtCompileTime,
00076 Rows = _Lhs::RowsAtCompileTime,
00077 MaxCols = _Rhs::MaxColsAtCompileTime,
00078 Cols = _Rhs::ColsAtCompileTime,
00079 MaxDepth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::MaxColsAtCompileTime,
00080 _Rhs::MaxRowsAtCompileTime),
00081 Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime,
00082 _Rhs::RowsAtCompileTime),
00083 LargeThreshold = EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
00084 };
00085
00086
00087
00088 private:
00089 enum {
00090 rows_select = product_size_category<Rows,MaxRows>::value,
00091 cols_select = product_size_category<Cols,MaxCols>::value,
00092 depth_select = product_size_category<Depth,MaxDepth>::value
00093 };
00094 typedef product_type_selector<rows_select, cols_select, depth_select> selector;
00095
00096 public:
00097 enum {
00098 value = selector::ret
00099 };
00100 #ifdef EIGEN_DEBUG_PRODUCT
00101 static void debug()
00102 {
00103 EIGEN_DEBUG_VAR(Rows);
00104 EIGEN_DEBUG_VAR(Cols);
00105 EIGEN_DEBUG_VAR(Depth);
00106 EIGEN_DEBUG_VAR(rows_select);
00107 EIGEN_DEBUG_VAR(cols_select);
00108 EIGEN_DEBUG_VAR(depth_select);
00109 EIGEN_DEBUG_VAR(value);
00110 }
00111 #endif
00112 };
00113
00114
00115
00116
00117
00118
00119 template<int M, int N> struct product_type_selector<M,N,1> { enum { ret = OuterProduct }; };
00120 template<int Depth> struct product_type_selector<1, 1, Depth> { enum { ret = InnerProduct }; };
00121 template<> struct product_type_selector<1, 1, 1> { enum { ret = InnerProduct }; };
00122 template<> struct product_type_selector<Small,1, Small> { enum { ret = CoeffBasedProductMode }; };
00123 template<> struct product_type_selector<1, Small,Small> { enum { ret = CoeffBasedProductMode }; };
00124 template<> struct product_type_selector<Small,Small,Small> { enum { ret = CoeffBasedProductMode }; };
00125 template<> struct product_type_selector<Small, Small, 1> { enum { ret = LazyCoeffBasedProductMode }; };
00126 template<> struct product_type_selector<Small, Large, 1> { enum { ret = LazyCoeffBasedProductMode }; };
00127 template<> struct product_type_selector<Large, Small, 1> { enum { ret = LazyCoeffBasedProductMode }; };
00128 template<> struct product_type_selector<1, Large,Small> { enum { ret = CoeffBasedProductMode }; };
00129 template<> struct product_type_selector<1, Large,Large> { enum { ret = GemvProduct }; };
00130 template<> struct product_type_selector<1, Small,Large> { enum { ret = CoeffBasedProductMode }; };
00131 template<> struct product_type_selector<Large,1, Small> { enum { ret = CoeffBasedProductMode }; };
00132 template<> struct product_type_selector<Large,1, Large> { enum { ret = GemvProduct }; };
00133 template<> struct product_type_selector<Small,1, Large> { enum { ret = CoeffBasedProductMode }; };
00134 template<> struct product_type_selector<Small,Small,Large> { enum { ret = GemmProduct }; };
00135 template<> struct product_type_selector<Large,Small,Large> { enum { ret = GemmProduct }; };
00136 template<> struct product_type_selector<Small,Large,Large> { enum { ret = GemmProduct }; };
00137 template<> struct product_type_selector<Large,Large,Large> { enum { ret = GemmProduct }; };
00138 template<> struct product_type_selector<Large,Small,Small> { enum { ret = GemmProduct }; };
00139 template<> struct product_type_selector<Small,Large,Small> { enum { ret = GemmProduct }; };
00140 template<> struct product_type_selector<Large,Large,Small> { enum { ret = GemmProduct }; };
00141
00142 }
00143
00161 template<typename Lhs, typename Rhs, int ProductType>
00162 struct ProductReturnType
00163 {
00164
00165
00166
00167
00168 typedef GeneralProduct<Lhs, Rhs, ProductType> Type;
00169 };
00170
00171 template<typename Lhs, typename Rhs>
00172 struct ProductReturnType<Lhs,Rhs,CoeffBasedProductMode>
00173 {
00174 typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type LhsNested;
00175 typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type RhsNested;
00176 typedef CoeffBasedProduct<LhsNested, RhsNested, EvalBeforeAssigningBit | EvalBeforeNestingBit> Type;
00177 };
00178
00179 template<typename Lhs, typename Rhs>
00180 struct ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode>
00181 {
00182 typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type LhsNested;
00183 typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type RhsNested;
00184 typedef CoeffBasedProduct<LhsNested, RhsNested, NestByRefBit> Type;
00185 };
00186
00187
00188 template<typename Lhs, typename Rhs>
00189 struct LazyProductReturnType : public ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode>
00190 {};
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 namespace internal {
00204
00205 template<typename Lhs, typename Rhs>
00206 struct traits<GeneralProduct<Lhs,Rhs,InnerProduct> >
00207 : traits<Matrix<typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> >
00208 {};
00209
00210 }
00211
00212 template<typename Lhs, typename Rhs>
00213 class GeneralProduct<Lhs, Rhs, InnerProduct>
00214 : internal::no_assignment_operator,
00215 public Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1>
00216 {
00217 typedef Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> Base;
00218 public:
00219 GeneralProduct(const Lhs& lhs, const Rhs& rhs)
00220 {
00221 EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
00222 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00223
00224 Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
00225 }
00226
00228 operator const typename Base::Scalar() const {
00229 return Base::coeff(0,0);
00230 }
00231 };
00232
00233
00234
00235
00236
00237 namespace internal {
00238 template<int StorageOrder> struct outer_product_selector;
00239
00240 template<typename Lhs, typename Rhs>
00241 struct traits<GeneralProduct<Lhs,Rhs,OuterProduct> >
00242 : traits<ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs> >
00243 {};
00244
00245 }
00246
00247 template<typename Lhs, typename Rhs>
00248 class GeneralProduct<Lhs, Rhs, OuterProduct>
00249 : public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
00250 {
00251 public:
00252 EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
00253
00254 GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
00255 {
00256 EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
00257 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00258 }
00259
00260 template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
00261 {
00262 internal::outer_product_selector<(int(Dest::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dest, alpha);
00263 }
00264 };
00265
00266 namespace internal {
00267
00268 template<> struct outer_product_selector<ColMajor> {
00269 template<typename ProductType, typename Dest>
00270 static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
00271 typedef typename Dest::Index Index;
00272
00273
00274 const Index cols = dest.cols();
00275 for (Index j=0; j<cols; ++j)
00276 dest.col(j) += (alpha * prod.rhs().coeff(j)) * prod.lhs();
00277 }
00278 };
00279
00280 template<> struct outer_product_selector<RowMajor> {
00281 template<typename ProductType, typename Dest>
00282 static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
00283 typedef typename Dest::Index Index;
00284
00285
00286 const Index rows = dest.rows();
00287 for (Index i=0; i<rows; ++i)
00288 dest.row(i) += (alpha * prod.lhs().coeff(i)) * prod.rhs();
00289 }
00290 };
00291
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 namespace internal {
00306
00307 template<typename Lhs, typename Rhs>
00308 struct traits<GeneralProduct<Lhs,Rhs,GemvProduct> >
00309 : traits<ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs> >
00310 {};
00311
00312 template<int Side, int StorageOrder, bool BlasCompatible>
00313 struct gemv_selector;
00314
00315 }
00316
00317 template<typename Lhs, typename Rhs>
00318 class GeneralProduct<Lhs, Rhs, GemvProduct>
00319 : public ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs>
00320 {
00321 public:
00322 EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
00323
00324 typedef typename Lhs::Scalar LhsScalar;
00325 typedef typename Rhs::Scalar RhsScalar;
00326
00327 GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
00328 {
00329
00330
00331 }
00332
00333 enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight };
00334 typedef typename internal::conditional<int(Side)==OnTheRight,_LhsNested,_RhsNested>::type MatrixType;
00335
00336 template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
00337 {
00338 eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols());
00339 internal::gemv_selector<Side,(int(MatrixType::Flags)&RowMajorBit) ? RowMajor : ColMajor,
00340 bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)>::run(*this, dst, alpha);
00341 }
00342 };
00343
00344 namespace internal {
00345
00346
00347 template<int StorageOrder, bool BlasCompatible>
00348 struct gemv_selector<OnTheLeft,StorageOrder,BlasCompatible>
00349 {
00350 template<typename ProductType, typename Dest>
00351 static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00352 {
00353 Transpose<Dest> destT(dest);
00354 enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor };
00355 gemv_selector<OnTheRight,OtherStorageOrder,BlasCompatible>
00356 ::run(GeneralProduct<Transpose<const typename ProductType::_RhsNested>,Transpose<const typename ProductType::_LhsNested>, GemvProduct>
00357 (prod.rhs().transpose(), prod.lhs().transpose()), destT, alpha);
00358 }
00359 };
00360
00361 template<typename Scalar,int Size,int MaxSize,bool Cond> struct gemv_static_vector_if;
00362
00363 template<typename Scalar,int Size,int MaxSize>
00364 struct gemv_static_vector_if<Scalar,Size,MaxSize,false>
00365 {
00366 EIGEN_STRONG_INLINE Scalar* data() { eigen_internal_assert(false && "should never be called"); return 0; }
00367 };
00368
00369 template<typename Scalar,int Size>
00370 struct gemv_static_vector_if<Scalar,Size,Dynamic,true>
00371 {
00372 EIGEN_STRONG_INLINE Scalar* data() { return 0; }
00373 };
00374
00375 template<typename Scalar,int Size,int MaxSize>
00376 struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
00377 {
00378 internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data;
00379 EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; }
00380 };
00381
00382 template<> struct gemv_selector<OnTheRight,ColMajor,true>
00383 {
00384 template<typename ProductType, typename Dest>
00385 static inline void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00386 {
00387 typedef typename ProductType::Index Index;
00388 typedef typename ProductType::LhsScalar LhsScalar;
00389 typedef typename ProductType::RhsScalar RhsScalar;
00390 typedef typename ProductType::Scalar ResScalar;
00391 typedef typename ProductType::RealScalar RealScalar;
00392 typedef typename ProductType::ActualLhsType ActualLhsType;
00393 typedef typename ProductType::ActualRhsType ActualRhsType;
00394 typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
00395 typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
00396 typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest;
00397
00398 const ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs());
00399 const ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs());
00400
00401 ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
00402 * RhsBlasTraits::extractScalarFactor(prod.rhs());
00403
00404 enum {
00405
00406
00407 EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1,
00408 ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
00409 MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal
00410 };
00411
00412 gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
00413
00414 bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0));
00415 bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
00416
00417 RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
00418
00419 ResScalar* actualDestPtr;
00420 bool freeDestPtr = false;
00421 if (evalToDest)
00422 {
00423 actualDestPtr = &dest.coeffRef(0);
00424 }
00425 else
00426 {
00427 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00428 int size = dest.size();
00429 EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00430 #endif
00431 if((actualDestPtr = static_dest.data())==0)
00432 {
00433 freeDestPtr = true;
00434 actualDestPtr = ei_aligned_stack_new(ResScalar,dest.size());
00435 }
00436 if(!alphaIsCompatible)
00437 {
00438 MappedDest(actualDestPtr, dest.size()).setZero();
00439 compatibleAlpha = RhsScalar(1);
00440 }
00441 else
00442 MappedDest(actualDestPtr, dest.size()) = dest;
00443 }
00444
00445 general_matrix_vector_product
00446 <Index,LhsScalar,ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
00447 actualLhs.rows(), actualLhs.cols(),
00448 &actualLhs.coeffRef(0,0), actualLhs.outerStride(),
00449 actualRhs.data(), actualRhs.innerStride(),
00450 actualDestPtr, 1,
00451 compatibleAlpha);
00452
00453 if (!evalToDest)
00454 {
00455 if(!alphaIsCompatible)
00456 dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
00457 else
00458 dest = MappedDest(actualDestPtr, dest.size());
00459 if(freeDestPtr) ei_aligned_stack_delete(ResScalar, actualDestPtr, dest.size());
00460 }
00461 }
00462 };
00463
00464 template<> struct gemv_selector<OnTheRight,RowMajor,true>
00465 {
00466 template<typename ProductType, typename Dest>
00467 static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00468 {
00469 typedef typename ProductType::LhsScalar LhsScalar;
00470 typedef typename ProductType::RhsScalar RhsScalar;
00471 typedef typename ProductType::Scalar ResScalar;
00472 typedef typename ProductType::Index Index;
00473 typedef typename ProductType::ActualLhsType ActualLhsType;
00474 typedef typename ProductType::ActualRhsType ActualRhsType;
00475 typedef typename ProductType::_ActualRhsType _ActualRhsType;
00476 typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
00477 typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
00478
00479 typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
00480 typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
00481
00482 ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
00483 * RhsBlasTraits::extractScalarFactor(prod.rhs());
00484
00485 enum {
00486
00487
00488 DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1
00489 };
00490
00491 gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
00492
00493 RhsScalar* actualRhsPtr;
00494 bool freeRhsPtr = false;
00495 if (DirectlyUseRhs)
00496 {
00497 actualRhsPtr = const_cast<RhsScalar*>(&actualRhs.coeffRef(0));
00498 }
00499 else
00500 {
00501 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00502 int size = actualRhs.size();
00503 EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00504 #endif
00505 if((actualRhsPtr = static_rhs.data())==0)
00506 {
00507 freeRhsPtr = true;
00508 actualRhsPtr = ei_aligned_stack_new(RhsScalar, actualRhs.size());
00509 }
00510 Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
00511 }
00512
00513 general_matrix_vector_product
00514 <Index,LhsScalar,RowMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
00515 actualLhs.rows(), actualLhs.cols(),
00516 &actualLhs.coeffRef(0,0), actualLhs.outerStride(),
00517 actualRhsPtr, 1,
00518 &dest.coeffRef(0,0), dest.innerStride(),
00519 actualAlpha);
00520
00521 if((!DirectlyUseRhs) && freeRhsPtr) ei_aligned_stack_delete(RhsScalar, actualRhsPtr, prod.rhs().size());
00522 }
00523 };
00524
00525 template<> struct gemv_selector<OnTheRight,ColMajor,false>
00526 {
00527 template<typename ProductType, typename Dest>
00528 static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00529 {
00530 typedef typename Dest::Index Index;
00531
00532 const Index size = prod.rhs().rows();
00533 for(Index k=0; k<size; ++k)
00534 dest += (alpha*prod.rhs().coeff(k)) * prod.lhs().col(k);
00535 }
00536 };
00537
00538 template<> struct gemv_selector<OnTheRight,RowMajor,false>
00539 {
00540 template<typename ProductType, typename Dest>
00541 static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
00542 {
00543 typedef typename Dest::Index Index;
00544
00545 const Index rows = prod.rows();
00546 for(Index i=0; i<rows; ++i)
00547 dest.coeffRef(i) += alpha * (prod.lhs().row(i).cwiseProduct(prod.rhs().transpose())).sum();
00548 }
00549 };
00550
00551 }
00552
00553
00554
00555
00556
00563 template<typename Derived>
00564 template<typename OtherDerived>
00565 inline const typename ProductReturnType<Derived,OtherDerived>::Type
00566 MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
00567 {
00568
00569
00570
00571
00572 enum {
00573 ProductIsValid = Derived::ColsAtCompileTime==Dynamic
00574 || OtherDerived::RowsAtCompileTime==Dynamic
00575 || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
00576 AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
00577 SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
00578 };
00579
00580
00581
00582 EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
00583 INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
00584 EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
00585 INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
00586 EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
00587 #ifdef EIGEN_DEBUG_PRODUCT
00588 internal::product_type<Derived,OtherDerived>::debug();
00589 #endif
00590 return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
00591 }
00592
00604 template<typename Derived>
00605 template<typename OtherDerived>
00606 const typename LazyProductReturnType<Derived,OtherDerived>::Type
00607 MatrixBase<Derived>::lazyProduct(const MatrixBase<OtherDerived> &other) const
00608 {
00609 enum {
00610 ProductIsValid = Derived::ColsAtCompileTime==Dynamic
00611 || OtherDerived::RowsAtCompileTime==Dynamic
00612 || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
00613 AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
00614 SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
00615 };
00616
00617
00618
00619 EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
00620 INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
00621 EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
00622 INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
00623 EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
00624
00625 return typename LazyProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
00626 }
00627
00628 #endif // EIGEN_PRODUCT_H