1 | // This file is part of Eigen, a lightweight C++ template library |
2 | // for linear algebra. |
3 | // |
4 | // Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com> |
5 | // Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
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_DIAGONAL_H |
12 | #define EIGEN_DIAGONAL_H |
13 | |
14 | namespace Eigen { |
15 | |
16 | /** \class Diagonal |
17 | * \ingroup Core_Module |
18 | * |
19 | * \brief Expression of a diagonal/subdiagonal/superdiagonal in a matrix |
20 | * |
21 | * \param MatrixType the type of the object in which we are taking a sub/main/super diagonal |
22 | * \param DiagIndex the index of the sub/super diagonal. The default is 0 and it means the main diagonal. |
23 | * 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. |
25 | * |
26 | * The matrix is not required to be square. |
27 | * |
28 | * This class represents an expression of the main diagonal, or any sub/super diagonal |
29 | * of a square matrix. It is the return type of MatrixBase::diagonal() and MatrixBase::diagonal(Index) and most of the |
30 | * time this is the only way it is used. |
31 | * |
32 | * \sa MatrixBase::diagonal(), MatrixBase::diagonal(Index) |
33 | */ |
34 | |
35 | namespace internal { |
36 | template<typename MatrixType, int DiagIndex> |
37 | struct traits<Diagonal<MatrixType,DiagIndex> > |
38 | : traits<MatrixType> |
39 | { |
40 | typedef typename ref_selector<MatrixType>::type MatrixTypeNested; |
41 | typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested; |
42 | typedef typename MatrixType::StorageKind StorageKind; |
43 | enum { |
44 | RowsAtCompileTime = (int(DiagIndex) == DynamicIndex || int(MatrixType::SizeAtCompileTime) == Dynamic) ? Dynamic |
45 | : (EIGEN_PLAIN_ENUM_MIN(MatrixType::RowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0), |
46 | MatrixType::ColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))), |
47 | ColsAtCompileTime = 1, |
48 | MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic |
49 | : DiagIndex == DynamicIndex ? EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime, |
50 | MatrixType::MaxColsAtCompileTime) |
51 | : (EIGEN_PLAIN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0), |
52 | MatrixType::MaxColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))), |
53 | MaxColsAtCompileTime = 1, |
54 | 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 |
56 | MatrixTypeOuterStride = outer_stride_at_compile_time<MatrixType>::ret, |
57 | InnerStrideAtCompileTime = MatrixTypeOuterStride == Dynamic ? Dynamic : MatrixTypeOuterStride+1, |
58 | OuterStrideAtCompileTime = 0 |
59 | }; |
60 | }; |
61 | } |
62 | |
63 | template<typename MatrixType, int _DiagIndex> class Diagonal |
64 | : public internal::dense_xpr_base< Diagonal<MatrixType,_DiagIndex> >::type |
65 | { |
66 | public: |
67 | |
68 | enum { DiagIndex = _DiagIndex }; |
69 | typedef typename internal::dense_xpr_base<Diagonal>::type Base; |
70 | EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal) |
71 | |
72 | EIGEN_DEVICE_FUNC |
73 | explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) |
74 | { |
75 | eigen_assert( a_index <= m_matrix.cols() && -a_index <= m_matrix.rows() ); |
76 | } |
77 | |
78 | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal) |
79 | |
80 | EIGEN_DEVICE_FUNC |
81 | inline Index rows() const |
82 | { |
83 | return m_index.value()<0 ? numext::mini<Index>(m_matrix.cols(),m_matrix.rows()+m_index.value()) |
84 | : numext::mini<Index>(m_matrix.rows(),m_matrix.cols()-m_index.value()); |
85 | } |
86 | |
87 | EIGEN_DEVICE_FUNC |
88 | inline Index cols() const { return 1; } |
89 | |
90 | EIGEN_DEVICE_FUNC |
91 | inline Index innerStride() const |
92 | { |
93 | return m_matrix.outerStride() + 1; |
94 | } |
95 | |
96 | EIGEN_DEVICE_FUNC |
97 | inline Index outerStride() const |
98 | { |
99 | return 0; |
100 | } |
101 | |
102 | typedef typename internal::conditional< |
103 | internal::is_lvalue<MatrixType>::value, |
104 | Scalar, |
105 | const Scalar |
106 | >::type ScalarWithConstIfNotLvalue; |
107 | |
108 | EIGEN_DEVICE_FUNC |
109 | inline ScalarWithConstIfNotLvalue* data() { return &(m_matrix.coeffRef(rowOffset(), colOffset())); } |
110 | EIGEN_DEVICE_FUNC |
111 | inline const Scalar* data() const { return &(m_matrix.coeffRef(rowOffset(), colOffset())); } |
112 | |
113 | EIGEN_DEVICE_FUNC |
114 | inline Scalar& coeffRef(Index row, Index) |
115 | { |
116 | EIGEN_STATIC_ASSERT_LVALUE(MatrixType) |
117 | return m_matrix.coeffRef(row+rowOffset(), row+colOffset()); |
118 | } |
119 | |
120 | EIGEN_DEVICE_FUNC |
121 | inline const Scalar& coeffRef(Index row, Index) const |
122 | { |
123 | return m_matrix.coeffRef(row+rowOffset(), row+colOffset()); |
124 | } |
125 | |
126 | EIGEN_DEVICE_FUNC |
127 | inline CoeffReturnType coeff(Index row, Index) const |
128 | { |
129 | return m_matrix.coeff(row+rowOffset(), row+colOffset()); |
130 | } |
131 | |
132 | EIGEN_DEVICE_FUNC |
133 | inline Scalar& coeffRef(Index idx) |
134 | { |
135 | EIGEN_STATIC_ASSERT_LVALUE(MatrixType) |
136 | return m_matrix.coeffRef(idx+rowOffset(), idx+colOffset()); |
137 | } |
138 | |
139 | EIGEN_DEVICE_FUNC |
140 | inline const Scalar& coeffRef(Index idx) const |
141 | { |
142 | return m_matrix.coeffRef(idx+rowOffset(), idx+colOffset()); |
143 | } |
144 | |
145 | EIGEN_DEVICE_FUNC |
146 | inline CoeffReturnType coeff(Index idx) const |
147 | { |
148 | return m_matrix.coeff(idx+rowOffset(), idx+colOffset()); |
149 | } |
150 | |
151 | EIGEN_DEVICE_FUNC |
152 | inline const typename internal::remove_all<typename MatrixType::Nested>::type& |
153 | nestedExpression() const |
154 | { |
155 | return m_matrix; |
156 | } |
157 | |
158 | EIGEN_DEVICE_FUNC |
159 | inline Index index() const |
160 | { |
161 | return m_index.value(); |
162 | } |
163 | |
164 | protected: |
165 | typename internal::ref_selector<MatrixType>::non_const_type m_matrix; |
166 | const internal::variable_if_dynamicindex<Index, DiagIndex> m_index; |
167 | |
168 | private: |
169 | // some compilers may fail to optimize std::max etc in case of compile-time constants... |
170 | EIGEN_DEVICE_FUNC |
171 | EIGEN_STRONG_INLINE Index absDiagIndex() const { return m_index.value()>0 ? m_index.value() : -m_index.value(); } |
172 | EIGEN_DEVICE_FUNC |
173 | EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value()>0 ? 0 : -m_index.value(); } |
174 | EIGEN_DEVICE_FUNC |
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 |
177 | template<int LoadMode> typename MatrixType::PacketReturnType packet(Index) const; |
178 | template<int LoadMode> typename MatrixType::PacketReturnType packet(Index,Index) const; |
179 | }; |
180 | |
181 | /** \returns an expression of the main diagonal of the matrix \c *this |
182 | * |
183 | * \c *this is not required to be square. |
184 | * |
185 | * Example: \include MatrixBase_diagonal.cpp |
186 | * Output: \verbinclude MatrixBase_diagonal.out |
187 | * |
188 | * \sa class Diagonal */ |
189 | template<typename Derived> |
190 | inline typename MatrixBase<Derived>::DiagonalReturnType |
191 | MatrixBase<Derived>::diagonal() |
192 | { |
193 | return DiagonalReturnType(derived()); |
194 | } |
195 | |
196 | /** This is the const version of diagonal(). */ |
197 | template<typename Derived> |
198 | inline typename MatrixBase<Derived>::ConstDiagonalReturnType |
199 | MatrixBase<Derived>::diagonal() const |
200 | { |
201 | return ConstDiagonalReturnType(derived()); |
202 | } |
203 | |
204 | /** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this |
205 | * |
206 | * \c *this is not required to be square. |
207 | * |
208 | * The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0 |
209 | * and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal. |
210 | * |
211 | * Example: \include MatrixBase_diagonal_int.cpp |
212 | * Output: \verbinclude MatrixBase_diagonal_int.out |
213 | * |
214 | * \sa MatrixBase::diagonal(), class Diagonal */ |
215 | template<typename Derived> |
216 | inline typename MatrixBase<Derived>::DiagonalDynamicIndexReturnType |
217 | MatrixBase<Derived>::diagonal(Index index) |
218 | { |
219 | return DiagonalDynamicIndexReturnType(derived(), index); |
220 | } |
221 | |
222 | /** This is the const version of diagonal(Index). */ |
223 | template<typename Derived> |
224 | inline typename MatrixBase<Derived>::ConstDiagonalDynamicIndexReturnType |
225 | MatrixBase<Derived>::diagonal(Index index) const |
226 | { |
227 | return ConstDiagonalDynamicIndexReturnType(derived(), index); |
228 | } |
229 | |
230 | /** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this |
231 | * |
232 | * \c *this is not required to be square. |
233 | * |
234 | * The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0 |
235 | * and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal. |
236 | * |
237 | * Example: \include MatrixBase_diagonal_template_int.cpp |
238 | * Output: \verbinclude MatrixBase_diagonal_template_int.out |
239 | * |
240 | * \sa MatrixBase::diagonal(), class Diagonal */ |
241 | template<typename Derived> |
242 | template<int Index_> |
243 | inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Index_>::Type |
244 | MatrixBase<Derived>::diagonal() |
245 | { |
246 | return typename DiagonalIndexReturnType<Index_>::Type(derived()); |
247 | } |
248 | |
249 | /** This is the const version of diagonal<int>(). */ |
250 | template<typename Derived> |
251 | template<int Index_> |
252 | inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Index_>::Type |
253 | MatrixBase<Derived>::diagonal() const |
254 | { |
255 | return typename ConstDiagonalIndexReturnType<Index_>::Type(derived()); |
256 | } |
257 | |
258 | } // end namespace Eigen |
259 | |
260 | #endif // EIGEN_DIAGONAL_H |
261 | |