Diagonal.h 9.37 KB
Newer Older
LM's avatar
LM committed
1 2 3 4
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
Don Gagne's avatar
Don Gagne committed
5
// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
LM's avatar
LM committed
6
//
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_DIAGONAL_H
#define EIGEN_DIAGONAL_H

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

LM's avatar
LM committed
16 17 18 19 20 21 22 23
/** \class Diagonal
  * \ingroup Core_Module
  *
  * \brief Expression of a diagonal/subdiagonal/superdiagonal in a matrix
  *
  * \param MatrixType the type of the object in which we are taking a sub/main/super diagonal
  * \param DiagIndex the index of the sub/super diagonal. The default is 0 and it means the main diagonal.
  *              A positive value means a superdiagonal, a negative value means a subdiagonal.
24
  *              You can also use DynamicIndex so the index can be set at runtime.
LM's avatar
LM committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
  *
  * The matrix is not required to be square.
  *
  * This class represents an expression of the main diagonal, or any sub/super diagonal
  * of a square matrix. It is the return type of MatrixBase::diagonal() and MatrixBase::diagonal(Index) and most of the
  * time this is the only way it is used.
  *
  * \sa MatrixBase::diagonal(), MatrixBase::diagonal(Index)
  */

namespace internal {
template<typename MatrixType, int DiagIndex>
struct traits<Diagonal<MatrixType,DiagIndex> >
 : traits<MatrixType>
{
40
  typedef typename ref_selector<MatrixType>::type MatrixTypeNested;
LM's avatar
LM committed
41 42 43
  typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
  typedef typename MatrixType::StorageKind StorageKind;
  enum {
Don Gagne's avatar
Don Gagne committed
44 45 46
    RowsAtCompileTime = (int(DiagIndex) == DynamicIndex || int(MatrixType::SizeAtCompileTime) == Dynamic) ? Dynamic
                      : (EIGEN_PLAIN_ENUM_MIN(MatrixType::RowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0),
                                              MatrixType::ColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))),
LM's avatar
LM committed
47 48
    ColsAtCompileTime = 1,
    MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic
Don Gagne's avatar
Don Gagne committed
49 50 51 52
                         : DiagIndex == DynamicIndex ? EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime,
                                                                              MatrixType::MaxColsAtCompileTime)
                         : (EIGEN_PLAIN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0),
                                                 MatrixType::MaxColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))),
LM's avatar
LM committed
53 54
    MaxColsAtCompileTime = 1,
    MaskLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
55
    Flags = (unsigned int)_MatrixTypeNested::Flags & (RowMajorBit | MaskLvalueBit | DirectAccessBit) & ~RowMajorBit, // FIXME DirectAccessBit should not be handled by expressions
LM's avatar
LM committed
56 57 58 59 60 61 62
    MatrixTypeOuterStride = outer_stride_at_compile_time<MatrixType>::ret,
    InnerStrideAtCompileTime = MatrixTypeOuterStride == Dynamic ? Dynamic : MatrixTypeOuterStride+1,
    OuterStrideAtCompileTime = 0
  };
};
}

Don Gagne's avatar
Don Gagne committed
63 64
template<typename MatrixType, int _DiagIndex> class Diagonal
   : public internal::dense_xpr_base< Diagonal<MatrixType,_DiagIndex> >::type
LM's avatar
LM committed
65 66 67
{
  public:

Don Gagne's avatar
Don Gagne committed
68
    enum { DiagIndex = _DiagIndex };
LM's avatar
LM committed
69 70 71
    typedef typename internal::dense_xpr_base<Diagonal>::type Base;
    EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal)

72 73 74 75 76
    EIGEN_DEVICE_FUNC
    explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index)
    {
      eigen_assert( a_index <= m_matrix.cols() && -a_index <= m_matrix.rows() );
    }
LM's avatar
LM committed
77 78 79

    EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)

80
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
81
    inline Index rows() const
82 83 84 85
    {
      return m_index.value()<0 ? numext::mini<Index>(m_matrix.cols(),m_matrix.rows()+m_index.value())
                               : numext::mini<Index>(m_matrix.rows(),m_matrix.cols()-m_index.value());
    }
LM's avatar
LM committed
86

87
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
88 89
    inline Index cols() const { return 1; }

90
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
91 92 93 94 95
    inline Index innerStride() const
    {
      return m_matrix.outerStride() + 1;
    }

96
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
97 98 99 100 101
    inline Index outerStride() const
    {
      return 0;
    }

Don Gagne's avatar
Don Gagne committed
102 103 104 105 106 107
    typedef typename internal::conditional<
                       internal::is_lvalue<MatrixType>::value,
                       Scalar,
                       const Scalar
                     >::type ScalarWithConstIfNotLvalue;

108 109 110 111
    EIGEN_DEVICE_FUNC
    inline ScalarWithConstIfNotLvalue* data() { return &(m_matrix.coeffRef(rowOffset(), colOffset())); }
    EIGEN_DEVICE_FUNC
    inline const Scalar* data() const { return &(m_matrix.coeffRef(rowOffset(), colOffset())); }
Don Gagne's avatar
Don Gagne committed
112

113
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
114 115 116
    inline Scalar& coeffRef(Index row, Index)
    {
      EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
117
      return m_matrix.coeffRef(row+rowOffset(), row+colOffset());
LM's avatar
LM committed
118 119
    }

120
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
121 122
    inline const Scalar& coeffRef(Index row, Index) const
    {
123
      return m_matrix.coeffRef(row+rowOffset(), row+colOffset());
LM's avatar
LM committed
124 125
    }

126
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
127 128 129 130 131
    inline CoeffReturnType coeff(Index row, Index) const
    {
      return m_matrix.coeff(row+rowOffset(), row+colOffset());
    }

132
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
133
    inline Scalar& coeffRef(Index idx)
LM's avatar
LM committed
134 135
    {
      EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
136
      return m_matrix.coeffRef(idx+rowOffset(), idx+colOffset());
LM's avatar
LM committed
137 138
    }

139
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
140
    inline const Scalar& coeffRef(Index idx) const
LM's avatar
LM committed
141
    {
142
      return m_matrix.coeffRef(idx+rowOffset(), idx+colOffset());
LM's avatar
LM committed
143 144
    }

145
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
146
    inline CoeffReturnType coeff(Index idx) const
LM's avatar
LM committed
147
    {
Don Gagne's avatar
Don Gagne committed
148 149 150
      return m_matrix.coeff(idx+rowOffset(), idx+colOffset());
    }

151 152
    EIGEN_DEVICE_FUNC
    inline const typename internal::remove_all<typename MatrixType::Nested>::type& 
Don Gagne's avatar
Don Gagne committed
153 154 155 156 157
    nestedExpression() const 
    {
      return m_matrix;
    }

158 159
    EIGEN_DEVICE_FUNC
    inline Index index() const
Don Gagne's avatar
Don Gagne committed
160 161
    {
      return m_index.value();
LM's avatar
LM committed
162 163 164
    }

  protected:
165
    typename internal::ref_selector<MatrixType>::non_const_type m_matrix;
Don Gagne's avatar
Don Gagne committed
166
    const internal::variable_if_dynamicindex<Index, DiagIndex> m_index;
LM's avatar
LM committed
167 168 169

  private:
    // some compilers may fail to optimize std::max etc in case of compile-time constants...
170
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
171
    EIGEN_STRONG_INLINE Index absDiagIndex() const { return m_index.value()>0 ? m_index.value() : -m_index.value(); }
172
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
173
    EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value()>0 ? 0 : -m_index.value(); }
174
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
175
    EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value()>0 ? m_index.value() : 0; }
176
    // trigger a compile-time error if someone try to call packet
LM's avatar
LM committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    template<int LoadMode> typename MatrixType::PacketReturnType packet(Index) const;
    template<int LoadMode> typename MatrixType::PacketReturnType packet(Index,Index) const;
};

/** \returns an expression of the main diagonal of the matrix \c *this
  *
  * \c *this is not required to be square.
  *
  * Example: \include MatrixBase_diagonal.cpp
  * Output: \verbinclude MatrixBase_diagonal.out
  *
  * \sa class Diagonal */
template<typename Derived>
inline typename MatrixBase<Derived>::DiagonalReturnType
MatrixBase<Derived>::diagonal()
{
193
  return DiagonalReturnType(derived());
LM's avatar
LM committed
194 195 196 197
}

/** This is the const version of diagonal(). */
template<typename Derived>
Don Gagne's avatar
Don Gagne committed
198
inline typename MatrixBase<Derived>::ConstDiagonalReturnType
LM's avatar
LM committed
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
MatrixBase<Derived>::diagonal() const
{
  return ConstDiagonalReturnType(derived());
}

/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this
  *
  * \c *this is not required to be square.
  *
  * The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0
  * and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal.
  *
  * Example: \include MatrixBase_diagonal_int.cpp
  * Output: \verbinclude MatrixBase_diagonal_int.out
  *
  * \sa MatrixBase::diagonal(), class Diagonal */
template<typename Derived>
216
inline typename MatrixBase<Derived>::DiagonalDynamicIndexReturnType
LM's avatar
LM committed
217 218
MatrixBase<Derived>::diagonal(Index index)
{
219
  return DiagonalDynamicIndexReturnType(derived(), index);
LM's avatar
LM committed
220 221 222 223
}

/** This is the const version of diagonal(Index). */
template<typename Derived>
224
inline typename MatrixBase<Derived>::ConstDiagonalDynamicIndexReturnType
LM's avatar
LM committed
225 226
MatrixBase<Derived>::diagonal(Index index) const
{
227
  return ConstDiagonalDynamicIndexReturnType(derived(), index);
LM's avatar
LM committed
228 229 230 231 232 233 234 235 236 237 238 239 240 241
}

/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this
  *
  * \c *this is not required to be square.
  *
  * The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0
  * and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal.
  *
  * Example: \include MatrixBase_diagonal_template_int.cpp
  * Output: \verbinclude MatrixBase_diagonal_template_int.out
  *
  * \sa MatrixBase::diagonal(), class Diagonal */
template<typename Derived>
242 243
template<int Index_>
inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Index_>::Type
LM's avatar
LM committed
244 245
MatrixBase<Derived>::diagonal()
{
246
  return typename DiagonalIndexReturnType<Index_>::Type(derived());
LM's avatar
LM committed
247 248 249 250
}

/** This is the const version of diagonal<int>(). */
template<typename Derived>
251 252
template<int Index_>
inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Index_>::Type
LM's avatar
LM committed
253 254
MatrixBase<Derived>::diagonal() const
{
255
  return typename ConstDiagonalIndexReturnType<Index_>::Type(derived());
LM's avatar
LM committed
256 257
}

Don Gagne's avatar
Don Gagne committed
258 259
} // end namespace Eigen

LM's avatar
LM committed
260
#endif // EIGEN_DIAGONAL_H