Diagonal.h 8.89 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 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
/** \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.
  *              You can also use Dynamic so the index can be set at runtime.
  *
  * 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>
{
  typedef typename nested<MatrixType>::type MatrixTypeNested;
  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 55 56 57 58 59 60 61 62 63
    MaxColsAtCompileTime = 1,
    MaskLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
    Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit | MaskLvalueBit | DirectAccessBit) & ~RowMajorBit,
    CoeffReadCost = _MatrixTypeNested::CoeffReadCost,
    MatrixTypeOuterStride = outer_stride_at_compile_time<MatrixType>::ret,
    InnerStrideAtCompileTime = MatrixTypeOuterStride == Dynamic ? Dynamic : MatrixTypeOuterStride+1,
    OuterStrideAtCompileTime = 0
  };
};
}

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

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

Don Gagne's avatar
Don Gagne committed
73
    inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) {}
LM's avatar
LM committed
74 75 76 77

    EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)

    inline Index rows() const
Don Gagne's avatar
Don Gagne committed
78
    { return m_index.value()<0 ? (std::min<Index>)(m_matrix.cols(),m_matrix.rows()+m_index.value()) : (std::min<Index>)(m_matrix.rows(),m_matrix.cols()-m_index.value()); }
LM's avatar
LM committed
79 80 81 82 83 84 85 86 87 88 89 90 91

    inline Index cols() const { return 1; }

    inline Index innerStride() const
    {
      return m_matrix.outerStride() + 1;
    }

    inline Index outerStride() const
    {
      return 0;
    }

Don Gagne's avatar
Don Gagne committed
92 93 94 95 96 97 98 99 100
    typedef typename internal::conditional<
                       internal::is_lvalue<MatrixType>::value,
                       Scalar,
                       const Scalar
                     >::type ScalarWithConstIfNotLvalue;

    inline ScalarWithConstIfNotLvalue* data() { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); }
    inline const Scalar* data() const { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); }

LM's avatar
LM committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    inline Scalar& coeffRef(Index row, Index)
    {
      EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
      return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset());
    }

    inline const Scalar& coeffRef(Index row, Index) const
    {
      return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset());
    }

    inline CoeffReturnType coeff(Index row, Index) const
    {
      return m_matrix.coeff(row+rowOffset(), row+colOffset());
    }

Don Gagne's avatar
Don Gagne committed
117
    inline Scalar& coeffRef(Index idx)
LM's avatar
LM committed
118 119
    {
      EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
Don Gagne's avatar
Don Gagne committed
120
      return m_matrix.const_cast_derived().coeffRef(idx+rowOffset(), idx+colOffset());
LM's avatar
LM committed
121 122
    }

Don Gagne's avatar
Don Gagne committed
123
    inline const Scalar& coeffRef(Index idx) const
LM's avatar
LM committed
124
    {
Don Gagne's avatar
Don Gagne committed
125
      return m_matrix.const_cast_derived().coeffRef(idx+rowOffset(), idx+colOffset());
LM's avatar
LM committed
126 127
    }

Don Gagne's avatar
Don Gagne committed
128
    inline CoeffReturnType coeff(Index idx) const
LM's avatar
LM committed
129
    {
Don Gagne's avatar
Don Gagne committed
130 131 132 133 134 135 136 137 138 139 140 141
      return m_matrix.coeff(idx+rowOffset(), idx+colOffset());
    }

    const typename internal::remove_all<typename MatrixType::Nested>::type& 
    nestedExpression() const 
    {
      return m_matrix;
    }

    int index() const
    {
      return m_index.value();
LM's avatar
LM committed
142 143 144
    }

  protected:
Don Gagne's avatar
Don Gagne committed
145 146
    typename MatrixType::Nested m_matrix;
    const internal::variable_if_dynamicindex<Index, DiagIndex> m_index;
LM's avatar
LM committed
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174

  private:
    // some compilers may fail to optimize std::max etc in case of compile-time constants...
    EIGEN_STRONG_INLINE Index absDiagIndex() const { return m_index.value()>0 ? m_index.value() : -m_index.value(); }
    EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value()>0 ? 0 : -m_index.value(); }
    EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value()>0 ? m_index.value() : 0; }
    // triger a compile time error is someone try to call packet
    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()
{
  return derived();
}

/** This is the const version of diagonal(). */
template<typename Derived>
Don Gagne's avatar
Don Gagne committed
175
inline typename MatrixBase<Derived>::ConstDiagonalReturnType
LM's avatar
LM committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
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>
Don Gagne's avatar
Don Gagne committed
193
inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<DynamicIndex>::Type
LM's avatar
LM committed
194 195
MatrixBase<Derived>::diagonal(Index index)
{
Don Gagne's avatar
Don Gagne committed
196
  return typename DiagonalIndexReturnType<DynamicIndex>::Type(derived(), index);
LM's avatar
LM committed
197 198 199 200
}

/** This is the const version of diagonal(Index). */
template<typename Derived>
Don Gagne's avatar
Don Gagne committed
201
inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<DynamicIndex>::Type
LM's avatar
LM committed
202 203
MatrixBase<Derived>::diagonal(Index index) const
{
Don Gagne's avatar
Don Gagne committed
204
  return typename ConstDiagonalIndexReturnType<DynamicIndex>::Type(derived(), index);
LM's avatar
LM committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
}

/** \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>
template<int Index>
inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Index>::Type
MatrixBase<Derived>::diagonal()
{
  return derived();
}

/** This is the const version of diagonal<int>(). */
template<typename Derived>
template<int Index>
inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Index>::Type
MatrixBase<Derived>::diagonal() const
{
  return derived();
}

Don Gagne's avatar
Don Gagne committed
235 236
} // end namespace Eigen

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