Block.h
Go to the documentation of this file.
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 // Eigen is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 3 of the License, or (at your option) any later version.
11 //
12 // Alternatively, you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License as
14 // published by the Free Software Foundation; either version 2 of
15 // the License, or (at your option) any later version.
16 //
17 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License and a copy of the GNU General Public License along with
24 // Eigen. If not, see <http://www.gnu.org/licenses/>.
25 
26 #ifndef EIGEN_BLOCK_H
27 #define EIGEN_BLOCK_H
28 
29 namespace Eigen {
30 
64 namespace internal {
65 template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess>
66 struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> > : traits<XprType>
67 {
68  typedef typename traits<XprType>::Scalar Scalar;
69  typedef typename traits<XprType>::StorageKind StorageKind;
70  typedef typename traits<XprType>::XprKind XprKind;
71  typedef typename nested<XprType>::type XprTypeNested;
72  typedef typename remove_reference<XprTypeNested>::type _XprTypeNested;
73  enum{
76  RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows,
77  ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols,
78  MaxRowsAtCompileTime = BlockRows==0 ? 0
79  : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime)
80  : int(traits<XprType>::MaxRowsAtCompileTime),
81  MaxColsAtCompileTime = BlockCols==0 ? 0
82  : ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
83  : int(traits<XprType>::MaxColsAtCompileTime),
84  XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
85  IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
86  : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
87  : XprTypeIsRowMajor,
88  HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
89  InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
90  InnerStrideAtCompileTime = HasSameStorageOrderAsXprType
91  ? int(inner_stride_at_compile_time<XprType>::ret)
92  : int(outer_stride_at_compile_time<XprType>::ret),
93  OuterStrideAtCompileTime = HasSameStorageOrderAsXprType
94  ? int(outer_stride_at_compile_time<XprType>::ret)
95  : int(inner_stride_at_compile_time<XprType>::ret),
96  MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0)
97  && (InnerStrideAtCompileTime == 1)
98  ? PacketAccessBit : 0,
99  MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
100  FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
101  FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
102  FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
103  Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
105  MaskPacketAccessBit |
106  MaskAlignedBit),
107  Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit
108  };
109 };
110 }
111 
112 template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class Block
113  : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> >::type
114 {
115  public:
116 
117  typedef typename internal::dense_xpr_base<Block>::type Base;
119 
120  class InnerIterator;
121 
124  inline Block(XprType& xpr, Index i)
125  : m_xpr(xpr),
126  // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
127  // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
128  // all other cases are invalid.
129  // The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
130  m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
131  m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
132  m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
133  m_blockCols(BlockCols==1 ? 1 : xpr.cols())
134  {
135  eigen_assert( (i>=0) && (
136  ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
137  ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
138  }
139 
142  inline Block(XprType& xpr, Index startRow, Index startCol)
143  : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
144  m_blockRows(BlockRows), m_blockCols(BlockCols)
145  {
146  EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
147  eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
148  && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
149  }
150 
153  inline Block(XprType& xpr,
154  Index startRow, Index startCol,
155  Index blockRows, Index blockCols)
156  : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
157  m_blockRows(blockRows), m_blockCols(blockCols)
158  {
159  eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
160  && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
161  eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
162  && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
163  }
164 
166 
167  inline Index rows() const { return m_blockRows.value(); }
168  inline Index cols() const { return m_blockCols.value(); }
169 
170  inline Scalar& coeffRef(Index row, Index col)
171  {
173  return m_xpr.const_cast_derived()
174  .coeffRef(row + m_startRow.value(), col + m_startCol.value());
175  }
176 
177  inline const Scalar& coeffRef(Index row, Index col) const
178  {
179  return m_xpr.derived()
180  .coeffRef(row + m_startRow.value(), col + m_startCol.value());
181  }
182 
183  EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const
184  {
185  return m_xpr.coeff(row + m_startRow.value(), col + m_startCol.value());
186  }
187 
188  inline Scalar& coeffRef(Index index)
189  {
191  return m_xpr.const_cast_derived()
192  .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
193  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
194  }
195 
196  inline const Scalar& coeffRef(Index index) const
197  {
198  return m_xpr.const_cast_derived()
199  .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
200  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
201  }
202 
203  inline const CoeffReturnType coeff(Index index) const
204  {
205  return m_xpr
206  .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
207  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
208  }
209 
210  template<int LoadMode>
211  inline PacketScalar packet(Index row, Index col) const
212  {
213  return m_xpr.template packet<Unaligned>
214  (row + m_startRow.value(), col + m_startCol.value());
215  }
216 
217  template<int LoadMode>
218  inline void writePacket(Index row, Index col, const PacketScalar& x)
219  {
220  m_xpr.const_cast_derived().template writePacket<Unaligned>
221  (row + m_startRow.value(), col + m_startCol.value(), x);
222  }
223 
224  template<int LoadMode>
225  inline PacketScalar packet(Index index) const
226  {
227  return m_xpr.template packet<Unaligned>
228  (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
229  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
230  }
231 
232  template<int LoadMode>
233  inline void writePacket(Index index, const PacketScalar& x)
234  {
235  m_xpr.const_cast_derived().template writePacket<Unaligned>
236  (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
237  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), x);
238  }
239 
240  #ifdef EIGEN_PARSED_BY_DOXYGEN
241 
242  inline const Scalar* data() const;
243  inline Index innerStride() const;
244  inline Index outerStride() const;
245  #endif
246 
247  const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const
248  {
249  return m_xpr;
250  }
251 
252  Index startRow() const
253  {
254  return m_startRow.value();
255  }
256 
257  Index startCol() const
258  {
259  return m_startCol.value();
260  }
261 
262  protected:
263 
264  const typename XprType::Nested m_xpr;
265  const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
266  const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
267  const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows;
268  const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
269 };
270 
272 template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
273 class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
274  : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel, true> >
275 {
276  public:
277 
280 
282 
285  inline Block(XprType& xpr, Index i)
286  : Base(internal::const_cast_ptr(&xpr.coeffRef(
287  (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0,
288  (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)),
289  BlockRows==1 ? 1 : xpr.rows(),
290  BlockCols==1 ? 1 : xpr.cols()),
291  m_xpr(xpr)
292  {
293  eigen_assert( (i>=0) && (
294  ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
295  ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
296  init();
297  }
298 
301  inline Block(XprType& xpr, Index startRow, Index startCol)
302  : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr)
303  {
304  eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
305  && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
306  init();
307  }
308 
311  inline Block(XprType& xpr,
312  Index startRow, Index startCol,
313  Index blockRows, Index blockCols)
314  : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols),
315  m_xpr(xpr)
316  {
317  eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
318  && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
319  eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
320  && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
321  init();
322  }
323 
324  const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const
325  {
326  return m_xpr;
327  }
328 
330  inline Index innerStride() const
331  {
332  return internal::traits<Block>::HasSameStorageOrderAsXprType
333  ? m_xpr.innerStride()
334  : m_xpr.outerStride();
335  }
336 
338  inline Index outerStride() const
339  {
340  return m_outerStride;
341  }
342 
343  #ifndef __SUNPRO_CC
344  // FIXME sunstudio is not friendly with the above friend...
345  // META-FIXME there is no 'friend' keyword around here. Is this obsolete?
346  protected:
347  #endif
348 
349  #ifndef EIGEN_PARSED_BY_DOXYGEN
350 
351  inline Block(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
352  : Base(data, blockRows, blockCols), m_xpr(xpr)
353  {
354  init();
355  }
356  #endif
357 
358  protected:
359  void init()
360  {
361  m_outerStride = internal::traits<Block>::HasSameStorageOrderAsXprType
362  ? m_xpr.outerStride()
363  : m_xpr.innerStride();
364  }
365 
366  typename XprType::Nested m_xpr;
368 };
369 
370 } // end namespace Eigen
371 
372 #endif // EIGEN_BLOCK_H