Please, help us to better know about our user community by answering the following short survey: https://forms.gle/wpyrxWi18ox9Z5ae9
Eigen  3.4.0
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 
13 namespace Eigen {
14 
15 // Subset of columns or rows
16 template<typename XprType, int BlockRows, int BlockCols>
17 class 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;
22 public:
23  enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
24 protected:
25  enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
26  typedef SparseMatrixBase<BlockType> Base;
27  using Base::convert_index;
28 public:
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 
93 namespace internal {
94 
95 template<typename SparseMatrixType, int BlockRows, int BlockCols>
96 class 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;
103 public:
104  enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
105  EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
106 protected:
107  typedef typename Base::IndexVector IndexVector;
108  enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
109 public:
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 : m_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  Index tmp_start = tmp.outerIndexPtr()[0];
143 
144  bool update_trailing_pointers = false;
145  if(nnz>free_size)
146  {
147  // realloc manually to reduce copies
148  typename SparseMatrixType::Storage newdata(m_matrix.data().allocatedSize() - block_size + nnz);
149 
150  internal::smart_copy(m_matrix.valuePtr(), m_matrix.valuePtr() + start, newdata.valuePtr());
151  internal::smart_copy(m_matrix.innerIndexPtr(), m_matrix.innerIndexPtr() + start, newdata.indexPtr());
152 
153  internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, newdata.valuePtr() + start);
154  internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz, newdata.indexPtr() + start);
155 
156  internal::smart_copy(matrix.valuePtr()+end, matrix.valuePtr()+end + tail_size, newdata.valuePtr()+start+nnz);
157  internal::smart_copy(matrix.innerIndexPtr()+end, matrix.innerIndexPtr()+end + tail_size, newdata.indexPtr()+start+nnz);
158 
159  newdata.resize(m_matrix.outerIndexPtr()[m_matrix.outerSize()] - block_size + nnz);
160 
161  matrix.data().swap(newdata);
162 
163  update_trailing_pointers = true;
164  }
165  else
166  {
167  if(m_matrix.isCompressed() && nnz!=block_size)
168  {
169  // no need to realloc, simply copy the tail at its respective position and insert tmp
170  matrix.data().resize(start + nnz + tail_size);
171 
172  internal::smart_memmove(matrix.valuePtr()+end, matrix.valuePtr() + end+tail_size, matrix.valuePtr() + start+nnz);
173  internal::smart_memmove(matrix.innerIndexPtr()+end, matrix.innerIndexPtr() + end+tail_size, matrix.innerIndexPtr() + start+nnz);
174 
175  update_trailing_pointers = true;
176  }
177 
178  internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, matrix.valuePtr() + start);
179  internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz, matrix.innerIndexPtr() + start);
180  }
181 
182  // update outer index pointers and innerNonZeros
183  if(IsVectorAtCompileTime)
184  {
185  if(!m_matrix.isCompressed())
186  matrix.innerNonZeroPtr()[m_outerStart] = StorageIndex(nnz);
187  matrix.outerIndexPtr()[m_outerStart] = StorageIndex(start);
188  }
189  else
190  {
191  StorageIndex p = StorageIndex(start);
192  for(Index k=0; k<m_outerSize.value(); ++k)
193  {
194  StorageIndex nnz_k = internal::convert_index<StorageIndex>(tmp.innerVector(k).nonZeros());
195  if(!m_matrix.isCompressed())
196  matrix.innerNonZeroPtr()[m_outerStart+k] = nnz_k;
197  matrix.outerIndexPtr()[m_outerStart+k] = p;
198  p += nnz_k;
199  }
200  }
201 
202  if(update_trailing_pointers)
203  {
204  StorageIndex offset = internal::convert_index<StorageIndex>(nnz - block_size);
205  for(Index k = m_outerStart + m_outerSize.value(); k<=matrix.outerSize(); ++k)
206  {
207  matrix.outerIndexPtr()[k] += offset;
208  }
209  }
210 
211  return derived();
212  }
213 
214  inline BlockType& operator=(const BlockType& other)
215  {
216  return operator=<BlockType>(other);
217  }
218 
219  inline const Scalar* valuePtr() const
220  { return m_matrix.valuePtr(); }
221  inline Scalar* valuePtr()
222  { return m_matrix.valuePtr(); }
223 
224  inline const StorageIndex* innerIndexPtr() const
225  { return m_matrix.innerIndexPtr(); }
226  inline StorageIndex* innerIndexPtr()
227  { return m_matrix.innerIndexPtr(); }
228 
229  inline const StorageIndex* outerIndexPtr() const
230  { return m_matrix.outerIndexPtr() + m_outerStart; }
231  inline StorageIndex* outerIndexPtr()
232  { return m_matrix.outerIndexPtr() + m_outerStart; }
233 
234  inline const StorageIndex* innerNonZeroPtr() const
235  { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr()+m_outerStart); }
236  inline StorageIndex* innerNonZeroPtr()
237  { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr()+m_outerStart); }
238 
239  bool isCompressed() const { return m_matrix.innerNonZeroPtr()==0; }
240 
241  inline Scalar& coeffRef(Index row, Index col)
242  {
243  return m_matrix.coeffRef(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
244  }
245 
246  inline const Scalar coeff(Index row, Index col) const
247  {
248  return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
249  }
250 
251  inline const Scalar coeff(Index index) const
252  {
253  return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
254  }
255 
256  const Scalar& lastCoeff() const
257  {
258  EIGEN_STATIC_ASSERT_VECTOR_ONLY(sparse_matrix_block_impl);
259  eigen_assert(Base::nonZeros()>0);
260  if(m_matrix.isCompressed())
261  return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart+1]-1];
262  else
263  return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart]+m_matrix.innerNonZeroPtr()[m_outerStart]-1];
264  }
265 
266  EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
267  EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
268 
269  inline const SparseMatrixType& nestedExpression() const { return m_matrix; }
270  inline SparseMatrixType& nestedExpression() { return m_matrix; }
271  Index startRow() const { return IsRowMajor ? m_outerStart : 0; }
272  Index startCol() const { return IsRowMajor ? 0 : m_outerStart; }
273  Index blockRows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
274  Index blockCols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
275 
276  protected:
277 
278  typename internal::ref_selector<SparseMatrixType>::non_const_type m_matrix;
279  Index m_outerStart;
280  const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
281 
282 };
283 
284 } // namespace internal
285 
286 template<typename _Scalar, int _Options, typename _StorageIndex, int BlockRows, int BlockCols>
287 class BlockImpl<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true,Sparse>
288  : public internal::sparse_matrix_block_impl<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols>
289 {
290 public:
291  typedef _StorageIndex StorageIndex;
292  typedef SparseMatrix<_Scalar, _Options, _StorageIndex> SparseMatrixType;
293  typedef internal::sparse_matrix_block_impl<SparseMatrixType,BlockRows,BlockCols> Base;
294  inline BlockImpl(SparseMatrixType& xpr, Index i)
295  : Base(xpr, i)
296  {}
297 
298  inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
299  : Base(xpr, startRow, startCol, blockRows, blockCols)
300  {}
301 
302  using Base::operator=;
303 };
304 
305 template<typename _Scalar, int _Options, typename _StorageIndex, int BlockRows, int BlockCols>
306 class BlockImpl<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true,Sparse>
307  : public internal::sparse_matrix_block_impl<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols>
308 {
309 public:
310  typedef _StorageIndex StorageIndex;
311  typedef const SparseMatrix<_Scalar, _Options, _StorageIndex> SparseMatrixType;
312  typedef internal::sparse_matrix_block_impl<SparseMatrixType,BlockRows,BlockCols> Base;
313  inline BlockImpl(SparseMatrixType& xpr, Index i)
314  : Base(xpr, i)
315  {}
316 
317  inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
318  : Base(xpr, startRow, startCol, blockRows, blockCols)
319  {}
320 
321  using Base::operator=;
322 private:
323  template<typename Derived> BlockImpl(const SparseMatrixBase<Derived>& xpr, Index i);
324  template<typename Derived> BlockImpl(const SparseMatrixBase<Derived>& xpr);
325 };
326 
327 //----------
328 
332 template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
333 class BlockImpl<XprType,BlockRows,BlockCols,InnerPanel,Sparse>
334  : public SparseMatrixBase<Block<XprType,BlockRows,BlockCols,InnerPanel> >, internal::no_assignment_operator
335 {
337  typedef SparseMatrixBase<BlockType> Base;
338  using Base::convert_index;
339 public:
340  enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
341  EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
342 
343  typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested;
344 
347  inline BlockImpl(XprType& xpr, Index i)
348  : m_matrix(xpr),
349  m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? convert_index(i) : 0),
350  m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? convert_index(i) : 0),
351  m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
352  m_blockCols(BlockCols==1 ? 1 : xpr.cols())
353  {}
354 
357  inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
358  : m_matrix(xpr), m_startRow(convert_index(startRow)), m_startCol(convert_index(startCol)), m_blockRows(convert_index(blockRows)), m_blockCols(convert_index(blockCols))
359  {}
360 
361  inline Index rows() const { return m_blockRows.value(); }
362  inline Index cols() const { return m_blockCols.value(); }
363 
364  inline Scalar& coeffRef(Index row, Index col)
365  {
366  return m_matrix.coeffRef(row + m_startRow.value(), col + m_startCol.value());
367  }
368 
369  inline const Scalar coeff(Index row, Index col) const
370  {
371  return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value());
372  }
373 
374  inline Scalar& coeffRef(Index index)
375  {
376  return m_matrix.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
377  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
378  }
379 
380  inline const Scalar coeff(Index index) const
381  {
382  return m_matrix.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
383  m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
384  }
385 
386  inline const XprType& nestedExpression() const { return m_matrix; }
387  inline XprType& nestedExpression() { return m_matrix; }
388  Index startRow() const { return m_startRow.value(); }
389  Index startCol() const { return m_startCol.value(); }
390  Index blockRows() const { return m_blockRows.value(); }
391  Index blockCols() const { return m_blockCols.value(); }
392 
393  protected:
394 // friend class internal::GenericSparseBlockInnerIteratorImpl<XprType,BlockRows,BlockCols,InnerPanel>;
395  friend struct internal::unary_evaluator<Block<XprType,BlockRows,BlockCols,InnerPanel>, internal::IteratorBased, Scalar >;
396 
397  Index nonZeros() const { return Dynamic; }
398 
399  typename internal::ref_selector<XprType>::non_const_type m_matrix;
400  const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
401  const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
402  const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows;
403  const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
404 
405  protected:
406  // Disable assignment with clear error message.
407  // Note that simply removing operator= yields compilation errors with ICC+MSVC
408  template<typename T>
409  BlockImpl& operator=(const T&)
410  {
411  EIGEN_STATIC_ASSERT(sizeof(T)==0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY);
412  return *this;
413  }
414 
415 };
416 
417 namespace internal {
418 
419 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
420 struct unary_evaluator<Block<ArgType,BlockRows,BlockCols,InnerPanel>, IteratorBased >
421  : public evaluator_base<Block<ArgType,BlockRows,BlockCols,InnerPanel> >
422 {
423  class InnerVectorInnerIterator;
424  class OuterVectorInnerIterator;
425  public:
427  typedef typename XprType::StorageIndex StorageIndex;
428  typedef typename XprType::Scalar Scalar;
429 
430  enum {
431  IsRowMajor = XprType::IsRowMajor,
432 
433  OuterVector = (BlockCols==1 && ArgType::IsRowMajor)
434  | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
435  // revert to || as soon as not needed anymore.
436  (BlockRows==1 && !ArgType::IsRowMajor),
437 
438  CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
439  Flags = XprType::Flags
440  };
441 
442  typedef typename internal::conditional<OuterVector,OuterVectorInnerIterator,InnerVectorInnerIterator>::type InnerIterator;
443 
444  explicit unary_evaluator(const XprType& op)
445  : m_argImpl(op.nestedExpression()), m_block(op)
446  {}
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  typedef typename evaluator<ArgType>::InnerIterator EvalIterator;
461 
462  evaluator<ArgType> m_argImpl;
463  const XprType &m_block;
464 };
465 
466 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
467 class unary_evaluator<Block<ArgType,BlockRows,BlockCols,InnerPanel>, IteratorBased>::InnerVectorInnerIterator
468  : public EvalIterator
469 {
470  // NOTE MSVC fails to compile if we don't explicitely "import" IsRowMajor from unary_evaluator
471  // because the base class EvalIterator has a private IsRowMajor enum too. (bug #1786)
472  // NOTE We cannot call it IsRowMajor because it would shadow unary_evaluator::IsRowMajor
473  enum { XprIsRowMajor = unary_evaluator::IsRowMajor };
474  const XprType& m_block;
475  Index m_end;
476 public:
477 
478  EIGEN_STRONG_INLINE InnerVectorInnerIterator(const unary_evaluator& aEval, Index outer)
479  : EvalIterator(aEval.m_argImpl, outer + (XprIsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol())),
480  m_block(aEval.m_block),
481  m_end(XprIsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows())
482  {
483  while( (EvalIterator::operator bool()) && (EvalIterator::index() < (XprIsRowMajor ? m_block.startCol() : m_block.startRow())) )
484  EvalIterator::operator++();
485  }
486 
487  inline StorageIndex index() const { return EvalIterator::index() - convert_index<StorageIndex>(XprIsRowMajor ? m_block.startCol() : m_block.startRow()); }
488  inline Index outer() const { return EvalIterator::outer() - (XprIsRowMajor ? m_block.startRow() : m_block.startCol()); }
489  inline Index row() const { return EvalIterator::row() - m_block.startRow(); }
490  inline Index col() const { return EvalIterator::col() - m_block.startCol(); }
491 
492  inline operator bool() const { return EvalIterator::operator bool() && EvalIterator::index() < m_end; }
493 };
494 
495 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
496 class unary_evaluator<Block<ArgType,BlockRows,BlockCols,InnerPanel>, IteratorBased>::OuterVectorInnerIterator
497 {
498  // NOTE see above
499  enum { XprIsRowMajor = unary_evaluator::IsRowMajor };
500  const unary_evaluator& m_eval;
501  Index m_outerPos;
502  const Index m_innerIndex;
503  Index m_end;
504  EvalIterator m_it;
505 public:
506 
507  EIGEN_STRONG_INLINE OuterVectorInnerIterator(const unary_evaluator& aEval, Index outer)
508  : m_eval(aEval),
509  m_outerPos( (XprIsRowMajor ? aEval.m_block.startCol() : aEval.m_block.startRow()) ),
510  m_innerIndex(XprIsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol()),
511  m_end(XprIsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows()),
512  m_it(m_eval.m_argImpl, m_outerPos)
513  {
514  EIGEN_UNUSED_VARIABLE(outer);
515  eigen_assert(outer==0);
516 
517  while(m_it && m_it.index() < m_innerIndex) ++m_it;
518  if((!m_it) || (m_it.index()!=m_innerIndex))
519  ++(*this);
520  }
521 
522  inline StorageIndex index() const { return convert_index<StorageIndex>(m_outerPos - (XprIsRowMajor ? m_eval.m_block.startCol() : m_eval.m_block.startRow())); }
523  inline Index outer() const { return 0; }
524  inline Index row() const { return XprIsRowMajor ? 0 : index(); }
525  inline Index col() const { return XprIsRowMajor ? index() : 0; }
526 
527  inline Scalar value() const { return m_it.value(); }
528  inline Scalar& valueRef() { return m_it.valueRef(); }
529 
530  inline OuterVectorInnerIterator& operator++()
531  {
532  // search next non-zero entry
533  while(++m_outerPos<m_end)
534  {
535  // Restart iterator at the next inner-vector:
536  m_it.~EvalIterator();
537  ::new (&m_it) EvalIterator(m_eval.m_argImpl, m_outerPos);
538  // search for the key m_innerIndex in the current outer-vector
539  while(m_it && m_it.index() < m_innerIndex) ++m_it;
540  if(m_it && m_it.index()==m_innerIndex) break;
541  }
542  return *this;
543  }
544 
545  inline operator bool() const { return m_outerPos < m_end; }
546 };
547 
548 template<typename _Scalar, int _Options, typename _StorageIndex, int BlockRows, int BlockCols>
549 struct unary_evaluator<Block<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true>, IteratorBased>
550  : evaluator<SparseCompressedBase<Block<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true> > >
551 {
552  typedef Block<SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true> XprType;
553  typedef evaluator<SparseCompressedBase<XprType> > Base;
554  explicit unary_evaluator(const XprType &xpr) : Base(xpr) {}
555 };
556 
557 template<typename _Scalar, int _Options, typename _StorageIndex, int BlockRows, int BlockCols>
558 struct unary_evaluator<Block<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true>, IteratorBased>
559  : evaluator<SparseCompressedBase<Block<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true> > >
560 {
561  typedef Block<const SparseMatrix<_Scalar, _Options, _StorageIndex>,BlockRows,BlockCols,true> XprType;
562  typedef evaluator<SparseCompressedBase<XprType> > Base;
563  explicit unary_evaluator(const XprType &xpr) : Base(xpr) {}
564 };
565 
566 } // end namespace internal
567 
568 
569 } // end namespace Eigen
570 
571 #endif // EIGEN_SPARSE_BLOCK_H
Namespace containing all symbols from the Eigen library.
Definition: Core:141
BlockImpl(XprType &xpr, Index i)
Definition: SparseBlock.h:347
BlockImpl(XprType &xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
Definition: SparseBlock.h:357
internal::traits< Block< XprType, BlockRows, BlockCols, InnerPanel > >::StorageIndex StorageIndex
Definition: SparseMatrixBase.h:43
Base class of any sparse matrices or sparse expressions.
Definition: SparseMatrixBase.h:26
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:74
Definition: Constants.h:510
Definition: Eigen_Colamd.h:50
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:103
const int Dynamic
Definition: Constants.h:22