1// This file is part of Eigen, a lightweight C++ template library 2// for linear algebra. 3// 4// Copyright (C) 2008-2009 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 15template<typename XprType, int BlockRows, int BlockCols> 16class BlockImpl<XprType,BlockRows,BlockCols,true,Sparse> 17 : public SparseMatrixBase<Block<XprType,BlockRows,BlockCols,true> > 18{ 19 typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested; 20 typedef Block<XprType, BlockRows, BlockCols, true> BlockType; 21public: 22 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor }; 23protected: 24 enum { OuterSize = IsRowMajor ? BlockRows : BlockCols }; 25public: 26 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) 27 28 class InnerIterator: public XprType::InnerIterator 29 { 30 typedef typename BlockImpl::Index Index; 31 public: 32 inline InnerIterator(const BlockType& xpr, Index outer) 33 : XprType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) 34 {} 35 inline Index row() const { return IsRowMajor ? m_outer : this->index(); } 36 inline Index col() const { return IsRowMajor ? this->index() : m_outer; } 37 protected: 38 Index m_outer; 39 }; 40 class ReverseInnerIterator: public XprType::ReverseInnerIterator 41 { 42 typedef typename BlockImpl::Index Index; 43 public: 44 inline ReverseInnerIterator(const BlockType& xpr, Index outer) 45 : XprType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) 46 {} 47 inline Index row() const { return IsRowMajor ? m_outer : this->index(); } 48 inline Index col() const { return IsRowMajor ? this->index() : m_outer; } 49 protected: 50 Index m_outer; 51 }; 52 53 inline BlockImpl(const XprType& xpr, int i) 54 : m_matrix(xpr), m_outerStart(i), m_outerSize(OuterSize) 55 {} 56 57 inline BlockImpl(const XprType& xpr, int startRow, int startCol, int blockRows, int blockCols) 58 : m_matrix(xpr), m_outerStart(IsRowMajor ? startRow : startCol), m_outerSize(IsRowMajor ? blockRows : blockCols) 59 {} 60 61 inline const Scalar coeff(int row, int col) const 62 { 63 return m_matrix.coeff(row + IsRowMajor ? m_outerStart : 0, col +IsRowMajor ? 0 : m_outerStart); 64 } 65 66 inline const Scalar coeff(int index) const 67 { 68 return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart); 69 } 70 71 EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } 72 EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } 73 74 protected: 75 76 typename XprType::Nested m_matrix; 77 Index m_outerStart; 78 const internal::variable_if_dynamic<Index, OuterSize> m_outerSize; 79 80 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl) 81 private: 82 Index nonZeros() const; 83}; 84 85 86/*************************************************************************** 87* specialisation for SparseMatrix 88***************************************************************************/ 89 90template<typename _Scalar, int _Options, typename _Index, int BlockRows, int BlockCols> 91class BlockImpl<SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true,Sparse> 92 : public SparseMatrixBase<Block<SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true> > 93{ 94 typedef SparseMatrix<_Scalar, _Options, _Index> SparseMatrixType; 95 typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _MatrixTypeNested; 96 typedef Block<SparseMatrixType, BlockRows, BlockCols, true> BlockType; 97 typedef Block<const SparseMatrixType, BlockRows, BlockCols, true> ConstBlockType; 98public: 99 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor }; 100 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) 101protected: 102 enum { OuterSize = IsRowMajor ? BlockRows : BlockCols }; 103public: 104 105 class InnerIterator: public SparseMatrixType::InnerIterator 106 { 107 public: 108 inline InnerIterator(const BlockType& xpr, Index outer) 109 : SparseMatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) 110 {} 111 inline Index row() const { return IsRowMajor ? m_outer : this->index(); } 112 inline Index col() const { return IsRowMajor ? this->index() : m_outer; } 113 protected: 114 Index m_outer; 115 }; 116 class ReverseInnerIterator: public SparseMatrixType::ReverseInnerIterator 117 { 118 public: 119 inline ReverseInnerIterator(const BlockType& xpr, Index outer) 120 : SparseMatrixType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) 121 {} 122 inline Index row() const { return IsRowMajor ? m_outer : this->index(); } 123 inline Index col() const { return IsRowMajor ? this->index() : m_outer; } 124 protected: 125 Index m_outer; 126 }; 127 128 inline BlockImpl(const SparseMatrixType& xpr, int i) 129 : m_matrix(xpr), m_outerStart(i), m_outerSize(OuterSize) 130 {} 131 132 inline BlockImpl(const SparseMatrixType& xpr, int startRow, int startCol, int blockRows, int blockCols) 133 : m_matrix(xpr), m_outerStart(IsRowMajor ? startRow : startCol), m_outerSize(IsRowMajor ? blockRows : blockCols) 134 {} 135 136 template<typename OtherDerived> 137 inline BlockType& operator=(const SparseMatrixBase<OtherDerived>& other) 138 { 139 typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _NestedMatrixType; 140 _NestedMatrixType& matrix = const_cast<_NestedMatrixType&>(m_matrix);; 141 // This assignement is slow if this vector set is not empty 142 // and/or it is not at the end of the nonzeros of the underlying matrix. 143 144 // 1 - eval to a temporary to avoid transposition and/or aliasing issues 145 SparseMatrix<Scalar, IsRowMajor ? RowMajor : ColMajor, Index> tmp(other); 146 147 // 2 - let's check whether there is enough allocated memory 148 Index nnz = tmp.nonZeros(); 149 Index start = m_outerStart==0 ? 0 : matrix.outerIndexPtr()[m_outerStart]; // starting position of the current block 150 Index end = m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()]; // ending posiiton of the current block 151 Index block_size = end - start; // available room in the current block 152 Index tail_size = m_matrix.outerIndexPtr()[m_matrix.outerSize()] - end; 153 154 Index free_size = m_matrix.isCompressed() 155 ? Index(matrix.data().allocatedSize()) + block_size 156 : block_size; 157 158 if(nnz>free_size) 159 { 160 // realloc manually to reduce copies 161 typename SparseMatrixType::Storage newdata(m_matrix.data().allocatedSize() - block_size + nnz); 162 163 std::memcpy(&newdata.value(0), &m_matrix.data().value(0), start*sizeof(Scalar)); 164 std::memcpy(&newdata.index(0), &m_matrix.data().index(0), start*sizeof(Index)); 165 166 std::memcpy(&newdata.value(start), &tmp.data().value(0), nnz*sizeof(Scalar)); 167 std::memcpy(&newdata.index(start), &tmp.data().index(0), nnz*sizeof(Index)); 168 169 std::memcpy(&newdata.value(start+nnz), &matrix.data().value(end), tail_size*sizeof(Scalar)); 170 std::memcpy(&newdata.index(start+nnz), &matrix.data().index(end), tail_size*sizeof(Index)); 171 172 newdata.resize(m_matrix.outerIndexPtr()[m_matrix.outerSize()] - block_size + nnz); 173 174 matrix.data().swap(newdata); 175 } 176 else 177 { 178 // no need to realloc, simply copy the tail at its respective position and insert tmp 179 matrix.data().resize(start + nnz + tail_size); 180 181 std::memmove(&matrix.data().value(start+nnz), &matrix.data().value(end), tail_size*sizeof(Scalar)); 182 std::memmove(&matrix.data().index(start+nnz), &matrix.data().index(end), tail_size*sizeof(Index)); 183 184 std::memcpy(&matrix.data().value(start), &tmp.data().value(0), nnz*sizeof(Scalar)); 185 std::memcpy(&matrix.data().index(start), &tmp.data().index(0), nnz*sizeof(Index)); 186 } 187 188 // update innerNonZeros 189 if(!m_matrix.isCompressed()) 190 for(Index j=0; j<m_outerSize.value(); ++j) 191 matrix.innerNonZeroPtr()[m_outerStart+j] = tmp.innerVector(j).nonZeros(); 192 193 // update outer index pointers 194 Index p = start; 195 for(Index k=0; k<m_outerSize.value(); ++k) 196 { 197 matrix.outerIndexPtr()[m_outerStart+k] = p; 198 p += tmp.innerVector(k).nonZeros(); 199 } 200 std::ptrdiff_t offset = nnz - block_size; 201 for(Index k = m_outerStart + m_outerSize.value(); k<=matrix.outerSize(); ++k) 202 { 203 matrix.outerIndexPtr()[k] += offset; 204 } 205 206 return derived(); 207 } 208 209 inline BlockType& operator=(const BlockType& other) 210 { 211 return operator=<BlockType>(other); 212 } 213 214 inline const Scalar* valuePtr() const 215 { return m_matrix.valuePtr() + m_matrix.outerIndexPtr()[m_outerStart]; } 216 inline Scalar* valuePtr() 217 { return m_matrix.const_cast_derived().valuePtr() + m_matrix.outerIndexPtr()[m_outerStart]; } 218 219 inline const Index* innerIndexPtr() const 220 { return m_matrix.innerIndexPtr() + m_matrix.outerIndexPtr()[m_outerStart]; } 221 inline Index* innerIndexPtr() 222 { return m_matrix.const_cast_derived().innerIndexPtr() + m_matrix.outerIndexPtr()[m_outerStart]; } 223 224 inline const Index* outerIndexPtr() const 225 { return m_matrix.outerIndexPtr() + m_outerStart; } 226 inline Index* outerIndexPtr() 227 { return m_matrix.const_cast_derived().outerIndexPtr() + m_outerStart; } 228 229 Index nonZeros() const 230 { 231 if(m_matrix.isCompressed()) 232 return std::size_t(m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()]) 233 - std::size_t(m_matrix.outerIndexPtr()[m_outerStart]); 234 else if(m_outerSize.value()==0) 235 return 0; 236 else 237 return Map<const Matrix<Index,OuterSize,1> >(m_matrix.innerNonZeroPtr()+m_outerStart, m_outerSize.value()).sum(); 238 } 239 240 inline Scalar& coeffRef(int row, int col) 241 { 242 return m_matrix.const_cast_derived().coeffRef(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart)); 243 } 244 245 inline const Scalar coeff(int row, int col) const 246 { 247 return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart)); 248 } 249 250 inline const Scalar coeff(int index) const 251 { 252 return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart); 253 } 254 255 const Scalar& lastCoeff() const 256 { 257 EIGEN_STATIC_ASSERT_VECTOR_ONLY(BlockImpl); 258 eigen_assert(nonZeros()>0); 259 if(m_matrix.isCompressed()) 260 return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart+1]-1]; 261 else 262 return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart]+m_matrix.innerNonZeroPtr()[m_outerStart]-1]; 263 } 264 265 EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } 266 EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } 267 268 protected: 269 270 typename SparseMatrixType::Nested m_matrix; 271 Index m_outerStart; 272 const internal::variable_if_dynamic<Index, OuterSize> m_outerSize; 273 274}; 275 276 277template<typename _Scalar, int _Options, typename _Index, int BlockRows, int BlockCols> 278class BlockImpl<const SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true,Sparse> 279 : public SparseMatrixBase<Block<const SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true> > 280{ 281 typedef SparseMatrix<_Scalar, _Options, _Index> SparseMatrixType; 282 typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _MatrixTypeNested; 283 typedef Block<const SparseMatrixType, BlockRows, BlockCols, true> BlockType; 284public: 285 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor }; 286 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) 287protected: 288 enum { OuterSize = IsRowMajor ? BlockRows : BlockCols }; 289public: 290 291 class InnerIterator: public SparseMatrixType::InnerIterator 292 { 293 public: 294 inline InnerIterator(const BlockType& xpr, Index outer) 295 : SparseMatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) 296 {} 297 inline Index row() const { return IsRowMajor ? m_outer : this->index(); } 298 inline Index col() const { return IsRowMajor ? this->index() : m_outer; } 299 protected: 300 Index m_outer; 301 }; 302 class ReverseInnerIterator: public SparseMatrixType::ReverseInnerIterator 303 { 304 public: 305 inline ReverseInnerIterator(const BlockType& xpr, Index outer) 306 : SparseMatrixType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) 307 {} 308 inline Index row() const { return IsRowMajor ? m_outer : this->index(); } 309 inline Index col() const { return IsRowMajor ? this->index() : m_outer; } 310 protected: 311 Index m_outer; 312 }; 313 314 inline BlockImpl(const SparseMatrixType& xpr, int i) 315 : m_matrix(xpr), m_outerStart(i), m_outerSize(OuterSize) 316 {} 317 318 inline BlockImpl(const SparseMatrixType& xpr, int startRow, int startCol, int blockRows, int blockCols) 319 : m_matrix(xpr), m_outerStart(IsRowMajor ? startRow : startCol), m_outerSize(IsRowMajor ? blockRows : blockCols) 320 {} 321 322 inline const Scalar* valuePtr() const 323 { return m_matrix.valuePtr() + m_matrix.outerIndexPtr()[m_outerStart]; } 324 325 inline const Index* innerIndexPtr() const 326 { return m_matrix.innerIndexPtr() + m_matrix.outerIndexPtr()[m_outerStart]; } 327 328 inline const Index* outerIndexPtr() const 329 { return m_matrix.outerIndexPtr() + m_outerStart; } 330 331 Index nonZeros() const 332 { 333 if(m_matrix.isCompressed()) 334 return std::size_t(m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()]) 335 - std::size_t(m_matrix.outerIndexPtr()[m_outerStart]); 336 else if(m_outerSize.value()==0) 337 return 0; 338 else 339 return Map<const Matrix<Index,OuterSize,1> >(m_matrix.innerNonZeroPtr()+m_outerStart, m_outerSize.value()).sum(); 340 } 341 342 inline const Scalar coeff(int row, int col) const 343 { 344 return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart)); 345 } 346 347 inline const Scalar coeff(int index) const 348 { 349 return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart); 350 } 351 352 const Scalar& lastCoeff() const 353 { 354 EIGEN_STATIC_ASSERT_VECTOR_ONLY(BlockImpl); 355 eigen_assert(nonZeros()>0); 356 if(m_matrix.isCompressed()) 357 return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart+1]-1]; 358 else 359 return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart]+m_matrix.innerNonZeroPtr()[m_outerStart]-1]; 360 } 361 362 EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } 363 EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } 364 365 protected: 366 367 typename SparseMatrixType::Nested m_matrix; 368 Index m_outerStart; 369 const internal::variable_if_dynamic<Index, OuterSize> m_outerSize; 370 371}; 372 373//---------- 374 375/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this 376 * is col-major (resp. row-major). 377 */ 378template<typename Derived> 379typename SparseMatrixBase<Derived>::InnerVectorReturnType SparseMatrixBase<Derived>::innerVector(Index outer) 380{ return InnerVectorReturnType(derived(), outer); } 381 382/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this 383 * is col-major (resp. row-major). Read-only. 384 */ 385template<typename Derived> 386const typename SparseMatrixBase<Derived>::ConstInnerVectorReturnType SparseMatrixBase<Derived>::innerVector(Index outer) const 387{ return ConstInnerVectorReturnType(derived(), outer); } 388 389/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this 390 * is col-major (resp. row-major). 391 */ 392template<typename Derived> 393typename SparseMatrixBase<Derived>::InnerVectorsReturnType 394SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize) 395{ 396 return Block<Derived,Dynamic,Dynamic,true>(derived(), 397 IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart, 398 IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); 399 400} 401 402/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this 403 * is col-major (resp. row-major). Read-only. 404 */ 405template<typename Derived> 406const typename SparseMatrixBase<Derived>::ConstInnerVectorsReturnType 407SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize) const 408{ 409 return Block<const Derived,Dynamic,Dynamic,true>(derived(), 410 IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart, 411 IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); 412 413} 414 415/** Generic implementation of sparse Block expression. 416 * Real-only. 417 */ 418template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> 419class BlockImpl<XprType,BlockRows,BlockCols,InnerPanel,Sparse> 420 : public SparseMatrixBase<Block<XprType,BlockRows,BlockCols,InnerPanel> >, internal::no_assignment_operator 421{ 422 typedef typename internal::remove_all<typename XprType::Nested>::type _MatrixTypeNested; 423 typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType; 424public: 425 enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor }; 426 EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) 427 428 /** Column or Row constructor 429 */ 430 inline BlockImpl(const XprType& xpr, int i) 431 : m_matrix(xpr), 432 m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0), 433 m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0), 434 m_blockRows(BlockRows==1 ? 1 : xpr.rows()), 435 m_blockCols(BlockCols==1 ? 1 : xpr.cols()) 436 {} 437 438 /** Dynamic-size constructor 439 */ 440 inline BlockImpl(const XprType& xpr, int startRow, int startCol, int blockRows, int blockCols) 441 : m_matrix(xpr), m_startRow(startRow), m_startCol(startCol), m_blockRows(blockRows), m_blockCols(blockCols) 442 {} 443 444 inline int rows() const { return m_blockRows.value(); } 445 inline int cols() const { return m_blockCols.value(); } 446 447 inline Scalar& coeffRef(int row, int col) 448 { 449 return m_matrix.const_cast_derived() 450 .coeffRef(row + m_startRow.value(), col + m_startCol.value()); 451 } 452 453 inline const Scalar coeff(int row, int col) const 454 { 455 return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value()); 456 } 457 458 inline Scalar& coeffRef(int index) 459 { 460 return m_matrix.const_cast_derived() 461 .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), 462 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); 463 } 464 465 inline const Scalar coeff(int index) const 466 { 467 return m_matrix 468 .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), 469 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); 470 } 471 472 inline const _MatrixTypeNested& nestedExpression() const { return m_matrix; } 473 474 class InnerIterator : public _MatrixTypeNested::InnerIterator 475 { 476 typedef typename _MatrixTypeNested::InnerIterator Base; 477 const BlockType& m_block; 478 Index m_end; 479 public: 480 481 EIGEN_STRONG_INLINE InnerIterator(const BlockType& block, Index outer) 482 : Base(block.derived().nestedExpression(), outer + (IsRowMajor ? block.m_startRow.value() : block.m_startCol.value())), 483 m_block(block), 484 m_end(IsRowMajor ? block.m_startCol.value()+block.m_blockCols.value() : block.m_startRow.value()+block.m_blockRows.value()) 485 { 486 while( (Base::operator bool()) && (Base::index() < (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value())) ) 487 Base::operator++(); 488 } 489 490 inline Index index() const { return Base::index() - (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value()); } 491 inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block.m_startRow.value() : m_block.m_startCol.value()); } 492 inline Index row() const { return Base::row() - m_block.m_startRow.value(); } 493 inline Index col() const { return Base::col() - m_block.m_startCol.value(); } 494 495 inline operator bool() const { return Base::operator bool() && Base::index() < m_end; } 496 }; 497 class ReverseInnerIterator : public _MatrixTypeNested::ReverseInnerIterator 498 { 499 typedef typename _MatrixTypeNested::ReverseInnerIterator Base; 500 const BlockType& m_block; 501 Index m_begin; 502 public: 503 504 EIGEN_STRONG_INLINE ReverseInnerIterator(const BlockType& block, Index outer) 505 : Base(block.derived().nestedExpression(), outer + (IsRowMajor ? block.m_startRow.value() : block.m_startCol.value())), 506 m_block(block), 507 m_begin(IsRowMajor ? block.m_startCol.value() : block.m_startRow.value()) 508 { 509 while( (Base::operator bool()) && (Base::index() >= (IsRowMajor ? m_block.m_startCol.value()+block.m_blockCols.value() : m_block.m_startRow.value()+block.m_blockRows.value())) ) 510 Base::operator--(); 511 } 512 513 inline Index index() const { return Base::index() - (IsRowMajor ? m_block.m_startCol.value() : m_block.m_startRow.value()); } 514 inline Index outer() const { return Base::outer() - (IsRowMajor ? m_block.m_startRow.value() : m_block.m_startCol.value()); } 515 inline Index row() const { return Base::row() - m_block.m_startRow.value(); } 516 inline Index col() const { return Base::col() - m_block.m_startCol.value(); } 517 518 inline operator bool() const { return Base::operator bool() && Base::index() >= m_begin; } 519 }; 520 protected: 521 friend class InnerIterator; 522 friend class ReverseInnerIterator; 523 524 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl) 525 526 typename XprType::Nested m_matrix; 527 const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow; 528 const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol; 529 const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows; 530 const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols; 531 532}; 533 534} // end namespace Eigen 535 536#endif // EIGEN_SPARSE_BLOCK_H 537 538