// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // // 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_DIAGONALMATRIX_H #define EIGEN_DIAGONALMATRIX_H template class DiagonalMatrixBase : ei_no_assignment_operator, public MatrixBase { public: typedef MatrixBase Base; typedef typename ei_traits::Scalar Scalar; typedef typename Base::PacketScalar PacketScalar; using Base::derived; typedef typename ei_cleantype::type _CoeffsVectorType; protected: // MSVC gets crazy if we define default parameters template struct construct_from_expression; // = vector template struct construct_from_expression { static void run(Derived& dst, const OtherDerived& src) { dst.diagonal() = src; } }; // = diagonal expression template struct construct_from_expression { 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 inline DiagonalMatrixBase(const MatrixBase& other) { construct_from_expression::ret> ::run(derived(),other.derived()); } template struct cast_selector { typedef const DiagonalMatrixWrapper, _CoeffsVectorType> > > return_type; inline static return_type run(const DiagonalMatrixBase& d) { return d.m_coeffs.template cast().nestByValue().asDiagonal(); } }; template struct cast_selector { 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 inline typename cast_selector::return_type cast() const { return cast_selector::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 inline Derived& operator=(const MatrixBase& other) { construct_from_expression::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(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 struct ei_traits > : ei_traits > { enum { Flags = (ei_traits >::Flags & HereditaryBits) | DiagonalBits }; }; template class DiagonalMatrix : public DiagonalMatrixBase, DiagonalMatrix<_Scalar,_Size> > { public: EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix) typedef DiagonalMatrixBase, 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 explicit inline DiagonalMatrix(const MatrixBase& other) : DiagonalBase(other) {} DiagonalMatrix& operator=(const DiagonalMatrix& other) { m_coeffs = other.m_coeffs; return *this; } template DiagonalMatrix& operator=(const MatrixBase& other) { EIGEN_STATIC_ASSERT(ei_is_diagonal::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 struct ei_traits > { typedef typename CoeffsVectorType::Scalar Scalar; typedef typename ei_nested::type CoeffsVectorTypeNested; typedef typename ei_unref::type _CoeffsVectorTypeNested; enum { RowsAtCompileTime = CoeffsVectorType::SizeAtCompileTime, ColsAtCompileTime = CoeffsVectorType::SizeAtCompileTime, MaxRowsAtCompileTime = CoeffsVectorType::MaxSizeAtCompileTime, MaxColsAtCompileTime = CoeffsVectorType::MaxSizeAtCompileTime, Flags = (_CoeffsVectorTypeNested::Flags & HereditaryBits) | DiagonalBits, CoeffReadCost = _CoeffsVectorTypeNested::CoeffReadCost }; }; template class DiagonalMatrixWrapper : public DiagonalMatrixBase > { typedef typename CoeffsVectorType::Nested CoeffsVectorTypeNested; typedef DiagonalMatrixBase > 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 inline const DiagonalMatrixWrapper MatrixBase::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 bool MatrixBase::isDiagonal (RealScalar prec) const { if(cols() != rows()) return false; RealScalar maxAbsOnDiagonal = static_cast(-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