Eigen  5.0.1
 
Loading...
Searching...
No Matches
SparseBlock.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_SPARSE_BLOCK_H
12#define EIGEN_SPARSE_BLOCK_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19// Subset of columns or rows
20template <typename XprType, int BlockRows, int BlockCols>
21class BlockImpl<XprType, BlockRows, BlockCols, true, Sparse>
22 : public SparseCompressedBase<Block<XprType, BlockRows, BlockCols, true> > {
23 using BlockType = Block<XprType, BlockRows, BlockCols, true>;
24
25 public:
26 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
27
28 protected:
29 enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
30 using Base = SparseCompressedBase<BlockType>;
31 using Base::convert_index;
32
33 public:
34 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
35
36 inline BlockImpl(XprType& xpr, Index i) : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize) {}
37
38 inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
39 : m_matrix(xpr),
40 m_outerStart(convert_index(IsRowMajor ? startRow : startCol)),
41 m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols)) {}
42
43 EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
44 EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
45
46 Index nonZeros() const {
47 return nonZerosImpl(std::integral_constant<bool, (internal::traits<XprType>::Flags & CompressedAccessBit) != 0>());
48 }
49
50 protected:
51 Index nonZerosImpl(std::true_type) const {
52 if (m_outerSize.value() == 0) return 0;
53 const StorageIndex* outer = m_matrix.outerIndexPtr();
54 if (!outer) return m_matrix.nonZeros();
55 const StorageIndex* innerNonZeros = m_matrix.innerNonZeroPtr();
56 if (!innerNonZeros) return outer[m_outerStart + m_outerSize.value()] - outer[m_outerStart];
57 Index nnz = 0;
58 for (Index j = m_outerStart; j < m_outerStart + m_outerSize.value(); ++j) nnz += innerNonZeros[j];
59 return nnz;
60 }
61
62 Index nonZerosImpl(std::false_type) const {
63 using EvaluatorType = internal::evaluator<XprType>;
64 EvaluatorType matEval(m_matrix);
65 Index nnz = 0;
66 Index end = m_outerStart + m_outerSize.value();
67 for (Index j = m_outerStart; j < end; ++j)
68 for (typename EvaluatorType::InnerIterator it(matEval, j); it; ++it) ++nnz;
69 return nnz;
70 }
71
72 public:
73 inline const Scalar coeff(Index row, Index col) const {
74 return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
75 }
76
77 inline const Scalar coeff(Index index) const {
78 return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
79 }
80
81 inline const XprType& nestedExpression() const { return m_matrix; }
82 inline XprType& nestedExpression() { return m_matrix; }
83 Index startRow() const { return IsRowMajor ? m_outerStart : 0; }
84 Index startCol() const { return IsRowMajor ? 0 : m_outerStart; }
85 Index blockRows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
86 Index blockCols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
87
88 inline const Scalar* valuePtr() const { return m_matrix.valuePtr(); }
89 inline Scalar* valuePtr() { return m_matrix.valuePtr(); }
90
91 inline const StorageIndex* innerIndexPtr() const { return m_matrix.innerIndexPtr(); }
92 inline StorageIndex* innerIndexPtr() { return m_matrix.innerIndexPtr(); }
93
94 inline const StorageIndex* outerIndexPtr() const {
95 const StorageIndex* p = m_matrix.outerIndexPtr();
96 return p ? p + m_outerStart : 0;
97 }
98 inline StorageIndex* outerIndexPtr() {
99 StorageIndex* p = m_matrix.outerIndexPtr();
100 return p ? p + m_outerStart : 0;
101 }
102
103 inline const StorageIndex* innerNonZeroPtr() const {
104 const StorageIndex* p = m_matrix.innerNonZeroPtr();
105 return p ? p + m_outerStart : 0;
106 }
107 inline StorageIndex* innerNonZeroPtr() {
108 StorageIndex* p = m_matrix.innerNonZeroPtr();
109 return p ? p + m_outerStart : 0;
110 }
111
112 bool isCompressed() const { return m_matrix.innerNonZeroPtr() == 0; }
113
114 protected:
115 typename internal::ref_selector<XprType>::non_const_type m_matrix;
116 Index m_outerStart;
117 const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
118
119 protected:
120 // Disable assignment with clear error message.
121 // Note that simply removing operator= yields compilation errors with ICC+MSVC
122 template <typename T>
123 BlockImpl& operator=(const T&) {
124 EIGEN_STATIC_ASSERT(sizeof(T) == 0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY);
125 return *this;
126 }
127};
128
129/***************************************************************************
130 * specialization for SparseMatrix
131 ***************************************************************************/
132
133namespace internal {
134
135template <typename SparseMatrixType, int BlockRows, int BlockCols>
136class sparse_matrix_block_impl : public SparseCompressedBase<Block<SparseMatrixType, BlockRows, BlockCols, true> > {
137 using BlockType = Block<SparseMatrixType, BlockRows, BlockCols, true>;
139 using Base::convert_index;
140
141 public:
142 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
143 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
144 protected:
145 enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
146
147 public:
148 inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index i)
149 : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize) {}
150
151 inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows,
152 Index blockCols)
153 : m_matrix(xpr),
154 m_outerStart(convert_index(IsRowMajor ? startRow : startCol)),
155 m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols)) {}
156
157 template <typename OtherDerived>
158 inline BlockType& operator=(const SparseMatrixBase<OtherDerived>& other) {
159 using NestedMatrixType_ = internal::remove_all_t<typename SparseMatrixType::Nested>;
160 NestedMatrixType_& matrix = m_matrix;
161 // This assignment is slow if this vector set is not empty
162 // and/or it is not at the end of the nonzeros of the underlying matrix.
163
164 // 1 - eval to a temporary to avoid transposition and/or aliasing issues
165 Ref<const SparseMatrix<Scalar, IsRowMajor ? RowMajor : ColMajor, StorageIndex> > tmp(other.derived());
166 eigen_internal_assert(tmp.outerSize() == m_outerSize.value());
167
168 // 2 - let's check whether there is enough allocated memory
169 Index nnz = tmp.nonZeros();
170 Index start =
171 m_outerStart == 0 ? 0 : m_matrix.outerIndexPtr()[m_outerStart]; // starting position of the current block
172 Index end = m_matrix.outerIndexPtr()[m_outerStart + m_outerSize.value()]; // ending position of the current block
173 Index block_size = end - start; // available room in the current block
174 Index tail_size = m_matrix.outerIndexPtr()[m_matrix.outerSize()] - end;
175
176 Index free_size = m_matrix.isCompressed() ? Index(matrix.data().allocatedSize()) + block_size : block_size;
177
178 Index tmp_start = tmp.outerIndexPtr()[0];
179
180 bool update_trailing_pointers = false;
181 if (nnz > free_size) {
182 // realloc manually to reduce copies
183 typename SparseMatrixType::Storage newdata(m_matrix.data().allocatedSize() - block_size + nnz);
184
185 internal::smart_copy(m_matrix.valuePtr(), m_matrix.valuePtr() + start, newdata.valuePtr());
186 internal::smart_copy(m_matrix.innerIndexPtr(), m_matrix.innerIndexPtr() + start, newdata.indexPtr());
187
188 internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, newdata.valuePtr() + start);
189 internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz,
190 newdata.indexPtr() + start);
191
192 internal::smart_copy(matrix.valuePtr() + end, matrix.valuePtr() + end + tail_size,
193 newdata.valuePtr() + start + nnz);
194 internal::smart_copy(matrix.innerIndexPtr() + end, matrix.innerIndexPtr() + end + tail_size,
195 newdata.indexPtr() + start + nnz);
196
197 newdata.resize(m_matrix.outerIndexPtr()[m_matrix.outerSize()] - block_size + nnz);
198
199 matrix.data().swap(newdata);
200
201 update_trailing_pointers = true;
202 } else {
203 if (m_matrix.isCompressed() && nnz != block_size) {
204 // no need to realloc, simply copy the tail at its respective position and insert tmp
205 matrix.data().resize(start + nnz + tail_size);
206
207 internal::smart_memmove(matrix.valuePtr() + end, matrix.valuePtr() + end + tail_size,
208 matrix.valuePtr() + start + nnz);
209 internal::smart_memmove(matrix.innerIndexPtr() + end, matrix.innerIndexPtr() + end + tail_size,
210 matrix.innerIndexPtr() + start + nnz);
211
212 update_trailing_pointers = true;
213 }
214
215 internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, matrix.valuePtr() + start);
216 internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz,
217 matrix.innerIndexPtr() + start);
218 }
219
220 // update outer index pointers and innerNonZeros
221 EIGEN_IF_CONSTEXPR (IsVectorAtCompileTime) {
222 if (!m_matrix.isCompressed()) matrix.innerNonZeroPtr()[m_outerStart] = StorageIndex(nnz);
223 matrix.outerIndexPtr()[m_outerStart] = StorageIndex(start);
224 } else {
225 StorageIndex p = StorageIndex(start);
226 for (Index k = 0; k < m_outerSize.value(); ++k) {
227 StorageIndex nnz_k = internal::convert_index<StorageIndex>(tmp.innerVector(k).nonZeros());
228 if (!m_matrix.isCompressed()) matrix.innerNonZeroPtr()[m_outerStart + k] = nnz_k;
229 matrix.outerIndexPtr()[m_outerStart + k] = p;
230 p += nnz_k;
231 }
232 }
233
234 if (update_trailing_pointers) {
235 StorageIndex offset = internal::convert_index<StorageIndex>(nnz - block_size);
236 for (Index k = m_outerStart + m_outerSize.value(); k <= matrix.outerSize(); ++k) {
237 matrix.outerIndexPtr()[k] += offset;
238 }
239 }
240
241 return derived();
242 }
243
244 inline BlockType& operator=(const BlockType& other) { return operator= <BlockType>(other); }
245
246 inline const Scalar* valuePtr() const { return m_matrix.valuePtr(); }
247 inline Scalar* valuePtr() { return m_matrix.valuePtr(); }
248
249 inline const StorageIndex* innerIndexPtr() const { return m_matrix.innerIndexPtr(); }
250 inline StorageIndex* innerIndexPtr() { return m_matrix.innerIndexPtr(); }
251
252 inline const StorageIndex* outerIndexPtr() const { return m_matrix.outerIndexPtr() + m_outerStart; }
253 inline StorageIndex* outerIndexPtr() { return m_matrix.outerIndexPtr() + m_outerStart; }
254
255 inline const StorageIndex* innerNonZeroPtr() const {
256 return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr() + m_outerStart);
257 }
258 inline StorageIndex* innerNonZeroPtr() { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr() + m_outerStart); }
259
260 bool isCompressed() const { return m_matrix.innerNonZeroPtr() == 0; }
261
262 inline Scalar& coeffRef(Index row, Index col) {
263 return m_matrix.coeffRef(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
264 }
265
266 inline const Scalar coeff(Index row, Index col) const {
267 return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
268 }
269
270 inline const Scalar coeff(Index index) const {
271 return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
272 }
273
274 const Scalar& lastCoeff() const {
275 EIGEN_STATIC_ASSERT_VECTOR_ONLY(sparse_matrix_block_impl);
276 eigen_assert(Base::nonZeros() > 0);
277 if (m_matrix.isCompressed())
278 return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart + 1] - 1];
279 else
280 return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart] + m_matrix.innerNonZeroPtr()[m_outerStart] - 1];
281 }
282
283 EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
284 EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
285
286 inline const SparseMatrixType& nestedExpression() const { return m_matrix; }
287 inline SparseMatrixType& nestedExpression() { return m_matrix; }
288 Index startRow() const { return IsRowMajor ? m_outerStart : 0; }
289 Index startCol() const { return IsRowMajor ? 0 : m_outerStart; }
290 Index blockRows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
291 Index blockCols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
292
293 protected:
294 typename internal::ref_selector<SparseMatrixType>::non_const_type m_matrix;
295 Index m_outerStart;
296 const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
297};
298
299} // namespace internal
300
301template <typename Scalar_, int Options_, typename StorageIndex_, int BlockRows, int BlockCols>
302class BlockImpl<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true, Sparse>
303 : public internal::sparse_matrix_block_impl<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols> {
304 public:
305 using StorageIndex = StorageIndex_;
306 using SparseMatrixType = SparseMatrix<Scalar_, Options_, StorageIndex_>;
307 using Base = internal::sparse_matrix_block_impl<SparseMatrixType, BlockRows, BlockCols>;
308 inline BlockImpl(SparseMatrixType& xpr, Index i) : Base(xpr, i) {}
309
310 inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
311 : Base(xpr, startRow, startCol, blockRows, blockCols) {}
312
313 using Base::operator=;
314};
315
316template <typename Scalar_, int Options_, typename StorageIndex_, int BlockRows, int BlockCols>
317class BlockImpl<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true, Sparse>
318 : public internal::sparse_matrix_block_impl<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows,
319 BlockCols> {
320 public:
321 using StorageIndex = StorageIndex_;
322 using SparseMatrixType = const SparseMatrix<Scalar_, Options_, StorageIndex_>;
323 using Base = internal::sparse_matrix_block_impl<SparseMatrixType, BlockRows, BlockCols>;
324 inline BlockImpl(SparseMatrixType& xpr, Index i) : Base(xpr, i) {}
325
326 inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
327 : Base(xpr, startRow, startCol, blockRows, blockCols) {}
328
329 using Base::operator=;
330
331 private:
332 template <typename Derived>
333 BlockImpl(const SparseMatrixBase<Derived>& xpr, Index i);
334 template <typename Derived>
335 BlockImpl(const SparseMatrixBase<Derived>& xpr);
336};
337
338//----------
339
343template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
344class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Sparse>
345 : public SparseMatrixBase<Block<XprType, BlockRows, BlockCols, InnerPanel> >, internal::no_assignment_operator {
347 using Base = SparseMatrixBase<BlockType>;
348 using Base::convert_index;
349
350 public:
351 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
352 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
353
354 using MatrixTypeNested_ = internal::remove_all_t<typename XprType::Nested>;
355
358 inline BlockImpl(XprType& xpr, Index i)
359 : m_matrix(xpr),
360 m_startRow((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) ? convert_index(i) : 0),
361 m_startCol((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) ? convert_index(i) : 0),
362 m_blockRows(BlockRows == 1 ? 1 : xpr.rows()),
363 m_blockCols(BlockCols == 1 ? 1 : xpr.cols()) {}
364
367 inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
368 : m_matrix(xpr),
369 m_startRow(convert_index(startRow)),
370 m_startCol(convert_index(startCol)),
371 m_blockRows(convert_index(blockRows)),
372 m_blockCols(convert_index(blockCols)) {}
373
374 inline Index rows() const { return m_blockRows.value(); }
375 inline Index cols() const { return m_blockCols.value(); }
376
377 inline Scalar& coeffRef(Index row, Index col) {
378 return m_matrix.coeffRef(row + m_startRow.value(), col + m_startCol.value());
379 }
380
381 inline const Scalar coeff(Index row, Index col) const {
382 return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value());
383 }
384
385 inline Scalar& coeffRef(Index index) {
386 return m_matrix.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
387 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
388 }
389
390 inline const Scalar coeff(Index index) const {
391 return m_matrix.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
392 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
393 }
394
395 inline const XprType& nestedExpression() const { return m_matrix; }
396 inline XprType& nestedExpression() { return m_matrix; }
397 Index startRow() const { return m_startRow.value(); }
398 Index startCol() const { return m_startCol.value(); }
399 Index blockRows() const { return m_blockRows.value(); }
400 Index blockCols() const { return m_blockCols.value(); }
401
402 protected:
403 friend struct internal::unary_evaluator<Block<XprType, BlockRows, BlockCols, InnerPanel>, internal::IteratorBased,
404 Scalar>;
405
406 Index nonZeros() const { return Dynamic; }
407
408 typename internal::ref_selector<XprType>::non_const_type m_matrix;
409 const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
410 const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
411 const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows;
412 const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
413
414 protected:
415 // Disable assignment with clear error message.
416 // Note that simply removing operator= yields compilation errors with ICC+MSVC
417 template <typename T>
418 BlockImpl& operator=(const T&) {
419 EIGEN_STATIC_ASSERT(sizeof(T) == 0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY);
420 return *this;
421 }
422};
423
424namespace internal {
425
426template <typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
427struct unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>, IteratorBased>
428 : public evaluator_base<Block<ArgType, BlockRows, BlockCols, InnerPanel> > {
429 class InnerVectorInnerIterator;
430 class OuterVectorInnerIterator;
431
432 public:
433 using XprType = Block<ArgType, BlockRows, BlockCols, InnerPanel>;
434 using StorageIndex = typename XprType::StorageIndex;
435 using Scalar = typename XprType::Scalar;
436
437 enum {
438 IsRowMajor = XprType::IsRowMajor,
439 OuterVector = (BlockCols == 1 && ArgType::IsRowMajor) || (BlockRows == 1 && !ArgType::IsRowMajor),
440 CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
441 Flags = XprType::Flags
442 };
443
444 using InnerIterator = std::conditional_t<OuterVector, OuterVectorInnerIterator, InnerVectorInnerIterator>;
445
446 explicit unary_evaluator(const XprType& op) : m_argImpl(op.nestedExpression()), m_block(op) {}
447
448 inline Index nonZerosEstimate() const {
449 const Index nnz = m_block.nonZeros();
450 if (nnz < 0) {
451 // Scale the non-zero estimate for the underlying expression linearly with block size.
452 // Return zero if the underlying block is empty.
453 const Index nested_sz = m_block.nestedExpression().size();
454 return nested_sz == 0 ? 0 : m_argImpl.nonZerosEstimate() * m_block.size() / nested_sz;
455 }
456 return nnz;
457 }
458
459 protected:
460 using EvalIterator = typename evaluator<ArgType>::InnerIterator;
461
462 evaluator<ArgType> m_argImpl;
463 const XprType& m_block;
464};
465
466template <typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
467class unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>, IteratorBased>::InnerVectorInnerIterator
468 : public EvalIterator {
469 // NOTE MSVC fails to compile if we don't explicitly "import" IsRowMajor from unary_evaluator
470 // because the base class EvalIterator has a private IsRowMajor enum too. (bug #1786)
471 // NOTE We cannot call it IsRowMajor because it would shadow unary_evaluator::IsRowMajor
472 enum { XprIsRowMajor = unary_evaluator::IsRowMajor };
473 const XprType& m_block;
474 Index m_end;
475
476 public:
477 EIGEN_STRONG_INLINE InnerVectorInnerIterator(const unary_evaluator& aEval, Index outer)
478 : EvalIterator(aEval.m_argImpl, outer + (XprIsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol())),
479 m_block(aEval.m_block),
480 m_end(XprIsRowMajor ? aEval.m_block.startCol() + aEval.m_block.blockCols()
481 : aEval.m_block.startRow() + aEval.m_block.blockRows()) {
482 while ((EvalIterator::operator bool()) &&
483 (EvalIterator::index() < (XprIsRowMajor ? m_block.startCol() : m_block.startRow())))
484 EvalIterator::operator++();
485 }
486
487 inline StorageIndex index() const {
488 return EvalIterator::index() - convert_index<StorageIndex>(XprIsRowMajor ? m_block.startCol() : m_block.startRow());
489 }
490 inline Index outer() const {
491 return EvalIterator::outer() - (XprIsRowMajor ? m_block.startRow() : m_block.startCol());
492 }
493 inline Index row() const { return EvalIterator::row() - m_block.startRow(); }
494 inline Index col() const { return EvalIterator::col() - m_block.startCol(); }
495
496 inline operator bool() const { return EvalIterator::operator bool() && EvalIterator::index() < m_end; }
497};
498
499template <typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
500class unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>, IteratorBased>::OuterVectorInnerIterator {
501 // NOTE see above
502 enum { XprIsRowMajor = unary_evaluator::IsRowMajor };
503 const unary_evaluator& m_eval;
504 Index m_outerPos;
505 const Index m_innerIndex;
506 Index m_end;
507 EvalIterator m_it;
508
509 public:
510 EIGEN_STRONG_INLINE OuterVectorInnerIterator(const unary_evaluator& aEval, Index outer)
511 : m_eval(aEval),
512 m_outerPos((XprIsRowMajor ? aEval.m_block.startCol() : aEval.m_block.startRow())),
513 m_innerIndex(XprIsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol()),
514 m_end(XprIsRowMajor ? aEval.m_block.startCol() + aEval.m_block.blockCols()
515 : aEval.m_block.startRow() + aEval.m_block.blockRows()),
516 m_it(m_eval.m_argImpl, m_outerPos) {
517 EIGEN_UNUSED_VARIABLE(outer);
518 eigen_assert(outer == 0);
519
520 while (m_it && m_it.index() < m_innerIndex) ++m_it;
521 if ((!m_it) || (m_it.index() != m_innerIndex)) ++(*this);
522 }
523
524 inline StorageIndex index() const {
525 return convert_index<StorageIndex>(m_outerPos -
526 (XprIsRowMajor ? m_eval.m_block.startCol() : m_eval.m_block.startRow()));
527 }
528 inline Index outer() const { return 0; }
529 inline Index row() const { return XprIsRowMajor ? 0 : index(); }
530 inline Index col() const { return XprIsRowMajor ? index() : 0; }
531
532 inline Scalar value() const { return m_it.value(); }
533 inline Scalar& valueRef() { return m_it.valueRef(); }
534
535 inline OuterVectorInnerIterator& operator++() {
536 // search next non-zero entry
537 while (++m_outerPos < m_end) {
538 // Restart iterator at the next inner-vector:
539 internal::destroy_at(&m_it);
540 internal::construct_at(&m_it, m_eval.m_argImpl, m_outerPos);
541 // search for the key m_innerIndex in the current outer-vector
542 while (m_it && m_it.index() < m_innerIndex) ++m_it;
543 if (m_it && m_it.index() == m_innerIndex) break;
544 }
545 return *this;
546 }
547
548 inline operator bool() const { return m_outerPos < m_end; }
549};
550
551template <typename Scalar_, int Options_, typename StorageIndex_, int BlockRows, int BlockCols>
552struct unary_evaluator<Block<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true>, IteratorBased>
553 : evaluator<
554 SparseCompressedBase<Block<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true> > > {
555 using XprType = Block<SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true>;
556 using Base = evaluator<SparseCompressedBase<XprType>>;
557 explicit unary_evaluator(const XprType& xpr) : Base(xpr) {}
558};
559
560template <typename Scalar_, int Options_, typename StorageIndex_, int BlockRows, int BlockCols>
561struct unary_evaluator<Block<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true>,
562 IteratorBased>
563 : evaluator<SparseCompressedBase<
564 Block<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true> > > {
565 using XprType = Block<const SparseMatrix<Scalar_, Options_, StorageIndex_>, BlockRows, BlockCols, true>;
566 using Base = evaluator<SparseCompressedBase<XprType>>;
567 explicit unary_evaluator(const XprType& xpr) : Base(xpr) {}
568};
569
570} // end namespace internal
571
572} // end namespace Eigen
573
574#endif // EIGEN_SPARSE_BLOCK_H
BlockImpl(XprType &xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
Definition SparseBlock.h:367
BlockImpl(XprType &xpr, Index i)
Definition SparseBlock.h:358
Expression of a fixed-size or dynamic-size block.
Definition Block.h:111
Common base class for sparse [compressed]-{row|column}-storage format.
Definition SparseCompressedBase.h:44
constexpr RowXpr row(Index i)
Definition SparseMatrixBase.h:1094
typename internal::traits< Derived >::StorageIndex StorageIndex
Definition SparseMatrixBase.h:45
constexpr ColXpr col(Index i)
Definition SparseMatrixBase.h:1081
@ IsVectorAtCompileTime
Definition SparseMatrixBase.h:82
A versatile sparse matrix representation.
Definition SparseMatrix.h:122
constexpr unsigned int CompressedAccessBit
Definition Constants.h:196
constexpr Derived & derived()
Definition EigenBase.h:50
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:44
Definition Constants.h:545