1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef EIGEN_SPARSEMATRIX_H
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_SPARSEMATRIX_H
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace Eigen {
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \ingroup SparseCore_Module
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \class SparseMatrix
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \brief A versatible sparse matrix representation
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * This class implements a more versatile variants of the common \em compressed row/column storage format.
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * Each colmun's (resp. row) non zeros are stored as a pair of value with associated row (resp. colmiun) index.
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * All the non zeros are stored in a single large buffer. Unlike the \em compressed format, there might be extra
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * space inbetween the nonzeros of two successive colmuns (resp. rows) such that insertion of new non-zero
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * can be done with limited memory reallocation and copies.
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * A call to the function makeCompressed() turns the matrix into the standard \em compressed format
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * compatible with many library.
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * More details on this storage sceheme are given in the \ref TutorialSparse "manual pages".
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \tparam _Scalar the scalar type, i.e. the type of the coefficients
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \tparam _Options Union of bit flags controlling the storage scheme. Currently the only possibility
347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  *                 is ColMajor or RowMajor. The default is 0 which means column-major.
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \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.
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * This class can be extended with the help of the plugin mechanism described on the page
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_SPARSEMATRIX_PLUGIN.
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  */
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace internal {
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar, int _Options, typename _Index>
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct traits<SparseMatrix<_Scalar, _Options, _Index> >
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef _Scalar Scalar;
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef _Index Index;
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Sparse StorageKind;
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef MatrixXpr XprKind;
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  enum {
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    RowsAtCompileTime = Dynamic,
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ColsAtCompileTime = Dynamic,
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    MaxRowsAtCompileTime = Dynamic,
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    MaxColsAtCompileTime = Dynamic,
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Flags = _Options | NestByRefBit | LvalueBit,
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CoeffReadCost = NumTraits<Scalar>::ReadCost,
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SupportedAccessPatterns = InnerRandomAccessPattern
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  };
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar, int _Options, typename _Index, int DiagIndex>
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct traits<Diagonal<const SparseMatrix<_Scalar, _Options, _Index>, DiagIndex> >
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef SparseMatrix<_Scalar, _Options, _Index> MatrixType;
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename nested<MatrixType>::type MatrixTypeNested;
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef _Scalar Scalar;
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Dense StorageKind;
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef _Index Index;
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef MatrixXpr XprKind;
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  enum {
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    RowsAtCompileTime = Dynamic,
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ColsAtCompileTime = 1,
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    MaxRowsAtCompileTime = Dynamic,
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    MaxColsAtCompileTime = 1,
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Flags = 0,
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CoeffReadCost = _MatrixTypeNested::CoeffReadCost*10
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  };
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace internal
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar, int _Options, typename _Index>
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass SparseMatrix
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  : public SparseMatrixBase<SparseMatrix<_Scalar, _Options, _Index> >
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_SPARSE_PUBLIC_INTERFACE(SparseMatrix)
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, +=)
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, -=)
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef MappedSparseMatrix<Scalar,Flags> Map;
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    using Base::IsRowMajor;
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef internal::CompressedStorage<Scalar,Index> Storage;
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    enum {
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Options = _Options
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    };
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef SparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0)> TransposedSparseMatrix;
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_outerSize;
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_innerSize;
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index* m_outerIndex;
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index* m_innerNonZeros;     // optional, if null then the data is compressed
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Storage m_data;
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Eigen::Map<Matrix<Index,Dynamic,1> > innerNonZeros() { return Eigen::Map<Matrix<Index,Dynamic,1> >(m_innerNonZeros, m_innerNonZeros?m_outerSize:0); }
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    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); }
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns whether \c *this is in compressed form. */
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline bool isCompressed() const { return m_innerNonZeros==0; }
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns the number of rows of the matrix */
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns the number of columns of the matrix */
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns the number of rows (resp. columns) of the matrix if the storage order column major (resp. row major) */
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index innerSize() const { return m_innerSize; }
125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns the number of columns (resp. rows) of the matrix if the storage order column major (resp. row major) */
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index outerSize() const { return m_outerSize; }
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a const pointer to the array of values.
129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function is aimed at interoperability with other libraries.
130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa innerIndexPtr(), outerIndexPtr() */
131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const Scalar* valuePtr() const { return &m_data.value(0); }
132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a non-const pointer to the array of values.
133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function is aimed at interoperability with other libraries.
134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa innerIndexPtr(), outerIndexPtr() */
135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Scalar* valuePtr() { return &m_data.value(0); }
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a const pointer to the array of inner indices.
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function is aimed at interoperability with other libraries.
139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa valuePtr(), outerIndexPtr() */
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const Index* innerIndexPtr() const { return &m_data.index(0); }
141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a non-const pointer to the array of inner indices.
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function is aimed at interoperability with other libraries.
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa valuePtr(), outerIndexPtr() */
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index* innerIndexPtr() { return &m_data.index(0); }
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a const pointer to the array of the starting positions of the inner vectors.
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function is aimed at interoperability with other libraries.
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa valuePtr(), innerIndexPtr() */
149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const Index* outerIndexPtr() const { return m_outerIndex; }
150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a non-const pointer to the array of the starting positions of the inner vectors.
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function is aimed at interoperability with other libraries.
152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa valuePtr(), innerIndexPtr() */
153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index* outerIndexPtr() { return m_outerIndex; }
154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a const pointer to the array of the number of non zeros of the inner vectors.
156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function is aimed at interoperability with other libraries.
157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \warning it returns the null pointer 0 in compressed mode */
158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const Index* innerNonZeroPtr() const { return m_innerNonZeros; }
159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a non-const pointer to the array of the number of non zeros of the inner vectors.
160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function is aimed at interoperability with other libraries.
161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \warning it returns the null pointer 0 in compressed mode */
162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index* innerNonZeroPtr() { return m_innerNonZeros; }
163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal */
165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Storage& data() { return m_data; }
166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal */
167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const Storage& data() const { return m_data; }
168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns the value of the matrix at position \a i, \a j
170c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function returns Scalar(0) if the element is an explicit \em zero */
171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Scalar coeff(Index row, Index col) const
172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
1737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(row>=0 && row<rows() && col>=0 && col<cols());
1747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      const Index outer = IsRowMajor ? row : col;
176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      const Index inner = IsRowMajor ? col : row;
177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index end = m_innerNonZeros ? m_outerIndex[outer] + m_innerNonZeros[outer] : m_outerIndex[outer+1];
178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return m_data.atInRange(m_outerIndex[outer], end, inner);
179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a non-const reference to the value of the matrix at position \a i, \a j
182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * If the element does not exist then it is inserted via the insert(Index,Index) function
184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * which itself turns the matrix into a non compressed form if that was not the case.
185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This is a O(log(nnz_j)) operation (binary search) plus the cost of insert(Index,Index)
187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * function if the element does not already exist.
188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      */
189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Scalar& coeffRef(Index row, Index col)
190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
1917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(row>=0 && row<rows() && col>=0 && col<cols());
1927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      const Index outer = IsRowMajor ? row : col;
194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      const Index inner = IsRowMajor ? col : row;
195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index start = m_outerIndex[outer];
197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index end = m_innerNonZeros ? m_outerIndex[outer] + m_innerNonZeros[outer] : m_outerIndex[outer+1];
198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(end<=start)
200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        return insert(row,col);
201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      const Index p = m_data.searchLowerIndex(start,end-1,inner);
202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if((p<end) && (m_data.index(p)==inner))
203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        return m_data.value(p);
204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        return insert(row,col);
206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a reference to a novel non zero coefficient with coordinates \a row x \a col.
209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * The non zero coefficient must \b not already exist.
210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * If the matrix \c *this is in compressed mode, then \c *this is turned into uncompressed
212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * mode while reserving room for 2 non zeros per inner vector. It is strongly recommended to first
213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * call reserve(const SizesType &) to reserve a more appropriate number of elements per
214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * inner vector that better match your scenario.
215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function performs a sorted insertion in O(1) if the elements of each inner vector are
217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * inserted in increasing inner index order, and in O(nnz_j) for a random insertion.
218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      */
2207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Scalar& insert(Index row, Index col)
221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
2227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(row>=0 && row<rows() && col>=0 && col<cols());
2237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(isCompressed())
225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
2267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        reserve(Matrix<Index,Dynamic,1>::Constant(outerSize(), 2));
227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return insertUncompressed(row,col);
229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    class InnerIterator;
234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    class ReverseInnerIterator;
235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Removes all non zeros but keep allocated memory */
237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void setZero()
238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.clear();
240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(Index));
241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(m_innerNonZeros)
242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        memset(m_innerNonZeros, 0, (m_outerSize)*sizeof(Index));
243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns the number of non zero coefficients */
246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index nonZeros() const
247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
248c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(m_innerNonZeros)
249c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        return innerNonZeros().sum();
250c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return static_cast<Index>(m_data.size());
251c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
252c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
253c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Preallocates \a reserveSize non zeros.
254c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
255c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * Precondition: the matrix must be in compressed mode. */
256c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void reserve(Index reserveSize)
257c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
258c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      eigen_assert(isCompressed() && "This function does not make sense in non compressed mode.");
259c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.reserve(reserveSize);
260c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
261c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
262c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    #ifdef EIGEN_PARSED_BY_DOXYGEN
263c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Preallocates \a reserveSize[\c j] non zeros for each column (resp. row) \c j.
264c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
265c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This function turns the matrix in non-compressed mode */
266c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<class SizesType>
267c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void reserve(const SizesType& reserveSizes);
268c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    #else
269c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<class SizesType>
270c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void reserve(const SizesType& reserveSizes, const typename SizesType::value_type& enableif = typename SizesType::value_type())
271c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
272c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      EIGEN_UNUSED_VARIABLE(enableif);
273c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      reserveInnerVectors(reserveSizes);
274c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
275c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<class SizesType>
276c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void reserve(const SizesType& reserveSizes, const typename SizesType::Scalar& enableif =
277c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    #if (!defined(_MSC_VER)) || (_MSC_VER>=1500) // MSVC 2005 fails to compile with this typename
278c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        typename
279c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    #endif
280c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        SizesType::Scalar())
281c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
282c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      EIGEN_UNUSED_VARIABLE(enableif);
283c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      reserveInnerVectors(reserveSizes);
284c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
285c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    #endif // EIGEN_PARSED_BY_DOXYGEN
286c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
287c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<class SizesType>
288c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void reserveInnerVectors(const SizesType& reserveSizes)
289c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
290c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(isCompressed())
291c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
292c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        std::size_t totalReserveSize = 0;
293c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        // turn the matrix into non-compressed mode
2947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_innerNonZeros = static_cast<Index*>(std::malloc(m_outerSize * sizeof(Index)));
2957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if (!m_innerNonZeros) internal::throw_std_bad_alloc();
296c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
297c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        // temporarily use m_innerSizes to hold the new starting points.
298c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index* newOuterIndex = m_innerNonZeros;
299c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
300c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index count = 0;
301c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        for(Index j=0; j<m_outerSize; ++j)
302c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
303c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          newOuterIndex[j] = count;
304c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          count += reserveSizes[j] + (m_outerIndex[j+1]-m_outerIndex[j]);
305c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          totalReserveSize += reserveSizes[j];
306c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
307c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_data.reserve(totalReserveSize);
3087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        Index previousOuterIndex = m_outerIndex[m_outerSize];
3097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        for(Index j=m_outerSize-1; j>=0; --j)
310c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
3117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          Index innerNNZ = previousOuterIndex - m_outerIndex[j];
3127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          for(Index i=innerNNZ-1; i>=0; --i)
313c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          {
314c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            m_data.index(newOuterIndex[j]+i) = m_data.index(m_outerIndex[j]+i);
315c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            m_data.value(newOuterIndex[j]+i) = m_data.value(m_outerIndex[j]+i);
316c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          }
317c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          previousOuterIndex = m_outerIndex[j];
318c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_outerIndex[j] = newOuterIndex[j];
319c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_innerNonZeros[j] = innerNNZ;
320c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
321c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_outerIndex[m_outerSize] = m_outerIndex[m_outerSize-1] + m_innerNonZeros[m_outerSize-1] + reserveSizes[m_outerSize-1];
322c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
323c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_data.resize(m_outerIndex[m_outerSize]);
324c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
325c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
326c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
3277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        Index* newOuterIndex = static_cast<Index*>(std::malloc((m_outerSize+1)*sizeof(Index)));
3287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if (!newOuterIndex) internal::throw_std_bad_alloc();
3297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
330c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index count = 0;
331c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        for(Index j=0; j<m_outerSize; ++j)
332c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
333c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          newOuterIndex[j] = count;
334c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          Index alreadyReserved = (m_outerIndex[j+1]-m_outerIndex[j]) - m_innerNonZeros[j];
3357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          Index toReserve = std::max<Index>(reserveSizes[j], alreadyReserved);
336c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          count += toReserve + m_innerNonZeros[j];
337c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
338c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        newOuterIndex[m_outerSize] = count;
339c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
340c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_data.resize(count);
3417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        for(Index j=m_outerSize-1; j>=0; --j)
342c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
3437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          Index offset = newOuterIndex[j] - m_outerIndex[j];
344c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          if(offset>0)
345c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          {
3467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            Index innerNNZ = m_innerNonZeros[j];
3477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            for(Index i=innerNNZ-1; i>=0; --i)
348c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            {
349c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              m_data.index(newOuterIndex[j]+i) = m_data.index(m_outerIndex[j]+i);
350c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              m_data.value(newOuterIndex[j]+i) = m_data.value(m_outerIndex[j]+i);
351c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            }
352c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          }
353c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
354c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
355c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        std::swap(m_outerIndex, newOuterIndex);
3567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        std::free(newOuterIndex);
357c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
358c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
359c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
360c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
361c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
362c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    //--- low level purely coherent filling ---
363c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
364c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
365c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \returns a reference to the non zero coefficient at position \a row, \a col assuming that:
366c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * - the nonzero does not already exist
367c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * - the new coefficient is the last one according to the storage order
368c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
369c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * Before filling a given inner vector you must call the statVec(Index) function.
370c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
371c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * After an insertion session, you should call the finalize() function.
372c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *
373c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa insert, insertBackByOuterInner, startVec */
374c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Scalar& insertBack(Index row, Index col)
375c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
376c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return insertBackByOuterInner(IsRowMajor?row:col, IsRowMajor?col:row);
377c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
378c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
379c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
380c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa insertBack, startVec */
381c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Scalar& insertBackByOuterInner(Index outer, Index inner)
382c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
383c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      eigen_assert(size_t(m_outerIndex[outer+1]) == m_data.size() && "Invalid ordered insertion (invalid outer index)");
384c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      eigen_assert( (m_outerIndex[outer+1]-m_outerIndex[outer]==0 || m_data.index(m_data.size()-1)<inner) && "Invalid ordered insertion (invalid inner index)");
385c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index p = m_outerIndex[outer+1];
386c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      ++m_outerIndex[outer+1];
387c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.append(0, inner);
388c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return m_data.value(p);
389c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
390c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
391c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
392c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \warning use it only if you know what you are doing */
393c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Scalar& insertBackByOuterInnerUnordered(Index outer, Index inner)
394c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
395c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index p = m_outerIndex[outer+1];
396c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      ++m_outerIndex[outer+1];
397c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.append(0, inner);
398c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return m_data.value(p);
399c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
400c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
401c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
402c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa insertBack, insertBackByOuterInner */
403c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void startVec(Index outer)
404c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
4057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(m_outerIndex[outer]==Index(m_data.size()) && "You must call startVec for each inner vector sequentially");
406c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      eigen_assert(m_outerIndex[outer+1]==0 && "You must call startVec for each inner vector sequentially");
407c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_outerIndex[outer+1] = m_outerIndex[outer];
408c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
409c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
410c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
411c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * Must be called after inserting a set of non zero entries using the low level compressed API.
412c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      */
413c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void finalize()
414c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
415c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(isCompressed())
416c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
417c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index size = static_cast<Index>(m_data.size());
418c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index i = m_outerSize;
419c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        // find the last filled column
420c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        while (i>=0 && m_outerIndex[i]==0)
421c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          --i;
422c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ++i;
423c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        while (i<=m_outerSize)
424c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
425c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_outerIndex[i] = size;
426c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          ++i;
427c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
428c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
429c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
430c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
431c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    //---
432c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
433c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename InputIterators>
434c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void setFromTriplets(const InputIterators& begin, const InputIterators& end);
435c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
436c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void sumupDuplicates();
437c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
438c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    //---
439c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
440c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
441c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * same as insert(Index,Index) except that the indices are given relative to the storage order */
4427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Scalar& insertByOuterInner(Index j, Index i)
443c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
444c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return insert(IsRowMajor ? j : i, IsRowMajor ? i : j);
445c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
446c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
447c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Turns the matrix into the \em compressed format.
448c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      */
449c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void makeCompressed()
450c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
451c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(isCompressed())
452c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        return;
453c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
454c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index oldStart = m_outerIndex[1];
455c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_outerIndex[1] = m_innerNonZeros[0];
456c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for(Index j=1; j<m_outerSize; ++j)
457c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
458c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index nextOldStart = m_outerIndex[j+1];
4597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        Index offset = oldStart - m_outerIndex[j];
460c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if(offset>0)
461c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
462c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          for(Index k=0; k<m_innerNonZeros[j]; ++k)
463c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          {
464c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            m_data.index(m_outerIndex[j]+k) = m_data.index(oldStart+k);
465c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            m_data.value(m_outerIndex[j]+k) = m_data.value(oldStart+k);
466c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          }
467c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
468c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_outerIndex[j+1] = m_outerIndex[j] + m_innerNonZeros[j];
469c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        oldStart = nextOldStart;
470c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
4717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      std::free(m_innerNonZeros);
472c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_innerNonZeros = 0;
473c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.resize(m_outerIndex[m_outerSize]);
474c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.squeeze();
475c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
476c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
4777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /** Turns the matrix into the uncompressed mode */
4787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    void uncompress()
4797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
4807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if(m_innerNonZeros != 0)
4817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        return;
4827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      m_innerNonZeros = static_cast<Index*>(std::malloc(m_outerSize * sizeof(Index)));
4837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      for (Index i = 0; i < m_outerSize; i++)
4847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
4857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_innerNonZeros[i] = m_outerIndex[i+1] - m_outerIndex[i];
4867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
4877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
4887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
489c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Suppresses all nonzeros which are \b much \b smaller \b than \a reference under the tolerence \a epsilon */
4907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    void prune(const Scalar& reference, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision())
491c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
492c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      prune(default_prunning_func(reference,epsilon));
493c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
494c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
495c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Turns the matrix into compressed format, and suppresses all nonzeros which do not satisfy the predicate \a keep.
496c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * The functor type \a KeepFunc must implement the following function:
497c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \code
498c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * bool operator() (const Index& row, const Index& col, const Scalar& value) const;
499c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \endcode
500c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa prune(Scalar,RealScalar)
501c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      */
502c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename KeepFunc>
503c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void prune(const KeepFunc& keep = KeepFunc())
504c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
505c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // TODO optimize the uncompressed mode to avoid moving and allocating the data twice
506c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // TODO also implement a unit test
507c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      makeCompressed();
508c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
509c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index k = 0;
510c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for(Index j=0; j<m_outerSize; ++j)
511c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
512c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index previousStart = m_outerIndex[j];
513c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_outerIndex[j] = k;
514c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index end = m_outerIndex[j+1];
515c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        for(Index i=previousStart; i<end; ++i)
516c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
517c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          if(keep(IsRowMajor?j:m_data.index(i), IsRowMajor?m_data.index(i):j, m_data.value(i)))
518c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          {
519c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            m_data.value(k) = m_data.value(i);
520c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            m_data.index(k) = m_data.index(i);
521c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            ++k;
522c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          }
523c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
524c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
525c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_outerIndex[m_outerSize] = k;
526c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.resize(k,0);
527c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
528c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
5297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /** Resizes the matrix to a \a rows x \a cols matrix leaving old values untouched.
5307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      * \sa resizeNonZeros(Index), reserve(), setZero()
5317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      */
5327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    void conservativeResize(Index rows, Index cols)
5337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
5347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // No change
5357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if (this->rows() == rows && this->cols() == cols) return;
5367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
5377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // If one dimension is null, then there is nothing to be preserved
5387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if(rows==0 || cols==0) return resize(rows,cols);
5397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
5407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Index innerChange = IsRowMajor ? cols - this->cols() : rows - this->rows();
5417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Index outerChange = IsRowMajor ? rows - this->rows() : cols - this->cols();
5427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Index newInnerSize = IsRowMajor ? cols : rows;
5437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
5447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // Deals with inner non zeros
5457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if (m_innerNonZeros)
5467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
5477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        // Resize m_innerNonZeros
5487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        Index *newInnerNonZeros = static_cast<Index*>(std::realloc(m_innerNonZeros, (m_outerSize + outerChange) * sizeof(Index)));
5497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if (!newInnerNonZeros) internal::throw_std_bad_alloc();
5507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_innerNonZeros = newInnerNonZeros;
5517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
5527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        for(Index i=m_outerSize; i<m_outerSize+outerChange; i++)
5537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          m_innerNonZeros[i] = 0;
5547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
5557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      else if (innerChange < 0)
5567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
5577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        // Inner size decreased: allocate a new m_innerNonZeros
5587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_innerNonZeros = static_cast<Index*>(std::malloc((m_outerSize+outerChange+1) * sizeof(Index)));
5597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if (!m_innerNonZeros) internal::throw_std_bad_alloc();
5607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        for(Index i = 0; i < m_outerSize; i++)
5617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          m_innerNonZeros[i] = m_outerIndex[i+1] - m_outerIndex[i];
5627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
5637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
5647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // Change the m_innerNonZeros in case of a decrease of inner size
5657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if (m_innerNonZeros && innerChange < 0)
5667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
5677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        for(Index i = 0; i < m_outerSize + (std::min)(outerChange, Index(0)); i++)
5687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        {
5697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          Index &n = m_innerNonZeros[i];
5707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          Index start = m_outerIndex[i];
5717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          while (n > 0 && m_data.index(start+n-1) >= newInnerSize) --n;
5727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        }
5737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
5747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
5757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      m_innerSize = newInnerSize;
5767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
5777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // Re-allocate outer index structure if necessary
5787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if (outerChange == 0)
5797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        return;
5807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
5817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Index *newOuterIndex = static_cast<Index*>(std::realloc(m_outerIndex, (m_outerSize + outerChange + 1) * sizeof(Index)));
5827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if (!newOuterIndex) internal::throw_std_bad_alloc();
5837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      m_outerIndex = newOuterIndex;
5847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      if (outerChange > 0)
5857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
5867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        Index last = m_outerSize == 0 ? 0 : m_outerIndex[m_outerSize];
5877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        for(Index i=m_outerSize; i<m_outerSize+outerChange+1; i++)
5887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          m_outerIndex[i] = last;
5897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
5907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      m_outerSize += outerChange;
5917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
5927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
593c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Resizes the matrix to a \a rows x \a cols matrix and initializes it to zero.
594c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa resizeNonZeros(Index), reserve(), setZero()
595c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      */
596c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void resize(Index rows, Index cols)
597c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
598c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      const Index outerSize = IsRowMajor ? rows : cols;
599c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_innerSize = IsRowMajor ? cols : rows;
600c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.clear();
601c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (m_outerSize != outerSize || m_outerSize==0)
602c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
6037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        std::free(m_outerIndex);
6047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_outerIndex = static_cast<Index*>(std::malloc((outerSize + 1) * sizeof(Index)));
6057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if (!m_outerIndex) internal::throw_std_bad_alloc();
6067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
607c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_outerSize = outerSize;
608c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
609c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(m_innerNonZeros)
610c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
6117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        std::free(m_innerNonZeros);
612c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_innerNonZeros = 0;
613c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
614c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(Index));
615c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
616c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
617c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
618c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * Resize the nonzero vector to \a size */
619c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void resizeNonZeros(Index size)
620c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
621c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // TODO remove this function
622c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.resize(size);
623c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
624c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
625c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \returns a const expression of the diagonal coefficients */
626c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Diagonal<const SparseMatrix> diagonal() const { return *this; }
627c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
628c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Default constructor yielding an empty \c 0 \c x \c 0 matrix */
629c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline SparseMatrix()
630c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      : m_outerSize(-1), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
631c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
632c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      check_template_parameters();
633c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      resize(0, 0);
634c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
635c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
636c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Constructs a \a rows \c x \a cols empty matrix */
637c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline SparseMatrix(Index rows, Index cols)
638c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
639c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
640c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      check_template_parameters();
641c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      resize(rows, cols);
642c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
643c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
644c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Constructs a sparse matrix from the sparse expression \a other */
645c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename OtherDerived>
646c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline SparseMatrix(const SparseMatrixBase<OtherDerived>& other)
647c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
648c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
6497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
6507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
651c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      check_template_parameters();
652c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *this = other.derived();
653c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
6547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
6557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /** Constructs a sparse matrix from the sparse selfadjoint view \a other */
6567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename OtherDerived, unsigned int UpLo>
6577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    inline SparseMatrix(const SparseSelfAdjointView<OtherDerived, UpLo>& other)
6587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
6597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
6607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      check_template_parameters();
6617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      *this = other;
6627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
663c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
664c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Copy constructor (it performs a deep copy) */
665c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline SparseMatrix(const SparseMatrix& other)
666c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
667c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
668c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      check_template_parameters();
669c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      *this = other.derived();
670c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
671c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
6727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /** \brief Copy constructor with in-place evaluation */
6737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    template<typename OtherDerived>
6747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    SparseMatrix(const ReturnByValue<OtherDerived>& other)
6757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0)
6767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
6777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      check_template_parameters();
6787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      initAssignment(other);
6797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      other.evalTo(*this);
6807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
6817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
682c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Swaps the content of two sparse matrices of the same type.
683c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * This is a fast operation that simply swaps the underlying pointers and parameters. */
684c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline void swap(SparseMatrix& other)
685c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
686c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n");
687c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::swap(m_outerIndex, other.m_outerIndex);
688c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::swap(m_innerSize, other.m_innerSize);
689c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::swap(m_outerSize, other.m_outerSize);
690c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::swap(m_innerNonZeros, other.m_innerNonZeros);
691c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.swap(other.m_data);
692c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
693c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
6947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /** Sets *this to the identity matrix */
6957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    inline void setIdentity()
6967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
6977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(rows() == cols() && "ONLY FOR SQUARED MATRICES");
6987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      this->m_data.resize(rows());
6997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Eigen::Map<Matrix<Index, Dynamic, 1> >(&this->m_data.index(0), rows()).setLinSpaced(0, rows()-1);
7007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Eigen::Map<Matrix<Scalar, Dynamic, 1> >(&this->m_data.value(0), rows()).setOnes();
7017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Eigen::Map<Matrix<Index, Dynamic, 1> >(this->m_outerIndex, rows()+1).setLinSpaced(0, rows());
7027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
703c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline SparseMatrix& operator=(const SparseMatrix& other)
704c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
705c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (other.isRValue())
706c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
707c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        swap(other.const_cast_derived());
708c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
7097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      else if(this!=&other)
710c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
711c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        initAssignment(other);
712c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if(other.isCompressed())
713c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
714c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          memcpy(m_outerIndex, other.m_outerIndex, (m_outerSize+1)*sizeof(Index));
715c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_data = other.m_data;
716c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
717c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        else
718c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
719c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          Base::operator=(other);
720c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
721c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
722c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return *this;
723c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
724c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
725c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    #ifndef EIGEN_PARSED_BY_DOXYGEN
726c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename Lhs, typename Rhs>
727c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline SparseMatrix& operator=(const SparseSparseProduct<Lhs,Rhs>& product)
728c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    { return Base::operator=(product); }
729c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
730c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename OtherDerived>
731c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline SparseMatrix& operator=(const ReturnByValue<OtherDerived>& other)
7327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
7337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      initAssignment(other);
7347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      return Base::operator=(other.derived());
7357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
736c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
737c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename OtherDerived>
738c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline SparseMatrix& operator=(const EigenBase<OtherDerived>& other)
739c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    { return Base::operator=(other.derived()); }
740c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    #endif
741c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
742c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename OtherDerived>
7437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other);
744c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
745c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    friend std::ostream & operator << (std::ostream & s, const SparseMatrix& m)
746c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
747c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      EIGEN_DBG_SPARSE(
748c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        s << "Nonzero entries:\n";
749c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if(m.isCompressed())
750c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          for (Index i=0; i<m.nonZeros(); ++i)
751c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
752c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        else
753c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          for (Index i=0; i<m.outerSize(); ++i)
754c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          {
7557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            Index p = m.m_outerIndex[i];
7567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            Index pe = m.m_outerIndex[i]+m.m_innerNonZeros[i];
757c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            Index k=p;
758c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            for (; k<pe; ++k)
759c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              s << "(" << m.m_data.value(k) << "," << m.m_data.index(k) << ") ";
760c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            for (; k<m.m_outerIndex[i+1]; ++k)
761c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              s << "(_,_) ";
762c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          }
763c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        s << std::endl;
764c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        s << std::endl;
765c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        s << "Outer pointers:\n";
766c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        for (Index i=0; i<m.outerSize(); ++i)
767c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          s << m.m_outerIndex[i] << " ";
768c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        s << " $" << std::endl;
769c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if(!m.isCompressed())
770c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
771c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          s << "Inner non zeros:\n";
772c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          for (Index i=0; i<m.outerSize(); ++i)
773c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath            s << m.m_innerNonZeros[i] << " ";
774c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          s << " $" << std::endl;
775c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
776c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        s << std::endl;
777c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      );
778c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      s << static_cast<const SparseMatrixBase<SparseMatrix>&>(m);
779c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return s;
780c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
781c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
782c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Destructor */
783c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline ~SparseMatrix()
784c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
7857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      std::free(m_outerIndex);
7867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      std::free(m_innerNonZeros);
787c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
788c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
789c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef EIGEN_PARSED_BY_DOXYGEN
790c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Overloaded for performance */
791c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar sum() const;
792c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif
793c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
794c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#   ifdef EIGEN_SPARSEMATRIX_PLUGIN
795c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#     include EIGEN_SPARSEMATRIX_PLUGIN
796c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#   endif
797c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
798c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathprotected:
799c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
800c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    template<typename Other>
801c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void initAssignment(const Other& other)
802c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
803c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      resize(other.rows(), other.cols());
804c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(m_innerNonZeros)
805c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
8067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        std::free(m_innerNonZeros);
807c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_innerNonZeros = 0;
808c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
809c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
810c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
811c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
812c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa insert(Index,Index) */
8137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_DONT_INLINE Scalar& insertCompressed(Index row, Index col);
814c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
815c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
816c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * A vector object that is equal to 0 everywhere but v at the position i */
817c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    class SingletonVector
818c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
819c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index m_index;
820c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index m_value;
821c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      public:
822c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        typedef Index value_type;
823c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        SingletonVector(Index i, Index v)
824c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          : m_index(i), m_value(v)
825c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {}
826c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
827c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index operator[](Index i) const { return i==m_index ? m_value : 0; }
828c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    };
829c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
830c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
831c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa insert(Index,Index) */
8327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_DONT_INLINE Scalar& insertUncompressed(Index row, Index col);
833c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
834c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic:
835c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** \internal
836c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \sa insert(Index,Index) */
8377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_STRONG_INLINE Scalar& insertBackUncompressed(Index row, Index col)
838c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
839c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      const Index outer = IsRowMajor ? row : col;
840c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      const Index inner = IsRowMajor ? col : row;
841c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
842c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      eigen_assert(!isCompressed());
843c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      eigen_assert(m_innerNonZeros[outer]<=(m_outerIndex[outer+1] - m_outerIndex[outer]));
844c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
8457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Index p = m_outerIndex[outer] + m_innerNonZeros[outer]++;
846c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_data.index(p) = inner;
847c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return (m_data.value(p) = 0);
848c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
849c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
850c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathprivate:
851c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static void check_template_parameters()
852c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
853c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    EIGEN_STATIC_ASSERT(NumTraits<Index>::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE);
8547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    EIGEN_STATIC_ASSERT((Options&(ColMajor|RowMajor))==Options,INVALID_MATRIX_TEMPLATE_PARAMETERS);
855c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
856c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
857c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  struct default_prunning_func {
8587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    default_prunning_func(const Scalar& ref, const RealScalar& eps) : reference(ref), epsilon(eps) {}
859c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline bool operator() (const Index&, const Index&, const Scalar& value) const
860c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
861c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return !internal::isMuchSmallerThan(value, reference, epsilon);
862c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
863c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar reference;
864c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    RealScalar epsilon;
865c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  };
866c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
867c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
868c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Scalar, int _Options, typename _Index>
869c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass SparseMatrix<Scalar,_Options,_Index>::InnerIterator
870c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
871c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
872c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    InnerIterator(const SparseMatrix& mat, Index outer)
873c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer), m_id(mat.m_outerIndex[outer])
874c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
875c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(mat.isCompressed())
876c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_end = mat.m_outerIndex[outer+1];
877c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
878c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_end = m_id + mat.m_innerNonZeros[outer];
879c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
880c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
881c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline InnerIterator& operator++() { m_id++; return *this; }
882c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
883c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const Scalar& value() const { return m_values[m_id]; }
884c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Scalar& valueRef() { return const_cast<Scalar&>(m_values[m_id]); }
885c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
886c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index index() const { return m_indices[m_id]; }
887c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index outer() const { return m_outer; }
888c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index row() const { return IsRowMajor ? m_outer : index(); }
889c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index col() const { return IsRowMajor ? index() : m_outer; }
890c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
891c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline operator bool() const { return (m_id < m_end); }
892c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
893c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
894c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Scalar* m_values;
895c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Index* m_indices;
896c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Index m_outer;
897c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_id;
898c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_end;
899c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
900c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
901c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Scalar, int _Options, typename _Index>
902c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass SparseMatrix<Scalar,_Options,_Index>::ReverseInnerIterator
903c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
904c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
905c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ReverseInnerIterator(const SparseMatrix& mat, Index outer)
906c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer), m_start(mat.m_outerIndex[outer])
907c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
908c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(mat.isCompressed())
909c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_id = mat.m_outerIndex[outer+1];
910c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
911c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_id = m_start + mat.m_innerNonZeros[outer];
912c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
913c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
914c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline ReverseInnerIterator& operator--() { --m_id; return *this; }
915c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
916c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline const Scalar& value() const { return m_values[m_id-1]; }
917c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Scalar& valueRef() { return const_cast<Scalar&>(m_values[m_id-1]); }
918c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
919c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index index() const { return m_indices[m_id-1]; }
920c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index outer() const { return m_outer; }
921c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index row() const { return IsRowMajor ? m_outer : index(); }
922c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline Index col() const { return IsRowMajor ? index() : m_outer; }
923c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
924c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    inline operator bool() const { return (m_id > m_start); }
925c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
926c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
927c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Scalar* m_values;
928c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Index* m_indices;
929c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Index m_outer;
930c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_id;
931c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const Index m_start;
932c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
933c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
934c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace internal {
935c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
936c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename InputIterator, typename SparseMatrixType>
937c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid set_from_triplets(const InputIterator& begin, const InputIterator& end, SparseMatrixType& mat, int Options = 0)
938c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
939c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  EIGEN_UNUSED_VARIABLE(Options);
940c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  enum { IsRowMajor = SparseMatrixType::IsRowMajor };
941c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename SparseMatrixType::Scalar Scalar;
942c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename SparseMatrixType::Index Index;
9437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  SparseMatrix<Scalar,IsRowMajor?ColMajor:RowMajor,Index> trMat(mat.rows(),mat.cols());
944c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
9457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  if(begin!=end)
9467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
9477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // pass 1: count the nnz per inner-vector
9487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Matrix<Index,Dynamic,1> wi(trMat.outerSize());
9497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    wi.setZero();
9507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for(InputIterator it(begin); it!=end; ++it)
9517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
9527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      eigen_assert(it->row()>=0 && it->row()<mat.rows() && it->col()>=0 && it->col()<mat.cols());
9537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      wi(IsRowMajor ? it->col() : it->row())++;
9547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
955c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
9567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // pass 2: insert all the elements into trMat
9577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    trMat.reserve(wi);
9587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for(InputIterator it(begin); it!=end; ++it)
9597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      trMat.insertBackUncompressed(it->row(),it->col()) = it->value();
960c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
9617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // pass 3:
9627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    trMat.sumupDuplicates();
9637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
964c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
965c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // pass 4: transposed copy -> implicit sorting
966c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  mat = trMat;
967c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
968c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
969c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
970c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
971c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
9727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/** Fill the matrix \c *this with the list of \em triplets defined by the iterator range \a begin - \a end.
973c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
974c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * A \em triplet is a tuple (i,j,value) defining a non-zero element.
975c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * The input list of triplets does not have to be sorted, and can contains duplicated elements.
976c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * In any case, the result is a \b sorted and \b compressed sparse matrix where the duplicates have been summed up.
977c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * This is a \em O(n) operation, with \em n the number of triplet elements.
978c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * The initial contents of \c *this is destroyed.
979c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * The matrix \c *this must be properly resized beforehand using the SparseMatrix(Index,Index) constructor,
980c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * or the resize(Index,Index) method. The sizes are not extracted from the triplet list.
981c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
982c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * The \a InputIterators value_type must provide the following interface:
983c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \code
984c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * Scalar value() const; // the value
985c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * Scalar row() const;   // the row index i
986c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * Scalar col() const;   // the column index j
987c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \endcode
988c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * See for instance the Eigen::Triplet template class.
989c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
990c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * Here is a typical usage example:
991c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \code
992c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef Triplet<double> T;
993c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    std::vector<T> tripletList;
994c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    triplets.reserve(estimation_of_entries);
995c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for(...)
996c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
997c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // ...
998c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      tripletList.push_back(T(i,j,v_ij));
999c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
1000c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    SparseMatrixType m(rows,cols);
1001c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m.setFromTriplets(tripletList.begin(), tripletList.end());
1002c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // m is ready to go!
1003c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \endcode
1004c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
1005c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \warning The list of triplets is read multiple times (at least twice). Therefore, it is not recommended to define
1006c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * an abstract iterator over a complex data-structure that would be expensive to evaluate. The triplets should rather
1007c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * be explicitely stored into a std::vector for instance.
1008c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  */
1009c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Scalar, int _Options, typename _Index>
1010c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename InputIterators>
1011c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid SparseMatrix<Scalar,_Options,_Index>::setFromTriplets(const InputIterators& begin, const InputIterators& end)
1012c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
1013c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  internal::set_from_triplets(begin, end, *this);
1014c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
1015c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1016c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \internal */
1017c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Scalar, int _Options, typename _Index>
1018c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid SparseMatrix<Scalar,_Options,_Index>::sumupDuplicates()
1019c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
1020c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  eigen_assert(!isCompressed());
1021c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // TODO, in practice we should be able to use m_innerNonZeros for that task
10227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Matrix<Index,Dynamic,1> wi(innerSize());
1023c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  wi.fill(-1);
1024c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index count = 0;
1025c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // for each inner-vector, wi[inner_index] will hold the position of first element into the index/value buffers
10267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for(Index j=0; j<outerSize(); ++j)
1027c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
1028c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index start   = count;
1029c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index oldEnd  = m_outerIndex[j]+m_innerNonZeros[j];
1030c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for(Index k=m_outerIndex[j]; k<oldEnd; ++k)
1031c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
1032c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index i = m_data.index(k);
1033c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if(wi(i)>=start)
1034c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
1035c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        // we already meet this entry => accumulate it
1036c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_data.value(wi(i)) += m_data.value(k);
1037c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
1038c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
1039c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
1040c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_data.value(count) = m_data.value(k);
1041c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_data.index(count) = m_data.index(k);
1042c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        wi(i) = count;
1043c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ++count;
1044c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
1045c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
1046c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_outerIndex[j] = start;
1047c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
1048c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m_outerIndex[m_outerSize] = count;
1049c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1050c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // turn the matrix into compressed form
10517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  std::free(m_innerNonZeros);
1052c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m_innerNonZeros = 0;
1053c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m_data.resize(m_outerIndex[m_outerSize]);
1054c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
1055c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Scalar, int _Options, typename _Index>
10577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename OtherDerived>
10587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos HernandezEIGEN_DONT_INLINE SparseMatrix<Scalar,_Options,_Index>& SparseMatrix<Scalar,_Options,_Index>::operator=(const SparseMatrixBase<OtherDerived>& other)
10597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
10607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
10617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
10627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
10637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
10647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  if (needToTranspose)
10657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
10667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // two passes algorithm:
10677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    //  1 - compute the number of coeffs per dest inner vector
10687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    //  2 - do the actual copy/eval
10697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // Since each coeff of the rhs has to be evaluated twice, let's evaluate it if needed
10707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename internal::nested<OtherDerived,2>::type OtherCopy;
10717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef typename internal::remove_all<OtherCopy>::type _OtherCopy;
10727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    OtherCopy otherCopy(other.derived());
10737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
10747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    SparseMatrix dest(other.rows(),other.cols());
10757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Eigen::Map<Matrix<Index, Dynamic, 1> > (dest.m_outerIndex,dest.outerSize()).setZero();
10767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
10777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // pass 1
10787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // FIXME the above copy could be merged with that pass
10797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (Index j=0; j<otherCopy.outerSize(); ++j)
10807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
10817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        ++dest.m_outerIndex[it.index()];
10827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
10837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // prefix sum
10847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index count = 0;
10857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Matrix<Index,Dynamic,1> positions(dest.outerSize());
10867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (Index j=0; j<dest.outerSize(); ++j)
10877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
10887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Index tmp = dest.m_outerIndex[j];
10897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      dest.m_outerIndex[j] = count;
10907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      positions[j] = count;
10917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      count += tmp;
10927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
10937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    dest.m_outerIndex[dest.outerSize()] = count;
10947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // alloc
10957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    dest.m_data.resize(count);
10967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // pass 2
10977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (Index j=0; j<otherCopy.outerSize(); ++j)
10987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
10997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
11007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
11017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        Index pos = positions[it.index()]++;
11027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        dest.m_data.index(pos) = j;
11037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        dest.m_data.value(pos) = it.value();
11047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
11057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
11067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    this->swap(dest);
11077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    return *this;
11087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
11097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  else
11107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
11117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    if(other.isRValue())
11127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      initAssignment(other.derived());
11137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // there is no special optimization
11147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    return Base::operator=(other.derived());
11157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
11167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}
11177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename _Scalar, int _Options, typename _Index>
11197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos HernandezEIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_Index>::Scalar& SparseMatrix<_Scalar,_Options,_Index>::insertUncompressed(Index row, Index col)
11207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
11217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  eigen_assert(!isCompressed());
11227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const Index outer = IsRowMajor ? row : col;
11247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const Index inner = IsRowMajor ? col : row;
11257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index room = m_outerIndex[outer+1] - m_outerIndex[outer];
11277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index innerNNZ = m_innerNonZeros[outer];
11287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  if(innerNNZ>=room)
11297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
11307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // this inner vector is full, we need to reallocate the whole buffer :(
11317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    reserve(SingletonVector(outer,std::max<Index>(2,innerNNZ)));
11327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
11337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index startId = m_outerIndex[outer];
11357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index p = startId + m_innerNonZeros[outer];
11367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  while ( (p > startId) && (m_data.index(p-1) > inner) )
11377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
11387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    m_data.index(p) = m_data.index(p-1);
11397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    m_data.value(p) = m_data.value(p-1);
11407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    --p;
11417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
11427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  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");
11437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  m_innerNonZeros[outer]++;
11457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  m_data.index(p) = inner;
11477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  return (m_data.value(p) = 0);
11487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}
11497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename _Scalar, int _Options, typename _Index>
11517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos HernandezEIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_Index>::Scalar& SparseMatrix<_Scalar,_Options,_Index>::insertCompressed(Index row, Index col)
11527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
11537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  eigen_assert(isCompressed());
11547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const Index outer = IsRowMajor ? row : col;
11567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  const Index inner = IsRowMajor ? col : row;
11577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index previousOuter = outer;
11597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  if (m_outerIndex[outer+1]==0)
11607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
11617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // we start a new inner vector
11627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    while (previousOuter>=0 && m_outerIndex[previousOuter]==0)
11637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
11647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      m_outerIndex[previousOuter] = static_cast<Index>(m_data.size());
11657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      --previousOuter;
11667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
11677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    m_outerIndex[outer+1] = m_outerIndex[outer];
11687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
11697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // here we have to handle the tricky case where the outerIndex array
11717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // starts with: [ 0 0 0 0 0 1 ...] and we are inserted in, e.g.,
11727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // the 2nd inner vector...
11737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0))
11747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                && (size_t(m_outerIndex[outer+1]) == m_data.size());
11757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  size_t startId = m_outerIndex[outer];
11777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // FIXME let's make sure sizeof(long int) == sizeof(size_t)
11787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  size_t p = m_outerIndex[outer+1];
11797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  ++m_outerIndex[outer+1];
11807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
11817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  double reallocRatio = 1;
11827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  if (m_data.allocatedSize()<=m_data.size())
11837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
11847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // if there is no preallocated memory, let's reserve a minimum of 32 elements
11857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    if (m_data.size()==0)
11867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
11877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      m_data.reserve(32);
11887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
11897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    else
11907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
11917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // we need to reallocate the data, to reduce multiple reallocations
11927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // we use a smart resize algorithm based on the current filling ratio
11937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // in addition, we use double to avoid integers overflows
11947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      double nnzEstimate = double(m_outerIndex[outer])*double(m_outerSize)/double(outer+1);
11957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      reallocRatio = (nnzEstimate-double(m_data.size()))/double(m_data.size());
11967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // furthermore we bound the realloc ratio to:
11977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      //   1) reduce multiple minor realloc when the matrix is almost filled
11987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      //   2) avoid to allocate too much memory when the matrix is almost empty
11997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      reallocRatio = (std::min)((std::max)(reallocRatio,1.5),8.);
12007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
12017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
12027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  m_data.resize(m_data.size()+1,reallocRatio);
12037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
12047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  if (!isLastVec)
12057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
12067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    if (previousOuter==-1)
12077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
12087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // oops wrong guess.
12097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // let's correct the outer offsets
12107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      for (Index k=0; k<=(outer+1); ++k)
12117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_outerIndex[k] = 0;
12127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Index k=outer+1;
12137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      while(m_outerIndex[k]==0)
12147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_outerIndex[k++] = 1;
12157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      while (k<=m_outerSize && m_outerIndex[k]!=0)
12167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_outerIndex[k++]++;
12177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      p = 0;
12187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      --k;
12197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      k = m_outerIndex[k]-1;
12207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      while (k>0)
12217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
12227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_data.index(k) = m_data.index(k-1);
12237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_data.value(k) = m_data.value(k-1);
12247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        k--;
12257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
12267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
12277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    else
12287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
12297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // we are not inserting into the last inner vec
12307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // update outer indices:
12317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Index j = outer+2;
12327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      while (j<=m_outerSize && m_outerIndex[j]!=0)
12337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_outerIndex[j++]++;
12347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      --j;
12357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // shift data of last vecs:
12367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      Index k = m_outerIndex[j]-1;
12377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      while (k>=Index(p))
12387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
12397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_data.index(k) = m_data.index(k-1);
12407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        m_data.value(k) = m_data.value(k-1);
12417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        k--;
12427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
12437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
12447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
12457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
12467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  while ( (p > startId) && (m_data.index(p-1) > inner) )
12477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
12487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    m_data.index(p) = m_data.index(p-1);
12497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    m_data.value(p) = m_data.value(p-1);
12507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    --p;
12517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
12527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
12537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  m_data.index(p) = inner;
12547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  return (m_data.value(p) = 0);
12557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}
12567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1257c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace Eigen
1258c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
1259c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif // EIGEN_SPARSEMATRIX_H
1260