Home | History | Annotate | Download | only in SparseCore
      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 (at) 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_SPARSEMATRIX_H
     11 #define EIGEN_SPARSEMATRIX_H
     12 
     13 namespace Eigen {
     14 
     15 /** \ingroup SparseCore_Module
     16   *
     17   * \class SparseMatrix
     18   *
     19   * \brief A versatible sparse matrix representation
     20   *
     21   * This class implements a more versatile variants of the common \em compressed row/column storage format.
     22   * Each colmun's (resp. row) non zeros are stored as a pair of value with associated row (resp. colmiun) index.
     23   * All the non zeros are stored in a single large buffer. Unlike the \em compressed format, there might be extra
     24   * space inbetween the nonzeros of two successive colmuns (resp. rows) such that insertion of new non-zero
     25   * can be done with limited memory reallocation and copies.
     26   *
     27   * A call to the function makeCompressed() turns the matrix into the standard \em compressed format
     28   * compatible with many library.
     29   *
     30   * More details on this storage sceheme are given in the \ref TutorialSparse "manual pages".
     31   *
     32   * \tparam _Scalar the scalar type, i.e. the type of the coefficients
     33   * \tparam _Options Union of bit flags controlling the storage scheme. Currently the only possibility
     34   *                 is ColMajor or RowMajor. The default is 0 which means column-major.
     35   * \tparam _StorageIndex the type of the indices. It has to be a \b signed type (e.g., short, int, std::ptrdiff_t). Default is \c int.
     36   *
     37   * \warning In %Eigen 3.2, the undocumented type \c SparseMatrix::Index was improperly defined as the storage index type (e.g., int),
     38   *          whereas it is now (starting from %Eigen 3.3) deprecated and always defined as Eigen::Index.
     39   *          Codes making use of \c SparseMatrix::Index, might thus likely have to be changed to use \c SparseMatrix::StorageIndex instead.
     40   *
     41   * This class can be extended with the help of the plugin mechanism described on the page
     42   * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_SPARSEMATRIX_PLUGIN.
     43   */
     44 
     45 namespace internal {
     46 template<typename _Scalar, int _Options, typename _StorageIndex>
     47 struct traits<SparseMatrix<_Scalar, _Options, _StorageIndex> >
     48 {
     49   typedef _Scalar Scalar;
     50   typedef _StorageIndex StorageIndex;
     51   typedef Sparse StorageKind;
     52   typedef MatrixXpr XprKind;
     53   enum {
     54     RowsAtCompileTime = Dynamic,
     55     ColsAtCompileTime = Dynamic,
     56     MaxRowsAtCompileTime = Dynamic,
     57     MaxColsAtCompileTime = Dynamic,
     58     Flags = _Options | NestByRefBit | LvalueBit | CompressedAccessBit,
     59     SupportedAccessPatterns = InnerRandomAccessPattern
     60   };
     61 };
     62 
     63 template<typename _Scalar, int _Options, typename _StorageIndex, int DiagIndex>
     64 struct traits<Diagonal<SparseMatrix<_Scalar, _Options, _StorageIndex>, DiagIndex> >
     65 {
     66   typedef SparseMatrix<_Scalar, _Options, _StorageIndex> MatrixType;
     67   typedef typename ref_selector<MatrixType>::type MatrixTypeNested;
     68   typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
     69 
     70   typedef _Scalar Scalar;
     71   typedef Dense StorageKind;
     72   typedef _StorageIndex StorageIndex;
     73   typedef MatrixXpr XprKind;
     74 
     75   enum {
     76     RowsAtCompileTime = Dynamic,
     77     ColsAtCompileTime = 1,
     78     MaxRowsAtCompileTime = Dynamic,
     79     MaxColsAtCompileTime = 1,
     80     Flags = LvalueBit
     81   };
     82 };
     83 
     84 template<typename _Scalar, int _Options, typename _StorageIndex, int DiagIndex>
     85 struct traits<Diagonal<const SparseMatrix<_Scalar, _Options, _StorageIndex>, DiagIndex> >
     86  : public traits<Diagonal<SparseMatrix<_Scalar, _Options, _StorageIndex>, DiagIndex> >
     87 {
     88   enum {
     89     Flags = 0
     90   };
     91 };
     92 
     93 } // end namespace internal
     94 
     95 template<typename _Scalar, int _Options, typename _StorageIndex>
     96 class SparseMatrix
     97   : public SparseCompressedBase<SparseMatrix<_Scalar, _Options, _StorageIndex> >
     98 {
     99     typedef SparseCompressedBase<SparseMatrix> Base;
    100     using Base::convert_index;
    101     friend class SparseVector<_Scalar,0,_StorageIndex>;
    102   public:
    103     using Base::isCompressed;
    104     using Base::nonZeros;
    105     EIGEN_SPARSE_PUBLIC_INTERFACE(SparseMatrix)
    106     using Base::operator+=;
    107     using Base::operator-=;
    108 
    109     typedef MappedSparseMatrix<Scalar,Flags> Map;
    110     typedef Diagonal<SparseMatrix> DiagonalReturnType;
    111     typedef Diagonal<const SparseMatrix> ConstDiagonalReturnType;
    112     typedef typename Base::InnerIterator InnerIterator;
    113     typedef typename Base::ReverseInnerIterator ReverseInnerIterator;
    114 
    115 
    116     using Base::IsRowMajor;
    117     typedef internal::CompressedStorage<Scalar,StorageIndex> Storage;
    118     enum {
    119       Options = _Options
    120     };
    121 
    122     typedef typename Base::IndexVector IndexVector;
    123     typedef typename Base::ScalarVector ScalarVector;
    124   protected:
    125     typedef SparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0)> TransposedSparseMatrix;
    126 
    127     Index m_outerSize;
    128     Index m_innerSize;
    129     StorageIndex* m_outerIndex;
    130     StorageIndex* m_innerNonZeros;     // optional, if null then the data is compressed
    131     Storage m_data;
    132 
    133   public:
    134 
    135     /** \returns the number of rows of the matrix */
    136     inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
    137     /** \returns the number of columns of the matrix */
    138     inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
    139 
    140     /** \returns the number of rows (resp. columns) of the matrix if the storage order column major (resp. row major) */
    141     inline Index innerSize() const { return m_innerSize; }
    142     /** \returns the number of columns (resp. rows) of the matrix if the storage order column major (resp. row major) */
    143     inline Index outerSize() const { return m_outerSize; }
    144 
    145     /** \returns a const pointer to the array of values.
    146       * This function is aimed at interoperability with other libraries.
    147       * \sa innerIndexPtr(), outerIndexPtr() */
    148     inline const Scalar* valuePtr() const { return m_data.valuePtr(); }
    149     /** \returns a non-const pointer to the array of values.
    150       * This function is aimed at interoperability with other libraries.
    151       * \sa innerIndexPtr(), outerIndexPtr() */
    152     inline Scalar* valuePtr() { return m_data.valuePtr(); }
    153 
    154     /** \returns a const pointer to the array of inner indices.
    155       * This function is aimed at interoperability with other libraries.
    156       * \sa valuePtr(), outerIndexPtr() */
    157     inline const StorageIndex* innerIndexPtr() const { return m_data.indexPtr(); }
    158     /** \returns a non-const pointer to the array of inner indices.
    159       * This function is aimed at interoperability with other libraries.
    160       * \sa valuePtr(), outerIndexPtr() */
    161     inline StorageIndex* innerIndexPtr() { return m_data.indexPtr(); }
    162 
    163     /** \returns a const pointer to the array of the starting positions of the inner vectors.
    164       * This function is aimed at interoperability with other libraries.
    165       * \sa valuePtr(), innerIndexPtr() */
    166     inline const StorageIndex* outerIndexPtr() const { return m_outerIndex; }
    167     /** \returns a non-const pointer to the array of the starting positions of the inner vectors.
    168       * This function is aimed at interoperability with other libraries.
    169       * \sa valuePtr(), innerIndexPtr() */
    170     inline StorageIndex* outerIndexPtr() { return m_outerIndex; }
    171 
    172     /** \returns a const pointer to the array of the number of non zeros of the inner vectors.
    173       * This function is aimed at interoperability with other libraries.
    174       * \warning it returns the null pointer 0 in compressed mode */
    175     inline const StorageIndex* innerNonZeroPtr() const { return m_innerNonZeros; }
    176     /** \returns a non-const pointer to the array of the number of non zeros of the inner vectors.
    177       * This function is aimed at interoperability with other libraries.
    178       * \warning it returns the null pointer 0 in compressed mode */
    179     inline StorageIndex* innerNonZeroPtr() { return m_innerNonZeros; }
    180 
    181     /** \internal */
    182     inline Storage& data() { return m_data; }
    183     /** \internal */
    184     inline const Storage& data() const { return m_data; }
    185 
    186     /** \returns the value of the matrix at position \a i, \a j
    187       * This function returns Scalar(0) if the element is an explicit \em zero */
    188     inline Scalar coeff(Index row, Index col) const
    189     {
    190       eigen_assert(row>=0 && row<rows() && col>=0 && col<cols());
    191 
    192       const Index outer = IsRowMajor ? row : col;
    193       const Index inner = IsRowMajor ? col : row;
    194       Index end = m_innerNonZeros ? m_outerIndex[outer] + m_innerNonZeros[outer] : m_outerIndex[outer+1];
    195       return m_data.atInRange(m_outerIndex[outer], end, StorageIndex(inner));
    196     }
    197 
    198     /** \returns a non-const reference to the value of the matrix at position \a i, \a j
    199       *
    200       * If the element does not exist then it is inserted via the insert(Index,Index) function
    201       * which itself turns the matrix into a non compressed form if that was not the case.
    202       *
    203       * This is a O(log(nnz_j)) operation (binary search) plus the cost of insert(Index,Index)
    204       * function if the element does not already exist.
    205       */
    206     inline Scalar& coeffRef(Index row, Index col)
    207     {
    208       eigen_assert(row>=0 && row<rows() && col>=0 && col<cols());
    209 
    210       const Index outer = IsRowMajor ? row : col;
    211       const Index inner = IsRowMajor ? col : row;
    212 
    213       Index start = m_outerIndex[outer];
    214       Index end = m_innerNonZeros ? m_outerIndex[outer] + m_innerNonZeros[outer] : m_outerIndex[outer+1];
    215       eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
    216       if(end<=start)
    217         return insert(row,col);
    218       const Index p = m_data.searchLowerIndex(start,end-1,StorageIndex(inner));
    219       if((p<end) && (m_data.index(p)==inner))
    220         return m_data.value(p);
    221       else
    222         return insert(row,col);
    223     }
    224 
    225     /** \returns a reference to a novel non zero coefficient with coordinates \a row x \a col.
    226       * The non zero coefficient must \b not already exist.
    227       *
    228       * If the matrix \c *this is in compressed mode, then \c *this is turned into uncompressed
    229       * mode while reserving room for 2 x this->innerSize() non zeros if reserve(Index) has not been called earlier.
    230       * In this case, the insertion procedure is optimized for a \e sequential insertion mode where elements are assumed to be
    231       * inserted by increasing outer-indices.
    232       *
    233       * If that's not the case, then it is strongly recommended to either use a triplet-list to assemble the matrix, or to first
    234       * call reserve(const SizesType &) to reserve the appropriate number of non-zero elements per inner vector.
    235       *
    236       * Assuming memory has been appropriately reserved, this function performs a sorted insertion in O(1)
    237       * if the elements of each inner vector are inserted in increasing inner index order, and in O(nnz_j) for a random insertion.
    238       *
    239       */
    240     Scalar& insert(Index row, Index col);
    241 
    242   public:
    243 
    244     /** Removes all non zeros but keep allocated memory
    245       *
    246       * This function does not free the currently allocated memory. To release as much as memory as possible,
    247       * call \code mat.data().squeeze(); \endcode after resizing it.
    248       *
    249       * \sa resize(Index,Index), data()
    250       */
    251     inline void setZero()
    252     {
    253       m_data.clear();
    254       memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(StorageIndex));
    255       if(m_innerNonZeros)
    256         memset(m_innerNonZeros, 0, (m_outerSize)*sizeof(StorageIndex));
    257     }
    258 
    259     /** Preallocates \a reserveSize non zeros.
    260       *
    261       * Precondition: the matrix must be in compressed mode. */
    262     inline void reserve(Index reserveSize)
    263     {
    264       eigen_assert(isCompressed() && "This function does not make sense in non compressed mode.");
    265       m_data.reserve(reserveSize);
    266     }
    267 
    268     #ifdef EIGEN_PARSED_BY_DOXYGEN
    269     /** Preallocates \a reserveSize[\c j] non zeros for each column (resp. row) \c j.
    270       *
    271       * This function turns the matrix in non-compressed mode.
    272       *
    273       * The type \c SizesType must expose the following interface:
    274         \code
    275         typedef value_type;
    276         const value_type& operator[](i) const;
    277         \endcode
    278       * for \c i in the [0,this->outerSize()[ range.
    279       * Typical choices include std::vector<int>, Eigen::VectorXi, Eigen::VectorXi::Constant, etc.
    280       */
    281     template<class SizesType>
    282     inline void reserve(const SizesType& reserveSizes);
    283     #else
    284     template<class SizesType>
    285     inline void reserve(const SizesType& reserveSizes, const typename SizesType::value_type& enableif =
    286     #if (!EIGEN_COMP_MSVC) || (EIGEN_COMP_MSVC>=1500) // MSVC 2005 fails to compile with this typename
    287         typename
    288     #endif
    289         SizesType::value_type())
    290     {
    291       EIGEN_UNUSED_VARIABLE(enableif);
    292       reserveInnerVectors(reserveSizes);
    293     }
    294     #endif // EIGEN_PARSED_BY_DOXYGEN
    295   protected:
    296     template<class SizesType>
    297     inline void reserveInnerVectors(const SizesType& reserveSizes)
    298     {
    299       if(isCompressed())
    300       {
    301         Index totalReserveSize = 0;
    302         // turn the matrix into non-compressed mode
    303         m_innerNonZeros = static_cast<StorageIndex*>(std::malloc(m_outerSize * sizeof(StorageIndex)));
    304         if (!m_innerNonZeros) internal::throw_std_bad_alloc();
    305 
    306         // temporarily use m_innerSizes to hold the new starting points.
    307         StorageIndex* newOuterIndex = m_innerNonZeros;
    308 
    309         StorageIndex count = 0;
    310         for(Index j=0; j<m_outerSize; ++j)
    311         {
    312           newOuterIndex[j] = count;
    313           count += reserveSizes[j] + (m_outerIndex[j+1]-m_outerIndex[j]);
    314           totalReserveSize += reserveSizes[j];
    315         }
    316         m_data.reserve(totalReserveSize);
    317         StorageIndex previousOuterIndex = m_outerIndex[m_outerSize];
    318         for(Index j=m_outerSize-1; j>=0; --j)
    319         {
    320           StorageIndex innerNNZ = previousOuterIndex - m_outerIndex[j];
    321           for(Index i=innerNNZ-1; i>=0; --i)
    322           {
    323             m_data.index(newOuterIndex[j]+i) = m_data.index(m_outerIndex[j]+i);
    324             m_data.value(newOuterIndex[j]+i) = m_data.value(m_outerIndex[j]+i);
    325           }
    326           previousOuterIndex = m_outerIndex[j];
    327           m_outerIndex[j] = newOuterIndex[j];
    328           m_innerNonZeros[j] = innerNNZ;
    329         }
    330         m_outerIndex[m_outerSize] = m_outerIndex[m_outerSize-1] + m_innerNonZeros[m_outerSize-1] + reserveSizes[m_outerSize-1];
    331 
    332         m_data.resize(m_outerIndex[m_outerSize]);
    333       }
    334       else
    335       {
    336         StorageIndex* newOuterIndex = static_cast<StorageIndex*>(std::malloc((m_outerSize+1)*sizeof(StorageIndex)));
    337         if (!newOuterIndex) internal::throw_std_bad_alloc();
    338 
    339         StorageIndex count = 0;
    340         for(Index j=0; j<m_outerSize; ++j)
    341         {
    342           newOuterIndex[j] = count;
    343           StorageIndex alreadyReserved = (m_outerIndex[j+1]-m_outerIndex[j]) - m_innerNonZeros[j];
    344           StorageIndex toReserve = std::max<StorageIndex>(reserveSizes[j], alreadyReserved);
    345           count += toReserve + m_innerNonZeros[j];
    346         }
    347         newOuterIndex[m_outerSize] = count;
    348 
    349         m_data.resize(count);
    350         for(Index j=m_outerSize-1; j>=0; --j)
    351         {
    352           Index offset = newOuterIndex[j] - m_outerIndex[j];
    353           if(offset>0)
    354           {
    355             StorageIndex innerNNZ = m_innerNonZeros[j];
    356             for(Index i=innerNNZ-1; i>=0; --i)
    357             {
    358               m_data.index(newOuterIndex[j]+i) = m_data.index(m_outerIndex[j]+i);
    359               m_data.value(newOuterIndex[j]+i) = m_data.value(m_outerIndex[j]+i);
    360             }
    361           }
    362         }
    363 
    364         std::swap(m_outerIndex, newOuterIndex);
    365         std::free(newOuterIndex);
    366       }
    367 
    368     }
    369   public:
    370 
    371     //--- low level purely coherent filling ---
    372 
    373     /** \internal
    374       * \returns a reference to the non zero coefficient at position \a row, \a col assuming that:
    375       * - the nonzero does not already exist
    376       * - the new coefficient is the last one according to the storage order
    377       *
    378       * Before filling a given inner vector you must call the statVec(Index) function.
    379       *
    380       * After an insertion session, you should call the finalize() function.
    381       *
    382       * \sa insert, insertBackByOuterInner, startVec */
    383     inline Scalar& insertBack(Index row, Index col)
    384     {
    385       return insertBackByOuterInner(IsRowMajor?row:col, IsRowMajor?col:row);
    386     }
    387 
    388     /** \internal
    389       * \sa insertBack, startVec */
    390     inline Scalar& insertBackByOuterInner(Index outer, Index inner)
    391     {
    392       eigen_assert(Index(m_outerIndex[outer+1]) == m_data.size() && "Invalid ordered insertion (invalid outer index)");
    393       eigen_assert( (m_outerIndex[outer+1]-m_outerIndex[outer]==0 || m_data.index(m_data.size()-1)<inner) && "Invalid ordered insertion (invalid inner index)");
    394       Index p = m_outerIndex[outer+1];
    395       ++m_outerIndex[outer+1];
    396       m_data.append(Scalar(0), inner);
    397       return m_data.value(p);
    398     }
    399 
    400     /** \internal
    401       * \warning use it only if you know what you are doing */
    402     inline Scalar& insertBackByOuterInnerUnordered(Index outer, Index inner)
    403     {
    404       Index p = m_outerIndex[outer+1];
    405       ++m_outerIndex[outer+1];
    406       m_data.append(Scalar(0), inner);
    407       return m_data.value(p);
    408     }
    409 
    410     /** \internal
    411       * \sa insertBack, insertBackByOuterInner */
    412     inline void startVec(Index outer)
    413     {
    414       eigen_assert(m_outerIndex[outer]==Index(m_data.size()) && "You must call startVec for each inner vector sequentially");
    415       eigen_assert(m_outerIndex[outer+1]==0 && "You must call startVec for each inner vector sequentially");
    416       m_outerIndex[outer+1] = m_outerIndex[outer];
    417     }
    418 
    419     /** \internal
    420       * Must be called after inserting a set of non zero entries using the low level compressed API.
    421       */
    422     inline void finalize()
    423     {
    424       if(isCompressed())
    425       {
    426         StorageIndex size = internal::convert_index<StorageIndex>(m_data.size());
    427         Index i = m_outerSize;
    428         // find the last filled column
    429         while (i>=0 && m_outerIndex[i]==0)
    430           --i;
    431         ++i;
    432         while (i<=m_outerSize)
    433         {
    434           m_outerIndex[i] = size;
    435           ++i;
    436         }
    437       }
    438     }
    439 
    440     //---
    441 
    442     template<typename InputIterators>
    443     void setFromTriplets(const InputIterators& begin, const InputIterators& end);
    444 
    445     template<typename InputIterators,typename DupFunctor>
    446     void setFromTriplets(const InputIterators& begin, const InputIterators& end, DupFunctor dup_func);
    447 
    448     void sumupDuplicates() { collapseDuplicates(internal::scalar_sum_op<Scalar,Scalar>()); }
    449 
    450     template<typename DupFunctor>
    451     void collapseDuplicates(DupFunctor dup_func = DupFunctor());
    452 
    453     //---
    454 
    455     /** \internal
    456       * same as insert(Index,Index) except that the indices are given relative to the storage order */
    457     Scalar& insertByOuterInner(Index j, Index i)
    458     {
    459       return insert(IsRowMajor ? j : i, IsRowMajor ? i : j);
    460     }
    461 
    462     /** Turns the matrix into the \em compressed format.
    463       */
    464     void makeCompressed()
    465     {
    466       if(isCompressed())
    467         return;
    468 
    469       eigen_internal_assert(m_outerIndex!=0 && m_outerSize>0);
    470 
    471       Index oldStart = m_outerIndex[1];
    472       m_outerIndex[1] = m_innerNonZeros[0];
    473       for(Index j=1; j<m_outerSize; ++j)
    474       {
    475         Index nextOldStart = m_outerIndex[j+1];
    476         Index offset = oldStart - m_outerIndex[j];
    477         if(offset>0)
    478         {
    479           for(Index k=0; k<m_innerNonZeros[j]; ++k)
    480           {
    481             m_data.index(m_outerIndex[j]+k) = m_data.index(oldStart+k);
    482             m_data.value(m_outerIndex[j]+k) = m_data.value(oldStart+k);
    483           }
    484         }
    485         m_outerIndex[j+1] = m_outerIndex[j] + m_innerNonZeros[j];
    486         oldStart = nextOldStart;
    487       }
    488       std::free(m_innerNonZeros);
    489       m_innerNonZeros = 0;
    490       m_data.resize(m_outerIndex[m_outerSize]);
    491       m_data.squeeze();
    492     }
    493 
    494     /** Turns the matrix into the uncompressed mode */
    495     void uncompress()
    496     {
    497       if(m_innerNonZeros != 0)
    498         return;
    499       m_innerNonZeros = static_cast<StorageIndex*>(std::malloc(m_outerSize * sizeof(StorageIndex)));
    500       for (Index i = 0; i < m_outerSize; i++)
    501       {
    502         m_innerNonZeros[i] = m_outerIndex[i+1] - m_outerIndex[i];
    503       }
    504     }
    505 
    506     /** Suppresses all nonzeros which are \b much \b smaller \b than \a reference under the tolerence \a epsilon */
    507     void prune(const Scalar& reference, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision())
    508     {
    509       prune(default_prunning_func(reference,epsilon));
    510     }
    511 
    512     /** Turns the matrix into compressed format, and suppresses all nonzeros which do not satisfy the predicate \a keep.
    513       * The functor type \a KeepFunc must implement the following function:
    514       * \code
    515       * bool operator() (const Index& row, const Index& col, const Scalar& value) const;
    516       * \endcode
    517       * \sa prune(Scalar,RealScalar)
    518       */
    519     template<typename KeepFunc>
    520     void prune(const KeepFunc& keep = KeepFunc())
    521     {
    522       // TODO optimize the uncompressed mode to avoid moving and allocating the data twice
    523       makeCompressed();
    524 
    525       StorageIndex k = 0;
    526       for(Index j=0; j<m_outerSize; ++j)
    527       {
    528         Index previousStart = m_outerIndex[j];
    529         m_outerIndex[j] = k;
    530         Index end = m_outerIndex[j+1];
    531         for(Index i=previousStart; i<end; ++i)
    532         {
    533           if(keep(IsRowMajor?j:m_data.index(i), IsRowMajor?m_data.index(i):j, m_data.value(i)))
    534           {
    535             m_data.value(k) = m_data.value(i);
    536             m_data.index(k) = m_data.index(i);
    537             ++k;
    538           }
    539         }
    540       }
    541       m_outerIndex[m_outerSize] = k;
    542       m_data.resize(k,0);
    543     }
    544 
    545     /** Resizes the matrix to a \a rows x \a cols matrix leaving old values untouched.
    546       *
    547       * If the sizes of the matrix are decreased, then the matrix is turned to \b uncompressed-mode
    548       * and the storage of the out of bounds coefficients is kept and reserved.
    549       * Call makeCompressed() to pack the entries and squeeze extra memory.
    550       *
    551       * \sa reserve(), setZero(), makeCompressed()
    552       */
    553     void conservativeResize(Index rows, Index cols)
    554     {
    555       // No change
    556       if (this->rows() == rows && this->cols() == cols) return;
    557 
    558       // If one dimension is null, then there is nothing to be preserved
    559       if(rows==0 || cols==0) return resize(rows,cols);
    560 
    561       Index innerChange = IsRowMajor ? cols - this->cols() : rows - this->rows();
    562       Index outerChange = IsRowMajor ? rows - this->rows() : cols - this->cols();
    563       StorageIndex newInnerSize = convert_index(IsRowMajor ? cols : rows);
    564 
    565       // Deals with inner non zeros
    566       if (m_innerNonZeros)
    567       {
    568         // Resize m_innerNonZeros
    569         StorageIndex *newInnerNonZeros = static_cast<StorageIndex*>(std::realloc(m_innerNonZeros, (m_outerSize + outerChange) * sizeof(StorageIndex)));
    570         if (!newInnerNonZeros) internal::throw_std_bad_alloc();
    571         m_innerNonZeros = newInnerNonZeros;
    572 
    573         for(Index i=m_outerSize; i<m_outerSize+outerChange; i++)
    574           m_innerNonZeros[i] = 0;
    575       }
    576       else if (innerChange < 0)
    577       {
    578         // Inner size decreased: allocate a new m_innerNonZeros
    579         m_innerNonZeros = static_cast<StorageIndex*>(std::malloc((m_outerSize+outerChange+1) * sizeof(StorageIndex)));
    580         if (!m_innerNonZeros) internal::throw_std_bad_alloc();
    581         for(Index i = 0; i < m_outerSize; i++)
    582           m_innerNonZeros[i] = m_outerIndex[i+1] - m_outerIndex[i];
    583       }
    584 
    585       // Change the m_innerNonZeros in case of a decrease of inner size
    586       if (m_innerNonZeros && innerChange < 0)
    587       {
    588         for(Index i = 0; i < m_outerSize + (std::min)(outerChange, Index(0)); i++)
    589         {
    590           StorageIndex &n = m_innerNonZeros[i];
    591           StorageIndex start = m_outerIndex[i];
    592           while (n > 0 && m_data.index(start+n-1) >= newInnerSize) --n;
    593         }
    594       }
    595 
    596       m_innerSize = newInnerSize;
    597 
    598       // Re-allocate outer index structure if necessary
    599       if (outerChange == 0)
    600         return;
    601 
    602       StorageIndex *newOuterIndex = static_cast<StorageIndex*>(std::realloc(m_outerIndex, (m_outerSize + outerChange + 1) * sizeof(StorageIndex)));
    603       if (!newOuterIndex) internal::throw_std_bad_alloc();
    604       m_outerIndex = newOuterIndex;
    605       if (outerChange > 0)
    606       {
    607         StorageIndex last = m_outerSize == 0 ? 0 : m_outerIndex[m_outerSize];
    608         for(Index i=m_outerSize; i<m_outerSize+outerChange+1; i++)
    609           m_outerIndex[i] = last;
    610       }
    611       m_outerSize += outerChange;
    612     }
    613 
    614     /** Resizes the matrix to a \a rows x \a cols matrix and initializes it to zero.
    615       *
    616       * This function does not free the currently allocated memory. To release as much as memory as possible,
    617       * call \code mat.data().squeeze(); \endcode after resizing it.
    618       *
    619       * \sa reserve(), setZero()
    620       */
    621     void resize(Index rows, Index cols)
    622     {
    623       const Index outerSize = IsRowMajor ? rows : cols;
    624       m_innerSize = IsRowMajor ? cols : rows;
    625       m_data.clear();
    626       if (m_outerSize != outerSize || m_outerSize==0)
    627       {
    628         std::free(m_outerIndex);
    629         m_outerIndex = static_cast<StorageIndex*>(std::malloc((outerSize + 1) * sizeof(StorageIndex)));
    630         if (!m_outerIndex) internal::throw_std_bad_alloc();
    631 
    632         m_outerSize = outerSize;
    633       }
    634       if(m_innerNonZeros)
    635       {
    636         std::free(m_innerNonZeros);
    637         m_innerNonZeros = 0;
    638       }
    639       memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(StorageIndex));
    640     }
    641 
    642     /** \internal
    643       * Resize the nonzero vector to \a size */
    644     void resizeNonZeros(Index size)
    645     {
    646       m_data.resize(size);
    647     }
    648 
    649     /** \returns a const expression of the diagonal coefficients. */
    650     const ConstDiagonalReturnType diagonal() const { return ConstDiagonalReturnType(*this); }
    651 
    652     /** \returns a read-write expression of the diagonal coefficients.
    653       * \warning If the diagonal entries are written, then all diagonal
    654       * entries \b must already exist, otherwise an assertion will be raised.
    655       */
    656     DiagonalReturnType diagonal() { return DiagonalReturnType(*this); }
    657 
    658     /** Default constructor yielding an empty \c 0 \c x \c 0 matrix */
    659     inline SparseMatrix()
    660       : m_outerSize(-1), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
    661     {
    662       check_template_parameters();
    663       resize(0, 0);
    664     }
    665 
    666     /** Constructs a \a rows \c x \a cols empty matrix */
    667     inline SparseMatrix(Index rows, Index cols)
    668       : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
    669     {
    670       check_template_parameters();
    671       resize(rows, cols);
    672     }
    673 
    674     /** Constructs a sparse matrix from the sparse expression \a other */
    675     template<typename OtherDerived>
    676     inline SparseMatrix(const SparseMatrixBase<OtherDerived>& other)
    677       : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
    678     {
    679       EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
    680         YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
    681       check_template_parameters();
    682       const bool needToTranspose = (Flags & RowMajorBit) != (internal::evaluator<OtherDerived>::Flags & RowMajorBit);
    683       if (needToTranspose)
    684         *this = other.derived();
    685       else
    686       {
    687         #ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
    688           EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
    689         #endif
    690         internal::call_assignment_no_alias(*this, other.derived());
    691       }
    692     }
    693 
    694     /** Constructs a sparse matrix from the sparse selfadjoint view \a other */
    695     template<typename OtherDerived, unsigned int UpLo>
    696     inline SparseMatrix(const SparseSelfAdjointView<OtherDerived, UpLo>& other)
    697       : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
    698     {
    699       check_template_parameters();
    700       Base::operator=(other);
    701     }
    702 
    703     /** Copy constructor (it performs a deep copy) */
    704     inline SparseMatrix(const SparseMatrix& other)
    705       : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
    706     {
    707       check_template_parameters();
    708       *this = other.derived();
    709     }
    710 
    711     /** \brief Copy constructor with in-place evaluation */
    712     template<typename OtherDerived>
    713     SparseMatrix(const ReturnByValue<OtherDerived>& other)
    714       : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
    715     {
    716       check_template_parameters();
    717       initAssignment(other);
    718       other.evalTo(*this);
    719     }
    720 
    721     /** \brief Copy constructor with in-place evaluation */
    722     template<typename OtherDerived>
    723     explicit SparseMatrix(const DiagonalBase<OtherDerived>& other)
    724       : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
    725     {
    726       check_template_parameters();
    727       *this = other.derived();
    728     }
    729 
    730     /** Swaps the content of two sparse matrices of the same type.
    731       * This is a fast operation that simply swaps the underlying pointers and parameters. */
    732     inline void swap(SparseMatrix& other)
    733     {
    734       //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n");
    735       std::swap(m_outerIndex, other.m_outerIndex);
    736       std::swap(m_innerSize, other.m_innerSize);
    737       std::swap(m_outerSize, other.m_outerSize);
    738       std::swap(m_innerNonZeros, other.m_innerNonZeros);
    739       m_data.swap(other.m_data);
    740     }
    741 
    742     /** Sets *this to the identity matrix.
    743       * This function also turns the matrix into compressed mode, and drop any reserved memory. */
    744     inline void setIdentity()
    745     {
    746       eigen_assert(rows() == cols() && "ONLY FOR SQUARED MATRICES");
    747       this->m_data.resize(rows());
    748       Eigen::Map<IndexVector>(this->m_data.indexPtr(), rows()).setLinSpaced(0, StorageIndex(rows()-1));
    749       Eigen::Map<ScalarVector>(this->m_data.valuePtr(), rows()).setOnes();
    750       Eigen::Map<IndexVector>(this->m_outerIndex, rows()+1).setLinSpaced(0, StorageIndex(rows()));
    751       std::free(m_innerNonZeros);
    752       m_innerNonZeros = 0;
    753     }
    754     inline SparseMatrix& operator=(const SparseMatrix& other)
    755     {
    756       if (other.isRValue())
    757       {
    758         swap(other.const_cast_derived());
    759       }
    760       else if(this!=&other)
    761       {
    762         #ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
    763           EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
    764         #endif
    765         initAssignment(other);
    766         if(other.isCompressed())
    767         {
    768           internal::smart_copy(other.m_outerIndex, other.m_outerIndex + m_outerSize + 1, m_outerIndex);
    769           m_data = other.m_data;
    770         }
    771         else
    772         {
    773           Base::operator=(other);
    774         }
    775       }
    776       return *this;
    777     }
    778 
    779 #ifndef EIGEN_PARSED_BY_DOXYGEN
    780     template<typename OtherDerived>
    781     inline SparseMatrix& operator=(const EigenBase<OtherDerived>& other)
    782     { return Base::operator=(other.derived()); }
    783 #endif // EIGEN_PARSED_BY_DOXYGEN
    784 
    785     template<typename OtherDerived>
    786     EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other);
    787 
    788     friend std::ostream & operator << (std::ostream & s, const SparseMatrix& m)
    789     {
    790       EIGEN_DBG_SPARSE(
    791         s << "Nonzero entries:\n";
    792         if(m.isCompressed())
    793         {
    794           for (Index i=0; i<m.nonZeros(); ++i)
    795             s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
    796         }
    797         else
    798         {
    799           for (Index i=0; i<m.outerSize(); ++i)
    800           {
    801             Index p = m.m_outerIndex[i];
    802             Index pe = m.m_outerIndex[i]+m.m_innerNonZeros[i];
    803             Index k=p;
    804             for (; k<pe; ++k) {
    805               s << "(" << m.m_data.value(k) << "," << m.m_data.index(k) << ") ";
    806             }
    807             for (; k<m.m_outerIndex[i+1]; ++k) {
    808               s << "(_,_) ";
    809             }
    810           }
    811         }
    812         s << std::endl;
    813         s << std::endl;
    814         s << "Outer pointers:\n";
    815         for (Index i=0; i<m.outerSize(); ++i) {
    816           s << m.m_outerIndex[i] << " ";
    817         }
    818         s << " $" << std::endl;
    819         if(!m.isCompressed())
    820         {
    821           s << "Inner non zeros:\n";
    822           for (Index i=0; i<m.outerSize(); ++i) {
    823             s << m.m_innerNonZeros[i] << " ";
    824           }
    825           s << " $" << std::endl;
    826         }
    827         s << std::endl;
    828       );
    829       s << static_cast<const SparseMatrixBase<SparseMatrix>&>(m);
    830       return s;
    831     }
    832 
    833     /** Destructor */
    834     inline ~SparseMatrix()
    835     {
    836       std::free(m_outerIndex);
    837       std::free(m_innerNonZeros);
    838     }
    839 
    840     /** Overloaded for performance */
    841     Scalar sum() const;
    842 
    843 #   ifdef EIGEN_SPARSEMATRIX_PLUGIN
    844 #     include EIGEN_SPARSEMATRIX_PLUGIN
    845 #   endif
    846 
    847 protected:
    848 
    849     template<typename Other>
    850     void initAssignment(const Other& other)
    851     {
    852       resize(other.rows(), other.cols());
    853       if(m_innerNonZeros)
    854       {
    855         std::free(m_innerNonZeros);
    856         m_innerNonZeros = 0;
    857       }
    858     }
    859 
    860     /** \internal
    861       * \sa insert(Index,Index) */
    862     EIGEN_DONT_INLINE Scalar& insertCompressed(Index row, Index col);
    863 
    864     /** \internal
    865       * A vector object that is equal to 0 everywhere but v at the position i */
    866     class SingletonVector
    867     {
    868         StorageIndex m_index;
    869         StorageIndex m_value;
    870       public:
    871         typedef StorageIndex value_type;
    872         SingletonVector(Index i, Index v)
    873           : m_index(convert_index(i)), m_value(convert_index(v))
    874         {}
    875 
    876         StorageIndex operator[](Index i) const { return i==m_index ? m_value : 0; }
    877     };
    878 
    879     /** \internal
    880       * \sa insert(Index,Index) */
    881     EIGEN_DONT_INLINE Scalar& insertUncompressed(Index row, Index col);
    882 
    883 public:
    884     /** \internal
    885       * \sa insert(Index,Index) */
    886     EIGEN_STRONG_INLINE Scalar& insertBackUncompressed(Index row, Index col)
    887     {
    888       const Index outer = IsRowMajor ? row : col;
    889       const Index inner = IsRowMajor ? col : row;
    890 
    891       eigen_assert(!isCompressed());
    892       eigen_assert(m_innerNonZeros[outer]<=(m_outerIndex[outer+1] - m_outerIndex[outer]));
    893 
    894       Index p = m_outerIndex[outer] + m_innerNonZeros[outer]++;
    895       m_data.index(p) = convert_index(inner);
    896       return (m_data.value(p) = 0);
    897     }
    898 
    899 private:
    900   static void check_template_parameters()
    901   {
    902     EIGEN_STATIC_ASSERT(NumTraits<StorageIndex>::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE);
    903     EIGEN_STATIC_ASSERT((Options&(ColMajor|RowMajor))==Options,INVALID_MATRIX_TEMPLATE_PARAMETERS);
    904   }
    905 
    906   struct default_prunning_func {
    907     default_prunning_func(const Scalar& ref, const RealScalar& eps) : reference(ref), epsilon(eps) {}
    908     inline bool operator() (const Index&, const Index&, const Scalar& value) const
    909     {
    910       return !internal::isMuchSmallerThan(value, reference, epsilon);
    911     }
    912     Scalar reference;
    913     RealScalar epsilon;
    914   };
    915 };
    916 
    917 namespace internal {
    918 
    919 template<typename InputIterator, typename SparseMatrixType, typename DupFunctor>
    920 void set_from_triplets(const InputIterator& begin, const InputIterator& end, SparseMatrixType& mat, DupFunctor dup_func)
    921 {
    922   enum { IsRowMajor = SparseMatrixType::IsRowMajor };
    923   typedef typename SparseMatrixType::Scalar Scalar;
    924   typedef typename SparseMatrixType::StorageIndex StorageIndex;
    925   SparseMatrix<Scalar,IsRowMajor?ColMajor:RowMajor,StorageIndex> trMat(mat.rows(),mat.cols());
    926 
    927   if(begin!=end)
    928   {
    929     // pass 1: count the nnz per inner-vector
    930     typename SparseMatrixType::IndexVector wi(trMat.outerSize());
    931     wi.setZero();
    932     for(InputIterator it(begin); it!=end; ++it)
    933     {
    934       eigen_assert(it->row()>=0 && it->row()<mat.rows() && it->col()>=0 && it->col()<mat.cols());
    935       wi(IsRowMajor ? it->col() : it->row())++;
    936     }
    937 
    938     // pass 2: insert all the elements into trMat
    939     trMat.reserve(wi);
    940     for(InputIterator it(begin); it!=end; ++it)
    941       trMat.insertBackUncompressed(it->row(),it->col()) = it->value();
    942 
    943     // pass 3:
    944     trMat.collapseDuplicates(dup_func);
    945   }
    946 
    947   // pass 4: transposed copy -> implicit sorting
    948   mat = trMat;
    949 }
    950 
    951 }
    952 
    953 
    954 /** Fill the matrix \c *this with the list of \em triplets defined by the iterator range \a begin - \a end.
    955   *
    956   * A \em triplet is a tuple (i,j,value) defining a non-zero element.
    957   * The input list of triplets does not have to be sorted, and can contains duplicated elements.
    958   * In any case, the result is a \b sorted and \b compressed sparse matrix where the duplicates have been summed up.
    959   * This is a \em O(n) operation, with \em n the number of triplet elements.
    960   * The initial contents of \c *this is destroyed.
    961   * The matrix \c *this must be properly resized beforehand using the SparseMatrix(Index,Index) constructor,
    962   * or the resize(Index,Index) method. The sizes are not extracted from the triplet list.
    963   *
    964   * The \a InputIterators value_type must provide the following interface:
    965   * \code
    966   * Scalar value() const; // the value
    967   * Scalar row() const;   // the row index i
    968   * Scalar col() const;   // the column index j
    969   * \endcode
    970   * See for instance the Eigen::Triplet template class.
    971   *
    972   * Here is a typical usage example:
    973   * \code
    974     typedef Triplet<double> T;
    975     std::vector<T> tripletList;
    976     triplets.reserve(estimation_of_entries);
    977     for(...)
    978     {
    979       // ...
    980       tripletList.push_back(T(i,j,v_ij));
    981     }
    982     SparseMatrixType m(rows,cols);
    983     m.setFromTriplets(tripletList.begin(), tripletList.end());
    984     // m is ready to go!
    985   * \endcode
    986   *
    987   * \warning The list of triplets is read multiple times (at least twice). Therefore, it is not recommended to define
    988   * an abstract iterator over a complex data-structure that would be expensive to evaluate. The triplets should rather
    989   * be explicitely stored into a std::vector for instance.
    990   */
    991 template<typename Scalar, int _Options, typename _StorageIndex>
    992 template<typename InputIterators>
    993 void SparseMatrix<Scalar,_Options,_StorageIndex>::setFromTriplets(const InputIterators& begin, const InputIterators& end)
    994 {
    995   internal::set_from_triplets<InputIterators, SparseMatrix<Scalar,_Options,_StorageIndex> >(begin, end, *this, internal::scalar_sum_op<Scalar,Scalar>());
    996 }
    997 
    998 /** The same as setFromTriplets but when duplicates are met the functor \a dup_func is applied:
    999   * \code
   1000   * value = dup_func(OldValue, NewValue)
   1001   * \endcode
   1002   * Here is a C++11 example keeping the latest entry only:
   1003   * \code
   1004   * mat.setFromTriplets(triplets.begin(), triplets.end(), [] (const Scalar&,const Scalar &b) { return b; });
   1005   * \endcode
   1006   */
   1007 template<typename Scalar, int _Options, typename _StorageIndex>
   1008 template<typename InputIterators,typename DupFunctor>
   1009 void SparseMatrix<Scalar,_Options,_StorageIndex>::setFromTriplets(const InputIterators& begin, const InputIterators& end, DupFunctor dup_func)
   1010 {
   1011   internal::set_from_triplets<InputIterators, SparseMatrix<Scalar,_Options,_StorageIndex>, DupFunctor>(begin, end, *this, dup_func);
   1012 }
   1013 
   1014 /** \internal */
   1015 template<typename Scalar, int _Options, typename _StorageIndex>
   1016 template<typename DupFunctor>
   1017 void SparseMatrix<Scalar,_Options,_StorageIndex>::collapseDuplicates(DupFunctor dup_func)
   1018 {
   1019   eigen_assert(!isCompressed());
   1020   // TODO, in practice we should be able to use m_innerNonZeros for that task
   1021   IndexVector wi(innerSize());
   1022   wi.fill(-1);
   1023   StorageIndex count = 0;
   1024   // for each inner-vector, wi[inner_index] will hold the position of first element into the index/value buffers
   1025   for(Index j=0; j<outerSize(); ++j)
   1026   {
   1027     StorageIndex start   = count;
   1028     Index oldEnd  = m_outerIndex[j]+m_innerNonZeros[j];
   1029     for(Index k=m_outerIndex[j]; k<oldEnd; ++k)
   1030     {
   1031       Index i = m_data.index(k);
   1032       if(wi(i)>=start)
   1033       {
   1034         // we already meet this entry => accumulate it
   1035         m_data.value(wi(i)) = dup_func(m_data.value(wi(i)), m_data.value(k));
   1036       }
   1037       else
   1038       {
   1039         m_data.value(count) = m_data.value(k);
   1040         m_data.index(count) = m_data.index(k);
   1041         wi(i) = count;
   1042         ++count;
   1043       }
   1044     }
   1045     m_outerIndex[j] = start;
   1046   }
   1047   m_outerIndex[m_outerSize] = count;
   1048 
   1049   // turn the matrix into compressed form
   1050   std::free(m_innerNonZeros);
   1051   m_innerNonZeros = 0;
   1052   m_data.resize(m_outerIndex[m_outerSize]);
   1053 }
   1054 
   1055 template<typename Scalar, int _Options, typename _StorageIndex>
   1056 template<typename OtherDerived>
   1057 EIGEN_DONT_INLINE SparseMatrix<Scalar,_Options,_StorageIndex>& SparseMatrix<Scalar,_Options,_StorageIndex>::operator=(const SparseMatrixBase<OtherDerived>& other)
   1058 {
   1059   EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
   1060         YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
   1061 
   1062   #ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
   1063     EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
   1064   #endif
   1065 
   1066   const bool needToTranspose = (Flags & RowMajorBit) != (internal::evaluator<OtherDerived>::Flags & RowMajorBit);
   1067   if (needToTranspose)
   1068   {
   1069     #ifdef EIGEN_SPARSE_TRANSPOSED_COPY_PLUGIN
   1070       EIGEN_SPARSE_TRANSPOSED_COPY_PLUGIN
   1071     #endif
   1072     // two passes algorithm:
   1073     //  1 - compute the number of coeffs per dest inner vector
   1074     //  2 - do the actual copy/eval
   1075     // Since each coeff of the rhs has to be evaluated twice, let's evaluate it if needed
   1076     typedef typename internal::nested_eval<OtherDerived,2,typename internal::plain_matrix_type<OtherDerived>::type >::type OtherCopy;
   1077     typedef typename internal::remove_all<OtherCopy>::type _OtherCopy;
   1078     typedef internal::evaluator<_OtherCopy> OtherCopyEval;
   1079     OtherCopy otherCopy(other.derived());
   1080     OtherCopyEval otherCopyEval(otherCopy);
   1081 
   1082     SparseMatrix dest(other.rows(),other.cols());
   1083     Eigen::Map<IndexVector> (dest.m_outerIndex,dest.outerSize()).setZero();
   1084 
   1085     // pass 1
   1086     // FIXME the above copy could be merged with that pass
   1087     for (Index j=0; j<otherCopy.outerSize(); ++j)
   1088       for (typename OtherCopyEval::InnerIterator it(otherCopyEval, j); it; ++it)
   1089         ++dest.m_outerIndex[it.index()];
   1090 
   1091     // prefix sum
   1092     StorageIndex count = 0;
   1093     IndexVector positions(dest.outerSize());
   1094     for (Index j=0; j<dest.outerSize(); ++j)
   1095     {
   1096       StorageIndex tmp = dest.m_outerIndex[j];
   1097       dest.m_outerIndex[j] = count;
   1098       positions[j] = count;
   1099       count += tmp;
   1100     }
   1101     dest.m_outerIndex[dest.outerSize()] = count;
   1102     // alloc
   1103     dest.m_data.resize(count);
   1104     // pass 2
   1105     for (StorageIndex j=0; j<otherCopy.outerSize(); ++j)
   1106     {
   1107       for (typename OtherCopyEval::InnerIterator it(otherCopyEval, j); it; ++it)
   1108       {
   1109         Index pos = positions[it.index()]++;
   1110         dest.m_data.index(pos) = j;
   1111         dest.m_data.value(pos) = it.value();
   1112       }
   1113     }
   1114     this->swap(dest);
   1115     return *this;
   1116   }
   1117   else
   1118   {
   1119     if(other.isRValue())
   1120     {
   1121       initAssignment(other.derived());
   1122     }
   1123     // there is no special optimization
   1124     return Base::operator=(other.derived());
   1125   }
   1126 }
   1127 
   1128 template<typename _Scalar, int _Options, typename _StorageIndex>
   1129 typename SparseMatrix<_Scalar,_Options,_StorageIndex>::Scalar& SparseMatrix<_Scalar,_Options,_StorageIndex>::insert(Index row, Index col)
   1130 {
   1131   eigen_assert(row>=0 && row<rows() && col>=0 && col<cols());
   1132 
   1133   const Index outer = IsRowMajor ? row : col;
   1134   const Index inner = IsRowMajor ? col : row;
   1135 
   1136   if(isCompressed())
   1137   {
   1138     if(nonZeros()==0)
   1139     {
   1140       // reserve space if not already done
   1141       if(m_data.allocatedSize()==0)
   1142         m_data.reserve(2*m_innerSize);
   1143 
   1144       // turn the matrix into non-compressed mode
   1145       m_innerNonZeros = static_cast<StorageIndex*>(std::malloc(m_outerSize * sizeof(StorageIndex)));
   1146       if(!m_innerNonZeros) internal::throw_std_bad_alloc();
   1147 
   1148       memset(m_innerNonZeros, 0, (m_outerSize)*sizeof(StorageIndex));
   1149 
   1150       // pack all inner-vectors to the end of the pre-allocated space
   1151       // and allocate the entire free-space to the first inner-vector
   1152       StorageIndex end = convert_index(m_data.allocatedSize());
   1153       for(Index j=1; j<=m_outerSize; ++j)
   1154         m_outerIndex[j] = end;
   1155     }
   1156     else
   1157     {
   1158       // turn the matrix into non-compressed mode
   1159       m_innerNonZeros = static_cast<StorageIndex*>(std::malloc(m_outerSize * sizeof(StorageIndex)));
   1160       if(!m_innerNonZeros) internal::throw_std_bad_alloc();
   1161       for(Index j=0; j<m_outerSize; ++j)
   1162         m_innerNonZeros[j] = m_outerIndex[j+1]-m_outerIndex[j];
   1163     }
   1164   }
   1165 
   1166   // check whether we can do a fast "push back" insertion
   1167   Index data_end = m_data.allocatedSize();
   1168 
   1169   // First case: we are filling a new inner vector which is packed at the end.
   1170   // We assume that all remaining inner-vectors are also empty and packed to the end.
   1171   if(m_outerIndex[outer]==data_end)
   1172   {
   1173     eigen_internal_assert(m_innerNonZeros[outer]==0);
   1174 
   1175     // pack previous empty inner-vectors to end of the used-space
   1176     // and allocate the entire free-space to the current inner-vector.
   1177     StorageIndex p = convert_index(m_data.size());
   1178     Index j = outer;
   1179     while(j>=0 && m_innerNonZeros[j]==0)
   1180       m_outerIndex[j--] = p;
   1181 
   1182     // push back the new element
   1183     ++m_innerNonZeros[outer];
   1184     m_data.append(Scalar(0), inner);
   1185 
   1186     // check for reallocation
   1187     if(data_end != m_data.allocatedSize())
   1188     {
   1189       // m_data has been reallocated
   1190       //  -> move remaining inner-vectors back to the end of the free-space
   1191       //     so that the entire free-space is allocated to the current inner-vector.
   1192       eigen_internal_assert(data_end < m_data.allocatedSize());
   1193       StorageIndex new_end = convert_index(m_data.allocatedSize());
   1194       for(Index k=outer+1; k<=m_outerSize; ++k)
   1195         if(m_outerIndex[k]==data_end)
   1196           m_outerIndex[k] = new_end;
   1197     }
   1198     return m_data.value(p);
   1199   }
   1200 
   1201   // Second case: the next inner-vector is packed to the end
   1202   // and the current inner-vector end match the used-space.
   1203   if(m_outerIndex[outer+1]==data_end && m_outerIndex[outer]+m_innerNonZeros[outer]==m_data.size())
   1204   {
   1205     eigen_internal_assert(outer+1==m_outerSize || m_innerNonZeros[outer+1]==0);
   1206 
   1207     // add space for the new element
   1208     ++m_innerNonZeros[outer];
   1209     m_data.resize(m_data.size()+1);
   1210 
   1211     // check for reallocation
   1212     if(data_end != m_data.allocatedSize())
   1213     {
   1214       // m_data has been reallocated
   1215       //  -> move remaining inner-vectors back to the end of the free-space
   1216       //     so that the entire free-space is allocated to the current inner-vector.
   1217       eigen_internal_assert(data_end < m_data.allocatedSize());
   1218       StorageIndex new_end = convert_index(m_data.allocatedSize());
   1219       for(Index k=outer+1; k<=m_outerSize; ++k)
   1220         if(m_outerIndex[k]==data_end)
   1221           m_outerIndex[k] = new_end;
   1222     }
   1223 
   1224     // and insert it at the right position (sorted insertion)
   1225     Index startId = m_outerIndex[outer];
   1226     Index p = m_outerIndex[outer]+m_innerNonZeros[outer]-1;
   1227     while ( (p > startId) && (m_data.index(p-1) > inner) )
   1228     {
   1229       m_data.index(p) = m_data.index(p-1);
   1230       m_data.value(p) = m_data.value(p-1);
   1231       --p;
   1232     }
   1233 
   1234     m_data.index(p) = convert_index(inner);
   1235     return (m_data.value(p) = 0);
   1236   }
   1237 
   1238   if(m_data.size() != m_data.allocatedSize())
   1239   {
   1240     // make sure the matrix is compatible to random un-compressed insertion:
   1241     m_data.resize(m_data.allocatedSize());
   1242     this->reserveInnerVectors(Array<StorageIndex,Dynamic,1>::Constant(m_outerSize, 2));
   1243   }
   1244 
   1245   return insertUncompressed(row,col);
   1246 }
   1247 
   1248 template<typename _Scalar, int _Options, typename _StorageIndex>
   1249 EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_StorageIndex>::Scalar& SparseMatrix<_Scalar,_Options,_StorageIndex>::insertUncompressed(Index row, Index col)
   1250 {
   1251   eigen_assert(!isCompressed());
   1252 
   1253   const Index outer = IsRowMajor ? row : col;
   1254   const StorageIndex inner = convert_index(IsRowMajor ? col : row);
   1255 
   1256   Index room = m_outerIndex[outer+1] - m_outerIndex[outer];
   1257   StorageIndex innerNNZ = m_innerNonZeros[outer];
   1258   if(innerNNZ>=room)
   1259   {
   1260     // this inner vector is full, we need to reallocate the whole buffer :(
   1261     reserve(SingletonVector(outer,std::max<StorageIndex>(2,innerNNZ)));
   1262   }
   1263 
   1264   Index startId = m_outerIndex[outer];
   1265   Index p = startId + m_innerNonZeros[outer];
   1266   while ( (p > startId) && (m_data.index(p-1) > inner) )
   1267   {
   1268     m_data.index(p) = m_data.index(p-1);
   1269     m_data.value(p) = m_data.value(p-1);
   1270     --p;
   1271   }
   1272   eigen_assert((p<=startId || m_data.index(p-1)!=inner) && "you cannot insert an element that already exists, you must call coeffRef to this end");
   1273 
   1274   m_innerNonZeros[outer]++;
   1275 
   1276   m_data.index(p) = inner;
   1277   return (m_data.value(p) = 0);
   1278 }
   1279 
   1280 template<typename _Scalar, int _Options, typename _StorageIndex>
   1281 EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_StorageIndex>::Scalar& SparseMatrix<_Scalar,_Options,_StorageIndex>::insertCompressed(Index row, Index col)
   1282 {
   1283   eigen_assert(isCompressed());
   1284 
   1285   const Index outer = IsRowMajor ? row : col;
   1286   const Index inner = IsRowMajor ? col : row;
   1287 
   1288   Index previousOuter = outer;
   1289   if (m_outerIndex[outer+1]==0)
   1290   {
   1291     // we start a new inner vector
   1292     while (previousOuter>=0 && m_outerIndex[previousOuter]==0)
   1293     {
   1294       m_outerIndex[previousOuter] = convert_index(m_data.size());
   1295       --previousOuter;
   1296     }
   1297     m_outerIndex[outer+1] = m_outerIndex[outer];
   1298   }
   1299 
   1300   // here we have to handle the tricky case where the outerIndex array
   1301   // starts with: [ 0 0 0 0 0 1 ...] and we are inserted in, e.g.,
   1302   // the 2nd inner vector...
   1303   bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0))
   1304                 && (std::size_t(m_outerIndex[outer+1]) == m_data.size());
   1305 
   1306   std::size_t startId = m_outerIndex[outer];
   1307   // FIXME let's make sure sizeof(long int) == sizeof(std::size_t)
   1308   std::size_t p = m_outerIndex[outer+1];
   1309   ++m_outerIndex[outer+1];
   1310 
   1311   double reallocRatio = 1;
   1312   if (m_data.allocatedSize()<=m_data.size())
   1313   {
   1314     // if there is no preallocated memory, let's reserve a minimum of 32 elements
   1315     if (m_data.size()==0)
   1316     {
   1317       m_data.reserve(32);
   1318     }
   1319     else
   1320     {
   1321       // we need to reallocate the data, to reduce multiple reallocations
   1322       // we use a smart resize algorithm based on the current filling ratio
   1323       // in addition, we use double to avoid integers overflows
   1324       double nnzEstimate = double(m_outerIndex[outer])*double(m_outerSize)/double(outer+1);
   1325       reallocRatio = (nnzEstimate-double(m_data.size()))/double(m_data.size());
   1326       // furthermore we bound the realloc ratio to:
   1327       //   1) reduce multiple minor realloc when the matrix is almost filled
   1328       //   2) avoid to allocate too much memory when the matrix is almost empty
   1329       reallocRatio = (std::min)((std::max)(reallocRatio,1.5),8.);
   1330     }
   1331   }
   1332   m_data.resize(m_data.size()+1,reallocRatio);
   1333 
   1334   if (!isLastVec)
   1335   {
   1336     if (previousOuter==-1)
   1337     {
   1338       // oops wrong guess.
   1339       // let's correct the outer offsets
   1340       for (Index k=0; k<=(outer+1); ++k)
   1341         m_outerIndex[k] = 0;
   1342       Index k=outer+1;
   1343       while(m_outerIndex[k]==0)
   1344         m_outerIndex[k++] = 1;
   1345       while (k<=m_outerSize && m_outerIndex[k]!=0)
   1346         m_outerIndex[k++]++;
   1347       p = 0;
   1348       --k;
   1349       k = m_outerIndex[k]-1;
   1350       while (k>0)
   1351       {
   1352         m_data.index(k) = m_data.index(k-1);
   1353         m_data.value(k) = m_data.value(k-1);
   1354         k--;
   1355       }
   1356     }
   1357     else
   1358     {
   1359       // we are not inserting into the last inner vec
   1360       // update outer indices:
   1361       Index j = outer+2;
   1362       while (j<=m_outerSize && m_outerIndex[j]!=0)
   1363         m_outerIndex[j++]++;
   1364       --j;
   1365       // shift data of last vecs:
   1366       Index k = m_outerIndex[j]-1;
   1367       while (k>=Index(p))
   1368       {
   1369         m_data.index(k) = m_data.index(k-1);
   1370         m_data.value(k) = m_data.value(k-1);
   1371         k--;
   1372       }
   1373     }
   1374   }
   1375 
   1376   while ( (p > startId) && (m_data.index(p-1) > inner) )
   1377   {
   1378     m_data.index(p) = m_data.index(p-1);
   1379     m_data.value(p) = m_data.value(p-1);
   1380     --p;
   1381   }
   1382 
   1383   m_data.index(p) = inner;
   1384   return (m_data.value(p) = 0);
   1385 }
   1386 
   1387 namespace internal {
   1388 
   1389 template<typename _Scalar, int _Options, typename _StorageIndex>
   1390 struct evaluator<SparseMatrix<_Scalar,_Options,_StorageIndex> >
   1391   : evaluator<SparseCompressedBase<SparseMatrix<_Scalar,_Options,_StorageIndex> > >
   1392 {
   1393   typedef evaluator<SparseCompressedBase<SparseMatrix<_Scalar,_Options,_StorageIndex> > > Base;
   1394   typedef SparseMatrix<_Scalar,_Options,_StorageIndex> SparseMatrixType;
   1395   evaluator() : Base() {}
   1396   explicit evaluator(const SparseMatrixType &mat) : Base(mat) {}
   1397 };
   1398 
   1399 }
   1400 
   1401 } // end namespace Eigen
   1402 
   1403 #endif // EIGEN_SPARSEMATRIX_H
   1404