00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef EIGEN_SPARSEMATRIX_H
00026 #define EIGEN_SPARSEMATRIX_H
00027
00037 template<typename _Scalar, int _Flags>
00038 struct ei_traits<SparseMatrix<_Scalar, _Flags> >
00039 {
00040 typedef _Scalar Scalar;
00041 enum {
00042 RowsAtCompileTime = Dynamic,
00043 ColsAtCompileTime = Dynamic,
00044 MaxRowsAtCompileTime = Dynamic,
00045 MaxColsAtCompileTime = Dynamic,
00046 Flags = SparseBit | _Flags,
00047 CoeffReadCost = NumTraits<Scalar>::ReadCost,
00048 SupportedAccessPatterns = InnerRandomAccessPattern
00049 };
00050 };
00051
00052
00053
00054 template<typename _Scalar, int _Flags>
00055 class SparseMatrix
00056 : public SparseMatrixBase<SparseMatrix<_Scalar, _Flags> >
00057 {
00058 public:
00059 EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseMatrix)
00060 EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, +=)
00061 EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, -=)
00062
00063
00064
00065
00066 typedef MappedSparseMatrix<Scalar,Flags> Map;
00067
00068 protected:
00069
00070 enum { IsRowMajor = Base::IsRowMajor };
00071 typedef SparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0)> TransposedSparseMatrix;
00072
00073 int m_outerSize;
00074 int m_innerSize;
00075 int* m_outerIndex;
00076 CompressedStorage<Scalar> m_data;
00077
00078 public:
00079
00080 inline int rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
00081 inline int cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
00082
00083 inline int innerSize() const { return m_innerSize; }
00084 inline int outerSize() const { return m_outerSize; }
00085 inline int innerNonZeros(int j) const { return m_outerIndex[j+1]-m_outerIndex[j]; }
00086
00087 inline const Scalar* _valuePtr() const { return &m_data.value(0); }
00088 inline Scalar* _valuePtr() { return &m_data.value(0); }
00089
00090 inline const int* _innerIndexPtr() const { return &m_data.index(0); }
00091 inline int* _innerIndexPtr() { return &m_data.index(0); }
00092
00093 inline const int* _outerIndexPtr() const { return m_outerIndex; }
00094 inline int* _outerIndexPtr() { return m_outerIndex; }
00095
00096 inline Scalar coeff(int row, int col) const
00097 {
00098 const int outer = IsRowMajor ? row : col;
00099 const int inner = IsRowMajor ? col : row;
00100 return m_data.atInRange(m_outerIndex[outer], m_outerIndex[outer+1], inner);
00101 }
00102
00103 inline Scalar& coeffRef(int row, int col)
00104 {
00105 const int outer = IsRowMajor ? row : col;
00106 const int inner = IsRowMajor ? col : row;
00107
00108 int start = m_outerIndex[outer];
00109 int end = m_outerIndex[outer+1];
00110 ei_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
00111 ei_assert(end>start && "coeffRef cannot be called on a zero coefficient");
00112 const int id = m_data.searchLowerIndex(start,end-1,inner);
00113 ei_assert((id<end) && (m_data.index(id)==inner) && "coeffRef cannot be called on a zero coefficient");
00114 return m_data.value(id);
00115 }
00116
00117 public:
00118
00119 class InnerIterator;
00120
00121 inline void setZero()
00122 {
00123 m_data.clear();
00124
00125 std::memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(int));
00126
00127
00128
00129
00130 }
00131
00133 inline int nonZeros() const { return m_data.size(); }
00134
00139 inline void startFill(int reserveSize = 1000)
00140 {
00141 setZero();
00142 m_data.reserve(reserveSize);
00143 }
00144
00147 inline Scalar& fill(int row, int col)
00148 {
00149 const int outer = IsRowMajor ? row : col;
00150 const int inner = IsRowMajor ? col : row;
00151
00152 if (m_outerIndex[outer+1]==0)
00153 {
00154
00155 int i = outer;
00156 while (i>=0 && m_outerIndex[i]==0)
00157 {
00158 m_outerIndex[i] = m_data.size();
00159 --i;
00160 }
00161 m_outerIndex[outer+1] = m_outerIndex[outer];
00162 }
00163 else
00164 {
00165 ei_assert(m_data.index(m_data.size()-1)<inner && "wrong sorted insertion");
00166 }
00167 assert(std::size_t(m_outerIndex[outer+1]) == m_data.size());
00168 int id = m_outerIndex[outer+1];
00169 ++m_outerIndex[outer+1];
00170
00171 m_data.append(0, inner);
00172 return m_data.value(id);
00173 }
00174
00177 inline Scalar& fillrand(int row, int col)
00178 {
00179 const int outer = IsRowMajor ? row : col;
00180 const int inner = IsRowMajor ? col : row;
00181 if (m_outerIndex[outer+1]==0)
00182 {
00183
00184
00185 int i = outer;
00186 while (i>=0 && m_outerIndex[i]==0)
00187 {
00188 m_outerIndex[i] = m_data.size();
00189 --i;
00190 }
00191 m_outerIndex[outer+1] = m_outerIndex[outer];
00192 }
00193 assert(std::size_t(m_outerIndex[outer+1]) == m_data.size() && "invalid outer index");
00194 std::size_t startId = m_outerIndex[outer];
00195
00196 std::size_t id = m_outerIndex[outer+1];
00197 ++m_outerIndex[outer+1];
00198
00199 float reallocRatio = 1;
00200 if (m_data.allocatedSize()<id+1)
00201 {
00202
00203
00204
00205 float nnzEstimate = float(m_outerIndex[outer])*float(m_outerSize)/float(outer);
00206 reallocRatio = (nnzEstimate-float(m_data.size()))/float(m_data.size());
00207
00208
00209
00210 reallocRatio = std::min(std::max(reallocRatio,1.5f),8.f);
00211 }
00212 m_data.resize(id+1,reallocRatio);
00213
00214 while ( (id > startId) && (m_data.index(id-1) > inner) )
00215 {
00216 m_data.index(id) = m_data.index(id-1);
00217 m_data.value(id) = m_data.value(id-1);
00218 --id;
00219 }
00220
00221 m_data.index(id) = inner;
00222 return (m_data.value(id) = 0);
00223 }
00224
00225 inline void endFill()
00226 {
00227 int size = m_data.size();
00228 int i = m_outerSize;
00229
00230 while (i>=0 && m_outerIndex[i]==0)
00231 --i;
00232 ++i;
00233 while (i<=m_outerSize)
00234 {
00235 m_outerIndex[i] = size;
00236 ++i;
00237 }
00238 }
00239
00240 void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
00241 {
00242 int k = 0;
00243 for (int j=0; j<m_outerSize; ++j)
00244 {
00245 int previousStart = m_outerIndex[j];
00246 m_outerIndex[j] = k;
00247 int end = m_outerIndex[j+1];
00248 for (int i=previousStart; i<end; ++i)
00249 {
00250 if (!ei_isMuchSmallerThan(m_data.value(i), reference, epsilon))
00251 {
00252 m_data.value(k) = m_data.value(i);
00253 m_data.index(k) = m_data.index(i);
00254 ++k;
00255 }
00256 }
00257 }
00258 m_outerIndex[m_outerSize] = k;
00259 m_data.resize(k,0);
00260 }
00261
00265 void resize(int rows, int cols)
00266 {
00267 const int outerSize = IsRowMajor ? rows : cols;
00268 m_innerSize = IsRowMajor ? cols : rows;
00269 m_data.clear();
00270 if (m_outerSize != outerSize || m_outerSize==0)
00271 {
00272 delete[] m_outerIndex;
00273 m_outerIndex = new int [outerSize+1];
00274 m_outerSize = outerSize;
00275 }
00276 std::memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(int));
00277 }
00278 void resizeNonZeros(int size)
00279 {
00280 m_data.resize(size);
00281 }
00282
00283 inline SparseMatrix()
00284 : m_outerSize(-1), m_innerSize(0), m_outerIndex(0)
00285 {
00286 resize(0, 0);
00287 }
00288
00289 inline SparseMatrix(int rows, int cols)
00290 : m_outerSize(0), m_innerSize(0), m_outerIndex(0)
00291 {
00292 resize(rows, cols);
00293 }
00294
00295 template<typename OtherDerived>
00296 inline SparseMatrix(const SparseMatrixBase<OtherDerived>& other)
00297 : m_outerSize(0), m_innerSize(0), m_outerIndex(0)
00298 {
00299 *this = other.derived();
00300 }
00301
00302 inline SparseMatrix(const SparseMatrix& other)
00303 : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0)
00304 {
00305 *this = other.derived();
00306 }
00307
00308 inline void swap(SparseMatrix& other)
00309 {
00310
00311 std::swap(m_outerIndex, other.m_outerIndex);
00312 std::swap(m_innerSize, other.m_innerSize);
00313 std::swap(m_outerSize, other.m_outerSize);
00314 m_data.swap(other.m_data);
00315 }
00316
00317 inline SparseMatrix& operator=(const SparseMatrix& other)
00318 {
00319
00320 if (other.isRValue())
00321 {
00322 swap(other.const_cast_derived());
00323 }
00324 else
00325 {
00326 resize(other.rows(), other.cols());
00327 std::memcpy(m_outerIndex, other.m_outerIndex, (m_outerSize+1)*sizeof(int));
00328 m_data = other.m_data;
00329 }
00330 return *this;
00331 }
00332
00333 template<typename OtherDerived>
00334 inline SparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other)
00335 {
00336 const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
00337 if (needToTranspose)
00338 {
00339
00340
00341
00342
00343
00344 typedef typename ei_eval<OtherDerived>::type OtherCopy;
00345 typedef typename ei_cleantype<OtherCopy>::type _OtherCopy;
00346 OtherCopy otherCopy(other.derived());
00347
00348 resize(other.rows(), other.cols());
00349 Eigen::Map<VectorXi>(m_outerIndex,outerSize()).setZero();
00350
00351
00352 for (int j=0; j<otherCopy.outerSize(); ++j)
00353 for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
00354 ++m_outerIndex[it.index()];
00355
00356
00357 int count = 0;
00358 VectorXi positions(outerSize());
00359 for (int j=0; j<outerSize(); ++j)
00360 {
00361 int tmp = m_outerIndex[j];
00362 m_outerIndex[j] = count;
00363 positions[j] = count;
00364 count += tmp;
00365 }
00366 m_outerIndex[outerSize()] = count;
00367
00368 m_data.resize(count);
00369
00370 for (int j=0; j<otherCopy.outerSize(); ++j)
00371 for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
00372 {
00373 int pos = positions[it.index()]++;
00374 m_data.index(pos) = j;
00375 m_data.value(pos) = it.value();
00376 }
00377
00378 return *this;
00379 }
00380 else
00381 {
00382
00383 return SparseMatrixBase<SparseMatrix>::operator=(other.derived());
00384 }
00385 }
00386
00387 friend std::ostream & operator << (std::ostream & s, const SparseMatrix& m)
00388 {
00389 EIGEN_DBG_SPARSE(
00390 s << "Nonzero entries:\n";
00391 for (int i=0; i<m.nonZeros(); ++i)
00392 {
00393 s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
00394 }
00395 s << std::endl;
00396 s << std::endl;
00397 s << "Column pointers:\n";
00398 for (int i=0; i<m.outerSize(); ++i)
00399 {
00400 s << m.m_outerIndex[i] << " ";
00401 }
00402 s << " $" << std::endl;
00403 s << std::endl;
00404 );
00405 s << static_cast<const SparseMatrixBase<SparseMatrix>&>(m);
00406 return s;
00407 }
00408
00410 inline ~SparseMatrix()
00411 {
00412 delete[] m_outerIndex;
00413 }
00414 };
00415
00416 template<typename Scalar, int _Flags>
00417 class SparseMatrix<Scalar,_Flags>::InnerIterator
00418 {
00419 public:
00420 InnerIterator(const SparseMatrix& mat, int outer)
00421 : m_matrix(mat), m_outer(outer), m_id(mat.m_outerIndex[outer]), m_start(m_id), m_end(mat.m_outerIndex[outer+1])
00422 {}
00423
00424 template<unsigned int Added, unsigned int Removed>
00425 InnerIterator(const Flagged<SparseMatrix,Added,Removed>& mat, int outer)
00426 : m_matrix(mat._expression()), m_outer(outer), m_id(m_matrix.m_outerIndex[outer]),
00427 m_start(m_id), m_end(m_matrix.m_outerIndex[outer+1])
00428 {}
00429
00430 inline InnerIterator& operator++() { m_id++; return *this; }
00431
00432 inline Scalar value() const { return m_matrix.m_data.value(m_id); }
00433 inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.m_data.value(m_id)); }
00434
00435 inline int index() const { return m_matrix.m_data.index(m_id); }
00436 inline int row() const { return IsRowMajor ? m_outer : index(); }
00437 inline int col() const { return IsRowMajor ? index() : m_outer; }
00438
00439 inline operator bool() const { return (m_id < m_end) && (m_id>=m_start); }
00440
00441 protected:
00442 const SparseMatrix& m_matrix;
00443 const int m_outer;
00444 int m_id;
00445 const int m_start;
00446 const int m_end;
00447
00448 private:
00449 InnerIterator& operator=(const InnerIterator&);
00450 };
00451
00452 #endif // EIGEN_SPARSEMATRIX_H