Eigen  5.0.1
 
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// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_TRIANGULARMATRIX_H
13#define EIGEN_TRIANGULARMATRIX_H
14
15// IWYU pragma: private
16#include "./InternalHeaderCheck.h"
17
18namespace Eigen {
19
20namespace internal {
21
22template <int Side, typename TriangularType, typename Rhs>
23struct triangular_solve_retval;
24
25template <typename MatrixType, unsigned int Mode, bool IsSelfAdjoint = (int(Mode) & int(SelfAdjoint)) != 0>
26struct triangular_base_return_types {
27 using MatrixConjugateReturnType = internal::remove_all_t<typename MatrixType::ConjugateReturnType>;
28 enum {
29 TransposeMode = (int(Mode) & int(Upper) ? Lower : 0) | (int(Mode) & int(Lower) ? Upper : 0) |
30 (int(Mode) & int(UnitDiag)) | (int(Mode) & int(ZeroDiag))
31 };
32 using ConstView = TriangularView<std::add_const_t<MatrixType>, Mode>;
33 using ConjugateReturnType = TriangularView<const MatrixConjugateReturnType, Mode>;
34 using AdjointReturnType = TriangularView<const typename MatrixType::AdjointReturnType, TransposeMode>;
35 using TransposeReturnType = TriangularView<typename MatrixType::TransposeReturnType, TransposeMode>;
36 using ConstTransposeReturnType = TriangularView<const typename MatrixType::ConstTransposeReturnType, TransposeMode>;
37};
38
39template <typename MatrixType, unsigned int Mode>
40struct triangular_base_return_types<MatrixType, Mode, true> {
41 using MatrixConjugateReturnType = internal::remove_all_t<typename MatrixType::ConjugateReturnType>;
42 enum {
43 TriangularPart = int(Mode) & int(Upper | Lower),
44 TransposeMode = (int(Mode) & int(Upper) ? Lower : 0) | (int(Mode) & int(Lower) ? Upper : 0)
45 };
46 using ConstView = SelfAdjointView<std::add_const_t<MatrixType>, TriangularPart>;
47 using ConjugateReturnType = SelfAdjointView<const MatrixConjugateReturnType, TriangularPart>;
48 using AdjointReturnType = SelfAdjointView<const typename MatrixType::AdjointReturnType, TransposeMode>;
49 using TransposeReturnType = SelfAdjointView<typename MatrixType::TransposeReturnType, TransposeMode>;
50 using ConstTransposeReturnType = SelfAdjointView<const typename MatrixType::ConstTransposeReturnType, TransposeMode>;
51};
52
53template <unsigned int Mode, typename Expression>
54EIGEN_DEVICE_FUNC inline typename triangular_base_return_types<Expression, Mode>::ConstView
55make_triangular_base_cwise_view(const Expression& expression) {
56 using ReturnType = typename triangular_base_return_types<Expression, Mode>::ConstView;
57 return ReturnType(expression);
58}
59
60} // namespace internal
61
67template <typename Derived>
68class TriangularBase : public EigenBase<Derived> {
69 public:
70 enum {
71 Mode = internal::traits<Derived>::Mode,
72 TransposeMode = (int(Mode) & int(Upper) ? Lower : 0) | (int(Mode) & int(Lower) ? Upper : 0) |
73 (int(Mode) & int(UnitDiag)) | (int(Mode) & int(ZeroDiag)),
74 RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
75 ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
76 MaxRowsAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime,
77 MaxColsAtCompileTime = internal::traits<Derived>::MaxColsAtCompileTime,
79 SizeAtCompileTime = (internal::size_of_xpr_at_compile_time<Derived>::value),
83
84 MaxSizeAtCompileTime = internal::size_at_compile_time(internal::traits<Derived>::MaxRowsAtCompileTime,
85 internal::traits<Derived>::MaxColsAtCompileTime)
86
87 };
88 using Scalar = typename internal::traits<Derived>::Scalar;
89 using StorageKind = typename internal::traits<Derived>::StorageKind;
90 using StorageIndex = typename internal::traits<Derived>::StorageIndex;
91 using DenseMatrixType = typename internal::traits<Derived>::FullMatrixType;
92 using ExpressionType = typename internal::traits<Derived>::ExpressionType;
93 using DenseType = DenseMatrixType;
94 using Nested = const Derived&;
95 using ReturnTypes = internal::triangular_base_return_types<ExpressionType, Mode>;
96 using ConstView = typename ReturnTypes::ConstView;
97 using ConjugateReturnType = typename ReturnTypes::ConjugateReturnType;
98 using AdjointReturnType = typename ReturnTypes::AdjointReturnType;
99 using TransposeReturnType = typename ReturnTypes::TransposeReturnType;
100 using ConstTransposeReturnType = typename ReturnTypes::ConstTransposeReturnType;
101
102 EIGEN_DEVICE_FUNC inline TriangularBase() {
103 eigen_assert(!((int(Mode) & int(UnitDiag)) && (int(Mode) & int(ZeroDiag))));
104 }
105
106 EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return derived().nestedExpression().rows(); }
107 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return derived().nestedExpression().cols(); }
108 EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return rows() * cols(); }
109 EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return derived().nestedExpression().outerStride(); }
110 EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return derived().nestedExpression().innerStride(); }
111
112 // dummy resize function
113 EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) {
114 EIGEN_UNUSED_VARIABLE(rows);
115 EIGEN_UNUSED_VARIABLE(cols);
116 eigen_assert(rows == this->rows() && cols == this->cols());
117 }
118
120 EIGEN_DEVICE_FUNC void fill(const Scalar& value) { setConstant(value); }
121
123 EIGEN_DEVICE_FUNC Derived& setConstant(const Scalar& value) {
124 EIGEN_STATIC_ASSERT_LVALUE(Derived);
125 return derived() = DenseMatrixType::Constant(rows(), cols(), value);
126 }
127
129 EIGEN_DEVICE_FUNC Derived& setZero() { return setConstant(Scalar(0)); }
130
132 EIGEN_DEVICE_FUNC Derived& setOnes() { return setConstant(Scalar(1)); }
133
135 EIGEN_DEVICE_FUNC Derived& setRandom() {
136 EIGEN_STATIC_ASSERT_LVALUE(Derived);
137 return derived() = DenseMatrixType::Random(rows(), cols());
138 }
139
141 EIGEN_DEVICE_FUNC Derived& setIdentity() {
142 EIGEN_STATIC_ASSERT_LVALUE(Derived);
143 return derived() = DenseMatrixType::Identity(rows(), cols());
144 }
145
154 EIGEN_DEVICE_FUNC inline Scalar coeff(Index row, Index col) const {
155 check_coordinates_internal(row, col);
156 return derived().nestedExpression().coeff(row, col);
157 }
158
163 EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col) {
164 EIGEN_STATIC_ASSERT_LVALUE(Derived);
165 check_coordinates_internal(row, col);
166 return derived().nestedExpression().coeffRef(row, col);
167 }
168
171 template <typename Other>
172 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, Other& other) {
173 coeffRef(row, col) = other.coeff(row, col);
174 }
175
179 EIGEN_DEVICE_FUNC inline Scalar operator()(Index row, Index col) const {
180 check_coordinates(row, col);
181 return coeff(row, col);
182 }
183
185 EIGEN_DEVICE_FUNC inline Scalar& operator()(Index row, Index col) {
186 check_coordinates(row, col);
187 return coeffRef(row, col);
188 }
189
190#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
191 EIGEN_DEVICE_FUNC inline Scalar operator[](Index row, Index col) const { return operator()(row, col); }
192 EIGEN_DEVICE_FUNC inline Scalar& operator[](Index row, Index col) { return operator()(row, col); }
193#endif
194
195#ifndef EIGEN_PARSED_BY_DOXYGEN
196 EIGEN_DEVICE_FUNC constexpr inline const Derived& derived() const noexcept {
197 return *static_cast<const Derived*>(this);
198 }
199 EIGEN_DEVICE_FUNC constexpr inline Derived& derived() noexcept { return *static_cast<Derived*>(this); }
200#endif // not EIGEN_PARSED_BY_DOXYGEN
201
202 template <typename DenseDerived>
203 EIGEN_DEVICE_FUNC void evalTo(MatrixBase<DenseDerived>& other) const;
204 template <typename DenseDerived>
205 EIGEN_DEVICE_FUNC void evalToLazy(MatrixBase<DenseDerived>& other) const;
206
207 template <typename OtherDerived>
208 EIGEN_DEVICE_FUNC const Product<Derived, OtherDerived> operator*(const MatrixBase<OtherDerived>& rhs) const {
209 return Product<Derived, OtherDerived>(derived(), rhs.derived());
210 }
211
212 template <typename OtherDerived>
213 EIGEN_DEVICE_FUNC const Product<Derived, OtherDerived> operator*(const DiagonalBase<OtherDerived>& rhs) const {
215 }
216
223 template <typename OtherDerived>
224 EIGEN_DEVICE_FUNC const Product<Derived, OtherDerived> operator*(const TriangularBase<OtherDerived>& rhs) const {
226 }
227
228 template <typename OtherDerived,
229 std::enable_if_t<int(Mode) == int(OtherDerived::Mode) && (int(Mode) & int(UnitDiag)) == 0, int> = 0>
230 EIGEN_DEVICE_FUNC inline auto operator+(const TriangularBase<OtherDerived>& other) const {
231 return internal::make_triangular_base_cwise_view<Mode>(derived().nestedExpression() +
232 other.derived().nestedExpression());
233 }
234
235 template <typename OtherDerived,
236 std::enable_if_t<int(Mode) == int(OtherDerived::Mode) && (int(Mode) & int(UnitDiag)) == 0, int> = 0>
237 EIGEN_DEVICE_FUNC inline auto operator-(const TriangularBase<OtherDerived>& other) const {
238 return internal::make_triangular_base_cwise_view<Mode>(derived().nestedExpression() -
239 other.derived().nestedExpression());
240 }
241
242 // Sums with a diagonal matrix keep the view's structure: the result is the same view of the lazy dense sum.
243 // A unit or zero diagonal is implicit in the view and would swallow the diagonal term, so those modes have
244 // no such operator; a self-adjoint view needs a real diagonal to stay self-adjoint.
245
246 // The Mode_ = Mode parameter makes the condition depend on the operator's own template parameters, so an
247 // excluded mode removes the overload instead of failing the class instantiation.
248
250 template <typename OtherDerived, unsigned int Mode_ = Mode,
251 std::enable_if_t<(int(Mode_) & (int(UnitDiag) | int(ZeroDiag))) == 0, int> = 0>
252 EIGEN_DEVICE_FUNC inline auto operator+(const DiagonalBase<OtherDerived>& other) const {
253 return internal::make_triangular_base_cwise_view<Mode>(derived().nestedExpression() + other.derived());
254 }
255
258 template <typename OtherDerived, unsigned int Mode_ = Mode,
259 std::enable_if_t<(int(Mode_) & (int(UnitDiag) | int(ZeroDiag))) == 0, int> = 0>
260 EIGEN_DEVICE_FUNC inline auto operator-(const DiagonalBase<OtherDerived>& other) const {
261 return internal::make_triangular_base_cwise_view<Mode>(derived().nestedExpression() - other.derived());
262 }
263
266 template <typename OtherDerived, unsigned int Mode_ = Mode,
267 std::enable_if_t<(int(Mode_) & (int(UnitDiag) | int(ZeroDiag))) == 0, int> = 0>
268 friend EIGEN_DEVICE_FUNC inline auto operator+(const DiagonalBase<OtherDerived>& lhs, const Derived& rhs) {
269 return internal::make_triangular_base_cwise_view<Mode>(lhs.derived() + rhs.nestedExpression());
270 }
271
274 template <typename OtherDerived, unsigned int Mode_ = Mode,
275 std::enable_if_t<(int(Mode_) & (int(UnitDiag) | int(ZeroDiag))) == 0, int> = 0>
276 friend EIGEN_DEVICE_FUNC inline auto operator-(const DiagonalBase<OtherDerived>& lhs, const Derived& rhs) {
277 return internal::make_triangular_base_cwise_view<Mode>(lhs.derived() - rhs.nestedExpression());
278 }
279
280 template <typename OtherDerived>
281 friend EIGEN_DEVICE_FUNC const Product<OtherDerived, Derived> operator*(const MatrixBase<OtherDerived>& lhs,
282 const Derived& rhs) {
283 return Product<OtherDerived, Derived>(lhs.derived(), rhs);
284 }
285
286 template <typename OtherDerived>
287 friend EIGEN_DEVICE_FUNC const Product<OtherDerived, Derived> operator*(const DiagonalBase<OtherDerived>& lhs,
288 const Derived& rhs) {
289 return Product<OtherDerived, Derived>(lhs.derived(), rhs);
290 }
291
292 // Products with permutations (and their inverses) evaluate to a dense matrix: the permuted view has no
293 // triangular or self-adjoint structure Eigen could represent. They live here rather than next to the
294 // MatrixBase permutation operators so that every operator* a TriangularBase takes part in is in one place.
295
297 template <typename OtherDerived>
300 }
301
303 template <typename OtherDerived>
305 const InverseImpl<OtherDerived, PermutationStorage>& rhs) const {
306 return Product<Derived, Inverse<OtherDerived>>(derived(), rhs.derived());
307 }
308
310 template <typename OtherDerived>
312 const Derived& rhs) {
313 return Product<OtherDerived, Derived>(lhs.derived(), rhs);
314 }
315
317 template <typename OtherDerived>
318 friend EIGEN_DEVICE_FUNC const Product<Inverse<OtherDerived>, Derived> operator*(
319 const InverseImpl<OtherDerived, PermutationStorage>& lhs, const Derived& rhs) {
320 return Product<Inverse<OtherDerived>, Derived>(lhs.derived(), rhs);
321 }
322
324 EIGEN_DEVICE_FUNC inline const ConjugateReturnType conjugate() const {
325 return ConjugateReturnType(derived().nestedExpression().conjugate());
326 }
327
331 template <bool Cond>
332 EIGEN_DEVICE_FUNC inline std::conditional_t<Cond, ConjugateReturnType, ConstView> conjugateIf() const {
333 using ReturnType = std::conditional_t<Cond, ConjugateReturnType, ConstView>;
334 return ReturnType(derived().nestedExpression().template conjugateIf<Cond>());
335 }
336
338 EIGEN_DEVICE_FUNC inline const AdjointReturnType adjoint() const {
339 return AdjointReturnType(derived().nestedExpression().adjoint());
340 }
341
343 template <class Dummy = int, std::enable_if_t<Eigen::internal::is_lvalue<ExpressionType>::value, Dummy*> = nullptr>
344 EIGEN_DEVICE_FUNC inline TransposeReturnType transpose() {
345 typename ExpressionType::TransposeReturnType tmp(derived().nestedExpression());
346 return TransposeReturnType(tmp);
347 }
348
349 template <class Dummy = int>
350 EIGEN_DEPRECATED_WITH_REASON("Omit the implementation-only argument.")
351 EIGEN_DEVICE_FUNC inline TransposeReturnType
352 transpose(std::enable_if_t<Eigen::internal::is_lvalue<ExpressionType>::value, Dummy*>) {
353 return transpose<Dummy>();
354 }
355
357 EIGEN_DEVICE_FUNC inline const ConstTransposeReturnType transpose() const {
358 return ConstTransposeReturnType(derived().nestedExpression().transpose());
359 }
360
361 EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const {
362 DenseMatrixType res(rows(), cols());
363 evalToLazy(res);
364 return res;
365 }
366
367 protected:
368 void check_coordinates(Index row, Index col) const {
369 EIGEN_ONLY_USED_FOR_DEBUG(row);
370 EIGEN_ONLY_USED_FOR_DEBUG(col);
371 eigen_assert(col >= 0 && col < cols() && row >= 0 && row < rows());
372 const int mode = int(Mode) & ~SelfAdjoint;
373 EIGEN_ONLY_USED_FOR_DEBUG(mode);
374 eigen_assert((mode == Upper && col >= row) || (mode == Lower && col <= row) ||
375 ((mode == StrictlyUpper || mode == UnitUpper) && col > row) ||
376 ((mode == StrictlyLower || mode == UnitLower) && col < row));
377 }
378
379#ifdef EIGEN_INTERNAL_DEBUGGING
380 void check_coordinates_internal(Index row, Index col) const { check_coordinates(row, col); }
381#else
382 void check_coordinates_internal(Index, Index) const {}
383#endif
384};
385
404namespace internal {
405template <typename MatrixType, unsigned int Mode_>
406struct traits<TriangularView<MatrixType, Mode_>> : traits<MatrixType> {
407 using MatrixTypeNested = typename ref_selector<MatrixType>::non_const_type;
408 using MatrixTypeNestedNonRef = std::remove_reference_t<MatrixTypeNested>;
409 using MatrixTypeNestedCleaned = remove_all_t<MatrixTypeNested>;
410 using FullMatrixType = typename MatrixType::PlainObject;
411 using ExpressionType = MatrixType;
412 enum {
413 Mode = Mode_,
414 FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
415 Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits | FlagsLvalueBit) &
417 };
418};
419} // namespace internal
420
421template <typename MatrixType_, unsigned int Mode_, typename StorageKind>
422class TriangularViewImpl;
423
424template <typename MatrixType_, unsigned int Mode_>
425class TriangularView
426 : public TriangularViewImpl<MatrixType_, Mode_, typename internal::traits<MatrixType_>::StorageKind> {
427 public:
428 using Base = TriangularViewImpl<MatrixType_, Mode_, typename internal::traits<MatrixType_>::StorageKind>;
429 using Scalar = typename internal::traits<TriangularView>::Scalar;
430 using MatrixType = MatrixType_;
431
432 protected:
433 using MatrixTypeNested = typename internal::traits<TriangularView>::MatrixTypeNested;
434 using MatrixTypeNestedNonRef = typename internal::traits<TriangularView>::MatrixTypeNestedNonRef;
435
436 public:
437 using StorageKind = typename internal::traits<TriangularView>::StorageKind;
438 using NestedExpression = typename internal::traits<TriangularView>::MatrixTypeNestedCleaned;
439
440 enum {
441 Mode = Mode_,
442 Flags = internal::traits<TriangularView>::Flags,
443 TransposeMode = (int(Mode) & int(Upper) ? Lower : 0) | (int(Mode) & int(Lower) ? Upper : 0) |
444 (int(Mode) & int(UnitDiag)) | (int(Mode) & int(ZeroDiag)),
445 IsVectorAtCompileTime = false
446 };
447
448 EIGEN_DEVICE_FUNC explicit inline TriangularView(MatrixType& matrix) : m_matrix(matrix) {}
449
450 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TriangularView)
451
452
453 EIGEN_DEVICE_FUNC constexpr const NestedExpression& nestedExpression() const noexcept { return m_matrix; }
454
456 EIGEN_DEVICE_FUNC constexpr NestedExpression& nestedExpression() noexcept { return m_matrix; }
457
458 template <typename Other>
459 EIGEN_DEVICE_FUNC inline Solve<TriangularView, Other> solve(const MatrixBase<Other>& other) const {
460 return Solve<TriangularView, Other>(*this, other.derived());
461 }
462
463 using Base::solve;
464
470 EIGEN_STATIC_ASSERT((Mode & (UnitDiag | ZeroDiag)) == 0, PROGRAMMING_ERROR);
472 }
473
476 EIGEN_STATIC_ASSERT((Mode & (UnitDiag | ZeroDiag)) == 0, PROGRAMMING_ERROR);
478 }
479
482 EIGEN_DEVICE_FUNC Scalar determinant() const {
483 EIGEN_IF_CONSTEXPR (Mode & UnitDiag) {
484 return 1;
485 } else EIGEN_IF_CONSTEXPR (Mode & ZeroDiag) {
486 return 0;
487 } else {
488 return m_matrix.diagonal().prod();
489 }
490 }
491
492 protected:
493 MatrixTypeNested m_matrix;
494};
495
505template <typename MatrixType_, unsigned int Mode_>
506class TriangularViewImpl<MatrixType_, Mode_, Dense> : public TriangularBase<TriangularView<MatrixType_, Mode_>> {
507 public:
508 using TriangularViewType = TriangularView<MatrixType_, Mode_>;
509
510 using Base = TriangularBase<TriangularViewType>;
511 using Scalar = typename internal::traits<TriangularViewType>::Scalar;
512
513 using MatrixType = MatrixType_;
514 using DenseMatrixType = typename MatrixType::PlainObject;
515 using PlainObject = DenseMatrixType;
516
517 public:
518 using Base::derived;
519 using Base::evalToLazy;
520 using Base::operator*;
521
522 using StorageKind = typename internal::traits<TriangularViewType>::StorageKind;
523
524 enum { Mode = Mode_, Flags = internal::traits<TriangularViewType>::Flags };
525
527 template <typename Other>
528 EIGEN_DEVICE_FUNC TriangularViewType& operator+=(const DenseBase<Other>& other) {
529 internal::call_assignment_no_alias(derived(), other.derived(),
530 internal::add_assign_op<Scalar, typename Other::Scalar>());
531 return derived();
532 }
533
534 template <typename Other>
535 EIGEN_DEVICE_FUNC TriangularViewType& operator-=(const DenseBase<Other>& other) {
536 internal::call_assignment_no_alias(derived(), other.derived(),
537 internal::sub_assign_op<Scalar, typename Other::Scalar>());
538 return derived();
539 }
540
542 EIGEN_DEVICE_FUNC TriangularViewType& operator*=(const typename internal::traits<MatrixType>::Scalar& other) {
543 return *this = derived().nestedExpression() * other;
544 }
545
546 EIGEN_DEVICE_FUNC TriangularViewType& operator/=(const typename internal::traits<MatrixType>::Scalar& other) {
547 return *this = derived().nestedExpression() / other;
548 }
549
551 template <typename OtherDerived>
552 EIGEN_DEVICE_FUNC TriangularViewType& operator=(const TriangularBase<OtherDerived>& other);
553
555 template <typename OtherDerived>
556 EIGEN_DEVICE_FUNC TriangularViewType& operator=(const MatrixBase<OtherDerived>& other);
557
558#ifndef EIGEN_PARSED_BY_DOXYGEN
559 EIGEN_DEVICE_FUNC TriangularViewType& operator=(const TriangularViewImpl& other) {
560 return *this = other.derived().nestedExpression();
561 }
562
563 template <typename OtherDerived>
565 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void lazyAssign(const TriangularBase<OtherDerived>& other);
566
567 template <typename OtherDerived>
569 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void lazyAssign(const MatrixBase<OtherDerived>& other);
570#endif
571
572 // Scaling a unit triangular view would break its implicit unit diagonal, so only non-unit modes participate.
573 template <unsigned int M = Mode, std::enable_if_t<(M & UnitDiag) == 0, int> = 0>
574 EIGEN_DEVICE_FUNC const TriangularView<
575 const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(MatrixType, Scalar, internal::scalar_product_op), Mode>
576 operator*(const Scalar& s) const {
577 return (derived().nestedExpression() * s).template triangularView<Mode>();
578 }
579
580 template <unsigned int M = Mode, std::enable_if_t<(M & UnitDiag) == 0, int> = 0>
581 friend EIGEN_DEVICE_FUNC const TriangularView<
582 const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar, MatrixType, internal::scalar_product_op), Mode>
583 operator*(const Scalar& s, const TriangularViewImpl& mat) {
584 return (s * mat.derived().nestedExpression()).template triangularView<Mode>();
585 }
586
610 template <int Side, typename Other>
611 inline const internal::triangular_solve_retval<Side, TriangularViewType, Other> solve(
612 const MatrixBase<Other>& other) const;
613
623 template <int Side, typename OtherDerived>
624 EIGEN_DEVICE_FUNC void solveInPlace(const MatrixBase<OtherDerived>& other) const;
625
626 template <typename OtherDerived>
627 EIGEN_DEVICE_FUNC void solveInPlace(const MatrixBase<OtherDerived>& other) const {
628 return solveInPlace<OnTheLeft>(other);
629 }
630
643 EIGEN_DEVICE_FUNC void inverseInPlace();
644
646 template <typename OtherDerived>
647 EIGEN_DEVICE_FUNC
648#ifdef EIGEN_PARSED_BY_DOXYGEN
649 void
650 swap(TriangularBase<OtherDerived>& other)
651#else
652 void
653 swap(TriangularBase<OtherDerived> const& other)
654#endif
655 {
656 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
657 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
658 }
659
661 template <typename OtherDerived>
663 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void swap(MatrixBase<OtherDerived> const& other) {
664 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
665 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
666 }
667
668 template <typename RhsType, typename DstType>
669 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _solve_impl(const RhsType& rhs, DstType& dst) const {
670 if (!internal::is_same_dense(dst, rhs)) dst = rhs;
671 this->solveInPlace(dst);
672 }
673
674 template <typename ProductType>
675 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha,
676 bool beta);
677
678 protected:
679 EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl)
680 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl)
681};
682
683/***************************************************************************
684 * Implementation of triangular evaluation/assignment
685 ***************************************************************************/
686
687#ifndef EIGEN_PARSED_BY_DOXYGEN
688// FIXME should we keep that possibility
689template <typename MatrixType, unsigned int Mode>
690template <typename OtherDerived>
691EIGEN_DEVICE_FUNC inline TriangularView<MatrixType, Mode>& TriangularViewImpl<MatrixType, Mode, Dense>::operator=(
692 const MatrixBase<OtherDerived>& other) {
693 internal::call_assignment_no_alias(derived(), other.derived(),
694 internal::assign_op<Scalar, typename OtherDerived::Scalar>());
695 return derived();
696}
697
698// FIXME should we keep that possibility
699template <typename MatrixType, unsigned int Mode>
700template <typename OtherDerived>
701EIGEN_DEVICE_FUNC void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(const MatrixBase<OtherDerived>& other) {
702 internal::call_assignment_no_alias(derived(), other.template triangularView<Mode>());
703}
704
705template <typename MatrixType, unsigned int Mode>
706template <typename OtherDerived>
707EIGEN_DEVICE_FUNC inline TriangularView<MatrixType, Mode>& TriangularViewImpl<MatrixType, Mode, Dense>::operator=(
708 const TriangularBase<OtherDerived>& other) {
709 eigen_assert(Mode == int(OtherDerived::Mode));
710 internal::call_assignment(derived(), other.derived());
711 return derived();
712}
713
714template <typename MatrixType, unsigned int Mode>
715template <typename OtherDerived>
716EIGEN_DEVICE_FUNC void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(
717 const TriangularBase<OtherDerived>& other) {
718 eigen_assert(Mode == int(OtherDerived::Mode));
719 internal::call_assignment_no_alias(derived(), other.derived());
720}
721#endif
722
723/***************************************************************************
724 * Implementation of TriangularBase methods
725 ***************************************************************************/
726
729template <typename Derived>
730template <typename DenseDerived>
731EIGEN_DEVICE_FUNC void TriangularBase<Derived>::evalTo(MatrixBase<DenseDerived>& other) const {
732 evalToLazy(other.derived());
733}
734
735/***************************************************************************
736 * Implementation of TriangularView methods
737 ***************************************************************************/
738
739/***************************************************************************
740 * Implementation of MatrixBase methods
741 ***************************************************************************/
742
754template <typename Derived>
755template <unsigned int Mode>
756EIGEN_DEVICE_FUNC constexpr typename MatrixBase<Derived>::template TriangularViewReturnType<Mode>::Type
757MatrixBase<Derived>::triangularView() {
758 return typename TriangularViewReturnType<Mode>::Type(derived());
759}
760
762template <typename Derived>
763template <unsigned int Mode>
764EIGEN_DEVICE_FUNC constexpr typename MatrixBase<Derived>::template ConstTriangularViewReturnType<Mode>::Type
765MatrixBase<Derived>::triangularView() const {
766 return typename ConstTriangularViewReturnType<Mode>::Type(derived());
767}
768
774template <typename Derived>
775bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const {
776 RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
777 for (Index j = 0; j < cols(); ++j) {
778 Index maxi = numext::mini(j, rows() - 1);
779 for (Index i = 0; i <= maxi; ++i) {
780 RealScalar absValue = numext::abs(coeff(i, j));
781 if (absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
782 }
783 }
784 RealScalar threshold = maxAbsOnUpperPart * prec;
785 for (Index j = 0; j < cols(); ++j)
786 for (Index i = j + 1; i < rows(); ++i)
787 if (numext::abs(coeff(i, j)) > threshold) return false;
788 return true;
789}
790
796template <typename Derived>
797bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const {
798 RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1);
799 for (Index j = 0; j < cols(); ++j)
800 for (Index i = j; i < rows(); ++i) {
801 RealScalar absValue = numext::abs(coeff(i, j));
802 if (absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
803 }
804 RealScalar threshold = maxAbsOnLowerPart * prec;
805 for (Index j = 1; j < cols(); ++j) {
806 // Rows [0, min(j, rows())) of column j lie strictly above the diagonal. For a column past the diagonal block of a
807 // wide matrix that is the whole column, so the bound is rows(), not rows() - 1.
808 Index maxi = numext::mini(j, rows());
809 for (Index i = 0; i < maxi; ++i)
810 if (numext::abs(coeff(i, j)) > threshold) return false;
811 }
812 return true;
813}
814
815/***************************************************************************
816****************************************************************************
817* Evaluators and Assignment of triangular expressions
818***************************************************************************
819***************************************************************************/
820
821namespace internal {
822
823// TODO: currently a triangular expression has the form TriangularView<.,.>
824// in the future triangular-ness should be defined by the expression traits
825// such that Transpose<TriangularView<.,.> > is valid. (currently TriangularBase::transpose() is overloaded to make
826// it work)
827template <typename MatrixType, unsigned int Mode>
828struct evaluator_traits<TriangularView<MatrixType, Mode>> {
829 using Kind = typename storage_kind_to_evaluator_kind<typename MatrixType::StorageKind>::Kind;
830 using Shape = typename glue_shapes<typename evaluator_traits<MatrixType>::Shape, TriangularShape>::type;
831};
832
833template <typename MatrixType, unsigned int Mode>
834struct unary_evaluator<TriangularView<MatrixType, Mode>, IndexBased> : evaluator<internal::remove_all_t<MatrixType>> {
835 using XprType = TriangularView<MatrixType, Mode>;
836 using Base = evaluator<internal::remove_all_t<MatrixType>>;
837 EIGEN_DEVICE_FUNC unary_evaluator(const XprType& xpr) : Base(xpr.nestedExpression()) {}
838};
839
840// Additional assignment kinds:
841struct Triangular2Triangular {};
842struct Triangular2Dense {};
843struct Dense2Triangular {};
844
845template <typename Kernel, unsigned int Mode, int UnrollCount, bool SetOpposite>
846struct triangular_assignment_loop;
847
853template <int UpLo, int Mode, int SetOpposite, typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor,
854 int Version = Specialized>
855class triangular_dense_assignment_kernel
856 : public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> {
857 protected:
858 using Base = generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version>;
859 using DstXprType = typename Base::DstXprType;
860 using SrcXprType = typename Base::SrcXprType;
861 using Base::m_dst;
862 using Base::m_functor;
863 using Base::m_src;
864
865 public:
866 using DstEvaluatorType = typename Base::DstEvaluatorType;
867 using SrcEvaluatorType = typename Base::SrcEvaluatorType;
868 using Scalar = typename Base::Scalar;
869 using AssignmentTraits = typename Base::AssignmentTraits;
870
871 EIGEN_DEVICE_FUNC triangular_dense_assignment_kernel(DstEvaluatorType& dst, const SrcEvaluatorType& src,
872 const Functor& func, DstXprType& dstExpr)
873 : Base(dst, src, func, dstExpr) {}
874
875#ifdef EIGEN_INTERNAL_DEBUGGING
876 EIGEN_DEVICE_FUNC void assignCoeff(Index row, Index col) {
877 eigen_internal_assert(row != col);
878 Base::assignCoeff(row, col);
879 }
880#else
881 using Base::assignCoeff;
882#endif
883
884 EIGEN_DEVICE_FUNC void assignDiagonalCoeff(Index id) {
885 EIGEN_IF_CONSTEXPR (Mode == UnitDiag && SetOpposite) {
886 m_functor.assignCoeff(m_dst.coeffRef(id, id), Scalar(1));
887 } else EIGEN_IF_CONSTEXPR (Mode == ZeroDiag && SetOpposite) {
888 m_functor.assignCoeff(m_dst.coeffRef(id, id), Scalar(0));
889 } else EIGEN_IF_CONSTEXPR (Mode == 0) {
890 Base::assignCoeff(id, id);
891 }
892 }
893
894 EIGEN_DEVICE_FUNC void assignOppositeCoeff(Index row, Index col) {
895 eigen_internal_assert(row != col);
896 EIGEN_IF_CONSTEXPR (SetOpposite) {
897 m_functor.assignCoeff(m_dst.coeffRef(row, col), Scalar(0));
898 }
899 }
900};
901
902template <int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType, typename Functor>
903EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_triangular_assignment_loop(DstXprType& dst, const SrcXprType& src,
904 const Functor& func) {
905 using DstEvaluatorType = evaluator<DstXprType>;
906 using SrcEvaluatorType = evaluator<SrcXprType>;
907
908 SrcEvaluatorType srcEvaluator(src);
909
910 Index dstRows = src.rows();
911 Index dstCols = src.cols();
912 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
913 DstEvaluatorType dstEvaluator(dst);
914
915 using Kernel = triangular_dense_assignment_kernel<Mode&(Lower | Upper), Mode&(UnitDiag | ZeroDiag | SelfAdjoint),
916 SetOpposite, DstEvaluatorType, SrcEvaluatorType, Functor>;
917 Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
918
919 enum {
920 unroll = DstXprType::SizeAtCompileTime != Dynamic && SrcEvaluatorType::CoeffReadCost < HugeCost &&
921 DstXprType::SizeAtCompileTime *
922 (int(DstEvaluatorType::CoeffReadCost) + int(SrcEvaluatorType::CoeffReadCost)) / 2 <=
923 EIGEN_UNROLLING_LIMIT
924 };
925
926 triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) : Dynamic, SetOpposite>::run(
927 kernel);
928}
929
930template <int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType>
931EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_triangular_assignment_loop(DstXprType& dst, const SrcXprType& src) {
932 call_triangular_assignment_loop<Mode, SetOpposite>(
933 dst, src, internal::assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>());
934}
935
936template <>
937struct AssignmentKind<TriangularShape, TriangularShape> {
938 using Kind = Triangular2Triangular;
939};
940template <>
941struct AssignmentKind<DenseShape, TriangularShape> {
942 using Kind = Triangular2Dense;
943};
944template <>
945struct AssignmentKind<TriangularShape, DenseShape> {
946 using Kind = Dense2Triangular;
947};
948
949template <typename Shape>
950struct is_dense_structured_shape
951 : bool_constant<std::is_same<Shape, TriangularShape>::value || std::is_same<Shape, SelfAdjointShape>::value> {};
952
953template <typename Lhs, typename Rhs>
954struct is_dense_structured_diagonal_product
955 : bool_constant<(is_dense_structured_shape<typename evaluator_traits<Lhs>::Shape>::value &&
956 std::is_same<typename evaluator_traits<Rhs>::Shape, DiagonalShape>::value) ||
957 (std::is_same<typename evaluator_traits<Lhs>::Shape, DiagonalShape>::value &&
958 is_dense_structured_shape<typename evaluator_traits<Rhs>::Shape>::value)> {};
959
960template <typename DstXprType, typename SrcXprType, typename Functor>
961struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Triangular> {
962 EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src, const Functor& func) {
963 eigen_assert(int(DstXprType::Mode) == int(SrcXprType::Mode));
964
965 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
966 }
967};
968
969template <typename DstXprType, typename SrcXprType, typename Functor>
970struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Dense> {
971 EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src, const Functor& func) {
972 call_triangular_assignment_loop<SrcXprType::Mode, (int(SrcXprType::Mode) & int(SelfAdjoint)) == 0>(dst, src, func);
973 }
974};
975
976template <typename DstXprType, typename SrcXprType, typename Functor>
977struct Assignment<DstXprType, SrcXprType, Functor, Dense2Triangular> {
978 EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src, const Functor& func) {
979 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
980 }
981};
982
983template <typename Kernel, unsigned int Mode, int UnrollCount, bool SetOpposite>
984struct triangular_assignment_loop {
985 // FIXME: this is not very clean, perhaps this information should be provided by the kernel?
986 using DstEvaluatorType = typename Kernel::DstEvaluatorType;
987 using DstXprType = typename DstEvaluatorType::XprType;
988
989 enum {
990 col = (UnrollCount - 1) / DstXprType::RowsAtCompileTime,
991 row = (UnrollCount - 1) % DstXprType::RowsAtCompileTime
992 };
993
994 using Scalar = typename Kernel::Scalar;
995
996 EIGEN_DEVICE_FUNC static inline void run(Kernel& kernel) {
997 triangular_assignment_loop<Kernel, Mode, UnrollCount - 1, SetOpposite>::run(kernel);
998
999 if (row == col)
1000 kernel.assignDiagonalCoeff(row);
1001 else if (((Mode & Lower) && row > col) || ((Mode & Upper) && row < col))
1002 kernel.assignCoeff(row, col);
1003 else EIGEN_IF_CONSTEXPR (SetOpposite) {
1004 kernel.assignOppositeCoeff(row, col);
1005 }
1006 }
1007};
1008
1009// prevent buggy user code from causing an infinite recursion
1010template <typename Kernel, unsigned int Mode, bool SetOpposite>
1011struct triangular_assignment_loop<Kernel, Mode, 0, SetOpposite> {
1012 EIGEN_DEVICE_FUNC static inline void run(Kernel&) {}
1013};
1014
1015// TODO: experiment with a recursive assignment procedure splitting the current
1016// triangular part into one rectangular and two triangular parts.
1017
1018template <typename Kernel, unsigned int Mode, bool SetOpposite>
1019struct triangular_assignment_loop<Kernel, Mode, Dynamic, SetOpposite> {
1020 using Scalar = typename Kernel::Scalar;
1021 using DstEvaluatorType = typename Kernel::DstEvaluatorType;
1022 using AssignmentTraits = typename Kernel::AssignmentTraits;
1023
1024 enum {
1025 IsRowMajor = (int(DstEvaluatorType::Flags) & RowMajorBit) != 0,
1026 // In col-major: inner=row, outer=col. Upper means row<col i.e. inner<outer -> active before diagonal.
1027 // In row-major: inner=col, outer=row. Upper means row<col i.e. inner>outer -> active after diagonal.
1028 // So ActiveBeforeDiag = (Upper XOR IsRowMajor).
1029 ActiveBeforeDiag = (bool(Mode & Upper) != bool(IsRowMajor))
1030 };
1031
1032 // Compile-time outer/inner to row/col mapping. These constant-fold away entirely:
1033 // ColMajor: row(outer,i) -> i, col(outer,i) -> outer
1034 // RowMajor: row(outer,i) -> outer, col(outer,i) -> i
1035 static constexpr Index row(Index outer, Index inner) { return IsRowMajor ? outer : inner; }
1036 static constexpr Index col(Index outer, Index inner) { return IsRowMajor ? inner : outer; }
1037
1038 // Iterates in outer/inner order matching the storage layout for cache friendliness.
1039 // Unlike the old code (which always iterated outer=col, inner=row), this gives
1040 // contiguous memory access for both ColMajor and RowMajor storage.
1041 // Simple scalar loops allow GCC to recognize memcpy/memset idioms and Clang to auto-vectorize.
1042 // Uses a single running index 'i' per column (not separate loop variables) so the compiler
1043 // can track the continuous progression and optimize register allocation.
1044 EIGEN_DEVICE_FUNC static inline void run(Kernel& kernel) {
1045 const Index outerSize = IsRowMajor ? kernel.rows() : kernel.cols();
1046 const Index innerSize = IsRowMajor ? kernel.cols() : kernel.rows();
1047
1048 for (Index outer = 0; outer < outerSize; ++outer) {
1049 const Index maxi = numext::mini(outer, innerSize);
1050 Index i = 0;
1051
1052 EIGEN_IF_CONSTEXPR (ActiveBeforeDiag) {
1053 for (; i < maxi; ++i) kernel.assignCoeff(row(outer, i), col(outer, i));
1054 } else EIGEN_IF_CONSTEXPR (SetOpposite) {
1055 for (; i < maxi; ++i) kernel.assignOppositeCoeff(row(outer, i), col(outer, i));
1056 } else {
1057 i = maxi;
1058 }
1059
1060 if (i < innerSize) kernel.assignDiagonalCoeff(i++);
1061
1062 EIGEN_IF_CONSTEXPR (!ActiveBeforeDiag) {
1063 for (; i < innerSize; ++i) kernel.assignCoeff(row(outer, i), col(outer, i));
1064 } else EIGEN_IF_CONSTEXPR (SetOpposite) {
1065 for (; i < innerSize; ++i) kernel.assignOppositeCoeff(row(outer, i), col(outer, i));
1066 }
1067 }
1068 }
1069};
1070
1071} // end namespace internal
1072
1075template <typename Derived>
1076template <typename DenseDerived>
1078 other.derived().resize(this->rows(), this->cols());
1079 internal::call_triangular_assignment_loop<Derived::Mode,
1080 (int(Derived::Mode) & int(SelfAdjoint)) == 0 /* SetOpposite */>(
1081 other.derived(), derived().nestedExpression());
1082}
1083
1084namespace internal {
1085
1086template <bool UseTriangularAssignmentLoop>
1087struct triangular_product_assignment_dispatcher {
1088 template <typename DstXprType, typename SrcXprType, typename Functor, typename Scalar>
1089 static void run(DstXprType& dst, const SrcXprType& src, const Functor&, const Scalar& alpha, bool beta) {
1090 if (!beta) {
1091 Index dstRows = src.rows();
1092 Index dstCols = src.cols();
1093 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
1094 }
1095
1096 dst._assignProduct(src, alpha, beta);
1097 }
1098};
1099
1100// Underlying-storage data pointer for the diagonal operand of a structured x diagonal
1101// product, or nullptr for non-diagonal operands. The structured (triangular/selfadjoint)
1102// operand can safely share storage with dst because the kernel reads each (row, col) cell
1103// before writing it; only diagonal/dst overlap can corrupt later reads via the diagonal
1104// entries that have already been written.
1105template <typename Op>
1106EIGEN_DEVICE_FUNC inline const void* diagonal_operand_data(const Op& op, DiagonalShape) {
1107 return extract_data(op.diagonal());
1108}
1109template <typename Op, typename Shape>
1110EIGEN_DEVICE_FUNC inline const void* diagonal_operand_data(const Op& /*op*/, Shape) {
1111 return nullptr;
1112}
1113
1114template <typename DstXprType, typename SrcXprType>
1115EIGEN_DEVICE_FUNC inline bool structured_diagonal_product_aliases(const DstXprType& dst, const SrcXprType& src) {
1116 const void* dst_data = dst.nestedExpression().data();
1117 if (dst_data == nullptr) return false;
1118 const void* lhs_diag_data =
1119 diagonal_operand_data(src.lhs(), typename evaluator_traits<typename SrcXprType::Lhs>::Shape{});
1120 const void* rhs_diag_data =
1121 diagonal_operand_data(src.rhs(), typename evaluator_traits<typename SrcXprType::Rhs>::Shape{});
1122 return (lhs_diag_data != nullptr && lhs_diag_data == dst_data) ||
1123 (rhs_diag_data != nullptr && rhs_diag_data == dst_data);
1124}
1125
1126template <>
1127struct triangular_product_assignment_dispatcher<true> {
1128 template <typename DstXprType, typename SrcXprType, typename Functor, typename Scalar>
1129 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, const Functor& func,
1130 const Scalar& alpha, bool beta) {
1131 EIGEN_UNUSED_VARIABLE(alpha);
1132 EIGEN_UNUSED_VARIABLE(beta);
1133 EIGEN_STATIC_ASSERT((int(DstXprType::Mode) & int(UnitDiag)) == 0,
1134 WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED);
1135 // The triangular assignment loop reads src.coeff(row, col) lazily while writing
1136 // dst.coeffRef(row, col). When the diagonal operand of the product shares storage with
1137 // dst (e.g.
1138 // A.triangularView<Upper>() = A.diagonal().asDiagonal() * A.triangularView<Upper>())
1139 // the diagonal entries already written in earlier columns would feed back as modified
1140 // values, corrupting later reads. Materialize the source into a temporary first when
1141 // overlap is detected at run time. The structured (triangular/selfadjoint) operand may
1142 // safely alias dst because the kernel reads each cell before writing it.
1143 if (structured_diagonal_product_aliases(dst, src)) {
1144 typename SrcXprType::PlainObject tmp(src);
1145 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, tmp, func);
1146 } else {
1147 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func);
1148 }
1149 }
1150};
1151
1152// Triangular = Product
1153template <typename DstXprType, typename Lhs, typename Rhs, typename Scalar>
1154struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
1155 internal::assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>, Dense2Triangular> {
1156 using SrcXprType = Product<Lhs, Rhs, DefaultProduct>;
1157 static void run(DstXprType& dst, const SrcXprType& src,
1158 const internal::assign_op<Scalar, typename SrcXprType::Scalar>& func) {
1159 enum { UseTriangularAssignmentLoop = is_dense_structured_diagonal_product<Lhs, Rhs>::value };
1160 triangular_product_assignment_dispatcher<UseTriangularAssignmentLoop>::run(dst, src, func, Scalar(1), false);
1161 }
1162};
1163
1164// Triangular += Product
1165template <typename DstXprType, typename Lhs, typename Rhs, typename Scalar>
1166struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
1167 internal::add_assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
1168 Dense2Triangular> {
1169 using SrcXprType = Product<Lhs, Rhs, DefaultProduct>;
1170 static void run(DstXprType& dst, const SrcXprType& src,
1171 const internal::add_assign_op<Scalar, typename SrcXprType::Scalar>& func) {
1172 enum { UseTriangularAssignmentLoop = is_dense_structured_diagonal_product<Lhs, Rhs>::value };
1173 triangular_product_assignment_dispatcher<UseTriangularAssignmentLoop>::run(dst, src, func, Scalar(1), true);
1174 }
1175};
1176
1177// Triangular -= Product
1178template <typename DstXprType, typename Lhs, typename Rhs, typename Scalar>
1179struct Assignment<DstXprType, Product<Lhs, Rhs, DefaultProduct>,
1180 internal::sub_assign_op<Scalar, typename Product<Lhs, Rhs, DefaultProduct>::Scalar>,
1181 Dense2Triangular> {
1182 using SrcXprType = Product<Lhs, Rhs, DefaultProduct>;
1183 static void run(DstXprType& dst, const SrcXprType& src,
1184 const internal::sub_assign_op<Scalar, typename SrcXprType::Scalar>& func) {
1185 enum { UseTriangularAssignmentLoop = is_dense_structured_diagonal_product<Lhs, Rhs>::value };
1186 triangular_product_assignment_dispatcher<UseTriangularAssignmentLoop>::run(dst, src, func, Scalar(-1), true);
1187 }
1188};
1189
1190} // end namespace internal
1191
1192} // end namespace Eigen
1193
1194#endif // EIGEN_TRIANGULARMATRIX_H
Base class for all dense matrices, vectors, and arrays.
Definition DenseBase.h:45
void resize(Index newSize)
Definition DenseBase.h:228
Base class for diagonal matrices and expressions.
Definition DiagonalMatrix.h:34
const Derived & derived() const
Definition DiagonalMatrix.h:60
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
bool isLowerTriangular(const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition TriangularMatrix.h:797
bool isUpperTriangular(const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition TriangularMatrix.h:775
const CwiseBinaryOp< internal::scalar_sum_op< Scalar, typename OtherDerived::Scalar >, const MatrixWrapper< ExpressionType >, const OtherDerived > operator+(const Eigen::MatrixBase< OtherDerived > &other) const
Base class for permutations.
Definition PermutationMatrix.h:92
Expression of the product of two arbitrary matrices or vectors.
Definition Product.h:203
Expression of a selfadjoint matrix from a triangular part of a dense matrix.
Definition SelfAdjointView.h:54
Pseudo expression representing a solving operation.
Definition Solve.h:63
Base class for triangular part in a matrix.
Definition TriangularMatrix.h:68
const Product< Derived, OtherDerived > operator*(const PermutationBase< OtherDerived > &rhs) const
Definition TriangularMatrix.h:298
const Product< Derived, OtherDerived > operator*(const TriangularBase< OtherDerived > &rhs) const
Definition TriangularMatrix.h:224
void copyCoeff(Index row, Index col, Other &other)
Definition TriangularMatrix.h:172
Derived & setConstant(const Scalar &value)
Definition TriangularMatrix.h:123
Scalar & coeffRef(Index row, Index col)
Definition TriangularMatrix.h:163
const AdjointReturnType adjoint() const
Definition TriangularMatrix.h:338
Derived & setOnes()
Definition TriangularMatrix.h:132
@ SizeAtCompileTime
Definition TriangularMatrix.h:79
const Product< Derived, Inverse< OtherDerived > > operator*(const InverseImpl< OtherDerived, PermutationStorage > &rhs) const
Definition TriangularMatrix.h:304
void evalTo(MatrixBase< DenseDerived > &other) const
Definition TriangularMatrix.h:731
Derived & setRandom()
Definition TriangularMatrix.h:135
const ConstTransposeReturnType transpose() const
Definition TriangularMatrix.h:357
auto operator-(const DiagonalBase< OtherDerived > &other) const
Definition TriangularMatrix.h:260
Scalar & operator()(Index row, Index col)
Definition TriangularMatrix.h:185
Derived & setIdentity()
Definition TriangularMatrix.h:141
friend const Product< OtherDerived, Derived > operator*(const PermutationBase< OtherDerived > &lhs, const Derived &rhs)
Definition TriangularMatrix.h:311
Scalar operator()(Index row, Index col) const
Definition TriangularMatrix.h:179
friend auto operator-(const DiagonalBase< OtherDerived > &lhs, const Derived &rhs)
Definition TriangularMatrix.h:276
const ConjugateReturnType conjugate() const
Definition TriangularMatrix.h:324
void evalToLazy(MatrixBase< DenseDerived > &other) const
Definition TriangularMatrix.h:1077
Derived & setZero()
Definition TriangularMatrix.h:129
friend const Product< Inverse< OtherDerived >, Derived > operator*(const InverseImpl< OtherDerived, PermutationStorage > &lhs, const Derived &rhs)
Definition TriangularMatrix.h:318
TransposeReturnType transpose()
Definition TriangularMatrix.h:344
void fill(const Scalar &value)
Definition TriangularMatrix.h:120
std::conditional_t< Cond, ConjugateReturnType, ConstView > conjugateIf() const
Definition TriangularMatrix.h:332
Scalar coeff(Index row, Index col) const
Definition TriangularMatrix.h:154
auto operator+(const DiagonalBase< OtherDerived > &other) const
Definition TriangularMatrix.h:252
TriangularViewType & operator*=(const typename internal::traits< MatrixType >::Scalar &other)
Definition TriangularMatrix.h:542
TriangularViewType & operator+=(const DenseBase< Other > &other)
Definition TriangularMatrix.h:528
TriangularViewType & operator/=(const typename internal::traits< MatrixType >::Scalar &other)
Definition TriangularMatrix.h:546
TriangularViewType & operator-=(const DenseBase< Other > &other)
Definition TriangularMatrix.h:535
TriangularViewType & operator=(const TriangularBase< OtherDerived > &other)
EIGEN_DEPRECATED void swap(MatrixBase< OtherDerived > const &other)
Definition TriangularMatrix.h:663
TriangularViewType & operator=(const MatrixBase< OtherDerived > &other)
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:650
Expression of a triangular part in a matrix.
Definition TriangularMatrix.h:426
Scalar determinant() const
Definition TriangularMatrix.h:482
constexpr const NestedExpression & nestedExpression() const noexcept
Definition TriangularMatrix.h:453
constexpr NestedExpression & nestedExpression() noexcept
Definition TriangularMatrix.h:456
const SelfAdjointView< MatrixTypeNestedNonRef, Mode > selfadjointView() const
Definition TriangularMatrix.h:475
SelfAdjointView< MatrixTypeNestedNonRef, Mode > selfadjointView()
Definition TriangularMatrix.h:469
@ StrictlyLower
Definition Constants.h:224
@ UnitDiag
Definition Constants.h:216
@ StrictlyUpper
Definition Constants.h:226
@ UnitLower
Definition Constants.h:220
@ ZeroDiag
Definition Constants.h:218
@ SelfAdjoint
Definition Constants.h:228
@ UnitUpper
Definition Constants.h:222
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
constexpr unsigned int PacketAccessBit
Definition Constants.h:98
constexpr unsigned int DirectAccessBit
Definition Constants.h:160
constexpr unsigned int LinearAccessBit
Definition Constants.h:134
constexpr unsigned int LvalueBit
Definition Constants.h:149
constexpr unsigned int RowMajorBit
Definition Constants.h:71
Definition Constants.h:542
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:44