269 return internal::make_triangular_base_cwise_view<Mode>(lhs.derived() + rhs.nestedExpression());
274 template <
typename OtherDerived,
unsigned int Mode_ = Mode,
275 std::enable_if_t<(int(Mode_) & (int(
UnitDiag) | int(
ZeroDiag))) == 0,
int> = 0>
277 return internal::make_triangular_base_cwise_view<Mode>(lhs.derived() - rhs.nestedExpression());
280 template <
typename OtherDerived>
282 const Derived& rhs) {
286 template <
typename OtherDerived>
287 friend EIGEN_DEVICE_FUNC
const Product<OtherDerived, Derived> operator*(
const DiagonalBase<OtherDerived>& lhs,
288 const Derived& rhs) {
289 return Product<OtherDerived, Derived>(lhs.derived(), rhs);
297 template <
typename OtherDerived>
303 template <
typename OtherDerived>
305 const InverseImpl<OtherDerived, PermutationStorage>& rhs)
const {
310 template <
typename OtherDerived>
312 const Derived& rhs) {
317 template <
typename OtherDerived>
319 const InverseImpl<OtherDerived, PermutationStorage>& lhs,
const Derived& rhs) {
324 EIGEN_DEVICE_FUNC
inline const ConjugateReturnType
conjugate()
const {
332 EIGEN_DEVICE_FUNC
inline std::conditional_t<Cond, ConjugateReturnType, ConstView>
conjugateIf()
const {
333 using ReturnType = std::conditional_t<Cond, ConjugateReturnType, ConstView>;
338 EIGEN_DEVICE_FUNC
inline const AdjointReturnType
adjoint()
const {
343 template <class Dummy = int, std::enable_if_t<Eigen::internal::is_lvalue<ExpressionType>::value, Dummy*> =
nullptr>
344 EIGEN_DEVICE_FUNC
inline TransposeReturnType
transpose() {
345 typename ExpressionType::TransposeReturnType tmp(
derived().nestedExpression());
346 return TransposeReturnType(tmp);
349 template <
class Dummy =
int>
350 EIGEN_DEPRECATED_WITH_REASON(
"Omit the implementation-only argument.")
351 EIGEN_DEVICE_FUNC inline TransposeReturnType
352 transpose(std::enable_if_t<Eigen::internal::is_lvalue<ExpressionType>::value, Dummy*>) {
357 EIGEN_DEVICE_FUNC
inline const ConstTransposeReturnType
transpose()
const {
361 EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix()
const {
362 DenseMatrixType res(rows(), cols());
368 void check_coordinates(Index row, Index col)
const {
369 EIGEN_ONLY_USED_FOR_DEBUG(row);
370 EIGEN_ONLY_USED_FOR_DEBUG(col);
371 eigen_assert(col >= 0 && col < cols() && row >= 0 && row < rows());
372 const int mode = int(Mode) & ~SelfAdjoint;
373 EIGEN_ONLY_USED_FOR_DEBUG(mode);
374 eigen_assert((mode ==
Upper && col >= row) || (mode ==
Lower && col <= row) ||
379#ifdef EIGEN_INTERNAL_DEBUGGING
380 void check_coordinates_internal(
Index row,
Index col)
const { check_coordinates(row, col); }
382 void check_coordinates_internal(
Index,
Index)
const {}
405template <
typename MatrixType,
unsigned int Mode_>
406struct traits<TriangularView<MatrixType, Mode_>> : traits<MatrixType> {
407 using MatrixTypeNested =
typename ref_selector<MatrixType>::non_const_type;
408 using MatrixTypeNestedNonRef = std::remove_reference_t<MatrixTypeNested>;
409 using MatrixTypeNestedCleaned = remove_all_t<MatrixTypeNested>;
410 using FullMatrixType =
typename MatrixType::PlainObject;
411 using ExpressionType = MatrixType;
414 FlagsLvalueBit = is_lvalue<MatrixType>::value ?
LvalueBit : 0,
415 Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits | FlagsLvalueBit) &
421template <
typename MatrixType_,
unsigned int Mode_,
typename StorageKind>
422class TriangularViewImpl;
424template <
typename MatrixType_,
unsigned int Mode_>
426 :
public TriangularViewImpl<MatrixType_, Mode_, typename internal::traits<MatrixType_>::StorageKind> {
428 using Base = TriangularViewImpl<MatrixType_, Mode_, typename internal::traits<MatrixType_>::StorageKind>;
429 using Scalar =
typename internal::traits<TriangularView>::Scalar;
430 using MatrixType = MatrixType_;
433 using MatrixTypeNested =
typename internal::traits<TriangularView>::MatrixTypeNested;
434 using MatrixTypeNestedNonRef =
typename internal::traits<TriangularView>::MatrixTypeNestedNonRef;
437 using StorageKind =
typename internal::traits<TriangularView>::StorageKind;
438 using NestedExpression =
typename internal::traits<TriangularView>::MatrixTypeNestedCleaned;
442 Flags = internal::traits<TriangularView>::Flags,
445 IsVectorAtCompileTime =
false
448 EIGEN_DEVICE_FUNC
explicit inline TriangularView(MatrixType& matrix) : m_matrix(matrix) {}
450 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TriangularView)
453 EIGEN_DEVICE_FUNC constexpr const NestedExpression&
nestedExpression() const noexcept {
return m_matrix; }
456 EIGEN_DEVICE_FUNC
constexpr NestedExpression&
nestedExpression() noexcept {
return m_matrix; }
458 template <
typename Other>
470 EIGEN_STATIC_ASSERT((Mode & (
UnitDiag |
ZeroDiag)) == 0, PROGRAMMING_ERROR);
476 EIGEN_STATIC_ASSERT((Mode & (
UnitDiag |
ZeroDiag)) == 0, PROGRAMMING_ERROR);
483 EIGEN_IF_CONSTEXPR (Mode &
UnitDiag) {
485 }
else EIGEN_IF_CONSTEXPR (Mode &
ZeroDiag) {
488 return m_matrix.diagonal().prod();
493 MatrixTypeNested m_matrix;
505template <
typename MatrixType_,
unsigned int Mode_>
506class TriangularViewImpl<MatrixType_, Mode_,
Dense> :
public TriangularBase<TriangularView<MatrixType_, Mode_>> {
510 using Base = TriangularBase<TriangularViewType>;
511 using Scalar =
typename internal::traits<TriangularViewType>::Scalar;
513 using MatrixType = MatrixType_;
514 using DenseMatrixType =
typename MatrixType::PlainObject;
515 using PlainObject = DenseMatrixType;
520 using Base::operator*;
522 using StorageKind =
typename internal::traits<TriangularViewType>::StorageKind;
524 enum { Mode = Mode_, Flags = internal::traits<TriangularViewType>::Flags };
527 template <
typename Other>
529 internal::call_assignment_no_alias(
derived(), other.derived(),
530 internal::add_assign_op<Scalar, typename Other::Scalar>());
534 template <
typename Other>
536 internal::call_assignment_no_alias(
derived(), other.derived(),
537 internal::sub_assign_op<Scalar, typename Other::Scalar>());
542 EIGEN_DEVICE_FUNC TriangularViewType&
operator*=(
const typename internal::traits<MatrixType>::Scalar& other) {
543 return *
this =
derived().nestedExpression() * other;
546 EIGEN_DEVICE_FUNC TriangularViewType&
operator/=(
const typename internal::traits<MatrixType>::Scalar& other) {
547 return *
this =
derived().nestedExpression() / other;
551 template <
typename OtherDerived>
552 EIGEN_DEVICE_FUNC TriangularViewType&
operator=(
const TriangularBase<OtherDerived>& other);
555 template <
typename OtherDerived>
558#ifndef EIGEN_PARSED_BY_DOXYGEN
559 EIGEN_DEVICE_FUNC TriangularViewType&
operator=(
const TriangularViewImpl& other) {
560 return *
this = other.derived().nestedExpression();
563 template <
typename OtherDerived>
567 template <
typename OtherDerived>
573 template <
unsigned int M = Mode, std::enable_if_t<(M & UnitDiag) == 0,
int> = 0>
575 const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(MatrixType, Scalar, internal::scalar_product_op), Mode>
576 operator*(
const Scalar& s)
const {
577 return (derived().nestedExpression() * s).template triangularView<Mode>();
580 template <
unsigned int M = Mode, std::enable_if_t<(M & UnitDiag) == 0,
int> = 0>
581 friend EIGEN_DEVICE_FUNC
const TriangularView<
582 const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar, MatrixType, internal::scalar_product_op), Mode>
583 operator*(
const Scalar& s,
const TriangularViewImpl& mat) {
584 return (s * mat.derived().nestedExpression()).template triangularView<Mode>();
610 template <
int S
ide,
typename Other>
611 inline const internal::triangular_solve_retval<Side, TriangularViewType, Other>
solve(
623 template <
int S
ide,
typename OtherDerived>
626 template <
typename OtherDerived>
646 template <
typename OtherDerived>
648#ifdef EIGEN_PARSED_BY_DOXYGEN
650 swap(TriangularBase<OtherDerived>& other)
653 swap(TriangularBase<OtherDerived>
const& other)
656 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
657 call_assignment(
derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
661 template <
typename OtherDerived>
664 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
665 call_assignment(
derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
668 template <
typename RhsType,
typename DstType>
669 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void _solve_impl(
const RhsType& rhs, DstType& dst)
const {
670 if (!internal::is_same_dense(dst, rhs)) dst = rhs;
671 this->solveInPlace(dst);
674 template <
typename ProductType>
675 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(
const ProductType& prod,
const Scalar& alpha,
679 EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl)
680 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl)
687#ifndef EIGEN_PARSED_BY_DOXYGEN
689template <
typename MatrixType,
unsigned int Mode>
690template <
typename OtherDerived>
693 internal::call_assignment_no_alias(derived(), other.derived(),
694 internal::assign_op<Scalar, typename OtherDerived::Scalar>());
699template <
typename MatrixType,
unsigned int Mode>
700template <
typename OtherDerived>
701EIGEN_DEVICE_FUNC
void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(
const MatrixBase<OtherDerived>& other) {
702 internal::call_assignment_no_alias(derived(), other.template triangularView<Mode>());
705template <
typename MatrixType,
unsigned int Mode>
706template <
typename OtherDerived>
709 eigen_assert(Mode ==
int(OtherDerived::Mode));
710 internal::call_assignment(derived(), other.derived());
714template <
typename MatrixType,
unsigned int Mode>
715template <
typename OtherDerived>
716EIGEN_DEVICE_FUNC
void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(
718 eigen_assert(Mode ==
int(OtherDerived::Mode));
719 internal::call_assignment_no_alias(derived(), other.derived());
729template <
typename Derived>
730template <
typename DenseDerived>
754template <
typename Derived>
755template <
unsigned int Mode>
757MatrixBase<Derived>::triangularView() {
758 return typename TriangularViewReturnType<Mode>::Type(derived());
762template <
typename Derived>
763template <
unsigned int Mode>
765MatrixBase<Derived>::triangularView()
const {
766 return typename ConstTriangularViewReturnType<Mode>::Type(derived());
774template <
typename Derived>
776 RealScalar maxAbsOnUpperPart =
static_cast<RealScalar
>(-1);
777 for (Index j = 0; j < cols(); ++j) {
778 Index maxi = numext::mini(j, rows() - 1);
779 for (Index i = 0; i <= maxi; ++i) {
780 RealScalar absValue = numext::abs(coeff(i, j));
781 if (absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
784 RealScalar threshold = maxAbsOnUpperPart * prec;
785 for (Index j = 0; j < cols(); ++j)
786 for (Index i = j + 1; i < rows(); ++i)
787 if (numext::abs(coeff(i, j)) > threshold)
return false;
796template <
typename Derived>
798 RealScalar maxAbsOnLowerPart =
static_cast<RealScalar
>(-1);
799 for (Index j = 0; j < cols(); ++j)
800 for (Index i = j; i < rows(); ++i) {
801 RealScalar absValue = numext::abs(coeff(i, j));
802 if (absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
804 RealScalar threshold = maxAbsOnLowerPart * prec;
805 for (Index j = 1; j < cols(); ++j) {
808 Index maxi = numext::mini(j, rows());
809 for (Index i = 0; i < maxi; ++i)
810 if (numext::abs(coeff(i, j)) > threshold)
return false;
827template <
typename MatrixType,
unsigned int Mode>
829 using Kind =
typename storage_kind_to_evaluator_kind<typename MatrixType::StorageKind>::Kind;
830 using Shape =
typename glue_shapes<typename evaluator_traits<MatrixType>::Shape, TriangularShape>::type;
833template <
typename MatrixType,
unsigned int Mode>
834struct unary_evaluator<TriangularView<MatrixType, Mode>, IndexBased> : evaluator<internal::remove_all_t<MatrixType>> {
835 using XprType = TriangularView<MatrixType, Mode>;
836 using Base = evaluator<internal::remove_all_t<MatrixType>>;
837 EIGEN_DEVICE_FUNC unary_evaluator(
const XprType& xpr) : Base(xpr.nestedExpression()) {}
841struct Triangular2Triangular {};
842struct Triangular2Dense {};
843struct Dense2Triangular {};
845template <
typename Kernel,
unsigned int Mode,
int UnrollCount,
bool SetOpposite>
846struct triangular_assignment_loop;
853template <
int UpLo,
int Mode,
int SetOpposite,
typename DstEvaluatorTypeT,
typename SrcEvaluatorTypeT,
typename Functor,
854 int Version = Specialized>
855class triangular_dense_assignment_kernel
856 :
public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> {
858 using Base = generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version>;
859 using DstXprType =
typename Base::DstXprType;
860 using SrcXprType =
typename Base::SrcXprType;
862 using Base::m_functor;
866 using DstEvaluatorType =
typename Base::DstEvaluatorType;
867 using SrcEvaluatorType =
typename Base::SrcEvaluatorType;
868 using Scalar =
typename Base::Scalar;
869 using AssignmentTraits =
typename Base::AssignmentTraits;
871 EIGEN_DEVICE_FUNC triangular_dense_assignment_kernel(DstEvaluatorType& dst,
const SrcEvaluatorType& src,
872 const Functor& func, DstXprType& dstExpr)
873 : Base(dst, src, func, dstExpr) {}
875#ifdef EIGEN_INTERNAL_DEBUGGING
876 EIGEN_DEVICE_FUNC
void assignCoeff(Index row, Index col) {
877 eigen_internal_assert(row != col);
878 Base::assignCoeff(row, col);
881 using Base::assignCoeff;
884 EIGEN_DEVICE_FUNC
void assignDiagonalCoeff(Index
id) {
885 EIGEN_IF_CONSTEXPR (Mode ==
UnitDiag && SetOpposite) {
886 m_functor.assignCoeff(m_dst.coeffRef(
id,
id), Scalar(1));
887 }
else EIGEN_IF_CONSTEXPR (Mode ==
ZeroDiag && SetOpposite) {
888 m_functor.assignCoeff(m_dst.coeffRef(
id,
id), Scalar(0));
889 }
else EIGEN_IF_CONSTEXPR (Mode == 0) {
890 Base::assignCoeff(
id,
id);
894 EIGEN_DEVICE_FUNC
void assignOppositeCoeff(Index row, Index col) {
895 eigen_internal_assert(row != col);
896 EIGEN_IF_CONSTEXPR (SetOpposite) {
897 m_functor.assignCoeff(m_dst.coeffRef(row, col), Scalar(0));
902template <
int Mode,
bool SetOpposite,
typename DstXprType,
typename SrcXprType,
typename Functor>
903EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_triangular_assignment_loop(DstXprType& dst,
const SrcXprType& src,
904 const Functor& func) {
905 using DstEvaluatorType = evaluator<DstXprType>;
906 using SrcEvaluatorType = evaluator<SrcXprType>;
908 SrcEvaluatorType srcEvaluator(src);
910 Index dstRows = src.rows();
911 Index dstCols = src.cols();
912 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
913 DstEvaluatorType dstEvaluator(dst);
916 SetOpposite, DstEvaluatorType, SrcEvaluatorType, Functor>;
917 Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
920 unroll = DstXprType::SizeAtCompileTime != Dynamic && SrcEvaluatorType::CoeffReadCost < HugeCost &&
921 DstXprType::SizeAtCompileTime *
922 (int(DstEvaluatorType::CoeffReadCost) + int(SrcEvaluatorType::CoeffReadCost)) / 2 <=
923 EIGEN_UNROLLING_LIMIT
926 triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) : Dynamic, SetOpposite>::run(
930template <
int Mode,
bool SetOpposite,
typename DstXprType,
typename SrcXprType>
931EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_triangular_assignment_loop(DstXprType& dst,
const SrcXprType& src) {
932 call_triangular_assignment_loop<Mode, SetOpposite>(
933 dst, src, internal::assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>());
937struct AssignmentKind<TriangularShape, TriangularShape> {
938 using Kind = Triangular2Triangular;
941struct AssignmentKind<DenseShape, TriangularShape> {
942 using Kind = Triangular2Dense;
945struct AssignmentKind<TriangularShape, DenseShape> {
946 using Kind = Dense2Triangular;
949template <
typename Shape>
950struct is_dense_structured_shape
951 : bool_constant<std::is_same<Shape, TriangularShape>::value || std::is_same<Shape, SelfAdjointShape>::value> {};
953template <
typename Lhs,
typename Rhs>
954struct is_dense_structured_diagonal_product
955 : bool_constant<(is_dense_structured_shape<typename evaluator_traits<Lhs>::Shape>::value &&
956 std::is_same<typename evaluator_traits<Rhs>::Shape, DiagonalShape>::value) ||
957 (std::is_same<typename evaluator_traits<Lhs>::Shape, DiagonalShape>::value &&
958 is_dense_structured_shape<typename evaluator_traits<Rhs>::Shape>::value)> {};
960template <
typename DstXprType,
typename SrcXprType,
typename Functor>
961struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Triangular> {
962 EIGEN_DEVICE_FUNC
static void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func) {
963 eigen_assert(
int(DstXprType::Mode) ==
int(SrcXprType::Mode));
965 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
969template <
typename DstXprType,
typename SrcXprType,
typename Functor>
970struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Dense> {
971 EIGEN_DEVICE_FUNC
static void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func) {
972 call_triangular_assignment_loop<SrcXprType::Mode, (int(SrcXprType::Mode) & int(SelfAdjoint)) == 0>(dst, src, func);
976template <
typename DstXprType,
typename SrcXprType,
typename Functor>
977struct Assignment<DstXprType, SrcXprType, Functor, Dense2Triangular> {
978 EIGEN_DEVICE_FUNC
static void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func) {
979 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
983template <
typename Kernel,
unsigned int Mode,
int UnrollCount,
bool SetOpposite>
984struct triangular_assignment_loop {
986 using DstEvaluatorType =
typename Kernel::DstEvaluatorType;
987 using DstXprType =
typename DstEvaluatorType::XprType;
990 col = (UnrollCount - 1) / DstXprType::RowsAtCompileTime,
991 row = (UnrollCount - 1) % DstXprType::RowsAtCompileTime
994 using Scalar =
typename Kernel::Scalar;
996 EIGEN_DEVICE_FUNC
static inline void run(Kernel& kernel) {
997 triangular_assignment_loop<Kernel, Mode, UnrollCount - 1, SetOpposite>::run(kernel);
1000 kernel.assignDiagonalCoeff(row);
1001 else if (((Mode &
Lower) && row > col) || ((Mode &
Upper) && row < col))
1002 kernel.assignCoeff(row, col);
1003 else EIGEN_IF_CONSTEXPR (SetOpposite) {
1004 kernel.assignOppositeCoeff(row, col);
1010template <
typename Kernel,
unsigned int Mode,
bool SetOpposite>
1011struct triangular_assignment_loop<Kernel, Mode, 0, SetOpposite> {
1012 EIGEN_DEVICE_FUNC
static inline void run(Kernel&) {}
1018template <
typename Kernel,
unsigned int Mode,
bool SetOpposite>
1019struct triangular_assignment_loop<Kernel, Mode, Dynamic, SetOpposite> {
1020 using Scalar =
typename Kernel::Scalar;
1021 using DstEvaluatorType =
typename Kernel::DstEvaluatorType;
1022 using AssignmentTraits =
typename Kernel::AssignmentTraits;
1025 IsRowMajor = (int(DstEvaluatorType::Flags) &
RowMajorBit) != 0,
1029 ActiveBeforeDiag = (
bool(Mode &
Upper) !=
bool(IsRowMajor))
1035 static constexpr Index row(Index outer, Index inner) {
return IsRowMajor ? outer : inner; }
1036 static constexpr Index col(Index outer, Index inner) {
return IsRowMajor ? inner : outer; }
1044 EIGEN_DEVICE_FUNC
static inline void run(Kernel& kernel) {
1045 const Index outerSize = IsRowMajor ? kernel.rows() : kernel.cols();
1046 const Index innerSize = IsRowMajor ? kernel.cols() : kernel.rows();
1048 for (Index outer = 0; outer < outerSize; ++outer) {
1049 const Index maxi = numext::mini(outer, innerSize);
1052 EIGEN_IF_CONSTEXPR (ActiveBeforeDiag) {
1053 for (; i < maxi; ++i) kernel.assignCoeff(row(outer, i), col(outer, i));
1054 }
else EIGEN_IF_CONSTEXPR (SetOpposite) {
1055 for (; i < maxi; ++i) kernel.assignOppositeCoeff(row(outer, i), col(outer, i));
1060 if (i < innerSize) kernel.assignDiagonalCoeff(i++);
1062 EIGEN_IF_CONSTEXPR (!ActiveBeforeDiag) {
1063 for (; i < innerSize; ++i) kernel.assignCoeff(row(outer, i), col(outer, i));
1064 }
else EIGEN_IF_CONSTEXPR (SetOpposite) {
1065 for (; i < innerSize; ++i) kernel.assignOppositeCoeff(row(outer, i), col(outer, i));
1075template <
typename Derived>
1076template <
typename DenseDerived>
1078 other.derived().
resize(this->rows(), this->cols());
1079 internal::call_triangular_assignment_loop<Derived::Mode,
1081 other.derived(),
derived().nestedExpression());
1086template <
bool UseTriangularAssignmentLoop>
1087struct triangular_product_assignment_dispatcher {
1088 template <
typename DstXprType,
typename SrcXprType,
typename Functor,
typename Scalar>
1089 static void run(DstXprType& dst,
const SrcXprType& src,
const Functor&,
const Scalar& alpha,
bool beta) {
1091 Index dstRows = src.rows();
1092 Index dstCols = src.cols();
1093 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
1096 dst._assignProduct(src, alpha, beta);
1105template <
typename Op>
1106EIGEN_DEVICE_FUNC
inline const void* diagonal_operand_data(
const Op& op, DiagonalShape) {
1107 return extract_data(op.diagonal());
1109template <
typename Op,
typename Shape>
1110EIGEN_DEVICE_FUNC
inline const void* diagonal_operand_data(
const Op& , Shape) {
1114template <
typename DstXprType,
typename SrcXprType>
1115EIGEN_DEVICE_FUNC
inline bool structured_diagonal_product_aliases(
const DstXprType& dst,
const SrcXprType& src) {
1116 const void* dst_data = dst.nestedExpression().data();
1117 if (dst_data ==
nullptr)
return false;
1118 const void* lhs_diag_data =
1119 diagonal_operand_data(src.lhs(),
typename evaluator_traits<typename SrcXprType::Lhs>::Shape{});
1120 const void* rhs_diag_data =
1121 diagonal_operand_data(src.rhs(),
typename evaluator_traits<typename SrcXprType::Rhs>::Shape{});
1122 return (lhs_diag_data !=
nullptr && lhs_diag_data == dst_data) ||
1123 (rhs_diag_data !=
nullptr && rhs_diag_data == dst_data);
1127struct triangular_product_assignment_dispatcher<true> {
1128 template <
typename DstXprType,
typename SrcXprType,
typename Functor,
typename Scalar>
1129 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func,
1130 const Scalar& alpha,
bool beta) {
1131 EIGEN_UNUSED_VARIABLE(alpha);
1132 EIGEN_UNUSED_VARIABLE(beta);
1133 EIGEN_STATIC_ASSERT((
int(DstXprType::Mode) &
int(
UnitDiag)) == 0,
1134 WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED);
1143 if (structured_diagonal_product_aliases(dst, src)) {
1144 typename SrcXprType::PlainObject tmp(src);
1145 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, tmp, func);
1147 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
1153template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename Scalar>
1154struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
1155 internal::assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>, Dense2Triangular> {
1156 using SrcXprType = Product<Lhs, Rhs, DefaultProduct>;
1157 static void run(DstXprType& dst,
const SrcXprType& src,
1158 const internal::assign_op<Scalar, typename SrcXprType::Scalar>& func) {
1159 enum { UseTriangularAssignmentLoop = is_dense_structured_diagonal_product<Lhs, Rhs>::value };
1160 triangular_product_assignment_dispatcher<UseTriangularAssignmentLoop>::run(dst, src, func, Scalar(1),
false);
1165template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename Scalar>
1166struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
1167 internal::add_assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
1169 using SrcXprType = Product<Lhs, Rhs, DefaultProduct>;
1170 static void run(DstXprType& dst,
const SrcXprType& src,
1171 const internal::add_assign_op<Scalar, typename SrcXprType::Scalar>& func) {
1172 enum { UseTriangularAssignmentLoop = is_dense_structured_diagonal_product<Lhs, Rhs>::value };
1173 triangular_product_assignment_dispatcher<UseTriangularAssignmentLoop>::run(dst, src, func, Scalar(1),
true);
1178template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename Scalar>
1179struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
1180 internal::sub_assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
1182 using SrcXprType = Product<Lhs, Rhs, DefaultProduct>;
1183 static void run(DstXprType& dst,
const SrcXprType& src,
1184 const internal::sub_assign_op<Scalar, typename SrcXprType::Scalar>& func) {
1185 enum { UseTriangularAssignmentLoop = is_dense_structured_diagonal_product<Lhs, Rhs>::value };
1186 triangular_product_assignment_dispatcher<UseTriangularAssignmentLoop>::run(dst, src, func, Scalar(-1),
true);