12#ifndef EIGEN_PRODUCTEVALUATORS_H
13#define EIGEN_PRODUCTEVALUATORS_H
16#include "./InternalHeaderCheck.h"
30template <
typename Lhs,
typename Rhs,
int Options>
31struct evaluator<Product<Lhs, Rhs, Options>> :
public product_evaluator<Product<Lhs, Rhs, Options>> {
32 typedef Product<Lhs, Rhs, Options> XprType;
33 typedef product_evaluator<XprType> Base;
35 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit evaluator(
const XprType& xpr) : Base(xpr) {}
40template <
typename Lhs,
typename Rhs,
typename Scalar1,
typename Scalar2,
typename Plain1>
41struct evaluator_assume_aliasing<CwiseBinaryOp<internal::scalar_product_op<Scalar1, Scalar2>,
42 const CwiseNullaryOp<internal::scalar_constant_op<Scalar1>, Plain1>,
43 const Product<Lhs, Rhs, DefaultProduct>>> {
44 static const bool value =
true;
46template <
typename Lhs,
typename Rhs,
typename Scalar1,
typename Scalar2,
typename Plain1>
47struct evaluator<CwiseBinaryOp<internal::scalar_product_op<Scalar1, Scalar2>,
48 const CwiseNullaryOp<internal::scalar_constant_op<Scalar1>, Plain1>,
49 const Product<Lhs, Rhs, DefaultProduct>>>
50 :
public evaluator<Product<EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar1, Lhs, product), Rhs, DefaultProduct>> {
51 typedef CwiseBinaryOp<internal::scalar_product_op<Scalar1, Scalar2>,
52 const CwiseNullaryOp<internal::scalar_constant_op<Scalar1>, Plain1>,
53 const Product<Lhs, Rhs, DefaultProduct>>
55 typedef evaluator<Product<EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar1, Lhs, product), Rhs, DefaultProduct>> Base;
57 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit evaluator(
const XprType& xpr)
58 : Base(xpr.lhs().functor().m_other * xpr.rhs().lhs() * xpr.rhs().rhs()) {}
61template <
typename Lhs,
typename Rhs,
int DiagIndex>
62struct evaluator<Diagonal<const Product<Lhs, Rhs, DefaultProduct>, DiagIndex>>
63 :
public evaluator<Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex>> {
64 typedef Diagonal<const Product<Lhs, Rhs, DefaultProduct>, DiagIndex> XprType;
65 typedef evaluator<Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex>> Base;
67 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit evaluator(
const XprType& xpr)
68 : Base(Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex>(
69 Product<Lhs, Rhs, LazyProduct>(xpr.nestedExpression().lhs(), xpr.nestedExpression().rhs()), xpr.index())) {}
75template <typename Lhs, typename Rhs, typename LhsShape = typename evaluator_traits<Lhs>::Shape,
76 typename RhsShape =
typename evaluator_traits<Rhs>::Shape,
77 int ProductType = internal::product_type<Lhs, Rhs>::value>
78struct generic_product_impl;
80template <
typename Lhs,
typename Rhs>
81struct evaluator_assume_aliasing<Product<Lhs, Rhs, DefaultProduct>> {
82 static const bool value =
true;
87template <
typename Lhs,
typename Rhs,
int Options,
int ProductTag,
typename LhsShape,
typename RhsShape>
88struct product_evaluator<Product<Lhs, Rhs, Options>, ProductTag, LhsShape, RhsShape>
89 :
public evaluator<typename Product<Lhs, Rhs, Options>::PlainObject> {
90 typedef Product<Lhs, Rhs, Options> XprType;
91 typedef typename XprType::PlainObject PlainObject;
92 typedef evaluator<PlainObject> Base;
95 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit product_evaluator(
const XprType& xpr)
96 : m_result(xpr.rows(), xpr.cols()) {
97 internal::construct_at<Base>(
this, m_result);
112 generic_product_impl<Lhs, Rhs, LhsShape, RhsShape, ProductTag>::evalTo(m_result, xpr.lhs(), xpr.rhs());
116 PlainObject m_result;
123template <
typename DstXprType,
typename Lhs,
typename Rhs,
int Options,
typename Scalar>
124struct Assignment<DstXprType, Product<Lhs, Rhs, Options>, internal::assign_op<Scalar, Scalar>, Dense2Dense,
125 std::enable_if_t<(Options == DefaultProduct || Options == AliasFreeProduct)>> {
126 typedef Product<Lhs, Rhs, Options> SrcXprType;
127 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
128 const internal::assign_op<Scalar, Scalar>&) {
129 Index dstRows = src.rows();
130 Index dstCols = src.cols();
131 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
133 generic_product_impl<Lhs, Rhs>::evalTo(dst, src.lhs(), src.rhs());
138template <
typename DstXprType,
typename Lhs,
typename Rhs,
int Options,
typename Scalar>
139struct Assignment<DstXprType, Product<Lhs, Rhs, Options>, internal::add_assign_op<Scalar, Scalar>, Dense2Dense,
140 std::enable_if_t<(Options == DefaultProduct || Options == AliasFreeProduct)>> {
141 typedef Product<Lhs, Rhs, Options> SrcXprType;
142 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
143 const internal::add_assign_op<Scalar, Scalar>&) {
144 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
146 generic_product_impl<Lhs, Rhs>::addTo(dst, src.lhs(), src.rhs());
151template <
typename DstXprType,
typename Lhs,
typename Rhs,
int Options,
typename Scalar>
152struct Assignment<DstXprType, Product<Lhs, Rhs, Options>, internal::sub_assign_op<Scalar, Scalar>, Dense2Dense,
153 std::enable_if_t<(Options == DefaultProduct || Options == AliasFreeProduct)>> {
154 typedef Product<Lhs, Rhs, Options> SrcXprType;
155 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
156 const internal::sub_assign_op<Scalar, Scalar>&) {
157 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
159 generic_product_impl<Lhs, Rhs>::subTo(dst, src.lhs(), src.rhs());
166template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename AssignFunc,
typename Scalar,
typename ScalarBis,
168struct Assignment<DstXprType,
169 CwiseBinaryOp<internal::scalar_product_op<ScalarBis, Scalar>,
170 const CwiseNullaryOp<internal::scalar_constant_op<ScalarBis>, Plain>,
171 const Product<Lhs, Rhs, DefaultProduct>>,
172 AssignFunc, Dense2Dense> {
173 typedef CwiseBinaryOp<internal::scalar_product_op<ScalarBis, Scalar>,
174 const CwiseNullaryOp<internal::scalar_constant_op<ScalarBis>, Plain>,
175 const Product<Lhs, Rhs, DefaultProduct>>
177 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
178 const AssignFunc& func) {
179 call_assignment_no_alias(dst, (src.lhs().functor().m_other * src.rhs().lhs()) * src.rhs().rhs(), func);
187template <
typename OtherXpr,
typename Lhs,
typename Rhs>
188struct evaluator_assume_aliasing<
190 internal::scalar_sum_op<typename OtherXpr::Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
191 const OtherXpr, const Product<Lhs, Rhs, DefaultProduct>>,
193 static const bool value =
true;
196template <
typename OtherXpr,
typename Lhs,
typename Rhs>
197struct evaluator_assume_aliasing<
199 internal::scalar_difference_op<typename OtherXpr::Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
200 const OtherXpr, const Product<Lhs, Rhs, DefaultProduct>>,
202 static const bool value =
true;
205template <
typename DstXprType,
typename OtherXpr,
typename ProductType,
typename Func1,
typename Func2>
206struct assignment_from_xpr_op_product {
207 template <
typename SrcXprType,
typename InitialFunc>
208 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
209 const InitialFunc& ) {
210 call_assignment_no_alias(dst, src.lhs(), Func1());
211 call_assignment_no_alias(dst, src.rhs(), Func2());
215#define EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(ASSIGN_OP, BINOP, ASSIGN_OP2) \
216 template <typename DstXprType, typename OtherXpr, typename Lhs, typename Rhs, typename DstScalar, \
217 typename SrcScalar, typename OtherScalar, typename ProdScalar> \
218 struct Assignment<DstXprType, \
219 CwiseBinaryOp<internal::BINOP<OtherScalar, ProdScalar>, const OtherXpr, \
220 const Product<Lhs, Rhs, DefaultProduct>>, \
221 internal::ASSIGN_OP<DstScalar, SrcScalar>, Dense2Dense> \
222 : assignment_from_xpr_op_product<DstXprType, OtherXpr, Product<Lhs, Rhs, DefaultProduct>, \
223 internal::ASSIGN_OP<DstScalar, OtherScalar>, \
224 internal::ASSIGN_OP2<DstScalar, ProdScalar>> {}
226EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_sum_op, add_assign_op);
227EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(add_assign_op, scalar_sum_op, add_assign_op);
228EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(sub_assign_op, scalar_sum_op, sub_assign_op);
230EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_difference_op, sub_assign_op);
231EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(add_assign_op, scalar_difference_op, sub_assign_op);
232EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(sub_assign_op, scalar_difference_op, add_assign_op);
236template <
typename Lhs,
typename Rhs>
237struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, InnerProduct> {
238 using impl = default_inner_product_impl<Lhs, Rhs, false>;
239 template <
typename Dst>
240 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
241 dst.coeffRef(0, 0) = impl::run(lhs, rhs);
244 template <
typename Dst>
245 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void addTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
246 dst.coeffRef(0, 0) += impl::run(lhs, rhs);
249 template <
typename Dst>
250 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void subTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
251 dst.coeffRef(0, 0) -= impl::run(lhs, rhs);
260template <
typename Dst,
typename Lhs,
typename Rhs,
typename Func>
261void EIGEN_DEVICE_FUNC outer_product_selector_run(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
const Func& func,
263 evaluator<Rhs> rhsEval(rhs);
264 ei_declare_local_nested_eval(Lhs, lhs, Rhs::SizeAtCompileTime, actual_lhs);
267 const Index cols = dst.cols();
268 for (
Index j = 0; j < cols; ++j) func(dst.col(j), rhsEval.coeff(
Index(0), j) * actual_lhs);
272template <
typename Dst,
typename Lhs,
typename Rhs,
typename Func>
273void EIGEN_DEVICE_FUNC outer_product_selector_run(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
const Func& func,
275 evaluator<Lhs> lhsEval(lhs);
276 ei_declare_local_nested_eval(Rhs, rhs, Lhs::SizeAtCompileTime, actual_rhs);
279 const Index rows = dst.rows();
280 for (
Index i = 0; i < rows; ++i) func(dst.row(i), lhsEval.coeff(i,
Index(0)) * actual_rhs);
283template <
typename Lhs,
typename Rhs>
284struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, OuterProduct> {
285 template <
typename T>
286 struct is_row_major : bool_constant<(int(T::Flags) & RowMajorBit)> {};
287 typedef typename Product<Lhs, Rhs>::Scalar Scalar;
291 template <
typename Dst,
typename Src>
292 EIGEN_DEVICE_FUNC
void operator()(
const Dst& dst,
const Src& src)
const {
293 dst.const_cast_derived() = src;
298 template <
typename Dst,
typename Src>
299 EIGEN_DEVICE_FUNC
void operator()(
const Dst& dst,
const Src& src)
const {
300 dst.const_cast_derived() += src;
304 template <
typename Dst,
typename Src>
305 EIGEN_DEVICE_FUNC
void operator()(
const Dst& dst,
const Src& src)
const {
306 dst.const_cast_derived() -= src;
313 explicit adds(
const Scalar& s) : m_scale(s) {}
315 template <
typename Dst,
typename Src>
316 void EIGEN_DEVICE_FUNC
operator()(
const Dst& dst,
const Src& src)
const {
317 dst.const_cast_derived() += m_scale * src;
321 template <
typename Dst>
322 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
323 internal::outer_product_selector_run(dst, lhs, rhs, set(), is_row_major<Dst>());
326 template <
typename Dst>
327 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void addTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
328 internal::outer_product_selector_run(dst, lhs, rhs, add(), is_row_major<Dst>());
331 template <
typename Dst>
332 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void subTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
333 internal::outer_product_selector_run(dst, lhs, rhs, sub(), is_row_major<Dst>());
336 template <
typename Dst>
337 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
338 const Scalar& alpha) {
339 internal::outer_product_selector_run(dst, lhs, rhs, adds(alpha), is_row_major<Dst>());
344template <
typename Lhs,
typename Rhs,
typename Derived>
345struct generic_product_impl_base {
346 typedef typename Product<Lhs, Rhs>::Scalar Scalar;
348 template <
typename Dst>
349 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
351 scaleAndAddTo(dst, lhs, rhs, Scalar(1));
354 template <
typename Dst>
355 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void addTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
356 scaleAndAddTo(dst, lhs, rhs, Scalar(1));
359 template <
typename Dst>
360 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void subTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
361 scaleAndAddTo(dst, lhs, rhs, Scalar(-1));
364 template <
typename Dst>
365 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
366 const Scalar& alpha) {
367 Derived::scaleAndAddTo(dst, lhs, rhs, alpha);
371template <
typename Lhs,
typename Rhs>
372struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, GemvProduct>
373 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, GemvProduct>> {
374 typedef typename nested_eval<Lhs, 1>::type LhsNested;
375 typedef typename nested_eval<Rhs, 1>::type RhsNested;
376 typedef typename Product<Lhs, Rhs>::Scalar Scalar;
378 typedef internal::remove_all_t<std::conditional_t<int(Side) ==
OnTheRight, LhsNested, RhsNested>> MatrixType;
380 template <
typename Dest>
381 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
382 const Scalar& alpha) {
384 if (lhs.rows() == 1 && rhs.cols() == 1) {
385 dst.coeffRef(0, 0) += alpha * lhs.row(0).conjugate().dot(rhs.col(0));
388 LhsNested actual_lhs(lhs);
389 RhsNested actual_rhs(rhs);
391 bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)>::run(actual_lhs,
397template <
typename Lhs,
typename Rhs>
398struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, CoeffBasedProductMode> {
399 typedef typename Product<Lhs, Rhs>::Scalar Scalar;
401 template <
typename Dst>
402 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
405 call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::assign_op<typename Dst::Scalar, Scalar>());
408 template <
typename Dst>
409 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void addTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
411 call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::add_assign_op<typename Dst::Scalar, Scalar>());
414 template <
typename Dst>
415 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void subTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
417 call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::sub_assign_op<typename Dst::Scalar, Scalar>());
434 template <
typename Dst,
typename Func>
435 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void eval_dynamic(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
438 HasScalarFactor = blas_traits<Lhs>::HasScalarFactor || blas_traits<Rhs>::HasScalarFactor,
439 ConjLhs = blas_traits<Lhs>::NeedToConjugate,
440 ConjRhs = blas_traits<Rhs>::NeedToConjugate
444 Scalar actualAlpha = combine_scalar_factors<Scalar>(lhs, rhs);
446 eval_dynamic_impl(dst, blas_traits<Lhs>::extract(lhs).
template conjugateIf<ConjLhs>(),
447 blas_traits<Rhs>::extract(rhs).
template conjugateIf<ConjRhs>(), func, actualAlpha,
448 bool_constant<HasScalarFactor>());
452 template <
typename Dst,
typename LhsT,
typename RhsT,
typename Func,
typename Scalar>
453 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void eval_dynamic_impl(Dst& dst,
const LhsT& lhs,
const RhsT& rhs,
454 const Func& func,
const Scalar& s ,
456 EIGEN_UNUSED_VARIABLE(s);
457 eigen_internal_assert(numext::is_exactly_one(s));
458 call_restricted_packet_assignment_no_alias(dst, lhs.lazyProduct(rhs), func);
461 template <
typename Dst,
typename LhsT,
typename RhsT,
typename Func,
typename Scalar>
462 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void eval_dynamic_impl(Dst& dst,
const LhsT& lhs,
const RhsT& rhs,
463 const Func& func,
const Scalar& s, true_type) {
464 call_restricted_packet_assignment_no_alias(dst, s * lhs.lazyProduct(rhs), func);
469template <
typename Lhs,
typename Rhs>
470struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, LazyCoeffBasedProductMode>
471 : generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, CoeffBasedProductMode> {};
479template <
int Traversal,
int UnrollingIndex,
typename Lhs,
typename Rhs,
typename RetScalar>
480struct etor_product_coeff_impl;
482template <
int StorageOrder,
int UnrollingIndex,
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
483struct etor_product_packet_impl;
485template <
typename Lhs,
typename Rhs,
int ProductTag>
486struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape, DenseShape>
487 : evaluator_base<Product<Lhs, Rhs, LazyProduct>> {
488 typedef Product<Lhs, Rhs, LazyProduct> XprType;
489 typedef typename XprType::Scalar Scalar;
490 typedef typename XprType::CoeffReturnType CoeffReturnType;
492 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit product_evaluator(
const XprType& xpr)
499 m_innerDim(xpr.lhs().cols()) {
500 EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::MulCost);
501 EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::AddCost);
502 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
504 std::cerr <<
"LhsOuterStrideBytes= " << LhsOuterStrideBytes <<
"\n";
505 std::cerr <<
"RhsOuterStrideBytes= " << RhsOuterStrideBytes <<
"\n";
506 std::cerr <<
"LhsAlignment= " << LhsAlignment <<
"\n";
507 std::cerr <<
"RhsAlignment= " << RhsAlignment <<
"\n";
508 std::cerr <<
"CanVectorizeLhs= " << CanVectorizeLhs <<
"\n";
509 std::cerr <<
"CanVectorizeRhs= " << CanVectorizeRhs <<
"\n";
510 std::cerr <<
"CanVectorizeInner= " << CanVectorizeInner <<
"\n";
511 std::cerr <<
"EvalToRowMajor= " << EvalToRowMajor <<
"\n";
512 std::cerr <<
"Alignment= " << Alignment <<
"\n";
513 std::cerr <<
"Flags= " << Flags <<
"\n";
519 typedef typename internal::nested_eval<Lhs, Rhs::ColsAtCompileTime>::type LhsNested;
520 typedef typename internal::nested_eval<Rhs, Lhs::RowsAtCompileTime>::type RhsNested;
522 typedef internal::remove_all_t<LhsNested> LhsNestedCleaned;
523 typedef internal::remove_all_t<RhsNested> RhsNestedCleaned;
525 typedef evaluator<LhsNestedCleaned> LhsEtorType;
526 typedef evaluator<RhsNestedCleaned> RhsEtorType;
529 RowsAtCompileTime = LhsNestedCleaned::RowsAtCompileTime,
530 ColsAtCompileTime = RhsNestedCleaned::ColsAtCompileTime,
531 InnerSize = min_size_prefer_fixed(LhsNestedCleaned::ColsAtCompileTime, RhsNestedCleaned::RowsAtCompileTime),
532 MaxRowsAtCompileTime = LhsNestedCleaned::MaxRowsAtCompileTime,
533 MaxColsAtCompileTime = RhsNestedCleaned::MaxColsAtCompileTime
536 typedef typename find_best_packet<Scalar, RowsAtCompileTime>::type LhsVecPacketType;
537 typedef typename find_best_packet<Scalar, ColsAtCompileTime>::type RhsVecPacketType;
541 LhsCoeffReadCost = LhsEtorType::CoeffReadCost,
542 RhsCoeffReadCost = RhsEtorType::CoeffReadCost,
543 CoeffReadCost = InnerSize == 0 ? NumTraits<Scalar>::ReadCost
546 : InnerSize * (NumTraits<Scalar>::MulCost + int(LhsCoeffReadCost) + int(RhsCoeffReadCost)) +
547 (InnerSize - 1) * NumTraits<Scalar>::AddCost,
549 Unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT,
551 LhsFlags = LhsEtorType::Flags,
552 RhsFlags = RhsEtorType::Flags,
557 LhsVecPacketSize = unpacket_traits<LhsVecPacketType>::size,
558 RhsVecPacketSize = unpacket_traits<RhsVecPacketType>::size,
562 plain_enum_min(LhsEtorType::Alignment, LhsVecPacketSize*
int(
sizeof(
typename LhsNestedCleaned::Scalar))),
564 plain_enum_min(RhsEtorType::Alignment, RhsVecPacketSize*
int(
sizeof(
typename RhsNestedCleaned::Scalar))),
566 SameType = is_same<typename LhsNestedCleaned::Scalar, typename RhsNestedCleaned::Scalar>::value,
568 CanVectorizeRhs = bool(RhsRowMajor) && (RhsFlags &
PacketAccessBit) && (ColsAtCompileTime != 1),
569 CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags &
PacketAccessBit) && (RowsAtCompileTime != 1),
571 EvalToRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? 1
572 : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1)
574 : (bool(RhsRowMajor) && !CanVectorizeLhs),
576 Flags = ((int(LhsFlags) | int(RhsFlags)) & HereditaryBits & ~
RowMajorBit) |
579 | (SameType && (CanVectorizeLhs || CanVectorizeRhs) ?
PacketAccessBit : 0) |
582 LhsOuterStrideBytes =
583 int(LhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename LhsNestedCleaned::Scalar)),
584 RhsOuterStrideBytes =
585 int(RhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename RhsNestedCleaned::Scalar)),
587 Alignment = bool(CanVectorizeLhs)
588 ? (LhsOuterStrideBytes <= 0 || (int(LhsOuterStrideBytes) % plain_enum_max(1, LhsAlignment)) != 0
591 : bool(CanVectorizeRhs)
592 ? (RhsOuterStrideBytes <= 0 || (int(RhsOuterStrideBytes) % plain_enum_max(1, RhsAlignment)) != 0
602 CanVectorizeInner = SameType && LhsRowMajor && (!RhsRowMajor) &&
604 (int(InnerSize) % packet_traits<Scalar>::size == 0)
607 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const CoeffReturnType coeff(
Index row,
Index col)
const {
608 return (m_lhs.row(row).transpose().cwiseProduct(m_rhs.col(col))).sum();
615 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const CoeffReturnType coeff(
Index index)
const {
616 const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index;
617 const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0;
618 return (m_lhs.row(row).transpose().cwiseProduct(m_rhs.col(col))).sum();
621 template <
int LoadMode,
typename PacketType>
622 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const PacketType packet(
Index row,
Index col)
const {
625 Unroll ? int(InnerSize) :
Dynamic, LhsEtorType, RhsEtorType, PacketType, LoadMode>
627 PacketImpl::run(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res);
631 template <
int LoadMode,
typename PacketType>
632 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const PacketType packet(
Index index)
const {
633 const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index;
634 const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0;
635 return packet<LoadMode, PacketType>(row, col);
638 template <
int LoadMode,
typename PacketType>
639 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const PacketType packetSegment(
Index row,
Index col,
Index begin,
643 Unroll ? int(InnerSize) :
Dynamic, LhsEtorType, RhsEtorType, PacketType, LoadMode>
645 PacketImpl::run_segment(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res, begin, count);
649 template <
int LoadMode,
typename PacketType>
650 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const PacketType packetSegment(
Index index,
Index begin,
Index count)
const {
651 const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index;
652 const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0;
653 return packetSegment<LoadMode, PacketType>(row, col, begin, count);
657 add_const_on_value_type_t<LhsNested> m_lhs;
658 add_const_on_value_type_t<RhsNested> m_rhs;
660 LhsEtorType m_lhsImpl;
661 RhsEtorType m_rhsImpl;
667template <
typename Lhs,
typename Rhs>
668struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, LazyCoeffBasedProductMode, DenseShape, DenseShape>
669 : product_evaluator<Product<Lhs, Rhs, LazyProduct>, CoeffBasedProductMode, DenseShape, DenseShape> {
670 typedef Product<Lhs, Rhs, DefaultProduct> XprType;
671 typedef Product<Lhs, Rhs, LazyProduct> BaseProduct;
672 typedef product_evaluator<BaseProduct, CoeffBasedProductMode, DenseShape, DenseShape> Base;
674 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit product_evaluator(
const XprType& xpr)
675 : Base(BaseProduct(xpr.lhs(), xpr.rhs())) {}
682template <
int UnrollingIndex,
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
683struct etor_product_packet_impl<
RowMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode> {
684 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
685 Index innerDim, Packet& res) {
686 etor_product_packet_impl<RowMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs,
688 res = pmadd(pset1<Packet>(lhs.coeff(row,
Index(UnrollingIndex - 1))),
689 rhs.template packet<LoadMode, Packet>(
Index(UnrollingIndex - 1), col), res);
691 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
692 Index innerDim, Packet& res, Index begin, Index count) {
693 etor_product_packet_impl<RowMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run_segment(
694 row, col, lhs, rhs, innerDim, res, begin, count);
695 res = pmadd(pset1<Packet>(lhs.coeff(row,
Index(UnrollingIndex - 1))),
696 rhs.template packetSegment<LoadMode, Packet>(
Index(UnrollingIndex - 1), col, begin, count), res);
700template <
int UnrollingIndex,
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
701struct etor_product_packet_impl<
ColMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode> {
702 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
703 Index innerDim, Packet& res) {
704 etor_product_packet_impl<ColMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs,
706 res = pmadd(lhs.template packet<LoadMode, Packet>(row,
Index(UnrollingIndex - 1)),
707 pset1<Packet>(rhs.coeff(
Index(UnrollingIndex - 1), col)), res);
709 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
710 Index innerDim, Packet& res, Index begin, Index count) {
711 etor_product_packet_impl<ColMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run_segment(
712 row, col, lhs, rhs, innerDim, res, begin, count);
713 res = pmadd(lhs.template packetSegment<LoadMode, Packet>(row,
Index(UnrollingIndex - 1), begin, count),
714 pset1<Packet>(rhs.coeff(
Index(UnrollingIndex - 1), col)), res);
718template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
719struct etor_product_packet_impl<
RowMajor, 1, Lhs, Rhs, Packet, LoadMode> {
720 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
721 Index , Packet& res) {
722 res = pmul(pset1<Packet>(lhs.coeff(row,
Index(0))), rhs.template packet<LoadMode, Packet>(
Index(0), col));
724 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
725 Index , Packet& res, Index begin,
727 res = pmul(pset1<Packet>(lhs.coeff(row,
Index(0))),
728 rhs.template packetSegment<LoadMode, Packet>(
Index(0), col, begin, count));
732template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
733struct etor_product_packet_impl<
ColMajor, 1, Lhs, Rhs, Packet, LoadMode> {
734 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
735 Index , Packet& res) {
736 res = pmul(lhs.template packet<LoadMode, Packet>(row,
Index(0)), pset1<Packet>(rhs.coeff(
Index(0), col)));
738 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
739 Index , Packet& res, Index begin,
741 res = pmul(lhs.template packetSegment<LoadMode, Packet>(row,
Index(0), begin, count),
742 pset1<Packet>(rhs.coeff(
Index(0), col)));
746template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
747struct etor_product_packet_impl<
RowMajor, 0, Lhs, Rhs, Packet, LoadMode> {
748 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index , Index ,
const Lhs& ,
749 const Rhs& , Index , Packet& res) {
750 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
752 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index , Index ,
const Lhs& ,
753 const Rhs& , Index , Packet& res,
755 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
759template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
760struct etor_product_packet_impl<
ColMajor, 0, Lhs, Rhs, Packet, LoadMode> {
761 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index , Index ,
const Lhs& ,
762 const Rhs& , Index , Packet& res) {
763 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
765 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index , Index ,
const Lhs& ,
766 const Rhs& , Index , Packet& res,
768 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
772template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
773struct etor_product_packet_impl<
RowMajor,
Dynamic, Lhs, Rhs, Packet, LoadMode> {
774 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
775 Index innerDim, Packet& res) {
776 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
777 for (Index i = 0; i < innerDim; ++i)
778 res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode, Packet>(i, col), res);
780 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
781 Index innerDim, Packet& res, Index begin, Index count) {
782 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
783 for (Index i = 0; i < innerDim; ++i)
784 res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packetSegment<LoadMode, Packet>(i, col, begin, count),
789template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
790struct etor_product_packet_impl<
ColMajor,
Dynamic, Lhs, Rhs, Packet, LoadMode> {
791 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
792 Index innerDim, Packet& res) {
793 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
794 for (Index i = 0; i < innerDim; ++i)
795 res = pmadd(lhs.template packet<LoadMode, Packet>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
797 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
798 Index innerDim, Packet& res, Index begin, Index count) {
799 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
800 for (Index i = 0; i < innerDim; ++i)
801 res = pmadd(lhs.template packetSegment<LoadMode, Packet>(row, i, begin, count), pset1<Packet>(rhs.coeff(i, col)),
809template <
int Mode,
bool LhsIsTriangular,
typename Lhs,
bool LhsIsVector,
typename Rhs,
bool RhsIsVector>
810struct triangular_product_impl;
812template <
typename Lhs,
typename Rhs,
int ProductTag>
813struct generic_product_impl<Lhs, Rhs, TriangularShape, DenseShape, ProductTag>
814 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, TriangularShape, DenseShape, ProductTag>> {
815 typedef typename Product<Lhs, Rhs>::Scalar Scalar;
817 template <
typename Dest>
818 static void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
819 triangular_product_impl<Lhs::Mode, true, typename Lhs::MatrixType, false, Rhs, Rhs::ColsAtCompileTime == 1>::run(
820 dst, lhs.nestedExpression(), rhs, alpha);
824template <
typename Lhs,
typename Rhs,
int ProductTag>
825struct generic_product_impl<Lhs, Rhs, DenseShape, TriangularShape, ProductTag>
826 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, DenseShape, TriangularShape, ProductTag>> {
827 typedef typename Product<Lhs, Rhs>::Scalar Scalar;
829 template <
typename Dest>
830 static void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
831 triangular_product_impl<Rhs::Mode, false, Lhs, Lhs::RowsAtCompileTime == 1, typename Rhs::MatrixType, false>::run(
832 dst, lhs, rhs.nestedExpression(), alpha);
839template <
typename Lhs,
int LhsMode,
bool LhsIsVector,
typename Rhs,
int RhsMode,
bool RhsIsVector>
840struct selfadjoint_product_impl;
842template <
typename Lhs,
typename Rhs,
int ProductTag>
843struct generic_product_impl<Lhs, Rhs, SelfAdjointShape, DenseShape, ProductTag>
844 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, SelfAdjointShape, DenseShape, ProductTag>> {
845 typedef typename Product<Lhs, Rhs>::Scalar Scalar;
847 template <
typename Dest>
848 static EIGEN_DEVICE_FUNC
void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
849 selfadjoint_product_impl<typename Lhs::MatrixType, Lhs::Mode, false, Rhs, 0, Rhs::ColsAtCompileTime == 1>::run(
850 dst, lhs.nestedExpression(), rhs, alpha);
854template <
typename Lhs,
typename Rhs,
int ProductTag>
855struct generic_product_impl<Lhs, Rhs, DenseShape, SelfAdjointShape, ProductTag>
856 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, DenseShape, SelfAdjointShape, ProductTag>> {
857 typedef typename Product<Lhs, Rhs>::Scalar Scalar;
859 template <
typename Dest>
860 static void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
861 selfadjoint_product_impl<Lhs, 0, Lhs::RowsAtCompileTime == 1, typename Rhs::MatrixType, Rhs::Mode, false>::run(
862 dst, lhs, rhs.nestedExpression(), alpha);
870template <
typename MatrixType,
typename DiagonalType,
typename Derived,
int ProductOrder>
871struct diagonal_product_evaluator_base : evaluator_base<Derived> {
872 typedef typename ScalarBinaryOpTraits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType Scalar;
876 CoeffReadCost = int(NumTraits<Scalar>::MulCost) + int(evaluator<MatrixType>::CoeffReadCost) +
877 int(evaluator<DiagonalType>::CoeffReadCost),
879 MatrixFlags = evaluator<MatrixType>::Flags,
880 DiagFlags = evaluator<DiagonalType>::Flags,
882 StorageOrder_ = (Derived::MaxRowsAtCompileTime == 1 && Derived::MaxColsAtCompileTime != 1) ? RowMajor
883 : (Derived::MaxColsAtCompileTime == 1 && Derived::MaxRowsAtCompileTime != 1) ?
ColMajor
888 ScalarAccessOnDiag_ = !((int(StorageOrder_) ==
ColMajor && int(ProductOrder) ==
OnTheLeft) ||
890 SameTypes_ = is_same<typename MatrixType::Scalar, typename DiagonalType::Scalar>::value,
894 Vectorizable_ = bool(int(MatrixFlags) &
PacketAccessBit) && SameTypes_ &&
898 (MatrixType::RowsAtCompileTime == 1 || MatrixType::ColsAtCompileTime == 1) ?
LinearAccessBit : 0,
900 ((HereditaryBits | LinearAccessMask_) & (unsigned int)(MatrixFlags)) | (Vectorizable_ ?
PacketAccessBit : 0),
901 Alignment = evaluator<MatrixType>::Alignment,
904 (DiagonalType::SizeAtCompileTime == 1) ||
905 (DiagonalType::SizeAtCompileTime ==
Dynamic && MatrixType::RowsAtCompileTime == 1 &&
907 (DiagonalType::SizeAtCompileTime ==
Dynamic && MatrixType::ColsAtCompileTime == 1 && ProductOrder ==
OnTheRight)
910 EIGEN_DEVICE_FUNC diagonal_product_evaluator_base(
const MatrixType& mat,
const DiagonalType& diag)
911 : m_diagImpl(diag), m_matImpl(mat) {
912 EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::MulCost);
913 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
916 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Scalar coeff(Index idx)
const {
918 return m_diagImpl.coeff(0) * m_matImpl.coeff(idx);
920 return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx);
924 template <
int LoadMode,
typename PacketType>
925 EIGEN_STRONG_INLINE PacketType packet_impl(Index row, Index col, Index
id, internal::true_type)
const {
926 return internal::pmul(m_matImpl.template packet<LoadMode, PacketType>(row, col),
927 internal::pset1<PacketType>(m_diagImpl.coeff(
id)));
930 template <
int LoadMode,
typename PacketType>
931 EIGEN_STRONG_INLINE PacketType packet_impl(Index row, Index col, Index
id, internal::false_type)
const {
933 InnerSize = (MatrixType::Flags &
RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
934 DiagonalPacketLoadMode = plain_enum_min(
936 ((InnerSize % 16) == 0) ? int(
Aligned16) : int(evaluator<DiagonalType>::Alignment))
938 return internal::pmul(m_matImpl.template packet<LoadMode, PacketType>(row, col),
939 m_diagImpl.template packet<DiagonalPacketLoadMode, PacketType>(
id));
942 template <
int LoadMode,
typename PacketType>
943 EIGEN_STRONG_INLINE PacketType packet_segment_impl(Index row, Index col, Index
id, Index begin, Index count,
944 internal::true_type)
const {
945 return internal::pmul(m_matImpl.template packetSegment<LoadMode, PacketType>(row, col, begin, count),
946 internal::pset1<PacketType>(m_diagImpl.coeff(
id)));
949 template <
int LoadMode,
typename PacketType>
950 EIGEN_STRONG_INLINE PacketType packet_segment_impl(Index row, Index col, Index
id, Index begin, Index count,
951 internal::false_type)
const {
953 InnerSize = (MatrixType::Flags &
RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
954 DiagonalPacketLoadMode = plain_enum_min(
956 ((InnerSize % 16) == 0) ? int(
Aligned16) : int(evaluator<DiagonalType>::Alignment))
958 return internal::pmul(m_matImpl.template packetSegment<LoadMode, PacketType>(row, col, begin, count),
959 m_diagImpl.template packetSegment<DiagonalPacketLoadMode, PacketType>(
id, begin, count));
962 evaluator<DiagonalType> m_diagImpl;
963 evaluator<MatrixType> m_matImpl;
967template <
typename Lhs,
typename Rhs,
int ProductKind,
int ProductTag>
968struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalShape, DenseShape>
969 : diagonal_product_evaluator_base<Rhs, typename Lhs::DiagonalVectorType, Product<Lhs, Rhs, LazyProduct>,
971 typedef diagonal_product_evaluator_base<Rhs, typename Lhs::DiagonalVectorType, Product<Lhs, Rhs, LazyProduct>,
975 using Base::m_diagImpl;
976 using Base::m_matImpl;
977 typedef typename Base::Scalar Scalar;
979 typedef Product<Lhs, Rhs, ProductKind> XprType;
980 typedef typename XprType::PlainObject PlainObject;
981 typedef typename Lhs::DiagonalVectorType DiagonalType;
983 static constexpr int StorageOrder = Base::StorageOrder_;
984 using IsRowMajor_t = bool_constant<StorageOrder == RowMajor>;
986 EIGEN_DEVICE_FUNC
explicit product_evaluator(
const XprType& xpr) : Base(xpr.rhs(), xpr.lhs().diagonal()) {}
988 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Scalar coeff(Index row, Index col)
const {
989 return m_diagImpl.coeff(row) * m_matImpl.coeff(row, col);
993 template <
int LoadMode,
typename PacketType>
994 EIGEN_STRONG_INLINE PacketType packet(Index row, Index col)
const {
997 return this->
template packet_impl<LoadMode, PacketType>(row, col, row, IsRowMajor_t());
1000 template <
int LoadMode,
typename PacketType>
1001 EIGEN_STRONG_INLINE PacketType packet(Index idx)
const {
1002 return packet<LoadMode, PacketType>(
int(StorageOrder) == ColMajor ? idx : 0,
1003 int(StorageOrder) == ColMajor ? 0 : idx);
1006 template <
int LoadMode,
typename PacketType>
1007 EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count)
const {
1010 return this->
template packet_segment_impl<LoadMode, PacketType>(row, col, row, begin, count, IsRowMajor_t());
1013 template <
int LoadMode,
typename PacketType>
1014 EIGEN_STRONG_INLINE PacketType packetSegment(Index idx, Index begin, Index count)
const {
1015 return packetSegment<LoadMode, PacketType>(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx,
1022template <
typename Lhs,
typename Rhs,
int ProductKind,
int ProductTag>
1023struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DenseShape, DiagonalShape>
1024 : diagonal_product_evaluator_base<Lhs, typename Rhs::DiagonalVectorType, Product<Lhs, Rhs, LazyProduct>,
1026 typedef diagonal_product_evaluator_base<Lhs, typename Rhs::DiagonalVectorType, Product<Lhs, Rhs, LazyProduct>,
1030 using Base::m_diagImpl;
1031 using Base::m_matImpl;
1032 typedef typename Base::Scalar Scalar;
1034 typedef Product<Lhs, Rhs, ProductKind> XprType;
1035 typedef typename XprType::PlainObject PlainObject;
1037 static constexpr int StorageOrder = Base::StorageOrder_;
1038 using IsColMajor_t = bool_constant<StorageOrder == ColMajor>;
1040 EIGEN_DEVICE_FUNC
explicit product_evaluator(
const XprType& xpr) : Base(xpr.lhs(), xpr.rhs().diagonal()) {}
1042 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Scalar coeff(Index row, Index col)
const {
1043 return m_matImpl.coeff(row, col) * m_diagImpl.coeff(col);
1047 template <
int LoadMode,
typename PacketType>
1048 EIGEN_STRONG_INLINE PacketType packet(Index row, Index col)
const {
1049 return this->
template packet_impl<LoadMode, PacketType>(row, col, col, IsColMajor_t());
1052 template <
int LoadMode,
typename PacketType>
1053 EIGEN_STRONG_INLINE PacketType packet(Index idx)
const {
1054 return packet<LoadMode, PacketType>(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx);
1057 template <
int LoadMode,
typename PacketType>
1058 EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count)
const {
1059 return this->
template packet_segment_impl<LoadMode, PacketType>(row, col, col, begin, count, IsColMajor_t());
1062 template <
int LoadMode,
typename PacketType>
1063 EIGEN_STRONG_INLINE PacketType packetSegment(Index idx, Index begin, Index count)
const {
1064 return packetSegment<LoadMode, PacketType>(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx,
1079template <
typename ExpressionType,
int S
ide,
bool Transposed,
typename ExpressionShape>
1080struct permutation_matrix_product;
1082template <
typename ExpressionType,
int S
ide,
bool Transposed>
1083struct permutation_matrix_product<ExpressionType, Side, Transposed, DenseShape> {
1084 typedef typename nested_eval<ExpressionType, 1>::type MatrixType;
1085 typedef remove_all_t<MatrixType> MatrixTypeCleaned;
1087 template <
typename Dest,
typename PermutationType>
1088 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Dest& dst,
const PermutationType& perm,
1089 const ExpressionType& xpr) {
1090 MatrixType mat(xpr);
1095 if (is_same_dense(dst, mat)) {
1097 Matrix<bool, PermutationType::RowsAtCompileTime, 1, 0, PermutationType::MaxRowsAtCompileTime> mask(perm.size());
1100 while (r < perm.size()) {
1102 while (r < perm.size() && mask[r]) r++;
1103 if (r >= perm.size())
break;
1107 mask.coeffRef(k0) =
true;
1108 for (Index k = perm.indices().coeff(k0); k != k0; k = perm.indices().coeff(k)) {
1109 Block<Dest, Side ==
OnTheLeft ? 1 : Dest::RowsAtCompileTime,
1110 Side ==
OnTheRight ? 1 : Dest::ColsAtCompileTime>(dst, k)
1111 .
swap(Block < Dest, Side == OnTheLeft ? 1 : Dest::RowsAtCompileTime,
1114 : Dest::ColsAtCompileTime > (dst, ((Side == OnTheLeft) ^ Transposed) ? k0 : kPrev));
1116 mask.coeffRef(k) =
true;
1121 for (Index i = 0; i < n; ++i) {
1122 Block<Dest, Side == OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side == OnTheRight ? 1 : Dest::ColsAtCompileTime>(
1123 dst, ((Side == OnTheLeft) ^ Transposed) ? perm.indices().coeff(i) : i)
1127 Block <
const MatrixTypeCleaned,
1128 Side ==
OnTheLeft ? 1 : MatrixTypeCleaned::RowsAtCompileTime,
1130 : MatrixTypeCleaned::ColsAtCompileTime >
1131 (mat, ((Side ==
OnTheRight) ^ Transposed) ? perm.indices().coeff(i) : i);
1137template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1138struct generic_product_impl<Lhs, Rhs, PermutationShape, MatrixShape, ProductTag> {
1139 template <
typename Dest>
1140 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
1141 permutation_matrix_product<Rhs, OnTheLeft, false, MatrixShape>::run(dst, lhs, rhs);
1145template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1146struct generic_product_impl<Lhs, Rhs, MatrixShape, PermutationShape, ProductTag> {
1147 template <
typename Dest>
1148 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
1149 permutation_matrix_product<Lhs, OnTheRight, false, MatrixShape>::run(dst, rhs, lhs);
1153template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1154struct generic_product_impl<Inverse<Lhs>, Rhs, PermutationShape, MatrixShape, ProductTag> {
1155 template <
typename Dest>
1156 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Inverse<Lhs>& lhs,
const Rhs& rhs) {
1157 permutation_matrix_product<Rhs, OnTheLeft, true, MatrixShape>::run(dst, lhs.nestedExpression(), rhs);
1161template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1162struct generic_product_impl<Lhs, Inverse<Rhs>, MatrixShape, PermutationShape, ProductTag> {
1163 template <
typename Dest>
1164 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Inverse<Rhs>& rhs) {
1165 permutation_matrix_product<Lhs, OnTheRight, true, MatrixShape>::run(dst, rhs.nestedExpression(), lhs);
1179template <
typename ExpressionType,
int S
ide,
bool Transposed,
typename ExpressionShape>
1180struct transposition_matrix_product {
1181 typedef typename nested_eval<ExpressionType, 1>::type MatrixType;
1182 typedef remove_all_t<MatrixType> MatrixTypeCleaned;
1184 template <
typename Dest,
typename TranspositionType>
1185 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Dest& dst,
const TranspositionType& tr,
1186 const ExpressionType& xpr) {
1187 MatrixType mat(xpr);
1188 typedef typename TranspositionType::StorageIndex StorageIndex;
1189 const Index size = tr.size();
1192 if (!is_same_dense(dst, mat)) dst = mat;
1194 for (Index k = (Transposed ? size - 1 : 0); Transposed ? k >= 0 : k < size; Transposed ? --k : ++k)
1195 if (
Index(j = tr.coeff(k)) != k) {
1196 if (Side == OnTheLeft)
1197 dst.row(k).swap(dst.row(j));
1198 else if (Side == OnTheRight)
1199 dst.col(k).swap(dst.col(j));
1204template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1205struct generic_product_impl<Lhs, Rhs, TranspositionsShape, MatrixShape, ProductTag> {
1206 template <
typename Dest>
1207 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
1208 transposition_matrix_product<Rhs, OnTheLeft, false, MatrixShape>::run(dst, lhs, rhs);
1212template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1213struct generic_product_impl<Lhs, Rhs, MatrixShape, TranspositionsShape, ProductTag> {
1214 template <
typename Dest>
1215 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
1216 transposition_matrix_product<Lhs, OnTheRight, false, MatrixShape>::run(dst, rhs, lhs);
1220template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1221struct generic_product_impl<Transpose<Lhs>, Rhs, TranspositionsShape, MatrixShape, ProductTag> {
1222 template <
typename Dest>
1223 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Transpose<Lhs>& lhs,
const Rhs& rhs) {
1224 transposition_matrix_product<Rhs, OnTheLeft, true, MatrixShape>::run(dst, lhs.nestedExpression(), rhs);
1228template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1229struct generic_product_impl<Lhs, Transpose<Rhs>, MatrixShape, TranspositionsShape, ProductTag> {
1230 template <
typename Dest>
1231 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Transpose<Rhs>& rhs) {
1232 transposition_matrix_product<Lhs, OnTheRight, true, MatrixShape>::run(dst, rhs.nestedExpression(), lhs);
1240template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1241struct generic_product_impl<Lhs, Rhs, SkewSymmetricShape, MatrixShape, ProductTag> {
1242 template <
typename Dest>
1243 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
1244 generic_product_impl<typename Lhs::DenseMatrixType, Rhs, DenseShape, MatrixShape, ProductTag>::evalTo(dst, lhs,
1249template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1250struct generic_product_impl<Lhs, Rhs, MatrixShape, SkewSymmetricShape, ProductTag> {
1251 template <
typename Dest>
1252 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
1253 generic_product_impl<Lhs, typename Rhs::DenseMatrixType, MatrixShape, DenseShape, ProductTag>::evalTo(dst, lhs,
1258template <
typename Lhs,
typename Rhs,
int ProductTag>
1259struct generic_product_impl<Lhs, Rhs, SkewSymmetricShape, SkewSymmetricShape, ProductTag> {
1260 template <
typename Dest>
1261 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
1262 generic_product_impl<
typename Lhs::DenseMatrixType,
typename Rhs::DenseMatrixType, DenseShape, DenseShape,
1263 ProductTag>::evalTo(dst, lhs, rhs);
1267template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1268struct generic_product_impl<Lhs, Rhs, MatrixShape, HomogeneousShape, ProductTag>
1269 : generic_product_impl<Lhs, typename Rhs::PlainObject, MatrixShape, DenseShape, ProductTag> {};
1271template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
1272struct generic_product_impl<Lhs, Rhs, HomogeneousShape, MatrixShape, ProductTag>
1273 : generic_product_impl<typename Lhs::PlainObject, Rhs, DenseShape, MatrixShape, ProductTag> {};
1275template <
typename Lhs,
typename Rhs,
int ProductTag>
1276struct generic_product_impl<Lhs, Rhs, PermutationShape, HomogeneousShape, ProductTag>
1277 : generic_product_impl<Lhs, Rhs, PermutationShape, DenseShape, ProductTag> {};
1279template <
typename Lhs,
typename Rhs,
int ProductTag>
1280struct generic_product_impl<Lhs, Rhs, HomogeneousShape, PermutationShape, ProductTag>
1281 : generic_product_impl<Lhs, Rhs, DenseShape, PermutationShape, ProductTag> {};
@ Aligned16
Definition Constants.h:237
@ ColMajor
Definition Constants.h:318
@ RowMajor
Definition Constants.h:320
@ OnTheLeft
Definition Constants.h:331
@ OnTheRight
Definition Constants.h:333
const unsigned int ActualPacketAccessBit
Definition Constants.h:108
const unsigned int PacketAccessBit
Definition Constants.h:97
const unsigned int LinearAccessBit
Definition Constants.h:133
const unsigned int EvalBeforeNestingBit
Definition Constants.h:74
const unsigned int RowMajorBit
Definition Constants.h:70
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
std::enable_if_t< std::is_base_of< DenseBase< std::decay_t< DerivedA > >, std::decay_t< DerivedA > >::value &&std::is_base_of< DenseBase< std::decay_t< DerivedB > >, std::decay_t< DerivedB > >::value, void > swap(DerivedA &&a, DerivedB &&b)
Definition DenseBase.h:667
const int HugeCost
Definition Constants.h:48
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:82
const int Dynamic
Definition Constants.h:25
adds(const Scalar &s)
Definition ProductEvaluators.h:313
void operator()(const Dst &dst, const Src &src) const
Definition ProductEvaluators.h:316