SparseBlock.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // Eigen is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 3 of the License, or (at your option) any later version.
00010 //
00011 // Alternatively, you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License as
00013 // published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License and a copy of the GNU General Public License along with
00023 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00024 
00025 #ifndef EIGEN_SPARSE_BLOCK_H
00026 #define EIGEN_SPARSE_BLOCK_H
00027 
00028 namespace internal {
00029 template<typename MatrixType, int Size>
00030 struct traits<SparseInnerVectorSet<MatrixType, Size> >
00031 {
00032   typedef typename traits<MatrixType>::Scalar Scalar;
00033   typedef typename traits<MatrixType>::Index Index;
00034   typedef typename traits<MatrixType>::StorageKind StorageKind;
00035   typedef MatrixXpr XprKind;
00036   enum {
00037     IsRowMajor = (int(MatrixType::Flags)&RowMajorBit)==RowMajorBit,
00038     Flags = MatrixType::Flags,
00039     RowsAtCompileTime = IsRowMajor ? Size : MatrixType::RowsAtCompileTime,
00040     ColsAtCompileTime = IsRowMajor ? MatrixType::ColsAtCompileTime : Size,
00041     MaxRowsAtCompileTime = RowsAtCompileTime,
00042     MaxColsAtCompileTime = ColsAtCompileTime,
00043     CoeffReadCost = MatrixType::CoeffReadCost
00044   };
00045 };
00046 } // end namespace internal
00047 
00048 template<typename MatrixType, int Size>
00049 class SparseInnerVectorSet : internal::no_assignment_operator,
00050   public SparseMatrixBase<SparseInnerVectorSet<MatrixType, Size> >
00051 {
00052   public:
00053 
00054     enum { IsRowMajor = internal::traits<SparseInnerVectorSet>::IsRowMajor };
00055 
00056     EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet)
00057     class InnerIterator: public MatrixType::InnerIterator
00058     {
00059       public:
00060         inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer)
00061           : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
00062         {}
00063         inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
00064         inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
00065       protected:
00066         Index m_outer;
00067     };
00068 
00069     inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize)
00070       : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
00071     {
00072       eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
00073     }
00074 
00075     inline SparseInnerVectorSet(const MatrixType& matrix, Index outer)
00076       : m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
00077     {
00078       eigen_assert(Size!=Dynamic);
00079       eigen_assert( (outer>=0) && (outer<matrix.outerSize()) );
00080     }
00081 
00082 //     template<typename OtherDerived>
00083 //     inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
00084 //     {
00085 //       return *this;
00086 //     }
00087 
00088 //     template<typename Sparse>
00089 //     inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
00090 //     {
00091 //       return *this;
00092 //     }
00093 
00094     EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
00095     EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
00096 
00097   protected:
00098 
00099     const typename MatrixType::Nested m_matrix;
00100     Index m_outerStart;
00101     const internal::variable_if_dynamic<Index, Size> m_outerSize;
00102 };
00103 
00104 /***************************************************************************
00105 * specialisation for DynamicSparseMatrix
00106 ***************************************************************************/
00107 
00108 template<typename _Scalar, int _Options, int Size>
00109 class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size>
00110   : public SparseMatrixBase<SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size> >
00111 {
00112     typedef DynamicSparseMatrix<_Scalar, _Options> MatrixType;
00113   public:
00114 
00115     enum { IsRowMajor = internal::traits<SparseInnerVectorSet>::IsRowMajor };
00116 
00117     EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet)
00118     class InnerIterator: public MatrixType::InnerIterator
00119     {
00120       public:
00121         inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer)
00122           : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
00123         {}
00124         inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
00125         inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
00126       protected:
00127         Index m_outer;
00128     };
00129 
00130     inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize)
00131       : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
00132     {
00133       eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
00134     }
00135 
00136     inline SparseInnerVectorSet(const MatrixType& matrix, Index outer)
00137       : m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
00138     {
00139       eigen_assert(Size!=Dynamic);
00140       eigen_assert( (outer>=0) && (outer<matrix.outerSize()) );
00141     }
00142 
00143     template<typename OtherDerived>
00144     inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
00145     {
00146       if (IsRowMajor != ((OtherDerived::Flags&RowMajorBit)==RowMajorBit))
00147       {
00148         // need to transpose => perform a block evaluation followed by a big swap
00149         DynamicSparseMatrix<Scalar,IsRowMajor?RowMajorBit:0> aux(other);
00150         *this = aux.markAsRValue();
00151       }
00152       else
00153       {
00154         // evaluate/copy vector per vector
00155         for (Index j=0; j<m_outerSize.value(); ++j)
00156         {
00157           SparseVector<Scalar,IsRowMajor ? RowMajorBit : 0> aux(other.innerVector(j));
00158           m_matrix.const_cast_derived()._data()[m_outerStart+j].swap(aux._data());
00159         }
00160       }
00161       return *this;
00162     }
00163 
00164     inline SparseInnerVectorSet& operator=(const SparseInnerVectorSet& other)
00165     {
00166       return operator=<SparseInnerVectorSet>(other);
00167     }
00168 
00169     Index nonZeros() const
00170     {
00171       Index count = 0;
00172       for (Index j=0; j<m_outerSize.value(); ++j)
00173         count += m_matrix._data()[m_outerStart+j].size();
00174       return count;
00175     }
00176 
00177     const Scalar& lastCoeff() const
00178     {
00179       EIGEN_STATIC_ASSERT_VECTOR_ONLY(SparseInnerVectorSet);
00180       eigen_assert(m_matrix.data()[m_outerStart].size()>0);
00181       return m_matrix.data()[m_outerStart].vale(m_matrix.data()[m_outerStart].size()-1);
00182     }
00183 
00184 //     template<typename Sparse>
00185 //     inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
00186 //     {
00187 //       return *this;
00188 //     }
00189 
00190     EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
00191     EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
00192 
00193   protected:
00194 
00195     const typename MatrixType::Nested m_matrix;
00196     Index m_outerStart;
00197     const internal::variable_if_dynamic<Index, Size> m_outerSize;
00198 
00199 };
00200 
00201 
00202 /***************************************************************************
00203 * specialisation for SparseMatrix
00204 ***************************************************************************/
00205 
00206 template<typename _Scalar, int _Options, typename _Index, int Size>
00207 class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size>
00208   : public SparseMatrixBase<SparseInnerVectorSet<SparseMatrix<_Scalar, _Options>, Size> >
00209 {
00210     typedef SparseMatrix<_Scalar, _Options> MatrixType;
00211   public:
00212 
00213     enum { IsRowMajor = internal::traits<SparseInnerVectorSet>::IsRowMajor };
00214 
00215     EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet)
00216     class InnerIterator: public MatrixType::InnerIterator
00217     {
00218       public:
00219         inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer)
00220           : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
00221         {}
00222         inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
00223         inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
00224       protected:
00225         Index m_outer;
00226     };
00227 
00228     inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize)
00229       : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
00230     {
00231       eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
00232     }
00233 
00234     inline SparseInnerVectorSet(const MatrixType& matrix, Index outer)
00235       : m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
00236     {
00237       eigen_assert(Size==1);
00238       eigen_assert( (outer>=0) && (outer<matrix.outerSize()) );
00239     }
00240 
00241     template<typename OtherDerived>
00242     inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
00243     {
00244       typedef typename internal::remove_all<typename MatrixType::Nested>::type _NestedMatrixType;
00245       _NestedMatrixType& matrix = const_cast<_NestedMatrixType&>(m_matrix);;
00246       // This assignement is slow if this vector set not empty
00247       // and/or it is not at the end of the nonzeros of the underlying matrix.
00248 
00249       // 1 - eval to a temporary to avoid transposition and/or aliasing issues
00250       SparseMatrix<Scalar, IsRowMajor ? RowMajor : ColMajor, Index> tmp(other);
00251 
00252       // 2 - let's check whether there is enough allocated memory
00253       Index nnz = tmp.nonZeros();
00254       Index nnz_previous = nonZeros();
00255       Index free_size = matrix.data().allocatedSize() - nnz_previous;
00256       std::size_t nnz_head = m_outerStart==0 ? 0 : matrix._outerIndexPtr()[m_outerStart];
00257       std::size_t tail = m_matrix._outerIndexPtr()[m_outerStart+m_outerSize.value()];
00258       std::size_t nnz_tail = matrix.nonZeros() - tail;
00259 
00260       if(nnz>free_size)
00261       {
00262         // realloc manually to reduce copies
00263         typename MatrixType::Storage newdata(m_matrix.nonZeros() - nnz_previous + nnz);
00264 
00265         std::memcpy(&newdata.value(0), &m_matrix.data().value(0), nnz_head*sizeof(Scalar));
00266         std::memcpy(&newdata.index(0), &m_matrix.data().index(0), nnz_head*sizeof(Index));
00267 
00268         std::memcpy(&newdata.value(nnz_head), &tmp.data().value(0), nnz*sizeof(Scalar));
00269         std::memcpy(&newdata.index(nnz_head), &tmp.data().index(0), nnz*sizeof(Index));
00270 
00271         std::memcpy(&newdata.value(nnz_head+nnz), &matrix.data().value(tail), nnz_tail*sizeof(Scalar));
00272         std::memcpy(&newdata.index(nnz_head+nnz), &matrix.data().index(tail), nnz_tail*sizeof(Index));
00273 
00274         matrix.data().swap(newdata);
00275       }
00276       else
00277       {
00278         // no need to realloc, simply copy the tail at its respective position and insert tmp
00279         matrix.data().resize(nnz_head + nnz + nnz_tail);
00280 
00281         if(nnz<nnz_previous)
00282         {
00283           std::memcpy(&matrix.data().value(nnz_head+nnz), &matrix.data().value(tail), nnz_tail*sizeof(Scalar));
00284           std::memcpy(&matrix.data().index(nnz_head+nnz), &matrix.data().index(tail), nnz_tail*sizeof(Index));
00285         }
00286         else
00287         {
00288           for(Index i=nnz_tail-1; i>=0; --i)
00289           {
00290             matrix.data().value(nnz_head+nnz+i) = matrix.data().value(tail+i);
00291             matrix.data().index(nnz_head+nnz+i) = matrix.data().index(tail+i);
00292           }
00293         }
00294 
00295         std::memcpy(&matrix.data().value(nnz_head), &tmp.data().value(0), nnz*sizeof(Scalar));
00296         std::memcpy(&matrix.data().index(nnz_head), &tmp.data().index(0), nnz*sizeof(Index));
00297       }
00298 
00299       // update outer index pointers
00300       Index p = nnz_head;
00301       for(Index k=1; k<m_outerSize.value(); ++k)
00302       {
00303         matrix._outerIndexPtr()[m_outerStart+k] = p;
00304         p += tmp.innerVector(k).nonZeros();
00305       }
00306       std::ptrdiff_t offset = nnz - nnz_previous;
00307       for(Index k = m_outerStart + m_outerSize.value(); k<=matrix.outerSize(); ++k)
00308       {
00309         matrix._outerIndexPtr()[k] += offset;
00310       }
00311 
00312       return *this;
00313     }
00314 
00315     inline SparseInnerVectorSet& operator=(const SparseInnerVectorSet& other)
00316     {
00317       return operator=<SparseInnerVectorSet>(other);
00318     }
00319 
00320     inline const Scalar* _valuePtr() const
00321     { return m_matrix._valuePtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
00322     inline Scalar* _valuePtr()
00323     { return m_matrix.const_cast_derived()._valuePtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
00324 
00325     inline const Index* _innerIndexPtr() const
00326     { return m_matrix._innerIndexPtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
00327     inline Index* _innerIndexPtr()
00328     { return m_matrix.const_cast_derived()._innerIndexPtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
00329 
00330     inline const Index* _outerIndexPtr() const
00331     { return m_matrix._outerIndexPtr() + m_outerStart; }
00332     inline Index* _outerIndexPtr()
00333     { return m_matrix.const_cast_derived()._outerIndexPtr() + m_outerStart; }
00334 
00335     Index nonZeros() const
00336     {
00337       return  std::size_t(m_matrix._outerIndexPtr()[m_outerStart+m_outerSize.value()])
00338             - std::size_t(m_matrix._outerIndexPtr()[m_outerStart]);
00339     }
00340 
00341     const Scalar& lastCoeff() const
00342     {
00343       EIGEN_STATIC_ASSERT_VECTOR_ONLY(SparseInnerVectorSet);
00344       eigen_assert(nonZeros()>0);
00345       return m_matrix._valuePtr()[m_matrix._outerIndexPtr()[m_outerStart+1]-1];
00346     }
00347 
00348 //     template<typename Sparse>
00349 //     inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
00350 //     {
00351 //       return *this;
00352 //     }
00353 
00354     EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
00355     EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
00356 
00357   protected:
00358 
00359     const typename MatrixType::Nested m_matrix;
00360     Index m_outerStart;
00361     const internal::variable_if_dynamic<Index, Size> m_outerSize;
00362 
00363 };
00364 
00365 //----------
00366 
00368 template<typename Derived>
00369 SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(Index i)
00370 {
00371   EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
00372   return innerVector(i);
00373 }
00374 
00377 template<typename Derived>
00378 const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(Index i) const
00379 {
00380   EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
00381   return innerVector(i);
00382 }
00383 
00385 template<typename Derived>
00386 SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(Index i)
00387 {
00388   EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
00389   return innerVector(i);
00390 }
00391 
00394 template<typename Derived>
00395 const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(Index i) const
00396 {
00397   EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
00398   return innerVector(i);
00399 }
00400 
00404 template<typename Derived>
00405 SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(Index outer)
00406 { return SparseInnerVectorSet<Derived,1>(derived(), outer); }
00407 
00411 template<typename Derived>
00412 const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(Index outer) const
00413 { return SparseInnerVectorSet<Derived,1>(derived(), outer); }
00414 
00415 //----------
00416 
00418 template<typename Derived>
00419 SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(Index start, Index size)
00420 {
00421   EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
00422   return innerVectors(start, size);
00423 }
00424 
00427 template<typename Derived>
00428 const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(Index start, Index size) const
00429 {
00430   EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
00431   return innerVectors(start, size);
00432 }
00433 
00435 template<typename Derived>
00436 SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(Index start, Index size)
00437 {
00438   EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
00439   return innerVectors(start, size);
00440 }
00441 
00444 template<typename Derived>
00445 const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(Index start, Index size) const
00446 {
00447   EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
00448   return innerVectors(start, size);
00449 }
00450 
00454 template<typename Derived>
00455 SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize)
00456 { return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); }
00457 
00461 template<typename Derived>
00462 const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize) const
00463 { return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); }
00464 
00465 #endif // EIGEN_SPARSE_BLOCK_H


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:32:46