00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "Wm4FoundationPCH.h"
00018 #include "Wm4LinearSystem.h"
00019
00020 namespace Wm4
00021 {
00022
00023 template <class Real>
00024 LinearSystem<Real>::LinearSystem ()
00025 {
00026 ZeroTolerance = Math<Real>::ZERO_TOLERANCE;
00027 }
00028
00029 template <class Real>
00030 bool LinearSystem<Real>::Solve2 (const Real aafA[2][2], const Real afB[2],
00031 Real afX[2])
00032 {
00033 Real fDet = aafA[0][0]*aafA[1][1]-aafA[0][1]*aafA[1][0];
00034 if (Math<Real>::FAbs(fDet) < ZeroTolerance)
00035 {
00036 return false;
00037 }
00038
00039 Real fInvDet = ((Real)1.0)/fDet;
00040 afX[0] = (aafA[1][1]*afB[0]-aafA[0][1]*afB[1])*fInvDet;
00041 afX[1] = (aafA[0][0]*afB[1]-aafA[1][0]*afB[0])*fInvDet;
00042 return true;
00043 }
00044
00045 template <class Real>
00046 bool LinearSystem<Real>::Solve3 (const Real aafA[3][3], const Real afB[3],
00047 Real afX[3])
00048 {
00049 Real aafAInv[3][3];
00050 aafAInv[0][0] = aafA[1][1]*aafA[2][2]-aafA[1][2]*aafA[2][1];
00051 aafAInv[0][1] = aafA[0][2]*aafA[2][1]-aafA[0][1]*aafA[2][2];
00052 aafAInv[0][2] = aafA[0][1]*aafA[1][2]-aafA[0][2]*aafA[1][1];
00053 aafAInv[1][0] = aafA[1][2]*aafA[2][0]-aafA[1][0]*aafA[2][2];
00054 aafAInv[1][1] = aafA[0][0]*aafA[2][2]-aafA[0][2]*aafA[2][0];
00055 aafAInv[1][2] = aafA[0][2]*aafA[1][0]-aafA[0][0]*aafA[1][2];
00056 aafAInv[2][0] = aafA[1][0]*aafA[2][1]-aafA[1][1]*aafA[2][0];
00057 aafAInv[2][1] = aafA[0][1]*aafA[2][0]-aafA[0][0]*aafA[2][1];
00058 aafAInv[2][2] = aafA[0][0]*aafA[1][1]-aafA[0][1]*aafA[1][0];
00059 Real fDet = aafA[0][0]*aafAInv[0][0] + aafA[0][1]*aafAInv[1][0] +
00060 aafA[0][2]*aafAInv[2][0];
00061
00062 if (Math<Real>::FAbs(fDet) < ZeroTolerance)
00063 {
00064 return false;
00065 }
00066
00067 Real fInvDet = ((Real)1.0)/fDet;
00068 for (int iRow = 0; iRow < 3; iRow++)
00069 {
00070 for (int iCol = 0; iCol < 3; iCol++)
00071 {
00072 aafAInv[iRow][iCol] *= fInvDet;
00073 }
00074 }
00075
00076 afX[0] = aafAInv[0][0]*afB[0]+aafAInv[0][1]*afB[1]+aafAInv[0][2]*afB[2];
00077 afX[1] = aafAInv[1][0]*afB[0]+aafAInv[1][1]*afB[1]+aafAInv[1][2]*afB[2];
00078 afX[2] = aafAInv[2][0]*afB[0]+aafAInv[2][1]*afB[1]+aafAInv[2][2]*afB[2];
00079 return true;
00080 }
00081
00082 template <class Real>
00083 bool LinearSystem<Real>::Inverse (const GMatrix<Real>& rkA,
00084 GMatrix<Real>& rkInvA)
00085 {
00086
00087 assert(rkA.GetRows() == rkA.GetColumns());
00088 int iSize = rkInvA.GetRows();
00089 rkInvA = rkA;
00090
00091 int* aiColIndex = WM4_NEW int[iSize];
00092 int* aiRowIndex = WM4_NEW int[iSize];
00093 bool* abPivoted = WM4_NEW bool[iSize];
00094 memset(abPivoted,0,iSize*sizeof(bool));
00095
00096 int i1, i2, iRow = 0, iCol = 0;
00097 Real fSave;
00098
00099
00100 for (int i0 = 0; i0 < iSize; i0++)
00101 {
00102
00103 Real fMax = 0.0f;
00104 for (i1 = 0; i1 < iSize; i1++)
00105 {
00106 if (!abPivoted[i1])
00107 {
00108 for (i2 = 0; i2 < iSize; i2++)
00109 {
00110 if (!abPivoted[i2])
00111 {
00112 Real fAbs = Math<Real>::FAbs(rkInvA[i1][i2]);
00113 if (fAbs > fMax)
00114 {
00115 fMax = fAbs;
00116 iRow = i1;
00117 iCol = i2;
00118 }
00119 }
00120 }
00121 }
00122 }
00123
00124 if (fMax == (Real)0.0)
00125 {
00126
00127 WM4_DELETE[] aiColIndex;
00128 WM4_DELETE[] aiRowIndex;
00129 WM4_DELETE[] abPivoted;
00130 return false;
00131 }
00132
00133 abPivoted[iCol] = true;
00134
00135
00136 if (iRow != iCol)
00137 {
00138 rkInvA.SwapRows(iRow,iCol);
00139 }
00140
00141
00142 aiRowIndex[i0] = iRow;
00143 aiColIndex[i0] = iCol;
00144
00145
00146 Real fInv = ((Real)1.0)/rkInvA[iCol][iCol];
00147 rkInvA[iCol][iCol] = (Real)1.0;
00148 for (i2 = 0; i2 < iSize; i2++)
00149 {
00150 rkInvA[iCol][i2] *= fInv;
00151 }
00152
00153
00154 for (i1 = 0; i1 < iSize; i1++)
00155 {
00156 if (i1 != iCol)
00157 {
00158 fSave = rkInvA[i1][iCol];
00159 rkInvA[i1][iCol] = (Real)0.0;
00160 for (i2 = 0; i2 < iSize; i2++)
00161 {
00162 rkInvA[i1][i2] -= rkInvA[iCol][i2]*fSave;
00163 }
00164 }
00165 }
00166 }
00167
00168
00169 for (i1 = iSize-1; i1 >= 0; i1--)
00170 {
00171 if (aiRowIndex[i1] != aiColIndex[i1])
00172 {
00173 for (i2 = 0; i2 < iSize; i2++)
00174 {
00175 fSave = rkInvA[i2][aiRowIndex[i1]];
00176 rkInvA[i2][aiRowIndex[i1]] = rkInvA[i2][aiColIndex[i1]];
00177 rkInvA[i2][aiColIndex[i1]] = fSave;
00178 }
00179 }
00180 }
00181
00182 WM4_DELETE[] aiColIndex;
00183 WM4_DELETE[] aiRowIndex;
00184 WM4_DELETE[] abPivoted;
00185 return true;
00186 }
00187
00188 template <class Real>
00189 bool LinearSystem<Real>::Solve (const GMatrix<Real>& rkA, const Real* afB,
00190 Real* afX)
00191 {
00192
00193 int iSize = rkA.GetColumns();
00194 GMatrix<Real> kInvA = rkA;
00195 size_t uiSize = iSize*sizeof(Real);
00196 System::Memcpy(afX,uiSize,afB,uiSize);
00197
00198 int* aiColIndex = WM4_NEW int[iSize];
00199 int* aiRowIndex = WM4_NEW int[iSize];
00200 bool* abPivoted = WM4_NEW bool[iSize];
00201 memset(abPivoted,0,iSize*sizeof(bool));
00202
00203 int i1, i2, iRow = 0, iCol = 0;
00204 Real fSave;
00205
00206
00207 for (int i0 = 0; i0 < iSize; i0++)
00208 {
00209
00210 Real fMax = 0.0f;
00211 for (i1 = 0; i1 < iSize; i1++)
00212 {
00213 if (!abPivoted[i1])
00214 {
00215 for (i2 = 0; i2 < iSize; i2++)
00216 {
00217 if (!abPivoted[i2])
00218 {
00219 Real fAbs = Math<Real>::FAbs(kInvA[i1][i2]);
00220 if (fAbs > fMax)
00221 {
00222 fMax = fAbs;
00223 iRow = i1;
00224 iCol = i2;
00225 }
00226 }
00227 }
00228 }
00229 }
00230
00231 if (fMax == (Real)0.0)
00232 {
00233
00234 WM4_DELETE[] aiColIndex;
00235 WM4_DELETE[] aiRowIndex;
00236 WM4_DELETE[] abPivoted;
00237 return false;
00238 }
00239
00240 abPivoted[iCol] = true;
00241
00242
00243 if (iRow != iCol)
00244 {
00245 kInvA.SwapRows(iRow,iCol);
00246
00247 fSave = afX[iRow];
00248 afX[iRow] = afX[iCol];
00249 afX[iCol] = fSave;
00250 }
00251
00252
00253 aiRowIndex[i0] = iRow;
00254 aiColIndex[i0] = iCol;
00255
00256
00257 Real fInv = ((Real)1.0)/kInvA[iCol][iCol];
00258 kInvA[iCol][iCol] = (Real)1.0;
00259 for (i2 = 0; i2 < iSize; i2++)
00260 {
00261 kInvA[iCol][i2] *= fInv;
00262 }
00263 afX[iCol] *= fInv;
00264
00265
00266 for (i1 = 0; i1 < iSize; i1++)
00267 {
00268 if (i1 != iCol)
00269 {
00270 fSave = kInvA[i1][iCol];
00271 kInvA[i1][iCol] = (Real)0.0;
00272 for (i2 = 0; i2 < iSize; i2++)
00273 kInvA[i1][i2] -= kInvA[iCol][i2]*fSave;
00274 afX[i1] -= afX[iCol]*fSave;
00275 }
00276 }
00277 }
00278
00279
00280 for (i1 = iSize-1; i1 >= 0; i1--)
00281 {
00282 if (aiRowIndex[i1] != aiColIndex[i1])
00283 {
00284 for (i2 = 0; i2 < iSize; i2++)
00285 {
00286 fSave = kInvA[i2][aiRowIndex[i1]];
00287 kInvA[i2][aiRowIndex[i1]] = kInvA[i2][aiColIndex[i1]];
00288 kInvA[i2][aiColIndex[i1]] = fSave;
00289 }
00290 }
00291 }
00292
00293 WM4_DELETE[] aiColIndex;
00294 WM4_DELETE[] aiRowIndex;
00295 WM4_DELETE[] abPivoted;
00296 return true;
00297 }
00298
00299 template <class Real>
00300 bool LinearSystem<Real>::SolveTri (int iSize, Real* afA, Real* afB,
00301 Real* afC, Real* afR, Real* afU)
00302 {
00303 if (afB[0] == (Real)0.0)
00304 {
00305 return false;
00306 }
00307
00308 Real* afD = WM4_NEW Real[iSize-1];
00309 Real fE = afB[0];
00310 Real fInvE = ((Real)1.0)/fE;
00311 afU[0] = afR[0]*fInvE;
00312
00313 int i0, i1;
00314 for (i0 = 0, i1 = 1; i1 < iSize; i0++, i1++)
00315 {
00316 afD[i0] = afC[i0]*fInvE;
00317 fE = afB[i1] - afA[i0]*afD[i0];
00318 if (fE == (Real)0.0)
00319 {
00320 WM4_DELETE[] afD;
00321 return false;
00322 }
00323 fInvE = ((Real)1.0)/fE;
00324 afU[i1] = (afR[i1] - afA[i0]*afU[i0])*fInvE;
00325 }
00326
00327 for (i0 = iSize-1, i1 = iSize-2; i1 >= 0; i0--, i1--)
00328 {
00329 afU[i1] -= afD[i1]*afU[i0];
00330 }
00331
00332 WM4_DELETE[] afD;
00333 return true;
00334 }
00335
00336 template <class Real>
00337 bool LinearSystem<Real>::SolveConstTri (int iSize, Real fA, Real fB, Real fC,
00338 Real* afR, Real* afU)
00339 {
00340 if (fB == (Real)0.0)
00341 {
00342 return false;
00343 }
00344
00345 Real* afD = WM4_NEW Real[iSize-1];
00346 Real fE = fB;
00347 Real fInvE = ((Real)1.0)/fE;
00348 afU[0] = afR[0]*fInvE;
00349
00350 int i0, i1;
00351 for (i0 = 0, i1 = 1; i1 < iSize; i0++, i1++)
00352 {
00353 afD[i0] = fC*fInvE;
00354 fE = fB - fA*afD[i0];
00355 if (fE == (Real)0.0)
00356 {
00357 WM4_DELETE[] afD;
00358 return false;
00359 }
00360 fInvE = ((Real)1.0)/fE;
00361 afU[i1] = (afR[i1] - fA*afU[i0])*fInvE;
00362 }
00363 for (i0 = iSize-1, i1 = iSize-2; i1 >= 0; i0--, i1--)
00364 {
00365 afU[i1] -= afD[i1]*afU[i0];
00366 }
00367
00368 WM4_DELETE[] afD;
00369 return true;
00370 }
00371
00372
00373
00374
00375
00376 template <class Real>
00377 Real LinearSystem<Real>::Dot (int iSize, const Real* afU, const Real* afV)
00378 {
00379 Real fDot = (Real)0.0;
00380 for (int i = 0; i < iSize; i++)
00381 {
00382 fDot += afU[i]*afV[i];
00383 }
00384 return fDot;
00385 }
00386
00387 template <class Real>
00388 void LinearSystem<Real>::Multiply (const GMatrix<Real>& rkA, const Real* afX,
00389 Real* afProd)
00390 {
00391 int iSize = rkA.GetRows();
00392 memset(afProd,0,iSize*sizeof(Real));
00393 for (int iRow = 0; iRow < iSize; iRow++)
00394 {
00395 for (int iCol = 0; iCol < iSize; iCol++)
00396 {
00397 afProd[iRow] += rkA[iRow][iCol]*afX[iCol];
00398 }
00399 }
00400 }
00401
00402 template <class Real>
00403 void LinearSystem<Real>::Multiply (int iSize, const SparseMatrix& rkA,
00404 const Real* afX, Real* afProd)
00405 {
00406 memset(afProd,0,iSize*sizeof(Real));
00407 typename SparseMatrix::const_iterator pkIter = rkA.begin();
00408 for (; pkIter != rkA.end(); pkIter++)
00409 {
00410 int i = pkIter->first.first;
00411 int j = pkIter->first.second;
00412 Real fValue = pkIter->second;
00413 afProd[i] += fValue*afX[j];
00414 if (i != j)
00415 {
00416 afProd[j] += fValue*afX[i];
00417 }
00418 }
00419 }
00420
00421 template <class Real>
00422 void LinearSystem<Real>::UpdateX (int iSize, Real* afX, Real fAlpha,
00423 const Real* afP)
00424 {
00425 for (int i = 0; i < iSize; i++)
00426 {
00427 afX[i] += fAlpha*afP[i];
00428 }
00429 }
00430
00431 template <class Real>
00432 void LinearSystem<Real>::UpdateR (int iSize, Real* afR, Real fAlpha,
00433 const Real* afW)
00434 {
00435 for (int i = 0; i < iSize; i++)
00436 {
00437 afR[i] -= fAlpha*afW[i];
00438 }
00439 }
00440
00441 template <class Real>
00442 void LinearSystem<Real>::UpdateP (int iSize, Real* afP, Real fBeta,
00443 const Real* afR)
00444 {
00445 for (int i = 0; i < iSize; i++)
00446 {
00447 afP[i] = afR[i] + fBeta*afP[i];
00448 }
00449 }
00450
00451 template <class Real>
00452 bool LinearSystem<Real>::SolveSymmetricCG (const GMatrix<Real>& rkA,
00453 const Real* afB, Real* afX)
00454 {
00455
00456 assert(rkA.GetRows() == rkA.GetColumns());
00457 int iSize = rkA.GetRows();
00458 Real* afR = WM4_NEW Real[iSize];
00459 Real* afP = WM4_NEW Real[iSize];
00460 Real* afW = WM4_NEW Real[iSize];
00461
00462
00463 size_t uiSize = iSize*sizeof(Real);
00464 memset(afX,0,uiSize);
00465 System::Memcpy(afR,uiSize,afB,uiSize);
00466 Real fRho0 = Dot(iSize,afR,afR);
00467 System::Memcpy(afP,uiSize,afR,uiSize);
00468 Multiply(rkA,afP,afW);
00469 Real fAlpha = fRho0/Dot(iSize,afP,afW);
00470 UpdateX(iSize,afX,fAlpha,afP);
00471 UpdateR(iSize,afR,fAlpha,afW);
00472 Real fRho1 = Dot(iSize,afR,afR);
00473
00474
00475 const int iMax = 1024;
00476 int i;
00477 for (i = 1; i < iMax; i++)
00478 {
00479 Real fRoot0 = Math<Real>::Sqrt(fRho1);
00480 Real fNorm = Dot(iSize,afB,afB);
00481 Real fRoot1 = Math<Real>::Sqrt(fNorm);
00482 if (fRoot0 <= ZeroTolerance*fRoot1)
00483 {
00484 break;
00485 }
00486
00487 Real fBeta = fRho1/fRho0;
00488 UpdateP(iSize,afP,fBeta,afR);
00489 Multiply(rkA,afP,afW);
00490 fAlpha = fRho1/Dot(iSize,afP,afW);
00491 UpdateX(iSize,afX,fAlpha,afP);
00492 UpdateR(iSize,afR,fAlpha,afW);
00493 fRho0 = fRho1;
00494 fRho1 = Dot(iSize,afR,afR);
00495 }
00496
00497 WM4_DELETE[] afW;
00498 WM4_DELETE[] afP;
00499 WM4_DELETE[] afR;
00500
00501 return i < iMax;
00502 }
00503
00504 template <class Real>
00505 bool LinearSystem<Real>::SolveSymmetricCG (int iSize,
00506 const SparseMatrix& rkA, const Real* afB, Real* afX)
00507 {
00508
00509 Real* afR = WM4_NEW Real[iSize];
00510 Real* afP = WM4_NEW Real[iSize];
00511 Real* afW = WM4_NEW Real[iSize];
00512
00513
00514 size_t uiSize = iSize*sizeof(Real);
00515 memset(afX,0,uiSize);
00516 System::Memcpy(afR,uiSize,afB,uiSize);
00517 Real fRho0 = Dot(iSize,afR,afR);
00518 System::Memcpy(afP,uiSize,afR,uiSize);
00519 Multiply(iSize,rkA,afP,afW);
00520 Real fAlpha = fRho0/Dot(iSize,afP,afW);
00521 UpdateX(iSize,afX,fAlpha,afP);
00522 UpdateR(iSize,afR,fAlpha,afW);
00523 Real fRho1 = Dot(iSize,afR,afR);
00524
00525
00526 const int iMax = 1024;
00527 int i;
00528 for (i = 1; i < iMax; i++)
00529 {
00530 Real fRoot0 = Math<Real>::Sqrt(fRho1);
00531 Real fNorm = Dot(iSize,afB,afB);
00532 Real fRoot1 = Math<Real>::Sqrt(fNorm);
00533 if (fRoot0 <= ZeroTolerance*fRoot1)
00534 {
00535 break;
00536 }
00537
00538 Real fBeta = fRho1/fRho0;
00539 UpdateP(iSize,afP,fBeta,afR);
00540 Multiply(iSize,rkA,afP,afW);
00541 fAlpha = fRho1/Dot(iSize,afP,afW);
00542 UpdateX(iSize,afX,fAlpha,afP);
00543 UpdateR(iSize,afR,fAlpha,afW);
00544 fRho0 = fRho1;
00545 fRho1 = Dot(iSize,afR,afR);
00546 }
00547
00548 WM4_DELETE[] afW;
00549 WM4_DELETE[] afP;
00550 WM4_DELETE[] afR;
00551
00552 return i < iMax;
00553 }
00554
00555
00556
00557
00558
00559 template <class Real>
00560 bool LinearSystem<Real>::ForwardEliminate (int iReduceRow,
00561 BandedMatrix<Real>& rkA, Real* afB)
00562 {
00563
00564 Real fDiag = rkA(iReduceRow,iReduceRow);
00565 if (fDiag == (Real)0.0)
00566 {
00567 return false;
00568 }
00569
00570 Real fInvDiag = ((Real)1.0)/fDiag;
00571 rkA(iReduceRow,iReduceRow) = (Real)1.0;
00572
00573
00574 int iColMin = iReduceRow + 1;
00575 int iColMax = iColMin + rkA.GetUBands();
00576 if (iColMax > rkA.GetSize())
00577 {
00578 iColMax = rkA.GetSize();
00579 }
00580
00581 int iCol;
00582 for (iCol = iColMin; iCol < iColMax; iCol++)
00583 {
00584 rkA(iReduceRow,iCol) *= fInvDiag;
00585 }
00586
00587 afB[iReduceRow] *= fInvDiag;
00588
00589
00590 int iRowMin = iReduceRow + 1;
00591 int iRowMax = iRowMin + rkA.GetLBands();
00592 if (iRowMax > rkA.GetSize())
00593 {
00594 iRowMax = rkA.GetSize();
00595 }
00596
00597 for (int iRow = iRowMin; iRow < iRowMax; iRow++)
00598 {
00599 Real fMult = rkA(iRow,iReduceRow);
00600 rkA(iRow,iReduceRow) = (Real)0.0;
00601 for (iCol = iColMin; iCol < iColMax; iCol++)
00602 {
00603 rkA(iRow,iCol) -= fMult*rkA(iReduceRow,iCol);
00604 }
00605 afB[iRow] -= fMult*afB[iReduceRow];
00606 }
00607
00608 return true;
00609 }
00610
00611 template <class Real>
00612 bool LinearSystem<Real>::SolveBanded (const BandedMatrix<Real>& rkA,
00613 const Real* afB, Real* afX)
00614 {
00615 BandedMatrix<Real> kTmp = rkA;
00616 int iSize = rkA.GetSize();
00617 size_t uiSize = iSize*sizeof(Real);
00618 System::Memcpy(afX,uiSize,afB,uiSize);
00619
00620
00621 int iRow;
00622 for (iRow = 0; iRow < iSize; iRow++)
00623 {
00624 if (!ForwardEliminate(iRow,kTmp,afX))
00625 {
00626 return false;
00627 }
00628 }
00629
00630
00631 for (iRow = iSize-2; iRow >= 0; iRow--)
00632 {
00633 int iColMin = iRow + 1;
00634 int iColMax = iColMin + kTmp.GetUBands();
00635 if (iColMax > iSize)
00636 {
00637 iColMax = iSize;
00638 }
00639 for (int iCol = iColMin; iCol < iColMax; iCol++)
00640 {
00641 afX[iRow] -= kTmp(iRow,iCol)*afX[iCol];
00642 }
00643 }
00644
00645 return true;
00646 }
00647
00648 template <class Real>
00649 bool LinearSystem<Real>::ForwardEliminate (int iReduceRow,
00650 BandedMatrix<Real>& rkA, GMatrix<Real>& rkB)
00651 {
00652
00653 Real fDiag = rkA(iReduceRow,iReduceRow);
00654 if (fDiag == (Real)0.0)
00655 {
00656 return false;
00657 }
00658
00659 Real fInvDiag = ((Real)1.0)/fDiag;
00660 rkA(iReduceRow,iReduceRow) = (Real)1.0;
00661
00662
00663 int iColMin = iReduceRow + 1;
00664 int iColMax = iColMin + rkA.GetUBands();
00665 if (iColMax > rkA.GetSize())
00666 {
00667 iColMax = rkA.GetSize();
00668 }
00669
00670 int iCol;
00671 for (iCol = iColMin; iCol < iColMax; iCol++)
00672 {
00673 rkA(iReduceRow,iCol) *= fInvDiag;
00674 }
00675 for (iCol = 0; iCol <= iReduceRow; iCol++)
00676 {
00677 rkB(iReduceRow,iCol) *= fInvDiag;
00678 }
00679
00680
00681 int iRowMin = iReduceRow + 1;
00682 int iRowMax = iRowMin + rkA.GetLBands();
00683 if (iRowMax > rkA.GetSize())
00684 {
00685 iRowMax = rkA.GetSize();
00686 }
00687
00688 for (int iRow = iRowMin; iRow < iRowMax; iRow++)
00689 {
00690 Real fMult = rkA(iRow,iReduceRow);
00691 rkA(iRow,iReduceRow) = (Real)0.0;
00692 for (iCol = iColMin; iCol < iColMax; iCol++)
00693 {
00694 rkA(iRow,iCol) -= fMult*rkA(iReduceRow,iCol);
00695 }
00696 for (iCol = 0; iCol <= iReduceRow; iCol++)
00697 {
00698 rkB(iRow,iCol) -= fMult*rkB(iReduceRow,iCol);
00699 }
00700 }
00701
00702 return true;
00703 }
00704
00705 template <class Real>
00706 void LinearSystem<Real>::BackwardEliminate (int iReduceRow,
00707 BandedMatrix<Real>& rkA, GMatrix<Real>& rkB)
00708 {
00709 int iRowMax = iReduceRow - 1;
00710 int iRowMin = iReduceRow - rkA.GetUBands();
00711 if (iRowMin < 0)
00712 {
00713 iRowMin = 0;
00714 }
00715
00716 for (int iRow = iRowMax; iRow >= iRowMin; iRow--)
00717 {
00718 Real fMult = rkA(iRow,iReduceRow);
00719 rkA(iRow,iReduceRow) = (Real)0.0;
00720 for (int iCol = 0; iCol < rkB.GetColumns(); iCol++)
00721 {
00722 rkB(iRow,iCol) -= fMult*rkB(iReduceRow,iCol);
00723 }
00724 }
00725 }
00726
00727 template <class Real>
00728 bool LinearSystem<Real>::Invert (const BandedMatrix<Real>& rkA,
00729 GMatrix<Real>& rkInvA)
00730 {
00731 int iSize = rkA.GetSize();
00732 BandedMatrix<Real> kTmp = rkA;
00733 int iRow;
00734 for (iRow = 0; iRow < iSize; iRow++)
00735 {
00736 for (int iCol = 0; iCol < iSize; iCol++)
00737 {
00738 if (iRow != iCol)
00739 {
00740 rkInvA(iRow,iCol) = (Real)0.0;
00741 }
00742 else
00743 {
00744 rkInvA(iRow,iRow) = (Real)1.0;
00745 }
00746 }
00747 }
00748
00749
00750 for (iRow = 0; iRow < iSize; iRow++)
00751 {
00752 if (!ForwardEliminate(iRow,kTmp,rkInvA))
00753 {
00754 return false;
00755 }
00756 }
00757
00758
00759 for (iRow = iSize-1; iRow >= 1; iRow--)
00760 {
00761 BackwardEliminate(iRow,kTmp,rkInvA);
00762 }
00763
00764 return true;
00765 }
00766
00767
00768
00769
00770
00771 template WM4_FOUNDATION_ITEM
00772 class LinearSystem<float>;
00773
00774 template WM4_FOUNDATION_ITEM
00775 class LinearSystem<double>;
00776
00777 }