MOAB  4.9.3pre
TriangularMatrix.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines