MOAB
4.9.3pre
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2008 Benoit Jacob <[email protected]> 00005 // Copyright (C) 2008-2009 Gael Guennebaud <[email protected]> 00006 // 00007 // This Source Code Form is subject to the terms of the Mozilla 00008 // Public License v. 2.0. If a copy of the MPL was not distributed 00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00010 00011 #ifndef EIGEN_TRIANGULARMATRIX_H 00012 #define EIGEN_TRIANGULARMATRIX_H 00013 00014 namespace Eigen { 00015 00016 namespace internal { 00017 00018 template<int Side, typename TriangularType, typename Rhs> struct triangular_solve_retval; 00019 00020 } 00021 00027 template<typename Derived> class TriangularBase : public EigenBase<Derived> 00028 { 00029 public: 00030 00031 enum { 00032 Mode = internal::traits<Derived>::Mode, 00033 RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime, 00034 ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime, 00035 MaxRowsAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime, 00036 MaxColsAtCompileTime = internal::traits<Derived>::MaxColsAtCompileTime, 00037 00038 SizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::RowsAtCompileTime, 00039 internal::traits<Derived>::ColsAtCompileTime>::ret), 00044 MaxSizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::MaxRowsAtCompileTime, 00045 internal::traits<Derived>::MaxColsAtCompileTime>::ret) 00046 00047 }; 00048 typedef typename internal::traits<Derived>::Scalar Scalar; 00049 typedef typename internal::traits<Derived>::StorageKind StorageKind; 00050 typedef typename internal::traits<Derived>::StorageIndex StorageIndex; 00051 typedef typename internal::traits<Derived>::FullMatrixType DenseMatrixType; 00052 typedef DenseMatrixType DenseType; 00053 typedef Derived const& Nested; 00054 00055 EIGEN_DEVICE_FUNC 00056 inline TriangularBase() { eigen_assert(!((Mode&UnitDiag) && (Mode&ZeroDiag))); } 00057 00058 EIGEN_DEVICE_FUNC 00059 inline Index rows() const { return derived().rows(); } 00060 EIGEN_DEVICE_FUNC 00061 inline Index cols() const { return derived().cols(); } 00062 EIGEN_DEVICE_FUNC 00063 inline Index outerStride() const { return derived().outerStride(); } 00064 EIGEN_DEVICE_FUNC 00065 inline Index innerStride() const { return derived().innerStride(); } 00066 00067 // dummy resize function 00068 void resize(Index rows, Index cols) 00069 { 00070 EIGEN_UNUSED_VARIABLE(rows); 00071 EIGEN_UNUSED_VARIABLE(cols); 00072 eigen_assert(rows==this->rows() && cols==this->cols()); 00073 } 00074 00075 EIGEN_DEVICE_FUNC 00076 inline Scalar coeff(Index row, Index col) const { return derived().coeff(row,col); } 00077 EIGEN_DEVICE_FUNC 00078 inline Scalar& coeffRef(Index row, Index col) { return derived().coeffRef(row,col); } 00079 00082 template<typename Other> 00083 EIGEN_DEVICE_FUNC 00084 EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, Other& other) 00085 { 00086 derived().coeffRef(row, col) = other.coeff(row, col); 00087 } 00088 00089 EIGEN_DEVICE_FUNC 00090 inline Scalar operator()(Index row, Index col) const 00091 { 00092 check_coordinates(row, col); 00093 return coeff(row,col); 00094 } 00095 EIGEN_DEVICE_FUNC 00096 inline Scalar& operator()(Index row, Index col) 00097 { 00098 check_coordinates(row, col); 00099 return coeffRef(row,col); 00100 } 00101 00102 #ifndef EIGEN_PARSED_BY_DOXYGEN 00103 EIGEN_DEVICE_FUNC 00104 inline const Derived& derived() const { return *static_cast<const Derived*>(this); } 00105 EIGEN_DEVICE_FUNC 00106 inline Derived& derived() { return *static_cast<Derived*>(this); } 00107 #endif // not EIGEN_PARSED_BY_DOXYGEN 00108 00109 template<typename DenseDerived> 00110 EIGEN_DEVICE_FUNC 00111 void evalTo(MatrixBase<DenseDerived> &other) const; 00112 template<typename DenseDerived> 00113 EIGEN_DEVICE_FUNC 00114 void evalToLazy(MatrixBase<DenseDerived> &other) const; 00115 00116 EIGEN_DEVICE_FUNC 00117 DenseMatrixType toDenseMatrix() const 00118 { 00119 DenseMatrixType res(rows(), cols()); 00120 evalToLazy(res); 00121 return res; 00122 } 00123 00124 protected: 00125 00126 void check_coordinates(Index row, Index col) const 00127 { 00128 EIGEN_ONLY_USED_FOR_DEBUG(row); 00129 EIGEN_ONLY_USED_FOR_DEBUG(col); 00130 eigen_assert(col>=0 && col<cols() && row>=0 && row<rows()); 00131 const int mode = int(Mode) & ~SelfAdjoint; 00132 EIGEN_ONLY_USED_FOR_DEBUG(mode); 00133 eigen_assert((mode==Upper && col>=row) 00134 || (mode==Lower && col<=row) 00135 || ((mode==StrictlyUpper || mode==UnitUpper) && col>row) 00136 || ((mode==StrictlyLower || mode==UnitLower) && col<row)); 00137 } 00138 00139 #ifdef EIGEN_INTERNAL_DEBUGGING 00140 void check_coordinates_internal(Index row, Index col) const 00141 { 00142 check_coordinates(row, col); 00143 } 00144 #else 00145 void check_coordinates_internal(Index , Index ) const {} 00146 #endif 00147 00148 }; 00149 00167 namespace internal { 00168 template<typename MatrixType, unsigned int _Mode> 00169 struct traits<TriangularView<MatrixType, _Mode> > : traits<MatrixType> 00170 { 00171 typedef typename ref_selector<MatrixType>::non_const_type MatrixTypeNested; 00172 typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedNonRef; 00173 typedef typename remove_all<MatrixTypeNested>::type MatrixTypeNestedCleaned; 00174 typedef typename MatrixType::PlainObject FullMatrixType; 00175 typedef MatrixType ExpressionType; 00176 enum { 00177 Mode = _Mode, 00178 FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0, 00179 Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits | FlagsLvalueBit) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) 00180 }; 00181 }; 00182 } 00183 00184 template<typename _MatrixType, unsigned int _Mode, typename StorageKind> class TriangularViewImpl; 00185 00186 template<typename _MatrixType, unsigned int _Mode> class TriangularView 00187 : public TriangularViewImpl<_MatrixType, _Mode, typename internal::traits<_MatrixType>::StorageKind > 00188 { 00189 public: 00190 00191 typedef TriangularViewImpl<_MatrixType, _Mode, typename internal::traits<_MatrixType>::StorageKind > Base; 00192 typedef typename internal::traits<TriangularView>::Scalar Scalar; 00193 typedef _MatrixType MatrixType; 00194 00195 protected: 00196 typedef typename internal::traits<TriangularView>::MatrixTypeNested MatrixTypeNested; 00197 typedef typename internal::traits<TriangularView>::MatrixTypeNestedNonRef MatrixTypeNestedNonRef; 00198 00199 typedef typename internal::remove_all<typename MatrixType::ConjugateReturnType>::type MatrixConjugateReturnType; 00200 00201 public: 00202 00203 typedef typename internal::traits<TriangularView>::StorageKind StorageKind; 00204 typedef typename internal::traits<TriangularView>::MatrixTypeNestedCleaned NestedExpression; 00205 00206 enum { 00207 Mode = _Mode, 00208 Flags = internal::traits<TriangularView>::Flags, 00209 TransposeMode = (Mode & Upper ? Lower : 0) 00210 | (Mode & Lower ? Upper : 0) 00211 | (Mode & (UnitDiag)) 00212 | (Mode & (ZeroDiag)), 00213 IsVectorAtCompileTime = false 00214 }; 00215 00216 EIGEN_DEVICE_FUNC 00217 explicit inline TriangularView(MatrixType& matrix) : m_matrix(matrix) 00218 {} 00219 00220 using Base::operator=; 00221 TriangularView& operator=(const TriangularView &other) 00222 { return Base::operator=(other); } 00223 00225 EIGEN_DEVICE_FUNC 00226 inline Index rows() const { return m_matrix.rows(); } 00228 EIGEN_DEVICE_FUNC 00229 inline Index cols() const { return m_matrix.cols(); } 00230 00232 EIGEN_DEVICE_FUNC 00233 const NestedExpression& nestedExpression() const { return m_matrix; } 00234 00236 EIGEN_DEVICE_FUNC 00237 NestedExpression& nestedExpression() { return m_matrix; } 00238 00239 typedef TriangularView<const MatrixConjugateReturnType,Mode> ConjugateReturnType; 00241 EIGEN_DEVICE_FUNC 00242 inline const ConjugateReturnType conjugate() const 00243 { return ConjugateReturnType(m_matrix.conjugate()); } 00244 00245 typedef TriangularView<const typename MatrixType::AdjointReturnType,TransposeMode> AdjointReturnType; 00247 EIGEN_DEVICE_FUNC 00248 inline const AdjointReturnType adjoint() const 00249 { return AdjointReturnType(m_matrix.adjoint()); } 00250 00251 typedef TriangularView<typename MatrixType::TransposeReturnType,TransposeMode> TransposeReturnType; 00253 EIGEN_DEVICE_FUNC 00254 inline TransposeReturnType transpose() 00255 { 00256 EIGEN_STATIC_ASSERT_LVALUE(MatrixType) 00257 typename MatrixType::TransposeReturnType tmp(m_matrix); 00258 return TransposeReturnType(tmp); 00259 } 00260 00261 typedef TriangularView<const typename MatrixType::ConstTransposeReturnType,TransposeMode> ConstTransposeReturnType; 00263 EIGEN_DEVICE_FUNC 00264 inline const ConstTransposeReturnType transpose() const 00265 { 00266 return ConstTransposeReturnType(m_matrix.transpose()); 00267 } 00268 00269 template<typename Other> 00270 EIGEN_DEVICE_FUNC 00271 inline const Solve<TriangularView, Other> 00272 solve(const MatrixBase<Other>& other) const 00273 { return Solve<TriangularView, Other>(*this, other.derived()); } 00274 00275 // workaround MSVC ICE 00276 #if EIGEN_COMP_MSVC 00277 template<int Side, typename Other> 00278 EIGEN_DEVICE_FUNC 00279 inline const internal::triangular_solve_retval<Side,TriangularView, Other> 00280 solve(const MatrixBase<Other>& other) const 00281 { return Base::template solve<Side>(other); } 00282 #else 00283 using Base::solve; 00284 #endif 00285 00290 EIGEN_DEVICE_FUNC 00291 SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView() 00292 { 00293 EIGEN_STATIC_ASSERT((Mode&(UnitDiag|ZeroDiag))==0,PROGRAMMING_ERROR); 00294 return SelfAdjointView<MatrixTypeNestedNonRef,Mode>(m_matrix); 00295 } 00296 00298 EIGEN_DEVICE_FUNC 00299 const SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView() const 00300 { 00301 EIGEN_STATIC_ASSERT((Mode&(UnitDiag|ZeroDiag))==0,PROGRAMMING_ERROR); 00302 return SelfAdjointView<MatrixTypeNestedNonRef,Mode>(m_matrix); 00303 } 00304 00305 00308 EIGEN_DEVICE_FUNC 00309 Scalar determinant() const 00310 { 00311 if (Mode & UnitDiag) 00312 return 1; 00313 else if (Mode & ZeroDiag) 00314 return 0; 00315 else 00316 return m_matrix.diagonal().prod(); 00317 } 00318 00319 protected: 00320 00321 MatrixTypeNested m_matrix; 00322 }; 00323 00333 template<typename _MatrixType, unsigned int _Mode> class TriangularViewImpl<_MatrixType,_Mode,Dense> 00334 : public TriangularBase<TriangularView<_MatrixType, _Mode> > 00335 { 00336 public: 00337 00338 typedef TriangularView<_MatrixType, _Mode> TriangularViewType; 00339 typedef TriangularBase<TriangularViewType> Base; 00340 typedef typename internal::traits<TriangularViewType>::Scalar Scalar; 00341 00342 typedef _MatrixType MatrixType; 00343 typedef typename MatrixType::PlainObject DenseMatrixType; 00344 typedef DenseMatrixType PlainObject; 00345 00346 public: 00347 using Base::evalToLazy; 00348 using Base::derived; 00349 00350 typedef typename internal::traits<TriangularViewType>::StorageKind StorageKind; 00351 00352 enum { 00353 Mode = _Mode, 00354 Flags = internal::traits<TriangularViewType>::Flags 00355 }; 00356 00359 EIGEN_DEVICE_FUNC 00360 inline Index outerStride() const { return derived().nestedExpression().outerStride(); } 00363 EIGEN_DEVICE_FUNC 00364 inline Index innerStride() const { return derived().nestedExpression().innerStride(); } 00365 00367 template<typename Other> 00368 EIGEN_DEVICE_FUNC 00369 TriangularViewType& operator+=(const DenseBase<Other>& other) { 00370 internal::call_assignment_no_alias(derived(), other.derived(), internal::add_assign_op<Scalar>()); 00371 return derived(); 00372 } 00374 template<typename Other> 00375 EIGEN_DEVICE_FUNC 00376 TriangularViewType& operator-=(const DenseBase<Other>& other) { 00377 internal::call_assignment_no_alias(derived(), other.derived(), internal::sub_assign_op<Scalar>()); 00378 return derived(); 00379 } 00380 00382 EIGEN_DEVICE_FUNC 00383 TriangularViewType& operator*=(const typename internal::traits<MatrixType>::Scalar& other) { return *this = derived().nestedExpression() * other; } 00385 EIGEN_DEVICE_FUNC 00386 TriangularViewType& operator/=(const typename internal::traits<MatrixType>::Scalar& other) { return *this = derived().nestedExpression() / other; } 00387 00389 EIGEN_DEVICE_FUNC 00390 void fill(const Scalar& value) { setConstant(value); } 00392 EIGEN_DEVICE_FUNC 00393 TriangularViewType& setConstant(const Scalar& value) 00394 { return *this = MatrixType::Constant(derived().rows(), derived().cols(), value); } 00396 EIGEN_DEVICE_FUNC 00397 TriangularViewType& setZero() { return setConstant(Scalar(0)); } 00399 EIGEN_DEVICE_FUNC 00400 TriangularViewType& setOnes() { return setConstant(Scalar(1)); } 00401 00405 EIGEN_DEVICE_FUNC 00406 inline Scalar coeff(Index row, Index col) const 00407 { 00408 Base::check_coordinates_internal(row, col); 00409 return derived().nestedExpression().coeff(row, col); 00410 } 00411 00415 EIGEN_DEVICE_FUNC 00416 inline Scalar& coeffRef(Index row, Index col) 00417 { 00418 EIGEN_STATIC_ASSERT_LVALUE(TriangularViewType); 00419 Base::check_coordinates_internal(row, col); 00420 return derived().nestedExpression().coeffRef(row, col); 00421 } 00422 00424 template<typename OtherDerived> 00425 EIGEN_DEVICE_FUNC 00426 TriangularViewType& operator=(const TriangularBase<OtherDerived>& other); 00427 00429 template<typename OtherDerived> 00430 EIGEN_DEVICE_FUNC 00431 TriangularViewType& operator=(const MatrixBase<OtherDerived>& other); 00432 00433 #ifndef EIGEN_PARSED_BY_DOXYGEN 00434 EIGEN_DEVICE_FUNC 00435 TriangularViewType& operator=(const TriangularViewImpl& other) 00436 { return *this = other.derived().nestedExpression(); } 00437 00439 template<typename OtherDerived> 00440 EIGEN_DEVICE_FUNC 00441 void lazyAssign(const TriangularBase<OtherDerived>& other); 00442 00444 template<typename OtherDerived> 00445 EIGEN_DEVICE_FUNC 00446 void lazyAssign(const MatrixBase<OtherDerived>& other); 00447 #endif 00448 00450 template<typename OtherDerived> 00451 EIGEN_DEVICE_FUNC 00452 const Product<TriangularViewType,OtherDerived> 00453 operator*(const MatrixBase<OtherDerived>& rhs) const 00454 { 00455 return Product<TriangularViewType,OtherDerived>(derived(), rhs.derived()); 00456 } 00457 00459 template<typename OtherDerived> friend 00460 EIGEN_DEVICE_FUNC 00461 const Product<OtherDerived,TriangularViewType> 00462 operator*(const MatrixBase<OtherDerived>& lhs, const TriangularViewImpl& rhs) 00463 { 00464 return Product<OtherDerived,TriangularViewType>(lhs.derived(),rhs.derived()); 00465 } 00466 00488 template<int Side, typename Other> 00489 EIGEN_DEVICE_FUNC 00490 inline const internal::triangular_solve_retval<Side,TriangularViewType, Other> 00491 solve(const MatrixBase<Other>& other) const; 00492 00500 template<int Side, typename OtherDerived> 00501 EIGEN_DEVICE_FUNC 00502 void solveInPlace(const MatrixBase<OtherDerived>& other) const; 00503 00504 template<typename OtherDerived> 00505 EIGEN_DEVICE_FUNC 00506 void solveInPlace(const MatrixBase<OtherDerived>& other) const 00507 { return solveInPlace<OnTheLeft>(other); } 00508 00510 template<typename OtherDerived> 00511 EIGEN_DEVICE_FUNC 00512 #ifdef EIGEN_PARSED_BY_DOXYGEN 00513 void swap(TriangularBase<OtherDerived> &other) 00514 #else 00515 void swap(TriangularBase<OtherDerived> const & other) 00516 #endif 00517 { 00518 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived); 00519 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>()); 00520 } 00521 00524 template<typename OtherDerived> 00525 EIGEN_DEVICE_FUNC 00526 void swap(MatrixBase<OtherDerived> const & other) 00527 { 00528 EIGEN_STATIC_ASSERT_LVALUE(OtherDerived); 00529 call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>()); 00530 } 00531 00532 template<typename RhsType, typename DstType> 00533 EIGEN_DEVICE_FUNC 00534 EIGEN_STRONG_INLINE void _solve_impl(const RhsType &rhs, DstType &dst) const { 00535 if(!(internal::is_same<RhsType,DstType>::value && internal::extract_data(dst) == internal::extract_data(rhs))) 00536 dst = rhs; 00537 this->solveInPlace(dst); 00538 } 00539 00540 template<typename ProductType> 00541 EIGEN_DEVICE_FUNC 00542 EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha); 00543 }; 00544 00545 /*************************************************************************** 00546 * Implementation of triangular evaluation/assignment 00547 ***************************************************************************/ 00548 00549 // FIXME should we keep that possibility 00550 template<typename MatrixType, unsigned int Mode> 00551 template<typename OtherDerived> 00552 inline TriangularView<MatrixType, Mode>& 00553 TriangularViewImpl<MatrixType, Mode, Dense>::operator=(const MatrixBase<OtherDerived>& other) 00554 { 00555 internal::call_assignment_no_alias(derived(), other.derived(), internal::assign_op<Scalar>()); 00556 return derived(); 00557 } 00558 00559 // FIXME should we keep that possibility 00560 template<typename MatrixType, unsigned int Mode> 00561 template<typename OtherDerived> 00562 void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(const MatrixBase<OtherDerived>& other) 00563 { 00564 internal::call_assignment_no_alias(derived(), other.template triangularView<Mode>()); 00565 } 00566 00567 00568 00569 template<typename MatrixType, unsigned int Mode> 00570 template<typename OtherDerived> 00571 inline TriangularView<MatrixType, Mode>& 00572 TriangularViewImpl<MatrixType, Mode, Dense>::operator=(const TriangularBase<OtherDerived>& other) 00573 { 00574 eigen_assert(Mode == int(OtherDerived::Mode)); 00575 internal::call_assignment(derived(), other.derived()); 00576 return derived(); 00577 } 00578 00579 template<typename MatrixType, unsigned int Mode> 00580 template<typename OtherDerived> 00581 void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(const TriangularBase<OtherDerived>& other) 00582 { 00583 eigen_assert(Mode == int(OtherDerived::Mode)); 00584 internal::call_assignment_no_alias(derived(), other.derived()); 00585 } 00586 00587 /*************************************************************************** 00588 * Implementation of TriangularBase methods 00589 ***************************************************************************/ 00590 00593 template<typename Derived> 00594 template<typename DenseDerived> 00595 void TriangularBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const 00596 { 00597 evalToLazy(other.derived()); 00598 } 00599 00600 /*************************************************************************** 00601 * Implementation of TriangularView methods 00602 ***************************************************************************/ 00603 00604 /*************************************************************************** 00605 * Implementation of MatrixBase methods 00606 ***************************************************************************/ 00607 00619 template<typename Derived> 00620 template<unsigned int Mode> 00621 typename MatrixBase<Derived>::template TriangularViewReturnType<Mode>::Type 00622 MatrixBase<Derived>::triangularView() 00623 { 00624 return typename TriangularViewReturnType<Mode>::Type(derived()); 00625 } 00626 00628 template<typename Derived> 00629 template<unsigned int Mode> 00630 typename MatrixBase<Derived>::template ConstTriangularViewReturnType<Mode>::Type 00631 MatrixBase<Derived>::triangularView() const 00632 { 00633 return typename ConstTriangularViewReturnType<Mode>::Type(derived()); 00634 } 00635 00641 template<typename Derived> 00642 bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const 00643 { 00644 using std::abs; 00645 RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1); 00646 for(Index j = 0; j < cols(); ++j) 00647 { 00648 Index maxi = (std::min)(j, rows()-1); 00649 for(Index i = 0; i <= maxi; ++i) 00650 { 00651 RealScalar absValue = abs(coeff(i,j)); 00652 if(absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue; 00653 } 00654 } 00655 RealScalar threshold = maxAbsOnUpperPart * prec; 00656 for(Index j = 0; j < cols(); ++j) 00657 for(Index i = j+1; i < rows(); ++i) 00658 if(abs(coeff(i, j)) > threshold) return false; 00659 return true; 00660 } 00661 00667 template<typename Derived> 00668 bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const 00669 { 00670 using std::abs; 00671 RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1); 00672 for(Index j = 0; j < cols(); ++j) 00673 for(Index i = j; i < rows(); ++i) 00674 { 00675 RealScalar absValue = abs(coeff(i,j)); 00676 if(absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue; 00677 } 00678 RealScalar threshold = maxAbsOnLowerPart * prec; 00679 for(Index j = 1; j < cols(); ++j) 00680 { 00681 Index maxi = (std::min)(j, rows()-1); 00682 for(Index i = 0; i < maxi; ++i) 00683 if(abs(coeff(i, j)) > threshold) return false; 00684 } 00685 return true; 00686 } 00687 00688 00689 /*************************************************************************** 00690 **************************************************************************** 00691 * Evaluators and Assignment of triangular expressions 00692 *************************************************************************** 00693 ***************************************************************************/ 00694 00695 namespace internal { 00696 00697 00698 // TODO currently a triangular expression has the form TriangularView<.,.> 00699 // in the future triangular-ness should be defined by the expression traits 00700 // such that Transpose<TriangularView<.,.> > is valid. (currently TriangularBase::transpose() is overloaded to make it work) 00701 template<typename MatrixType, unsigned int Mode> 00702 struct evaluator_traits<TriangularView<MatrixType,Mode> > 00703 { 00704 typedef typename storage_kind_to_evaluator_kind<typename MatrixType::StorageKind>::Kind Kind; 00705 typedef typename glue_shapes<typename evaluator_traits<MatrixType>::Shape, TriangularShape>::type Shape; 00706 }; 00707 00708 template<typename MatrixType, unsigned int Mode> 00709 struct unary_evaluator<TriangularView<MatrixType,Mode>, IndexBased> 00710 : evaluator<typename internal::remove_all<MatrixType>::type> 00711 { 00712 typedef TriangularView<MatrixType,Mode> XprType; 00713 typedef evaluator<typename internal::remove_all<MatrixType>::type> Base; 00714 unary_evaluator(const XprType &xpr) : Base(xpr.nestedExpression()) {} 00715 }; 00716 00717 // Additional assignment kinds: 00718 struct Triangular2Triangular {}; 00719 struct Triangular2Dense {}; 00720 struct Dense2Triangular {}; 00721 00722 00723 template<typename Kernel, unsigned int Mode, int UnrollCount, bool ClearOpposite> struct triangular_assignment_loop; 00724 00725 00731 template<int UpLo, int Mode, int SetOpposite, typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor, int Version = Specialized> 00732 class triangular_dense_assignment_kernel : public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> 00733 { 00734 protected: 00735 typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, Version> Base; 00736 typedef typename Base::DstXprType DstXprType; 00737 typedef typename Base::SrcXprType SrcXprType; 00738 using Base::m_dst; 00739 using Base::m_src; 00740 using Base::m_functor; 00741 public: 00742 00743 typedef typename Base::DstEvaluatorType DstEvaluatorType; 00744 typedef typename Base::SrcEvaluatorType SrcEvaluatorType; 00745 typedef typename Base::Scalar Scalar; 00746 typedef typename Base::AssignmentTraits AssignmentTraits; 00747 00748 00749 EIGEN_DEVICE_FUNC triangular_dense_assignment_kernel(DstEvaluatorType &dst, const SrcEvaluatorType &src, const Functor &func, DstXprType& dstExpr) 00750 : Base(dst, src, func, dstExpr) 00751 {} 00752 00753 #ifdef EIGEN_INTERNAL_DEBUGGING 00754 EIGEN_DEVICE_FUNC void assignCoeff(Index row, Index col) 00755 { 00756 eigen_internal_assert(row!=col); 00757 Base::assignCoeff(row,col); 00758 } 00759 #else 00760 using Base::assignCoeff; 00761 #endif 00762 00763 EIGEN_DEVICE_FUNC void assignDiagonalCoeff(Index id) 00764 { 00765 if(Mode==UnitDiag && SetOpposite) m_functor.assignCoeff(m_dst.coeffRef(id,id), Scalar(1)); 00766 else if(Mode==ZeroDiag && SetOpposite) m_functor.assignCoeff(m_dst.coeffRef(id,id), Scalar(0)); 00767 else if(Mode==0) Base::assignCoeff(id,id); 00768 } 00769 00770 EIGEN_DEVICE_FUNC void assignOppositeCoeff(Index row, Index col) 00771 { 00772 eigen_internal_assert(row!=col); 00773 if(SetOpposite) 00774 m_functor.assignCoeff(m_dst.coeffRef(row,col), Scalar(0)); 00775 } 00776 }; 00777 00778 template<int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType, typename Functor> 00779 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00780 void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func) 00781 { 00782 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); 00783 00784 typedef evaluator<DstXprType> DstEvaluatorType; 00785 typedef evaluator<SrcXprType> SrcEvaluatorType; 00786 00787 DstEvaluatorType dstEvaluator(dst); 00788 SrcEvaluatorType srcEvaluator(src); 00789 00790 typedef triangular_dense_assignment_kernel< Mode&(Lower|Upper),Mode&(UnitDiag|ZeroDiag|SelfAdjoint),SetOpposite, 00791 DstEvaluatorType,SrcEvaluatorType,Functor> Kernel; 00792 Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived()); 00793 00794 enum { 00795 unroll = DstXprType::SizeAtCompileTime != Dynamic 00796 && SrcEvaluatorType::CoeffReadCost < HugeCost 00797 && DstXprType::SizeAtCompileTime * SrcEvaluatorType::CoeffReadCost / 2 <= EIGEN_UNROLLING_LIMIT 00798 }; 00799 00800 triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) : Dynamic, SetOpposite>::run(kernel); 00801 } 00802 00803 template<int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType> 00804 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00805 void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& src) 00806 { 00807 call_triangular_assignment_loop<Mode,SetOpposite>(dst, src, internal::assign_op<typename DstXprType::Scalar>()); 00808 } 00809 00810 template<> struct AssignmentKind<TriangularShape,TriangularShape> { typedef Triangular2Triangular Kind; }; 00811 template<> struct AssignmentKind<DenseShape,TriangularShape> { typedef Triangular2Dense Kind; }; 00812 template<> struct AssignmentKind<TriangularShape,DenseShape> { typedef Dense2Triangular Kind; }; 00813 00814 00815 template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> 00816 struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Triangular, Scalar> 00817 { 00818 EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const Functor &func) 00819 { 00820 eigen_assert(int(DstXprType::Mode) == int(SrcXprType::Mode)); 00821 00822 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func); 00823 } 00824 }; 00825 00826 template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> 00827 struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Dense, Scalar> 00828 { 00829 EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const Functor &func) 00830 { 00831 call_triangular_assignment_loop<SrcXprType::Mode, (SrcXprType::Mode&SelfAdjoint)==0>(dst, src, func); 00832 } 00833 }; 00834 00835 template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> 00836 struct Assignment<DstXprType, SrcXprType, Functor, Dense2Triangular, Scalar> 00837 { 00838 EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const Functor &func) 00839 { 00840 call_triangular_assignment_loop<DstXprType::Mode, false>(dst, src, func); 00841 } 00842 }; 00843 00844 00845 template<typename Kernel, unsigned int Mode, int UnrollCount, bool SetOpposite> 00846 struct triangular_assignment_loop 00847 { 00848 // FIXME: this is not very clean, perhaps this information should be provided by the kernel? 00849 typedef typename Kernel::DstEvaluatorType DstEvaluatorType; 00850 typedef typename DstEvaluatorType::XprType DstXprType; 00851 00852 enum { 00853 col = (UnrollCount-1) / DstXprType::RowsAtCompileTime, 00854 row = (UnrollCount-1) % DstXprType::RowsAtCompileTime 00855 }; 00856 00857 typedef typename Kernel::Scalar Scalar; 00858 00859 EIGEN_DEVICE_FUNC 00860 static inline void run(Kernel &kernel) 00861 { 00862 triangular_assignment_loop<Kernel, Mode, UnrollCount-1, SetOpposite>::run(kernel); 00863 00864 if(row==col) 00865 kernel.assignDiagonalCoeff(row); 00866 else if( ((Mode&Lower) && row>col) || ((Mode&Upper) && row<col) ) 00867 kernel.assignCoeff(row,col); 00868 else if(SetOpposite) 00869 kernel.assignOppositeCoeff(row,col); 00870 } 00871 }; 00872 00873 // prevent buggy user code from causing an infinite recursion 00874 template<typename Kernel, unsigned int Mode, bool SetOpposite> 00875 struct triangular_assignment_loop<Kernel, Mode, 0, SetOpposite> 00876 { 00877 EIGEN_DEVICE_FUNC 00878 static inline void run(Kernel &) {} 00879 }; 00880 00881 00882 00883 // TODO: experiment with a recursive assignment procedure splitting the current 00884 // triangular part into one rectangular and two triangular parts. 00885 00886 00887 template<typename Kernel, unsigned int Mode, bool SetOpposite> 00888 struct triangular_assignment_loop<Kernel, Mode, Dynamic, SetOpposite> 00889 { 00890 typedef typename Kernel::Scalar Scalar; 00891 EIGEN_DEVICE_FUNC 00892 static inline void run(Kernel &kernel) 00893 { 00894 for(Index j = 0; j < kernel.cols(); ++j) 00895 { 00896 Index maxi = (std::min)(j, kernel.rows()); 00897 Index i = 0; 00898 if (((Mode&Lower) && SetOpposite) || (Mode&Upper)) 00899 { 00900 for(; i < maxi; ++i) 00901 if(Mode&Upper) kernel.assignCoeff(i, j); 00902 else kernel.assignOppositeCoeff(i, j); 00903 } 00904 else 00905 i = maxi; 00906 00907 if(i<kernel.rows()) // then i==j 00908 kernel.assignDiagonalCoeff(i++); 00909 00910 if (((Mode&Upper) && SetOpposite) || (Mode&Lower)) 00911 { 00912 for(; i < kernel.rows(); ++i) 00913 if(Mode&Lower) kernel.assignCoeff(i, j); 00914 else kernel.assignOppositeCoeff(i, j); 00915 } 00916 } 00917 } 00918 }; 00919 00920 } // end namespace internal 00921 00924 template<typename Derived> 00925 template<typename DenseDerived> 00926 void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const 00927 { 00928 other.derived().resize(this->rows(), this->cols()); 00929 internal::call_triangular_assignment_loop<Derived::Mode,(Derived::Mode&SelfAdjoint)==0 /* SetOpposite */>(other.derived(), derived().nestedExpression()); 00930 } 00931 00932 namespace internal { 00933 00934 // Triangular = Product 00935 template< typename DstXprType, typename Lhs, typename Rhs, typename Scalar> 00936 struct Assignment<DstXprType, Product<Lhs,Rhs,DefaultProduct>, internal::assign_op<Scalar>, Dense2Triangular, Scalar> 00937 { 00938 typedef Product<Lhs,Rhs,DefaultProduct> SrcXprType; 00939 static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar> &) 00940 { 00941 dst.setZero(); 00942 dst._assignProduct(src, 1); 00943 } 00944 }; 00945 00946 // Triangular += Product 00947 template< typename DstXprType, typename Lhs, typename Rhs, typename Scalar> 00948 struct Assignment<DstXprType, Product<Lhs,Rhs,DefaultProduct>, internal::add_assign_op<Scalar>, Dense2Triangular, Scalar> 00949 { 00950 typedef Product<Lhs,Rhs,DefaultProduct> SrcXprType; 00951 static void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<Scalar> &) 00952 { 00953 dst._assignProduct(src, 1); 00954 } 00955 }; 00956 00957 // Triangular -= Product 00958 template< typename DstXprType, typename Lhs, typename Rhs, typename Scalar> 00959 struct Assignment<DstXprType, Product<Lhs,Rhs,DefaultProduct>, internal::sub_assign_op<Scalar>, Dense2Triangular, Scalar> 00960 { 00961 typedef Product<Lhs,Rhs,DefaultProduct> SrcXprType; 00962 static void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<Scalar> &) 00963 { 00964 dst._assignProduct(src, -1); 00965 } 00966 }; 00967 00968 } // end namespace internal 00969 00970 } // end namespace Eigen 00971 00972 #endif // EIGEN_TRIANGULARMATRIX_H