File indexing completed on 2025-01-18 09:57:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_SKYLINEINPLACELU_H
0011 #define EIGEN_SKYLINEINPLACELU_H
0012
0013 namespace Eigen {
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 template<typename MatrixType>
0025 class SkylineInplaceLU {
0026 protected:
0027 typedef typename MatrixType::Scalar Scalar;
0028 typedef typename MatrixType::Index Index;
0029
0030 typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
0031
0032 public:
0033
0034
0035
0036 SkylineInplaceLU(MatrixType& matrix, int flags = 0)
0037 : m_flags(flags), m_status(0), m_lu(matrix) {
0038 m_precision = RealScalar(0.1) * Eigen::dummy_precision<RealScalar > ();
0039 m_lu.IsRowMajor ? computeRowMajor() : compute();
0040 }
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 void setPrecision(RealScalar v) {
0053 m_precision = v;
0054 }
0055
0056
0057
0058
0059 RealScalar precision() const {
0060 return m_precision;
0061 }
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 void setFlags(int f) {
0072 m_flags = f;
0073 }
0074
0075
0076 int flags() const {
0077 return m_flags;
0078 }
0079
0080 void setOrderingMethod(int m) {
0081 m_flags = m;
0082 }
0083
0084 int orderingMethod() const {
0085 return m_flags;
0086 }
0087
0088
0089 void compute();
0090 void computeRowMajor();
0091
0092
0093
0094
0095
0096
0097
0098 template<typename BDerived, typename XDerived>
0099 bool solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>* x,
0100 const int transposed = 0) const;
0101
0102
0103 inline bool succeeded(void) const {
0104 return m_succeeded;
0105 }
0106
0107 protected:
0108 RealScalar m_precision;
0109 int m_flags;
0110 mutable int m_status;
0111 bool m_succeeded;
0112 MatrixType& m_lu;
0113 };
0114
0115
0116
0117
0118 template<typename MatrixType>
0119
0120 void SkylineInplaceLU<MatrixType>::compute() {
0121 const size_t rows = m_lu.rows();
0122 const size_t cols = m_lu.cols();
0123
0124 eigen_assert(rows == cols && "We do not (yet) support rectangular LU.");
0125 eigen_assert(!m_lu.IsRowMajor && "LU decomposition does not work with rowMajor Storage");
0126
0127 for (Index row = 0; row < rows; row++) {
0128 const double pivot = m_lu.coeffDiag(row);
0129
0130
0131 const Index& col = row;
0132 for (typename MatrixType::InnerLowerIterator lIt(m_lu, col); lIt; ++lIt) {
0133 lIt.valueRef() /= pivot;
0134 }
0135
0136
0137 typename MatrixType::InnerLowerIterator lIt(m_lu, col);
0138 for (Index rrow = row + 1; rrow < m_lu.rows(); rrow++) {
0139 typename MatrixType::InnerUpperIterator uItPivot(m_lu, row);
0140 typename MatrixType::InnerUpperIterator uIt(m_lu, rrow);
0141 const double coef = lIt.value();
0142
0143 uItPivot += (rrow - row - 1);
0144
0145
0146 for (++uItPivot; uIt && uItPivot;) {
0147 uIt.valueRef() -= uItPivot.value() * coef;
0148
0149 ++uIt;
0150 ++uItPivot;
0151 }
0152 ++lIt;
0153 }
0154
0155
0156 typename MatrixType::InnerLowerIterator lIt3(m_lu, col);
0157 for (Index rrow = row + 1; rrow < m_lu.rows(); rrow++) {
0158 typename MatrixType::InnerUpperIterator uItPivot(m_lu, row);
0159 const double coef = lIt3.value();
0160
0161
0162 for (Index i = 0; i < rrow - row - 1; i++) {
0163 m_lu.coeffRefLower(rrow, row + i + 1) -= uItPivot.value() * coef;
0164 ++uItPivot;
0165 }
0166 ++lIt3;
0167 }
0168
0169 typename MatrixType::InnerLowerIterator lIt2(m_lu, col);
0170 for (Index rrow = row + 1; rrow < m_lu.rows(); rrow++) {
0171
0172 typename MatrixType::InnerUpperIterator uItPivot(m_lu, row);
0173 typename MatrixType::InnerUpperIterator uIt(m_lu, rrow);
0174 const double coef = lIt2.value();
0175
0176 uItPivot += (rrow - row - 1);
0177 m_lu.coeffRefDiag(rrow) -= uItPivot.value() * coef;
0178 ++lIt2;
0179 }
0180 }
0181 }
0182
0183 template<typename MatrixType>
0184 void SkylineInplaceLU<MatrixType>::computeRowMajor() {
0185 const size_t rows = m_lu.rows();
0186 const size_t cols = m_lu.cols();
0187
0188 eigen_assert(rows == cols && "We do not (yet) support rectangular LU.");
0189 eigen_assert(m_lu.IsRowMajor && "You're trying to apply rowMajor decomposition on a ColMajor matrix !");
0190
0191 for (Index row = 0; row < rows; row++) {
0192 typename MatrixType::InnerLowerIterator llIt(m_lu, row);
0193
0194
0195 for (Index col = llIt.col(); col < row; col++) {
0196 if (m_lu.coeffExistLower(row, col)) {
0197 const double diag = m_lu.coeffDiag(col);
0198
0199 typename MatrixType::InnerLowerIterator lIt(m_lu, row);
0200 typename MatrixType::InnerUpperIterator uIt(m_lu, col);
0201
0202
0203 const Index offset = lIt.col() - uIt.row();
0204
0205
0206 Index stop = offset > 0 ? col - lIt.col() : col - uIt.row();
0207
0208
0209 #ifdef VECTORIZE
0210 Map<VectorXd > rowVal(lIt.valuePtr() + (offset > 0 ? 0 : -offset), stop);
0211 Map<VectorXd > colVal(uIt.valuePtr() + (offset > 0 ? offset : 0), stop);
0212
0213
0214 Scalar newCoeff = m_lu.coeffLower(row, col) - rowVal.dot(colVal);
0215 #else
0216 if (offset > 0)
0217 uIt += offset;
0218 else
0219 lIt += -offset;
0220 Scalar newCoeff = m_lu.coeffLower(row, col);
0221
0222 for (Index k = 0; k < stop; ++k) {
0223 const Scalar tmp = newCoeff;
0224 newCoeff = tmp - lIt.value() * uIt.value();
0225 ++lIt;
0226 ++uIt;
0227 }
0228 #endif
0229
0230 m_lu.coeffRefLower(row, col) = newCoeff / diag;
0231 }
0232 }
0233
0234
0235 const Index col = row;
0236 typename MatrixType::InnerUpperIterator uuIt(m_lu, col);
0237 for (Index rrow = uuIt.row(); rrow < col; rrow++) {
0238
0239 typename MatrixType::InnerLowerIterator lIt(m_lu, rrow);
0240 typename MatrixType::InnerUpperIterator uIt(m_lu, col);
0241 const Index offset = lIt.col() - uIt.row();
0242
0243 Index stop = offset > 0 ? rrow - lIt.col() : rrow - uIt.row();
0244
0245 #ifdef VECTORIZE
0246 Map<VectorXd > rowVal(lIt.valuePtr() + (offset > 0 ? 0 : -offset), stop);
0247 Map<VectorXd > colVal(uIt.valuePtr() + (offset > 0 ? offset : 0), stop);
0248
0249 Scalar newCoeff = m_lu.coeffUpper(rrow, col) - rowVal.dot(colVal);
0250 #else
0251 if (offset > 0)
0252 uIt += offset;
0253 else
0254 lIt += -offset;
0255 Scalar newCoeff = m_lu.coeffUpper(rrow, col);
0256 for (Index k = 0; k < stop; ++k) {
0257 const Scalar tmp = newCoeff;
0258 newCoeff = tmp - lIt.value() * uIt.value();
0259
0260 ++lIt;
0261 ++uIt;
0262 }
0263 #endif
0264 m_lu.coeffRefUpper(rrow, col) = newCoeff;
0265 }
0266
0267
0268
0269 typename MatrixType::InnerLowerIterator lIt(m_lu, row);
0270 typename MatrixType::InnerUpperIterator uIt(m_lu, row);
0271
0272 const Index offset = lIt.col() - uIt.row();
0273
0274
0275 Index stop = offset > 0 ? lIt.size() : uIt.size();
0276 #ifdef VECTORIZE
0277 Map<VectorXd > rowVal(lIt.valuePtr() + (offset > 0 ? 0 : -offset), stop);
0278 Map<VectorXd > colVal(uIt.valuePtr() + (offset > 0 ? offset : 0), stop);
0279 Scalar newCoeff = m_lu.coeffDiag(row) - rowVal.dot(colVal);
0280 #else
0281 if (offset > 0)
0282 uIt += offset;
0283 else
0284 lIt += -offset;
0285 Scalar newCoeff = m_lu.coeffDiag(row);
0286 for (Index k = 0; k < stop; ++k) {
0287 const Scalar tmp = newCoeff;
0288 newCoeff = tmp - lIt.value() * uIt.value();
0289 ++lIt;
0290 ++uIt;
0291 }
0292 #endif
0293 m_lu.coeffRefDiag(row) = newCoeff;
0294 }
0295 }
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 template<typename MatrixType>
0306 template<typename BDerived, typename XDerived>
0307 bool SkylineInplaceLU<MatrixType>::solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>* x, const int transposed) const {
0308 const size_t rows = m_lu.rows();
0309 const size_t cols = m_lu.cols();
0310
0311
0312 for (Index row = 0; row < rows; row++) {
0313 x->coeffRef(row) = b.coeff(row);
0314 Scalar newVal = x->coeff(row);
0315 typename MatrixType::InnerLowerIterator lIt(m_lu, row);
0316
0317 Index col = lIt.col();
0318 while (lIt.col() < row) {
0319
0320 newVal -= x->coeff(col++) * lIt.value();
0321 ++lIt;
0322 }
0323
0324 x->coeffRef(row) = newVal;
0325 }
0326
0327
0328 for (Index col = rows - 1; col > 0; col--) {
0329 x->coeffRef(col) = x->coeff(col) / m_lu.coeffDiag(col);
0330
0331 const Scalar x_col = x->coeff(col);
0332
0333 typename MatrixType::InnerUpperIterator uIt(m_lu, col);
0334 uIt += uIt.size()-1;
0335
0336
0337 while (uIt) {
0338 x->coeffRef(uIt.row()) -= x_col * uIt.value();
0339
0340 uIt += -1;
0341 }
0342
0343
0344 }
0345 x->coeffRef(0) = x->coeff(0) / m_lu.coeffDiag(0);
0346
0347 return true;
0348 }
0349
0350 }
0351
0352 #endif