xref: /aosp_15_r20/external/eigen/Eigen/src/Core/DiagonalMatrix.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2009 Gael Guennebaud <[email protected]>
5 // Copyright (C) 2007-2009 Benoit Jacob <[email protected]>
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 DiagonalVectorType::RealScalar RealScalar;
24     typedef typename internal::traits<Derived>::StorageKind StorageKind;
25     typedef typename internal::traits<Derived>::StorageIndex StorageIndex;
26 
27     enum {
28       RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
29       ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
30       MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
31       MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
32       IsVectorAtCompileTime = 0,
33       Flags = NoPreferredStorageOrderBit
34     };
35 
36     typedef Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, 0, MaxRowsAtCompileTime, MaxColsAtCompileTime> DenseMatrixType;
37     typedef DenseMatrixType DenseType;
38     typedef DiagonalMatrix<Scalar,DiagonalVectorType::SizeAtCompileTime,DiagonalVectorType::MaxSizeAtCompileTime> PlainObject;
39 
40     EIGEN_DEVICE_FUNC
derived()41     inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
42     EIGEN_DEVICE_FUNC
derived()43     inline Derived& derived() { return *static_cast<Derived*>(this); }
44 
45     EIGEN_DEVICE_FUNC
toDenseMatrix()46     DenseMatrixType toDenseMatrix() const { return derived(); }
47 
48     EIGEN_DEVICE_FUNC
diagonal()49     inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
50     EIGEN_DEVICE_FUNC
diagonal()51     inline DiagonalVectorType& diagonal() { return derived().diagonal(); }
52 
53     EIGEN_DEVICE_FUNC
rows()54     inline Index rows() const { return diagonal().size(); }
55     EIGEN_DEVICE_FUNC
cols()56     inline Index cols() const { return diagonal().size(); }
57 
58     template<typename MatrixDerived>
59     EIGEN_DEVICE_FUNC
60     const Product<Derived,MatrixDerived,LazyProduct>
61     operator*(const MatrixBase<MatrixDerived> &matrix) const
62     {
63       return Product<Derived, MatrixDerived, LazyProduct>(derived(),matrix.derived());
64     }
65 
66     typedef DiagonalWrapper<const CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const DiagonalVectorType> > InverseReturnType;
67     EIGEN_DEVICE_FUNC
68     inline const InverseReturnType
inverse()69     inverse() const
70     {
71       return InverseReturnType(diagonal().cwiseInverse());
72     }
73 
74     EIGEN_DEVICE_FUNC
75     inline const DiagonalWrapper<const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DiagonalVectorType,Scalar,product) >
76     operator*(const Scalar& scalar) const
77     {
78       return DiagonalWrapper<const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DiagonalVectorType,Scalar,product) >(diagonal() * scalar);
79     }
80     EIGEN_DEVICE_FUNC
81     friend inline const DiagonalWrapper<const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar,DiagonalVectorType,product) >
82     operator*(const Scalar& scalar, const DiagonalBase& other)
83     {
84       return DiagonalWrapper<const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar,DiagonalVectorType,product) >(scalar * other.diagonal());
85     }
86 
87     template<typename OtherDerived>
88     EIGEN_DEVICE_FUNC
89     #ifdef EIGEN_PARSED_BY_DOXYGEN
90     inline unspecified_expression_type
91     #else
92     inline const DiagonalWrapper<const EIGEN_CWISE_BINARY_RETURN_TYPE(DiagonalVectorType,typename OtherDerived::DiagonalVectorType,sum) >
93     #endif
94     operator+(const DiagonalBase<OtherDerived>& other) const
95     {
96       return (diagonal() + other.diagonal()).asDiagonal();
97     }
98 
99     template<typename OtherDerived>
100     EIGEN_DEVICE_FUNC
101     #ifdef EIGEN_PARSED_BY_DOXYGEN
102     inline unspecified_expression_type
103     #else
104     inline const DiagonalWrapper<const EIGEN_CWISE_BINARY_RETURN_TYPE(DiagonalVectorType,typename OtherDerived::DiagonalVectorType,difference) >
105     #endif
106     operator-(const DiagonalBase<OtherDerived>& other) const
107     {
108       return (diagonal() - other.diagonal()).asDiagonal();
109     }
110 };
111 
112 #endif
113 
114 /** \class DiagonalMatrix
115   * \ingroup Core_Module
116   *
117   * \brief Represents a diagonal matrix with its storage
118   *
119   * \param _Scalar the type of coefficients
120   * \param SizeAtCompileTime the dimension of the matrix, or Dynamic
121   * \param MaxSizeAtCompileTime the dimension of the matrix, or Dynamic. This parameter is optional and defaults
122   *        to SizeAtCompileTime. Most of the time, you do not need to specify it.
123   *
124   * \sa class DiagonalWrapper
125   */
126 
127 namespace internal {
128 template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime>
129 struct traits<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> >
130  : traits<Matrix<_Scalar,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
131 {
132   typedef Matrix<_Scalar,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1> DiagonalVectorType;
133   typedef DiagonalShape StorageKind;
134   enum {
135     Flags = LvalueBit | NoPreferredStorageOrderBit
136   };
137 };
138 }
139 template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime>
140 class DiagonalMatrix
141   : public DiagonalBase<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> >
142 {
143   public:
144     #ifndef EIGEN_PARSED_BY_DOXYGEN
145     typedef typename internal::traits<DiagonalMatrix>::DiagonalVectorType DiagonalVectorType;
146     typedef const DiagonalMatrix& Nested;
147     typedef _Scalar Scalar;
148     typedef typename internal::traits<DiagonalMatrix>::StorageKind StorageKind;
149     typedef typename internal::traits<DiagonalMatrix>::StorageIndex StorageIndex;
150     #endif
151 
152   protected:
153 
154     DiagonalVectorType m_diagonal;
155 
156   public:
157 
158     /** const version of diagonal(). */
159     EIGEN_DEVICE_FUNC
160     inline const DiagonalVectorType& diagonal() const { return m_diagonal; }
161     /** \returns a reference to the stored vector of diagonal coefficients. */
162     EIGEN_DEVICE_FUNC
163     inline DiagonalVectorType& diagonal() { return m_diagonal; }
164 
165     /** Default constructor without initialization */
166     EIGEN_DEVICE_FUNC
167     inline DiagonalMatrix() {}
168 
169     /** Constructs a diagonal matrix with given dimension  */
170     EIGEN_DEVICE_FUNC
171     explicit inline DiagonalMatrix(Index dim) : m_diagonal(dim) {}
172 
173     /** 2D constructor. */
174     EIGEN_DEVICE_FUNC
175     inline DiagonalMatrix(const Scalar& x, const Scalar& y) : m_diagonal(x,y) {}
176 
177     /** 3D constructor. */
178     EIGEN_DEVICE_FUNC
179     inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z) : m_diagonal(x,y,z) {}
180 
181     #if EIGEN_HAS_CXX11
182     /** \brief Construct a diagonal matrix with fixed size from an arbitrary number of coefficients. \cpp11
183       *
184       * There exists C++98 anologue constructors for fixed-size diagonal matrices having 2 or 3 coefficients.
185       *
186       * \warning To construct a diagonal matrix of fixed size, the number of values passed to this
187       * constructor must match the fixed dimension of \c *this.
188       *
189       * \sa DiagonalMatrix(const Scalar&, const Scalar&)
190       * \sa DiagonalMatrix(const Scalar&, const Scalar&, const Scalar&)
191       */
192     template <typename... ArgTypes>
193     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
194     DiagonalMatrix(const Scalar& a0, const Scalar& a1, const Scalar& a2, const ArgTypes&... args)
195       : m_diagonal(a0, a1, a2, args...) {}
196 
197     /** \brief Constructs a DiagonalMatrix and initializes it by elements given by an initializer list of initializer
198       * lists \cpp11
199       */
200     EIGEN_DEVICE_FUNC
201     explicit EIGEN_STRONG_INLINE DiagonalMatrix(const std::initializer_list<std::initializer_list<Scalar>>& list)
202       : m_diagonal(list) {}
203     #endif  // EIGEN_HAS_CXX11
204 
205     /** Copy constructor. */
206     template<typename OtherDerived>
207     EIGEN_DEVICE_FUNC
208     inline DiagonalMatrix(const DiagonalBase<OtherDerived>& other) : m_diagonal(other.diagonal()) {}
209 
210     #ifndef EIGEN_PARSED_BY_DOXYGEN
211     /** copy constructor. prevent a default copy constructor from hiding the other templated constructor */
212     inline DiagonalMatrix(const DiagonalMatrix& other) : m_diagonal(other.diagonal()) {}
213     #endif
214 
215     /** generic constructor from expression of the diagonal coefficients */
216     template<typename OtherDerived>
217     EIGEN_DEVICE_FUNC
218     explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : m_diagonal(other)
219     {}
220 
221     /** Copy operator. */
222     template<typename OtherDerived>
223     EIGEN_DEVICE_FUNC
224     DiagonalMatrix& operator=(const DiagonalBase<OtherDerived>& other)
225     {
226       m_diagonal = other.diagonal();
227       return *this;
228     }
229 
230     #ifndef EIGEN_PARSED_BY_DOXYGEN
231     /** This is a special case of the templated operator=. Its purpose is to
232       * prevent a default operator= from hiding the templated operator=.
233       */
234     EIGEN_DEVICE_FUNC
235     DiagonalMatrix& operator=(const DiagonalMatrix& other)
236     {
237       m_diagonal = other.diagonal();
238       return *this;
239     }
240     #endif
241 
242     /** Resizes to given size. */
243     EIGEN_DEVICE_FUNC
244     inline void resize(Index size) { m_diagonal.resize(size); }
245     /** Sets all coefficients to zero. */
246     EIGEN_DEVICE_FUNC
247     inline void setZero() { m_diagonal.setZero(); }
248     /** Resizes and sets all coefficients to zero. */
249     EIGEN_DEVICE_FUNC
250     inline void setZero(Index size) { m_diagonal.setZero(size); }
251     /** Sets this matrix to be the identity matrix of the current size. */
252     EIGEN_DEVICE_FUNC
253     inline void setIdentity() { m_diagonal.setOnes(); }
254     /** Sets this matrix to be the identity matrix of the given size. */
255     EIGEN_DEVICE_FUNC
256     inline void setIdentity(Index size) { m_diagonal.setOnes(size); }
257 };
258 
259 /** \class DiagonalWrapper
260   * \ingroup Core_Module
261   *
262   * \brief Expression of a diagonal matrix
263   *
264   * \param _DiagonalVectorType the type of the vector of diagonal coefficients
265   *
266   * This class is an expression of a diagonal matrix, but not storing its own vector of diagonal coefficients,
267   * instead wrapping an existing vector expression. It is the return type of MatrixBase::asDiagonal()
268   * and most of the time this is the only way that it is used.
269   *
270   * \sa class DiagonalMatrix, class DiagonalBase, MatrixBase::asDiagonal()
271   */
272 
273 namespace internal {
274 template<typename _DiagonalVectorType>
275 struct traits<DiagonalWrapper<_DiagonalVectorType> >
276 {
277   typedef _DiagonalVectorType DiagonalVectorType;
278   typedef typename DiagonalVectorType::Scalar Scalar;
279   typedef typename DiagonalVectorType::StorageIndex StorageIndex;
280   typedef DiagonalShape StorageKind;
281   typedef typename traits<DiagonalVectorType>::XprKind XprKind;
282   enum {
283     RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
284     ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
285     MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
286     MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
287     Flags =  (traits<DiagonalVectorType>::Flags & LvalueBit) | NoPreferredStorageOrderBit
288   };
289 };
290 }
291 
292 template<typename _DiagonalVectorType>
293 class DiagonalWrapper
294   : public DiagonalBase<DiagonalWrapper<_DiagonalVectorType> >, internal::no_assignment_operator
295 {
296   public:
297     #ifndef EIGEN_PARSED_BY_DOXYGEN
298     typedef _DiagonalVectorType DiagonalVectorType;
299     typedef DiagonalWrapper Nested;
300     #endif
301 
302     /** Constructor from expression of diagonal coefficients to wrap. */
303     EIGEN_DEVICE_FUNC
304     explicit inline DiagonalWrapper(DiagonalVectorType& a_diagonal) : m_diagonal(a_diagonal) {}
305 
306     /** \returns a const reference to the wrapped expression of diagonal coefficients. */
307     EIGEN_DEVICE_FUNC
308     const DiagonalVectorType& diagonal() const { return m_diagonal; }
309 
310   protected:
311     typename DiagonalVectorType::Nested m_diagonal;
312 };
313 
314 /** \returns a pseudo-expression of a diagonal matrix with *this as vector of diagonal coefficients
315   *
316   * \only_for_vectors
317   *
318   * Example: \include MatrixBase_asDiagonal.cpp
319   * Output: \verbinclude MatrixBase_asDiagonal.out
320   *
321   * \sa class DiagonalWrapper, class DiagonalMatrix, diagonal(), isDiagonal()
322   **/
323 template<typename Derived>
324 EIGEN_DEVICE_FUNC inline const DiagonalWrapper<const Derived>
325 MatrixBase<Derived>::asDiagonal() const
326 {
327   return DiagonalWrapper<const Derived>(derived());
328 }
329 
330 /** \returns true if *this is approximately equal to a diagonal matrix,
331   *          within the precision given by \a prec.
332   *
333   * Example: \include MatrixBase_isDiagonal.cpp
334   * Output: \verbinclude MatrixBase_isDiagonal.out
335   *
336   * \sa asDiagonal()
337   */
338 template<typename Derived>
339 bool MatrixBase<Derived>::isDiagonal(const RealScalar& prec) const
340 {
341   if(cols() != rows()) return false;
342   RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
343   for(Index j = 0; j < cols(); ++j)
344   {
345     RealScalar absOnDiagonal = numext::abs(coeff(j,j));
346     if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
347   }
348   for(Index j = 0; j < cols(); ++j)
349     for(Index i = 0; i < j; ++i)
350     {
351       if(!internal::isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false;
352       if(!internal::isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false;
353     }
354   return true;
355 }
356 
357 namespace internal {
358 
359 template<> struct storage_kind_to_shape<DiagonalShape> { typedef DiagonalShape Shape; };
360 
361 struct Diagonal2Dense {};
362 
363 template<> struct AssignmentKind<DenseShape,DiagonalShape> { typedef Diagonal2Dense Kind; };
364 
365 // Diagonal matrix to Dense assignment
366 template< typename DstXprType, typename SrcXprType, typename Functor>
367 struct Assignment<DstXprType, SrcXprType, Functor, Diagonal2Dense>
368 {
369   static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
370   {
371     Index dstRows = src.rows();
372     Index dstCols = src.cols();
373     if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
374       dst.resize(dstRows, dstCols);
375 
376     dst.setZero();
377     dst.diagonal() = src.diagonal();
378   }
379 
380   static void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
381   { dst.diagonal() += src.diagonal(); }
382 
383   static void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
384   { dst.diagonal() -= src.diagonal(); }
385 };
386 
387 } // namespace internal
388 
389 } // end namespace Eigen
390 
391 #endif // EIGEN_DIAGONALMATRIX_H
392