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 #ifndef __OPENKN_GAUSSIAN_ELIMINATION_HPP__
00027 #define __OPENKN_GAUSSIAN_ELIMINATION_HPP__
00028
00029
00030
00031
00032 #include <algorithm>
00033 #include <vector>
00034
00035
00036
00037
00038 #include "MathException.hpp"
00039 #include "Matrix.hpp"
00040 #include "Vector.hpp"
00041
00042
00043 namespace kn{
00044
00054 template <class T>
00055 unsigned int gaussianElimination(Matrix<T> & A, Vector<T> &b, Vector<T> &x, const bool total = false){
00056 if(total) return gaussianEliminationTotal(A,b,x);
00057 else return gaussianEliminationPartial(A,b,x);
00058 }
00059
00060
00069 template <class T>
00070 unsigned int gaussianEliminationPartial(Matrix<T> & A, Vector<T> &b, Vector<T> &x){
00071
00072 const double gaussianEliminationZero = 1.0e-10;
00073
00074
00075 if(A.columns() != A.rows())
00076 throw MathException("The input matrix is not a square matrix" ,"gaussianEliminationPartial");
00077
00078 if(A.columns() != b.size())
00079 throw MathException("The input matrix is not compatible with the 'b' vector" ,"gaussianEliminationPartial");
00080
00081 if(A.rows() != x.size())
00082 throw MathException("The input matrix is not compatible with the 'x' vector" ,"gaussianEliminationPartial");
00083
00084
00085 unsigned int nbIteration = 0;
00086 while(nbIteration < A.columns()-1){
00087
00088
00089 T maxValue;
00090 unsigned int maxValueRow;
00091 gaussianEliminationFindPartialPivot(A,nbIteration,maxValueRow,maxValue);
00092
00093
00094 if(fabs(maxValue) < gaussianEliminationZero)
00095 return 0;
00096
00097
00098 if(maxValueRow != nbIteration){
00099
00100 std::swap_ranges(&(A[maxValueRow][nbIteration]),A[maxValueRow]+A.columns(),&(A[nbIteration][nbIteration]));
00101
00102 std::swap(b[maxValueRow],b[nbIteration]);
00103 }
00104
00105
00106 if(fabs(A[nbIteration][nbIteration]) < gaussianEliminationZero) return 0;
00107
00108
00109 gaussianRowsElimination(A,b,nbIteration);
00110
00111
00112 ++nbIteration;
00113 }
00114
00115
00116 if(fabs(A[nbIteration][nbIteration]) < gaussianEliminationZero) return 0;
00117
00118
00119 gaussianBackSubstitutionPartial(A,b,x);
00120
00121 return 1;
00122 }
00123
00124
00133 template <class T>
00134 unsigned int gaussianEliminationTotal(Matrix<T> & A, Vector<T> &b, Vector<T> &x){
00135
00136 const double gaussianEliminationZero = 1.0e-10;
00137
00138
00139 if(A.columns() != A.rows())
00140 throw MathException("The input matrix is not a square matrix" ,"gaussianEliminationPartial");
00141
00142 if(A.columns() != b.size())
00143 throw MathException("The input matrix is not compatible with the 'b' vector" ,"gaussianEliminationPartial");
00144
00145 if(A.rows() != x.size())
00146 throw MathException("The input matrix is not compatible with the 'x' vector" ,"gaussianEliminationPartial");
00147
00148
00149 std::vector<unsigned int> sorter(x.size());
00150 for(unsigned int i=0; i<sorter.size(); ++i)
00151 sorter[i] = i;
00152
00153
00154 unsigned int nbIteration = 0;
00155 while(nbIteration < A.columns()-1){
00156
00157
00158 T maxValue;
00159 unsigned int maxValueRow,maxValueCol;
00160 gaussianEliminationFindTotalPivot(A,nbIteration,maxValueRow,maxValueCol,maxValue);
00161
00162
00163 if(fabs(maxValue) < gaussianEliminationZero)
00164 return 0;
00165
00166
00167 if(maxValueRow != nbIteration){
00168
00169 std::swap_ranges(&(A[maxValueRow][nbIteration]),A[maxValueRow]+A.columns(),&(A[nbIteration][nbIteration]));
00170
00171 std::swap(b[maxValueRow],b[nbIteration]);
00172 }
00173
00174
00175 if(maxValueCol != nbIteration){
00176
00177 A.swapColumns(maxValueCol,nbIteration);
00178
00179 std::swap(sorter[maxValueCol],sorter[nbIteration]);
00180 }
00181
00182
00183 gaussianRowsElimination(A,b,nbIteration);
00184
00185
00186 ++nbIteration;
00187 }
00188
00189
00190 if(fabs(A[nbIteration][nbIteration]) < gaussianEliminationZero) return 0;
00191
00192
00193 gaussianBackSubstitutionTotal(A,b,x,sorter);
00194
00195 return 1;
00196 }
00197
00198
00207 template <class T>
00208 unsigned int gaussianEliminationInverseMatrix(const Matrix<T> & A, Matrix<T> & Ainverse, const bool total = false){
00209 if(total) return gaussianEliminationInverseMatrixTotal(A,Ainverse);
00210 else return gaussianEliminationInverseMatrixPartial(A,Ainverse);
00211 }
00212
00213
00221 template <class T>
00222 unsigned int gaussianEliminationInverseMatrixPartial(const Matrix<T> & A_, Matrix<T> & Ainverse){
00223
00224 const double gaussianEliminationZero = 1.0e-10;
00225
00226
00227 Matrix<T> A(A_);
00228
00229
00230 if(A.columns() != A.rows())
00231 throw MathException("The input matrix is not a square matrix" ,"gaussianEliminationInverseMatrixPartial");
00232
00233 if(Ainverse.columns() != Ainverse.rows())
00234 throw MathException("The output matrix is not compatible with the 'b' vector" ,"gaussianEliminationInverseMatrixPartial");
00235
00236 if(A.rows() != Ainverse.rows())
00237 throw MathException("The input an d output matrices size are not compatible" ,"gaussianEliminationInverseMatrixPartial");
00238
00239
00240 Matrix<T> Id(A.rows(),A.columns());
00241 Id.setIdentity();
00242
00243
00244 unsigned int nbIteration = 0;
00245 while(nbIteration < A.columns()-1){
00246
00247
00248 T maxValue;
00249 unsigned int maxValueRow;
00250 gaussianEliminationFindPartialPivot(A,nbIteration,maxValueRow,maxValue);
00251
00252
00253 if(fabs(maxValue) < gaussianEliminationZero)
00254 return 0;
00255
00256
00257 if(maxValueRow != nbIteration){
00258
00259 std::swap_ranges(&(A[maxValueRow][nbIteration]),A[maxValueRow]+A.columns(),&(A[nbIteration][nbIteration]));
00260
00261 Id.swapRows(maxValueRow,nbIteration);
00262 }
00263
00264
00265 gaussianRowsElimination(A,Id,nbIteration);
00266
00267
00268 ++nbIteration;
00269 }
00270
00271
00272 if(fabs(A[nbIteration][nbIteration]) < gaussianEliminationZero) return 0;
00273
00274
00275 gaussianBackSubstitutionPartial(A,Id,Ainverse);
00276
00277 return 1;
00278 }
00279
00280
00288 template <class T>
00289 unsigned int gaussianEliminationInverseMatrixTotal(const Matrix<T> & A_, Matrix<T> & Ainverse){
00290
00291 const double gaussianEliminationZero = 1.0e-10;
00292
00293
00294 Matrix<T> A(A_);
00295
00296
00297 if(A.columns() != A.rows())
00298 throw MathException("The input matrix is not a square matrix" ,"gaussianEliminationInverseMatrixPartial");
00299
00300 if(Ainverse.columns() != Ainverse.rows())
00301 throw MathException("The output matrix is not compatible with the 'b' vector" ,"gaussianEliminationInverseMatrixPartial");
00302
00303 if(A.rows() != Ainverse.rows())
00304 throw MathException("The input an d output matrices size are not compatible" ,"gaussianEliminationInverseMatrixPartial");
00305
00306
00307 Matrix<T> Id(A.rows(),A.columns());
00308 Id.setIdentity();
00309
00310
00311 std::vector<unsigned int> sorter(Id.rows());
00312 for(unsigned int i=0; i<sorter.size(); ++i)
00313 sorter[i] = i;
00314
00315
00316 unsigned int nbIteration = 0;
00317 while(nbIteration < A.columns()-1){
00318
00319
00320 T maxValue;
00321 unsigned int maxValueRow,maxValueCol;
00322 gaussianEliminationFindTotalPivot(A,nbIteration,maxValueRow,maxValueCol,maxValue);
00323
00324
00325 if(fabs(maxValue) < gaussianEliminationZero)
00326 return 0;
00327
00328
00329 if(maxValueRow != nbIteration){
00330
00331 std::swap_ranges(&(A[maxValueRow][nbIteration]),A[maxValueRow]+A.columns(),&(A[nbIteration][nbIteration]));
00332
00333 Id.swapRows(maxValueRow,nbIteration);
00334 }
00335
00336
00337 if(maxValueCol != nbIteration){
00338
00339 A.swapColumns(maxValueCol,nbIteration);
00340
00341 std::swap(sorter[maxValueCol],sorter[nbIteration]);
00342 }
00343
00344
00345 gaussianRowsElimination(A,Id,nbIteration);
00346
00347
00348 ++nbIteration;
00349 }
00350
00351
00352 if(fabs(A[nbIteration][nbIteration]) < gaussianEliminationZero) return 0;
00353
00354
00355 gaussianBackSubstitutionTotal(A,Id,Ainverse,sorter);
00356
00357 return 1;
00358 }
00359
00360
00368 template <class T>
00369 void gaussianBackSubstitutionPartial(const Matrix<T> & A, const Vector<T> &b, Vector<T> &x){
00370 for(int i=int(A.rows())-1; i>=0; --i){
00371 T numerator = T(0);
00372 for(int j=i+1; j<int(A.columns()); ++j)
00373 numerator += A[i][j] * x[j];
00374
00375 x[i] = (b[i] - numerator) / A[i][i];
00376 }
00377 }
00379
00380
00388 template <class T>
00389 void gaussianBackSubstitutionPartial(const Matrix<T> & A, const Matrix<T> &B, Matrix<T> &X){
00390 for(unsigned int m=0; m<X.columns(); ++m)
00391 for(int i=int(A.rows())-1; i>=0; --i){
00392 T numerator = T(0);
00393 for(int j=i+1; j<int(A.columns()); ++j)
00394 numerator += A[i][j] * X[j][m];
00395
00396 X[i][m] = (B[i][m] - numerator) / A[i][i];
00397 }
00398 }
00400
00401
00410 template <class T>
00411 void gaussianBackSubstitutionTotal(const Matrix<T> & A, const Vector<T> &b, Vector<T> &x, const std::vector<unsigned int> &sorter){
00412 for(int i=int(A.rows())-1; i>=0; --i){
00413 T numerator = T(0);
00414 for(int j=i+1; j<int(A.columns()); ++j)
00415 numerator += A[i][j] * x[sorter[j]];
00416
00417 x[sorter[i]] = (b[i] - numerator) / A[i][i];
00418 }
00419 }
00421
00422
00431 template <class T>
00432 void gaussianBackSubstitutionTotal(const Matrix<T> & A, const Matrix<T> &B, Matrix<T> &X, const std::vector<unsigned int> &sorter){
00433 for(unsigned int m=0; m<X.columns(); ++m)
00434 for(int i=int(A.rows())-1; i>=0; --i){
00435 T numerator = T(0);
00436 for(int j=i+1; j<int(A.columns()); ++j)
00437 numerator += A[i][j] * X[sorter[j]][m];
00438
00439 X[sorter[i]][m] = (B[i][m] - numerator) / A[i][i];
00440 }
00441 }
00443
00444
00453 template <class T>
00454 void gaussianEliminationFindPartialPivot(const Matrix<T> & A, const unsigned int nbIteration,
00455 unsigned int & maxValueRow, T & maxValue){
00456
00457 maxValueRow = nbIteration;
00458 maxValue = A[nbIteration][nbIteration];
00459
00460 for(unsigned int i = nbIteration+1 ; i < A.rows(); ++i) {
00461 T tmp = T(fabs((A[i][nbIteration])));
00462 if((tmp > maxValue)){
00463 maxValueRow = i;
00464 maxValue = tmp;
00465 }
00466 }
00467 }
00469
00470
00480 template <class T>
00481 void gaussianEliminationFindTotalPivot(const Matrix<T> & A, const unsigned int nbIteration,
00482 unsigned int & maxValueRow, unsigned int & maxValueCol, T & maxValue){
00483
00484 maxValueRow = maxValueCol = nbIteration;
00485 maxValue = A[nbIteration][nbIteration];
00486
00487 for(unsigned int i = nbIteration ; i < A.rows(); ++i)
00488 for(unsigned int j = nbIteration ; j < A.columns(); ++j) {
00489 T tmp = T(fabs((A[i][j])));
00490 if((tmp > maxValue)){
00491 maxValueRow = i;
00492 maxValueCol = j;
00493 maxValue = tmp;
00494 }
00495 }
00496 }
00498
00499
00507 template <class T>
00508 void gaussianRowsElimination(Matrix<T> & A, Vector<T> & b, const unsigned int nbIteration){
00509
00510 for(unsigned int i = nbIteration+1; i < A.rows(); ++i){
00511 T tmp = T(A[i][nbIteration] / A[nbIteration][nbIteration]);
00512
00513
00514 A[i][nbIteration] = T(0);
00515 for(unsigned int j = nbIteration+1; j < A.columns(); ++j){
00516 A[i][j] -= tmp * A[nbIteration][j];
00517 }
00518
00519
00520 b[i] -= tmp * b[nbIteration];
00521 }
00522 }
00524
00525
00533 template <class T>
00534 void gaussianRowsElimination(Matrix<T> & A, Matrix<T> & Id, const unsigned int nbIteration){
00535
00536 for(unsigned int i = nbIteration+1; i < A.rows(); ++i){
00537 T tmp = T(A[i][nbIteration] / A[nbIteration][nbIteration]);
00538
00539
00540 A[i][nbIteration] = T(0);
00541 for(unsigned int j = nbIteration+1; j < A.columns(); ++j){
00542 A[i][j] -= tmp * A[nbIteration][j];
00543 }
00544
00545
00546 for(unsigned int j = 0; j < Id.columns(); ++j){
00547 Id[i][j] -= tmp * Id[nbIteration][j];
00548 }
00549 }
00550 }
00552
00553
00554
00555
00556
00557 }
00558
00559
00560
00561
00562 #endif