• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // This file is part of Eigen, a lightweight C++ template library
2  // for linear algebra.
3  //
4  // Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5  // Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
6  //
7  // This Source Code Form is subject to the terms of the Mozilla
8  // Public License v. 2.0. If a copy of the MPL was not distributed
9  // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10  
11  #ifndef EIGEN_DIAGONALMATRIX_H
12  #define EIGEN_DIAGONALMATRIX_H
13  
14  namespace Eigen {
15  
16  #ifndef EIGEN_PARSED_BY_DOXYGEN
17  template<typename Derived>
18  class DiagonalBase : public EigenBase<Derived>
19  {
20    public:
21      typedef typename internal::traits<Derived>::DiagonalVectorType DiagonalVectorType;
22      typedef typename DiagonalVectorType::Scalar Scalar;
23      typedef typename internal::traits<Derived>::StorageKind StorageKind;
24      typedef typename internal::traits<Derived>::Index Index;
25  
26      enum {
27        RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
28        ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
29        MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
30        MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
31        IsVectorAtCompileTime = 0,
32        Flags = 0
33      };
34  
35      typedef Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, 0, MaxRowsAtCompileTime, MaxColsAtCompileTime> DenseMatrixType;
36      typedef DenseMatrixType DenseType;
37      typedef DiagonalMatrix<Scalar,DiagonalVectorType::SizeAtCompileTime,DiagonalVectorType::MaxSizeAtCompileTime> PlainObject;
38  
derived()39      inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
derived()40      inline Derived& derived() { return *static_cast<Derived*>(this); }
41  
toDenseMatrix()42      DenseMatrixType toDenseMatrix() const { return derived(); }
43      template<typename DenseDerived>
44      void evalTo(MatrixBase<DenseDerived> &other) const;
45      template<typename DenseDerived>
addTo(MatrixBase<DenseDerived> & other)46      void addTo(MatrixBase<DenseDerived> &other) const
47      { other.diagonal() += diagonal(); }
48      template<typename DenseDerived>
subTo(MatrixBase<DenseDerived> & other)49      void subTo(MatrixBase<DenseDerived> &other) const
50      { other.diagonal() -= diagonal(); }
51  
diagonal()52      inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
diagonal()53      inline DiagonalVectorType& diagonal() { return derived().diagonal(); }
54  
rows()55      inline Index rows() const { return diagonal().size(); }
cols()56      inline Index cols() const { return diagonal().size(); }
57  
58      template<typename MatrixDerived>
59      const DiagonalProduct<MatrixDerived, Derived, OnTheLeft>
60      operator*(const MatrixBase<MatrixDerived> &matrix) const;
61  
62      inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const DiagonalVectorType> >
inverse()63      inverse() const
64      {
65        return diagonal().cwiseInverse();
66      }
67  
68      #ifdef EIGEN2_SUPPORT
69      template<typename OtherDerived>
70      bool isApprox(const DiagonalBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
71      {
72        return diagonal().isApprox(other.diagonal(), precision);
73      }
74      template<typename OtherDerived>
75      bool isApprox(const MatrixBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
76      {
77        return toDenseMatrix().isApprox(other, precision);
78      }
79      #endif
80  };
81  
82  template<typename Derived>
83  template<typename DenseDerived>
evalTo(MatrixBase<DenseDerived> & other)84  void DiagonalBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const
85  {
86    other.setZero();
87    other.diagonal() = diagonal();
88  }
89  #endif
90  
91  /** \class DiagonalMatrix
92    * \ingroup Core_Module
93    *
94    * \brief Represents a diagonal matrix with its storage
95    *
96    * \param _Scalar the type of coefficients
97    * \param SizeAtCompileTime the dimension of the matrix, or Dynamic
98    * \param MaxSizeAtCompileTime the dimension of the matrix, or Dynamic. This parameter is optional and defaults
99    *        to SizeAtCompileTime. Most of the time, you do not need to specify it.
100    *
101    * \sa class DiagonalWrapper
102    */
103  
104  namespace internal {
105  template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime>
106  struct traits<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> >
107   : traits<Matrix<_Scalar,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
108  {
109    typedef Matrix<_Scalar,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1> DiagonalVectorType;
110    typedef Dense StorageKind;
111    typedef DenseIndex Index;
112    enum {
113      Flags = LvalueBit
114    };
115  };
116  }
117  template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime>
118  class DiagonalMatrix
119    : public DiagonalBase<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> >
120  {
121    public:
122      #ifndef EIGEN_PARSED_BY_DOXYGEN
123      typedef typename internal::traits<DiagonalMatrix>::DiagonalVectorType DiagonalVectorType;
124      typedef const DiagonalMatrix& Nested;
125      typedef _Scalar Scalar;
126      typedef typename internal::traits<DiagonalMatrix>::StorageKind StorageKind;
127      typedef typename internal::traits<DiagonalMatrix>::Index Index;
128      #endif
129  
130    protected:
131  
132      DiagonalVectorType m_diagonal;
133  
134    public:
135  
136      /** const version of diagonal(). */
137      inline const DiagonalVectorType& diagonal() const { return m_diagonal; }
138      /** \returns a reference to the stored vector of diagonal coefficients. */
139      inline DiagonalVectorType& diagonal() { return m_diagonal; }
140  
141      /** Default constructor without initialization */
142      inline DiagonalMatrix() {}
143  
144      /** Constructs a diagonal matrix with given dimension  */
145      inline DiagonalMatrix(Index dim) : m_diagonal(dim) {}
146  
147      /** 2D constructor. */
148      inline DiagonalMatrix(const Scalar& x, const Scalar& y) : m_diagonal(x,y) {}
149  
150      /** 3D constructor. */
151      inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z) : m_diagonal(x,y,z) {}
152  
153      /** Copy constructor. */
154      template<typename OtherDerived>
155      inline DiagonalMatrix(const DiagonalBase<OtherDerived>& other) : m_diagonal(other.diagonal()) {}
156  
157      #ifndef EIGEN_PARSED_BY_DOXYGEN
158      /** copy constructor. prevent a default copy constructor from hiding the other templated constructor */
159      inline DiagonalMatrix(const DiagonalMatrix& other) : m_diagonal(other.diagonal()) {}
160      #endif
161  
162      /** generic constructor from expression of the diagonal coefficients */
163      template<typename OtherDerived>
164      explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : m_diagonal(other)
165      {}
166  
167      /** Copy operator. */
168      template<typename OtherDerived>
169      DiagonalMatrix& operator=(const DiagonalBase<OtherDerived>& other)
170      {
171        m_diagonal = other.diagonal();
172        return *this;
173      }
174  
175      #ifndef EIGEN_PARSED_BY_DOXYGEN
176      /** This is a special case of the templated operator=. Its purpose is to
177        * prevent a default operator= from hiding the templated operator=.
178        */
179      DiagonalMatrix& operator=(const DiagonalMatrix& other)
180      {
181        m_diagonal = other.diagonal();
182        return *this;
183      }
184      #endif
185  
186      /** Resizes to given size. */
187      inline void resize(Index size) { m_diagonal.resize(size); }
188      /** Sets all coefficients to zero. */
189      inline void setZero() { m_diagonal.setZero(); }
190      /** Resizes and sets all coefficients to zero. */
191      inline void setZero(Index size) { m_diagonal.setZero(size); }
192      /** Sets this matrix to be the identity matrix of the current size. */
193      inline void setIdentity() { m_diagonal.setOnes(); }
194      /** Sets this matrix to be the identity matrix of the given size. */
195      inline void setIdentity(Index size) { m_diagonal.setOnes(size); }
196  };
197  
198  /** \class DiagonalWrapper
199    * \ingroup Core_Module
200    *
201    * \brief Expression of a diagonal matrix
202    *
203    * \param _DiagonalVectorType the type of the vector of diagonal coefficients
204    *
205    * This class is an expression of a diagonal matrix, but not storing its own vector of diagonal coefficients,
206    * instead wrapping an existing vector expression. It is the return type of MatrixBase::asDiagonal()
207    * and most of the time this is the only way that it is used.
208    *
209    * \sa class DiagonalMatrix, class DiagonalBase, MatrixBase::asDiagonal()
210    */
211  
212  namespace internal {
213  template<typename _DiagonalVectorType>
214  struct traits<DiagonalWrapper<_DiagonalVectorType> >
215  {
216    typedef _DiagonalVectorType DiagonalVectorType;
217    typedef typename DiagonalVectorType::Scalar Scalar;
218    typedef typename DiagonalVectorType::Index Index;
219    typedef typename DiagonalVectorType::StorageKind StorageKind;
220    enum {
221      RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
222      ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
223      MaxRowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
224      MaxColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
225      Flags =  traits<DiagonalVectorType>::Flags & LvalueBit
226    };
227  };
228  }
229  
230  template<typename _DiagonalVectorType>
231  class DiagonalWrapper
232    : public DiagonalBase<DiagonalWrapper<_DiagonalVectorType> >, internal::no_assignment_operator
233  {
234    public:
235      #ifndef EIGEN_PARSED_BY_DOXYGEN
236      typedef _DiagonalVectorType DiagonalVectorType;
237      typedef DiagonalWrapper Nested;
238      #endif
239  
240      /** Constructor from expression of diagonal coefficients to wrap. */
241      inline DiagonalWrapper(DiagonalVectorType& diagonal) : m_diagonal(diagonal) {}
242  
243      /** \returns a const reference to the wrapped expression of diagonal coefficients. */
244      const DiagonalVectorType& diagonal() const { return m_diagonal; }
245  
246    protected:
247      typename DiagonalVectorType::Nested m_diagonal;
248  };
249  
250  /** \returns a pseudo-expression of a diagonal matrix with *this as vector of diagonal coefficients
251    *
252    * \only_for_vectors
253    *
254    * Example: \include MatrixBase_asDiagonal.cpp
255    * Output: \verbinclude MatrixBase_asDiagonal.out
256    *
257    * \sa class DiagonalWrapper, class DiagonalMatrix, diagonal(), isDiagonal()
258    **/
259  template<typename Derived>
260  inline const DiagonalWrapper<const Derived>
261  MatrixBase<Derived>::asDiagonal() const
262  {
263    return derived();
264  }
265  
266  /** \returns true if *this is approximately equal to a diagonal matrix,
267    *          within the precision given by \a prec.
268    *
269    * Example: \include MatrixBase_isDiagonal.cpp
270    * Output: \verbinclude MatrixBase_isDiagonal.out
271    *
272    * \sa asDiagonal()
273    */
274  template<typename Derived>
275  bool MatrixBase<Derived>::isDiagonal(RealScalar prec) const
276  {
277    if(cols() != rows()) return false;
278    RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
279    for(Index j = 0; j < cols(); ++j)
280    {
281      RealScalar absOnDiagonal = internal::abs(coeff(j,j));
282      if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
283    }
284    for(Index j = 0; j < cols(); ++j)
285      for(Index i = 0; i < j; ++i)
286      {
287        if(!internal::isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false;
288        if(!internal::isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false;
289      }
290    return true;
291  }
292  
293  } // end namespace Eigen
294  
295  #endif // EIGEN_DIAGONALMATRIX_H
296