13#ifndef EIGEN_PRODUCTEVALUATORS_H
14#define EIGEN_PRODUCTEVALUATORS_H
17#include "./InternalHeaderCheck.h"
23#pragma warning(disable : 4804)
38template <
typename Lhs,
typename Rhs,
int Options>
39struct evaluator<Product<Lhs, Rhs, Options>> :
public product_evaluator<Product<Lhs, Rhs, Options>> {
40 using XprType = Product<Lhs, Rhs, Options>;
41 using Base = product_evaluator<XprType>;
43 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit evaluator(
const XprType& xpr) : Base(xpr) {}
47template <typename Lhs, typename Shape = typename evaluator_traits<Lhs>::Shape>
48struct product_can_fold_scalar
49 : bool_constant<std::is_same<Shape, DenseShape>::value || std::is_same<Shape, SparseShape>::value ||
50 std::is_same<Shape, DiagonalShape>::value || std::is_same<Shape, SelfAdjointShape>::value> {};
52template <
typename Lhs>
53struct product_can_fold_scalar<Lhs, TriangularShape> : bool_constant<(int(Lhs::Mode) & int(UnitDiag)) == 0> {};
56template <
typename Lhs,
typename Rhs>
57struct product_evaluator_can_fold_scalar
58 : bool_constant<product_can_fold_scalar<Lhs>::value &&
59 !(std::is_same<typename evaluator_traits<Lhs>::Shape, SelfAdjointShape>::value &&
60 std::is_same<typename evaluator_traits<Rhs>::Shape, DiagonalShape>::value)> {};
62template <
typename Xpr,
63 bool Fold = product_evaluator_can_fold_scalar<typename Xpr::Rhs::Lhs, typename Xpr::Rhs::Rhs>::value>
64struct scaled_product_evaluator_type {
66 using type = std::conditional_t<product_can_fold_scalar<typename Xpr::Rhs::Lhs>::value, evaluator<EvalToTemp<Xpr>>,
67 binary_evaluator<Xpr>>;
70template <
typename Xpr>
71struct scaled_product_evaluator_type<Xpr, true> {
73 evaluator<remove_all_t<decltype((std::declval<Xpr>().lhs().functor().m_other * std::declval<Xpr>().rhs().lhs()) *
74 std::declval<Xpr>().rhs().rhs())>>;
79template <
typename Lhs,
typename Rhs,
typename Scalar1,
typename Scalar2,
typename Plain1>
80struct evaluator_assume_aliasing<CwiseBinaryOp<internal::scalar_product_op<Scalar1, Scalar2>,
81 const CwiseNullaryOp<internal::scalar_constant_op<Scalar1>, Plain1>,
82 const Product<Lhs, Rhs, DefaultProduct>>> : std::true_type {};
83template <
typename Lhs,
typename Rhs,
typename Scalar1,
typename Scalar2,
typename Plain1>
84struct evaluator<CwiseBinaryOp<internal::scalar_product_op<Scalar1, Scalar2>,
85 const CwiseNullaryOp<internal::scalar_constant_op<Scalar1>, Plain1>,
86 const Product<Lhs, Rhs, DefaultProduct>>>
87 : scaled_product_evaluator_type<CwiseBinaryOp<internal::scalar_product_op<Scalar1, Scalar2>,
88 const CwiseNullaryOp<internal::scalar_constant_op<Scalar1>, Plain1>,
89 const Product<Lhs, Rhs, DefaultProduct>>>::type {
90 using XprType = CwiseBinaryOp<internal::scalar_product_op<Scalar1, Scalar2>,
91 const CwiseNullaryOp<internal::scalar_constant_op<Scalar1>, Plain1>,
92 const Product<Lhs, Rhs, DefaultProduct>>;
93 using Base =
typename scaled_product_evaluator_type<XprType>::type;
95 template <bool Fold = product_evaluator_can_fold_scalar<Lhs, Rhs>::value, std::enable_if_t<Fold, int> = 0>
96 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit evaluator(
const XprType& xpr)
97 : Base(xpr.lhs().functor().m_other * xpr.rhs().lhs() * xpr.rhs().rhs()) {}
99 template <bool Fold = product_evaluator_can_fold_scalar<Lhs, Rhs>::value, std::enable_if_t<!Fold, int> = 0>
100 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit evaluator(
const XprType& xpr) : Base(xpr) {}
103template <
typename Lhs,
typename Rhs,
int DiagIndex>
104struct evaluator<Diagonal<const Product<Lhs, Rhs, DefaultProduct>, DiagIndex>>
105 :
public evaluator<Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex>> {
106 using XprType = Diagonal<const Product<Lhs, Rhs, DefaultProduct>, DiagIndex>;
107 using Base = evaluator<Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex>>;
109 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit evaluator(
const XprType& xpr)
110 : Base(Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex>(
111 Product<Lhs, Rhs, LazyProduct>(xpr.nestedExpression().lhs(), xpr.nestedExpression().rhs()), xpr.index())) {}
117template <typename Lhs, typename Rhs, typename LhsShape = typename evaluator_traits<Lhs>::Shape,
118 typename RhsShape =
typename evaluator_traits<Rhs>::Shape,
119 int ProductType = internal::product_type<Lhs, Rhs>::value>
120struct generic_product_impl;
122template <
typename Lhs,
typename Rhs>
123struct evaluator_assume_aliasing<Product<Lhs, Rhs, DefaultProduct>> : std::true_type {};
127template <
typename Lhs,
typename Rhs,
int Options,
int ProductTag,
typename LhsShape,
typename RhsShape>
128struct product_evaluator<Product<Lhs, Rhs, Options>, ProductTag, LhsShape, RhsShape>
129 :
public evaluator<typename Product<Lhs, Rhs, Options>::PlainObject> {
130 using XprType = Product<Lhs, Rhs, Options>;
131 using PlainObject =
typename XprType::PlainObject;
132 using Base = evaluator<PlainObject>;
135 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit product_evaluator(
const XprType& xpr)
136 : m_result(xpr.rows(), xpr.cols()) {
137 internal::construct_at<Base>(
this, m_result);
152 generic_product_impl<Lhs, Rhs, LhsShape, RhsShape, ProductTag>::evalTo(m_result, xpr.lhs(), xpr.rhs());
156 PlainObject m_result;
163template <
typename DstXprType,
typename Lhs,
typename Rhs,
int Options,
typename Scalar>
164struct Assignment<DstXprType, Product<Lhs, Rhs, Options>, internal::assign_op<Scalar, Scalar>, Dense2Dense,
165 std::enable_if_t<(Options == DefaultProduct || Options == AliasFreeProduct)>> {
166 using SrcXprType = Product<Lhs, Rhs, Options>;
167 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
168 const internal::assign_op<Scalar, Scalar>& func) {
169 resize_if_allowed(dst, src, func);
171 generic_product_impl<Lhs, Rhs>::evalTo(dst, src.lhs(), src.rhs());
176template <
typename DstXprType,
typename Lhs,
typename Rhs,
int Options,
typename Scalar>
177struct Assignment<DstXprType, Product<Lhs, Rhs, Options>, internal::add_assign_op<Scalar, Scalar>, Dense2Dense,
178 std::enable_if_t<(Options == DefaultProduct || Options == AliasFreeProduct)>> {
179 using SrcXprType = Product<Lhs, Rhs, Options>;
180 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
181 const internal::add_assign_op<Scalar, Scalar>&) {
182 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
184 generic_product_impl<Lhs, Rhs>::addTo(dst, src.lhs(), src.rhs());
189template <
typename DstXprType,
typename Lhs,
typename Rhs,
int Options,
typename Scalar>
190struct Assignment<DstXprType, Product<Lhs, Rhs, Options>, internal::sub_assign_op<Scalar, Scalar>, Dense2Dense,
191 std::enable_if_t<(Options == DefaultProduct || Options == AliasFreeProduct)>> {
192 using SrcXprType = Product<Lhs, Rhs, Options>;
193 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
194 const internal::sub_assign_op<Scalar, Scalar>&) {
195 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
197 generic_product_impl<Lhs, Rhs>::subTo(dst, src.lhs(), src.rhs());
204template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename AssignFunc,
typename Scalar,
typename ScalarBis,
206struct Assignment<DstXprType,
207 CwiseBinaryOp<internal::scalar_product_op<ScalarBis, Scalar>,
208 const CwiseNullaryOp<internal::scalar_constant_op<ScalarBis>, Plain>,
209 const Product<Lhs, Rhs, DefaultProduct>>,
210 AssignFunc, Dense2Dense, std::enable_if_t<product_can_fold_scalar<Lhs>::value>> {
211 using SrcXprType = CwiseBinaryOp<internal::scalar_product_op<ScalarBis, Scalar>,
212 const CwiseNullaryOp<internal::scalar_constant_op<ScalarBis>, Plain>,
213 const Product<Lhs, Rhs, DefaultProduct>>;
214 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
215 const AssignFunc& func) {
216 call_assignment_no_alias(dst, (src.lhs().functor().m_other * src.rhs().lhs()) * src.rhs().rhs(), func);
224template <
typename OtherXpr,
typename Lhs,
typename Rhs>
225struct evaluator_assume_aliasing<
227 internal::scalar_sum_op<typename OtherXpr::Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
228 const OtherXpr, const Product<Lhs, Rhs, DefaultProduct>>,
229 DenseShape> : std::true_type {};
231template <
typename OtherXpr,
typename Lhs,
typename Rhs>
232struct evaluator_assume_aliasing<
234 internal::scalar_difference_op<typename OtherXpr::Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
235 const OtherXpr, const Product<Lhs, Rhs, DefaultProduct>>,
236 DenseShape> : std::true_type {};
238template <
typename DstXprType,
typename OtherXpr,
typename ProductType,
typename Func1,
typename Func2>
239struct assignment_from_xpr_op_product {
240 template <
typename SrcXprType,
typename InitialFunc>
241 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
242 const InitialFunc& ) {
243 call_assignment_no_alias(dst, src.lhs(), Func1());
244 call_assignment_no_alias(dst, src.rhs(), Func2());
248#define EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(ASSIGN_OP, BINOP, ASSIGN_OP2) \
249 template <typename DstXprType, typename OtherXpr, typename Lhs, typename Rhs, typename DstScalar, \
250 typename SrcScalar, typename OtherScalar, typename ProdScalar> \
251 struct Assignment<DstXprType, \
252 CwiseBinaryOp<internal::BINOP<OtherScalar, ProdScalar>, const OtherXpr, \
253 const Product<Lhs, Rhs, DefaultProduct>>, \
254 internal::ASSIGN_OP<DstScalar, SrcScalar>, Dense2Dense> \
255 : assignment_from_xpr_op_product<DstXprType, OtherXpr, Product<Lhs, Rhs, DefaultProduct>, \
256 internal::ASSIGN_OP<DstScalar, OtherScalar>, \
257 internal::ASSIGN_OP2<DstScalar, ProdScalar>> {}
259EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_sum_op, add_assign_op);
260EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(add_assign_op, scalar_sum_op, add_assign_op);
261EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(sub_assign_op, scalar_sum_op, sub_assign_op);
263EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_difference_op, sub_assign_op);
264EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(add_assign_op, scalar_difference_op, sub_assign_op);
265EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(sub_assign_op, scalar_difference_op, add_assign_op);
269template <
typename Lhs,
typename Rhs>
270struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, InnerProduct> {
271 using impl = inner_product_dispatch<Lhs, Rhs, false>;
272 template <
typename Dst>
273 static EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
void evalTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
274 dst.coeffRef(0, 0) = impl::run(lhs, rhs);
277 template <
typename Dst>
278 static EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
void addTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
279 dst.coeffRef(0, 0) += impl::run(lhs, rhs);
282 template <
typename Dst>
283 static EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
void subTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
284 dst.coeffRef(0, 0) -= impl::run(lhs, rhs);
293template <
typename Dst,
typename Lhs,
typename Rhs,
typename Func>
294void EIGEN_DEVICE_FUNC outer_product_selector_run(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
const Func& func,
295 const std::false_type&) {
296 evaluator<Rhs> rhsEval(rhs);
297 ei_declare_local_nested_eval(Lhs, lhs, Rhs::SizeAtCompileTime, actual_lhs);
300 const Index cols = dst.cols();
301 for (Index j = 0; j < cols; ++j) func(dst.col(j), rhsEval.coeff(Index(0), j) * actual_lhs);
305template <
typename Dst,
typename Lhs,
typename Rhs,
typename Func>
306void EIGEN_DEVICE_FUNC outer_product_selector_run(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
const Func& func,
307 const std::true_type&) {
308 evaluator<Lhs> lhsEval(lhs);
309 ei_declare_local_nested_eval(Rhs, rhs, Lhs::SizeAtCompileTime, actual_rhs);
312 const Index rows = dst.rows();
313 for (Index i = 0; i < rows; ++i) func(dst.row(i), lhsEval.coeff(i, Index(0)) * actual_rhs);
316template <
typename Dst>
317EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool outer_product_use_small_assignment(
const Dst& dst) {
318 return dst.rows() <= 16 && dst.cols() <= 16;
321template <
bool ApplyScale = true,
typename Dst,
typename Lhs,
typename Rhs,
typename Func,
typename Scalar>
322void EIGEN_DEVICE_FUNC outer_product_selector_run_small(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
const Func& func,
323 const Scalar& alpha,
const std::false_type&) {
324 evaluator<Rhs> rhsEval(rhs);
325 ei_declare_local_nested_eval(Lhs, lhs, Rhs::SizeAtCompileTime, actual_lhs);
326 const Index rows = dst.rows();
327 const Index cols = dst.cols();
328 for (Index j = 0; j < cols; ++j) {
329 const typename Rhs::Scalar rhs_j = rhsEval.coeff(Index(0), j);
330 for (Index i = 0; i < rows; ++i) {
331 EIGEN_IF_CONSTEXPR (ApplyScale) {
332 func.assignCoeff(dst.coeffRef(i, j), internal::mul(alpha, internal::mul(rhs_j, actual_lhs.coeff(i, Index(0)))));
334 func.assignCoeff(dst.coeffRef(i, j), internal::mul(rhs_j, actual_lhs.coeff(i, Index(0))));
340template <
bool ApplyScale = true,
typename Dst,
typename Lhs,
typename Rhs,
typename Func,
typename Scalar>
341void EIGEN_DEVICE_FUNC outer_product_selector_run_small(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
const Func& func,
342 const Scalar& alpha,
const std::true_type&) {
343 evaluator<Lhs> lhsEval(lhs);
344 ei_declare_local_nested_eval(Rhs, rhs, Lhs::SizeAtCompileTime, actual_rhs);
345 const Index rows = dst.rows();
346 const Index cols = dst.cols();
347 for (Index i = 0; i < rows; ++i) {
348 const typename Lhs::Scalar lhs_i = lhsEval.coeff(i, Index(0));
349 for (Index j = 0; j < cols; ++j) {
350 EIGEN_IF_CONSTEXPR (ApplyScale) {
351 func.assignCoeff(dst.coeffRef(i, j), internal::mul(alpha, internal::mul(lhs_i, actual_rhs.coeff(Index(0), j))));
353 func.assignCoeff(dst.coeffRef(i, j), internal::mul(lhs_i, actual_rhs.coeff(Index(0), j)));
359template <
typename Lhs,
typename Rhs>
360struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, OuterProduct> {
361 template <
typename T>
362 struct is_row_major : bool_constant<(int(T::Flags) & RowMajorBit)> {};
363 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
367 template <
typename Dst,
typename Src>
368 EIGEN_DEVICE_FUNC
void operator()(
const Dst& dst,
const Src& src)
const {
369 dst.const_cast_derived() = src;
374 template <
typename Dst,
typename Src>
375 EIGEN_DEVICE_FUNC
void operator()(
const Dst& dst,
const Src& src)
const {
376 dst.const_cast_derived() += src;
380 template <
typename Dst,
typename Src>
381 EIGEN_DEVICE_FUNC
void operator()(
const Dst& dst,
const Src& src)
const {
382 dst.const_cast_derived() -= src;
389 EIGEN_DEVICE_FUNC
explicit adds(
const Scalar& s) : m_scale(s) {}
391 template <
typename Dst,
typename Src>
392 void EIGEN_DEVICE_FUNC
operator()(
const Dst& dst,
const Src& src)
const {
393 dst.const_cast_derived() += m_scale * src;
397 template <
typename Dst>
398 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
399 if (internal::outer_product_use_small_assignment(dst)) {
400 internal::outer_product_selector_run_small<false>(
401 dst, lhs, rhs, internal::assign_op<typename Dst::Scalar, Scalar>(), Scalar(1), is_row_major<Dst>());
403 internal::outer_product_selector_run(dst, lhs, rhs, set(), is_row_major<Dst>());
407 template <
typename Dst>
408 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void addTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
409 if (internal::outer_product_use_small_assignment(dst)) {
410 internal::outer_product_selector_run_small<false>(
411 dst, lhs, rhs, internal::add_assign_op<typename Dst::Scalar, Scalar>(), Scalar(1), is_row_major<Dst>());
413 internal::outer_product_selector_run(dst, lhs, rhs, add(), is_row_major<Dst>());
417 template <
typename Dst>
418 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void subTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
419 if (internal::outer_product_use_small_assignment(dst)) {
420 internal::outer_product_selector_run_small<false>(
421 dst, lhs, rhs, internal::sub_assign_op<typename Dst::Scalar, Scalar>(), Scalar(1), is_row_major<Dst>());
423 internal::outer_product_selector_run(dst, lhs, rhs, sub(), is_row_major<Dst>());
427 template <
typename Dst>
428 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
429 const Scalar& alpha) {
430 if (internal::outer_product_use_small_assignment(dst)) {
431 internal::outer_product_selector_run_small(dst, lhs, rhs, internal::add_assign_op<typename Dst::Scalar, Scalar>(),
432 alpha, is_row_major<Dst>());
434 internal::outer_product_selector_run(dst, lhs, rhs, adds(alpha), is_row_major<Dst>());
440template <
typename Lhs,
typename Rhs,
typename Derived>
441struct generic_product_impl_base {
442 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
444 template <
typename Dst>
445 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
447 scaleAndAddTo(dst, lhs, rhs, Scalar(1));
450 template <
typename Dst>
451 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void addTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
452 scaleAndAddTo(dst, lhs, rhs, Scalar(1));
455 template <
typename Dst>
456 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void subTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
457 scaleAndAddTo(dst, lhs, rhs, Scalar(-1));
460 template <
typename Dst>
461 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
462 const Scalar& alpha) {
463 Derived::scaleAndAddTo(dst, lhs, rhs, alpha);
467template <
typename Lhs,
typename Rhs>
468struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, GemvProduct>
469 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, GemvProduct>> {
470 using LhsNested =
typename nested_eval<Lhs, 1>::type;
471 using RhsNested =
typename nested_eval<Rhs, 1>::type;
472 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
474 using MatrixType = internal::remove_all_t<std::conditional_t<int(Side) ==
OnTheRight, LhsNested, RhsNested>>;
476 template <
typename Dest>
477 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
478 const Scalar& alpha) {
480 if (lhs.rows() == 1 && rhs.cols() == 1) {
481 dst.coeffRef(0, 0) += alpha * lhs.row(0).conjugate().dot(rhs.col(0));
484 LhsNested actual_lhs(lhs);
485 RhsNested actual_rhs(rhs);
487 bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)>::run(actual_lhs,
510template <
typename Packet,
bool ColMajor,
511 bool Terminal = std::is_same<typename unpacket_traits<Packet>::half, Packet>::value>
512struct product_packet_cascade {
513 template <
typename Func,
typename Dst,
typename ProdEval>
514 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(
const Func& func, Dst& dst,
const ProdEval& prod, Index outer,
515 Index begin, Index end) {
516 constexpr int PacketSize = unpacket_traits<Packet>::size;
517 Index pktEnd = begin + numext::round_down(end - begin, PacketSize);
519 for (; i < pktEnd; i += PacketSize) {
521 func.template assignPacket<Unaligned, Packet>(&dst.coeffRef(r, c), prod.template packet<Unaligned, Packet>(r, c));
524 product_packet_cascade<typename unpacket_traits<Packet>::half,
ColMajor>::run(func, dst, prod, outer, i, end);
529template <
typename Packet,
bool ColMajor>
530struct product_packet_cascade<Packet,
ColMajor, true> {
531 template <
typename Func,
typename Dst,
typename ProdEval>
532 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(
const Func& func, Dst& dst,
const ProdEval& prod, Index outer,
533 Index begin, Index end) {
534 constexpr int PacketSize = unpacket_traits<Packet>::size;
535 Index pktEnd = begin + numext::round_down(end - begin, PacketSize);
537 for (; i < pktEnd; i += PacketSize) {
539 func.template assignPacket<Unaligned, Packet>(&dst.coeffRef(r, c), prod.template packet<Unaligned, Packet>(r, c));
541 for (; i < end; ++i) {
543 func.assignCoeff(dst.coeffRef(r, c), prod.coeff(r, c));
554template <
typename Packet,
int Size,
555 bool Terminal = std::is_same<typename unpacket_traits<Packet>::half, Packet>::value>
556struct largest_exact_divisor_size {
557 static constexpr int s = unpacket_traits<Packet>::size;
558 static constexpr int value =
559 (Size % s == 0) ? s : largest_exact_divisor_size<typename unpacket_traits<Packet>::half, Size>::value;
561template <
typename Packet,
int Size>
562struct largest_exact_divisor_size<Packet, Size, true> {
563 static constexpr int s = unpacket_traits<Packet>::size;
564 static constexpr int value = (Size % s == 0) ? s : 1;
584template <
typename ProdEval,
typename Dst,
typename Func>
585struct product_packet_cascade_traits {
586 using Scalar =
typename ProdEval::Scalar;
587 using DstEval = evaluator<Dst>;
588 static constexpr int Rows = ProdEval::RowsAtCompileTime;
589 static constexpr int Cols = ProdEval::ColsAtCompileTime;
590 static constexpr bool DstRowMajor = bool(Dst::IsRowMajor);
591 static constexpr bool DstContiguous =
592 (int(DstEval::Flags) &
DirectAccessBit) != 0 &&
int(Dst::InnerStrideAtCompileTime) == 1;
598 static constexpr bool ProdRowMajor = (int(ProdEval::Flags) &
RowMajorBit) != 0;
599 static constexpr bool VecLhs =
600 bool(ProdEval::CanVectorizeLhs) && !ProdRowMajor && !DstRowMajor && Rows != Dynamic;
601 static constexpr bool VecRhs =
602 bool(ProdEval::CanVectorizeRhs) && ProdRowMajor && DstRowMajor && Cols != Dynamic;
603 static constexpr int Extent = VecLhs ? Rows : VecRhs ? Cols : 1;
604 using Packet =
typename find_largest_packet<Scalar, Extent>::type;
605 static constexpr int LargestSize = unpacket_traits<Packet>::size;
606 static constexpr int GenericSize = largest_exact_divisor_size<typename packet_traits<Scalar>::type, Extent>::value;
607 static constexpr bool MightVectorize =
608 bool(EIGEN_UNALIGNED_VECTORIZE) &&
610 bool(functor_traits<Func>::PacketAccess);
615 static constexpr bool Enable = bool(ProdEval::SameType) && (VecLhs || VecRhs) && DstContiguous && MightVectorize &&
616 (LargestSize <= Extent) && (LargestSize > GenericSize);
622template <
typename Traits,
typename Func,
typename Dst,
typename ProdEval>
623EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void product_run_packet_cascade(
const Func& func, Dst& dst,
624 const ProdEval& prod) {
625 using Packet =
typename Traits::Packet;
626 Index rows = dst.rows(), cols = dst.cols();
627 Index outerCount = Traits::VecLhs ? cols : rows;
628 Index innerEnd = Traits::VecLhs ? rows : cols;
629 for (Index outer = 0; outer < outerCount; ++outer)
630 product_packet_cascade<Packet, Traits::VecLhs>::run(func, dst, prod, outer, 0, innerEnd);
638template <
typename Func,
typename Dst,
typename Lhs,
typename Rhs>
639EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void product_packet_assign(std::true_type,
const Func& func, Dst& dst,
640 const Lhs& lhs,
const Rhs& rhs) {
641 using ProdEval = product_evaluator<Product<Lhs, Rhs, LazyProduct>, CoeffBasedProductMode, DenseShape, DenseShape>;
642 using Traits = product_packet_cascade_traits<ProdEval, Dst, Func>;
643 const ProdEval prodEval(lhs, rhs);
644 product_run_packet_cascade<Traits>(func, dst, prodEval);
646template <
typename Func,
typename Dst,
typename Lhs,
typename Rhs>
647EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void product_packet_assign(std::false_type,
const Func& func, Dst& dst,
648 const Lhs& lhs,
const Rhs& rhs) {
649 call_assignment_no_alias(dst, lhs.lazyProduct(rhs), func);
652template <
typename Lhs,
typename Rhs>
653struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, CoeffBasedProductMode> {
654 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
656 template <
typename Dst>
657 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
666 call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::assign_op<typename Dst::Scalar, Scalar>());
669 template <
typename Dst>
670 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void addTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
672 using ProdEval = product_evaluator<Product<Lhs, Rhs, LazyProduct>, CoeffBasedProductMode, DenseShape, DenseShape>;
673 using Func = internal::add_assign_op<typename Dst::Scalar, Scalar>;
674 using Traits = product_packet_cascade_traits<ProdEval, Dst, Func>;
675 product_packet_assign(bool_constant<Traits::Enable>(), Func(), dst, lhs, rhs);
678 template <
typename Dst>
679 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void subTo(Dst& dst,
const Lhs& lhs,
const Rhs& rhs) {
681 using ProdEval = product_evaluator<Product<Lhs, Rhs, LazyProduct>, CoeffBasedProductMode, DenseShape, DenseShape>;
682 using Func = internal::sub_assign_op<typename Dst::Scalar, Scalar>;
683 using Traits = product_packet_cascade_traits<ProdEval, Dst, Func>;
684 product_packet_assign(bool_constant<Traits::Enable>(), Func(), dst, lhs, rhs);
701 template <
typename Dst,
typename Func>
702 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void eval_dynamic(Dst& dst,
const Lhs& lhs,
const Rhs& rhs,
705 HasScalarFactor = blas_traits<Lhs>::HasScalarFactor || blas_traits<Rhs>::HasScalarFactor,
706 ConjLhs = blas_traits<Lhs>::NeedToConjugate,
707 ConjRhs = blas_traits<Rhs>::NeedToConjugate
711 Scalar actualAlpha = combine_scalar_factors<Scalar>(lhs, rhs);
713 eval_dynamic_impl(dst, blas_traits<Lhs>::extract(lhs).
template conjugateIf<ConjLhs>(),
714 blas_traits<Rhs>::extract(rhs).
template conjugateIf<ConjRhs>(), func, actualAlpha,
715 bool_constant<HasScalarFactor>());
719 template <
typename Dst,
typename LhsT,
typename RhsT,
typename Func,
typename Scalar>
720 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void eval_dynamic_impl(Dst& dst,
const LhsT& lhs,
const RhsT& rhs,
721 const Func& func,
const Scalar& s ,
723 EIGEN_UNUSED_VARIABLE(s);
724 eigen_internal_assert(numext::is_exactly_one(s));
725 call_restricted_packet_assignment_no_alias(dst, lhs.lazyProduct(rhs), func);
728 template <
typename Dst,
typename LhsT,
typename RhsT,
typename Func,
typename Scalar>
729 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void eval_dynamic_impl(Dst& dst,
const LhsT& lhs,
const RhsT& rhs,
730 const Func& func,
const Scalar& s,
732 call_restricted_packet_assignment_no_alias(dst, s * lhs.lazyProduct(rhs), func);
737template <
typename Lhs,
typename Rhs>
738struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, LazyCoeffBasedProductMode>
739 : generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, CoeffBasedProductMode> {};
741template <
int StorageOrder,
int UnrollingIndex,
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
742struct etor_product_packet_impl;
744struct product_empty_packet_evaluator {
745 template <
typename Xpr>
746 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit product_empty_packet_evaluator(
const Xpr&) {}
749template <
typename Lhs,
typename Rhs,
int ProductTag>
750struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape, DenseShape>
751 : evaluator_base<Product<Lhs, Rhs, LazyProduct>> {
752 using XprType = Product<Lhs, Rhs, LazyProduct>;
753 using Scalar =
typename XprType::Scalar;
754 using CoeffReturnType =
typename XprType::CoeffReturnType;
756 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit product_evaluator(
const XprType& xpr)
757 : product_evaluator(xpr.lhs(), xpr.rhs()) {}
761 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE product_evaluator(
const Lhs& lhs,
const Rhs& rhs)
766 m_innerDim(lhs.cols()) {
767 EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::MulCost);
768 EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::AddCost);
769 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
774 using LhsNested =
typename internal::nested_eval<Lhs, Rhs::ColsAtCompileTime>::type;
775 using RhsNested =
typename internal::nested_eval<Rhs, Lhs::RowsAtCompileTime>::type;
777 using LhsNestedCleaned = internal::remove_all_t<LhsNested>;
778 using RhsNestedCleaned = internal::remove_all_t<RhsNested>;
780 using LhsScalar =
typename LhsNestedCleaned::Scalar;
781 using RhsScalar =
typename RhsNestedCleaned::Scalar;
783 using LhsEtorType = evaluator<LhsNestedCleaned>;
784 using RhsEtorType = evaluator<RhsNestedCleaned>;
787 RowsAtCompileTime = LhsNestedCleaned::RowsAtCompileTime,
788 ColsAtCompileTime = RhsNestedCleaned::ColsAtCompileTime,
789 InnerSize = min_size_prefer_fixed(LhsNestedCleaned::ColsAtCompileTime, RhsNestedCleaned::RowsAtCompileTime),
790 MaxRowsAtCompileTime = LhsNestedCleaned::MaxRowsAtCompileTime,
791 MaxColsAtCompileTime = RhsNestedCleaned::MaxColsAtCompileTime
794 using LhsVecPacketType =
typename find_best_packet<Scalar, RowsAtCompileTime>::type;
795 using RhsVecPacketType =
typename find_best_packet<Scalar, ColsAtCompileTime>::type;
797 static constexpr int LhsCoeffReadCost = LhsEtorType::CoeffReadCost;
798 static constexpr int RhsCoeffReadCost = RhsEtorType::CoeffReadCost;
799 static constexpr int CoeffReadCost =
800 InnerSize == 0 ? NumTraits<Scalar>::ReadCost
801 : InnerSize == Dynamic
803 : InnerSize * (NumTraits<Scalar>::MulCost + int(LhsCoeffReadCost) + int(RhsCoeffReadCost)) +
804 (InnerSize - 1) * NumTraits<Scalar>::AddCost;
806 static constexpr bool Unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT;
808 static constexpr int LhsFlags = LhsEtorType::Flags;
809 static constexpr int RhsFlags = RhsEtorType::Flags;
811 static constexpr int LhsRowMajor = LhsFlags &
RowMajorBit;
812 static constexpr int RhsRowMajor = RhsFlags &
RowMajorBit;
814 static constexpr int LhsVecPacketSize = unpacket_traits<LhsVecPacketType>::size;
815 static constexpr int RhsVecPacketSize = unpacket_traits<RhsVecPacketType>::size;
818 static constexpr int LhsAlignment =
819 plain_enum_min(LhsEtorType::Alignment, LhsVecPacketSize*
int(
sizeof(
typename LhsNestedCleaned::Scalar)));
820 static constexpr int RhsAlignment =
821 plain_enum_min(RhsEtorType::Alignment, RhsVecPacketSize*
int(
sizeof(
typename RhsNestedCleaned::Scalar)));
823 static constexpr bool SameType =
824 std::is_same<typename LhsNestedCleaned::Scalar, typename RhsNestedCleaned::Scalar>::value;
826 static constexpr bool CanVectorizeRhs = bool(RhsRowMajor) && (RhsFlags &
PacketAccessBit) && (ColsAtCompileTime != 1);
827 static constexpr bool CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags &
PacketAccessBit) && (RowsAtCompileTime != 1);
829 static constexpr int EvalToRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? 1
830 : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1)
832 : (bool(RhsRowMajor) && !CanVectorizeLhs);
834 static constexpr int Flags = ((int(LhsFlags) | int(RhsFlags)) & HereditaryBits & ~RowMajorBit) |
837 | (SameType && (CanVectorizeLhs || CanVectorizeRhs) ?
PacketAccessBit : 0) |
839 using LhsPacketEtorType =
840 std::conditional_t<bool(
int(Flags) &
PacketAccessBit), LhsEtorType, product_empty_packet_evaluator>;
841 using RhsPacketEtorType =
842 std::conditional_t<bool(
int(Flags) &
PacketAccessBit), RhsEtorType, product_empty_packet_evaluator>;
844 static constexpr bool SingleTermCoeff = InnerSize == 1 && std::is_same<LhsPacketEtorType, LhsEtorType>::value &&
845 std::is_same<RhsPacketEtorType, RhsEtorType>::value;
847 static constexpr int LhsOuterStrideBytes =
848 int(LhsNestedCleaned::OuterStrideAtCompileTime) * int(
sizeof(
typename LhsNestedCleaned::Scalar));
849 static constexpr int RhsOuterStrideBytes =
850 int(RhsNestedCleaned::OuterStrideAtCompileTime) * int(
sizeof(
typename RhsNestedCleaned::Scalar));
852 static constexpr int Alignment =
853 bool(CanVectorizeLhs)
854 ? (LhsOuterStrideBytes <= 0 || (int(LhsOuterStrideBytes) % plain_enum_max(1, LhsAlignment)) != 0
857 : bool(CanVectorizeRhs)
858 ? (RhsOuterStrideBytes <= 0 || (int(RhsOuterStrideBytes) % plain_enum_max(1, RhsAlignment)) != 0
863 EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
const CoeffReturnType coeff(Index row, Index col)
const {
864 return coeff_impl(row, col, bool_constant<SingleTermCoeff>());
867 EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff_impl(Index row, Index col,
868 std::true_type)
const {
869 return fast_mult_op<LhsScalar, RhsScalar>()(m_lhsImpl.coeff(row, Index(0)), m_rhsImpl.coeff(Index(0), col));
872 EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff_impl(Index row, Index col,
873 std::false_type)
const {
877 return m_lhs.row(row).transpose().binaryExpr(m_rhs.col(col), fast_mult_op<LhsScalar, RhsScalar>()).sum();
884 EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
const CoeffReturnType coeff(Index index)
const {
885 const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index;
886 const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0;
887 return coeff(row, col);
890 template <
int LoadMode,
typename PacketType>
891 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const PacketType packet(Index row, Index col)
const {
895 Unroll ? int(InnerSize) : Dynamic, LhsEtorType, RhsEtorType, PacketType, LoadMode>;
896 PacketImpl::run(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res);
900 template <
int LoadMode,
typename PacketType>
901 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const PacketType packet(Index index)
const {
902 const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index;
903 const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0;
904 return packet<LoadMode, PacketType>(row, col);
907 template <
int LoadMode,
typename PacketType>
908 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const PacketType packetSegment(Index row, Index col, Index begin,
913 Unroll ? int(InnerSize) : Dynamic, LhsEtorType, RhsEtorType, PacketType, LoadMode>;
914 PacketImpl::run_segment(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res, begin, count);
918 template <
int LoadMode,
typename PacketType>
919 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const PacketType packetSegment(Index index, Index begin, Index count)
const {
920 const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index;
921 const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0;
922 return packetSegment<LoadMode, PacketType>(row, col, begin, count);
926 add_const_on_value_type_t<LhsNested> m_lhs;
927 add_const_on_value_type_t<RhsNested> m_rhs;
929 LhsPacketEtorType m_lhsImpl;
930 RhsPacketEtorType m_rhsImpl;
932 variable_if_dynamic<Index, InnerSize> m_innerDim;
935template <
typename Lhs,
typename Rhs>
936struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, LazyCoeffBasedProductMode, DenseShape, DenseShape>
937 : product_evaluator<Product<Lhs, Rhs, LazyProduct>, CoeffBasedProductMode, DenseShape, DenseShape> {
938 using XprType = Product<Lhs, Rhs, DefaultProduct>;
939 using BaseProduct = Product<Lhs, Rhs, LazyProduct>;
940 using Base = product_evaluator<BaseProduct, CoeffBasedProductMode, DenseShape, DenseShape>;
942 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit product_evaluator(
const XprType& xpr)
943 : Base(BaseProduct(xpr.lhs(), xpr.rhs())) {}
950template <
int UnrollingIndex,
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
951struct etor_product_packet_impl<
RowMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode> {
952 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
953 Index innerDim, Packet& res) {
954 etor_product_packet_impl<RowMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs,
956 res = pmadd(pset1<Packet>(lhs.coeff(row, Index(UnrollingIndex - 1))),
957 rhs.template packet<LoadMode, Packet>(Index(UnrollingIndex - 1), col), res);
959 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
960 Index innerDim, Packet& res, Index begin, Index count) {
961 etor_product_packet_impl<RowMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run_segment(
962 row, col, lhs, rhs, innerDim, res, begin, count);
963 res = pmadd(pset1<Packet>(lhs.coeff(row, Index(UnrollingIndex - 1))),
964 rhs.template packetSegment<LoadMode, Packet>(Index(UnrollingIndex - 1), col, begin, count), res);
968template <
int UnrollingIndex,
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
969struct etor_product_packet_impl<
ColMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode> {
970 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
971 Index innerDim, Packet& res) {
972 etor_product_packet_impl<ColMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs,
974 res = pmadd(lhs.template packet<LoadMode, Packet>(row, Index(UnrollingIndex - 1)),
975 pset1<Packet>(rhs.coeff(Index(UnrollingIndex - 1), col)), res);
977 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
978 Index innerDim, Packet& res, Index begin, Index count) {
979 etor_product_packet_impl<ColMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run_segment(
980 row, col, lhs, rhs, innerDim, res, begin, count);
981 res = pmadd(lhs.template packetSegment<LoadMode, Packet>(row, Index(UnrollingIndex - 1), begin, count),
982 pset1<Packet>(rhs.coeff(Index(UnrollingIndex - 1), col)), res);
986template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
987struct etor_product_packet_impl<
RowMajor, 1, Lhs, Rhs, Packet, LoadMode> {
988 static EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
989 Index , Packet& res) {
990 res = pmul(pset1<Packet>(lhs.coeff(row, Index(0))), rhs.template packet<LoadMode, Packet>(Index(0), col));
992 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
993 Index , Packet& res, Index begin,
995 res = pmul(pset1<Packet>(lhs.coeff(row, Index(0))),
996 rhs.template packetSegment<LoadMode, Packet>(Index(0), col, begin, count));
1000template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
1001struct etor_product_packet_impl<
ColMajor, 1, Lhs, Rhs, Packet, LoadMode> {
1002 static EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
1003 Index , Packet& res) {
1004 res = pmul(lhs.template packet<LoadMode, Packet>(row, Index(0)), pset1<Packet>(rhs.coeff(Index(0), col)));
1006 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
1007 Index , Packet& res, Index begin,
1009 res = pmul(lhs.template packetSegment<LoadMode, Packet>(row, Index(0), begin, count),
1010 pset1<Packet>(rhs.coeff(Index(0), col)));
1014template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
1015struct etor_product_packet_impl<
RowMajor, 0, Lhs, Rhs, Packet, LoadMode> {
1016 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index , Index ,
const Lhs& ,
1017 const Rhs& , Index , Packet& res) {
1018 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
1020 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index , Index ,
const Lhs& ,
1021 const Rhs& , Index , Packet& res,
1023 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
1027template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
1028struct etor_product_packet_impl<
ColMajor, 0, Lhs, Rhs, Packet, LoadMode> {
1029 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index , Index ,
const Lhs& ,
1030 const Rhs& , Index , Packet& res) {
1031 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
1033 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index , Index ,
const Lhs& ,
1034 const Rhs& , Index , Packet& res,
1036 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
1040template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
1041struct etor_product_packet_impl<
RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode> {
1042 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
1043 Index innerDim, Packet& res) {
1044 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
1045 for (Index i = 0; i < innerDim; ++i)
1046 res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode, Packet>(i, col), res);
1048 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
1049 Index innerDim, Packet& res, Index begin, Index count) {
1050 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
1051 for (Index i = 0; i < innerDim; ++i)
1052 res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packetSegment<LoadMode, Packet>(i, col, begin, count),
1057template <
typename Lhs,
typename Rhs,
typename Packet,
int LoadMode>
1058struct etor_product_packet_impl<
ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode> {
1059 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
1060 Index innerDim, Packet& res) {
1061 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
1062 for (Index i = 0; i < innerDim; ++i)
1063 res = pmadd(lhs.template packet<LoadMode, Packet>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
1065 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run_segment(Index row, Index col,
const Lhs& lhs,
const Rhs& rhs,
1066 Index innerDim, Packet& res, Index begin, Index count) {
1067 res = pset1<Packet>(
typename unpacket_traits<Packet>::type(0));
1068 for (Index i = 0; i < innerDim; ++i)
1069 res = pmadd(lhs.template packetSegment<LoadMode, Packet>(row, i, begin, count), pset1<Packet>(rhs.coeff(i, col)),
1077template <
int Mode,
bool LhsIsTriangular,
typename Lhs,
bool LhsIsVector,
typename Rhs,
bool RhsIsVector>
1078struct triangular_product_impl;
1080template <
int ProductOrder>
1081struct diagonal_product_segment_impl;
1084struct diagonal_product_segment_impl<
OnTheLeft> {
1085 template <
typename DstSegment,
typename Coeffs,
typename DiagonalType,
typename Alpha>
1086 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstSegment& dst,
const Coeffs& coeffs,
1087 const DiagonalType& diagonal, Index begin, Index ,
1088 const Alpha& alpha) {
1089 dst += alpha * diagonal.segment(begin, dst.size()).cwiseProduct(coeffs);
1091 template <
typename DstSegment,
typename Coeffs,
typename DiagonalType>
1092 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void runOverwrite(DstSegment& dst,
const Coeffs& coeffs,
1093 const DiagonalType& diagonal, Index begin,
1095 dst = diagonal.segment(begin, dst.size()).cwiseProduct(coeffs);
1100struct diagonal_product_segment_impl<
OnTheRight> {
1101 template <
typename DstSegment,
typename Coeffs,
typename DiagonalType,
typename Alpha>
1102 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstSegment& dst,
const Coeffs& coeffs,
1103 const DiagonalType& diagonal, Index , Index col,
1104 const Alpha& alpha) {
1105 dst += alpha * (coeffs * diagonal.coeff(col));
1107 template <
typename DstSegment,
typename Coeffs,
typename DiagonalType>
1108 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void runOverwrite(DstSegment& dst,
const Coeffs& coeffs,
1109 const DiagonalType& diagonal, Index ,
1111 dst = coeffs * diagonal.coeff(col);
1115template <
int Mode,
int ProductOrder,
typename MatrixType,
typename DiagonalType>
1116struct triangular_diagonal_product_impl {
1117 using MatrixScalar =
typename MatrixType::Scalar;
1119 template <
typename Dest,
typename Alpha>
1120 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Dest& dst,
const MatrixType& matrix,
1121 const DiagonalType& diagonal,
const Alpha& alpha) {
1122 eigen_assert(((ProductOrder ==
OnTheLeft && diagonal.size() == matrix.rows()) ||
1123 (ProductOrder ==
OnTheRight && diagonal.size() == matrix.cols())) &&
1124 "invalid matrix product");
1126 const Index rows = matrix.rows();
1127 const Index cols = matrix.cols();
1128 for (Index col = 0; col < cols; ++col) {
1129 EIGEN_IF_CONSTEXPR ((Mode &
Upper) ==
Upper) {
1130 const Index end = (std::min)(rows, ((Mode & (
UnitDiag |
ZeroDiag)) ? col : col + 1));
1131 addStoredSegment(dst, matrix, diagonal, 0, end, col, alpha);
1134 addStoredSegment(dst, matrix, diagonal, begin, rows - begin, col, alpha);
1138 if (col < rows) addUnitCoeff(dst, diagonal, col, alpha);
1144 template <
typename Dest,
typename Alpha>
1145 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void addStoredSegment(Dest& dst,
const MatrixType& matrix,
1146 const DiagonalType& diagonal, Index begin,
1147 Index size, Index col,
const Alpha& alpha) {
1148 if (size <= 0)
return;
1149 auto dstSegment = dst.col(col).segment(begin, size);
1150 diagonal_product_segment_impl<ProductOrder>::run(dstSegment, matrix.col(col).segment(begin, size), diagonal, begin,
1154 template <
typename Dest,
typename Alpha>
1155 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void addUnitCoeff(Dest& dst,
const DiagonalType& diagonal, Index index,
1156 const Alpha& alpha) {
1157 EIGEN_IF_CONSTEXPR (ProductOrder ==
OnTheLeft) {
1158 dst.coeffRef(index, index) += alpha * (diagonal.coeff(index) * MatrixScalar(1));
1160 dst.coeffRef(index, index) += alpha * (MatrixScalar(1) * diagonal.coeff(index));
1165template <
typename Lhs,
typename Rhs,
int ProductTag>
1166struct generic_product_impl<Lhs, Rhs, TriangularShape, DenseShape, ProductTag>
1167 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, TriangularShape, DenseShape, ProductTag>> {
1168 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1170 template <
typename Dest>
1171 static void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
1172 triangular_product_impl<Lhs::Mode, true, typename Lhs::MatrixType, false, Rhs, Rhs::ColsAtCompileTime == 1>::run(
1173 dst, lhs.nestedExpression(), rhs, alpha);
1177template <
typename Lhs,
typename Rhs,
int ProductTag>
1178struct generic_product_impl<Lhs, Rhs, DenseShape, TriangularShape, ProductTag>
1179 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, DenseShape, TriangularShape, ProductTag>> {
1180 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1182 template <
typename Dest>
1183 static void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
1184 triangular_product_impl<Rhs::Mode, false, Lhs, Lhs::RowsAtCompileTime == 1, typename Rhs::MatrixType, false>::run(
1185 dst, lhs, rhs.nestedExpression(), alpha);
1189template <
typename Lhs,
typename Rhs,
int ProductTag>
1190struct generic_product_impl<Lhs, Rhs, TriangularShape, DiagonalShape, ProductTag>
1191 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, TriangularShape, DiagonalShape, ProductTag>> {
1192 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1194 template <
typename Dest>
1195 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
1196 const Scalar& alpha) {
1197 triangular_diagonal_product_impl<Lhs::Mode,
OnTheRight,
typename Lhs::MatrixType,
1198 typename Rhs::DiagonalVectorType>::run(dst, lhs.nestedExpression(), rhs.diagonal(),
1203template <
typename Lhs,
typename Rhs,
int ProductTag>
1204struct generic_product_impl<Lhs, Rhs, DiagonalShape, TriangularShape, ProductTag>
1205 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, DiagonalShape, TriangularShape, ProductTag>> {
1206 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1208 template <
typename Dest>
1209 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
1210 const Scalar& alpha) {
1211 triangular_diagonal_product_impl<Rhs::Mode,
OnTheLeft,
typename Rhs::MatrixType,
1212 typename Lhs::DiagonalVectorType>::run(dst, rhs.nestedExpression(), lhs.diagonal(),
1220template <
typename Lhs,
int LhsMode,
bool LhsIsVector,
typename Rhs,
int RhsMode,
bool RhsIsVector>
1221struct selfadjoint_product_impl;
1223template <
int Mode,
int ProductOrder,
typename MatrixType,
typename DiagonalType>
1224struct selfadjoint_diagonal_product_impl {
1227 template <
typename Dest,
typename Alpha>
1228 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Dest& dst,
const MatrixType& matrix,
1229 const DiagonalType& diagonal,
const Alpha& alpha) {
1230 runImpl<true>(dst, matrix, diagonal, alpha);
1236 template <
typename Dest>
1237 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void runOverwrite(Dest& dst,
const MatrixType& matrix,
1238 const DiagonalType& diagonal) {
1239 using Scalar =
typename traits<MatrixType>::Scalar;
1240 runImpl<false>(dst, matrix, diagonal, Scalar(1));
1250 static constexpr Index BlockSize = 32;
1259 template <
bool Accumulate,
typename Dest,
typename Alpha>
1260 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void runImpl(Dest& dst,
const MatrixType& matrix,
1261 const DiagonalType& diagonal,
const Alpha& alpha) {
1262 eigen_assert(matrix.rows() == matrix.cols() &&
"SelfAdjointView is only for squared matrices");
1263 eigen_assert(diagonal.size() == matrix.rows() &&
"invalid matrix product");
1265 const Index size = matrix.rows();
1268 for (Index col = 0; col < size; ++col) {
1269 EIGEN_IF_CONSTEXPR ((Mode &
Upper) ==
Upper) {
1270 storedSegment<Accumulate>(dst, matrix, diagonal, 0, col + 1, col, alpha);
1272 storedSegment<Accumulate>(dst, matrix, diagonal, col, size - col, col, alpha);
1277 for (Index ib = 0; ib < size; ib += BlockSize) {
1278 const Index ib_end = numext::mini(size, ib + BlockSize);
1279 const Index br = ib_end - ib;
1280 EIGEN_IF_CONSTEXPR ((Mode &
Upper) ==
Upper) {
1282 for (Index jb = 0; jb < ib; jb += BlockSize) {
1283 const Index bc = numext::mini(jb + BlockSize, ib) - jb;
1284 mirrorBlock<Accumulate>(dst, matrix, diagonal, ib, jb, br, bc, alpha);
1287 for (Index col = ib; col < ib_end; ++col)
1288 conjugateSegment<Accumulate>(dst, matrix, diagonal, col + 1, ib_end - col - 1, col, alpha);
1291 for (Index jb = ib_end; jb < size; jb += BlockSize) {
1292 const Index bc = numext::mini(size, jb + BlockSize) - jb;
1293 mirrorBlock<Accumulate>(dst, matrix, diagonal, ib, jb, br, bc, alpha);
1296 for (Index col = ib; col < ib_end; ++col)
1297 conjugateSegment<Accumulate>(dst, matrix, diagonal, ib, col - ib, col, alpha);
1302 template <
bool Accumulate,
typename Dest,
typename Alpha>
1303 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void storedSegment(Dest& dst,
const MatrixType& matrix,
1304 const DiagonalType& diagonal, Index begin, Index size,
1305 Index col,
const Alpha& alpha) {
1306 if (size <= 0)
return;
1307 auto dstSegment = dst.col(col).segment(begin, size);
1308 auto srcSegment = matrix.col(col).segment(begin, size);
1309 EIGEN_IF_CONSTEXPR (Accumulate) {
1310 diagonal_product_segment_impl<ProductOrder>::run(dstSegment, srcSegment, diagonal, begin, col, alpha);
1312 diagonal_product_segment_impl<ProductOrder>::runOverwrite(dstSegment, srcSegment, diagonal, begin, col);
1316 template <
bool Accumulate,
typename Dest,
typename Alpha>
1317 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void conjugateSegment(Dest& dst,
const MatrixType& matrix,
1318 const DiagonalType& diagonal, Index begin,
1319 Index size, Index col,
const Alpha& alpha) {
1320 if (size <= 0)
return;
1321 auto dstSegment = dst.col(col).segment(begin, size);
1322 auto srcSegment = matrix.row(col).segment(begin, size).conjugate().transpose();
1323 EIGEN_IF_CONSTEXPR (Accumulate) {
1324 diagonal_product_segment_impl<ProductOrder>::run(dstSegment, srcSegment, diagonal, begin, col, alpha);
1326 diagonal_product_segment_impl<ProductOrder>::runOverwrite(dstSegment, srcSegment, diagonal, begin, col);
1333 template <
bool Accumulate,
typename Dest,
typename Alpha>
1334 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void mirrorBlock(Dest& dst,
const MatrixType& matrix,
1335 const DiagonalType& diagonal, Index ib, Index jb,
1336 Index br, Index bc,
const Alpha& alpha) {
1337 auto dstBlock = dst.block(ib, jb, br, bc);
1338 auto srcAdjoint = matrix.block(jb, ib, bc, br).adjoint();
1339 EIGEN_IF_CONSTEXPR (ProductOrder ==
OnTheRight) {
1340 auto scaled = srcAdjoint * diagonal.segment(jb, bc).asDiagonal();
1341 EIGEN_IF_CONSTEXPR (Accumulate) {
1342 dstBlock += alpha * scaled;
1347 auto scaled = diagonal.segment(ib, br).asDiagonal() * srcAdjoint;
1348 EIGEN_IF_CONSTEXPR (Accumulate) {
1349 dstBlock += alpha * scaled;
1357template <
typename Lhs,
typename Rhs,
int ProductTag>
1358struct generic_product_impl<Lhs, Rhs, SelfAdjointShape, DenseShape, ProductTag>
1359 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, SelfAdjointShape, DenseShape, ProductTag>> {
1360 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1362 template <
typename Dest>
1363 static EIGEN_DEVICE_FUNC
void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
1364 selfadjoint_product_impl<typename Lhs::MatrixType, Lhs::Mode, false, Rhs, 0, Rhs::ColsAtCompileTime == 1>::run(
1365 dst, lhs.nestedExpression(), rhs, alpha);
1369template <
typename Lhs,
typename Rhs,
int ProductTag>
1370struct generic_product_impl<Lhs, Rhs, DenseShape, SelfAdjointShape, ProductTag>
1371 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, DenseShape, SelfAdjointShape, ProductTag>> {
1372 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1374 template <
typename Dest>
1375 static void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
1376 selfadjoint_product_impl<Lhs, 0, Lhs::RowsAtCompileTime == 1, typename Rhs::MatrixType, Rhs::Mode, false>::run(
1377 dst, lhs, rhs.nestedExpression(), alpha);
1381template <
typename Lhs,
typename Rhs,
int ProductTag>
1382struct generic_product_impl<Lhs, Rhs, SelfAdjointShape, DiagonalShape, ProductTag>
1383 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, SelfAdjointShape, DiagonalShape, ProductTag>> {
1384 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1391 using LhsBlasTraits = blas_traits<typename Lhs::MatrixType>;
1393 static constexpr bool ConjLhs = LhsBlasTraits::NeedToConjugate;
1394 using ActualLhsMatrix =
1395 decltype(LhsBlasTraits::extract(std::declval<const typename Lhs::MatrixType&>()).template conjugateIf<ConjLhs>());
1396 using ActualLhsMatrixType = remove_all_t<ActualLhsMatrix>;
1398 selfadjoint_diagonal_product_impl<Lhs::Mode, OnTheRight, ActualLhsMatrixType, typename Rhs::DiagonalVectorType>;
1400 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ActualLhsMatrix actualLhsMatrix(
const typename Lhs::MatrixType& matrix) {
1401 return LhsBlasTraits::extract(matrix).template conjugateIf<ConjLhs>();
1404 template <
typename Dest>
1405 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
1406 EIGEN_IF_CONSTEXPR (LhsBlasTraits::HasScalarFactor) {
1408 Scalar factor = LhsBlasTraits::extractScalarFactor(lhs.nestedExpression());
1410 Kernel::run(dst, actualLhsMatrix(lhs.nestedExpression()), rhs.diagonal(), factor);
1413 Kernel::runOverwrite(dst, actualLhsMatrix(lhs.nestedExpression()), rhs.diagonal());
1417 template <
typename Dest>
1418 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
1419 const Scalar& alpha) {
1420 Scalar combinedAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs.nestedExpression());
1421 Kernel::run(dst, actualLhsMatrix(lhs.nestedExpression()), rhs.diagonal(), combinedAlpha);
1425template <
typename Lhs,
typename Rhs,
int ProductTag>
1426struct generic_product_impl<Lhs, Rhs, DiagonalShape, SelfAdjointShape, ProductTag>
1427 : generic_product_impl_base<Lhs, Rhs, generic_product_impl<Lhs, Rhs, DiagonalShape, SelfAdjointShape, ProductTag>> {
1428 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1431 using RhsBlasTraits = blas_traits<typename Rhs::MatrixType>;
1432 static constexpr bool ConjRhs = RhsBlasTraits::NeedToConjugate;
1433 using ActualRhsMatrix =
1434 decltype(RhsBlasTraits::extract(std::declval<const typename Rhs::MatrixType&>()).template conjugateIf<ConjRhs>());
1435 using ActualRhsMatrixType = remove_all_t<ActualRhsMatrix>;
1437 selfadjoint_diagonal_product_impl<Rhs::Mode, OnTheLeft, ActualRhsMatrixType, typename Lhs::DiagonalVectorType>;
1439 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ActualRhsMatrix actualRhsMatrix(
const typename Rhs::MatrixType& matrix) {
1440 return RhsBlasTraits::extract(matrix).template conjugateIf<ConjRhs>();
1443 template <
typename Dest>
1444 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
1445 EIGEN_IF_CONSTEXPR (RhsBlasTraits::HasScalarFactor) {
1446 Scalar factor = RhsBlasTraits::extractScalarFactor(rhs.nestedExpression());
1448 Kernel::run(dst, actualRhsMatrix(rhs.nestedExpression()), lhs.diagonal(), factor);
1450 Kernel::runOverwrite(dst, actualRhsMatrix(rhs.nestedExpression()), lhs.diagonal());
1454 template <
typename Dest>
1455 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
1456 const Scalar& alpha) {
1457 Scalar combinedAlpha = alpha * RhsBlasTraits::extractScalarFactor(rhs.nestedExpression());
1458 Kernel::run(dst, actualRhsMatrix(rhs.nestedExpression()), lhs.diagonal(), combinedAlpha);
1472template <typename View, typename Shape = typename evaluator_traits<View>::Shape>
1473struct densified_view_operand {
1474 using Scalar =
typename View::Scalar;
1475 template <
typename Dense>
1476 static Scalar run(Dense& dense,
const View& view) {
1482template <
typename View>
1483struct densified_view_operand<View, SelfAdjointShape> {
1484 using Scalar =
typename View::Scalar;
1485 using BlasTraits = blas_traits<typename View::MatrixType>;
1486 static constexpr unsigned int UpLo = unsigned(
int(View::Mode) &
int(
Upper |
Lower));
1487 template <
typename Dense>
1488 static Scalar run(Dense& dense,
const View& view) {
1489 dense = BlasTraits::extract(view.nestedExpression())
1490 .template conjugateIf<bool(BlasTraits::NeedToConjugate)>()
1491 .template selfadjointView<UpLo>();
1492 return BlasTraits::extractScalarFactor(view.nestedExpression());
1503template <
typename Lhs,
typename Rhs,
typename LhsShape,
typename RhsShape,
int ProductTag,
bool DensifyRhs>
1504struct structured_view_product_impl;
1506template <
typename Lhs,
typename Rhs,
typename LhsShape,
typename RhsShape,
int ProductTag>
1507struct structured_view_product_impl<Lhs, Rhs, LhsShape, RhsShape, ProductTag, true>
1508 : generic_product_impl_base<Lhs, Rhs,
1509 structured_view_product_impl<Lhs, Rhs, LhsShape, RhsShape, ProductTag, true>> {
1510 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1511 using RhsDenseType =
typename Rhs::DenseMatrixType;
1513 template <
typename Dest>
1514 static void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
1515 RhsDenseType rhsDense(rhs.rows(), rhs.cols());
1516 const Scalar factor = densified_view_operand<Rhs>::run(rhsDense, rhs);
1517 generic_product_impl<Lhs, RhsDenseType, LhsShape, DenseShape, ProductTag>::scaleAndAddTo(dst, lhs, rhsDense,
1522template <
typename Lhs,
typename Rhs,
typename LhsShape,
typename RhsShape,
int ProductTag>
1523struct structured_view_product_impl<Lhs, Rhs, LhsShape, RhsShape, ProductTag, false>
1524 : generic_product_impl_base<Lhs, Rhs,
1525 structured_view_product_impl<Lhs, Rhs, LhsShape, RhsShape, ProductTag, false>> {
1526 using Scalar =
typename Product<Lhs, Rhs>::Scalar;
1527 using LhsDenseType =
typename Lhs::DenseMatrixType;
1529 template <
typename Dest>
1530 static void scaleAndAddTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs,
const Scalar& alpha) {
1531 LhsDenseType lhsDense(lhs.rows(), lhs.cols());
1532 const Scalar factor = densified_view_operand<Lhs>::run(lhsDense, lhs);
1533 generic_product_impl<LhsDenseType, Rhs, DenseShape, RhsShape, ProductTag>::scaleAndAddTo(dst, lhsDense, rhs,
1538template <
typename Lhs,
typename Rhs,
int ProductTag>
1539struct generic_product_impl<Lhs, Rhs, TriangularShape, TriangularShape, ProductTag>
1540 : structured_view_product_impl<Lhs, Rhs, TriangularShape, TriangularShape, ProductTag, true> {};
1542template <
typename Lhs,
typename Rhs,
int ProductTag>
1543struct generic_product_impl<Lhs, Rhs, TriangularShape, SelfAdjointShape, ProductTag>
1544 : structured_view_product_impl<Lhs, Rhs, TriangularShape, SelfAdjointShape, ProductTag, true> {};
1546template <
typename Lhs,
typename Rhs,
int ProductTag>
1547struct generic_product_impl<Lhs, Rhs, SelfAdjointShape, TriangularShape, ProductTag>
1548 : structured_view_product_impl<Lhs, Rhs, SelfAdjointShape, TriangularShape, ProductTag, false> {};
1550template <
typename Lhs,
typename Rhs,
int ProductTag>
1551struct generic_product_impl<Lhs, Rhs, SelfAdjointShape, SelfAdjointShape, ProductTag>
1552 : structured_view_product_impl<Lhs, Rhs, SelfAdjointShape, SelfAdjointShape, ProductTag, true> {};
1558template <
typename MatrixType,
typename DiagonalType,
typename Derived,
int ProductOrder>
1559struct diagonal_product_evaluator_base : evaluator_base<Derived> {
1560 using Scalar =
typename ScalarBinaryOpTraits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType;
1564 CoeffReadCost = int(NumTraits<Scalar>::MulCost) + int(evaluator<MatrixType>::CoeffReadCost) +
1565 int(evaluator<DiagonalType>::CoeffReadCost),
1567 MatrixFlags = evaluator<MatrixType>::Flags,
1568 DiagFlags = evaluator<DiagonalType>::Flags,
1570 StorageOrder_ = (Derived::MaxRowsAtCompileTime == 1 && Derived::MaxColsAtCompileTime != 1) ?
RowMajor
1571 : (Derived::MaxColsAtCompileTime == 1 && Derived::MaxRowsAtCompileTime != 1) ?
ColMajor
1576 ScalarAccessOnDiag_ = !((int(StorageOrder_) ==
ColMajor && int(ProductOrder) ==
OnTheLeft) ||
1578 SameTypes_ = std::is_same<typename MatrixType::Scalar, typename DiagonalType::Scalar>::value,
1582 Vectorizable_ = bool(int(MatrixFlags) &
PacketAccessBit) && SameTypes_ &&
1586 (MatrixType::RowsAtCompileTime == 1 || MatrixType::ColsAtCompileTime == 1) ?
LinearAccessBit : 0,
1587 Flags = ((HereditaryBits | LinearAccessMask_) & static_cast<unsigned int>(MatrixFlags)) |
1589 Alignment = evaluator<MatrixType>::Alignment,
1592 (DiagonalType::SizeAtCompileTime == 1) ||
1593 (DiagonalType::SizeAtCompileTime == Dynamic && MatrixType::RowsAtCompileTime == 1 &&
1595 (DiagonalType::SizeAtCompileTime == Dynamic && MatrixType::ColsAtCompileTime == 1 && ProductOrder ==
OnTheRight)
1598 EIGEN_DEVICE_FUNC diagonal_product_evaluator_base(
const MatrixType& mat,
const DiagonalType& diag)
1599 : m_diagImpl(diag), m_matImpl(mat) {
1600 EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::MulCost);
1601 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
1604 EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
const Scalar coeff(Index idx)
const {
1605 EIGEN_IF_CONSTEXPR (AsScalarProduct)
1606 return m_diagImpl.coeff(0) * m_matImpl.coeff(idx);
1608 return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx);
1612 template <
int LoadMode,
typename PacketType>
1613 EIGEN_STRONG_INLINE PacketType packet_impl(Index row, Index col, Index
id, std::true_type)
const {
1614 return internal::pmul(m_matImpl.template packet<LoadMode, PacketType>(row, col),
1615 internal::pset1<PacketType>(m_diagImpl.coeff(
id)));
1618 template <
int LoadMode,
typename PacketType>
1619 EIGEN_STRONG_INLINE PacketType packet_impl(Index row, Index col, Index
id, std::false_type)
const {
1621 InnerSize = (MatrixType::Flags &
RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
1622 DiagonalPacketLoadMode = plain_enum_min(
1623 LoadMode, ((InnerSize * int(sizeof(Scalar))) % int(unpacket_traits<PacketType>::alignment) == 0)
1624 ? int(unpacket_traits<PacketType>::alignment)
1625 : int(evaluator<DiagonalType>::Alignment))
1627 return internal::pmul(m_matImpl.template packet<LoadMode, PacketType>(row, col),
1628 m_diagImpl.template packet<DiagonalPacketLoadMode, PacketType>(
id));
1631 template <
int LoadMode,
typename PacketType>
1632 EIGEN_STRONG_INLINE PacketType packet_segment_impl(Index row, Index col, Index
id, Index begin, Index count,
1633 std::true_type)
const {
1634 return internal::pmul(m_matImpl.template packetSegment<LoadMode, PacketType>(row, col, begin, count),
1635 internal::pset1<PacketType>(m_diagImpl.coeff(
id)));
1638 template <
int LoadMode,
typename PacketType>
1639 EIGEN_STRONG_INLINE PacketType packet_segment_impl(Index row, Index col, Index
id, Index begin, Index count,
1640 std::false_type)
const {
1642 InnerSize = (MatrixType::Flags &
RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
1643 DiagonalPacketLoadMode = plain_enum_min(
1644 LoadMode, ((InnerSize * int(sizeof(Scalar))) % int(unpacket_traits<PacketType>::alignment) == 0)
1645 ? int(unpacket_traits<PacketType>::alignment)
1646 : int(evaluator<DiagonalType>::Alignment))
1648 return internal::pmul(m_matImpl.template packetSegment<LoadMode, PacketType>(row, col, begin, count),
1649 m_diagImpl.template packetSegment<DiagonalPacketLoadMode, PacketType>(
id, begin, count));
1652 evaluator<DiagonalType> m_diagImpl;
1653 evaluator<MatrixType> m_matImpl;
1657template <
typename Lhs,
typename Rhs,
int ProductKind,
int ProductTag>
1658struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalShape, DenseShape>
1659 : diagonal_product_evaluator_base<Rhs, typename Lhs::DiagonalVectorType, Product<Lhs, Rhs, LazyProduct>,
1662 diagonal_product_evaluator_base<Rhs, typename Lhs::DiagonalVectorType, Product<Lhs, Rhs, LazyProduct>,
OnTheLeft>;
1664 using Base::m_diagImpl;
1665 using Base::m_matImpl;
1666 using Scalar =
typename Base::Scalar;
1668 using XprType = Product<Lhs, Rhs, ProductKind>;
1669 using PlainObject =
typename XprType::PlainObject;
1671 static constexpr int StorageOrder = Base::StorageOrder_;
1672 using IsRowMajor_t = bool_constant<StorageOrder == RowMajor>;
1674 EIGEN_DEVICE_FUNC
constexpr explicit product_evaluator(
const XprType& xpr) : Base(xpr.rhs(), xpr.lhs().diagonal()) {}
1676 EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
const Scalar coeff(Index row, Index col)
const {
1677 return m_diagImpl.coeff(row) * m_matImpl.coeff(row, col);
1681 template <
int LoadMode,
typename PacketType>
1682 EIGEN_STRONG_INLINE PacketType packet(Index row, Index col)
const {
1685 return this->
template packet_impl<LoadMode, PacketType>(row, col, row, IsRowMajor_t());
1688 template <
int LoadMode,
typename PacketType>
1689 EIGEN_STRONG_INLINE PacketType packet(Index idx)
const {
1690 return packet<LoadMode, PacketType>(
int(StorageOrder) == ColMajor ? idx : 0,
1691 int(StorageOrder) == ColMajor ? 0 : idx);
1694 template <
int LoadMode,
typename PacketType>
1695 EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count)
const {
1698 return this->
template packet_segment_impl<LoadMode, PacketType>(row, col, row, begin, count, IsRowMajor_t());
1701 template <
int LoadMode,
typename PacketType>
1702 EIGEN_STRONG_INLINE PacketType packetSegment(Index idx, Index begin, Index count)
const {
1703 return packetSegment<LoadMode, PacketType>(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx,
1710template <
typename Lhs,
typename Rhs,
int ProductKind,
int ProductTag>
1711struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DenseShape, DiagonalShape>
1712 : diagonal_product_evaluator_base<Lhs, typename Rhs::DiagonalVectorType, Product<Lhs, Rhs, LazyProduct>,
1714 using Base = diagonal_product_evaluator_base<Lhs, typename Rhs::DiagonalVectorType, Product<Lhs, Rhs, LazyProduct>,
1717 using Base::m_diagImpl;
1718 using Base::m_matImpl;
1719 using Scalar =
typename Base::Scalar;
1721 using XprType = Product<Lhs, Rhs, ProductKind>;
1722 using PlainObject =
typename XprType::PlainObject;
1724 static constexpr int StorageOrder = Base::StorageOrder_;
1725 using IsColMajor_t = bool_constant<StorageOrder == ColMajor>;
1727 EIGEN_DEVICE_FUNC
constexpr explicit product_evaluator(
const XprType& xpr) : Base(xpr.lhs(), xpr.rhs().diagonal()) {}
1729 EIGEN_DEVICE_FUNC
constexpr EIGEN_STRONG_INLINE
const Scalar coeff(Index row, Index col)
const {
1730 return m_matImpl.coeff(row, col) * m_diagImpl.coeff(col);
1734 template <
int LoadMode,
typename PacketType>
1735 EIGEN_STRONG_INLINE PacketType packet(Index row, Index col)
const {
1736 return this->
template packet_impl<LoadMode, PacketType>(row, col, col, IsColMajor_t());
1739 template <
int LoadMode,
typename PacketType>
1740 EIGEN_STRONG_INLINE PacketType packet(Index idx)
const {
1741 return packet<LoadMode, PacketType>(StorageOrder ==
ColMajor ? idx : 0, StorageOrder ==
ColMajor ? 0 : idx);
1744 template <
int LoadMode,
typename PacketType>
1745 EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count)
const {
1746 return this->
template packet_segment_impl<LoadMode, PacketType>(row, col, col, begin, count, IsColMajor_t());
1749 template <
int LoadMode,
typename PacketType>
1750 EIGEN_STRONG_INLINE PacketType packetSegment(Index idx, Index begin, Index count)
const {
1751 return packetSegment<LoadMode, PacketType>(StorageOrder ==
ColMajor ? idx : 0, StorageOrder ==
ColMajor ? 0 : idx,
1768template <
int Mode,
int ProductOrder,
typename MatrixType,
typename DiagonalType,
typename Derived>
1769struct triangular_diagonal_product_lazy_evaluator_base : evaluator_base<Derived> {
1770 using Scalar =
typename ScalarBinaryOpTraits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType;
1771 using MatrixScalar =
typename MatrixType::Scalar;
1774 CoeffReadCost = int(NumTraits<Scalar>::MulCost) + int(evaluator<MatrixType>::CoeffReadCost) +
1775 int(evaluator<DiagonalType>::CoeffReadCost),
1776 Flags = HereditaryBits &
static_cast<unsigned int>(evaluator<MatrixType>::Flags),
1780 EIGEN_DEVICE_FUNC triangular_diagonal_product_lazy_evaluator_base(
const MatrixType& mat,
const DiagonalType& diag)
1781 : m_diagImpl(diag), m_matImpl(mat) {}
1783 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col)
const {
1784 const bool inActive = ((Mode &
Upper) ==
Upper) ? (row <= col) : (row >= col);
1785 if (!inActive)
return Scalar(0);
1788 return ProductOrder ==
OnTheLeft ? Scalar(m_diagImpl.coeff(row) * MatrixScalar(1))
1789 : Scalar(MatrixScalar(1) * m_diagImpl.coeff(col));
1793 return ProductOrder ==
OnTheLeft ? Scalar(m_diagImpl.coeff(row) * m_matImpl.coeff(row, col))
1794 : Scalar(m_matImpl.coeff(row, col) * m_diagImpl.coeff(col));
1798 evaluator<DiagonalType> m_diagImpl;
1799 evaluator<MatrixType> m_matImpl;
1803template <
typename Lhs,
typename Rhs,
int ProductKind,
int ProductTag>
1804struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, TriangularShape, DiagonalShape>
1805 : triangular_diagonal_product_lazy_evaluator_base<
1806 Lhs::Mode, OnTheRight, typename Lhs::MatrixType, typename Rhs::DiagonalVectorType,
1807 product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, TriangularShape, DiagonalShape>> {
1808 using XprType = Product<Lhs, Rhs, ProductKind>;
1809 using Base = triangular_diagonal_product_lazy_evaluator_base<
1810 Lhs::Mode,
OnTheRight,
typename Lhs::MatrixType,
typename Rhs::DiagonalVectorType,
1811 product_evaluator<XprType, ProductTag, TriangularShape, DiagonalShape>>;
1813 EIGEN_DEVICE_FUNC
explicit product_evaluator(
const XprType& xpr)
1814 : Base(xpr.lhs().nestedExpression(), xpr.rhs().diagonal()) {}
1818template <
typename Lhs,
typename Rhs,
int ProductKind,
int ProductTag>
1819struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalShape, TriangularShape>
1820 : triangular_diagonal_product_lazy_evaluator_base<
1821 Rhs::Mode, OnTheLeft, typename Rhs::MatrixType, typename Lhs::DiagonalVectorType,
1822 product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalShape, TriangularShape>> {
1823 using XprType = Product<Lhs, Rhs, ProductKind>;
1824 using Base = triangular_diagonal_product_lazy_evaluator_base<
1825 Rhs::Mode,
OnTheLeft,
typename Rhs::MatrixType,
typename Lhs::DiagonalVectorType,
1826 product_evaluator<XprType, ProductTag, DiagonalShape, TriangularShape>>;
1828 EIGEN_DEVICE_FUNC
explicit product_evaluator(
const XprType& xpr)
1829 : Base(xpr.rhs().nestedExpression(), xpr.lhs().diagonal()) {}
1834template <
int Mode,
int ProductOrder,
typename MatrixType,
typename DiagonalType,
typename ProductXpr,
1836 NumTraits<typename MatrixType::Scalar>::IsComplex && blas_traits<MatrixType>::HasScalarFactor>
1837struct selfadjoint_diagonal_product_lazy_evaluator_base : evaluator_base<ProductXpr> {
1838 using Scalar =
typename ScalarBinaryOpTraits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType;
1841 CoeffReadCost = int(NumTraits<Scalar>::MulCost) + int(evaluator<MatrixType>::CoeffReadCost) +
1842 int(evaluator<DiagonalType>::CoeffReadCost),
1843 Flags = HereditaryBits &
static_cast<unsigned int>(evaluator<MatrixType>::Flags),
1847 EIGEN_DEVICE_FUNC selfadjoint_diagonal_product_lazy_evaluator_base(
const ProductXpr&,
const MatrixType& mat,
1848 const DiagonalType& diag)
1849 : m_diagImpl(diag), m_matImpl(mat) {}
1851 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col)
const {
1852 const bool storedHere = ((Mode &
Upper) ==
Upper) ? (row <= col) : (row >= col);
1853 const Scalar matCoeff =
1854 storedHere ? Scalar(m_matImpl.coeff(row, col)) : Scalar(numext::conj(m_matImpl.coeff(col, row)));
1855 return ProductOrder ==
OnTheLeft ? Scalar(m_diagImpl.coeff(row) * matCoeff)
1856 : Scalar(matCoeff * m_diagImpl.coeff(col));
1860 evaluator<DiagonalType> m_diagImpl;
1861 evaluator<MatrixType> m_matImpl;
1866template <
int Mode,
int ProductOrder,
typename MatrixType,
typename DiagonalType,
typename ProductXpr>
1867struct selfadjoint_diagonal_product_lazy_evaluator_base<Mode, ProductOrder, MatrixType, DiagonalType, ProductXpr, true>
1868 : evaluator<EvalToTemp<Product<typename ProductXpr::Lhs, typename ProductXpr::Rhs, DefaultProduct>>> {
1869 using DefaultProductType = Product<typename ProductXpr::Lhs, typename ProductXpr::Rhs, DefaultProduct>;
1870 using Base = evaluator<EvalToTemp<DefaultProductType>>;
1871 EIGEN_DEVICE_FUNC selfadjoint_diagonal_product_lazy_evaluator_base(
const ProductXpr& xpr,
const MatrixType&,
1872 const DiagonalType&)
1873 : Base(DefaultProductType(xpr.lhs(), xpr.rhs())) {}
1877template <
typename Lhs,
typename Rhs,
int ProductKind,
int ProductTag>
1878struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, SelfAdjointShape, DiagonalShape>
1879 : selfadjoint_diagonal_product_lazy_evaluator_base<Lhs::Mode, OnTheRight, typename Lhs::MatrixType,
1880 typename Rhs::DiagonalVectorType,
1881 Product<Lhs, Rhs, ProductKind>> {
1882 using XprType = Product<Lhs, Rhs, ProductKind>;
1883 using Base = selfadjoint_diagonal_product_lazy_evaluator_base<Lhs::Mode,
OnTheRight,
typename Lhs::MatrixType,
1884 typename Rhs::DiagonalVectorType, XprType>;
1886 EIGEN_DEVICE_FUNC
explicit product_evaluator(
const XprType& xpr)
1887 : Base(xpr, xpr.lhs().nestedExpression(), xpr.rhs().diagonal()) {}
1891template <
typename Lhs,
typename Rhs,
int ProductKind,
int ProductTag>
1892struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalShape, SelfAdjointShape>
1893 : selfadjoint_diagonal_product_lazy_evaluator_base<Rhs::Mode, OnTheLeft, typename Rhs::MatrixType,
1894 typename Lhs::DiagonalVectorType,
1895 Product<Lhs, Rhs, ProductKind>> {
1896 using XprType = Product<Lhs, Rhs, ProductKind>;
1897 using Base = selfadjoint_diagonal_product_lazy_evaluator_base<Rhs::Mode,
OnTheLeft,
typename Rhs::MatrixType,
1898 typename Lhs::DiagonalVectorType, XprType>;
1900 EIGEN_DEVICE_FUNC
explicit product_evaluator(
const XprType& xpr)
1901 : Base(xpr, xpr.rhs().nestedExpression(), xpr.lhs().diagonal()) {}
1916template <
typename ExpressionType,
int S
ide,
bool Transposed,
typename ExpressionShape>
1917struct permutation_matrix_product {
1918 template <
typename Dest,
typename PermutationType>
1919 static EIGEN_DEVICE_FUNC
void run(Dest&,
const PermutationType&,
const ExpressionType&) {
1920 static_assert(std::is_same<ExpressionShape, DenseShape>::value,
1921 "PERMUTATION_PRODUCTS_ARE_NOT_IMPLEMENTED_FOR_THIS_OPERAND_SHAPE");
1925template <
typename ExpressionType,
int S
ide,
bool Transposed>
1926struct permutation_matrix_product<ExpressionType, Side, Transposed, DenseShape> {
1927 using MatrixType =
typename nested_eval<ExpressionType, 1>::type;
1928 using MatrixTypeCleaned = remove_all_t<MatrixType>;
1930 template <
typename Dest,
typename PermutationType>
1931 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Dest& dst,
const PermutationType& perm,
1932 const ExpressionType& xpr) {
1933 MatrixType mat(xpr);
1934 const Index n = Side ==
OnTheLeft ? mat.rows() : mat.cols();
1938 if (is_same_dense(dst, mat)) {
1940 Matrix<bool, PermutationType::RowsAtCompileTime, 1, 0, PermutationType::MaxRowsAtCompileTime> mask(perm.size());
1943 while (r < perm.size()) {
1945 while (r < perm.size() && mask[r]) r++;
1946 if (r >= perm.size())
break;
1950 mask.coeffRef(k0) =
true;
1951 for (Index k = perm.indices().coeff(k0); k != k0; k = perm.indices().coeff(k)) {
1952 Block<Dest, Side ==
OnTheLeft ? 1 : Dest::RowsAtCompileTime,
1953 Side ==
OnTheRight ? 1 : Dest::ColsAtCompileTime>(dst, k)
1954 .swap(Block < Dest, Side == OnTheLeft ? 1 : Dest::RowsAtCompileTime,
1957 : Dest::ColsAtCompileTime > (dst, ((Side == OnTheLeft) ^ Transposed) ? k0 : kPrev));
1959 mask.coeffRef(k) =
true;
1964 for (Index i = 0; i < n; ++i) {
1965 Block<Dest, Side == OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side == OnTheRight ? 1 : Dest::ColsAtCompileTime>(
1966 dst, ((Side == OnTheLeft) ^ Transposed) ? perm.indices().coeff(i) : i)
1970 Block <
const MatrixTypeCleaned,
1971 Side ==
OnTheLeft ? 1 : MatrixTypeCleaned::RowsAtCompileTime,
1973 : MatrixTypeCleaned::ColsAtCompileTime >
1974 (mat, ((Side ==
OnTheRight) ^ Transposed) ? perm.indices().coeff(i) : i);
1985template <
typename ExpressionType,
int S
ide,
bool Transposed>
1986struct permutation_densified_matrix_product {
1987 using DenseType =
typename ExpressionType::DenseMatrixType;
1989 template <
typename Dest,
typename PermutationType>
1990 static EIGEN_DEVICE_FUNC
void run(Dest& dst,
const PermutationType& perm,
const ExpressionType& xpr) {
1991 const DenseType dense(xpr);
1992 permutation_matrix_product<DenseType, Side, Transposed, DenseShape>::run(dst, perm, dense);
1996template <
typename ExpressionType,
int S
ide,
bool Transposed>
1997struct permutation_matrix_product<ExpressionType, Side, Transposed, TriangularShape>
1998 : permutation_densified_matrix_product<ExpressionType, Side, Transposed> {};
2000template <
typename ExpressionType,
int S
ide,
bool Transposed>
2001struct permutation_matrix_product<ExpressionType, Side, Transposed, SelfAdjointShape>
2002 : permutation_densified_matrix_product<ExpressionType, Side, Transposed> {};
2004template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2005struct generic_product_impl<Lhs, Rhs, PermutationShape, MatrixShape, ProductTag> {
2006 template <
typename Dest>
2007 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
2008 permutation_matrix_product<Rhs, OnTheLeft, false, MatrixShape>::run(dst, lhs, rhs);
2012template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2013struct generic_product_impl<Lhs, Rhs, MatrixShape, PermutationShape, ProductTag> {
2014 template <
typename Dest>
2015 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
2016 permutation_matrix_product<Lhs, OnTheRight, false, MatrixShape>::run(dst, rhs, lhs);
2020template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2021struct generic_product_impl<Inverse<Lhs>, Rhs, PermutationShape, MatrixShape, ProductTag> {
2022 template <
typename Dest>
2023 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Inverse<Lhs>& lhs,
const Rhs& rhs) {
2024 permutation_matrix_product<Rhs, OnTheLeft, true, MatrixShape>::run(dst, lhs.nestedExpression(), rhs);
2028template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2029struct generic_product_impl<Lhs, Inverse<Rhs>, MatrixShape, PermutationShape, ProductTag> {
2030 template <
typename Dest>
2031 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Inverse<Rhs>& rhs) {
2032 permutation_matrix_product<Lhs, OnTheRight, true, MatrixShape>::run(dst, rhs.nestedExpression(), lhs);
2046template <
typename ExpressionType,
int S
ide,
bool Transposed,
typename ExpressionShape>
2047struct transposition_matrix_product {
2048 using MatrixType =
typename nested_eval<ExpressionType, 1>::type;
2049 using MatrixTypeCleaned = remove_all_t<MatrixType>;
2051 template <
typename Dest,
typename TranspositionType>
2052 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(Dest& dst,
const TranspositionType& tr,
2053 const ExpressionType& xpr) {
2055 static_assert(std::is_same<ExpressionShape, DenseShape>::value,
2056 "TRANSPOSITIONS_PRODUCTS_ARE_ONLY_IMPLEMENTED_FOR_DENSE_OPERANDS");
2057 MatrixType mat(xpr);
2058 using StorageIndex =
typename TranspositionType::StorageIndex;
2059 const Index size = tr.size();
2062 if (!is_same_dense(dst, mat)) dst = mat;
2064 for (Index k = (Transposed ? size - 1 : 0); Transposed ? k >= 0 : k < size; Transposed ? --k : ++k)
2065 if (Index(j = tr.coeff(k)) != k) {
2066 EIGEN_IF_CONSTEXPR (Side == OnTheLeft) {
2067 dst.row(k).swap(dst.row(j));
2068 }
else EIGEN_IF_CONSTEXPR (Side == OnTheRight) {
2069 dst.col(k).swap(dst.col(j));
2075template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2076struct generic_product_impl<Lhs, Rhs, TranspositionsShape, MatrixShape, ProductTag> {
2077 template <
typename Dest>
2078 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
2079 transposition_matrix_product<Rhs, OnTheLeft, false, MatrixShape>::run(dst, lhs, rhs);
2083template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2084struct generic_product_impl<Lhs, Rhs, MatrixShape, TranspositionsShape, ProductTag> {
2085 template <
typename Dest>
2086 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
2087 transposition_matrix_product<Lhs, OnTheRight, false, MatrixShape>::run(dst, rhs, lhs);
2091template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2092struct generic_product_impl<Transpose<Lhs>, Rhs, TranspositionsShape, MatrixShape, ProductTag> {
2093 template <
typename Dest>
2094 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Transpose<Lhs>& lhs,
const Rhs& rhs) {
2095 transposition_matrix_product<Rhs, OnTheLeft, true, MatrixShape>::run(dst, lhs.nestedExpression(), rhs);
2099template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2100struct generic_product_impl<Lhs, Transpose<Rhs>, MatrixShape, TranspositionsShape, ProductTag> {
2101 template <
typename Dest>
2102 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Transpose<Rhs>& rhs) {
2103 transposition_matrix_product<Lhs, OnTheRight, true, MatrixShape>::run(dst, rhs.nestedExpression(), lhs);
2113template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2114struct generic_product_impl<Lhs, Rhs, SkewSymmetricShape, MatrixShape, ProductTag> {
2115 template <
typename Dest>
2116 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
2117 call_assignment_no_alias(dst,
typename Lhs::DenseMatrixType(lhs) * rhs);
2121template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2122struct generic_product_impl<Lhs, Rhs, MatrixShape, SkewSymmetricShape, ProductTag> {
2123 template <
typename Dest>
2124 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
2125 call_assignment_no_alias(dst, lhs *
typename Rhs::DenseMatrixType(rhs));
2129template <
typename Lhs,
typename Rhs,
int ProductTag>
2130struct generic_product_impl<Lhs, Rhs, SkewSymmetricShape, SkewSymmetricShape, ProductTag> {
2131 template <
typename Dest>
2132 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void evalTo(Dest& dst,
const Lhs& lhs,
const Rhs& rhs) {
2133 generic_product_impl<
typename Lhs::DenseMatrixType,
typename Rhs::DenseMatrixType, DenseShape, DenseShape,
2134 ProductTag>::evalTo(dst, lhs, rhs);
2138template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2139struct generic_product_impl<Lhs, Rhs, MatrixShape, HomogeneousShape, ProductTag>
2140 : generic_product_impl<Lhs, typename Rhs::PlainObject, MatrixShape, DenseShape, ProductTag> {};
2142template <
typename Lhs,
typename Rhs,
int ProductTag,
typename MatrixShape>
2143struct generic_product_impl<Lhs, Rhs, HomogeneousShape, MatrixShape, ProductTag>
2144 : generic_product_impl<typename Lhs::PlainObject, Rhs, DenseShape, MatrixShape, ProductTag> {};
2146template <
typename Lhs,
typename Rhs,
int ProductTag>
2147struct generic_product_impl<Lhs, Rhs, PermutationShape, HomogeneousShape, ProductTag>
2148 : generic_product_impl<Lhs, Rhs, PermutationShape, DenseShape, ProductTag> {};
2150template <
typename Lhs,
typename Rhs,
int ProductTag>
2151struct generic_product_impl<Lhs, Rhs, HomogeneousShape, PermutationShape, ProductTag>
2152 : generic_product_impl<Lhs, Rhs, DenseShape, PermutationShape, ProductTag> {};
@ UnitDiag
Definition Constants.h:216
@ ZeroDiag
Definition Constants.h:218
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ ColMajor
Definition Constants.h:319
@ RowMajor
Definition Constants.h:321
@ OnTheLeft
Definition Constants.h:332
@ OnTheRight
Definition Constants.h:334
constexpr unsigned int ActualPacketAccessBit
Definition Constants.h:109
constexpr unsigned int PacketAccessBit
Definition Constants.h:98
constexpr unsigned int DirectAccessBit
Definition Constants.h:160
constexpr unsigned int EvalBeforeNestingBit
Definition Constants.h:75
constexpr unsigned int LinearAccessBit
Definition Constants.h:134
constexpr unsigned int RowMajorBit
Definition Constants.h:71
adds(const Scalar &s)
Definition ProductEvaluators.h:389
void operator()(const Dst &dst, const Src &src) const
Definition ProductEvaluators.h:392