// This file is part of Eigen, a lightweight C++ template library // for linear algebra. Eigen itself is part of the KDE project. // // Copyright (C) 2008 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 3 of the License, or (at your option) any later version. // // Alternatively, you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of // the License, or (at your option) any later version. // // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License and a copy of the GNU General Public License along with // Eigen. If not, see . #ifndef EIGEN_TRIANGULAR_H #define EIGEN_TRIANGULAR_H /** \class Triangular * * \brief Expression of a triangular matrix from a square matrix * * \param Mode or-ed bit field indicating the triangular part (Upper or Lower) we are taking, * and the property of the diagonal if any (UnitDiagBit or NullDiagBit). * \param MatrixType the type of the object in which we are taking the triangular part * * This class represents an expression of the upper or lower triangular part of * a squared matrix. It is the return type of MatrixBase::upper(), MatrixBase::lower(), * MatrixBase::upperWithUnitDiagBit(), etc., and used to optimize operations involving * triangular matrices. Most of the time this is the only way it is used. * * Examples of some key features: * \code * m1 = ().upper(); * \endcode * In this example, the strictly lower part of the expression is not evaluated, * m1 might be resized and the strict lower part of m1 == 0. * * \code * m1.upper() = ; * \endcode * This example diverge from the previous one in the sense that the strictly * lower part of m1 is left unchanged, and optimal loops are employed. Note that * m1 might also be resized. * * Of course, in both examples \c has to be a square matrix. * * \sa MatrixBase::upper(), MatrixBase::lower(), class TriangularProduct */ template struct ei_traits > { typedef typename MatrixType::Scalar Scalar; typedef typename ei_nested::type MatrixTypeNested; typedef typename ei_unref::type _MatrixTypeNested; enum { RowsAtCompileTime = MatrixType::RowsAtCompileTime, ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, Flags = (_MatrixTypeNested::Flags & ~(VectorizableBit | Like1DArrayBit | DirectAccessBit)) | Mode, CoeffReadCost = _MatrixTypeNested::CoeffReadCost }; }; template class Triangular : public MatrixBase > { public: EIGEN_GENERIC_PUBLIC_INTERFACE(Triangular) inline Triangular(const MatrixType& matrix) : m_matrix(matrix) { assert(!( (Flags&UnitDiagBit) && (Flags&NullDiagBit))); assert(matrix.rows()==matrix.cols()); } EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Triangular) /** Overloaded to keep a Triangular expression */ inline Triangular<(Upper | Lower) ^ Mode, Flagged,TemporaryBit,0> > transpose() { return m_matrix.transpose().temporary(); } /** Overloaded to keep a Triangular expression */ inline const Triangular<(Upper | Lower) ^ Mode, Flagged,TemporaryBit,0> > transpose() const { return m_matrix.transpose().temporary(); } /** \returns the product of the inverse of *this with \a other. * * This function computes the inverse-matrix matrix product inverse(*this) * \a other * It works as a forward (resp. backward) substitution if *this is an upper (resp. lower) * triangular matrix. */ template typename OtherDerived::Eval inverseProduct(const MatrixBase& other) const { assert(_cols() == other.rows()); assert(!(Flags & NullDiagBit)); typename OtherDerived::Eval res(other.rows(), other.cols()); for (int c=0 ; crow(i).start(i)) * res.col(c).start(i))(0,0); if (Flags & UnitDiagBit) res(i,c) = tmp; else res(i,c) = tmp/_coeff(i,i); } } else { // backward substitution if (Flags & UnitDiagBit) res(_cols()-1,c) = other(_cols()-1,c); else res(_cols()-1,c) = other(_cols()-1, c)/_coeff(_rows()-1, _cols()-1); for (int i=_rows()-2 ; i>=0 ; --i) { Scalar tmp = other(i,c) - ((this->row(i).end(_cols()-i-1)) * res.col(c).end(_cols()-i-1))(0,0); if (Flags & UnitDiagBit) res(i,c) = tmp; else res(i,c) = tmp/_coeff(i,i); } } } return res; } private: inline int _rows() const { return m_matrix.rows(); } inline int _cols() const { return m_matrix.cols(); } inline Scalar& _coeffRef(int row, int col) { ei_assert( ((! (Flags & Lower)) && row<=col) || (Flags & Lower && col<=row)); return m_matrix.const_cast_derived().coeffRef(row, col); } inline Scalar _coeff(int row, int col) const { if ((Flags & Lower) ? col>row : row>col) return 0; if (Flags & UnitDiagBit) return col==row ? 1 : m_matrix.coeff(row, col); else if (Flags & NullDiagBit) return col==row ? 0 : m_matrix.coeff(row, col); else return m_matrix.coeff(row, col); } protected: const typename MatrixType::Nested m_matrix; }; /** \returns an expression of a upper triangular matrix * * \sa isUpper(), upperWithNullDiagBit(), upperWithNullDiagBit(), lower() */ template inline Triangular MatrixBase::upper(void) { return Triangular(derived()); } /** This is the const version of upper(). */ template inline const Triangular MatrixBase::upper(void) const { return Triangular(derived()); } /** \returns an expression of a lower triangular matrix * * \sa isLower(), lowerWithUnitDiag(), lowerWithNullDiag(), upper() */ template inline Triangular MatrixBase::lower(void) { return Triangular(derived()); } /** This is the const version of lower().*/ template inline const Triangular MatrixBase::lower(void) const { return Triangular(derived()); } /** \returns an expression of a upper triangular matrix with a unit diagonal * * \sa upper(), lowerWithUnitDiagBit() */ template inline const Triangular MatrixBase::upperWithUnitDiag(void) const { return Triangular(derived()); } /** \returns an expression of a strictly upper triangular matrix (diagonal==zero) * FIXME could also be called strictlyUpper() or upperStrict() * * \sa upper(), lowerWithNullDiag() */ template inline const Triangular MatrixBase::upperWithNullDiag(void) const { return Triangular(derived()); } /** \returns an expression of a lower triangular matrix with a unit diagonal * * \sa lower(), upperWithUnitDiag() */ template inline const Triangular MatrixBase::lowerWithUnitDiag(void) const { return Triangular(derived()); } /** \returns an expression of a strictly lower triangular matrix (diagonal==zero) * FIXME could also be called strictlyLower() or lowerStrict() * * \sa lower(), upperWithNullDiag() */ template inline const Triangular MatrixBase::lowerWithNullDiag(void) const { return Triangular(derived()); } /** \returns true if *this is approximately equal to an upper triangular matrix, * within the precision given by \a prec. * * \sa isLower(), upper() */ template bool MatrixBase::isUpper(RealScalar prec) const { if(cols() != rows()) return false; RealScalar maxAbsOnUpperPart = static_cast(-1); for(int j = 0; j < cols(); j++) for(int i = 0; i <= j; i++) { RealScalar absValue = ei_abs(coeff(i,j)); if(absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue; } for(int j = 0; j < cols()-1; j++) for(int i = j+1; i < rows(); i++) if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnUpperPart, prec)) return false; return true; } /** \returns true if *this is approximately equal to a lower triangular matrix, * within the precision given by \a prec. * * \sa isUpper(), upper() */ template bool MatrixBase::isLower(RealScalar prec) const { if(cols() != rows()) return false; RealScalar maxAbsOnLowerPart = static_cast(-1); for(int j = 0; j < cols(); j++) for(int i = j; i < rows(); i++) { RealScalar absValue = ei_abs(coeff(i,j)); if(absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue; } for(int j = 1; j < cols(); j++) for(int i = 0; i < j; i++) if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnLowerPart, prec)) return false; return true; } #endif // EIGEN_TRIANGULAR_H