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