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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #ifndef EIGEN_SPARSELDLT_H
00064 #define EIGEN_SPARSELDLT_H
00065
00076 template<typename MatrixType, int Backend = DefaultBackend>
00077 class SparseLDLT
00078 {
00079 protected:
00080 typedef typename MatrixType::Scalar Scalar;
00081 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
00082 typedef SparseMatrix<Scalar,LowerTriangular|UnitDiagBit> CholMatrixType;
00083 typedef Matrix<Scalar,MatrixType::ColsAtCompileTime,1> VectorType;
00084
00085 enum {
00086 SupernodalFactorIsDirty = 0x10000,
00087 MatrixLIsDirty = 0x20000
00088 };
00089
00090 public:
00091
00093 SparseLDLT(int flags = 0)
00094 : m_flags(flags), m_status(0)
00095 {
00096 ei_assert((MatrixType::Flags&RowMajorBit)==0);
00097 m_precision = RealScalar(0.1) * Eigen::precision<RealScalar>();
00098 }
00099
00102 SparseLDLT(const MatrixType& matrix, int flags = 0)
00103 : m_matrix(matrix.rows(), matrix.cols()), m_flags(flags), m_status(0)
00104 {
00105 ei_assert((MatrixType::Flags&RowMajorBit)==0);
00106 m_precision = RealScalar(0.1) * Eigen::precision<RealScalar>();
00107 compute(matrix);
00108 }
00109
00123 void setPrecision(RealScalar v) { m_precision = v; }
00124
00128 RealScalar precision() const { return m_precision; }
00129
00140 void settagss(int f) { m_flags = f; }
00142 int flags() const { return m_flags; }
00143
00145 void compute(const MatrixType& matrix);
00146
00148 void _symbolic(const MatrixType& matrix);
00151 bool _numeric(const MatrixType& matrix);
00152
00154 inline const CholMatrixType& matrixL(void) const { return m_matrix; }
00155
00157 inline VectorType vectorD(void) const { return m_diag; }
00158
00159 template<typename Derived>
00160 bool solveInPlace(MatrixBase<Derived> &b) const;
00161
00163 inline bool succeeded(void) const { return m_succeeded; }
00164
00165 protected:
00166 CholMatrixType m_matrix;
00167 VectorType m_diag;
00168 VectorXi m_parent;
00169 VectorXi m_nonZerosPerCol;
00170
00171 RealScalar m_precision;
00172 int m_flags;
00173 mutable int m_status;
00174 bool m_succeeded;
00175 };
00176
00180 template<typename MatrixType, int Backend>
00181 void SparseLDLT<MatrixType,Backend>::compute(const MatrixType& a)
00182 {
00183 _symbolic(a);
00184 m_succeeded = _numeric(a);
00185 }
00186
00187 template<typename MatrixType, int Backend>
00188 void SparseLDLT<MatrixType,Backend>::_symbolic(const MatrixType& a)
00189 {
00190 assert(a.rows()==a.cols());
00191 const int size = a.rows();
00192 m_matrix.resize(size, size);
00193 m_parent.resize(size);
00194 m_nonZerosPerCol.resize(size);
00195 int * tags = ei_aligned_stack_new(int, size);
00196
00197 const int* Ap = a._outerIndexPtr();
00198 const int* Ai = a._innerIndexPtr();
00199 int* Lp = m_matrix._outerIndexPtr();
00200 const int* P = 0;
00201 int* Pinv = 0;
00202
00203 if (P)
00204 {
00205
00206 for (int k = 0; k < size; ++k)
00207 Pinv[P[k]] = k;
00208 }
00209 for (int k = 0; k < size; ++k)
00210 {
00211
00212 m_parent[k] = -1;
00213 tags[k] = k;
00214 m_nonZerosPerCol[k] = 0;
00215 int kk = P ? P[k] : k;
00216 int p2 = Ap[kk+1];
00217 for (int p = Ap[kk]; p < p2; ++p)
00218 {
00219
00220 int i = Pinv ? Pinv[Ai[p]] : Ai[p];
00221 if (i < k)
00222 {
00223
00224 for (; tags[i] != k; i = m_parent[i])
00225 {
00226
00227 if (m_parent[i] == -1)
00228 m_parent[i] = k;
00229 ++m_nonZerosPerCol[i];
00230 tags[i] = k;
00231 }
00232 }
00233 }
00234 }
00235
00236 Lp[0] = 0;
00237 for (int k = 0; k < size; ++k)
00238 Lp[k+1] = Lp[k] + m_nonZerosPerCol[k];
00239
00240 m_matrix.resizeNonZeros(Lp[size]);
00241 ei_aligned_stack_delete(int, tags, size);
00242 }
00243
00244 template<typename MatrixType, int Backend>
00245 bool SparseLDLT<MatrixType,Backend>::_numeric(const MatrixType& a)
00246 {
00247 assert(a.rows()==a.cols());
00248 const int size = a.rows();
00249 assert(m_parent.size()==size);
00250 assert(m_nonZerosPerCol.size()==size);
00251
00252 const int* Ap = a._outerIndexPtr();
00253 const int* Ai = a._innerIndexPtr();
00254 const Scalar* Ax = a._valuePtr();
00255 const int* Lp = m_matrix._outerIndexPtr();
00256 int* Li = m_matrix._innerIndexPtr();
00257 Scalar* Lx = m_matrix._valuePtr();
00258 m_diag.resize(size);
00259
00260 Scalar * y = ei_aligned_stack_new(Scalar, size);
00261 int * pattern = ei_aligned_stack_new(int, size);
00262 int * tags = ei_aligned_stack_new(int, size);
00263
00264 const int* P = 0;
00265 const int* Pinv = 0;
00266 bool ok = true;
00267
00268 for (int k = 0; k < size; ++k)
00269 {
00270
00271 y[k] = 0.0;
00272 int top = size;
00273 tags[k] = k;
00274 m_nonZerosPerCol[k] = 0;
00275 int kk = (P) ? (P[k]) : (k);
00276 int p2 = Ap[kk+1];
00277 for (int p = Ap[kk]; p < p2; ++p)
00278 {
00279 int i = Pinv ? Pinv[Ai[p]] : Ai[p];
00280 if (i <= k)
00281 {
00282 y[i] += Ax[p];
00283 int len;
00284 for (len = 0; tags[i] != k; i = m_parent[i])
00285 {
00286 pattern[len++] = i;
00287 tags[i] = k;
00288 }
00289 while (len > 0)
00290 pattern[--top] = pattern[--len];
00291 }
00292 }
00293
00294 m_diag[k] = y[k];
00295 y[k] = 0.0;
00296 for (; top < size; ++top)
00297 {
00298 int i = pattern[top];
00299 Scalar yi = y[i];
00300 y[i] = 0.0;
00301 int p2 = Lp[i] + m_nonZerosPerCol[i];
00302 int p;
00303 for (p = Lp[i]; p < p2; ++p)
00304 y[Li[p]] -= Lx[p] * yi;
00305 Scalar l_ki = yi / m_diag[i];
00306 m_diag[k] -= l_ki * yi;
00307 Li[p] = k;
00308 Lx[p] = l_ki;
00309 ++m_nonZerosPerCol[i];
00310 }
00311 if (m_diag[k] == 0.0)
00312 {
00313 ok = false;
00314 break;
00315 }
00316 }
00317
00318 ei_aligned_stack_delete(Scalar, y, size);
00319 ei_aligned_stack_delete(int, pattern, size);
00320 ei_aligned_stack_delete(int, tags, size);
00321
00322 return ok;
00323 }
00324
00326 template<typename MatrixType, int Backend>
00327 template<typename Derived>
00328 bool SparseLDLT<MatrixType, Backend>::solveInPlace(MatrixBase<Derived> &b) const
00329 {
00330 const int size = m_matrix.rows();
00331 ei_assert(size==b.rows());
00332 if (!m_succeeded)
00333 return false;
00334
00335 if (m_matrix.nonZeros()>0)
00336 m_matrix.solveTriangularInPlace(b);
00337 b = b.cwise() / m_diag;
00338
00339
00340 if (m_matrix.nonZeros()>0)
00341 m_matrix.transpose().solveTriangularInPlace(b);
00342
00343 return true;
00344 }
00345
00346 #endif // EIGEN_SPARSELDLT_H