Wm4LinearSystem.cpp

Go to the documentation of this file.
00001 // Wild Magic Source Code
00002 // David Eberly
00003 // http://www.geometrictools.com
00004 // Copyright (c) 1998-2007
00005 //
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation; either version 2.1 of the License, or (at
00009 // your option) any later version.  The license is available for reading at
00010 // either of the locations:
00011 //     http://www.gnu.org/copyleft/lgpl.html
00012 //     http://www.geometrictools.com/License/WildMagicLicense.pdf
00013 // The license applies to versions 0 through 4 of Wild Magic.
00014 //
00015 // Version: 4.0.0 (2006/06/28)
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     // computations are performed in-place
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     // elimination by full pivoting
00100     for (int i0 = 0; i0 < iSize; i0++)
00101     {
00102         // search matrix (excluding pivoted rows) for maximum absolute entry
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             // matrix is not invertible
00127             WM4_DELETE[] aiColIndex;
00128             WM4_DELETE[] aiRowIndex;
00129             WM4_DELETE[] abPivoted;
00130             return false;
00131         }
00132 
00133         abPivoted[iCol] = true;
00134 
00135         // swap rows so that A[iCol][iCol] contains the pivot entry
00136         if (iRow != iCol)
00137         {
00138             rkInvA.SwapRows(iRow,iCol);
00139         }
00140 
00141         // keep track of the permutations of the rows
00142         aiRowIndex[i0] = iRow;
00143         aiColIndex[i0] = iCol;
00144 
00145         // scale the row so that the pivot entry is 1
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         // zero out the pivot column locations in the other rows
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     // reorder rows so that A[][] stores the inverse of the original matrix
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     // computations are performed in-place
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     // elimination by full pivoting
00207     for (int i0 = 0; i0 < iSize; i0++)
00208     {
00209         // search matrix (excluding pivoted rows) for maximum absolute entry
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             // matrix is not invertible
00234             WM4_DELETE[] aiColIndex;
00235             WM4_DELETE[] aiRowIndex;
00236             WM4_DELETE[] abPivoted;
00237             return false;
00238         }
00239 
00240         abPivoted[iCol] = true;
00241 
00242         // swap rows so that A[iCol][iCol] contains the pivot entry
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         // keep track of the permutations of the rows
00253         aiRowIndex[i0] = iRow;
00254         aiColIndex[i0] = iCol;
00255 
00256         // scale the row so that the pivot entry is 1
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         // zero out the pivot column locations in the other rows
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     // reorder rows so that A[][] stores the inverse of the original matrix
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 // conjugate gradient methods
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     // based on the algorithm in "Matrix Computations" by Golum and Van Loan
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     // first iteration
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     // remaining iterations
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     // based on the algorithm in "Matrix Computations" by Golum and Van Loan
00509     Real* afR = WM4_NEW Real[iSize];
00510     Real* afP = WM4_NEW Real[iSize];
00511     Real* afW = WM4_NEW Real[iSize];
00512 
00513     // first iteration
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     // remaining iterations
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 // banded matrices
00558 //----------------------------------------------------------------------------
00559 template <class Real>
00560 bool LinearSystem<Real>::ForwardEliminate (int iReduceRow,
00561     BandedMatrix<Real>& rkA, Real* afB)
00562 {
00563     // the pivot must be nonzero in order to proceed
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     // multiply row to be consistent with diagonal term of 1
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     // reduce remaining rows
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     // forward elimination
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     // backward substitution
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     // the pivot must be nonzero in order to proceed
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     // multiply row to be consistent with diagonal term of 1
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     // reduce remaining rows
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     // forward elimination
00750     for (iRow = 0; iRow < iSize; iRow++)
00751     {
00752         if (!ForwardEliminate(iRow,kTmp,rkInvA))
00753         {
00754             return false;
00755         }
00756     }
00757 
00758     // backward elimination
00759     for (iRow = iSize-1; iRow >= 1; iRow--)
00760     {
00761         BackwardEliminate(iRow,kTmp,rkInvA);
00762     }
00763 
00764     return true;
00765 }
00766 //----------------------------------------------------------------------------
00767 
00768 //----------------------------------------------------------------------------
00769 // explicit instantiation
00770 //----------------------------------------------------------------------------
00771 template WM4_FOUNDATION_ITEM
00772 class LinearSystem<float>;
00773 
00774 template WM4_FOUNDATION_ITEM
00775 class LinearSystem<double>;
00776 //----------------------------------------------------------------------------
00777 }

Generated on Wed Nov 23 19:01:04 2011 for FreeCAD by  doxygen 1.6.1