$darkmode
Eigen  5.0.1-dev
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 
17 namespace Eigen {
18 
19 namespace internal {
20 
21 template <int Side, typename TriangularType, typename Rhs>
22 struct triangular_solve_retval;
23 
24 }
25 
31 template <typename Derived>
32 class 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 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 #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 
145 namespace internal {
146 template <typename MatrixType, unsigned int Mode_>
147 struct 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) &
158  };
159 };
160 } // namespace internal
161 
162 template <typename MatrixType_, unsigned int Mode_, typename StorageKind>
163 class TriangularViewImpl;
164 
165 template <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 constexpr Index rows() const noexcept { return m_matrix.rows(); }
199  EIGEN_DEVICE_FUNC constexpr Index cols() const 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 
207  typedef TriangularView<const MatrixConjugateReturnType, Mode> ConjugateReturnType;
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 
296 template <typename MatrixType_, unsigned int Mode_>
297 class 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>
377  EIGEN_DEVICE_FUNC TriangularViewType& operator=(const TriangularBase<OtherDerived>& other);
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>
406  friend EIGEN_DEVICE_FUNC const Product<OtherDerived, TriangularViewType> operator*(
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
499 template <typename MatrixType, unsigned int Mode>
500 template <typename OtherDerived>
501 EIGEN_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
509 template <typename MatrixType, unsigned int Mode>
510 template <typename OtherDerived>
511 EIGEN_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 
515 template <typename MatrixType, unsigned int Mode>
516 template <typename OtherDerived>
517 EIGEN_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 
524 template <typename MatrixType, unsigned int Mode>
525 template <typename OtherDerived>
526 EIGEN_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 
539 template <typename Derived>
540 template <typename DenseDerived>
541 EIGEN_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 
564 template <typename Derived>
565 template <unsigned int Mode>
566 EIGEN_DEVICE_FUNC typename MatrixBase<Derived>::template TriangularViewReturnType<Mode>::Type
568  return typename TriangularViewReturnType<Mode>::Type(derived());
569 }
570 
572 template <typename Derived>
573 template <unsigned int Mode>
574 EIGEN_DEVICE_FUNC typename MatrixBase<Derived>::template ConstTriangularViewReturnType<Mode>::Type
576  return typename ConstTriangularViewReturnType<Mode>::Type(derived());
577 }
578 
584 template <typename Derived>
585 bool 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 
606 template <typename Derived>
607 bool 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 
629 namespace 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)
635 template <typename MatrixType, unsigned int Mode>
636 struct 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 
641 template <typename MatrixType, unsigned int Mode>
642 struct 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:
649 struct Triangular2Triangular {};
650 struct Triangular2Dense {};
651 struct Dense2Triangular {};
652 
653 template <typename Kernel, unsigned int Mode, int UnrollCount, bool ClearOpposite>
654 struct triangular_assignment_loop;
655 
661 template <int UpLo, int Mode, int SetOpposite, typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor,
662  int Version = Specialized>
663 class 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 
707 template <int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType, typename Functor>
708 EIGEN_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 
736 template <int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType>
737 EIGEN_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 
742 template <>
743 struct AssignmentKind<TriangularShape, TriangularShape> {
744  typedef Triangular2Triangular Kind;
745 };
746 template <>
747 struct AssignmentKind<DenseShape, TriangularShape> {
748  typedef Triangular2Dense Kind;
749 };
750 template <>
751 struct AssignmentKind<TriangularShape, DenseShape> {
752  typedef Dense2Triangular Kind;
753 };
754 
755 template <typename DstXprType, typename SrcXprType, typename Functor>
756 struct 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 
764 template <typename DstXprType, typename SrcXprType, typename Functor>
765 struct 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 
771 template <typename DstXprType, typename SrcXprType, typename Functor>
772 struct 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 
778 template <typename Kernel, unsigned int Mode, int UnrollCount, bool SetOpposite>
779 struct 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
804 template <typename Kernel, unsigned int Mode, bool SetOpposite>
805 struct 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 
812 template <typename Kernel, unsigned int Mode, bool SetOpposite>
813 struct 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 
846 template <typename Derived>
847 template <typename DenseDerived>
848 EIGEN_DEVICE_FUNC void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived>& other) const {
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 
855 namespace internal {
856 
857 // Triangular = Product
858 template <typename DstXprType, typename Lhs, typename Rhs, typename Scalar>
859 struct 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
873 template <typename DstXprType, typename Lhs, typename Rhs, typename Scalar>
874 struct 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
885 template <typename DstXprType, typename Lhs, typename Rhs, typename Scalar>
886 struct 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
Index innerStride() const
Definition: TriangularMatrix.h:321
constexpr Derived & derived()
Definition: EigenBase.h:49
TransposeReturnType transpose(std::enable_if_t< Eigen::internal::is_lvalue< MatrixType >::value, Dummy *>=nullptr)
Definition: TriangularMatrix.h:229
TriangularViewType & setConstant(const Scalar &value)
Definition: TriangularMatrix.h:350
const ConjugateReturnType conjugate() const
Definition: TriangularMatrix.h:209
const int HugeCost
Definition: Constants.h:48
Expression of the product of two arbitrary matrices or vectors.
Definition: Product.h:198
const AdjointReturnType adjoint() const
Definition: TriangularMatrix.h:224
Definition: Constants.h:223
Base class for triangular part in a matrix.
Definition: TriangularMatrix.h:32
EIGEN_DEPRECATED void swap(MatrixBase< OtherDerived > const &other)
Definition: TriangularMatrix.h:473
const unsigned int DirectAccessBit
Definition: Constants.h:159
Scalar determinant() const
Definition: TriangularMatrix.h:274
const unsigned int LvalueBit
Definition: Constants.h:148
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
void fill(const Scalar &value)
Definition: TriangularMatrix.h:348
void swap(TriangularBase< OtherDerived > &other)
Definition: TriangularMatrix.h:460
const NestedExpression & nestedExpression() const
Definition: TriangularMatrix.h:202
const SelfAdjointView< MatrixTypeNestedNonRef, Mode > selfadjointView() const
Definition: TriangularMatrix.h:267
Eigen::Index Index
The interface type of indices.
Definition: EigenBase.h:43
Base class for all dense matrices, vectors, and arrays.
Definition: DenseBase.h:38
const unsigned int PacketAccessBit
Definition: Constants.h:97
TriangularViewType & operator-=(const DenseBase< Other > &other)
Definition: TriangularMatrix.h:332
Definition: EigenBase.h:33
NestedExpression & nestedExpression()
Definition: TriangularMatrix.h:205
TriangularViewType & setOnes()
Definition: TriangularMatrix.h:356
bool isUpperTriangular(const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition: TriangularMatrix.h:585
void copyCoeff(Index row, Index col, Other &other)
Definition: TriangularMatrix.h:79
Definition: Constants.h:211
const ConstTransposeReturnType transpose() const
Definition: TriangularMatrix.h:237
const Product< TriangularViewType, OtherDerived > operator*(const MatrixBase< OtherDerived > &rhs) const
Definition: TriangularMatrix.h:399
Scalar coeff(Index row, Index col) const
Definition: TriangularMatrix.h:361
Definition: Constants.h:215
friend const Product< OtherDerived, TriangularViewType > operator*(const MatrixBase< OtherDerived > &lhs, const TriangularViewImpl &rhs)
Definition: TriangularMatrix.h:406
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
SelfAdjointView< MatrixTypeNestedNonRef, Mode > selfadjointView()
Definition: TriangularMatrix.h:261
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
void evalTo(MatrixBase< DenseDerived > &other) const
Definition: TriangularMatrix.h:541
constexpr Index rows() const noexcept
Definition: TriangularMatrix.h:197
TriangularViewType & operator+=(const DenseBase< Other > &other)
Definition: TriangularMatrix.h:325
Expression of a selfadjoint matrix from a triangular part of a dense matrix.
Definition: SelfAdjointView.h:51
Definition: Constants.h:225
TriangularViewType & setZero()
Definition: TriangularMatrix.h:354
Definition: Constants.h:221
Definition: Constants.h:213
constexpr Derived & derived()
Definition: EigenBase.h:49
Definition: Constants.h:217
Definition: Constants.h:219
bool isLowerTriangular(const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition: TriangularMatrix.h:607
Definition: TriangularMatrix.h:41
Definition: Constants.h:227
Expression of a triangular part in a matrix.
Definition: TriangularMatrix.h:166
TriangularViewType & operator/=(const typename internal::traits< MatrixType >::Scalar &other)
Definition: TriangularMatrix.h:343
Definition: Constants.h:519
constexpr Index cols() const noexcept
Definition: TriangularMatrix.h:199
std::conditional_t< Cond, ConjugateReturnType, ConstTriangularView > conjugateIf() const
Definition: TriangularMatrix.h:217
const int Dynamic
Definition: Constants.h:25
Pseudo expression representing a solving operation.
Definition: Solve.h:62
TriangularViewType & operator*=(const typename internal::traits< MatrixType >::Scalar &other)
Definition: TriangularMatrix.h:339
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:52
const unsigned int LinearAccessBit
Definition: Constants.h:133
void evalToLazy(MatrixBase< DenseDerived > &other) const
Definition: TriangularMatrix.h:848
Scalar & coeffRef(Index row, Index col)
Definition: TriangularMatrix.h:369
Index outerStride() const
Definition: TriangularMatrix.h:318