Eigen  3.3.0
 
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
10#ifndef EIGEN_SPARSE_BLOCK_H
11#define EIGEN_SPARSE_BLOCK_H
12
13namespace Eigen {
14
15// Subset of columns or rows
16template<typename XprType, int BlockRows, int BlockCols>
17class BlockImpl<XprType,BlockRows,BlockCols,true,Sparse>
18 : public SparseMatrixBase<Block<XprType,BlockRows,BlockCols,true> >
19{
20 typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
21 typedef Block<XprType, BlockRows, BlockCols, true> BlockType;
22public:
23 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
24protected:
25 enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
26 typedef SparseMatrixBase<BlockType> Base;
27 using Base::convert_index;
28public:
29 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
30
31 inline BlockImpl(XprType& xpr, Index i)
32 : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize)
33 {}
34
35 inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
36 : m_matrix(xpr), m_outerStart(convert_index(IsRowMajor ? startRow : startCol)), m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols))
37 {}
38
39 EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
40 EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
41
42 Index nonZeros() const
43 {
44 typedef internal::evaluator<XprType> EvaluatorType;
45 EvaluatorType matEval(m_matrix);
46 Index nnz = 0;
47 Index end = m_outerStart + m_outerSize.value();
48 for(Index j=m_outerStart; j<end; ++j)
49 for(typename EvaluatorType::InnerIterator it(matEval, j); it; ++it)
50 ++nnz;
51 return nnz;
52 }
53
54 inline const Scalar coeff(Index row, Index col) const
55 {
56 return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
57 }
58
59 inline const Scalar coeff(Index index) const
60 {
61 return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
62 }
63
64 inline const XprType& nestedExpression() const { return m_matrix; }
65 inline XprType& nestedExpression() { return m_matrix; }
66 Index startRow() const { return IsRowMajor ? m_outerStart : 0; }
67 Index startCol() const { return IsRowMajor ? 0 : m_outerStart; }
68 Index blockRows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
69 Index blockCols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
70
71 protected:
72
73 typename internal::ref_selector<XprType>::non_const_type m_matrix;
74 Index m_outerStart;
75 const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
76
77 protected:
78 // Disable assignment with clear error message.
79 // Note that simply removing operator= yields compilation errors with ICC+MSVC
80 template<typename T>
81 BlockImpl& operator=(const T&)
82 {
83 EIGEN_STATIC_ASSERT(sizeof(T)==0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY);
84 return *this;
85 }
86};
87
88
89/***************************************************************************
90* specialization for SparseMatrix
91***************************************************************************/
92
93namespace internal {
94
95template<typename SparseMatrixType, int BlockRows, int BlockCols>
96class sparse_matrix_block_impl
97 : public SparseCompressedBase<Block<SparseMatrixType,BlockRows,BlockCols,true> >
98{
99 typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _MatrixTypeNested;
100 typedef Block<SparseMatrixType, BlockRows, BlockCols, true> BlockType;
101 typedef SparseCompressedBase<Block<SparseMatrixType,BlockRows,BlockCols,true> > Base;
102 using Base::convert_index;
103public:
104 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
105 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
106protected:
107 typedef typename Base::IndexVector IndexVector;
108 enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
109public:
110
111 inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index i)
112 : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize)
113 {}
114
115 inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
116 : m_matrix(xpr), m_outerStart(convert_index(IsRowMajor ? startRow : startCol)), m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols))
117 {}
118
119 template<typename OtherDerived>
120 inline BlockType& operator=(const SparseMatrixBase<OtherDerived>& other)
121 {
122 typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _NestedMatrixType;
123 _NestedMatrixType& matrix = m_matrix;
124 // This assignment is slow if this vector set is not empty
125 // and/or it is not at the end of the nonzeros of the underlying matrix.
126
127 // 1 - eval to a temporary to avoid transposition and/or aliasing issues
128 Ref<const SparseMatrix<Scalar, IsRowMajor ? RowMajor : ColMajor, StorageIndex> > tmp(other.derived());
129 eigen_internal_assert(tmp.outerSize()==m_outerSize.value());
130
131 // 2 - let's check whether there is enough allocated memory
132 Index nnz = tmp.nonZeros();
133 Index start = m_outerStart==0 ? 0 : matrix.outerIndexPtr()[m_outerStart]; // starting position of the current block
134 Index end = m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()]; // ending position of the current block
135 Index block_size = end - start; // available room in the current block
136 Index tail_size = m_matrix.outerIndexPtr()[m_matrix.outerSize()] - end;
137
138 Index free_size = m_matrix.isCompressed()
139 ? Index(matrix.data().allocatedSize()) + block_size
140 : block_size;
141
142 bool update_trailing_pointers = false;
143 if(nnz>free_size)
144 {
145 // realloc manually to reduce copies
146 typename SparseMatrixType::Storage newdata(m_matrix.data().allocatedSize() - block_size + nnz);
147
148 internal::smart_copy(m_matrix.valuePtr(), m_matrix.valuePtr() + start, newdata.valuePtr());
149 internal::smart_copy(m_matrix.innerIndexPtr(), m_matrix.innerIndexPtr() + start, newdata.indexPtr());
150
151 internal::smart_copy(tmp.valuePtr(), tmp.valuePtr() + nnz, newdata.valuePtr() + start);
152 internal::smart_copy(tmp.innerIndexPtr(), tmp.innerIndexPtr() + nnz, newdata.indexPtr() + start);
153
154 internal::smart_copy(matrix.valuePtr()+end, matrix.valuePtr()+end + tail_size, newdata.valuePtr()+start+nnz);
155 internal::smart_copy(matrix.innerIndexPtr()+end, matrix.innerIndexPtr()+end + tail_size, newdata.indexPtr()+start+nnz);
156
157 newdata.resize(m_matrix.outerIndexPtr()[m_matrix.outerSize()] - block_size + nnz);
158
159 matrix.data().swap(newdata);
160
161 update_trailing_pointers = true;
162 }
163 else
164 {
165 if(m_matrix.isCompressed())
166 {
167 // no need to realloc, simply copy the tail at its respective position and insert tmp
168 matrix.data().resize(start + nnz + tail_size);
169
170 internal::smart_memmove(matrix.valuePtr()+end, matrix.valuePtr() + end+tail_size, matrix.valuePtr() + start+nnz);
171 internal::smart_memmove(matrix.innerIndexPtr()+end, matrix.innerIndexPtr() + end+tail_size, matrix.innerIndexPtr() + start+nnz);
172
173 update_trailing_pointers = true;
174 }
175
176 internal::smart_copy(tmp.valuePtr(), tmp.valuePtr() + nnz, matrix.valuePtr() + start);
177 internal::smart_copy(tmp.innerIndexPtr(), tmp.innerIndexPtr() + nnz, matrix.innerIndexPtr() + start);
178 }
179
180 // update outer index pointers and innerNonZeros
182 {
183 if(!m_matrix.isCompressed())
184 matrix.innerNonZeroPtr()[m_outerStart] = StorageIndex(nnz);
185 matrix.outerIndexPtr()[m_outerStart] = StorageIndex(start);
186 }
187 else
188 {
189 StorageIndex p = StorageIndex(start);
190 for(Index k=0; k<m_outerSize.value(); ++k)
191 {
192 StorageIndex nnz_k = internal::convert_index<StorageIndex>(tmp.innerVector(k).nonZeros());
193 if(!m_matrix.isCompressed())
194 matrix.innerNonZeroPtr()[m_outerStart+k] = nnz_k;
195 matrix.outerIndexPtr()[m_outerStart+k] = p;
196 p += nnz_k;
197 }
198 }
199
200 if(update_trailing_pointers)
201 {
202 StorageIndex offset = internal::convert_index<StorageIndex>(nnz - block_size);
203 for(Index k = m_outerStart + m_outerSize.value(); k<=matrix.outerSize(); ++k)
204 {
205 matrix.outerIndexPtr()[k] += offset;
206 }
207 }
208
209 return derived();
210 }
211
212 inline BlockType& operator=(const BlockType& other)
213 {
214 return operator=<BlockType>(other);
215 }
216
217 inline const Scalar* valuePtr() const
218 { return m_matrix.valuePtr(); }
219 inline Scalar* valuePtr()
220 { return m_matrix.valuePtr(); }
221
222 inline const StorageIndex* innerIndexPtr() const
223 { return m_matrix.innerIndexPtr(); }
224 inline StorageIndex* innerIndexPtr()
225 { return m_matrix.innerIndexPtr(); }
226
227 inline const StorageIndex* outerIndexPtr() const
228 { return m_matrix.outerIndexPtr() + m_outerStart; }
229 inline StorageIndex* outerIndexPtr()
230 { return m_matrix.outerIndexPtr() + m_outerStart; }
231
232 inline const StorageIndex* innerNonZeroPtr() const
233 { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr()+m_outerStart); }
234 inline StorageIndex* innerNonZeroPtr()
235 { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr()+m_outerStart); }
236
237 bool isCompressed() const { return m_matrix.innerNonZeroPtr()==0; }
238
239 inline Scalar& coeffRef(Index row, Index col)
240 {
241 return m_matrix.coeffRef(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
242 }
243
244 inline const Scalar coeff(Index row, Index col) const
245 {
246 return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
247 }
248
249 inline const Scalar coeff(Index index) const
250 {
251 return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
252 }
253
254 const Scalar& lastCoeff() const
255 {
256 EIGEN_STATIC_ASSERT_VECTOR_ONLY(sparse_matrix_block_impl);
257 eigen_assert(Base::nonZeros()>0);
258 if(m_matrix.isCompressed())
259 return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart+1]-1];
260 else
261 return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart]+m_matrix.innerNonZeroPtr()[m_outerStart]-1];
262 }
263
264 EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
265 EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
266
267 inline const SparseMatrixType& nestedExpression() const { return m_matrix; }
268 inline SparseMatrixType& nestedExpression() { return m_matrix; }
269 Index startRow() const { return IsRowMajor ? m_outerStart : 0; }
270 Index startCol() const { return IsRowMajor ? 0 : m_outerStart; }
271 Index blockRows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
272 Index blockCols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
273
274 protected:
275
276 typename internal::ref_selector<SparseMatrixType>::non_const_type m_matrix;
277 Index m_outerStart;
278 const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
279
280};
281
282} // namespace internal
283
284template<typename _Scalar, int _Options, typename _StorageIndex, int BlockRows, int BlockCols>
285class BlockImpl<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true,Sparse>
286 : public internal::sparse_matrix_block_impl<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols>
287{
288public:
289 typedef _StorageIndex StorageIndex;
290 typedef SparseMatrix<_Scalar, _Options, _StorageIndex> SparseMatrixType;
291 typedef internal::sparse_matrix_block_impl<SparseMatrixType,BlockRows,BlockCols> Base;
292 inline BlockImpl(SparseMatrixType& xpr, Index i)
293 : Base(xpr, i)
294 {}
295
296 inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
297 : Base(xpr, startRow, startCol, blockRows, blockCols)
298 {}
299
300 using Base::operator=;
301};
302
303template<typename _Scalar, int _Options, typename _StorageIndex, int BlockRows, int BlockCols>
304class BlockImpl<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true,Sparse>
305 : public internal::sparse_matrix_block_impl<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols>
306{
307public:
308 typedef _StorageIndex StorageIndex;
309 typedef const SparseMatrix<_Scalar, _Options, _StorageIndex> SparseMatrixType;
310 typedef internal::sparse_matrix_block_impl<SparseMatrixType,BlockRows,BlockCols> Base;
311 inline BlockImpl(SparseMatrixType& xpr, Index i)
312 : Base(xpr, i)
313 {}
314
315 inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
316 : Base(xpr, startRow, startCol, blockRows, blockCols)
317 {}
318
319 using Base::operator=;
320private:
321 template<typename Derived> BlockImpl(const SparseMatrixBase<Derived>& xpr, Index i);
322 template<typename Derived> BlockImpl(const SparseMatrixBase<Derived>& xpr);
323};
324
325//----------
326
330template<typename Derived>
332{ return InnerVectorReturnType(derived(), outer); }
333
337template<typename Derived>
339{ return ConstInnerVectorReturnType(derived(), outer); }
340
344template<typename Derived>
349 IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart,
350 IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize);
351
352}
357template<typename Derived>
360{
362 IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart,
363 IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize);
364
365}
366
370template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
371class BlockImpl<XprType,BlockRows,BlockCols,InnerPanel,Sparse>
372 : public SparseMatrixBase<Block<XprType,BlockRows,BlockCols,InnerPanel> >, internal::no_assignment_operator
373{
376 using Base::convert_index;
377public:
378 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
379 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
380
381 typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
382
385 inline BlockImpl(XprType& xpr, Index i)
386 : m_matrix(xpr),
387 m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? convert_index(i) : 0),
388 m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? convert_index(i) : 0),
389 m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
390 m_blockCols(BlockCols==1 ? 1 : xpr.cols())
391 {}
392
395 inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
396 : m_matrix(xpr), m_startRow(convert_index(startRow)), m_startCol(convert_index(startCol)), m_blockRows(convert_index(blockRows)), m_blockCols(convert_index(blockCols))
397 {}
398
399 inline Index rows() const { return m_blockRows.value(); }
400 inline Index cols() const { return m_blockCols.value(); }
401
402 inline Scalar& coeffRef(Index row, Index col)
403 {
404 return m_matrix.coeffRef(row + m_startRow.value(), col + m_startCol.value());
405 }
406
407 inline const Scalar coeff(Index row, Index col) const
408 {
409 return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value());
410 }
411
412 inline Scalar& coeffRef(Index index)
413 {
414 return m_matrix.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
415 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
416 }
417
418 inline const Scalar coeff(Index index) const
419 {
420 return m_matrix.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
421 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
422 }
423
424 inline const XprType& nestedExpression() const { return m_matrix; }
425 inline XprType& nestedExpression() { return m_matrix; }
426 Index startRow() const { return m_startRow.value(); }
427 Index startCol() const { return m_startCol.value(); }
428 Index blockRows() const { return m_blockRows.value(); }
429 Index blockCols() const { return m_blockCols.value(); }
430
431 protected:
432// friend class internal::GenericSparseBlockInnerIteratorImpl<XprType,BlockRows,BlockCols,InnerPanel>;
433 friend class ReverseInnerIterator;
434 friend struct internal::unary_evaluator<Block<XprType,BlockRows,BlockCols,InnerPanel>, internal::IteratorBased, Scalar >;
435
436 Index nonZeros() const { return Dynamic; }
437
438 typename internal::ref_selector<XprType>::non_const_type m_matrix;
439 const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
440 const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
441 const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows;
442 const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
443
444 protected:
445 // Disable assignment with clear error message.
446 // Note that simply removing operator= yields compilation errors with ICC+MSVC
447 template<typename T>
448 BlockImpl& operator=(const T&)
449 {
450 EIGEN_STATIC_ASSERT(sizeof(T)==0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY);
451 return *this;
452 }
453
454};
455
456namespace internal {
457
458template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
459struct unary_evaluator<Block<ArgType,BlockRows,BlockCols,InnerPanel>, IteratorBased >
460 : public evaluator_base<Block<ArgType,BlockRows,BlockCols,InnerPanel> >
461{
462 class InnerVectorInnerIterator;
463 class OuterVectorInnerIterator;
464 public:
465 typedef Block<ArgType,BlockRows,BlockCols,InnerPanel> XprType;
466 typedef typename XprType::StorageIndex StorageIndex;
467 typedef typename XprType::Scalar Scalar;
468
469 class ReverseInnerIterator;
470
471 enum {
472 IsRowMajor = XprType::IsRowMajor,
473
474 OuterVector = (BlockCols==1 && ArgType::IsRowMajor)
475 | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
476 // revert to || as soon as not needed anymore.
477 (BlockRows==1 && !ArgType::IsRowMajor),
478
479 CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
480 Flags = XprType::Flags
481 };
482
483 typedef typename internal::conditional<OuterVector,OuterVectorInnerIterator,InnerVectorInnerIterator>::type InnerIterator;
484
485 explicit unary_evaluator(const XprType& op)
486 : m_argImpl(op.nestedExpression()), m_block(op)
487 {}
488
489 inline Index nonZerosEstimate() const {
490 Index nnz = m_block.nonZeros();
491 if(nnz<0)
492 return m_argImpl.nonZerosEstimate() * m_block.size() / m_block.nestedExpression().size();
493 return nnz;
494 }
495
496 protected:
497 typedef typename evaluator<ArgType>::InnerIterator EvalIterator;
498
499 evaluator<ArgType> m_argImpl;
500 const XprType &m_block;
501};
502
503template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
504class unary_evaluator<Block<ArgType,BlockRows,BlockCols,InnerPanel>, IteratorBased>::InnerVectorInnerIterator
505 : public EvalIterator
506{
507 enum { IsRowMajor = unary_evaluator::IsRowMajor };
508 const XprType& m_block;
509 Index m_end;
510public:
511
512 EIGEN_STRONG_INLINE InnerVectorInnerIterator(const unary_evaluator& aEval, Index outer)
513 : EvalIterator(aEval.m_argImpl, outer + (IsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol())),
514 m_block(aEval.m_block),
515 m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows())
516 {
517 while( (EvalIterator::operator bool()) && (EvalIterator::index() < (IsRowMajor ? m_block.startCol() : m_block.startRow())) )
518 EvalIterator::operator++();
519 }
520
521 inline StorageIndex index() const { return EvalIterator::index() - convert_index<StorageIndex>(IsRowMajor ? m_block.startCol() : m_block.startRow()); }
522 inline Index outer() const { return EvalIterator::outer() - (IsRowMajor ? m_block.startRow() : m_block.startCol()); }
523 inline Index row() const { return EvalIterator::row() - m_block.startRow(); }
524 inline Index col() const { return EvalIterator::col() - m_block.startCol(); }
525
526 inline operator bool() const { return EvalIterator::operator bool() && EvalIterator::index() < m_end; }
527};
528
529template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
530class unary_evaluator<Block<ArgType,BlockRows,BlockCols,InnerPanel>, IteratorBased>::OuterVectorInnerIterator
531{
532 enum { IsRowMajor = unary_evaluator::IsRowMajor };
533 const unary_evaluator& m_eval;
534 Index m_outerPos;
535 Index m_innerIndex;
536 Scalar m_value;
537 Index m_end;
538public:
539
540 EIGEN_STRONG_INLINE OuterVectorInnerIterator(const unary_evaluator& aEval, Index outer)
541 : m_eval(aEval),
542 m_outerPos( (IsRowMajor ? aEval.m_block.startCol() : aEval.m_block.startRow()) - 1), // -1 so that operator++ finds the first non-zero entry
543 m_innerIndex(IsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol()),
544 m_value(0),
545 m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows())
546 {
547 EIGEN_UNUSED_VARIABLE(outer);
548 eigen_assert(outer==0);
549
550 ++(*this);
551 }
552
553 inline StorageIndex index() const { return convert_index<StorageIndex>(m_outerPos - (IsRowMajor ? m_eval.m_block.startCol() : m_eval.m_block.startRow())); }
554 inline Index outer() const { return 0; }
555 inline Index row() const { return IsRowMajor ? 0 : index(); }
556 inline Index col() const { return IsRowMajor ? index() : 0; }
557
558 inline Scalar value() const { return m_value; }
559
560 inline OuterVectorInnerIterator& operator++()
561 {
562 // search next non-zero entry
563 while(++m_outerPos<m_end)
564 {
565 EvalIterator it(m_eval.m_argImpl, m_outerPos);
566 // search for the key m_innerIndex in the current outer-vector
567 while(it && it.index() < m_innerIndex) ++it;
568 if(it && it.index()==m_innerIndex)
569 {
570 m_value = it.value();
571 break;
572 }
573 }
574 return *this;
575 }
576
577 inline operator bool() const { return m_outerPos < m_end; }
578};
579
580template<typename _Scalar, int _Options, typename _StorageIndex, int BlockRows, int BlockCols>
581struct unary_evaluator<Block<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true>, IteratorBased>
582 : evaluator<SparseCompressedBase<Block<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true> > >
583{
584 typedef Block<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true> XprType;
585 typedef evaluator<SparseCompressedBase<XprType> > Base;
586 explicit unary_evaluator(const XprType &xpr) : Base(xpr) {}
587};
588
589template<typename _Scalar, int _Options, typename _StorageIndex, int BlockRows, int BlockCols>
590struct unary_evaluator<Block<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true>, IteratorBased>
591 : evaluator<SparseCompressedBase<Block<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true> > >
592{
593 typedef Block<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true> XprType;
594 typedef evaluator<SparseCompressedBase<XprType> > Base;
595 explicit unary_evaluator(const XprType &xpr) : Base(xpr) {}
596};
597
598} // end namespace internal
599
600
601} // end namespace Eigen
602
603#endif // EIGEN_SPARSE_BLOCK_H
BlockImpl(XprType &xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
Definition: SparseBlock.h:395
BlockImpl(XprType &xpr, Index i)
Definition: SparseBlock.h:385
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:105
const StorageIndex * innerIndexPtr() const
Definition: SparseCompressedBase.h:80
const Scalar * valuePtr() const
Definition: SparseCompressedBase.h:71
const StorageIndex * outerIndexPtr() const
Definition: SparseCompressedBase.h:90
const StorageIndex * innerNonZeroPtr() const
Definition: SparseCompressedBase.h:100
Base class of any sparse matrices or sparse expressions.
Definition: SparseMatrixBase.h:28
Index rows() const
Definition: SparseMatrixBase.h:167
@ IsVectorAtCompileTime
Definition: SparseMatrixBase.h:80
Index cols() const
Definition: SparseMatrixBase.h:169
Namespace containing all symbols from the Eigen library.
Definition: Core:287
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:33
const int Dynamic
Definition: Constants.h:21
Eigen::Index Index
The interface type of indices.
Definition: EigenBase.h:37
Derived & derived()
Definition: EigenBase.h:44
Definition: Constants.h:494