273 EIGEN_STATIC_ASSERT((Mode & (
UnitDiag |
ZeroDiag)) == 0, PROGRAMMING_ERROR);
285 return m_matrix.diagonal().prod();
289 MatrixTypeNested m_matrix;
301template <
typename MatrixType_,
unsigned int Mode_>
302class TriangularViewImpl<MatrixType_, Mode_,
Dense> :
public TriangularBase<TriangularView<MatrixType_, Mode_>> {
306 typedef TriangularBase<TriangularViewType> Base;
307 typedef typename internal::traits<TriangularViewType>::Scalar Scalar;
309 typedef MatrixType_ MatrixType;
310 typedef typename MatrixType::PlainObject DenseMatrixType;
311 typedef DenseMatrixType PlainObject;
317 typedef typename internal::traits<TriangularViewType>::StorageKind StorageKind;
319 enum { Mode = Mode_, Flags = internal::traits<TriangularViewType>::Flags };
329 template <
typename Other>
331 internal::call_assignment_no_alias(
derived(), other.derived(),
332 internal::add_assign_op<Scalar, typename Other::Scalar>());
336 template <
typename Other>
338 internal::call_assignment_no_alias(
derived(), other.derived(),
339 internal::sub_assign_op<Scalar, typename Other::Scalar>());
344 EIGEN_DEVICE_FUNC TriangularViewType&
operator*=(
const typename internal::traits<MatrixType>::Scalar& other) {
345 return *
this =
derived().nestedExpression() * other;
348 EIGEN_DEVICE_FUNC TriangularViewType&
operator/=(
const typename internal::traits<MatrixType>::Scalar& other) {
349 return *
this =
derived().nestedExpression() / other;
355 EIGEN_DEVICE_FUNC TriangularViewType&
setConstant(
const Scalar& value) {
356 return *
this = MatrixType::Constant(
derived().rows(),
derived().cols(), value);
367 Base::check_coordinates_internal(row, col);
368 return derived().nestedExpression().coeff(row, col);
375 EIGEN_STATIC_ASSERT_LVALUE(TriangularViewType);
376 Base::check_coordinates_internal(row, col);
377 return derived().nestedExpression().coeffRef(row, col);
381 template <
typename OtherDerived>
382 EIGEN_DEVICE_FUNC TriangularViewType&
operator=(
const TriangularBase<OtherDerived>& other);
385 template <
typename OtherDerived>
388#ifndef EIGEN_PARSED_BY_DOXYGEN
389 EIGEN_DEVICE_FUNC TriangularViewType&
operator=(
const TriangularViewImpl& other) {
390 return *
this = other.derived().nestedExpression();
393 template <
typename OtherDerived>
397 template <
typename OtherDerived>
403 template <
typename OtherDerived>
410 template <
typename OtherDerived>
439 template <
int S
ide,
typename Other>
440 inline const internal::triangular_solve_retval<Side, TriangularViewType, Other>
solve(
452 template <
int S
ide,
typename OtherDerived>
455 template <
typename OtherDerived>
461 template <
typename OtherDerived>
463#ifdef EIGEN_PARSED_BY_DOXYGEN
465 swap(TriangularBase<OtherDerived>& other)
468 swap(TriangularBase<OtherDerived>
const& other)
471 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
472 call_assignment(
derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
476 template <
typename OtherDerived>
479 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
480 call_assignment(
derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
483 template <
typename RhsType,
typename DstType>
484 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void _solve_impl(
const RhsType& rhs, DstType& dst)
const {
485 if (!internal::is_same_dense(dst, rhs)) dst = rhs;
486 this->solveInPlace(dst);
489 template <
typename ProductType>
490 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(
const ProductType& prod,
const Scalar& alpha,
494 EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl)
495 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl)
502#ifndef EIGEN_PARSED_BY_DOXYGEN
504template <
typename MatrixType,
unsigned int Mode>
505template <
typename OtherDerived>
508 internal::call_assignment_no_alias(derived(), other.derived(),
509 internal::assign_op<Scalar, typename OtherDerived::Scalar>());
514template <
typename MatrixType,
unsigned int Mode>
515template <
typename OtherDerived>
516EIGEN_DEVICE_FUNC
void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(
const MatrixBase<OtherDerived>& other) {
517 internal::call_assignment_no_alias(derived(), other.template triangularView<Mode>());
520template <
typename MatrixType,
unsigned int Mode>
521template <
typename OtherDerived>
524 eigen_assert(Mode ==
int(OtherDerived::Mode));
525 internal::call_assignment(derived(), other.derived());
529template <
typename MatrixType,
unsigned int Mode>
530template <
typename OtherDerived>
531EIGEN_DEVICE_FUNC
void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(
533 eigen_assert(Mode ==
int(OtherDerived::Mode));
534 internal::call_assignment_no_alias(derived(), other.derived());
544template <
typename Derived>
545template <
typename DenseDerived>
569template <
typename Derived>
570template <
unsigned int Mode>
572MatrixBase<Derived>::triangularView() {
573 return typename TriangularViewReturnType<Mode>::Type(derived());
577template <
typename Derived>
578template <
unsigned int Mode>
580MatrixBase<Derived>::triangularView()
const {
581 return typename ConstTriangularViewReturnType<Mode>::Type(derived());
589template <
typename Derived>
591 RealScalar maxAbsOnUpperPart =
static_cast<RealScalar
>(-1);
592 for (
Index j = 0; j < cols(); ++j) {
593 Index maxi = numext::mini(j, rows() - 1);
594 for (
Index i = 0; i <= maxi; ++i) {
595 RealScalar absValue = numext::abs(coeff(i, j));
596 if (absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
599 RealScalar threshold = maxAbsOnUpperPart * prec;
600 for (
Index j = 0; j < cols(); ++j)
601 for (
Index i = j + 1; i < rows(); ++i)
602 if (numext::abs(coeff(i, j)) > threshold)
return false;
611template <
typename Derived>
613 RealScalar maxAbsOnLowerPart =
static_cast<RealScalar
>(-1);
614 for (
Index j = 0; j < cols(); ++j)
615 for (
Index i = j; i < rows(); ++i) {
616 RealScalar absValue = numext::abs(coeff(i, j));
617 if (absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
619 RealScalar threshold = maxAbsOnLowerPart * prec;
620 for (
Index j = 1; j < cols(); ++j) {
621 Index maxi = numext::mini(j, rows() - 1);
622 for (
Index i = 0; i < maxi; ++i)
623 if (numext::abs(coeff(i, j)) > threshold)
return false;
640template <
typename MatrixType,
unsigned int Mode>
642 typedef typename storage_kind_to_evaluator_kind<typename MatrixType::StorageKind>::Kind Kind;
643 typedef typename glue_shapes<typename evaluator_traits<MatrixType>::Shape, TriangularShape>::type Shape;
646template <
typename MatrixType,
unsigned int Mode>
647struct unary_evaluator<TriangularView<MatrixType, Mode>, IndexBased> : evaluator<internal::remove_all_t<MatrixType>> {
648 typedef TriangularView<MatrixType, Mode> XprType;
649 typedef evaluator<internal::remove_all_t<MatrixType>> Base;
650 EIGEN_DEVICE_FUNC unary_evaluator(
const XprType& xpr) : Base(xpr.nestedExpression()) {}
654struct Triangular2Triangular {};
655struct Triangular2Dense {};
656struct Dense2Triangular {};
658template <
typename Kernel,
unsigned int Mode,
int UnrollCount,
bool ClearOpposite>
659struct triangular_assignment_loop;
666template <
int UpLo,
int Mode,
int SetOpposite,
typename DstEvaluatorTypeT,
typename SrcEvaluatorTypeT,
typename Functor,
667 int Version = Specialized>
668class triangular_dense_assignment_kernel
669 :
public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> {
671 typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> Base;
672 typedef typename Base::DstXprType DstXprType;
673 typedef typename Base::SrcXprType SrcXprType;
675 using Base::m_functor;
679 typedef typename Base::DstEvaluatorType DstEvaluatorType;
680 typedef typename Base::SrcEvaluatorType SrcEvaluatorType;
681 typedef typename Base::Scalar Scalar;
682 typedef typename Base::AssignmentTraits AssignmentTraits;
684 EIGEN_DEVICE_FUNC triangular_dense_assignment_kernel(DstEvaluatorType& dst,
const SrcEvaluatorType& src,
685 const Functor& func, DstXprType& dstExpr)
686 : Base(dst, src, func, dstExpr) {}
688#ifdef EIGEN_INTERNAL_DEBUGGING
689 EIGEN_DEVICE_FUNC
void assignCoeff(
Index row,
Index col) {
690 eigen_internal_assert(row != col);
691 Base::assignCoeff(row, col);
694 using Base::assignCoeff;
697 EIGEN_DEVICE_FUNC
void assignDiagonalCoeff(
Index id) {
698 if (Mode ==
UnitDiag && SetOpposite)
699 m_functor.assignCoeff(m_dst.coeffRef(
id,
id), Scalar(1));
700 else if (Mode ==
ZeroDiag && SetOpposite)
701 m_functor.assignCoeff(m_dst.coeffRef(
id,
id), Scalar(0));
703 Base::assignCoeff(
id,
id);
706 EIGEN_DEVICE_FUNC
void assignOppositeCoeff(
Index row,
Index col) {
707 eigen_internal_assert(row != col);
708 if (SetOpposite) m_functor.assignCoeff(m_dst.coeffRef(row, col), Scalar(0));
712template <
int Mode,
bool SetOpposite,
typename DstXprType,
typename SrcXprType,
typename Functor>
713EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_triangular_assignment_loop(DstXprType& dst,
const SrcXprType& src,
714 const Functor& func) {
715 typedef evaluator<DstXprType> DstEvaluatorType;
716 typedef evaluator<SrcXprType> SrcEvaluatorType;
718 SrcEvaluatorType srcEvaluator(src);
720 Index dstRows = src.rows();
721 Index dstCols = src.cols();
722 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
723 DstEvaluatorType dstEvaluator(dst);
726 SetOpposite, DstEvaluatorType, SrcEvaluatorType, Functor>
728 Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
731 unroll = DstXprType::SizeAtCompileTime !=
Dynamic && SrcEvaluatorType::CoeffReadCost <
HugeCost &&
732 DstXprType::SizeAtCompileTime *
733 (int(DstEvaluatorType::CoeffReadCost) + int(SrcEvaluatorType::CoeffReadCost)) / 2 <=
734 EIGEN_UNROLLING_LIMIT
737 triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) :
Dynamic, SetOpposite>::run(
741template <
int Mode,
bool SetOpposite,
typename DstXprType,
typename SrcXprType>
742EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_triangular_assignment_loop(DstXprType& dst,
const SrcXprType& src) {
743 call_triangular_assignment_loop<Mode, SetOpposite>(
744 dst, src, internal::assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>());
748struct AssignmentKind<TriangularShape, TriangularShape> {
749 typedef Triangular2Triangular Kind;
752struct AssignmentKind<DenseShape, TriangularShape> {
753 typedef Triangular2Dense Kind;
756struct AssignmentKind<TriangularShape, DenseShape> {
757 typedef Dense2Triangular Kind;
760template <
typename DstXprType,
typename SrcXprType,
typename Functor>
761struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Triangular> {
762 EIGEN_DEVICE_FUNC
static void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func) {
763 eigen_assert(
int(DstXprType::Mode) ==
int(SrcXprType::Mode));
765 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
769template <
typename DstXprType,
typename SrcXprType,
typename Functor>
770struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Dense> {
771 EIGEN_DEVICE_FUNC
static void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func) {
772 call_triangular_assignment_loop<SrcXprType::Mode, (int(SrcXprType::Mode) & int(SelfAdjoint)) == 0>(dst, src, func);
776template <
typename DstXprType,
typename SrcXprType,
typename Functor>
777struct Assignment<DstXprType, SrcXprType, Functor, Dense2Triangular> {
778 EIGEN_DEVICE_FUNC
static void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func) {
779 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
783template <
typename Kernel,
unsigned int Mode,
int UnrollCount,
bool SetOpposite>
784struct triangular_assignment_loop {
786 typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
787 typedef typename DstEvaluatorType::XprType DstXprType;
790 col = (UnrollCount - 1) / DstXprType::RowsAtCompileTime,
791 row = (UnrollCount - 1) % DstXprType::RowsAtCompileTime
794 typedef typename Kernel::Scalar Scalar;
796 EIGEN_DEVICE_FUNC
static inline void run(Kernel& kernel) {
797 triangular_assignment_loop<Kernel, Mode, UnrollCount - 1, SetOpposite>::run(kernel);
800 kernel.assignDiagonalCoeff(row);
801 else if (((Mode &
Lower) && row > col) || ((Mode &
Upper) && row < col))
802 kernel.assignCoeff(row, col);
803 else if (SetOpposite)
804 kernel.assignOppositeCoeff(row, col);
809template <
typename Kernel,
unsigned int Mode,
bool SetOpposite>
810struct triangular_assignment_loop<Kernel, Mode, 0, SetOpposite> {
811 EIGEN_DEVICE_FUNC
static inline void run(Kernel&) {}
817template <
typename Kernel,
unsigned int Mode,
bool SetOpposite>
818struct triangular_assignment_loop<Kernel, Mode,
Dynamic, SetOpposite> {
819 typedef typename Kernel::Scalar Scalar;
820 EIGEN_DEVICE_FUNC
static inline void run(Kernel& kernel) {
821 for (
Index j = 0; j < kernel.cols(); ++j) {
822 Index maxi = numext::mini(j, kernel.rows());
824 if (((Mode &
Lower) && SetOpposite) || (Mode &
Upper)) {
825 for (; i < maxi; ++i)
827 kernel.assignCoeff(i, j);
829 kernel.assignOppositeCoeff(i, j);
833 if (i < kernel.rows())
834 kernel.assignDiagonalCoeff(i++);
836 if (((Mode &
Upper) && SetOpposite) || (Mode &
Lower)) {
837 for (; i < kernel.rows(); ++i)
839 kernel.assignCoeff(i, j);
841 kernel.assignOppositeCoeff(i, j);
851template <
typename Derived>
852template <
typename DenseDerived>
854 other.derived().
resize(this->rows(), this->cols());
855 internal::call_triangular_assignment_loop<Derived::Mode,
857 other.derived(),
derived().nestedExpression());
863template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename Scalar>
864struct Assignment<DstXprType,
Product<Lhs, Rhs, DefaultProduct>,
865 internal::assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>, Dense2Triangular> {
867 static void run(DstXprType& dst,
const SrcXprType& src,
868 const internal::assign_op<Scalar, typename SrcXprType::Scalar>&) {
869 Index dstRows = src.rows();
870 Index dstCols = src.cols();
871 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
873 dst._assignProduct(src,
Scalar(1),
false);
878template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename Scalar>
879struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
880 internal::add_assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
882 typedef Product<Lhs, Rhs, DefaultProduct> SrcXprType;
883 static void run(DstXprType& dst,
const SrcXprType& src,
884 const internal::add_assign_op<Scalar, typename SrcXprType::Scalar>&) {
885 dst._assignProduct(src, Scalar(1),
true);
890template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename Scalar>
891struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
892 internal::sub_assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
894 typedef Product<Lhs, Rhs, DefaultProduct> SrcXprType;
895 static void run(DstXprType& dst,
const SrcXprType& src,
896 const internal::sub_assign_op<Scalar, typename SrcXprType::Scalar>&) {
897 dst._assignProduct(src, Scalar(-1),
true);