Eigen  5.0.1
 
Loading...
Searching...
No Matches
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// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_BLOCK_H
13#define EIGEN_BLOCK_H
14
15// IWYU pragma: private
16#include "./InternalHeaderCheck.h"
17
18namespace Eigen {
19
20namespace internal {
21template <typename XprType_, int BlockRows, int BlockCols, bool InnerPanel_>
22struct traits<Block<XprType_, BlockRows, BlockCols, InnerPanel_>> : traits<XprType_> {
23 using Scalar = typename traits<XprType_>::Scalar;
24 using StorageKind = typename traits<XprType_>::StorageKind;
25 using XprKind = typename traits<XprType_>::XprKind;
26 using XprTypeNested = typename ref_selector<XprType_>::type;
27 using XprTypeNested_ = std::remove_reference_t<XprTypeNested>;
28 enum {
29 MatrixRows = traits<XprType_>::RowsAtCompileTime,
30 MatrixCols = traits<XprType_>::ColsAtCompileTime,
31 RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows,
32 ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols,
33 MaxRowsAtCompileTime = BlockRows == 0 ? 0
34 : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime)
35 : int(traits<XprType_>::MaxRowsAtCompileTime),
36 MaxColsAtCompileTime = BlockCols == 0 ? 0
37 : ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
38 : int(traits<XprType_>::MaxColsAtCompileTime),
39
40 XprTypeIsRowMajor = (int(traits<XprType_>::Flags) & RowMajorBit) != 0,
41 IsRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? 1
42 : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) ? 0
43 : XprTypeIsRowMajor,
44 HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
45 InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
46 InnerStrideAtCompileTime = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time<XprType_>::value)
47 : int(outer_stride_at_compile_time<XprType_>::value),
48 OuterStrideAtCompileTime = HasSameStorageOrderAsXprType ? int(outer_stride_at_compile_time<XprType_>::value)
49 : int(inner_stride_at_compile_time<XprType_>::value),
50
51 // FIXME, this traits is rather specialized for dense object and it needs to be cleaned further
52 FlagsLvalueBit = is_lvalue<XprType_>::value ? LvalueBit : 0,
53 FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
54 Flags = (traits<XprType_>::Flags & (DirectAccessBit | (InnerPanel_ ? CompressedAccessBit : 0))) | FlagsLvalueBit |
55 FlagsRowMajorBit,
56 // FIXME DirectAccessBit should not be handled by expressions
57 //
58 // Alignment is needed by MapBase's assertions
59 // We can safely set it to false here. Internal alignment errors will be detected by an eigen_internal_assert in the
60 // respective evaluator
61 Alignment = 0,
62 InnerPanel = InnerPanel_ ? 1 : 0
63 };
64};
65
66template <typename XprType, int BlockRows = Dynamic, int BlockCols = Dynamic, bool InnerPanel = false,
67 bool HasDirectAccess = internal::has_direct_access<XprType>::value>
68class BlockImpl_dense;
69
70} // end namespace internal
71
72template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel, typename StorageKind>
73class BlockImpl;
74
109template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
110class Block
111 : public BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind> {
112 using Impl = BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind>;
113 using BlockHelper = internal::block_xpr_helper<Block>;
114
115 public:
116 // typedef typename Impl::Base Base;
117 using Base = Impl;
118 EIGEN_GENERIC_PUBLIC_INTERFACE(Block)
119 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
120
121 using NestedExpression = internal::remove_all_t<XprType>;
122
125 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Block(XprType& xpr, Index i) : Impl(xpr, i) {
126 eigen_assert((i >= 0) && (((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) && i < xpr.rows()) ||
127 ((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) && i < xpr.cols())));
128 }
129
132 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Block(XprType& xpr, Index startRow, Index startCol)
133 : Impl(xpr, startRow, startCol) {
134 EIGEN_STATIC_ASSERT(RowsAtCompileTime != Dynamic && ColsAtCompileTime != Dynamic,
135 THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
136 eigen_assert(startRow >= 0 && BlockRows >= 0 && startRow + BlockRows <= xpr.rows() && startCol >= 0 &&
137 BlockCols >= 0 && startCol + BlockCols <= xpr.cols());
138 }
139
142 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Block(XprType& xpr, Index startRow, Index startCol, Index blockRows,
143 Index blockCols)
144 : Impl(xpr, startRow, startCol, blockRows, blockCols) {
145 eigen_assert((RowsAtCompileTime == Dynamic || RowsAtCompileTime == blockRows) &&
146 (ColsAtCompileTime == Dynamic || ColsAtCompileTime == blockCols));
147 eigen_assert(startRow >= 0 && blockRows >= 0 && startRow <= xpr.rows() - blockRows && startCol >= 0 &&
148 blockCols >= 0 && startCol <= xpr.cols() - blockCols);
149 }
150
151 // convert nested blocks (e.g. Block<Block<MatrixType>>) to a simple block expression (Block<MatrixType>)
152
153 static constexpr bool UnwoundInnerPanel = BlockHelper::is_inner_panel(true);
156
157 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ConstUnwindReturnType unwind() const {
158 return ConstUnwindReturnType(BlockHelper::base(*this), BlockHelper::row(*this, 0), BlockHelper::col(*this, 0),
159 this->rows(), this->cols());
160 }
161
162 template <typename T = Block, typename EnableIf = std::enable_if_t<!std::is_const<T>::value>>
163 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE UnwindReturnType unwind() {
164 return UnwindReturnType(BlockHelper::base(*this), BlockHelper::row(*this, 0), BlockHelper::col(*this, 0),
165 this->rows(), this->cols());
166 }
167};
168
169// The generic default implementation for dense block simply forward to the internal::BlockImpl_dense
170// that must be specialized for direct and non-direct access...
171template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
172class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Dense>
173 : public internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel> {
174 using Impl = internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel>;
175 using StorageIndex = typename XprType::StorageIndex;
176
177 public:
178 using Base = Impl;
179 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
180 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index i) : Impl(xpr, i) {}
181 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index startRow, Index startCol)
182 : Impl(xpr, startRow, startCol) {}
183 EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index startRow, Index startCol,
184 Index blockRows, Index blockCols)
185 : Impl(xpr, startRow, startCol, blockRows, blockCols) {}
186};
187
188namespace internal {
189
191template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess>
192class BlockImpl_dense : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel>>::type {
193 using BlockType = Block<XprType, BlockRows, BlockCols, InnerPanel>;
194 using XprTypeNested = typename internal::ref_selector<XprType>::non_const_type;
195
196 public:
197 using Base = typename internal::dense_xpr_base<BlockType>::type;
198 EIGEN_DENSE_PUBLIC_INTERFACE(BlockType)
199 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
200
201
203 EIGEN_DEVICE_FUNC constexpr 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 constexpr 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 constexpr 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 constexpr Index rows() const { return m_blockRows.value(); }
226 EIGEN_DEVICE_FUNC constexpr 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
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 constexpr StorageIndex startRow() const noexcept { return m_startRow.value(); }
293
294 EIGEN_DEVICE_FUNC 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
307template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
308class BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel, true>
309 : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel>> {
310 using BlockType = Block<XprType, BlockRows, BlockCols, InnerPanel>;
311 using XprTypeNested = typename internal::ref_selector<XprType>::non_const_type;
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 using Base = MapBase<BlockType>;
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 constexpr Index innerStride() const noexcept {
384 return internal::traits<BlockType>::HasSameStorageOrderAsXprType ? m_xpr.innerStride() : m_xpr.outerStride();
385 }
386
388 EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_outerStride; }
389
390 EIGEN_DEVICE_FUNC constexpr StorageIndex startRow() const noexcept { return m_startRow.value(); }
391
392 EIGEN_DEVICE_FUNC constexpr StorageIndex startCol() const noexcept { return m_startCol.value(); }
393
394 protected:
395 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void init() {
396 m_outerStride =
397 internal::traits<BlockType>::HasSameStorageOrderAsXprType ? m_xpr.outerStride() : m_xpr.innerStride();
398 }
399
400 XprTypeNested m_xpr;
401 const internal::variable_if_dynamic<StorageIndex, (XprType::RowsAtCompileTime == 1 && BlockRows == 1) ? 0 : Dynamic>
402 m_startRow;
403 const internal::variable_if_dynamic<StorageIndex, (XprType::ColsAtCompileTime == 1 && BlockCols == 1) ? 0 : Dynamic>
404 m_startCol;
405 Index m_outerStride;
406};
407
408} // end namespace internal
409
410} // end namespace Eigen
411
412#endif // EIGEN_BLOCK_H
Expression of a fixed-size or dynamic-size block.
Definition Block.h:111
constexpr Block(XprType &xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
Definition Block.h:142
constexpr Block(XprType &xpr, Index i)
Definition Block.h:125
constexpr Block(XprType &xpr, Index startRow, Index startCol)
Definition Block.h:132
constexpr unsigned int DirectAccessBit
Definition Constants.h:160
constexpr unsigned int LvalueBit
Definition Constants.h:149
constexpr unsigned int RowMajorBit
Definition Constants.h:71
constexpr unsigned int CompressedAccessBit
Definition Constants.h:196