1 | // This file is part of Eigen, a lightweight C++ template library |
---|
2 | // for linear algebra. |
---|
3 | // |
---|
4 | // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
---|
5 | // Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
---|
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_BLOCK_H |
---|
12 | #define EIGEN_BLOCK_H |
---|
13 | |
---|
14 | namespace Eigen { |
---|
15 | |
---|
16 | /** \class Block |
---|
17 | * \ingroup Core_Module |
---|
18 | * |
---|
19 | * \brief Expression of a fixed-size or dynamic-size block |
---|
20 | * |
---|
21 | * \param XprType the type of the expression in which we are taking a block |
---|
22 | * \param BlockRows the number of rows of the block we are taking at compile time (optional) |
---|
23 | * \param BlockCols the number of columns of the block we are taking at compile time (optional) |
---|
24 | * \param _DirectAccessStatus \internal used for partial specialization |
---|
25 | * |
---|
26 | * This class represents an expression of either a fixed-size or dynamic-size block. It is the return |
---|
27 | * type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and |
---|
28 | * most of the time this is the only way it is used. |
---|
29 | * |
---|
30 | * However, if you want to directly maniputate block expressions, |
---|
31 | * for instance if you want to write a function returning such an expression, you |
---|
32 | * will need to use this class. |
---|
33 | * |
---|
34 | * Here is an example illustrating the dynamic case: |
---|
35 | * \include class_Block.cpp |
---|
36 | * Output: \verbinclude class_Block.out |
---|
37 | * |
---|
38 | * \note Even though this expression has dynamic size, in the case where \a XprType |
---|
39 | * has fixed size, this expression inherits a fixed maximal size which means that evaluating |
---|
40 | * it does not cause a dynamic memory allocation. |
---|
41 | * |
---|
42 | * Here is an example illustrating the fixed-size case: |
---|
43 | * \include class_FixedBlock.cpp |
---|
44 | * Output: \verbinclude class_FixedBlock.out |
---|
45 | * |
---|
46 | * \sa DenseBase::block(Index,Index,Index,Index), DenseBase::block(Index,Index), class VectorBlock |
---|
47 | */ |
---|
48 | |
---|
49 | namespace internal { |
---|
50 | template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> |
---|
51 | struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> > : traits<XprType> |
---|
52 | { |
---|
53 | typedef typename traits<XprType>::Scalar Scalar; |
---|
54 | typedef typename traits<XprType>::StorageKind StorageKind; |
---|
55 | typedef typename traits<XprType>::XprKind XprKind; |
---|
56 | typedef typename nested<XprType>::type XprTypeNested; |
---|
57 | typedef typename remove_reference<XprTypeNested>::type _XprTypeNested; |
---|
58 | enum{ |
---|
59 | MatrixRows = traits<XprType>::RowsAtCompileTime, |
---|
60 | MatrixCols = traits<XprType>::ColsAtCompileTime, |
---|
61 | RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows, |
---|
62 | ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols, |
---|
63 | MaxRowsAtCompileTime = BlockRows==0 ? 0 |
---|
64 | : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime) |
---|
65 | : int(traits<XprType>::MaxRowsAtCompileTime), |
---|
66 | MaxColsAtCompileTime = BlockCols==0 ? 0 |
---|
67 | : ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime) |
---|
68 | : int(traits<XprType>::MaxColsAtCompileTime), |
---|
69 | XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0, |
---|
70 | IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1 |
---|
71 | : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0 |
---|
72 | : XprTypeIsRowMajor, |
---|
73 | HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor), |
---|
74 | InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime), |
---|
75 | InnerStrideAtCompileTime = HasSameStorageOrderAsXprType |
---|
76 | ? int(inner_stride_at_compile_time<XprType>::ret) |
---|
77 | : int(outer_stride_at_compile_time<XprType>::ret), |
---|
78 | OuterStrideAtCompileTime = HasSameStorageOrderAsXprType |
---|
79 | ? int(outer_stride_at_compile_time<XprType>::ret) |
---|
80 | : int(inner_stride_at_compile_time<XprType>::ret), |
---|
81 | MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0) |
---|
82 | && (InnerStrideAtCompileTime == 1) |
---|
83 | ? PacketAccessBit : 0, |
---|
84 | MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0, |
---|
85 | FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0, |
---|
86 | FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0, |
---|
87 | FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, |
---|
88 | Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) | |
---|
89 | DirectAccessBit | |
---|
90 | MaskPacketAccessBit | |
---|
91 | MaskAlignedBit), |
---|
92 | Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit |
---|
93 | }; |
---|
94 | }; |
---|
95 | } |
---|
96 | |
---|
97 | template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class Block |
---|
98 | : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> >::type |
---|
99 | { |
---|
100 | public: |
---|
101 | |
---|
102 | typedef typename internal::dense_xpr_base<Block>::type Base; |
---|
103 | EIGEN_DENSE_PUBLIC_INTERFACE(Block) |
---|
104 | |
---|
105 | class InnerIterator; |
---|
106 | |
---|
107 | /** Column or Row constructor |
---|
108 | */ |
---|
109 | inline Block(XprType& xpr, Index i) |
---|
110 | : m_xpr(xpr), |
---|
111 | // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime, |
---|
112 | // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1, |
---|
113 | // all other cases are invalid. |
---|
114 | // The case a 1x1 matrix seems ambiguous, but the result is the same anyway. |
---|
115 | m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0), |
---|
116 | m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0), |
---|
117 | m_blockRows(BlockRows==1 ? 1 : xpr.rows()), |
---|
118 | m_blockCols(BlockCols==1 ? 1 : xpr.cols()) |
---|
119 | { |
---|
120 | eigen_assert( (i>=0) && ( |
---|
121 | ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows()) |
---|
122 | ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols()))); |
---|
123 | } |
---|
124 | |
---|
125 | /** Fixed-size constructor |
---|
126 | */ |
---|
127 | inline Block(XprType& xpr, Index startRow, Index startCol) |
---|
128 | : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), |
---|
129 | m_blockRows(BlockRows), m_blockCols(BlockCols) |
---|
130 | { |
---|
131 | EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) |
---|
132 | eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows() |
---|
133 | && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols()); |
---|
134 | } |
---|
135 | |
---|
136 | /** Dynamic-size constructor |
---|
137 | */ |
---|
138 | inline Block(XprType& xpr, |
---|
139 | Index startRow, Index startCol, |
---|
140 | Index blockRows, Index blockCols) |
---|
141 | : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), |
---|
142 | m_blockRows(blockRows), m_blockCols(blockCols) |
---|
143 | { |
---|
144 | eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) |
---|
145 | && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); |
---|
146 | eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows() |
---|
147 | && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols()); |
---|
148 | } |
---|
149 | |
---|
150 | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) |
---|
151 | |
---|
152 | inline Index rows() const { return m_blockRows.value(); } |
---|
153 | inline Index cols() const { return m_blockCols.value(); } |
---|
154 | |
---|
155 | inline Scalar& coeffRef(Index row, Index col) |
---|
156 | { |
---|
157 | EIGEN_STATIC_ASSERT_LVALUE(XprType) |
---|
158 | return m_xpr.const_cast_derived() |
---|
159 | .coeffRef(row + m_startRow.value(), col + m_startCol.value()); |
---|
160 | } |
---|
161 | |
---|
162 | inline const Scalar& coeffRef(Index row, Index col) const |
---|
163 | { |
---|
164 | return m_xpr.derived() |
---|
165 | .coeffRef(row + m_startRow.value(), col + m_startCol.value()); |
---|
166 | } |
---|
167 | |
---|
168 | EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const |
---|
169 | { |
---|
170 | return m_xpr.coeff(row + m_startRow.value(), col + m_startCol.value()); |
---|
171 | } |
---|
172 | |
---|
173 | inline Scalar& coeffRef(Index index) |
---|
174 | { |
---|
175 | EIGEN_STATIC_ASSERT_LVALUE(XprType) |
---|
176 | return m_xpr.const_cast_derived() |
---|
177 | .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
---|
178 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
---|
179 | } |
---|
180 | |
---|
181 | inline const Scalar& coeffRef(Index index) const |
---|
182 | { |
---|
183 | return m_xpr.const_cast_derived() |
---|
184 | .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
---|
185 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
---|
186 | } |
---|
187 | |
---|
188 | inline const CoeffReturnType coeff(Index index) const |
---|
189 | { |
---|
190 | return m_xpr |
---|
191 | .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
---|
192 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
---|
193 | } |
---|
194 | |
---|
195 | template<int LoadMode> |
---|
196 | inline PacketScalar packet(Index row, Index col) const |
---|
197 | { |
---|
198 | return m_xpr.template packet<Unaligned> |
---|
199 | (row + m_startRow.value(), col + m_startCol.value()); |
---|
200 | } |
---|
201 | |
---|
202 | template<int LoadMode> |
---|
203 | inline void writePacket(Index row, Index col, const PacketScalar& x) |
---|
204 | { |
---|
205 | m_xpr.const_cast_derived().template writePacket<Unaligned> |
---|
206 | (row + m_startRow.value(), col + m_startCol.value(), x); |
---|
207 | } |
---|
208 | |
---|
209 | template<int LoadMode> |
---|
210 | inline PacketScalar packet(Index index) const |
---|
211 | { |
---|
212 | return m_xpr.template packet<Unaligned> |
---|
213 | (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
---|
214 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
---|
215 | } |
---|
216 | |
---|
217 | template<int LoadMode> |
---|
218 | inline void writePacket(Index index, const PacketScalar& x) |
---|
219 | { |
---|
220 | m_xpr.const_cast_derived().template writePacket<Unaligned> |
---|
221 | (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
---|
222 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), x); |
---|
223 | } |
---|
224 | |
---|
225 | #ifdef EIGEN_PARSED_BY_DOXYGEN |
---|
226 | /** \sa MapBase::data() */ |
---|
227 | inline const Scalar* data() const; |
---|
228 | inline Index innerStride() const; |
---|
229 | inline Index outerStride() const; |
---|
230 | #endif |
---|
231 | |
---|
232 | const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const |
---|
233 | { |
---|
234 | return m_xpr; |
---|
235 | } |
---|
236 | |
---|
237 | Index startRow() const |
---|
238 | { |
---|
239 | return m_startRow.value(); |
---|
240 | } |
---|
241 | |
---|
242 | Index startCol() const |
---|
243 | { |
---|
244 | return m_startCol.value(); |
---|
245 | } |
---|
246 | |
---|
247 | protected: |
---|
248 | |
---|
249 | const typename XprType::Nested m_xpr; |
---|
250 | const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow; |
---|
251 | const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol; |
---|
252 | const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows; |
---|
253 | const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols; |
---|
254 | }; |
---|
255 | |
---|
256 | /** \internal */ |
---|
257 | template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> |
---|
258 | class Block<XprType,BlockRows,BlockCols, InnerPanel,true> |
---|
259 | : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel, true> > |
---|
260 | { |
---|
261 | public: |
---|
262 | |
---|
263 | typedef MapBase<Block> Base; |
---|
264 | EIGEN_DENSE_PUBLIC_INTERFACE(Block) |
---|
265 | |
---|
266 | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) |
---|
267 | |
---|
268 | /** Column or Row constructor |
---|
269 | */ |
---|
270 | inline Block(XprType& xpr, Index i) |
---|
271 | : Base(internal::const_cast_ptr(&xpr.coeffRef( |
---|
272 | (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0, |
---|
273 | (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)), |
---|
274 | BlockRows==1 ? 1 : xpr.rows(), |
---|
275 | BlockCols==1 ? 1 : xpr.cols()), |
---|
276 | m_xpr(xpr) |
---|
277 | { |
---|
278 | eigen_assert( (i>=0) && ( |
---|
279 | ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows()) |
---|
280 | ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols()))); |
---|
281 | init(); |
---|
282 | } |
---|
283 | |
---|
284 | /** Fixed-size constructor |
---|
285 | */ |
---|
286 | inline Block(XprType& xpr, Index startRow, Index startCol) |
---|
287 | : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr) |
---|
288 | { |
---|
289 | eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows() |
---|
290 | && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols()); |
---|
291 | init(); |
---|
292 | } |
---|
293 | |
---|
294 | /** Dynamic-size constructor |
---|
295 | */ |
---|
296 | inline Block(XprType& xpr, |
---|
297 | Index startRow, Index startCol, |
---|
298 | Index blockRows, Index blockCols) |
---|
299 | : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols), |
---|
300 | m_xpr(xpr) |
---|
301 | { |
---|
302 | eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) |
---|
303 | && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); |
---|
304 | eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows() |
---|
305 | && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols()); |
---|
306 | init(); |
---|
307 | } |
---|
308 | |
---|
309 | const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const |
---|
310 | { |
---|
311 | return m_xpr; |
---|
312 | } |
---|
313 | |
---|
314 | /** \sa MapBase::innerStride() */ |
---|
315 | inline Index innerStride() const |
---|
316 | { |
---|
317 | return internal::traits<Block>::HasSameStorageOrderAsXprType |
---|
318 | ? m_xpr.innerStride() |
---|
319 | : m_xpr.outerStride(); |
---|
320 | } |
---|
321 | |
---|
322 | /** \sa MapBase::outerStride() */ |
---|
323 | inline Index outerStride() const |
---|
324 | { |
---|
325 | return m_outerStride; |
---|
326 | } |
---|
327 | |
---|
328 | #ifndef __SUNPRO_CC |
---|
329 | // FIXME sunstudio is not friendly with the above friend... |
---|
330 | // META-FIXME there is no 'friend' keyword around here. Is this obsolete? |
---|
331 | protected: |
---|
332 | #endif |
---|
333 | |
---|
334 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
---|
335 | /** \internal used by allowAligned() */ |
---|
336 | inline Block(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols) |
---|
337 | : Base(data, blockRows, blockCols), m_xpr(xpr) |
---|
338 | { |
---|
339 | init(); |
---|
340 | } |
---|
341 | #endif |
---|
342 | |
---|
343 | protected: |
---|
344 | void init() |
---|
345 | { |
---|
346 | m_outerStride = internal::traits<Block>::HasSameStorageOrderAsXprType |
---|
347 | ? m_xpr.outerStride() |
---|
348 | : m_xpr.innerStride(); |
---|
349 | } |
---|
350 | |
---|
351 | typename XprType::Nested m_xpr; |
---|
352 | Index m_outerStride; |
---|
353 | }; |
---|
354 | |
---|
355 | } // end namespace Eigen |
---|
356 | |
---|
357 | #endif // EIGEN_BLOCK_H |
---|