Eigen  5.0.1-dev+7c7d8473
 
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 <jacob.benoit.1@gmail.com>
5// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
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),
45
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 constexpr Index rows() const noexcept { return derived().rows(); }
62 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return derived().cols(); }
63 EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return derived().outerStride(); }
64 EIGEN_DEVICE_FUNC constexpr Index innerStride() const 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#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
93 EIGEN_DEVICE_FUNC inline Scalar operator[](Index row, Index col) const { return operator()(row, col); }
94 EIGEN_DEVICE_FUNC inline Scalar& operator[](Index row, Index col) { return operator()(row, col); }
95#endif
96
97#ifndef EIGEN_PARSED_BY_DOXYGEN
98 EIGEN_DEVICE_FUNC inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
99 EIGEN_DEVICE_FUNC inline Derived& derived() { return *static_cast<Derived*>(this); }
100#endif // not EIGEN_PARSED_BY_DOXYGEN
101
102 template <typename DenseDerived>
103 EIGEN_DEVICE_FUNC void evalTo(MatrixBase<DenseDerived>& other) const;
104 template <typename DenseDerived>
105 EIGEN_DEVICE_FUNC void evalToLazy(MatrixBase<DenseDerived>& other) const;
106
107 EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const {
108 DenseMatrixType res(rows(), cols());
109 evalToLazy(res);
110 return res;
111 }
112
113 protected:
114 void check_coordinates(Index row, Index col) const {
115 EIGEN_ONLY_USED_FOR_DEBUG(row);
116 EIGEN_ONLY_USED_FOR_DEBUG(col);
117 eigen_assert(col >= 0 && col < cols() && row >= 0 && row < rows());
118 const int mode = int(Mode) & ~SelfAdjoint;
119 EIGEN_ONLY_USED_FOR_DEBUG(mode);
120 eigen_assert((mode == Upper && col >= row) || (mode == Lower && col <= row) ||
121 ((mode == StrictlyUpper || mode == UnitUpper) && col > row) ||
122 ((mode == StrictlyLower || mode == UnitLower) && col < row));
123 }
124
125#ifdef EIGEN_INTERNAL_DEBUGGING
126 void check_coordinates_internal(Index row, Index col) const { check_coordinates(row, col); }
127#else
128 void check_coordinates_internal(Index, Index) const {}
129#endif
130};
131
150namespace internal {
151template <typename MatrixType, unsigned int Mode_>
152struct traits<TriangularView<MatrixType, Mode_>> : traits<MatrixType> {
153 typedef typename ref_selector<MatrixType>::non_const_type MatrixTypeNested;
154 typedef std::remove_reference_t<MatrixTypeNested> MatrixTypeNestedNonRef;
155 typedef remove_all_t<MatrixTypeNested> MatrixTypeNestedCleaned;
156 typedef typename MatrixType::PlainObject FullMatrixType;
157 typedef MatrixType ExpressionType;
158 enum {
159 Mode = Mode_,
160 FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
161 Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits | FlagsLvalueBit) &
163 };
164};
165} // namespace internal
166
167template <typename MatrixType_, unsigned int Mode_, typename StorageKind>
168class TriangularViewImpl;
169
170template <typename MatrixType_, unsigned int Mode_>
171class TriangularView
172 : public TriangularViewImpl<MatrixType_, Mode_, typename internal::traits<MatrixType_>::StorageKind> {
173 public:
174 typedef TriangularViewImpl<MatrixType_, Mode_, typename internal::traits<MatrixType_>::StorageKind> Base;
175 typedef typename internal::traits<TriangularView>::Scalar Scalar;
176 typedef MatrixType_ MatrixType;
177
178 protected:
179 typedef typename internal::traits<TriangularView>::MatrixTypeNested MatrixTypeNested;
180 typedef typename internal::traits<TriangularView>::MatrixTypeNestedNonRef MatrixTypeNestedNonRef;
181
182 typedef internal::remove_all_t<typename MatrixType::ConjugateReturnType> MatrixConjugateReturnType;
183 typedef TriangularView<std::add_const_t<MatrixType>, Mode_> ConstTriangularView;
184
185 public:
186 typedef typename internal::traits<TriangularView>::StorageKind StorageKind;
187 typedef typename internal::traits<TriangularView>::MatrixTypeNestedCleaned NestedExpression;
188
189 enum {
190 Mode = Mode_,
191 Flags = internal::traits<TriangularView>::Flags,
192 TransposeMode = (int(Mode) & int(Upper) ? Lower : 0) | (int(Mode) & int(Lower) ? Upper : 0) |
193 (int(Mode) & int(UnitDiag)) | (int(Mode) & int(ZeroDiag)),
194 IsVectorAtCompileTime = false
195 };
196
197 EIGEN_DEVICE_FUNC explicit inline TriangularView(MatrixType& matrix) : m_matrix(matrix) {}
198
199 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TriangularView)
200
201
202 EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); }
204 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); }
205
207 EIGEN_DEVICE_FUNC const NestedExpression& nestedExpression() const { return m_matrix; }
208
210 EIGEN_DEVICE_FUNC NestedExpression& nestedExpression() { return m_matrix; }
211
214 EIGEN_DEVICE_FUNC inline const ConjugateReturnType conjugate() const {
215 return ConjugateReturnType(m_matrix.conjugate());
216 }
217
221 template <bool Cond>
222 EIGEN_DEVICE_FUNC inline std::conditional_t<Cond, ConjugateReturnType, ConstTriangularView> conjugateIf() const {
223 typedef std::conditional_t<Cond, ConjugateReturnType, ConstTriangularView> ReturnType;
224 return ReturnType(m_matrix.template conjugateIf<Cond>());
225 }
226
229 EIGEN_DEVICE_FUNC inline const AdjointReturnType adjoint() const { return AdjointReturnType(m_matrix.adjoint()); }
230
233 template <class Dummy = int>
234 EIGEN_DEVICE_FUNC inline TransposeReturnType transpose(
235 std::enable_if_t<Eigen::internal::is_lvalue<MatrixType>::value, Dummy*> = nullptr) {
236 typename MatrixType::TransposeReturnType tmp(m_matrix);
237 return TransposeReturnType(tmp);
238 }
239
242 EIGEN_DEVICE_FUNC inline const ConstTransposeReturnType transpose() const {
243 return ConstTransposeReturnType(m_matrix.transpose());
244 }
245
246 template <typename Other>
247 EIGEN_DEVICE_FUNC inline const Solve<TriangularView, Other> solve(const MatrixBase<Other>& other) const {
248 return Solve<TriangularView, Other>(*this, other.derived());
249 }
250
251// workaround MSVC ICE
252#if EIGEN_COMP_MSVC
253 template <int Side, typename Other>
254 EIGEN_DEVICE_FUNC inline const internal::triangular_solve_retval<Side, TriangularView, Other> solve(
255 const MatrixBase<Other>& other) const {
256 return Base::template solve<Side>(other);
257 }
258#else
259 using Base::solve;
260#endif
261
267 EIGEN_STATIC_ASSERT((Mode & (UnitDiag | ZeroDiag)) == 0, PROGRAMMING_ERROR);
269 }
270
273 EIGEN_STATIC_ASSERT((Mode & (UnitDiag | ZeroDiag)) == 0, PROGRAMMING_ERROR);
275 }
276
279 EIGEN_DEVICE_FUNC Scalar determinant() const {
280 if (Mode & UnitDiag)
281 return 1;
282 else if (Mode & ZeroDiag)
283 return 0;
284 else
285 return m_matrix.diagonal().prod();
286 }
287
288 protected:
289 MatrixTypeNested m_matrix;
290};
291
301template <typename MatrixType_, unsigned int Mode_>
302class TriangularViewImpl<MatrixType_, Mode_, Dense> : public TriangularBase<TriangularView<MatrixType_, Mode_>> {
303 public:
304 typedef TriangularView<MatrixType_, Mode_> TriangularViewType;
305
306 typedef TriangularBase<TriangularViewType> Base;
307 typedef typename internal::traits<TriangularViewType>::Scalar Scalar;
308
309 typedef MatrixType_ MatrixType;
310 typedef typename MatrixType::PlainObject DenseMatrixType;
311 typedef DenseMatrixType PlainObject;
312
313 public:
314 using Base::derived;
315 using Base::evalToLazy;
316
317 typedef typename internal::traits<TriangularViewType>::StorageKind StorageKind;
318
319 enum { Mode = Mode_, Flags = internal::traits<TriangularViewType>::Flags };
320
323 EIGEN_DEVICE_FUNC inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
326 EIGEN_DEVICE_FUNC inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
327
329 template <typename Other>
330 EIGEN_DEVICE_FUNC TriangularViewType& operator+=(const DenseBase<Other>& other) {
331 internal::call_assignment_no_alias(derived(), other.derived(),
332 internal::add_assign_op<Scalar, typename Other::Scalar>());
333 return derived();
334 }
335
336 template <typename Other>
337 EIGEN_DEVICE_FUNC TriangularViewType& operator-=(const DenseBase<Other>& other) {
338 internal::call_assignment_no_alias(derived(), other.derived(),
339 internal::sub_assign_op<Scalar, typename Other::Scalar>());
340 return derived();
341 }
342
344 EIGEN_DEVICE_FUNC TriangularViewType& operator*=(const typename internal::traits<MatrixType>::Scalar& other) {
345 return *this = derived().nestedExpression() * other;
346 }
347
348 EIGEN_DEVICE_FUNC TriangularViewType& operator/=(const typename internal::traits<MatrixType>::Scalar& other) {
349 return *this = derived().nestedExpression() / other;
350 }
351
353 EIGEN_DEVICE_FUNC void fill(const Scalar& value) { setConstant(value); }
355 EIGEN_DEVICE_FUNC TriangularViewType& setConstant(const Scalar& value) {
356 return *this = MatrixType::Constant(derived().rows(), derived().cols(), value);
357 }
358
359 EIGEN_DEVICE_FUNC TriangularViewType& setZero() { return setConstant(Scalar(0)); }
361 EIGEN_DEVICE_FUNC TriangularViewType& setOnes() { return setConstant(Scalar(1)); }
362
366 EIGEN_DEVICE_FUNC inline Scalar coeff(Index row, Index col) const {
367 Base::check_coordinates_internal(row, col);
368 return derived().nestedExpression().coeff(row, col);
369 }
370
374 EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col) {
375 EIGEN_STATIC_ASSERT_LVALUE(TriangularViewType);
376 Base::check_coordinates_internal(row, col);
377 return derived().nestedExpression().coeffRef(row, col);
378 }
379
381 template <typename OtherDerived>
382 EIGEN_DEVICE_FUNC TriangularViewType& operator=(const TriangularBase<OtherDerived>& other);
383
385 template <typename OtherDerived>
386 EIGEN_DEVICE_FUNC TriangularViewType& operator=(const MatrixBase<OtherDerived>& other);
387
388#ifndef EIGEN_PARSED_BY_DOXYGEN
389 EIGEN_DEVICE_FUNC TriangularViewType& operator=(const TriangularViewImpl& other) {
390 return *this = other.derived().nestedExpression();
391 }
392
393 template <typename OtherDerived>
395 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void lazyAssign(const TriangularBase<OtherDerived>& other);
396
397 template <typename OtherDerived>
399 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void lazyAssign(const MatrixBase<OtherDerived>& other);
400#endif
401
403 template <typename OtherDerived>
405 const MatrixBase<OtherDerived>& rhs) const {
406 return Product<TriangularViewType, OtherDerived>(derived(), rhs.derived());
407 }
408
410 template <typename OtherDerived>
412 const MatrixBase<OtherDerived>& lhs, const TriangularViewImpl& rhs) {
413 return Product<OtherDerived, TriangularViewType>(lhs.derived(), rhs.derived());
414 }
415
439 template <int Side, typename Other>
440 inline const internal::triangular_solve_retval<Side, TriangularViewType, Other> solve(
441 const MatrixBase<Other>& other) const;
442
452 template <int Side, typename OtherDerived>
453 EIGEN_DEVICE_FUNC void solveInPlace(const MatrixBase<OtherDerived>& other) const;
454
455 template <typename OtherDerived>
456 EIGEN_DEVICE_FUNC void solveInPlace(const MatrixBase<OtherDerived>& other) const {
457 return solveInPlace<OnTheLeft>(other);
458 }
459
461 template <typename OtherDerived>
462 EIGEN_DEVICE_FUNC
463#ifdef EIGEN_PARSED_BY_DOXYGEN
464 void
465 swap(TriangularBase<OtherDerived>& other)
466#else
467 void
468 swap(TriangularBase<OtherDerived> const& other)
469#endif
470 {
471 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
472 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
473 }
474
476 template <typename OtherDerived>
478 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void swap(MatrixBase<OtherDerived> const& other) {
479 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
480 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
481 }
482
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);
487 }
488
489 template <typename ProductType>
490 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha,
491 bool beta);
492
493 protected:
494 EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl)
495 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl)
496};
497
498/***************************************************************************
499 * Implementation of triangular evaluation/assignment
500 ***************************************************************************/
501
502#ifndef EIGEN_PARSED_BY_DOXYGEN
503// FIXME should we keep that possibility
504template <typename MatrixType, unsigned int Mode>
505template <typename OtherDerived>
506EIGEN_DEVICE_FUNC inline TriangularView<MatrixType, Mode>& TriangularViewImpl<MatrixType, Mode, Dense>::operator=(
507 const MatrixBase<OtherDerived>& other) {
508 internal::call_assignment_no_alias(derived(), other.derived(),
509 internal::assign_op<Scalar, typename OtherDerived::Scalar>());
510 return derived();
511}
512
513// FIXME should we keep that possibility
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>());
518}
519
520template <typename MatrixType, unsigned int Mode>
521template <typename OtherDerived>
522EIGEN_DEVICE_FUNC inline TriangularView<MatrixType, Mode>& TriangularViewImpl<MatrixType, Mode, Dense>::operator=(
523 const TriangularBase<OtherDerived>& other) {
524 eigen_assert(Mode == int(OtherDerived::Mode));
525 internal::call_assignment(derived(), other.derived());
526 return derived();
527}
528
529template <typename MatrixType, unsigned int Mode>
530template <typename OtherDerived>
531EIGEN_DEVICE_FUNC void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(
532 const TriangularBase<OtherDerived>& other) {
533 eigen_assert(Mode == int(OtherDerived::Mode));
534 internal::call_assignment_no_alias(derived(), other.derived());
535}
536#endif
537
538/***************************************************************************
539 * Implementation of TriangularBase methods
540 ***************************************************************************/
541
544template <typename Derived>
545template <typename DenseDerived>
546EIGEN_DEVICE_FUNC void TriangularBase<Derived>::evalTo(MatrixBase<DenseDerived>& other) const {
547 evalToLazy(other.derived());
548}
549
550/***************************************************************************
551 * Implementation of TriangularView methods
552 ***************************************************************************/
553
554/***************************************************************************
555 * Implementation of MatrixBase methods
556 ***************************************************************************/
557
569template <typename Derived>
570template <unsigned int Mode>
571EIGEN_DEVICE_FUNC typename MatrixBase<Derived>::template TriangularViewReturnType<Mode>::Type
572MatrixBase<Derived>::triangularView() {
573 return typename TriangularViewReturnType<Mode>::Type(derived());
574}
575
577template <typename Derived>
578template <unsigned int Mode>
579EIGEN_DEVICE_FUNC typename MatrixBase<Derived>::template ConstTriangularViewReturnType<Mode>::Type
580MatrixBase<Derived>::triangularView() const {
581 return typename ConstTriangularViewReturnType<Mode>::Type(derived());
582}
583
589template <typename Derived>
590bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const {
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;
597 }
598 }
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;
603 return true;
604}
605
611template <typename Derived>
612bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const {
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;
618 }
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;
624 }
625 return true;
626}
627
628/***************************************************************************
629****************************************************************************
630* Evaluators and Assignment of triangular expressions
631***************************************************************************
632***************************************************************************/
633
634namespace internal {
635
636// TODO currently a triangular expression has the form TriangularView<.,.>
637// in the future triangular-ness should be defined by the expression traits
638// such that Transpose<TriangularView<.,.> > is valid. (currently TriangularBase::transpose() is overloaded to make
639// it work)
640template <typename MatrixType, unsigned int Mode>
641struct evaluator_traits<TriangularView<MatrixType, 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;
644};
645
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()) {}
651};
652
653// Additional assignment kinds:
654struct Triangular2Triangular {};
655struct Triangular2Dense {};
656struct Dense2Triangular {};
657
658template <typename Kernel, unsigned int Mode, int UnrollCount, bool ClearOpposite>
659struct triangular_assignment_loop;
660
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> {
670 protected:
671 typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> Base;
672 typedef typename Base::DstXprType DstXprType;
673 typedef typename Base::SrcXprType SrcXprType;
674 using Base::m_dst;
675 using Base::m_functor;
676 using Base::m_src;
677
678 public:
679 typedef typename Base::DstEvaluatorType DstEvaluatorType;
680 typedef typename Base::SrcEvaluatorType SrcEvaluatorType;
681 typedef typename Base::Scalar Scalar;
682 typedef typename Base::AssignmentTraits AssignmentTraits;
683
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) {}
687
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);
692 }
693#else
694 using Base::assignCoeff;
695#endif
696
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));
702 else if (Mode == 0)
703 Base::assignCoeff(id, id);
704 }
705
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));
709 }
710};
711
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;
717
718 SrcEvaluatorType srcEvaluator(src);
719
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);
724
725 typedef triangular_dense_assignment_kernel<Mode&(Lower | Upper), Mode&(UnitDiag | ZeroDiag | SelfAdjoint),
726 SetOpposite, DstEvaluatorType, SrcEvaluatorType, Functor>
727 Kernel;
728 Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
729
730 enum {
731 unroll = DstXprType::SizeAtCompileTime != Dynamic && SrcEvaluatorType::CoeffReadCost < HugeCost &&
732 DstXprType::SizeAtCompileTime *
733 (int(DstEvaluatorType::CoeffReadCost) + int(SrcEvaluatorType::CoeffReadCost)) / 2 <=
734 EIGEN_UNROLLING_LIMIT
735 };
736
737 triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) : Dynamic, SetOpposite>::run(
738 kernel);
739}
740
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>());
745}
746
747template <>
748struct AssignmentKind<TriangularShape, TriangularShape> {
749 typedef Triangular2Triangular Kind;
750};
751template <>
752struct AssignmentKind<DenseShape, TriangularShape> {
753 typedef Triangular2Dense Kind;
754};
755template <>
756struct AssignmentKind<TriangularShape, DenseShape> {
757 typedef Dense2Triangular Kind;
758};
759
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));
764
765 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
766 }
767};
768
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);
773 }
774};
775
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);
780 }
781};
782
783template <typename Kernel, unsigned int Mode, int UnrollCount, bool SetOpposite>
784struct triangular_assignment_loop {
785 // FIXME: this is not very clean, perhaps this information should be provided by the kernel?
786 typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
787 typedef typename DstEvaluatorType::XprType DstXprType;
788
789 enum {
790 col = (UnrollCount - 1) / DstXprType::RowsAtCompileTime,
791 row = (UnrollCount - 1) % DstXprType::RowsAtCompileTime
792 };
793
794 typedef typename Kernel::Scalar Scalar;
795
796 EIGEN_DEVICE_FUNC static inline void run(Kernel& kernel) {
797 triangular_assignment_loop<Kernel, Mode, UnrollCount - 1, SetOpposite>::run(kernel);
798
799 if (row == col)
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);
805 }
806};
807
808// prevent buggy user code from causing an infinite recursion
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&) {}
812};
813
814// TODO: experiment with a recursive assignment procedure splitting the current
815// triangular part into one rectangular and two triangular parts.
816
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());
823 Index i = 0;
824 if (((Mode & Lower) && SetOpposite) || (Mode & Upper)) {
825 for (; i < maxi; ++i)
826 if (Mode & Upper)
827 kernel.assignCoeff(i, j);
828 else
829 kernel.assignOppositeCoeff(i, j);
830 } else
831 i = maxi;
832
833 if (i < kernel.rows()) // then i==j
834 kernel.assignDiagonalCoeff(i++);
835
836 if (((Mode & Upper) && SetOpposite) || (Mode & Lower)) {
837 for (; i < kernel.rows(); ++i)
838 if (Mode & Lower)
839 kernel.assignCoeff(i, j);
840 else
841 kernel.assignOppositeCoeff(i, j);
842 }
843 }
844 }
845};
846
847} // end namespace internal
848
851template <typename Derived>
852template <typename DenseDerived>
854 other.derived().resize(this->rows(), this->cols());
855 internal::call_triangular_assignment_loop<Derived::Mode,
856 (int(Derived::Mode) & int(SelfAdjoint)) == 0 /* SetOpposite */>(
857 other.derived(), derived().nestedExpression());
858}
859
860namespace internal {
861
862// Triangular = Product
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> {
866 typedef Product<Lhs, Rhs, DefaultProduct> SrcXprType;
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);
872
873 dst._assignProduct(src, Scalar(1), false);
874 }
875};
876
877// Triangular += Product
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>,
881 Dense2Triangular> {
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);
886 }
887};
888
889// Triangular -= Product
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>,
893 Dense2Triangular> {
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);
898 }
899};
900
901} // end namespace internal
902
903} // end namespace Eigen
904
905#endif // EIGEN_TRIANGULARMATRIX_H
Base class for all dense matrices, vectors, and arrays.
Definition DenseBase.h:44
void resize(Index newSize)
Definition DenseBase.h:228
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:52
bool isLowerTriangular(const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition TriangularMatrix.h:612
bool isUpperTriangular(const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition TriangularMatrix.h:590
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
@ SizeAtCompileTime
Definition TriangularMatrix.h:41
void evalTo(MatrixBase< DenseDerived > &other) const
Definition TriangularMatrix.h:546
void evalToLazy(MatrixBase< DenseDerived > &other) const
Definition TriangularMatrix.h:853
Scalar coeff(Index row, Index col) const
Definition TriangularMatrix.h:366
TriangularViewType & setConstant(const Scalar &value)
Definition TriangularMatrix.h:355
void fill(const Scalar &value)
Definition TriangularMatrix.h:353
TriangularViewType & operator*=(const typename internal::traits< MatrixType >::Scalar &other)
Definition TriangularMatrix.h:344
TriangularViewType & operator+=(const DenseBase< Other > &other)
Definition TriangularMatrix.h:330
TriangularViewType & operator/=(const typename internal::traits< MatrixType >::Scalar &other)
Definition TriangularMatrix.h:348
Index outerStride() const
Definition TriangularMatrix.h:323
TriangularViewType & operator-=(const DenseBase< Other > &other)
Definition TriangularMatrix.h:337
TriangularViewType & setZero()
Definition TriangularMatrix.h:359
friend const Product< OtherDerived, TriangularViewType > operator*(const MatrixBase< OtherDerived > &lhs, const TriangularViewImpl &rhs)
Definition TriangularMatrix.h:411
TriangularViewType & operator=(const TriangularBase< OtherDerived > &other)
Scalar & coeffRef(Index row, Index col)
Definition TriangularMatrix.h:374
TriangularViewType & setOnes()
Definition TriangularMatrix.h:361
EIGEN_DEPRECATED void swap(MatrixBase< OtherDerived > const &other)
Definition TriangularMatrix.h:478
TriangularViewType & operator=(const MatrixBase< OtherDerived > &other)
Index innerStride() const
Definition TriangularMatrix.h:326
const Product< TriangularViewType, OtherDerived > operator*(const MatrixBase< OtherDerived > &rhs) const
Definition TriangularMatrix.h:404
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:465
Expression of a triangular part in a matrix.
Definition TriangularMatrix.h:172
const ConjugateReturnType conjugate() const
Definition TriangularMatrix.h:214
const NestedExpression & nestedExpression() const
Definition TriangularMatrix.h:207
Scalar determinant() const
Definition TriangularMatrix.h:279
TransposeReturnType transpose(std::enable_if_t< Eigen::internal::is_lvalue< MatrixType >::value, Dummy * >=nullptr)
Definition TriangularMatrix.h:234
const ConstTransposeReturnType transpose() const
Definition TriangularMatrix.h:242
const AdjointReturnType adjoint() const
Definition TriangularMatrix.h:229
std::conditional_t< Cond, ConjugateReturnType, ConstTriangularView > conjugateIf() const
Definition TriangularMatrix.h:222
const SelfAdjointView< MatrixTypeNestedNonRef, Mode > selfadjointView() const
Definition TriangularMatrix.h:272
SelfAdjointView< MatrixTypeNestedNonRef, Mode > selfadjointView()
Definition TriangularMatrix.h:266
constexpr Index rows() const noexcept
Definition TriangularMatrix.h:202
NestedExpression & nestedExpression()
Definition TriangularMatrix.h:210
constexpr Index cols() const noexcept
Definition TriangularMatrix.h:204
@ 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 PacketAccessBit
Definition Constants.h:97
const unsigned int LinearAccessBit
Definition Constants.h:133
const unsigned int DirectAccessBit
Definition Constants.h:159
const unsigned int LvalueBit
Definition Constants.h:148
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
std::enable_if_t< std::is_base_of< DenseBase< std::decay_t< DerivedA > >, std::decay_t< DerivedA > >::value &&std::is_base_of< DenseBase< std::decay_t< DerivedB > >, std::decay_t< DerivedB > >::value, void > swap(DerivedA &&a, DerivedB &&b)
Definition DenseBase.h:667
const int HugeCost
Definition Constants.h:48
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:82
const int Dynamic
Definition Constants.h:25
Definition Constants.h:519
Definition EigenBase.h:33
constexpr Derived & derived()
Definition EigenBase.h:49
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:43