192template<
typename Lhs,
typename Rhs>
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>
208 Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
212 operator const typename Base::Scalar()
const {
213 return Base::coeff(0,0);
224template<
typename ProductType,
typename Dest,
typename Func>
225EIGEN_DONT_INLINE
void outer_product_selector_run(
const ProductType& prod, Dest& dest,
const Func& func,
const false_type&)
227 typedef typename Dest::Index Index;
230 const Index cols = dest.cols();
231 for (Index j=0; j<cols; ++j)
232 func(dest.col(j), prod.rhs().coeff(0,j) * prod.lhs());
236template<
typename ProductType,
typename Dest,
typename Func>
237EIGEN_DONT_INLINE
void outer_product_selector_run(
const ProductType& prod, Dest& dest,
const Func& func,
const true_type&) {
238 typedef typename Dest::Index Index;
241 const Index rows = dest.rows();
242 for (Index i=0; i<rows; ++i)
243 func(dest.row(i), prod.lhs().coeff(i,0) * prod.rhs());
246template<
typename Lhs,
typename Rhs>
247struct traits<GeneralProduct<Lhs,Rhs,OuterProduct> >
248 : traits<ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs> >
253template<
typename Lhs,
typename Rhs>
255 :
public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
257 template<
typename T>
struct is_row_major : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
260 EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
262 GeneralProduct(
const Lhs& lhs,
const Rhs& rhs) : Base(lhs,rhs)
266 struct set {
template<
typename Dst,
typename Src>
void operator()(
const Dst& dst,
const Src& src)
const { dst.const_cast_derived() = src; } };
267 struct add {
template<
typename Dst,
typename Src>
void operator()(
const Dst& dst,
const Src& src)
const { dst.const_cast_derived() += src; } };
268 struct sub {
template<
typename Dst,
typename Src>
void operator()(
const Dst& dst,
const Src& src)
const { dst.const_cast_derived() -= src; } };
271 adds(
const Scalar& s) : m_scale(s) {}
272 template<
typename Dst,
typename Src>
void operator()(
const Dst& dst,
const Src& src)
const {
273 dst.const_cast_derived() += m_scale * src;
277 template<
typename Dest>
278 inline void evalTo(Dest& dest)
const {
279 internal::outer_product_selector_run(*
this, dest, set(), is_row_major<Dest>());
282 template<
typename Dest>
283 inline void addTo(Dest& dest)
const {
284 internal::outer_product_selector_run(*
this, dest, add(), is_row_major<Dest>());
287 template<
typename Dest>
288 inline void subTo(Dest& dest)
const {
289 internal::outer_product_selector_run(*
this, dest, sub(), is_row_major<Dest>());
292 template<
typename Dest>
void scaleAndAddTo(Dest& dest,
const Scalar& alpha)
const
294 internal::outer_product_selector_run(*
this, dest, adds(alpha), is_row_major<Dest>());
311template<
typename Lhs,
typename Rhs>
312struct traits<GeneralProduct<Lhs,Rhs,GemvProduct> >
313 : traits<ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs> >
316template<
int S
ide,
int StorageOrder,
bool BlasCompatible>
321template<
typename Lhs,
typename Rhs>
323 :
public ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs>
326 EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
328 typedef typename Lhs::Scalar LhsScalar;
329 typedef typename Rhs::Scalar RhsScalar;
331 GeneralProduct(
const Lhs& a_lhs,
const Rhs& a_rhs) : Base(a_lhs,a_rhs)
338 typedef typename internal::conditional<int(Side)==
OnTheRight,_LhsNested,_RhsNested>::type MatrixType;
340 template<
typename Dest>
void scaleAndAddTo(Dest& dst,
const Scalar& alpha)
const
342 eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols());
344 bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)>::run(*this, dst, alpha);
351template<
int StorageOrder,
bool BlasCompatible>
352struct gemv_selector<
OnTheLeft,StorageOrder,BlasCompatible>
354 template<
typename ProductType,
typename Dest>
355 static void run(
const ProductType& prod, Dest& dest,
const typename ProductType::Scalar& alpha)
357 Transpose<Dest> destT(dest);
359 gemv_selector<OnTheRight,OtherStorageOrder,BlasCompatible>
360 ::run(GeneralProduct<Transpose<const typename ProductType::_RhsNested>,Transpose<const typename ProductType::_LhsNested>, GemvProduct>
361 (prod.rhs().transpose(), prod.lhs().transpose()), destT, alpha);
365template<
typename Scalar,
int Size,
int MaxSize,
bool Cond>
struct gemv_static_vector_if;
367template<
typename Scalar,
int Size,
int MaxSize>
368struct gemv_static_vector_if<Scalar,Size,MaxSize,false>
370 EIGEN_STRONG_INLINE Scalar* data() { eigen_internal_assert(
false &&
"should never be called");
return 0; }
373template<
typename Scalar,
int Size>
374struct gemv_static_vector_if<Scalar,Size,Dynamic,true>
376 EIGEN_STRONG_INLINE Scalar* data() {
return 0; }
379template<
typename Scalar,
int Size,
int MaxSize>
380struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
382 #if EIGEN_ALIGN_STATICALLY
383 internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data;
384 EIGEN_STRONG_INLINE Scalar* data() {
return m_data.array; }
389 ForceAlignment = internal::packet_traits<Scalar>::Vectorizable,
390 PacketSize = internal::packet_traits<Scalar>::size
392 internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data;
393 EIGEN_STRONG_INLINE Scalar* data() {
394 return ForceAlignment
395 ?
reinterpret_cast<Scalar*
>((
reinterpret_cast<size_t>(m_data.array) & ~(size_t(15))) + 16)
403 template<
typename ProductType,
typename Dest>
404 static inline void run(
const ProductType& prod, Dest& dest,
const typename ProductType::Scalar& alpha)
406 typedef typename ProductType::Index Index;
407 typedef typename ProductType::LhsScalar LhsScalar;
408 typedef typename ProductType::RhsScalar RhsScalar;
409 typedef typename ProductType::Scalar ResScalar;
410 typedef typename ProductType::RealScalar RealScalar;
411 typedef typename ProductType::ActualLhsType ActualLhsType;
412 typedef typename ProductType::ActualRhsType ActualRhsType;
413 typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
414 typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
415 typedef Map<Matrix<ResScalar,Dynamic,1>,
Aligned> MappedDest;
417 ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs());
418 ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs());
420 ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
421 * RhsBlasTraits::extractScalarFactor(prod.rhs());
424 typedef typename conditional<Dest::IsVectorAtCompileTime, Dest, typename Dest::ColXpr>::type ActualDest;
429 EvalToDestAtCompileTime = (ActualDest::InnerStrideAtCompileTime==1),
430 ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
431 MightCannotUseDest = (ActualDest::InnerStrideAtCompileTime!=1) || ComplexByReal
434 gemv_static_vector_if<ResScalar,ActualDest::SizeAtCompileTime,ActualDest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
436 bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
437 bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
439 RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
441 ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
442 evalToDest ? dest.data() : static_dest.data());
446 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
447 int size = dest.size();
448 EIGEN_DENSE_STORAGE_CTOR_PLUGIN
450 if(!alphaIsCompatible)
452 MappedDest(actualDestPtr, dest.size()).setZero();
453 compatibleAlpha = RhsScalar(1);
456 MappedDest(actualDestPtr, dest.size()) = dest;
459 general_matrix_vector_product
460 <Index,LhsScalar,
ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
461 actualLhs.rows(), actualLhs.cols(),
462 actualLhs.data(), actualLhs.outerStride(),
463 actualRhs.data(), actualRhs.innerStride(),
469 if(!alphaIsCompatible)
470 dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
472 dest = MappedDest(actualDestPtr, dest.size());
479 template<
typename ProductType,
typename Dest>
480 static void run(
const ProductType& prod, Dest& dest,
const typename ProductType::Scalar& alpha)
482 typedef typename ProductType::LhsScalar LhsScalar;
483 typedef typename ProductType::RhsScalar RhsScalar;
484 typedef typename ProductType::Scalar ResScalar;
485 typedef typename ProductType::Index Index;
486 typedef typename ProductType::ActualLhsType ActualLhsType;
487 typedef typename ProductType::ActualRhsType ActualRhsType;
488 typedef typename ProductType::_ActualRhsType _ActualRhsType;
489 typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
490 typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
492 typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
493 typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
495 ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
496 * RhsBlasTraits::extractScalarFactor(prod.rhs());
501 DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1
504 gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
506 ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(),
507 DirectlyUseRhs ?
const_cast<RhsScalar*
>(actualRhs.data()) : static_rhs.data());
511 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
512 int size = actualRhs.size();
513 EIGEN_DENSE_STORAGE_CTOR_PLUGIN
515 Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
518 general_matrix_vector_product
519 <Index,LhsScalar,
RowMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
520 actualLhs.rows(), actualLhs.cols(),
521 actualLhs.data(), actualLhs.outerStride(),
523 dest.data(), dest.col(0).innerStride(),
530 template<
typename ProductType,
typename Dest>
531 static void run(
const ProductType& prod, Dest& dest,
const typename ProductType::Scalar& alpha)
533 typedef typename Dest::Index Index;
535 const Index size = prod.rhs().rows();
536 for(Index k=0; k<size; ++k)
537 dest += (alpha*prod.rhs().coeff(k)) * prod.lhs().col(k);
543 template<
typename ProductType,
typename Dest>
544 static void run(
const ProductType& prod, Dest& dest,
const typename ProductType::Scalar& alpha)
546 typedef typename Dest::Index Index;
548 const Index rows = prod.rows();
549 for(Index i=0; i<rows; ++i)
550 dest.coeffRef(i) += alpha * (prod.lhs().row(i).cwiseProduct(prod.rhs().transpose())).sum();
566template<
typename Derived>
567template<
typename OtherDerived>
568inline const typename ProductReturnType<Derived, OtherDerived>::Type
576 ProductIsValid = Derived::ColsAtCompileTime==Dynamic
577 || OtherDerived::RowsAtCompileTime==Dynamic
578 || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
579 AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
580 SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
585 EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
586 INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
587 EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
588 INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
589 EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
590#ifdef EIGEN_DEBUG_PRODUCT
591 internal::product_type<Derived,OtherDerived>::debug();
593 return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
607template<
typename Derived>
608template<
typename OtherDerived>
609const typename LazyProductReturnType<Derived,OtherDerived>::Type
613 ProductIsValid = Derived::ColsAtCompileTime==Dynamic
614 || OtherDerived::RowsAtCompileTime==Dynamic
615 || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
616 AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
617 SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
622 EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
623 INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
624 EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
625 INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
626 EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
628 return typename LazyProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());