Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
TriangularMatrix.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008 Benoit Jacob <[email protected]>
5// Copyright (C) 2008-2009 Gael Guennebaud <[email protected]>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10
11#ifndef EIGEN_TRIANGULARMATRIX_H
12#define EIGEN_TRIANGULARMATRIX_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20
21template <int Side, typename TriangularType, typename Rhs>
22struct triangular_solve_retval;
23
24}
25
31template <typename Derived>
32class TriangularBase : public EigenBase<Derived> {
33 public:
34 enum {
35 Mode = internal::traits<Derived>::Mode,
36 RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
37 ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
38 MaxRowsAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime,
39 MaxColsAtCompileTime = internal::traits<Derived>::MaxColsAtCompileTime,
40
41 SizeAtCompileTime = (internal::size_of_xpr_at_compile_time<Derived>::ret),
46 MaxSizeAtCompileTime = internal::size_at_compile_time(internal::traits<Derived>::MaxRowsAtCompileTime,
47 internal::traits<Derived>::MaxColsAtCompileTime)
48
49 };
50 typedef typename internal::traits<Derived>::Scalar Scalar;
51 typedef typename internal::traits<Derived>::StorageKind StorageKind;
52 typedef typename internal::traits<Derived>::StorageIndex StorageIndex;
53 typedef typename internal::traits<Derived>::FullMatrixType DenseMatrixType;
54 typedef DenseMatrixType DenseType;
55 typedef Derived const& Nested;
56
57 EIGEN_DEVICE_FUNC inline TriangularBase() {
58 eigen_assert(!((int(Mode) & int(UnitDiag)) && (int(Mode) & int(ZeroDiag))));
59 }
60
61 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return derived().rows(); }
62 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return derived().cols(); }
63 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT { return derived().outerStride(); }
64 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT { return derived().innerStride(); }
65
66 // dummy resize function
67 EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) {
68 EIGEN_UNUSED_VARIABLE(rows);
69 EIGEN_UNUSED_VARIABLE(cols);
70 eigen_assert(rows == this->rows() && cols == this->cols());
71 }
72
73 EIGEN_DEVICE_FUNC inline Scalar coeff(Index row, Index col) const { return derived().coeff(row, col); }
74 EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col) { return derived().coeffRef(row, col); }
75
78 template <typename Other>
79 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, Other& other) {
80 derived().coeffRef(row, col) = other.coeff(row, col);
81 }
82
83 EIGEN_DEVICE_FUNC inline Scalar operator()(Index row, Index col) const {
84 check_coordinates(row, col);
85 return coeff(row, col);
86 }
87 EIGEN_DEVICE_FUNC inline Scalar& operator()(Index row, Index col) {
88 check_coordinates(row, col);
89 return coeffRef(row, col);
90 }
91
92#ifndef EIGEN_PARSED_BY_DOXYGEN
93 EIGEN_DEVICE_FUNC inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
94 EIGEN_DEVICE_FUNC inline Derived& derived() { return *static_cast<Derived*>(this); }
95#endif // not EIGEN_PARSED_BY_DOXYGEN
96
97 template <typename DenseDerived>
98 EIGEN_DEVICE_FUNC void evalTo(MatrixBase<DenseDerived>& other) const;
99 template <typename DenseDerived>
100 EIGEN_DEVICE_FUNC void evalToLazy(MatrixBase<DenseDerived>& other) const;
101
102 EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const {
103 DenseMatrixType res(rows(), cols());
104 evalToLazy(res);
105 return res;
106 }
107
108 protected:
109 void check_coordinates(Index row, Index col) const {
110 EIGEN_ONLY_USED_FOR_DEBUG(row);
111 EIGEN_ONLY_USED_FOR_DEBUG(col);
112 eigen_assert(col >= 0 && col < cols() && row >= 0 && row < rows());
113 const int mode = int(Mode) & ~SelfAdjoint;
114 EIGEN_ONLY_USED_FOR_DEBUG(mode);
115 eigen_assert((mode == Upper && col >= row) || (mode == Lower && col <= row) ||
116 ((mode == StrictlyUpper || mode == UnitUpper) && col > row) ||
117 ((mode == StrictlyLower || mode == UnitLower) && col < row));
118 }
119
120#ifdef EIGEN_INTERNAL_DEBUGGING
121 void check_coordinates_internal(Index row, Index col) const { check_coordinates(row, col); }
122#else
123 void check_coordinates_internal(Index, Index) const {}
124#endif
125};
126
145namespace internal {
146template <typename MatrixType, unsigned int Mode_>
147struct traits<TriangularView<MatrixType, Mode_>> : traits<MatrixType> {
148 typedef typename ref_selector<MatrixType>::non_const_type MatrixTypeNested;
149 typedef std::remove_reference_t<MatrixTypeNested> MatrixTypeNestedNonRef;
150 typedef remove_all_t<MatrixTypeNested> MatrixTypeNestedCleaned;
151 typedef typename MatrixType::PlainObject FullMatrixType;
152 typedef MatrixType ExpressionType;
153 enum {
154 Mode = Mode_,
155 FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
156 Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits | FlagsLvalueBit) &
157 (~(PacketAccessBit | DirectAccessBit | LinearAccessBit)))
158 };
159};
160} // namespace internal
161
162template <typename MatrixType_, unsigned int Mode_, typename StorageKind>
163class TriangularViewImpl;
164
165template <typename MatrixType_, unsigned int Mode_>
167 : public TriangularViewImpl<MatrixType_, Mode_, typename internal::traits<MatrixType_>::StorageKind> {
168 public:
169 typedef TriangularViewImpl<MatrixType_, Mode_, typename internal::traits<MatrixType_>::StorageKind> Base;
170 typedef typename internal::traits<TriangularView>::Scalar Scalar;
171 typedef MatrixType_ MatrixType;
172
173 protected:
174 typedef typename internal::traits<TriangularView>::MatrixTypeNested MatrixTypeNested;
175 typedef typename internal::traits<TriangularView>::MatrixTypeNestedNonRef MatrixTypeNestedNonRef;
176
177 typedef internal::remove_all_t<typename MatrixType::ConjugateReturnType> MatrixConjugateReturnType;
179
180 public:
181 typedef typename internal::traits<TriangularView>::StorageKind StorageKind;
182 typedef typename internal::traits<TriangularView>::MatrixTypeNestedCleaned NestedExpression;
183
184 enum {
185 Mode = Mode_,
186 Flags = internal::traits<TriangularView>::Flags,
187 TransposeMode = (int(Mode) & int(Upper) ? Lower : 0) | (int(Mode) & int(Lower) ? Upper : 0) |
188 (int(Mode) & int(UnitDiag)) | (int(Mode) & int(ZeroDiag)),
189 IsVectorAtCompileTime = false
190 };
191
192 EIGEN_DEVICE_FUNC explicit inline TriangularView(MatrixType& matrix) : m_matrix(matrix) {}
193
194 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TriangularView)
195
196
197 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
199 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
200
202 EIGEN_DEVICE_FUNC const NestedExpression& nestedExpression() const { return m_matrix; }
203
205 EIGEN_DEVICE_FUNC NestedExpression& nestedExpression() { return m_matrix; }
206
209 EIGEN_DEVICE_FUNC inline const ConjugateReturnType conjugate() const {
210 return ConjugateReturnType(m_matrix.conjugate());
211 }
212
216 template <bool Cond>
217 EIGEN_DEVICE_FUNC inline std::conditional_t<Cond, ConjugateReturnType, ConstTriangularView> conjugateIf() const {
218 typedef std::conditional_t<Cond, ConjugateReturnType, ConstTriangularView> ReturnType;
219 return ReturnType(m_matrix.template conjugateIf<Cond>());
220 }
221
224 EIGEN_DEVICE_FUNC inline const AdjointReturnType adjoint() const { return AdjointReturnType(m_matrix.adjoint()); }
225
228 template <class Dummy = int>
229 EIGEN_DEVICE_FUNC inline TransposeReturnType transpose(
230 std::enable_if_t<Eigen::internal::is_lvalue<MatrixType>::value, Dummy*> = nullptr) {
231 typename MatrixType::TransposeReturnType tmp(m_matrix);
232 return TransposeReturnType(tmp);
233 }
234
237 EIGEN_DEVICE_FUNC inline const ConstTransposeReturnType transpose() const {
238 return ConstTransposeReturnType(m_matrix.transpose());
239 }
240
241 template <typename Other>
242 EIGEN_DEVICE_FUNC inline const Solve<TriangularView, Other> solve(const MatrixBase<Other>& other) const {
243 return Solve<TriangularView, Other>(*this, other.derived());
244 }
245
246// workaround MSVC ICE
247#if EIGEN_COMP_MSVC
248 template <int Side, typename Other>
249 EIGEN_DEVICE_FUNC inline const internal::triangular_solve_retval<Side, TriangularView, Other> solve(
250 const MatrixBase<Other>& other) const {
251 return Base::template solve<Side>(other);
252 }
253#else
254 using Base::solve;
255#endif
256
262 EIGEN_STATIC_ASSERT((Mode & (UnitDiag | ZeroDiag)) == 0, PROGRAMMING_ERROR);
264 }
265
268 EIGEN_STATIC_ASSERT((Mode & (UnitDiag | ZeroDiag)) == 0, PROGRAMMING_ERROR);
270 }
271
274 EIGEN_DEVICE_FUNC Scalar determinant() const {
275 if (Mode & UnitDiag)
276 return 1;
277 else if (Mode & ZeroDiag)
278 return 0;
279 else
280 return m_matrix.diagonal().prod();
281 }
282
283 protected:
284 MatrixTypeNested m_matrix;
285};
286
296template <typename MatrixType_, unsigned int Mode_>
297class TriangularViewImpl<MatrixType_, Mode_, Dense> : public TriangularBase<TriangularView<MatrixType_, Mode_>> {
298 public:
300
302 typedef typename internal::traits<TriangularViewType>::Scalar Scalar;
303
304 typedef MatrixType_ MatrixType;
305 typedef typename MatrixType::PlainObject DenseMatrixType;
306 typedef DenseMatrixType PlainObject;
307
308 public:
309 using Base::derived;
310 using Base::evalToLazy;
311
312 typedef typename internal::traits<TriangularViewType>::StorageKind StorageKind;
313
314 enum { Mode = Mode_, Flags = internal::traits<TriangularViewType>::Flags };
315
318 EIGEN_DEVICE_FUNC inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
321 EIGEN_DEVICE_FUNC inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
322
324 template <typename Other>
325 EIGEN_DEVICE_FUNC TriangularViewType& operator+=(const DenseBase<Other>& other) {
326 internal::call_assignment_no_alias(derived(), other.derived(),
327 internal::add_assign_op<Scalar, typename Other::Scalar>());
328 return derived();
329 }
331 template <typename Other>
332 EIGEN_DEVICE_FUNC TriangularViewType& operator-=(const DenseBase<Other>& other) {
333 internal::call_assignment_no_alias(derived(), other.derived(),
334 internal::sub_assign_op<Scalar, typename Other::Scalar>());
335 return derived();
336 }
337
339 EIGEN_DEVICE_FUNC TriangularViewType& operator*=(const typename internal::traits<MatrixType>::Scalar& other) {
340 return *this = derived().nestedExpression() * other;
341 }
343 EIGEN_DEVICE_FUNC TriangularViewType& operator/=(const typename internal::traits<MatrixType>::Scalar& other) {
344 return *this = derived().nestedExpression() / other;
345 }
346
348 EIGEN_DEVICE_FUNC void fill(const Scalar& value) { setConstant(value); }
350 EIGEN_DEVICE_FUNC TriangularViewType& setConstant(const Scalar& value) {
351 return *this = MatrixType::Constant(derived().rows(), derived().cols(), value);
352 }
354 EIGEN_DEVICE_FUNC TriangularViewType& setZero() { return setConstant(Scalar(0)); }
356 EIGEN_DEVICE_FUNC TriangularViewType& setOnes() { return setConstant(Scalar(1)); }
357
361 EIGEN_DEVICE_FUNC inline Scalar coeff(Index row, Index col) const {
362 Base::check_coordinates_internal(row, col);
363 return derived().nestedExpression().coeff(row, col);
364 }
365
369 EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col) {
370 EIGEN_STATIC_ASSERT_LVALUE(TriangularViewType);
371 Base::check_coordinates_internal(row, col);
372 return derived().nestedExpression().coeffRef(row, col);
373 }
374
376 template <typename OtherDerived>
378
380 template <typename OtherDerived>
381 EIGEN_DEVICE_FUNC TriangularViewType& operator=(const MatrixBase<OtherDerived>& other);
382
383#ifndef EIGEN_PARSED_BY_DOXYGEN
384 EIGEN_DEVICE_FUNC TriangularViewType& operator=(const TriangularViewImpl& other) {
385 return *this = other.derived().nestedExpression();
386 }
387
388 template <typename OtherDerived>
390 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void lazyAssign(const TriangularBase<OtherDerived>& other);
391
392 template <typename OtherDerived>
394 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void lazyAssign(const MatrixBase<OtherDerived>& other);
395#endif
396
398 template <typename OtherDerived>
400 const MatrixBase<OtherDerived>& rhs) const {
401 return Product<TriangularViewType, OtherDerived>(derived(), rhs.derived());
402 }
403
405 template <typename OtherDerived>
407 const MatrixBase<OtherDerived>& lhs, const TriangularViewImpl& rhs) {
408 return Product<OtherDerived, TriangularViewType>(lhs.derived(), rhs.derived());
409 }
410
434 template <int Side, typename Other>
435 inline const internal::triangular_solve_retval<Side, TriangularViewType, Other> solve(
436 const MatrixBase<Other>& other) const;
437
447 template <int Side, typename OtherDerived>
448 EIGEN_DEVICE_FUNC void solveInPlace(const MatrixBase<OtherDerived>& other) const;
449
450 template <typename OtherDerived>
451 EIGEN_DEVICE_FUNC void solveInPlace(const MatrixBase<OtherDerived>& other) const {
452 return solveInPlace<OnTheLeft>(other);
453 }
454
456 template <typename OtherDerived>
457 EIGEN_DEVICE_FUNC
458#ifdef EIGEN_PARSED_BY_DOXYGEN
459 void
461#else
462 void
463 swap(TriangularBase<OtherDerived> const& other)
464#endif
465 {
466 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
467 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
468 }
469
471 template <typename OtherDerived>
473 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void swap(MatrixBase<OtherDerived> const& other) {
474 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
475 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
476 }
477
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);
482 }
483
484 template <typename ProductType>
485 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha,
486 bool beta);
487
488 protected:
489 EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl)
490 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl)
491};
492
493/***************************************************************************
494 * Implementation of triangular evaluation/assignment
495 ***************************************************************************/
496
497#ifndef EIGEN_PARSED_BY_DOXYGEN
498// FIXME should we keep that possibility
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>());
505 return derived();
506}
507
508// FIXME should we keep that possibility
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>());
513}
514
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());
521 return derived();
522}
523
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());
530}
531#endif
532
533/***************************************************************************
534 * Implementation of TriangularBase methods
535 ***************************************************************************/
536
539template <typename Derived>
540template <typename DenseDerived>
541EIGEN_DEVICE_FUNC void TriangularBase<Derived>::evalTo(MatrixBase<DenseDerived>& other) const {
542 evalToLazy(other.derived());
543}
544
545/***************************************************************************
546 * Implementation of TriangularView methods
547 ***************************************************************************/
548
549/***************************************************************************
550 * Implementation of MatrixBase methods
551 ***************************************************************************/
552
564template <typename Derived>
565template <unsigned int Mode>
566EIGEN_DEVICE_FUNC typename MatrixBase<Derived>::template TriangularViewReturnType<Mode>::Type
570
572template <typename Derived>
573template <unsigned int Mode>
574EIGEN_DEVICE_FUNC typename MatrixBase<Derived>::template ConstTriangularViewReturnType<Mode>::Type
578
584template <typename Derived>
585bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const {
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;
592 }
593 }
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;
598 return true;
599}
600
606template <typename Derived>
607bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const {
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;
613 }
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;
619 }
620 return true;
621}
622
623/***************************************************************************
624****************************************************************************
625* Evaluators and Assignment of triangular expressions
626***************************************************************************
627***************************************************************************/
628
629namespace internal {
630
631// TODO currently a triangular expression has the form TriangularView<.,.>
632// in the future triangular-ness should be defined by the expression traits
633// such that Transpose<TriangularView<.,.> > is valid. (currently TriangularBase::transpose() is overloaded to make
634// it work)
635template <typename MatrixType, unsigned int Mode>
636struct evaluator_traits<TriangularView<MatrixType, 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;
639};
640
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()) {}
646};
647
648// Additional assignment kinds:
649struct Triangular2Triangular {};
650struct Triangular2Dense {};
651struct Dense2Triangular {};
652
653template <typename Kernel, unsigned int Mode, int UnrollCount, bool ClearOpposite>
654struct triangular_assignment_loop;
655
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> {
665 protected:
666 typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> Base;
667 typedef typename Base::DstXprType DstXprType;
668 typedef typename Base::SrcXprType SrcXprType;
669 using Base::m_dst;
670 using Base::m_functor;
671 using Base::m_src;
672
673 public:
674 typedef typename Base::DstEvaluatorType DstEvaluatorType;
675 typedef typename Base::SrcEvaluatorType SrcEvaluatorType;
676 typedef typename Base::Scalar Scalar;
677 typedef typename Base::AssignmentTraits AssignmentTraits;
678
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) {}
682
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);
687 }
688#else
689 using Base::assignCoeff;
690#endif
691
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));
697 else if (Mode == 0)
698 Base::assignCoeff(id, id);
699 }
700
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));
704 }
705};
706
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;
712
713 SrcEvaluatorType srcEvaluator(src);
714
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);
719
720 typedef triangular_dense_assignment_kernel<Mode&(Lower | Upper), Mode&(UnitDiag | ZeroDiag | SelfAdjoint),
721 SetOpposite, DstEvaluatorType, SrcEvaluatorType, Functor>
722 Kernel;
723 Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
724
725 enum {
726 unroll = DstXprType::SizeAtCompileTime != Dynamic && SrcEvaluatorType::CoeffReadCost < HugeCost &&
727 DstXprType::SizeAtCompileTime *
728 (int(DstEvaluatorType::CoeffReadCost) + int(SrcEvaluatorType::CoeffReadCost)) / 2 <=
729 EIGEN_UNROLLING_LIMIT
730 };
731
732 triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) : Dynamic, SetOpposite>::run(
733 kernel);
734}
735
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>());
740}
741
742template <>
743struct AssignmentKind<TriangularShape, TriangularShape> {
744 typedef Triangular2Triangular Kind;
745};
746template <>
747struct AssignmentKind<DenseShape, TriangularShape> {
748 typedef Triangular2Dense Kind;
749};
750template <>
751struct AssignmentKind<TriangularShape, DenseShape> {
752 typedef Dense2Triangular Kind;
753};
754
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));
759
760 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
761 }
762};
763
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);
768 }
769};
770
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);
775 }
776};
777
778template <typename Kernel, unsigned int Mode, int UnrollCount, bool SetOpposite>
779struct triangular_assignment_loop {
780 // FIXME: this is not very clean, perhaps this information should be provided by the kernel?
781 typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
782 typedef typename DstEvaluatorType::XprType DstXprType;
783
784 enum {
785 col = (UnrollCount - 1) / DstXprType::RowsAtCompileTime,
786 row = (UnrollCount - 1) % DstXprType::RowsAtCompileTime
787 };
788
789 typedef typename Kernel::Scalar Scalar;
790
791 EIGEN_DEVICE_FUNC static inline void run(Kernel& kernel) {
792 triangular_assignment_loop<Kernel, Mode, UnrollCount - 1, SetOpposite>::run(kernel);
793
794 if (row == col)
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);
800 }
801};
802
803// prevent buggy user code from causing an infinite recursion
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&) {}
807};
808
809// TODO: experiment with a recursive assignment procedure splitting the current
810// triangular part into one rectangular and two triangular parts.
811
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());
818 Index i = 0;
819 if (((Mode & Lower) && SetOpposite) || (Mode & Upper)) {
820 for (; i < maxi; ++i)
821 if (Mode & Upper)
822 kernel.assignCoeff(i, j);
823 else
824 kernel.assignOppositeCoeff(i, j);
825 } else
826 i = maxi;
827
828 if (i < kernel.rows()) // then i==j
829 kernel.assignDiagonalCoeff(i++);
830
831 if (((Mode & Upper) && SetOpposite) || (Mode & Lower)) {
832 for (; i < kernel.rows(); ++i)
833 if (Mode & Lower)
834 kernel.assignCoeff(i, j);
835 else
836 kernel.assignOppositeCoeff(i, j);
837 }
838 }
839 }
840};
841
842} // end namespace internal
843
846template <typename Derived>
847template <typename DenseDerived>
849 other.derived().resize(this->rows(), this->cols());
850 internal::call_triangular_assignment_loop<Derived::Mode,
851 (int(Derived::Mode) & int(SelfAdjoint)) == 0 /* SetOpposite */>(
852 other.derived(), derived().nestedExpression());
853}
854
855namespace internal {
856
857// Triangular = Product
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> {
861 typedef Product<Lhs, Rhs, DefaultProduct> SrcXprType;
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);
867
868 dst._assignProduct(src, Scalar(1), false);
869 }
870};
871
872// Triangular += Product
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>,
876 Dense2Triangular> {
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);
881 }
882};
883
884// Triangular -= Product
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>,
888 Dense2Triangular> {
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);
893 }
894};
895
896} // end namespace internal
897
898} // end namespace Eigen
899
900#endif // EIGEN_TRIANGULARMATRIX_H
Base class for all dense matrices, vectors, and arrays.
Definition DenseBase.h:44
Derived & derived()
Definition EigenBase.h:49
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:52
Expression of the product of two arbitrary matrices or vectors.
Definition Product.h:202
Expression of a selfadjoint matrix from a triangular part of a dense matrix.
Definition SelfAdjointView.h:51
Pseudo expression representing a solving operation.
Definition Solve.h:62
Base class for triangular part in a matrix.
Definition TriangularMatrix.h:32
void copyCoeff(Index row, Index col, Other &other)
Definition TriangularMatrix.h:79
void evalTo(MatrixBase< DenseDerived > &other) const
Definition TriangularMatrix.h:541
void evalToLazy(MatrixBase< DenseDerived > &other) const
Definition TriangularMatrix.h:848
@ SizeAtCompileTime
Definition TriangularMatrix.h:41
Scalar coeff(Index row, Index col) const
Definition TriangularMatrix.h:361
TriangularViewType & setConstant(const Scalar &value)
Definition TriangularMatrix.h:350
void fill(const Scalar &value)
Definition TriangularMatrix.h:348
TriangularViewType & operator*=(const typename internal::traits< MatrixType >::Scalar &other)
Definition TriangularMatrix.h:339
TriangularViewType & operator+=(const DenseBase< Other > &other)
Definition TriangularMatrix.h:325
TriangularViewType & operator/=(const typename internal::traits< MatrixType >::Scalar &other)
Definition TriangularMatrix.h:343
Index outerStride() const
Definition TriangularMatrix.h:318
TriangularViewType & operator-=(const DenseBase< Other > &other)
Definition TriangularMatrix.h:332
TriangularViewType & setZero()
Definition TriangularMatrix.h:354
friend const Product< OtherDerived, TriangularViewType > operator*(const MatrixBase< OtherDerived > &lhs, const TriangularViewImpl &rhs)
Definition TriangularMatrix.h:406
TriangularViewType & operator=(const TriangularBase< OtherDerived > &other)
Scalar & coeffRef(Index row, Index col)
Definition TriangularMatrix.h:369
TriangularViewType & setOnes()
Definition TriangularMatrix.h:356
EIGEN_DEPRECATED void swap(MatrixBase< OtherDerived > const &other)
Definition TriangularMatrix.h:473
TriangularViewType & operator=(const MatrixBase< OtherDerived > &other)
Index innerStride() const
Definition TriangularMatrix.h:321
const Product< TriangularViewType, OtherDerived > operator*(const MatrixBase< OtherDerived > &rhs) const
Definition TriangularMatrix.h:399
const internal::triangular_solve_retval< Side, TriangularViewType, Other > solve(const MatrixBase< Other > &other) const
void solveInPlace(const MatrixBase< OtherDerived > &other) const
void swap(TriangularBase< OtherDerived > &other)
Definition TriangularMatrix.h:460
Expression of a triangular part in a matrix.
Definition TriangularMatrix.h:167
const ConjugateReturnType conjugate() const
Definition TriangularMatrix.h:209
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition TriangularMatrix.h:197
const NestedExpression & nestedExpression() const
Definition TriangularMatrix.h:202
Scalar determinant() const
Definition TriangularMatrix.h:274
TransposeReturnType transpose(std::enable_if_t< Eigen::internal::is_lvalue< MatrixType >::value, Dummy * >=nullptr)
Definition TriangularMatrix.h:229
const ConstTransposeReturnType transpose() const
Definition TriangularMatrix.h:237
const AdjointReturnType adjoint() const
Definition TriangularMatrix.h:224
std::conditional_t< Cond, ConjugateReturnType, ConstTriangularView > conjugateIf() const
Definition TriangularMatrix.h:217
SelfAdjointView< MatrixTypeNestedNonRef, Mode > selfadjointView()
Definition TriangularMatrix.h:261
NestedExpression & nestedExpression()
Definition TriangularMatrix.h:205
EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Definition TriangularMatrix.h:199
@ StrictlyLower
Definition Constants.h:223
@ UnitDiag
Definition Constants.h:215
@ StrictlyUpper
Definition Constants.h:225
@ UnitLower
Definition Constants.h:219
@ ZeroDiag
Definition Constants.h:217
@ SelfAdjoint
Definition Constants.h:227
@ UnitUpper
Definition Constants.h:221
@ Lower
Definition Constants.h:211
@ Upper
Definition Constants.h:213
const unsigned int LvalueBit
Definition Constants.h:148
Namespace containing all symbols from the Eigen library.
Definition Core:137
const int HugeCost
Definition Constants.h:48
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
const int Dynamic
Definition Constants.h:25
Definition Constants.h:516
Definition EigenBase.h:33
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:43
Derived & derived()
Definition EigenBase.h:49