| // This file is part of Eigen, a lightweight C++ template library |
| // for linear algebra. |
| // |
| // Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr> |
| // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> |
| // |
| // 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 <http://www.gnu.org/licenses/>. |
| |
| #ifndef EIGEN_DIAGONALMATRIX_H |
| #define EIGEN_DIAGONALMATRIX_H |
| |
| |
| template<typename CoeffsVectorType, typename Derived> |
| class DiagonalMatrixBase : ei_no_assignment_operator, |
| public MatrixBase<Derived> |
| { |
| public: |
| typedef MatrixBase<Derived> Base; |
| typedef typename ei_traits<Derived>::Scalar Scalar; |
| typedef typename Base::PacketScalar PacketScalar; |
| using Base::derived; |
| typedef typename ei_cleantype<CoeffsVectorType>::type _CoeffsVectorType; |
| |
| protected: |
| |
| // MSVC gets crazy if we define default parameters |
| template<typename OtherDerived, bool IsVector, bool IsDiagonal> struct construct_from_expression; |
| |
| // = vector |
| template<typename OtherDerived> |
| struct construct_from_expression<OtherDerived,true,false> |
| { |
| static void run(Derived& dst, const OtherDerived& src) |
| { dst.diagonal() = src; } |
| }; |
| |
| // = diagonal expression |
| template<typename OtherDerived, bool IsVector> |
| struct construct_from_expression<OtherDerived,IsVector,true> |
| { |
| static void run(Derived& dst, const OtherDerived& src) |
| { dst.diagonal() = src.diagonal(); } |
| }; |
| |
| /** Default constructor without initialization */ |
| inline DiagonalMatrixBase() {} |
| /** Constructs a diagonal matrix with given dimension */ |
| inline DiagonalMatrixBase(int dim) : m_coeffs(dim) {} |
| /** Generic constructor from an expression */ |
| template<typename OtherDerived> |
| inline DiagonalMatrixBase(const MatrixBase<OtherDerived>& other) |
| { |
| construct_from_expression<OtherDerived,OtherDerived::IsVectorAtCompileTime,ei_is_diagonal<OtherDerived>::ret> |
| ::run(derived(),other.derived()); |
| } |
| |
| template<typename NewType,int dummy=0> |
| struct cast_selector { |
| typedef const DiagonalMatrixWrapper<NestByValue<CwiseUnaryOp<ei_scalar_cast_op<Scalar, NewType>, _CoeffsVectorType> > > return_type; |
| inline static return_type run(const DiagonalMatrixBase& d) { |
| return d.m_coeffs.template cast<NewType>().nestByValue().asDiagonal(); |
| } |
| }; |
| |
| template<int dummy> |
| struct cast_selector<Scalar,dummy> { |
| typedef const Derived& return_type; |
| inline static return_type run(const DiagonalMatrixBase& d) { |
| return d.derived(); |
| } |
| }; |
| |
| public: |
| |
| inline DiagonalMatrixBase(const _CoeffsVectorType& coeffs) : m_coeffs(coeffs) |
| { |
| EIGEN_STATIC_ASSERT_VECTOR_ONLY(_CoeffsVectorType); |
| ei_assert(coeffs.size() > 0); |
| } |
| |
| template<typename NewType> |
| inline typename cast_selector<NewType,0>::return_type |
| cast() const |
| { |
| return cast_selector<NewType,0>::run(*this); |
| } |
| |
| /** Assignment operator. |
| * The right-hand-side \a other must be either a vector representing the diagonal |
| * coefficients or a diagonal matrix expression. |
| */ |
| template<typename OtherDerived> |
| inline Derived& operator=(const MatrixBase<OtherDerived>& other) |
| { |
| construct_from_expression<OtherDerived,OtherDerived::IsVectorAtCompileTime,ei_is_diagonal<OtherDerived>::ret> |
| ::run(derived(),other); |
| return derived(); |
| } |
| |
| inline int rows() const { return m_coeffs.size(); } |
| inline int cols() const { return m_coeffs.size(); } |
| |
| inline const Scalar coeff(int row, int col) const |
| { |
| return row == col ? m_coeffs.coeff(row) : static_cast<Scalar>(0); |
| } |
| |
| inline Scalar& coeffRef(int row, int col) |
| { |
| ei_assert(row==col); |
| return m_coeffs.coeffRef(row); |
| } |
| |
| inline _CoeffsVectorType& diagonal() { return m_coeffs; } |
| inline const _CoeffsVectorType& diagonal() const { return m_coeffs; } |
| |
| protected: |
| CoeffsVectorType m_coeffs; |
| }; |
| |
| /** \class DiagonalMatrix |
| * \nonstableyet |
| * |
| * \brief Represent a diagonal matrix with its storage |
| * |
| * \param _Scalar the type of coefficients |
| * \param _Size the dimension of the matrix |
| * |
| * \sa class Matrix |
| */ |
| template<typename _Scalar,int _Size> |
| struct ei_traits<DiagonalMatrix<_Scalar,_Size> > : ei_traits<Matrix<_Scalar,_Size,_Size> > |
| { |
| enum { |
| Flags = (ei_traits<Matrix<_Scalar,_Size,_Size> >::Flags & HereditaryBits) | DiagonalBits |
| }; |
| }; |
| |
| template<typename _Scalar, int _Size> |
| class DiagonalMatrix |
| : public DiagonalMatrixBase<Matrix<_Scalar,_Size,1>, DiagonalMatrix<_Scalar,_Size> > |
| { |
| public: |
| EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix) |
| typedef DiagonalMatrixBase<Matrix<_Scalar,_Size,1>, DiagonalMatrix<_Scalar,_Size> > DiagonalBase; |
| |
| protected: |
| typedef Matrix<_Scalar,_Size,1> CoeffVectorType; |
| using DiagonalBase::m_coeffs; |
| |
| public: |
| |
| /** Default constructor without initialization */ |
| inline DiagonalMatrix() : DiagonalBase() |
| {} |
| |
| /** Constructs a diagonal matrix with given dimension */ |
| inline DiagonalMatrix(int dim) : DiagonalBase(dim) |
| {} |
| |
| /** 2D only */ |
| inline DiagonalMatrix(const Scalar& sx, const Scalar& sy) |
| { |
| EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DiagonalMatrix,2,2); |
| m_coeffs.x() = sx; |
| m_coeffs.y() = sy; |
| } |
| /** 3D only */ |
| inline DiagonalMatrix(const Scalar& sx, const Scalar& sy, const Scalar& sz) |
| { |
| EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DiagonalMatrix,3,3); |
| m_coeffs.x() = sx; |
| m_coeffs.y() = sy; |
| m_coeffs.z() = sz; |
| } |
| |
| /** copy constructor */ |
| inline DiagonalMatrix(const DiagonalMatrix& other) : DiagonalBase(other.m_coeffs) |
| {} |
| |
| /** generic constructor from expression */ |
| template<typename OtherDerived> |
| explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : DiagonalBase(other) |
| {} |
| |
| DiagonalMatrix& operator=(const DiagonalMatrix& other) |
| { |
| m_coeffs = other.m_coeffs; |
| return *this; |
| } |
| |
| template<typename OtherDerived> |
| DiagonalMatrix& operator=(const MatrixBase<OtherDerived>& other) |
| { |
| EIGEN_STATIC_ASSERT(ei_is_diagonal<OtherDerived>::ret, THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX); |
| m_coeffs = other.diagonal(); |
| return *this; |
| } |
| |
| inline void resize(int size) |
| { |
| m_coeffs.resize(size); |
| } |
| |
| inline void resize(int rows, int cols) |
| { |
| ei_assert(rows==cols && "a diagonal matrix must be square"); |
| m_coeffs.resize(rows); |
| } |
| |
| inline void setZero() { m_coeffs.setZero(); } |
| }; |
| |
| /** \class DiagonalMatrixWrapper |
| * \nonstableyet |
| * |
| * \brief Expression of a diagonal matrix |
| * |
| * \param CoeffsVectorType the type of the vector of diagonal coefficients |
| * |
| * This class is an expression of a diagonal matrix with given vector of diagonal |
| * coefficients. It is the return type of MatrixBase::diagonal(const OtherDerived&) |
| * and most of the time this is the only way it is used. |
| * |
| * \sa class DiagonalMatrixBase, class DiagonalMatrix, MatrixBase::asDiagonal() |
| */ |
| template<typename CoeffsVectorType> |
| struct ei_traits<DiagonalMatrixWrapper<CoeffsVectorType> > |
| { |
| typedef typename CoeffsVectorType::Scalar Scalar; |
| typedef typename ei_nested<CoeffsVectorType>::type CoeffsVectorTypeNested; |
| typedef typename ei_unref<CoeffsVectorTypeNested>::type _CoeffsVectorTypeNested; |
| enum { |
| RowsAtCompileTime = CoeffsVectorType::SizeAtCompileTime, |
| ColsAtCompileTime = CoeffsVectorType::SizeAtCompileTime, |
| MaxRowsAtCompileTime = CoeffsVectorType::MaxSizeAtCompileTime, |
| MaxColsAtCompileTime = CoeffsVectorType::MaxSizeAtCompileTime, |
| Flags = (_CoeffsVectorTypeNested::Flags & HereditaryBits) | DiagonalBits, |
| CoeffReadCost = _CoeffsVectorTypeNested::CoeffReadCost |
| }; |
| }; |
| template<typename CoeffsVectorType> |
| class DiagonalMatrixWrapper |
| : public DiagonalMatrixBase<typename CoeffsVectorType::Nested, DiagonalMatrixWrapper<CoeffsVectorType> > |
| { |
| typedef typename CoeffsVectorType::Nested CoeffsVectorTypeNested; |
| typedef DiagonalMatrixBase<CoeffsVectorTypeNested, DiagonalMatrixWrapper<CoeffsVectorType> > DiagonalBase; |
| public: |
| EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrixWrapper) |
| inline DiagonalMatrixWrapper(const CoeffsVectorType& coeffs) : DiagonalBase(coeffs) |
| {} |
| }; |
| |
| /** \nonstableyet |
| * \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients |
| * |
| * \only_for_vectors |
| * |
| * \addexample AsDiagonalExample \label How to build a diagonal matrix from a vector |
| * |
| * Example: \include MatrixBase_asDiagonal.cpp |
| * Output: \verbinclude MatrixBase_asDiagonal.out |
| * |
| * \sa class DiagonalMatrix, isDiagonal() |
| **/ |
| template<typename Derived> |
| inline const DiagonalMatrixWrapper<Derived> |
| MatrixBase<Derived>::asDiagonal() const |
| { |
| return derived(); |
| } |
| |
| /** \nonstableyet |
| * \returns true if *this is approximately equal to a diagonal matrix, |
| * within the precision given by \a prec. |
| * |
| * Example: \include MatrixBase_isDiagonal.cpp |
| * Output: \verbinclude MatrixBase_isDiagonal.out |
| * |
| * \sa asDiagonal() |
| */ |
| template<typename Derived> |
| bool MatrixBase<Derived>::isDiagonal |
| (RealScalar prec) const |
| { |
| if(cols() != rows()) return false; |
| RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1); |
| for(int j = 0; j < cols(); ++j) |
| { |
| RealScalar absOnDiagonal = ei_abs(coeff(j,j)); |
| if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal; |
| } |
| for(int j = 0; j < cols(); ++j) |
| for(int i = 0; i < j; ++i) |
| { |
| if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false; |
| if(!ei_isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false; |
| } |
| return true; |
| } |
| |
| #endif // EIGEN_DIAGONALMATRIX_H |