DiagonalMatrix.h 12.4 KB
Newer Older
LM's avatar
LM committed
1 2 3 4 5 6
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
//
Don Gagne's avatar
Don Gagne committed
7 8 9
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
LM's avatar
LM committed
10 11 12 13

#ifndef EIGEN_DIAGONALMATRIX_H
#define EIGEN_DIAGONALMATRIX_H

Don Gagne's avatar
Don Gagne committed
14 15
namespace Eigen { 

LM's avatar
LM committed
16 17 18 19 20 21 22
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename Derived>
class DiagonalBase : public EigenBase<Derived>
{
  public:
    typedef typename internal::traits<Derived>::DiagonalVectorType DiagonalVectorType;
    typedef typename DiagonalVectorType::Scalar Scalar;
Don Gagne's avatar
Don Gagne committed
23
    typedef typename DiagonalVectorType::RealScalar RealScalar;
LM's avatar
LM committed
24
    typedef typename internal::traits<Derived>::StorageKind StorageKind;
25
    typedef typename internal::traits<Derived>::StorageIndex StorageIndex;
LM's avatar
LM committed
26 27 28 29 30 31 32

    enum {
      RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
      ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
      MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
      MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
      IsVectorAtCompileTime = 0,
33
      Flags = NoPreferredStorageOrderBit
LM's avatar
LM committed
34 35 36 37 38 39
    };

    typedef Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, 0, MaxRowsAtCompileTime, MaxColsAtCompileTime> DenseMatrixType;
    typedef DenseMatrixType DenseType;
    typedef DiagonalMatrix<Scalar,DiagonalVectorType::SizeAtCompileTime,DiagonalVectorType::MaxSizeAtCompileTime> PlainObject;

40
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
41
    inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
42
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
43 44
    inline Derived& derived() { return *static_cast<Derived*>(this); }

45
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
46
    DenseMatrixType toDenseMatrix() const { return derived(); }
47 48
    
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
49
    inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
50
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
51 52
    inline DiagonalVectorType& diagonal() { return derived().diagonal(); }

53
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
54
    inline Index rows() const { return diagonal().size(); }
55
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
56 57 58
    inline Index cols() const { return diagonal().size(); }

    template<typename MatrixDerived>
59 60
    EIGEN_DEVICE_FUNC
    const Product<Derived,MatrixDerived,LazyProduct>
Don Gagne's avatar
Don Gagne committed
61 62
    operator*(const MatrixBase<MatrixDerived> &matrix) const
    {
63
      return Product<Derived, MatrixDerived, LazyProduct>(derived(),matrix.derived());
Don Gagne's avatar
Don Gagne committed
64
    }
LM's avatar
LM committed
65

66 67 68
    typedef DiagonalWrapper<const CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const DiagonalVectorType> > InverseReturnType;
    EIGEN_DEVICE_FUNC
    inline const InverseReturnType
LM's avatar
LM committed
69 70
    inverse() const
    {
71
      return InverseReturnType(diagonal().cwiseInverse());
LM's avatar
LM committed
72 73
    }
    
74 75
    EIGEN_DEVICE_FUNC
    inline const DiagonalWrapper<const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DiagonalVectorType,Scalar,product) >
Don Gagne's avatar
Don Gagne committed
76 77
    operator*(const Scalar& scalar) const
    {
78
      return DiagonalWrapper<const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DiagonalVectorType,Scalar,product) >(diagonal() * scalar);
Don Gagne's avatar
Don Gagne committed
79
    }
80 81
    EIGEN_DEVICE_FUNC
    friend inline const DiagonalWrapper<const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar,DiagonalVectorType,product) >
Don Gagne's avatar
Don Gagne committed
82 83
    operator*(const Scalar& scalar, const DiagonalBase& other)
    {
84
      return DiagonalWrapper<const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar,DiagonalVectorType,product) >(scalar * other.diagonal());
LM's avatar
LM committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
    }
};

#endif

/** \class DiagonalMatrix
  * \ingroup Core_Module
  *
  * \brief Represents a diagonal matrix with its storage
  *
  * \param _Scalar the type of coefficients
  * \param SizeAtCompileTime the dimension of the matrix, or Dynamic
  * \param MaxSizeAtCompileTime the dimension of the matrix, or Dynamic. This parameter is optional and defaults
  *        to SizeAtCompileTime. Most of the time, you do not need to specify it.
  *
  * \sa class DiagonalWrapper
  */

namespace internal {
template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime>
struct traits<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> >
 : traits<Matrix<_Scalar,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
{
  typedef Matrix<_Scalar,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1> DiagonalVectorType;
109
  typedef DiagonalShape StorageKind;
LM's avatar
LM committed
110
  enum {
111
    Flags = LvalueBit | NoPreferredStorageOrderBit
LM's avatar
LM committed
112 113 114 115 116 117 118 119 120 121 122 123 124
  };
};
}
template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime>
class DiagonalMatrix
  : public DiagonalBase<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> >
{
  public:
    #ifndef EIGEN_PARSED_BY_DOXYGEN
    typedef typename internal::traits<DiagonalMatrix>::DiagonalVectorType DiagonalVectorType;
    typedef const DiagonalMatrix& Nested;
    typedef _Scalar Scalar;
    typedef typename internal::traits<DiagonalMatrix>::StorageKind StorageKind;
125
    typedef typename internal::traits<DiagonalMatrix>::StorageIndex StorageIndex;
LM's avatar
LM committed
126 127 128 129 130 131 132 133 134
    #endif

  protected:

    DiagonalVectorType m_diagonal;

  public:

    /** const version of diagonal(). */
135
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
136 137
    inline const DiagonalVectorType& diagonal() const { return m_diagonal; }
    /** \returns a reference to the stored vector of diagonal coefficients. */
138
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
139 140 141
    inline DiagonalVectorType& diagonal() { return m_diagonal; }

    /** Default constructor without initialization */
142
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
143 144 145
    inline DiagonalMatrix() {}

    /** Constructs a diagonal matrix with given dimension  */
146 147
    EIGEN_DEVICE_FUNC
    explicit inline DiagonalMatrix(Index dim) : m_diagonal(dim) {}
LM's avatar
LM committed
148 149

    /** 2D constructor. */
150
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
151 152 153
    inline DiagonalMatrix(const Scalar& x, const Scalar& y) : m_diagonal(x,y) {}

    /** 3D constructor. */
154
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
155 156 157 158
    inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z) : m_diagonal(x,y,z) {}

    /** Copy constructor. */
    template<typename OtherDerived>
159
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
160 161 162 163 164 165 166 167 168
    inline DiagonalMatrix(const DiagonalBase<OtherDerived>& other) : m_diagonal(other.diagonal()) {}

    #ifndef EIGEN_PARSED_BY_DOXYGEN
    /** copy constructor. prevent a default copy constructor from hiding the other templated constructor */
    inline DiagonalMatrix(const DiagonalMatrix& other) : m_diagonal(other.diagonal()) {}
    #endif

    /** generic constructor from expression of the diagonal coefficients */
    template<typename OtherDerived>
169
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
170 171 172 173 174
    explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : m_diagonal(other)
    {}

    /** Copy operator. */
    template<typename OtherDerived>
175
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
176 177 178 179 180 181 182 183 184 185
    DiagonalMatrix& operator=(const DiagonalBase<OtherDerived>& other)
    {
      m_diagonal = other.diagonal();
      return *this;
    }

    #ifndef EIGEN_PARSED_BY_DOXYGEN
    /** This is a special case of the templated operator=. Its purpose is to
      * prevent a default operator= from hiding the templated operator=.
      */
186
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
187 188 189 190 191 192 193 194
    DiagonalMatrix& operator=(const DiagonalMatrix& other)
    {
      m_diagonal = other.diagonal();
      return *this;
    }
    #endif

    /** Resizes to given size. */
195
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
196 197
    inline void resize(Index size) { m_diagonal.resize(size); }
    /** Sets all coefficients to zero. */
198
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
199 200
    inline void setZero() { m_diagonal.setZero(); }
    /** Resizes and sets all coefficients to zero. */
201
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
202 203
    inline void setZero(Index size) { m_diagonal.setZero(size); }
    /** Sets this matrix to be the identity matrix of the current size. */
204
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
205 206
    inline void setIdentity() { m_diagonal.setOnes(); }
    /** Sets this matrix to be the identity matrix of the given size. */
207
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
    inline void setIdentity(Index size) { m_diagonal.setOnes(size); }
};

/** \class DiagonalWrapper
  * \ingroup Core_Module
  *
  * \brief Expression of a diagonal matrix
  *
  * \param _DiagonalVectorType the type of the vector of diagonal coefficients
  *
  * This class is an expression of a diagonal matrix, but not storing its own vector of diagonal coefficients,
  * instead wrapping an existing vector expression. It is the return type of MatrixBase::asDiagonal()
  * and most of the time this is the only way that it is used.
  *
  * \sa class DiagonalMatrix, class DiagonalBase, MatrixBase::asDiagonal()
  */

namespace internal {
template<typename _DiagonalVectorType>
struct traits<DiagonalWrapper<_DiagonalVectorType> >
{
  typedef _DiagonalVectorType DiagonalVectorType;
  typedef typename DiagonalVectorType::Scalar Scalar;
231 232 233
  typedef typename DiagonalVectorType::StorageIndex StorageIndex;
  typedef DiagonalShape StorageKind;
  typedef typename traits<DiagonalVectorType>::XprKind XprKind;
LM's avatar
LM committed
234 235 236
  enum {
    RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
    ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
237 238 239
    MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
    MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
    Flags =  (traits<DiagonalVectorType>::Flags & LvalueBit) | NoPreferredStorageOrderBit
LM's avatar
LM committed
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
  };
};
}

template<typename _DiagonalVectorType>
class DiagonalWrapper
  : public DiagonalBase<DiagonalWrapper<_DiagonalVectorType> >, internal::no_assignment_operator
{
  public:
    #ifndef EIGEN_PARSED_BY_DOXYGEN
    typedef _DiagonalVectorType DiagonalVectorType;
    typedef DiagonalWrapper Nested;
    #endif

    /** Constructor from expression of diagonal coefficients to wrap. */
255 256
    EIGEN_DEVICE_FUNC
    explicit inline DiagonalWrapper(DiagonalVectorType& a_diagonal) : m_diagonal(a_diagonal) {}
LM's avatar
LM committed
257 258

    /** \returns a const reference to the wrapped expression of diagonal coefficients. */
259
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
260 261 262
    const DiagonalVectorType& diagonal() const { return m_diagonal; }

  protected:
Don Gagne's avatar
Don Gagne committed
263
    typename DiagonalVectorType::Nested m_diagonal;
LM's avatar
LM committed
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
};

/** \returns a pseudo-expression of a diagonal matrix with *this as vector of diagonal coefficients
  *
  * \only_for_vectors
  *
  * Example: \include MatrixBase_asDiagonal.cpp
  * Output: \verbinclude MatrixBase_asDiagonal.out
  *
  * \sa class DiagonalWrapper, class DiagonalMatrix, diagonal(), isDiagonal()
  **/
template<typename Derived>
inline const DiagonalWrapper<const Derived>
MatrixBase<Derived>::asDiagonal() const
{
279
  return DiagonalWrapper<const Derived>(derived());
LM's avatar
LM committed
280 281 282 283 284 285 286 287 288 289 290
}

/** \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>
Don Gagne's avatar
Don Gagne committed
291
bool MatrixBase<Derived>::isDiagonal(const RealScalar& prec) const
LM's avatar
LM committed
292 293 294 295 296
{
  if(cols() != rows()) return false;
  RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
  for(Index j = 0; j < cols(); ++j)
  {
297
    RealScalar absOnDiagonal = numext::abs(coeff(j,j));
LM's avatar
LM committed
298 299 300 301 302 303 304 305 306 307 308
    if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
  }
  for(Index j = 0; j < cols(); ++j)
    for(Index i = 0; i < j; ++i)
    {
      if(!internal::isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false;
      if(!internal::isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false;
    }
  return true;
}

309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
namespace internal {

template<> struct storage_kind_to_shape<DiagonalShape> { typedef DiagonalShape Shape; };

struct Diagonal2Dense {};

template<> struct AssignmentKind<DenseShape,DiagonalShape> { typedef Diagonal2Dense Kind; };

// Diagonal matrix to Dense assignment
template< typename DstXprType, typename SrcXprType, typename Functor>
struct Assignment<DstXprType, SrcXprType, Functor, Diagonal2Dense>
{
  static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
  {
    Index dstRows = src.rows();
    Index dstCols = src.cols();
    if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
      dst.resize(dstRows, dstCols);
    
    dst.setZero();
    dst.diagonal() = src.diagonal();
  }
  
  static void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
  { dst.diagonal() += src.diagonal(); }
  
  static void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
  { dst.diagonal() -= src.diagonal(); }
};

} // namespace internal

Don Gagne's avatar
Don Gagne committed
341 342
} // end namespace Eigen

LM's avatar
LM committed
343
#endif // EIGEN_DIAGONALMATRIX_H