// 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 squared 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 squared matrix. * * \sa MatrixBase::upper(), MatrixBase::lower(), class TriangularProduct */ template struct ei_traits > { typedef typename MatrixType::Scalar Scalar; enum { RowsAtCompileTime = MatrixType::SizeAtCompileTime, ColsAtCompileTime = MatrixType::SizeAtCompileTime, MaxRowsAtCompileTime = MatrixType::MaxSizeAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxSizeAtCompileTime, Flags = MatrixType::Flags & (~(VectorizableBit | Like1DArrayBit)) | Mode, CoeffReadCost = MatrixType::CoeffReadCost }; }; template class Triangular : public MatrixBase > { public: EIGEN_GENERIC_PUBLIC_INTERFACE(Triangular) Triangular(const MatrixType& matrix) : m_matrix(matrix) { assert(!( (Flags&UnitDiagBit) && (Flags&NullDiagBit))); assert(matrix.rows()==matrix.cols()); } /** Overloaded to keep a Triangular expression */ Triangular<(Upper | Lower) xor Mode, Transpose > transpose() { return Triangular<(Upper | Lower) xor Mode, Transpose >((m_matrix.transpose())); } /** Overloaded to keep a Triangular expression */ const Triangular<(Upper | Lower) xor Mode, Transpose > transpose() const { return Triangular<(Upper | Lower) xor Mode, Transpose >((m_matrix.transpose())); } #if 0 template Triangular& operator=(const MatrixBase& other); /** Overloaded to provide optimal evaluation loops */ template Triangular& operator +=(const MatrixBase& other) { return *this = m_matrix + other; } /** Overloaded to provide optimal evaluation loops */ template Triangular& operator *=(const MatrixBase& other) { return *this = this->lazyProduct(other).eval(); } /** Optimized triangular matrix - matrix product */ template TriangularProduct lazyProduct(const MatrixBase& other) const { return TriangularProduct(m_matrix, other.ref()); } /** Optimized triangular matrix - matrix product */ template Eval > operator * (const MatrixBase& other) const { return this->lazyProduct(other).eval(); } /** Optimized matrix - triangular matrix product */ template friend Eval, Transpose > > > operator * (const MatrixBase& other, const Triangular& tri) { return tri.transpose().lazyProduct(other.transpose()).transpose().eval(); } #endif /** \returns the product of the inverse of *this with \a other. * * This function computes the inverse-matrix matrix product inv(*this) \a other * This process is also as 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 ; c=0 ; --i) { Scalar tmp = other.col(c)[i]; for (int j = i+1 ; j < _cols() ; ++j) tmp -= _coeff(i,j) * res.col(c)[j]; if (Flags & UnitDiagBit) res.col(c)[i] = tmp; else res.col(c)[i] = tmp/_coeff(i,i); } } } return res; } private: int _rows() const { return m_matrix.rows(); } int _cols() const { return m_matrix.cols(); } Scalar& _coeffRef(int row, int col) { assert( ((! Flags & Lower) && row<=col) || (Flags & Lower && col<=row)); return m_matrix.coeffRef(row, col); } 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 Triangular MatrixBase::upper(void) { return Triangular(derived()); } /** This is the const version of upper(). */ template const Triangular MatrixBase::upper(void) const { return Triangular(derived()); } /** \returns an expression of a lower triangular matrix * * \sa isLower(), lowerWithUnitDiag(), lowerWithNullDiag(), upper() */ template Triangular MatrixBase::lower(void) { return Triangular(derived()); } /** This is the const version of lower().*/ template 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 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 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 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 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