280 return m_matrix.diagonal().prod();
284 MatrixTypeNested m_matrix;
296template <
typename MatrixType_,
unsigned int Mode_>
297class TriangularViewImpl<MatrixType_, Mode_,
Dense> :
public TriangularBase<TriangularView<MatrixType_, Mode_>> {
302 typedef typename internal::traits<TriangularViewType>::Scalar Scalar;
304 typedef MatrixType_ MatrixType;
305 typedef typename MatrixType::PlainObject DenseMatrixType;
306 typedef DenseMatrixType PlainObject;
310 using Base::evalToLazy;
312 typedef typename internal::traits<TriangularViewType>::StorageKind StorageKind;
314 enum { Mode = Mode_, Flags = internal::traits<TriangularViewType>::Flags };
318 EIGEN_DEVICE_FUNC
inline Index outerStride()
const {
return derived().nestedExpression().outerStride(); }
321 EIGEN_DEVICE_FUNC
inline Index innerStride()
const {
return derived().nestedExpression().innerStride(); }
324 template <
typename Other>
326 internal::call_assignment_no_alias(derived(), other.
derived(),
327 internal::add_assign_op<Scalar, typename Other::Scalar>());
331 template <
typename Other>
333 internal::call_assignment_no_alias(derived(), other.
derived(),
334 internal::sub_assign_op<Scalar, typename Other::Scalar>());
348 EIGEN_DEVICE_FUNC
void fill(
const Scalar& value) { setConstant(value); }
351 return *
this = MatrixType::Constant(derived().rows(), derived().cols(), value);
362 Base::check_coordinates_internal(row, col);
363 return derived().nestedExpression().coeff(row, col);
371 Base::check_coordinates_internal(row, col);
372 return derived().nestedExpression().coeffRef(row, col);
376 template <
typename OtherDerived>
380 template <
typename OtherDerived>
383#ifndef EIGEN_PARSED_BY_DOXYGEN
385 return *
this = other.derived().nestedExpression();
388 template <
typename OtherDerived>
392 template <
typename OtherDerived>
398 template <
typename OtherDerived>
405 template <
typename OtherDerived>
434 template <
int S
ide,
typename Other>
435 inline const internal::triangular_solve_retval<Side, TriangularViewType, Other>
solve(
447 template <
int S
ide,
typename OtherDerived>
450 template <
typename OtherDerived>
452 return solveInPlace<OnTheLeft>(other);
456 template <
typename OtherDerived>
458#ifdef EIGEN_PARSED_BY_DOXYGEN
466 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
467 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
471 template <
typename OtherDerived>
474 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
475 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
478 template <
typename RhsType,
typename DstType>
479 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void _solve_impl(
const RhsType& rhs, DstType& dst)
const {
480 if (!internal::is_same_dense(dst, rhs)) dst = rhs;
481 this->solveInPlace(dst);
484 template <
typename ProductType>
485 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(
const ProductType& prod,
const Scalar& alpha,
489 EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl)
490 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl)
497#ifndef EIGEN_PARSED_BY_DOXYGEN
499template <
typename MatrixType,
unsigned int Mode>
500template <
typename OtherDerived>
501EIGEN_DEVICE_FUNC
inline TriangularView<MatrixType, Mode>& TriangularViewImpl<MatrixType, Mode, Dense>::operator=(
502 const MatrixBase<OtherDerived>& other) {
503 internal::call_assignment_no_alias(derived(), other.derived(),
504 internal::assign_op<Scalar, typename OtherDerived::Scalar>());
509template <
typename MatrixType,
unsigned int Mode>
510template <
typename OtherDerived>
511EIGEN_DEVICE_FUNC
void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(
const MatrixBase<OtherDerived>& other) {
512 internal::call_assignment_no_alias(derived(), other.template triangularView<Mode>());
515template <
typename MatrixType,
unsigned int Mode>
516template <
typename OtherDerived>
517EIGEN_DEVICE_FUNC
inline TriangularView<MatrixType, Mode>& TriangularViewImpl<MatrixType, Mode, Dense>::operator=(
518 const TriangularBase<OtherDerived>& other) {
519 eigen_assert(Mode ==
int(OtherDerived::Mode));
520 internal::call_assignment(derived(), other.derived());
524template <
typename MatrixType,
unsigned int Mode>
525template <
typename OtherDerived>
526EIGEN_DEVICE_FUNC
void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(
527 const TriangularBase<OtherDerived>& other) {
528 eigen_assert(Mode ==
int(OtherDerived::Mode));
529 internal::call_assignment_no_alias(derived(), other.derived());
539template <
typename Derived>
540template <
typename DenseDerived>
564template <
typename Derived>
565template <
unsigned int Mode>
572template <
typename Derived>
573template <
unsigned int Mode>
584template <
typename Derived>
586 RealScalar maxAbsOnUpperPart =
static_cast<RealScalar
>(-1);
587 for (
Index j = 0; j < cols(); ++j) {
588 Index maxi = numext::mini(j, rows() - 1);
589 for (
Index i = 0; i <= maxi; ++i) {
590 RealScalar absValue = numext::abs(coeff(i, j));
591 if (absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
594 RealScalar threshold = maxAbsOnUpperPart * prec;
595 for (
Index j = 0; j < cols(); ++j)
596 for (
Index i = j + 1; i < rows(); ++i)
597 if (numext::abs(coeff(i, j)) > threshold)
return false;
606template <
typename Derived>
608 RealScalar maxAbsOnLowerPart =
static_cast<RealScalar
>(-1);
609 for (
Index j = 0; j < cols(); ++j)
610 for (
Index i = j; i < rows(); ++i) {
611 RealScalar absValue = numext::abs(coeff(i, j));
612 if (absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
614 RealScalar threshold = maxAbsOnLowerPart * prec;
615 for (
Index j = 1; j < cols(); ++j) {
616 Index maxi = numext::mini(j, rows() - 1);
617 for (
Index i = 0; i < maxi; ++i)
618 if (numext::abs(coeff(i, j)) > threshold)
return false;
635template <
typename MatrixType,
unsigned int Mode>
637 typedef typename storage_kind_to_evaluator_kind<typename MatrixType::StorageKind>::Kind Kind;
638 typedef typename glue_shapes<typename evaluator_traits<MatrixType>::Shape, TriangularShape>::type Shape;
641template <
typename MatrixType,
unsigned int Mode>
642struct unary_evaluator<TriangularView<MatrixType, Mode>, IndexBased> : evaluator<internal::remove_all_t<MatrixType>> {
643 typedef TriangularView<MatrixType, Mode> XprType;
644 typedef evaluator<internal::remove_all_t<MatrixType>> Base;
645 EIGEN_DEVICE_FUNC unary_evaluator(
const XprType& xpr) : Base(xpr.nestedExpression()) {}
649struct Triangular2Triangular {};
650struct Triangular2Dense {};
651struct Dense2Triangular {};
653template <
typename Kernel,
unsigned int Mode,
int UnrollCount,
bool ClearOpposite>
654struct triangular_assignment_loop;
661template <
int UpLo,
int Mode,
int SetOpposite,
typename DstEvaluatorTypeT,
typename SrcEvaluatorTypeT,
typename Functor,
662 int Version = Specialized>
663class triangular_dense_assignment_kernel
664 :
public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> {
666 typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> Base;
667 typedef typename Base::DstXprType DstXprType;
668 typedef typename Base::SrcXprType SrcXprType;
670 using Base::m_functor;
674 typedef typename Base::DstEvaluatorType DstEvaluatorType;
675 typedef typename Base::SrcEvaluatorType SrcEvaluatorType;
676 typedef typename Base::Scalar Scalar;
677 typedef typename Base::AssignmentTraits AssignmentTraits;
679 EIGEN_DEVICE_FUNC triangular_dense_assignment_kernel(DstEvaluatorType& dst,
const SrcEvaluatorType& src,
680 const Functor& func, DstXprType& dstExpr)
681 : Base(dst, src, func, dstExpr) {}
683#ifdef EIGEN_INTERNAL_DEBUGGING
684 EIGEN_DEVICE_FUNC
void assignCoeff(Index row, Index col) {
685 eigen_internal_assert(row != col);
686 Base::assignCoeff(row, col);
689 using Base::assignCoeff;
692 EIGEN_DEVICE_FUNC
void assignDiagonalCoeff(Index
id) {
693 if (Mode ==
UnitDiag && SetOpposite)
694 m_functor.assignCoeff(m_dst.coeffRef(
id,
id), Scalar(1));
695 else if (Mode ==
ZeroDiag && SetOpposite)
696 m_functor.assignCoeff(m_dst.coeffRef(
id,
id), Scalar(0));
698 Base::assignCoeff(
id,
id);
701 EIGEN_DEVICE_FUNC
void assignOppositeCoeff(Index row, Index col) {
702 eigen_internal_assert(row != col);
703 if (SetOpposite) m_functor.assignCoeff(m_dst.coeffRef(row, col), Scalar(0));
707template <
int Mode,
bool SetOpposite,
typename DstXprType,
typename SrcXprType,
typename Functor>
708EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_triangular_assignment_loop(DstXprType& dst,
const SrcXprType& src,
709 const Functor& func) {
710 typedef evaluator<DstXprType> DstEvaluatorType;
711 typedef evaluator<SrcXprType> SrcEvaluatorType;
713 SrcEvaluatorType srcEvaluator(src);
715 Index dstRows = src.rows();
716 Index dstCols = src.cols();
717 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
718 DstEvaluatorType dstEvaluator(dst);
721 SetOpposite, DstEvaluatorType, SrcEvaluatorType, Functor>
723 Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
726 unroll = DstXprType::SizeAtCompileTime !=
Dynamic && SrcEvaluatorType::CoeffReadCost <
HugeCost &&
727 DstXprType::SizeAtCompileTime *
728 (int(DstEvaluatorType::CoeffReadCost) + int(SrcEvaluatorType::CoeffReadCost)) / 2 <=
729 EIGEN_UNROLLING_LIMIT
732 triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) :
Dynamic, SetOpposite>::run(
736template <
int Mode,
bool SetOpposite,
typename DstXprType,
typename SrcXprType>
737EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_triangular_assignment_loop(DstXprType& dst,
const SrcXprType& src) {
738 call_triangular_assignment_loop<Mode, SetOpposite>(
739 dst, src, internal::assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>());
743struct AssignmentKind<TriangularShape, TriangularShape> {
744 typedef Triangular2Triangular Kind;
747struct AssignmentKind<DenseShape, TriangularShape> {
748 typedef Triangular2Dense Kind;
751struct AssignmentKind<TriangularShape, DenseShape> {
752 typedef Dense2Triangular Kind;
755template <
typename DstXprType,
typename SrcXprType,
typename Functor>
756struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Triangular> {
757 EIGEN_DEVICE_FUNC
static void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func) {
758 eigen_assert(
int(DstXprType::Mode) ==
int(SrcXprType::Mode));
760 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
764template <
typename DstXprType,
typename SrcXprType,
typename Functor>
765struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Dense> {
766 EIGEN_DEVICE_FUNC
static void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func) {
767 call_triangular_assignment_loop<SrcXprType::Mode, (int(SrcXprType::Mode) & int(SelfAdjoint)) == 0>(dst, src, func);
771template <
typename DstXprType,
typename SrcXprType,
typename Functor>
772struct Assignment<DstXprType, SrcXprType, Functor, Dense2Triangular> {
773 EIGEN_DEVICE_FUNC
static void run(DstXprType& dst,
const SrcXprType& src,
const Functor& func) {
774 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
778template <
typename Kernel,
unsigned int Mode,
int UnrollCount,
bool SetOpposite>
779struct triangular_assignment_loop {
781 typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
782 typedef typename DstEvaluatorType::XprType DstXprType;
785 col = (UnrollCount - 1) / DstXprType::RowsAtCompileTime,
786 row = (UnrollCount - 1) % DstXprType::RowsAtCompileTime
789 typedef typename Kernel::Scalar Scalar;
791 EIGEN_DEVICE_FUNC
static inline void run(Kernel& kernel) {
792 triangular_assignment_loop<Kernel, Mode, UnrollCount - 1, SetOpposite>::run(kernel);
795 kernel.assignDiagonalCoeff(row);
796 else if (((Mode &
Lower) && row > col) || ((Mode &
Upper) && row < col))
797 kernel.assignCoeff(row, col);
798 else if (SetOpposite)
799 kernel.assignOppositeCoeff(row, col);
804template <
typename Kernel,
unsigned int Mode,
bool SetOpposite>
805struct triangular_assignment_loop<Kernel, Mode, 0, SetOpposite> {
806 EIGEN_DEVICE_FUNC
static inline void run(Kernel&) {}
812template <
typename Kernel,
unsigned int Mode,
bool SetOpposite>
813struct triangular_assignment_loop<Kernel, Mode,
Dynamic, SetOpposite> {
814 typedef typename Kernel::Scalar Scalar;
815 EIGEN_DEVICE_FUNC
static inline void run(Kernel& kernel) {
816 for (Index j = 0; j < kernel.cols(); ++j) {
817 Index maxi = numext::mini(j, kernel.rows());
819 if (((Mode &
Lower) && SetOpposite) || (Mode &
Upper)) {
820 for (; i < maxi; ++i)
822 kernel.assignCoeff(i, j);
824 kernel.assignOppositeCoeff(i, j);
828 if (i < kernel.rows())
829 kernel.assignDiagonalCoeff(i++);
831 if (((Mode &
Upper) && SetOpposite) || (Mode &
Lower)) {
832 for (; i < kernel.rows(); ++i)
834 kernel.assignCoeff(i, j);
836 kernel.assignOppositeCoeff(i, j);
846template <
typename Derived>
847template <
typename DenseDerived>
849 other.
derived().resize(this->rows(), this->cols());
850 internal::call_triangular_assignment_loop<Derived::Mode,
852 other.
derived(), derived().nestedExpression());
858template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename Scalar>
859struct Assignment<DstXprType,
Product<Lhs, Rhs, DefaultProduct>,
860 internal::assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>, Dense2Triangular> {
862 static void run(DstXprType& dst,
const SrcXprType& src,
863 const internal::assign_op<Scalar, typename SrcXprType::Scalar>&) {
864 Index dstRows = src.rows();
865 Index dstCols = src.cols();
866 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
868 dst._assignProduct(src, Scalar(1),
false);
873template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename Scalar>
874struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
875 internal::add_assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
877 typedef Product<Lhs, Rhs, DefaultProduct> SrcXprType;
878 static void run(DstXprType& dst,
const SrcXprType& src,
879 const internal::add_assign_op<Scalar, typename SrcXprType::Scalar>&) {
880 dst._assignProduct(src, Scalar(1),
true);
885template <
typename DstXprType,
typename Lhs,
typename Rhs,
typename Scalar>
886struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
887 internal::sub_assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
889 typedef Product<Lhs, Rhs, DefaultProduct> SrcXprType;
890 static void run(DstXprType& dst,
const SrcXprType& src,
891 const internal::sub_assign_op<Scalar, typename SrcXprType::Scalar>&) {
892 dst._assignProduct(src, Scalar(-1),
true);