169 typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type LhsNested;
170 typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type RhsNested;
171 typedef CoeffBasedProduct<LhsNested, RhsNested, NestByRefBit> Type;
175template<
typename Lhs,
typename Rhs>
176struct LazyProductReturnType :
public ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode>
192template<
typename Lhs,
typename Rhs>
193struct traits<GeneralProduct<Lhs,Rhs,InnerProduct> >
194 : traits<Matrix<typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> >
199template<
typename Lhs,
typename Rhs>
201 : internal::no_assignment_operator,
202 public Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1>
204 typedef Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> Base;
206 GeneralProduct(
const Lhs& lhs,
const Rhs& rhs)
208 EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
209 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
211 Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
215 operator const typename Base::Scalar()
const {
216 return Base::coeff(0,0);
225template<
int StorageOrder>
struct outer_product_selector;
227template<
typename Lhs,
typename Rhs>
228struct traits<GeneralProduct<Lhs,Rhs,OuterProduct> >
229 : traits<ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs> >
234template<
typename Lhs,
typename Rhs>
236 :
public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
239 EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
241 GeneralProduct(
const Lhs& lhs,
const Rhs& rhs) : Base(lhs,rhs)
243 EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
244 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
247 template<
typename Dest>
void scaleAndAddTo(Dest& dest, Scalar alpha)
const
255template<>
struct outer_product_selector<
ColMajor> {
256 template<
typename ProductType,
typename Dest>
257 static EIGEN_DONT_INLINE
void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha) {
258 typedef typename Dest::Index Index;
261 const Index cols = dest.cols();
262 for (Index j=0; j<cols; ++j)
263 dest.col(j) += (alpha * prod.rhs().coeff(j)) * prod.lhs();
267template<>
struct outer_product_selector<
RowMajor> {
268 template<
typename ProductType,
typename Dest>
269 static EIGEN_DONT_INLINE
void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha) {
270 typedef typename Dest::Index Index;
273 const Index rows = dest.rows();
274 for (Index i=0; i<rows; ++i)
275 dest.row(i) += (alpha * prod.lhs().coeff(i)) * prod.rhs();
294template<
typename Lhs,
typename Rhs>
295struct traits<GeneralProduct<Lhs,Rhs,GemvProduct> >
296 : traits<ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs> >
299template<
int S
ide,
int StorageOrder,
bool BlasCompatible>
304template<
typename Lhs,
typename Rhs>
306 :
public ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs>
309 EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
311 typedef typename Lhs::Scalar LhsScalar;
312 typedef typename Rhs::Scalar RhsScalar;
314 GeneralProduct(
const Lhs& lhs,
const Rhs& rhs) : Base(lhs,rhs)
321 typedef typename internal::conditional<int(Side)==
OnTheRight,_LhsNested,_RhsNested>::type MatrixType;
323 template<
typename Dest>
void scaleAndAddTo(Dest& dst, Scalar alpha)
const
325 eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols());
327 bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)>::run(*this, dst, alpha);
334template<
int StorageOrder,
bool BlasCompatible>
335struct gemv_selector<
OnTheLeft,StorageOrder,BlasCompatible>
337 template<
typename ProductType,
typename Dest>
338 static void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
340 Transpose<Dest> destT(dest);
342 gemv_selector<OnTheRight,OtherStorageOrder,BlasCompatible>
343 ::run(GeneralProduct<Transpose<const typename ProductType::_RhsNested>,Transpose<const typename ProductType::_LhsNested>, GemvProduct>
344 (prod.rhs().transpose(), prod.lhs().transpose()), destT, alpha);
348template<
typename Scalar,
int Size,
int MaxSize,
bool Cond>
struct gemv_static_vector_if;
350template<
typename Scalar,
int Size,
int MaxSize>
351struct gemv_static_vector_if<Scalar,Size,MaxSize,false>
353 EIGEN_STRONG_INLINE Scalar* data() { eigen_internal_assert(
false &&
"should never be called");
return 0; }
356template<
typename Scalar,
int Size>
357struct gemv_static_vector_if<Scalar,Size,Dynamic,true>
359 EIGEN_STRONG_INLINE Scalar* data() {
return 0; }
362template<
typename Scalar,
int Size,
int MaxSize>
363struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
365 #if EIGEN_ALIGN_STATICALLY
366 internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data;
367 EIGEN_STRONG_INLINE Scalar* data() {
return m_data.array; }
372 ForceAlignment = internal::packet_traits<Scalar>::Vectorizable,
373 PacketSize = internal::packet_traits<Scalar>::size
375 internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data;
376 EIGEN_STRONG_INLINE Scalar* data() {
377 return ForceAlignment
378 ?
reinterpret_cast<Scalar*
>((
reinterpret_cast<size_t>(m_data.array) & ~(size_t(15))) + 16)
386 template<
typename ProductType,
typename Dest>
387 static inline void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
389 typedef typename ProductType::Index Index;
390 typedef typename ProductType::LhsScalar LhsScalar;
391 typedef typename ProductType::RhsScalar RhsScalar;
392 typedef typename ProductType::Scalar ResScalar;
393 typedef typename ProductType::RealScalar RealScalar;
394 typedef typename ProductType::ActualLhsType ActualLhsType;
395 typedef typename ProductType::ActualRhsType ActualRhsType;
396 typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
397 typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
398 typedef Map<Matrix<ResScalar,Dynamic,1>,
Aligned> MappedDest;
400 ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs());
401 ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs());
403 ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
404 * RhsBlasTraits::extractScalarFactor(prod.rhs());
409 EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1,
410 ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
411 MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal
414 gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
416 bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0));
417 bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
419 RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
421 ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
422 evalToDest ? dest.data() : static_dest.data());
426 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
427 int size = dest.size();
428 EIGEN_DENSE_STORAGE_CTOR_PLUGIN
430 if(!alphaIsCompatible)
432 MappedDest(actualDestPtr, dest.size()).setZero();
433 compatibleAlpha = RhsScalar(1);
436 MappedDest(actualDestPtr, dest.size()) = dest;
439 general_matrix_vector_product
440 <Index,LhsScalar,
ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
441 actualLhs.rows(), actualLhs.cols(),
442 actualLhs.data(), actualLhs.outerStride(),
443 actualRhs.data(), actualRhs.innerStride(),
449 if(!alphaIsCompatible)
450 dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
452 dest = MappedDest(actualDestPtr, dest.size());
459 template<
typename ProductType,
typename Dest>
460 static void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
462 typedef typename ProductType::LhsScalar LhsScalar;
463 typedef typename ProductType::RhsScalar RhsScalar;
464 typedef typename ProductType::Scalar ResScalar;
465 typedef typename ProductType::Index Index;
466 typedef typename ProductType::ActualLhsType ActualLhsType;
467 typedef typename ProductType::ActualRhsType ActualRhsType;
468 typedef typename ProductType::_ActualRhsType _ActualRhsType;
469 typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
470 typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
472 typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
473 typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
475 ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
476 * RhsBlasTraits::extractScalarFactor(prod.rhs());
481 DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1
484 gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
486 ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(),
487 DirectlyUseRhs ?
const_cast<RhsScalar*
>(actualRhs.data()) : static_rhs.data());
491 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
492 int size = actualRhs.size();
493 EIGEN_DENSE_STORAGE_CTOR_PLUGIN
495 Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
498 general_matrix_vector_product
499 <Index,LhsScalar,
RowMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
500 actualLhs.rows(), actualLhs.cols(),
501 actualLhs.data(), actualLhs.outerStride(),
503 dest.data(), dest.innerStride(),
510 template<
typename ProductType,
typename Dest>
511 static void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
513 typedef typename Dest::Index Index;
515 const Index size = prod.rhs().rows();
516 for(Index k=0; k<size; ++k)
517 dest += (alpha*prod.rhs().coeff(k)) * prod.lhs().col(k);
523 template<
typename ProductType,
typename Dest>
524 static void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
526 typedef typename Dest::Index Index;
528 const Index rows = prod.rows();
529 for(Index i=0; i<rows; ++i)
530 dest.coeffRef(i) += alpha * (prod.lhs().row(i).cwiseProduct(prod.rhs().transpose())).sum();
546template<
typename Derived>
547template<
typename OtherDerived>
548inline const typename ProductReturnType<Derived, OtherDerived>::Type
556 ProductIsValid = Derived::ColsAtCompileTime==Dynamic
557 || OtherDerived::RowsAtCompileTime==Dynamic
558 || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
559 AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
560 SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
565 EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
566 INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
567 EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
568 INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
569 EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
570#ifdef EIGEN_DEBUG_PRODUCT
571 internal::product_type<Derived,OtherDerived>::debug();
573 return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
587template<
typename Derived>
588template<
typename OtherDerived>
589const typename LazyProductReturnType<Derived,OtherDerived>::Type
593 ProductIsValid = Derived::ColsAtCompileTime==Dynamic
594 || OtherDerived::RowsAtCompileTime==Dynamic
595 || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
596 AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
597 SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
602 EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
603 INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
604 EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
605 INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
606 EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
608 return typename LazyProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());