$darkmode
Eigen  5.0.1-dev
Block.h
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 // IWYU pragma: private
15 #include "./InternalHeaderCheck.h"
16 
17 namespace Eigen {
18 
19 namespace internal {
20 template <typename XprType_, int BlockRows, int BlockCols, bool InnerPanel_>
21 struct traits<Block<XprType_, BlockRows, BlockCols, InnerPanel_>> : traits<XprType_> {
22  typedef typename traits<XprType_>::Scalar Scalar;
23  typedef typename traits<XprType_>::StorageKind StorageKind;
24  typedef typename traits<XprType_>::XprKind XprKind;
25  typedef typename ref_selector<XprType_>::type XprTypeNested;
26  typedef std::remove_reference_t<XprTypeNested> XprTypeNested_;
27  enum {
28  MatrixRows = traits<XprType_>::RowsAtCompileTime,
29  MatrixCols = traits<XprType_>::ColsAtCompileTime,
30  RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows,
31  ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols,
32  MaxRowsAtCompileTime = BlockRows == 0 ? 0
33  : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime)
34  : int(traits<XprType_>::MaxRowsAtCompileTime),
35  MaxColsAtCompileTime = BlockCols == 0 ? 0
36  : ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
37  : int(traits<XprType_>::MaxColsAtCompileTime),
38 
39  XprTypeIsRowMajor = (int(traits<XprType_>::Flags) & RowMajorBit) != 0,
40  IsRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? 1
41  : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) ? 0
42  : XprTypeIsRowMajor,
43  HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
44  InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
45  InnerStrideAtCompileTime = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time<XprType_>::ret)
46  : int(outer_stride_at_compile_time<XprType_>::ret),
47  OuterStrideAtCompileTime = HasSameStorageOrderAsXprType ? int(outer_stride_at_compile_time<XprType_>::ret)
48  : int(inner_stride_at_compile_time<XprType_>::ret),
49 
50  // FIXME, this traits is rather specialized for dense object and it needs to be cleaned further
51  FlagsLvalueBit = is_lvalue<XprType_>::value ? LvalueBit : 0,
52  FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
53  Flags = (traits<XprType_>::Flags & (DirectAccessBit | (InnerPanel_ ? CompressedAccessBit : 0))) | FlagsLvalueBit |
54  FlagsRowMajorBit,
55  // FIXME DirectAccessBit should not be handled by expressions
56  //
57  // Alignment is needed by MapBase's assertions
58  // We can sefely set it to false here. Internal alignment errors will be detected by an eigen_internal_assert in the
59  // respective evaluator
60  Alignment = 0,
61  InnerPanel = InnerPanel_ ? 1 : 0
62  };
63 };
64 
65 template <typename XprType, int BlockRows = Dynamic, int BlockCols = Dynamic, bool InnerPanel = false,
66  bool HasDirectAccess = internal::has_direct_access<XprType>::ret>
67 class BlockImpl_dense;
68 
69 } // end namespace internal
70 
71 template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel, typename StorageKind>
72 class BlockImpl;
73 
108 template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
109 class Block
110  : public BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind> {
111  typedef BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind> Impl;
112  using BlockHelper = internal::block_xpr_helper<Block>;
113 
114  public:
115  // typedef typename Impl::Base Base;
116  typedef Impl Base;
117  EIGEN_GENERIC_PUBLIC_INTERFACE(Block)
118  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
119 
120  typedef internal::remove_all_t<XprType> NestedExpression;
121 
124  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Block(XprType& xpr, Index i) : Impl(xpr, i) {
125  eigen_assert((i >= 0) && (((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) && i < xpr.rows()) ||
126  ((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) && i < xpr.cols())));
127  }
128 
131  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Block(XprType& xpr, Index startRow, Index startCol)
132  : Impl(xpr, startRow, startCol) {
133  EIGEN_STATIC_ASSERT(RowsAtCompileTime != Dynamic && ColsAtCompileTime != Dynamic,
134  THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
135  eigen_assert(startRow >= 0 && BlockRows >= 0 && startRow + BlockRows <= xpr.rows() && startCol >= 0 &&
136  BlockCols >= 0 && startCol + BlockCols <= xpr.cols());
137  }
138 
141  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Block(XprType& xpr, Index startRow, Index startCol, Index blockRows,
142  Index blockCols)
143  : Impl(xpr, startRow, startCol, blockRows, blockCols) {
144  eigen_assert((RowsAtCompileTime == Dynamic || RowsAtCompileTime == blockRows) &&
145  (ColsAtCompileTime == Dynamic || ColsAtCompileTime == blockCols));
146  eigen_assert(startRow >= 0 && blockRows >= 0 && startRow <= xpr.rows() - blockRows && startCol >= 0 &&
147  blockCols >= 0 && startCol <= xpr.cols() - blockCols);
148  }
149 
150  // convert nested blocks (e.g. Block<Block<MatrixType>>) to a simple block expression (Block<MatrixType>)
151 
154 
155  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ConstUnwindReturnType unwind() const {
156  return ConstUnwindReturnType(BlockHelper::base(*this), BlockHelper::row(*this, 0), BlockHelper::col(*this, 0),
157  this->rows(), this->cols());
158  }
159 
160  template <typename T = Block, typename EnableIf = std::enable_if_t<!std::is_const<T>::value>>
161  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE UnwindReturnType unwind() {
162  return UnwindReturnType(BlockHelper::base(*this), BlockHelper::row(*this, 0), BlockHelper::col(*this, 0),
163  this->rows(), this->cols());
164  }
165 };
166 
167 // The generic default implementation for dense block simply forward to the internal::BlockImpl_dense
168 // that must be specialized for direct and non-direct access...
169 template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
170 class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Dense>
171  : public internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel> {
172  typedef internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel> Impl;
173  typedef typename XprType::StorageIndex StorageIndex;
174 
175  public:
176  typedef Impl Base;
177  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
178  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index i) : Impl(xpr, i) {}
179  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index startRow, Index startCol)
180  : Impl(xpr, startRow, startCol) {}
181  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows,
182  Index blockCols)
183  : Impl(xpr, startRow, startCol, blockRows, blockCols) {}
184 };
185 
186 namespace internal {
187 
189 template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess>
190 class BlockImpl_dense : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel>>::type {
191  typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
192  typedef typename internal::ref_selector<XprType>::non_const_type XprTypeNested;
193 
194  public:
195  typedef typename internal::dense_xpr_base<BlockType>::type Base;
196  EIGEN_DENSE_PUBLIC_INTERFACE(BlockType)
197  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
198 
199  // class InnerIterator; // FIXME apparently never used
200 
201 
203  EIGEN_DEVICE_FUNC inline BlockImpl_dense(XprType& xpr, Index i)
204  : m_xpr(xpr),
205  // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
206  // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
207  // all other cases are invalid.
208  // The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
209  m_startRow((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) ? i : 0),
210  m_startCol((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) ? i : 0),
211  m_blockRows(BlockRows == 1 ? 1 : xpr.rows()),
212  m_blockCols(BlockCols == 1 ? 1 : xpr.cols()) {}
213 
216  EIGEN_DEVICE_FUNC inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
217  : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), m_blockRows(BlockRows), m_blockCols(BlockCols) {}
218 
221  EIGEN_DEVICE_FUNC inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol, Index blockRows,
222  Index blockCols)
223  : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), m_blockRows(blockRows), m_blockCols(blockCols) {}
224 
225  EIGEN_DEVICE_FUNC inline Index rows() const { return m_blockRows.value(); }
226  EIGEN_DEVICE_FUNC inline Index cols() const { return m_blockCols.value(); }
227 
228  EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index rowId, Index colId) {
229  EIGEN_STATIC_ASSERT_LVALUE(XprType)
230  return m_xpr.coeffRef(rowId + m_startRow.value(), colId + m_startCol.value());
231  }
232 
233  EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index rowId, Index colId) const {
234  return m_xpr.derived().coeffRef(rowId + m_startRow.value(), colId + m_startCol.value());
235  }
236 
237  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index rowId, Index colId) const {
238  return m_xpr.coeff(rowId + m_startRow.value(), colId + m_startCol.value());
239  }
240 
241  EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index index) {
242  EIGEN_STATIC_ASSERT_LVALUE(XprType)
243  return m_xpr.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
244  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
245  }
246 
247  EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index index) const {
248  return m_xpr.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
249  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
250  }
251 
252  EIGEN_DEVICE_FUNC inline const CoeffReturnType coeff(Index index) const {
253  return m_xpr.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
254  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
255  }
256 
257  template <int LoadMode>
258  EIGEN_DEVICE_FUNC inline PacketScalar packet(Index rowId, Index colId) const {
259  return m_xpr.template packet<Unaligned>(rowId + m_startRow.value(), colId + m_startCol.value());
260  }
261 
262  template <int LoadMode>
263  EIGEN_DEVICE_FUNC inline void writePacket(Index rowId, Index colId, const PacketScalar& val) {
264  m_xpr.template writePacket<Unaligned>(rowId + m_startRow.value(), colId + m_startCol.value(), val);
265  }
266 
267  template <int LoadMode>
268  EIGEN_DEVICE_FUNC inline PacketScalar packet(Index index) const {
269  return m_xpr.template packet<Unaligned>(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
270  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
271  }
272 
273  template <int LoadMode>
274  EIGEN_DEVICE_FUNC inline void writePacket(Index index, const PacketScalar& val) {
275  m_xpr.template writePacket<Unaligned>(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
276  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), val);
277  }
278 
279 #ifdef EIGEN_PARSED_BY_DOXYGEN
280 
281  EIGEN_DEVICE_FUNC constexpr const Scalar* data() const;
282  EIGEN_DEVICE_FUNC inline Index innerStride() const;
283  EIGEN_DEVICE_FUNC inline Index outerStride() const;
284 #endif
285 
286  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all_t<XprTypeNested>& nestedExpression() const {
287  return m_xpr;
288  }
289 
290  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE XprType& nestedExpression() { return m_xpr; }
291 
292  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr StorageIndex startRow() const noexcept { return m_startRow.value(); }
293 
294  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr StorageIndex startCol() const noexcept { return m_startCol.value(); }
295 
296  protected:
297  XprTypeNested m_xpr;
298  const internal::variable_if_dynamic<StorageIndex, (XprType::RowsAtCompileTime == 1 && BlockRows == 1) ? 0 : Dynamic>
299  m_startRow;
300  const internal::variable_if_dynamic<StorageIndex, (XprType::ColsAtCompileTime == 1 && BlockCols == 1) ? 0 : Dynamic>
301  m_startCol;
302  const internal::variable_if_dynamic<StorageIndex, RowsAtCompileTime> m_blockRows;
303  const internal::variable_if_dynamic<StorageIndex, ColsAtCompileTime> m_blockCols;
304 };
305 
307 template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
308 class BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel, true>
309  : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel>> {
310  typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
311  typedef typename internal::ref_selector<XprType>::non_const_type XprTypeNested;
312  enum { XprTypeIsRowMajor = (int(traits<XprType>::Flags) & RowMajorBit) != 0 };
313 
317  template <typename Scalar>
318  EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE static Scalar* add_to_nullable_pointer(Scalar* base, Index offset) {
319  return base != nullptr ? base + offset : nullptr;
320  }
321 
322  public:
323  typedef MapBase<BlockType> Base;
324  EIGEN_DENSE_PUBLIC_INTERFACE(BlockType)
325  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
326 
327 
329  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl_dense(XprType& xpr, Index i)
330  : Base((BlockRows == 0 || BlockCols == 0)
331  ? nullptr
332  : add_to_nullable_pointer(
333  xpr.data(),
334  i * (((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) && (!XprTypeIsRowMajor)) ||
335  ((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) &&
336  (XprTypeIsRowMajor))
337  ? xpr.innerStride()
338  : xpr.outerStride())),
339  BlockRows == 1 ? 1 : xpr.rows(), BlockCols == 1 ? 1 : xpr.cols()),
340  m_xpr(xpr),
341  m_startRow((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) ? i : 0),
342  m_startCol((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) ? i : 0) {
343  init();
344  }
345 
348  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
349  : Base((BlockRows == 0 || BlockCols == 0)
350  ? nullptr
351  : add_to_nullable_pointer(xpr.data(),
352  xpr.innerStride() * (XprTypeIsRowMajor ? startCol : startRow) +
353  xpr.outerStride() * (XprTypeIsRowMajor ? startRow : startCol))),
354  m_xpr(xpr),
355  m_startRow(startRow),
356  m_startCol(startCol) {
357  init();
358  }
359 
362  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl_dense(XprType& xpr, Index startRow, Index startCol, Index blockRows,
363  Index blockCols)
364  : Base((blockRows == 0 || blockCols == 0)
365  ? nullptr
366  : add_to_nullable_pointer(xpr.data(),
367  xpr.innerStride() * (XprTypeIsRowMajor ? startCol : startRow) +
368  xpr.outerStride() * (XprTypeIsRowMajor ? startRow : startCol)),
369  blockRows, blockCols),
370  m_xpr(xpr),
371  m_startRow(startRow),
372  m_startCol(startCol) {
373  init();
374  }
375 
376  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all_t<XprTypeNested>& nestedExpression() const noexcept {
377  return m_xpr;
378  }
379 
380  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE XprType& nestedExpression() { return m_xpr; }
381 
383  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index innerStride() const noexcept {
384  return internal::traits<BlockType>::HasSameStorageOrderAsXprType ? m_xpr.innerStride() : m_xpr.outerStride();
385  }
386 
388  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index outerStride() const noexcept {
389  return internal::traits<BlockType>::HasSameStorageOrderAsXprType ? m_xpr.outerStride() : m_xpr.innerStride();
390  }
391 
392  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr StorageIndex startRow() const noexcept { return m_startRow.value(); }
393 
394  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr StorageIndex startCol() const noexcept { return m_startCol.value(); }
395 
396 #ifndef __SUNPRO_CC
397  // FIXME sunstudio is not friendly with the above friend...
398  // META-FIXME there is no 'friend' keyword around here. Is this obsolete?
399  protected:
400 #endif
401 
402 #ifndef EIGEN_PARSED_BY_DOXYGEN
403 
404  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows,
405  Index blockCols)
406  : Base(data, blockRows, blockCols), m_xpr(xpr) {
407  init();
408  }
409 #endif
410 
411  protected:
412  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void init() {
413  m_outerStride =
414  internal::traits<BlockType>::HasSameStorageOrderAsXprType ? m_xpr.outerStride() : m_xpr.innerStride();
415  }
416 
417  XprTypeNested m_xpr;
418  const internal::variable_if_dynamic<StorageIndex, (XprType::RowsAtCompileTime == 1 && BlockRows == 1) ? 0 : Dynamic>
419  m_startRow;
420  const internal::variable_if_dynamic<StorageIndex, (XprType::ColsAtCompileTime == 1 && BlockCols == 1) ? 0 : Dynamic>
421  m_startCol;
422  Index m_outerStride;
423 };
424 
425 } // end namespace internal
426 
427 } // end namespace Eigen
428 
429 #endif // EIGEN_BLOCK_H
const unsigned int CompressedAccessBit
Definition: Constants.h:195
const unsigned int DirectAccessBit
Definition: Constants.h:159
const unsigned int LvalueBit
Definition: Constants.h:148
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
const unsigned int RowMajorBit
Definition: Constants.h:70
Block(XprType &xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
Definition: Block.h:141
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
Block(XprType &xpr, Index i)
Definition: Block.h:124
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:109
Block(XprType &xpr, Index startRow, Index startCol)
Definition: Block.h:131
const int Dynamic
Definition: Constants.h:25