26 #ifndef EIGEN_GENERAL_PRODUCT_H
27 #define EIGEN_GENERAL_PRODUCT_H
50 template<typename Lhs, typename Rhs, int ProductType = internal::product_type<Lhs,Rhs>::value>
60 template<
int Rows,
int Cols,
int Depth>
struct product_type_selector;
62 template<
int Size,
int MaxSize>
struct product_size_category
64 enum { is_large = MaxSize ==
Dynamic ||
66 value = is_large ?
Large
72 template<
typename Lhs,
typename Rhs>
struct product_type
74 typedef typename remove_all<Lhs>::type _Lhs;
75 typedef typename remove_all<Rhs>::type _Rhs;
77 MaxRows = _Lhs::MaxRowsAtCompileTime,
78 Rows = _Lhs::RowsAtCompileTime,
79 MaxCols = _Rhs::MaxColsAtCompileTime,
80 Cols = _Rhs::ColsAtCompileTime,
82 _Rhs::MaxRowsAtCompileTime),
84 _Rhs::RowsAtCompileTime),
92 rows_select = product_size_category<Rows,MaxRows>::value,
93 cols_select = product_size_category<Cols,MaxCols>::value,
94 depth_select = product_size_category<Depth,MaxDepth>::value
96 typedef product_type_selector<rows_select, cols_select, depth_select> selector;
100 value = selector::ret
102 #ifdef EIGEN_DEBUG_PRODUCT
121 template<
int M,
int N>
struct product_type_selector<M,N,1> {
enum { ret =
OuterProduct }; };
122 template<
int Depth>
struct product_type_selector<1, 1, Depth> {
enum { ret =
InnerProduct }; };
123 template<>
struct product_type_selector<1, 1, 1> {
enum { ret =
InnerProduct }; };
163 template<
typename Lhs,
typename Rhs,
int ProductType>
173 template<
typename Lhs,
typename Rhs>
176 typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type
LhsNested;
177 typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type
RhsNested;
181 template<
typename Lhs,
typename Rhs>
184 typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type
LhsNested;
185 typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type
RhsNested;
190 template<
typename Lhs,
typename Rhs>
207 template<
typename Lhs,
typename Rhs>
209 :
traits<Matrix<typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> >
214 template<
typename Lhs,
typename Rhs>
216 : internal::no_assignment_operator,
217 public Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1>
223 EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
224 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
226 Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
231 return Base::coeff(0,0);
240 template<
int StorageOrder>
struct outer_product_selector;
242 template<
typename Lhs,
typename Rhs>
244 :
traits<ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs> >
249 template<
typename Lhs,
typename Rhs>
251 :
public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
258 EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
259 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
262 template<
typename Dest>
void scaleAndAddTo(Dest& dest,
Scalar alpha)
const
264 internal::outer_product_selector<(int(Dest::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*
this, dest, alpha);
270 template<>
struct outer_product_selector<
ColMajor> {
271 template<
typename ProductType,
typename Dest>
272 static EIGEN_DONT_INLINE void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha) {
273 typedef typename Dest::Index Index;
276 const Index cols = dest.cols();
277 for (Index j=0; j<cols; ++j)
278 dest.col(j) += (alpha * prod.rhs().coeff(j)) * prod.lhs();
282 template<>
struct outer_product_selector<
RowMajor> {
283 template<
typename ProductType,
typename Dest>
284 static EIGEN_DONT_INLINE void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha) {
285 typedef typename Dest::Index Index;
288 const Index rows = dest.rows();
289 for (Index i=0; i<rows; ++i)
290 dest.row(i) += (alpha * prod.lhs().coeff(i)) * prod.rhs();
309 template<
typename Lhs,
typename Rhs>
311 :
traits<ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs> >
314 template<
int S
ide,
int StorageOrder,
bool BlasCompatible>
315 struct gemv_selector;
319 template<
typename Lhs,
typename Rhs>
321 :
public ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs>
336 typedef typename internal::conditional<int(Side)==OnTheRight,_LhsNested,_RhsNested>::type
MatrixType;
338 template<
typename Dest>
void scaleAndAddTo(Dest& dst,
Scalar alpha)
const
340 eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols());
342 bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)>::run(*
this, dst, alpha);
349 template<
int StorageOrder,
bool BlasCompatible>
350 struct gemv_selector<
OnTheLeft,StorageOrder,BlasCompatible>
352 template<
typename ProductType,
typename Dest>
353 static void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
355 Transpose<Dest> destT(dest);
357 gemv_selector<OnTheRight,OtherStorageOrder,BlasCompatible>
358 ::run(
GeneralProduct<Transpose<const typename ProductType::_RhsNested>,Transpose<const typename ProductType::_LhsNested>,
GemvProduct>
359 (prod.rhs().transpose(), prod.lhs().transpose()), destT, alpha);
363 template<
typename Scalar,
int Size,
int MaxSize,
bool Cond>
struct gemv_static_vector_if;
365 template<
typename Scalar,
int Size,
int MaxSize>
366 struct gemv_static_vector_if<Scalar,Size,MaxSize,false>
371 template<
typename Scalar,
int Size>
372 struct gemv_static_vector_if<Scalar,Size,
Dynamic,true>
377 template<
typename Scalar,
int Size,
int MaxSize>
378 struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
380 #if EIGEN_ALIGN_STATICALLY
381 internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data;
387 ForceAlignment = internal::packet_traits<Scalar>::Vectorizable,
388 PacketSize = internal::packet_traits<Scalar>::size
390 internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data;
392 return ForceAlignment
393 ?
reinterpret_cast<Scalar*
>((
reinterpret_cast<size_t>(m_data.array) & ~(
size_t(15))) + 16)
401 template<
typename ProductType,
typename Dest>
402 static inline void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
404 typedef typename ProductType::Index Index;
405 typedef typename ProductType::LhsScalar LhsScalar;
406 typedef typename ProductType::RhsScalar RhsScalar;
407 typedef typename ProductType::Scalar ResScalar;
408 typedef typename ProductType::RealScalar RealScalar;
409 typedef typename ProductType::ActualLhsType ActualLhsType;
410 typedef typename ProductType::ActualRhsType ActualRhsType;
411 typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
412 typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
413 typedef Map<Matrix<ResScalar,Dynamic,1>,
Aligned> MappedDest;
415 ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs());
416 ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs());
418 ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
419 * RhsBlasTraits::extractScalarFactor(prod.rhs());
424 EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1,
426 MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal
429 gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
431 bool alphaIsCompatible = (!ComplexByReal) || (
imag(actualAlpha)==RealScalar(0));
432 bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
434 RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
437 evalToDest ? dest.data() : static_dest.data());
441 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
442 int size = dest.size();
443 EIGEN_DENSE_STORAGE_CTOR_PLUGIN
445 if(!alphaIsCompatible)
447 MappedDest(actualDestPtr, dest.size()).setZero();
448 compatibleAlpha = RhsScalar(1);
451 MappedDest(actualDestPtr, dest.size()) = dest;
455 <Index,LhsScalar,
ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
456 actualLhs.rows(), actualLhs.cols(),
457 actualLhs.data(), actualLhs.outerStride(),
458 actualRhs.data(), actualRhs.innerStride(),
464 if(!alphaIsCompatible)
465 dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
467 dest = MappedDest(actualDestPtr, dest.size());
474 template<
typename ProductType,
typename Dest>
475 static void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
477 typedef typename ProductType::LhsScalar LhsScalar;
478 typedef typename ProductType::RhsScalar RhsScalar;
479 typedef typename ProductType::Scalar ResScalar;
480 typedef typename ProductType::Index Index;
481 typedef typename ProductType::ActualLhsType ActualLhsType;
482 typedef typename ProductType::ActualRhsType ActualRhsType;
483 typedef typename ProductType::_ActualRhsType _ActualRhsType;
484 typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
485 typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
487 typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
488 typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
490 ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
491 * RhsBlasTraits::extractScalarFactor(prod.rhs());
496 DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1
499 gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
502 DirectlyUseRhs ?
const_cast<RhsScalar*
>(actualRhs.data()) : static_rhs.data());
506 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
507 int size = actualRhs.size();
508 EIGEN_DENSE_STORAGE_CTOR_PLUGIN
510 Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
514 <Index,LhsScalar,
RowMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
515 actualLhs.rows(), actualLhs.cols(),
516 actualLhs.data(), actualLhs.outerStride(),
518 dest.data(), dest.innerStride(),
523 template<>
struct gemv_selector<
OnTheRight,ColMajor,false>
525 template<
typename ProductType,
typename Dest>
526 static void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
528 typedef typename Dest::Index Index;
530 const Index size = prod.rhs().rows();
531 for(Index k=0; k<size; ++k)
532 dest += (alpha*prod.rhs().coeff(k)) * prod.lhs().col(k);
536 template<>
struct gemv_selector<
OnTheRight,RowMajor,false>
538 template<
typename ProductType,
typename Dest>
539 static void run(
const ProductType& prod, Dest& dest,
typename ProductType::Scalar alpha)
541 typedef typename Dest::Index Index;
543 const Index rows = prod.rows();
544 for(Index i=0; i<rows; ++i)
545 dest.coeffRef(i) += alpha * (prod.lhs().row(i).cwiseProduct(prod.rhs().transpose())).sum();
561 template<
typename Derived>
562 template<
typename OtherDerived>
571 ProductIsValid = Derived::ColsAtCompileTime==
Dynamic
572 || OtherDerived::RowsAtCompileTime==
Dynamic
573 ||
int(Derived::ColsAtCompileTime)==
int(OtherDerived::RowsAtCompileTime),
574 AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
581 INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
583 INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
585 #ifdef EIGEN_DEBUG_PRODUCT
586 internal::product_type<Derived,OtherDerived>::debug();
602 template<
typename Derived>
603 template<
typename OtherDerived>
608 ProductIsValid = Derived::ColsAtCompileTime==
Dynamic
609 || OtherDerived::RowsAtCompileTime==
Dynamic
610 ||
int(Derived::ColsAtCompileTime)==
int(OtherDerived::RowsAtCompileTime),
611 AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
618 INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
620 INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
628 #endif // EIGEN_PRODUCT_H