computation/basic_functions/Functions_MatVect.cxx

00001 // Copyright (C) 2001-2009 Vivien Mallet
00002 //
00003 // This file is part of the linear-algebra library Seldon,
00004 // http://seldon.sourceforge.net/.
00005 //
00006 // Seldon is free software; you can redistribute it and/or modify it under the
00007 // terms of the GNU Lesser General Public License as published by the Free
00008 // Software Foundation; either version 2.1 of the License, or (at your option)
00009 // any later version.
00010 //
00011 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
00014 // more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public License
00017 // along with Seldon. If not, see http://www.gnu.org/licenses/.
00018 
00019 
00020 #ifndef SELDON_FILE_FUNCTIONS_MATVECT_CXX
00021 #define SELDON_FILE_FUNCTIONS_MATVECT_CXX
00022 
00023 
00024 #include "Functions_MatVect.hxx"
00025 
00026 
00027 /*
00028   Functions defined in this file:
00029 
00030   M X -> Y
00031   Mlt(M, X, Y)
00032 
00033   alpha M X -> Y
00034   Mlt(alpha, M, X, Y)
00035 
00036   M X -> Y
00037   M^T X -> Y
00038   Mlt(Trans, M, X, Y)
00039 
00040   alpha M X + beta Y -> Y
00041   MltAdd(alpha, M, X, beta, Y)
00042 
00043   Gauss(M, X)
00044 
00045   GaussSeidel(M, X, Y, iter)
00046 
00047   SOR(M, X, Y, omega, iter)
00048 
00049   SolveLU(M, Y)
00050 
00051   Solve(M, Y)
00052 */
00053 
00054 
00055 namespace Seldon
00056 {
00057 
00058 
00060   // MLT //
00061 
00062 
00064 
00072   template <class T0, class Prop0, class Storage0, class Allocator0,
00073             class T1, class Storage1, class Allocator1,
00074             class T2, class Storage2, class Allocator2>
00075   void Mlt(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
00076            const Vector<T1, Storage1, Allocator1>& X,
00077            Vector<T2, Storage2, Allocator2>& Y)
00078   {
00079     Y.Fill(T2(0));
00080     MltAdd(T2(1), M, X, T2(0), Y);
00081   }
00082 
00083 
00085 
00096   template <class T1, class Prop1, class Storage1, class Allocator1,
00097             class T2, class Storage2, class Allocator2,
00098             class T3, class Storage3, class Allocator3>
00099   void Mlt(const T3& alpha,
00100            const Matrix<T1, Prop1, Storage1, Allocator1>& M,
00101            const Vector<T2, Storage2, Allocator2>& X,
00102            Vector<T3, Storage3, Allocator3>& Y)
00103   {
00104     Y.Fill(T2(0));
00105     MltAdd(alpha, M, X, T3(0), Y);
00106   }
00107 
00108 
00110 
00120   template <class T1, class Prop1, class Storage1, class Allocator1,
00121             class T2, class Storage2, class Allocator2,
00122             class T3, class Storage3, class Allocator3>
00123   void Mlt(const SeldonTranspose& Trans,
00124            const Matrix<T1, Prop1, Storage1, Allocator1>& M,
00125            const Vector<T2, Storage2, Allocator2>& X,
00126            Vector<T3, Storage3, Allocator3>& Y)
00127   {
00128     Y.Fill(T2(0));
00129     MltAdd(T2(1), Trans, M, X, T3(0), Y);
00130   }
00131 
00132 
00133   // MLT //
00135 
00136 
00138   // MLTADD //
00139 
00140 
00141   /*** PETSc matrices ***/
00142 
00143 
00144   template <class T0,
00145             class T1, class Prop1, class Allocator1,
00146             class T2, class Allocator2,
00147             class T3,
00148             class T4, class Allocator4>
00149   void MltAdd(const T0 alpha,
00150               const Matrix<T1, Prop1, PETScMPIAIJ, Allocator1>& M,
00151               const Vector<T2, PETScSeq, Allocator2>& X,
00152               const T3 beta, Vector<T4, PETScSeq, Allocator4>& Y)
00153   {
00154 #ifdef SELDON_CHECK_DIMENSIONS
00155     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00156 #endif
00157     if (beta == T3(0))
00158       if (alpha == T0(0))
00159         {
00160           Y.Fill(T4(0));
00161           return;
00162         }
00163       else
00164         {
00165           MatMult(M.GetPetscMatrix(), X.GetPetscVector(), Y.GetPetscVector());
00166           if (alpha != T0(1))
00167             VecScale(Y.GetPetscVector(), alpha);
00168           return;
00169         }
00170     if (alpha == T0(1))
00171       {
00172         if (beta != T3(1))
00173           VecScale(Y.GetPetscVector(), beta);
00174         MatMultAdd(M.GetPetscMatrix(), X.GetPetscVector(),
00175                    Y.GetPetscVector(),Y.GetPetscVector());
00176         return;
00177       }
00178     Vector<T2, PETScSeq, Allocator2> tmp;
00179     tmp.Copy(Y);
00180     MatMult(M.GetPetscMatrix(), X.GetPetscVector(), tmp.GetPetscVector());
00181     VecAXPBY(Y.GetPetscVector(), alpha, beta, tmp.GetPetscVector());
00182     return;
00183   }
00184 
00185 
00186   template <class T0,
00187             class T1, class Prop1, class Allocator1,
00188             class T2, class Allocator2,
00189             class T3,
00190             class T4, class Allocator4>
00191   void MltAdd(const T0 alpha,
00192               const Matrix<T1, Prop1, PETScMPIAIJ, Allocator1>& M,
00193               const Vector<T2, PETScPar, Allocator2>& X,
00194               const T3 beta, Vector<T4, PETScPar, Allocator4>& Y)
00195   {
00196 #ifdef SELDON_CHECK_DIMENSIONS
00197     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00198 #endif
00199     if (beta == T3(0))
00200       if (alpha == T0(0))
00201         {
00202           Y.Fill(T4(0));
00203           return;
00204         }
00205       else
00206         {
00207           MatMult(M.GetPetscMatrix(), X.GetPetscVector(), Y.GetPetscVector());
00208           if (alpha != T0(1))
00209             VecScale(Y.GetPetscVector(), alpha);
00210           return;
00211         }
00212     if (alpha == T0(1))
00213       {
00214         if (beta != T3(1))
00215           VecScale(Y.GetPetscVector(), beta);
00216         MatMultAdd(M.GetPetscMatrix(), X.GetPetscVector(),
00217                    Y.GetPetscVector(),Y.GetPetscVector());
00218         return;
00219       }
00220     Vector<T2, PETScPar, Allocator2> tmp;
00221     tmp.Copy(Y);
00222     MatMult(M.GetPetscMatrix(), X.GetPetscVector(), tmp.GetPetscVector());
00223     VecAXPBY(Y.GetPetscVector(), alpha, beta, tmp.GetPetscVector());
00224     return;
00225   }
00226 
00227 
00228   template <class T0,
00229             class T1, class Prop1, class Allocator1,
00230             class T2, class Allocator2,
00231             class T3,
00232             class T4, class Allocator4>
00233   void MltAdd(const T0 alpha,
00234               const Matrix<T1, Prop1, PETScMPIAIJ, Allocator1>& M,
00235               const Vector<T2, VectFull, Allocator2>& X,
00236               const T3 beta, Vector<T4, PETScSeq, Allocator4>& Y)
00237   {
00238 #ifdef SELDON_CHECK_DIMENSIONS
00239     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00240 #endif
00241 
00242     Vector<T4, PETScSeq, Allocator4> X_Petsc;
00243     X_Petsc.Reallocate(X.GetM());
00244     for (int i = 0; i < X.GetM(); i++)
00245       X_Petsc.SetBuffer(i, X(i));
00246     X_Petsc.Flush();
00247 
00248     if (beta == T3(0))
00249       if (alpha == T0(0))
00250         {
00251           Y.Fill(T4(0));
00252           return;
00253         }
00254       else
00255         {
00256           MatMult(M.GetPetscMatrix(), X_Petsc.GetPetscVector(),
00257                   Y.GetPetscVector());
00258           if (alpha != T0(1))
00259             VecScale(Y.GetPetscVector(), alpha);
00260           return;
00261         }
00262     if (alpha == T0(1))
00263       {
00264         if (beta != T3(1))
00265           VecScale(Y.GetPetscVector(), beta);
00266         MatMultAdd(M.GetPetscMatrix(), X_Petsc.GetPetscVector(),
00267                    Y.GetPetscVector(),Y.GetPetscVector());
00268         return;
00269       }
00270     Vector<T2, PETScSeq, Allocator2> tmp;
00271     tmp.Copy(Y);
00272     MatMult(M.GetPetscMatrix(), X_Petsc.GetPetscVector(),
00273             tmp.GetPetscVector());
00274     VecAXPBY(Y.GetPetscVector(), alpha, beta, tmp.GetPetscVector());
00275     return;
00276   }
00277 
00278 
00279   template <class T0,
00280             class T1, class Prop1, class Allocator1,
00281             class T2, class Allocator2,
00282             class T3,
00283             class T4, class Allocator4>
00284   void MltAdd(const T0 alpha,
00285               const Matrix<T1, Prop1, PETScMPIAIJ, Allocator1>& M,
00286               const Vector<T2, VectFull, Allocator2>& X,
00287               const T3 beta, Vector<T4, PETScPar, Allocator4>& Y)
00288   {
00289 #ifdef SELDON_CHECK_DIMENSIONS
00290     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00291 #endif
00292 
00293     Vector<T4, PETScPar, Allocator4> X_Petsc;
00294     X_Petsc.SetCommunicator(M.GetCommunicator());
00295     X_Petsc.Reallocate(X.GetM());
00296     for (int i = 0; i < X.GetM(); i++)
00297       X_Petsc.SetBuffer(i, X(i));
00298     X_Petsc.Flush();
00299 
00300     if (beta == T3(0))
00301       if (alpha == T0(0))
00302         {
00303           Y.Fill(T4(0));
00304           return;
00305         }
00306       else
00307         {
00308           MatMult(M.GetPetscMatrix(), X_Petsc.GetPetscVector(),
00309                   Y.GetPetscVector());
00310           if (alpha != T0(1))
00311             VecScale(Y.GetPetscVector(), alpha);
00312           return;
00313         }
00314     if (alpha == T0(1))
00315       {
00316         if (beta != T3(1))
00317           VecScale(Y.GetPetscVector(), beta);
00318         MatMultAdd(M.GetPetscMatrix(), X_Petsc.GetPetscVector(),
00319                    Y.GetPetscVector(),Y.GetPetscVector());
00320         return;
00321       }
00322     Vector<T2, PETScPar, Allocator2> tmp;
00323     tmp.Copy(Y);
00324     MatMult(M.GetPetscMatrix(), X_Petsc.GetPetscVector(),
00325             tmp.GetPetscVector());
00326     VecAXPBY(Y.GetPetscVector(), alpha, beta, tmp.GetPetscVector());
00327     return;
00328   }
00329 
00330 
00331   template <class T0,
00332             class T1, class Prop1, class Allocator1,
00333             class T2, class Allocator2,
00334             class T3,
00335             class T4, class Allocator4>
00336   void MltAdd(const T0 alpha,
00337               const Matrix<T1, Prop1, PETScMPIDense, Allocator1>& M,
00338               const Vector<T2, VectFull, Allocator2>& X,
00339               const T3 beta, Vector<T4, PETScPar, Allocator4>& Y)
00340   {
00341 #ifdef SELDON_CHECK_DIMENSIONS
00342     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00343 #endif
00344 
00345     Vector<T4, PETScPar, Allocator4> X_Petsc;
00346      X_Petsc.SetCommunicator(M.GetCommunicator());
00347     X_Petsc.Reallocate(X.GetM());
00348     for (int i = 0; i < X.GetM(); i++)
00349       X_Petsc.SetBuffer(i, X(i));
00350     X_Petsc.Flush();
00351 
00352     if (beta == T3(0))
00353       if (alpha == T0(0))
00354         {
00355           Y.Fill(T4(0));
00356           return;
00357         }
00358       else
00359         {
00360           MatMult(M.GetPetscMatrix(), X_Petsc.GetPetscVector(),
00361                   Y.GetPetscVector());
00362           if (alpha != T0(1))
00363             VecScale(Y.GetPetscVector(), alpha);
00364           return;
00365         }
00366     if (alpha == T0(1))
00367       {
00368         if (beta != T3(1))
00369           VecScale(Y.GetPetscVector(), beta);
00370         MatMultAdd(M.GetPetscMatrix(), X_Petsc.GetPetscVector(),
00371                    Y.GetPetscVector(),Y.GetPetscVector());
00372         return;
00373       }
00374     Vector<T2, PETScPar, Allocator2> tmp;
00375     tmp.Copy(Y);
00376     tmp.SetCommunicator(M.GetCommunicator());
00377     MatMult(M.GetPetscMatrix(), X_Petsc.GetPetscVector(),
00378             tmp.GetPetscVector());
00379     VecAXPBY(Y.GetPetscVector(), alpha, beta, tmp.GetPetscVector());
00380     return;
00381   }
00382 
00383 
00384 
00385   /*** Sparse matrices ***/
00386 
00387 
00388   template <class T0,
00389             class T1, class Prop1, class Allocator1,
00390             class T2, class Storage2, class Allocator2,
00391             class T3,
00392             class T4, class Storage4, class Allocator4>
00393   void MltAdd(const T0 alpha,
00394               const Matrix<T1, Prop1, RowSparse, Allocator1>& M,
00395               const Vector<T2, Storage2, Allocator2>& X,
00396               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00397   {
00398     int ma = M.GetM();
00399 
00400 #ifdef SELDON_CHECK_DIMENSIONS
00401     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00402 #endif
00403 
00404     Mlt(beta, Y);
00405 
00406     T4 zero(0);
00407     T4 temp;
00408 
00409     int* ptr = M.GetPtr();
00410     int* ind = M.GetInd();
00411     typename Matrix<T1, Prop1, RowSparse, Allocator1>::pointer
00412       data = M.GetData();
00413 
00414     for (int i = 0; i < ma; i++)
00415       {
00416         temp = zero;
00417         for (int j = ptr[i]; j < ptr[i+1]; j++)
00418           temp += data[j] * X(ind[j]);
00419         Y(i) += alpha * temp;
00420       }
00421   }
00422 
00423 
00424   template <class T0,
00425             class T1, class Prop1, class Allocator1,
00426             class T2, class Storage2, class Allocator2,
00427             class T3,
00428             class T4, class Allocator4>
00429   void MltAdd(const T0 alpha,
00430               const Matrix<T1, Prop1, RowSparse, Allocator1>& M,
00431               const Vector<T2, Storage2, Allocator2>& X,
00432               const T3 beta, Vector<T4, Collection, Allocator4>& Y)
00433   {
00434     int ma = M.GetM();
00435 
00436 #ifdef SELDON_CHECK_DIMENSIONS
00437     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00438 #endif
00439 
00440     Mlt(beta, Y);
00441 
00442     typename T4::value_type zero(0);
00443     typename T4::value_type temp;
00444 
00445     int* ptr = M.GetPtr();
00446     int* ind = M.GetInd();
00447     typename Matrix<T1, Prop1, RowSparse, Allocator1>::pointer
00448       data = M.GetData();
00449 
00450     for (int i = 0; i < ma; i++)
00451       {
00452         temp = zero;
00453         for (int j = ptr[i]; j < ptr[i+1]; j++)
00454           temp += data[j] * X(ind[j]);
00455         Y(i) += alpha * temp;
00456       }
00457   }
00458 
00459 
00460   /*** Complex sparse matrices ***/
00461 
00462 
00463   template <class T0,
00464             class T1, class Prop1, class Allocator1,
00465             class T2, class Storage2, class Allocator2,
00466             class T3,
00467             class T4, class Storage4, class Allocator4>
00468   void MltAdd(const T0 alpha,
00469               const Matrix<T1, Prop1, RowComplexSparse, Allocator1>& M,
00470               const Vector<T2, Storage2, Allocator2>& X,
00471               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00472   {
00473     int i, j;
00474 
00475     int ma = M.GetM();
00476 
00477 #ifdef SELDON_CHECK_DIMENSIONS
00478     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00479 #endif
00480 
00481     Mlt(beta, Y);
00482 
00483     complex<T1> zero(0);
00484     complex<T1> temp;
00485 
00486     int* real_ptr = M.GetRealPtr();
00487     int* imag_ptr = M.GetImagPtr();
00488     int* real_ind = M.GetRealInd();
00489     int* imag_ind = M.GetImagInd();
00490     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00491       real_data = M.GetRealData();
00492     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00493       imag_data = M.GetImagData();
00494 
00495     for (i = 0; i < ma; i++)
00496       {
00497         temp = zero;
00498         for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00499           temp += real_data[j] * X(real_ind[j]);
00500         Y(i) += alpha * temp;
00501       }
00502 
00503     for (i = 0; i < ma; i++)
00504       {
00505         temp = zero;
00506         for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00507           temp += complex<T1>(T1(0), imag_data[j]) * X(imag_ind[j]);
00508         Y(i) += alpha * temp;
00509       }
00510   }
00511 
00512 
00513   /*** Symmetric sparse matrices ***/
00514 
00515 
00516   template <class T0,
00517             class T1, class Prop1, class Allocator1,
00518             class T2, class Storage2, class Allocator2,
00519             class T3,
00520             class T4, class Storage4, class Allocator4>
00521   void MltAdd(const T0 alpha,
00522               const Matrix<T1, Prop1, RowSymSparse, Allocator1>& M,
00523               const Vector<T2, Storage2, Allocator2>& X,
00524               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00525   {
00526     int ma = M.GetM();
00527 
00528 #ifdef SELDON_CHECK_DIMENSIONS
00529     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00530 #endif
00531 
00532     Mlt(beta, Y);
00533 
00534     int i, j;
00535     T4 zero(0);
00536     T4 temp;
00537 
00538     int* ptr = M.GetPtr();
00539     int* ind = M.GetInd();
00540     typename Matrix<T1, Prop1, RowSymSparse, Allocator1>::pointer
00541       data = M.GetData();
00542 
00543     for (i = 0; i < ma; i++)
00544       {
00545         temp = zero;
00546         for (j = ptr[i]; j < ptr[i + 1]; j++)
00547           temp += data[j] * X(ind[j]);
00548         Y(i) += alpha * temp;
00549       }
00550     for (i = 0; i < ma-1; i++)
00551       for (j = ptr[i]; j < ptr[i + 1]; j++)
00552         if (ind[j] != i)
00553           Y(ind[j]) += alpha * data[j] * X(i);
00554   }
00555 
00556 
00557   template <class T0,
00558             class T1, class Prop1, class Allocator1,
00559             class T2, class Allocator2,
00560             class T3,
00561             class T4, class Allocator4>
00562   void MltAdd(const T0 alpha,
00563               const Matrix<T1, Prop1, RowSymSparse, Allocator1>& M,
00564               const Vector<T2, Collection, Allocator2>& X,
00565               const T3 beta, Vector<T4, Collection, Allocator4>& Y)
00566   {
00567     int ma = M.GetM();
00568 
00569 #ifdef SELDON_CHECK_DIMENSIONS
00570     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00571 #endif
00572 
00573     Mlt(beta, Y);
00574 
00575     int i, j;
00576     typename T4::value_type zero(0);
00577     typename T4::value_type temp;
00578 
00579     int* ptr = M.GetPtr();
00580     int* ind = M.GetInd();
00581     typename Matrix<T1, Prop1, RowSymSparse, Allocator1>::pointer
00582       data = M.GetData();
00583 
00584     for (i = 0; i < ma; i++)
00585       {
00586         temp = zero;
00587         for (j = ptr[i]; j < ptr[i + 1]; j++)
00588           temp += data[j] * X(ind[j]);
00589         Y(i) += alpha * temp;
00590       }
00591     for (i = 0; i < ma-1; i++)
00592       for (j = ptr[i]; j < ptr[i + 1]; j++)
00593         if (ind[j] != i)
00594           Y(ind[j]) += alpha * data[j] * X(i);
00595   }
00596 
00597 
00598   template <class T0,
00599             class T1, class Prop1, class Allocator1,
00600             class T2, class Storage2, class Allocator2,
00601             class T3,
00602             class T4, class Allocator4>
00603   void MltAdd(const T0 alpha,
00604               const Matrix<T1, Prop1, RowSymSparse, Allocator1>& M,
00605               const Vector<T2, Storage2, Allocator2>& X,
00606               const T3 beta, Vector<T4, Collection, Allocator4>& Y)
00607   {
00608     int ma = M.GetM();
00609 
00610 #ifdef SELDON_CHECK_DIMENSIONS
00611     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00612 #endif
00613 
00614     Mlt(beta, Y);
00615 
00616     int i, j;
00617     typename T4::value_type zero(0);
00618     typename T4::value_type temp;
00619 
00620     int* ptr = M.GetPtr();
00621     int* ind = M.GetInd();
00622     typename Matrix<T1, Prop1, RowSymSparse, Allocator1>::pointer
00623       data = M.GetData();
00624 
00625     for (i = 0; i < ma; i++)
00626       {
00627         temp = zero;
00628         for (j = ptr[i]; j < ptr[i + 1]; j++)
00629           temp += data[j] * X(ind[j]);
00630         Y(i) += alpha * temp;
00631       }
00632     for (i = 0; i < ma-1; i++)
00633       for (j = ptr[i]; j < ptr[i + 1]; j++)
00634         if (ind[j] != i)
00635           Y(ind[j]) += alpha * data[j] * X(i);
00636   }
00637 
00638 
00639   /*** Symmetric complex sparse matrices ***/
00640 
00641 
00642   template <class T0,
00643             class T1, class Prop1, class Allocator1,
00644             class T2, class Storage2, class Allocator2,
00645             class T3,
00646             class T4, class Storage4, class Allocator4>
00647   void MltAdd(const T0 alpha,
00648               const Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>& M,
00649               const Vector<T2, Storage2, Allocator2>& X,
00650               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00651   {
00652     int ma = M.GetM();
00653 
00654 #ifdef SELDON_CHECK_DIMENSIONS
00655     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00656 #endif
00657 
00658     Mlt(beta, Y);
00659 
00660     int i, j;
00661     complex<T1> zero(0);
00662     complex<T1> temp;
00663 
00664     int* real_ptr = M.GetRealPtr();
00665     int* imag_ptr = M.GetImagPtr();
00666     int* real_ind = M.GetRealInd();
00667     int* imag_ind = M.GetImagInd();
00668     typename Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>::pointer
00669       real_data = M.GetRealData();
00670     typename Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>::pointer
00671       imag_data = M.GetImagData();
00672 
00673     for (i = 0; i<ma; i++)
00674       {
00675         temp = zero;
00676         for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00677           temp += real_data[j] * X(real_ind[j]);
00678         Y(i) += alpha * temp;
00679       }
00680     for (i = 0; i<ma-1; i++)
00681       for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00682         if (real_ind[j] != i)
00683           Y(real_ind[j]) += alpha * real_data[j] * X(i);
00684 
00685     for (i = 0; i < ma; i++)
00686       {
00687         temp = zero;
00688         for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00689           temp += complex<T1>(T1(0), imag_data[j]) * X(imag_ind[j]);
00690         Y(i) += alpha * temp;
00691       }
00692     for (i = 0; i<ma-1; i++)
00693       for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00694         if (imag_ind[j] != i)
00695           Y(imag_ind[j]) += alpha * complex<T1>(T1(0), imag_data[j]) * X(i);
00696   }
00697 
00698 
00699   /*** Sparse matrices, *Trans ***/
00700 
00701 
00702   // NoTrans.
00703   template <class T0,
00704             class T1, class Prop1, class Allocator1,
00705             class T2, class Storage2, class Allocator2,
00706             class T3,
00707             class T4, class Storage4, class Allocator4>
00708   void MltAdd(const T0 alpha,
00709               const class_SeldonNoTrans& Trans,
00710               const Matrix<T1, Prop1, RowSparse, Allocator1>& M,
00711               const Vector<T2, Storage2, Allocator2>& X,
00712               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00713   {
00714     MltAdd(alpha, M, X, beta, Y);
00715   }
00716 
00717 
00718   // Trans.
00719   template <class T0,
00720             class T1, class Prop1, class Allocator1,
00721             class T2, class Storage2, class Allocator2,
00722             class T3,
00723             class T4, class Storage4, class Allocator4>
00724   void MltAdd(const T0 alpha,
00725               const class_SeldonTrans& Trans,
00726               const Matrix<T1, Prop1, RowSparse, Allocator1>& M,
00727               const Vector<T2, Storage2, Allocator2>& X,
00728               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00729   {
00730     int i, j;
00731 
00732     int ma = M.GetM();
00733 
00734 #ifdef SELDON_CHECK_DIMENSIONS
00735     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonTrans, M, X, beta, Y)");
00736 #endif
00737 
00738     Mlt(beta, Y);
00739 
00740     int* ptr = M.GetPtr();
00741     int* ind = M.GetInd();
00742     typename Matrix<T1, Prop1, RowSparse, Allocator1>::pointer
00743       data = M.GetData();
00744 
00745     for (i = 0; i < ma; i++)
00746       for (j = ptr[i]; j < ptr[i + 1]; j++)
00747         Y(ind[j]) += alpha * data[j] * X(i);
00748   }
00749 
00750 
00751   // ConjTrans.
00752   template <class T0,
00753             class T1, class Prop1, class Allocator1,
00754             class T2, class Storage2, class Allocator2,
00755             class T3,
00756             class T4, class Storage4, class Allocator4>
00757   void MltAdd(const T0 alpha,
00758               const class_SeldonConjTrans& Trans,
00759               const Matrix<complex<T1>, Prop1, RowSparse, Allocator1>& M,
00760               const Vector<T2, Storage2, Allocator2>& X,
00761               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00762   {
00763     int i, j;
00764 
00765     int ma = M.GetM();
00766 
00767 #ifdef SELDON_CHECK_DIMENSIONS
00768     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonConjTrans, M, X, beta, Y)");
00769 #endif
00770 
00771     Mlt(beta, Y);
00772 
00773     int* ptr = M.GetPtr();
00774     int* ind = M.GetInd();
00775     typename Matrix<complex<T1>, Prop1, RowSparse, Allocator1>::pointer
00776       data = M.GetData();
00777 
00778     for (i = 0; i < ma; i++)
00779       for (j = ptr[i]; j < ptr[i + 1]; j++)
00780         Y(ind[j]) += alpha * conj(data[j]) * X(i);
00781   }
00782 
00783 
00784   /*** Complex sparse matrices, *Trans ***/
00785 
00786 
00787   // NoTrans.
00788   template <class T0,
00789             class T1, class Prop1, class Allocator1,
00790             class T2, class Storage2, class Allocator2,
00791             class T3,
00792             class T4, class Storage4, class Allocator4>
00793   void MltAdd(const T0 alpha,
00794               const class_SeldonNoTrans& Trans,
00795               const Matrix<T1, Prop1, RowComplexSparse, Allocator1>& M,
00796               const Vector<T2, Storage2, Allocator2>& X,
00797               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00798   {
00799     MltAdd(alpha, M, X, beta, Y);
00800   }
00801 
00802 
00803   // Trans.
00804   template <class T0,
00805             class T1, class Prop1, class Allocator1,
00806             class T2, class Storage2, class Allocator2,
00807             class T3,
00808             class T4, class Storage4, class Allocator4>
00809   void MltAdd(const T0 alpha,
00810               const class_SeldonTrans& Trans,
00811               const Matrix<T1, Prop1, RowComplexSparse, Allocator1>& M,
00812               const Vector<T2, Storage2, Allocator2>& X,
00813               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00814   {
00815     int i, j;
00816 
00817     int ma = M.GetM();
00818 
00819 #ifdef SELDON_CHECK_DIMENSIONS
00820     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonTrans, M, X, beta, Y)");
00821 #endif
00822 
00823     Mlt(beta, Y);
00824 
00825     int* real_ptr = M.GetRealPtr();
00826     int* imag_ptr = M.GetImagPtr();
00827     int* real_ind = M.GetRealInd();
00828     int* imag_ind = M.GetImagInd();
00829     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00830       real_data = M.GetRealData();
00831     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00832       imag_data = M.GetImagData();
00833 
00834     for (i = 0; i < ma; i++)
00835       for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00836         Y(real_ind[j]) += alpha * real_data[j] * X(i);
00837 
00838     for (i = 0; i < ma; i++)
00839       for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00840         Y(imag_ind[j]) += alpha * complex<T1>(T1(0), imag_data[j]) * X(i);
00841   }
00842 
00843 
00844   // ConjTrans.
00845   template <class T0,
00846             class T1, class Prop1, class Allocator1,
00847             class T2, class Storage2, class Allocator2,
00848             class T3,
00849             class T4, class Storage4, class Allocator4>
00850   void MltAdd(const T0 alpha,
00851               const class_SeldonConjTrans& Trans,
00852               const Matrix<T1, Prop1, RowComplexSparse, Allocator1>& M,
00853               const Vector<T2, Storage2, Allocator2>& X,
00854               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00855   {
00856     int i, j;
00857 
00858     int ma = M.GetM();
00859 
00860 #ifdef SELDON_CHECK_DIMENSIONS
00861     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonConjTrans, M, X, beta, Y)");
00862 #endif
00863 
00864     Mlt(beta, Y);
00865 
00866     int* real_ptr = M.GetRealPtr();
00867     int* imag_ptr = M.GetImagPtr();
00868     int* real_ind = M.GetRealInd();
00869     int* imag_ind = M.GetImagInd();
00870     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00871       real_data = M.GetRealData();
00872     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00873       imag_data = M.GetImagData();
00874 
00875     for (i = 0; i < ma; i++)
00876       for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00877         Y(real_ind[j]) += alpha * real_data[j] * X(i);
00878 
00879     for (i = 0; i < ma; i++)
00880       for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00881         Y(imag_ind[j]) += alpha * complex<T1>(T1(0), - imag_data[j]) * X(i);
00882   }
00883 
00884 
00885   /*** Symmetric sparse matrices, *Trans ***/
00886 
00887 
00888   // NoTrans.
00889   template <class T0,
00890             class T1, class Prop1, class Allocator1,
00891             class T2, class Storage2, class Allocator2,
00892             class T3,
00893             class T4, class Storage4, class Allocator4>
00894   void MltAdd(const T0 alpha,
00895               const class_SeldonNoTrans& Trans,
00896               const Matrix<T1, Prop1, RowSymSparse, Allocator1>& M,
00897               const Vector<T2, Storage2, Allocator2>& X,
00898               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00899   {
00900     MltAdd(alpha, M, X, beta, Y);
00901   }
00902 
00903 
00904   // Trans.
00905   template <class T0,
00906             class T1, class Prop1, class Allocator1,
00907             class T2, class Storage2, class Allocator2,
00908             class T3,
00909             class T4, class Storage4, class Allocator4>
00910   void MltAdd(const T0 alpha,
00911               const class_SeldonTrans& Trans,
00912               const Matrix<T1, Prop1, RowSymSparse, Allocator1>& M,
00913               const Vector<T2, Storage2, Allocator2>& X,
00914               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00915   {
00916     MltAdd(alpha, M, X, beta, Y);
00917   }
00918 
00919 
00920   // ConjTrans.
00921   template <class T0,
00922             class T1, class Prop1, class Allocator1,
00923             class T2, class Storage2, class Allocator2,
00924             class T3,
00925             class T4, class Storage4, class Allocator4>
00926   void MltAdd(const T0 alpha,
00927               const class_SeldonConjTrans& Trans,
00928               const Matrix<complex<T1>, Prop1, RowSymSparse, Allocator1>& M,
00929               const Vector<T2, Storage2, Allocator2>& X,
00930               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00931   {
00932     int ma = M.GetM();
00933 
00934 #ifdef SELDON_CHECK_DIMENSIONS
00935     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonConjTrans, M, X, beta, Y)");
00936 #endif
00937 
00938     Mlt(beta, Y);
00939 
00940     int i, j;
00941     complex<T1> zero(0);
00942     complex<T1> temp;
00943 
00944     int* ptr = M.GetPtr();
00945     int* ind = M.GetInd();
00946     typename Matrix<complex<T1>, Prop1, RowSymSparse, Allocator1>::pointer
00947       data = M.GetData();
00948 
00949     for (i = 0; i < ma; i++)
00950       {
00951         temp = zero;
00952         for (j = ptr[i]; j < ptr[i + 1]; j++)
00953           temp += conj(data[j]) * X(ind[j]);
00954         Y(i) += temp;
00955       }
00956     for (i = 0; i < ma - 1; i++)
00957       for (j = ptr[i]; j < ptr[i + 1]; j++)
00958         if (ind[j] != i)
00959           Y(ind[j]) += conj(data[j]) * X(i);
00960   }
00961 
00962 
00963   /*** Symmetric complex sparse matrices, *Trans ***/
00964 
00965 
00966   // NoTrans.
00967   template <class T0,
00968             class T1, class Prop1, class Allocator1,
00969             class T2, class Storage2, class Allocator2,
00970             class T3,
00971             class T4, class Storage4, class Allocator4>
00972   void MltAdd(const T0 alpha,
00973               const class_SeldonNoTrans& Trans,
00974               const Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>& M,
00975               const Vector<T2, Storage2, Allocator2>& X,
00976               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00977   {
00978     MltAdd(alpha, M, X, beta, Y);
00979   }
00980 
00981 
00982   // Trans.
00983   template <class T0,
00984             class T1, class Prop1, class Allocator1,
00985             class T2, class Storage2, class Allocator2,
00986             class T3,
00987             class T4, class Storage4, class Allocator4>
00988   void MltAdd(const T0 alpha,
00989               const class_SeldonTrans& Trans,
00990               const Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>& M,
00991               const Vector<T2, Storage2, Allocator2>& X,
00992               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00993   {
00994     MltAdd(alpha, M, X, beta, Y);
00995   }
00996 
00997 
00998   // ConjTrans.
00999   template <class T0,
01000             class T1, class Prop1, class Allocator1,
01001             class T2, class Storage2, class Allocator2,
01002             class T3,
01003             class T4, class Storage4, class Allocator4>
01004   void MltAdd(const T0 alpha,
01005               const class_SeldonConjTrans& Trans,
01006               const Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>& M,
01007               const Vector<T2, Storage2, Allocator2>& X,
01008               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
01009   {
01010     int ma = M.GetM();
01011 
01012 #ifdef SELDON_CHECK_DIMENSIONS
01013     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonConjTrans, M, X, beta, Y)");
01014 #endif
01015 
01016     Mlt(beta, Y);
01017 
01018     int i, j;
01019     complex<T1> zero(0);
01020     complex<T1> temp;
01021 
01022     int* real_ptr = M.GetRealPtr();
01023     int* imag_ptr = M.GetImagPtr();
01024     int* real_ind = M.GetRealInd();
01025     int* imag_ind = M.GetImagInd();
01026     typename Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>::pointer
01027       real_data = M.GetRealData();
01028     typename Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>::pointer
01029       imag_data = M.GetImagData();
01030 
01031     for (i = 0; i < ma; i++)
01032       {
01033         temp = zero;
01034         for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
01035           temp += real_data[j] * X(real_ind[j]);
01036         Y(i) += temp;
01037       }
01038     for (i = 0; i < ma - 1; i++)
01039       for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
01040         if (real_ind[j] != i)
01041           Y(real_ind[j]) += real_data[j] * X(i);
01042 
01043     for (i = 0; i < ma; i++)
01044       {
01045         temp = zero;
01046         for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
01047           temp += complex<T1>(T1(0), - imag_data[j]) * X(imag_ind[j]);
01048         Y(i) += temp;
01049       }
01050     for (i = 0; i < ma - 1; i++)
01051       for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
01052         if (imag_ind[j] != i)
01053           Y(imag_ind[j]) += complex<T1>(T1(0), - imag_data[j]) * X(i);
01054   }
01055 
01056 
01057   // MLTADD //
01059 
01060 
01062   // MLTADD //
01063 
01064 
01079   template <class T0,
01080             class T1, class Prop1, class Storage1, class Allocator1,
01081             class T2, class Storage2, class Allocator2,
01082             class T3,
01083             class T4, class Storage4, class Allocator4>
01084   void MltAdd(const T0 alpha,
01085               const Matrix<T1, Prop1, Storage1, Allocator1>& M,
01086               const Vector<T2, Storage2, Allocator2>& X,
01087               const T3 beta,
01088               Vector<T4, Storage4, Allocator4>& Y)
01089   {
01090     int ma = M.GetM();
01091     int na = M.GetN();
01092 
01093 #ifdef SELDON_CHECK_DIMENSIONS
01094     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
01095 #endif
01096 
01097     Mlt(beta, Y);
01098 
01099     T4 zero(0);
01100     T4 temp;
01101     T4 alpha_(alpha);
01102 
01103     for (int i = 0; i < ma; i++)
01104       {
01105         temp = zero;
01106         for (int j = 0; j < na; j++)
01107           temp += M(i, j) * X(j);
01108         Y(i) += alpha_ * temp;
01109       }
01110   }
01111 
01112 
01127   template <class T0,
01128             class T1, class Prop1, class Storage1, class Allocator1,
01129             class T2, class Storage2, class Allocator2,
01130             class T3,
01131             class T4, class Allocator4>
01132   void MltAdd(const T0 alpha,
01133               const Matrix<T1, Prop1, Storage1, Allocator1>& M,
01134               const Vector<T2, Storage2, Allocator2>& X,
01135               const T3 beta,
01136               Vector<T4, Collection, Allocator4>& Y)
01137   {
01138     int ma = M.GetM();
01139     int na = M.GetN();
01140 
01141 #ifdef SELDON_CHECK_DIMENSIONS
01142     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
01143 #endif
01144 
01145     Mlt(beta, Y);
01146 
01147     typename T4::value_type zero(0);
01148     typename T4::value_type temp;
01149     typename T4::value_type alpha_(alpha);
01150 
01151     for (int i = 0; i < ma; i++)
01152       {
01153         temp = zero;
01154         for (int j = 0; j < na; j++)
01155           temp += M(i, j) * X(j);
01156         Y(i) += alpha_ * temp;
01157       }
01158   }
01159 
01160 
01175   template <class T0,
01176             class T1, class Prop1, class Allocator1,
01177             class T2, class Allocator2,
01178             class T3,
01179             class T4, class Allocator4>
01180   void MltAdd(const T0 alpha,
01181               const Matrix<T1, Prop1, RowMajorCollection, Allocator1>& M,
01182               const Vector<T2, Collection, Allocator2>& X,
01183               const T3 beta,
01184               Vector<T4, Collection, Allocator4>& Y)
01185   {
01186     int ma = M.GetMmatrix();
01187     int na = M.GetNmatrix();
01188 
01189 #ifdef SELDON_CHECK_DIMENSIONS
01190     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
01191 #endif
01192     typedef typename T4::value_type value_type;
01193 
01194     Mlt(value_type(beta), Y);
01195 
01196     for (int i = 0; i < ma; i++)
01197       for (int j = 0; j < na; j++)
01198         MltAdd(alpha, M.GetMatrix(i, j), X.GetVector(j), value_type(1.),
01199                Y.GetVector(i));
01200   }
01201 
01202 
01217   template <class T0,
01218             class T1, class Prop1, class Allocator1,
01219             class T2, class Allocator2,
01220             class T3,
01221             class T4, class Allocator4>
01222   void MltAdd(const T0 alpha,
01223               const Matrix<T1, Prop1, ColMajorCollection, Allocator1>& M,
01224               const Vector<T2, Collection, Allocator2>& X,
01225               const T3 beta,
01226               Vector<T4, Collection, Allocator4>& Y)
01227   {
01228     int ma = M.GetMmatrix();
01229     int na = M.GetNmatrix();
01230 
01231 #ifdef SELDON_CHECK_DIMENSIONS
01232     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
01233 #endif
01234     typedef typename T4::value_type value_type;
01235 
01236     Mlt(value_type(beta), Y);
01237 
01238     for (int i = 0; i < ma; i++)
01239       for (int j = 0; j < na; j++)
01240         MltAdd(alpha, M.GetMatrix(i, j), X.GetVector(j), value_type(1.),
01241                Y.GetVector(i));
01242   }
01243 
01244 
01264   template <class T0,
01265             class T1, class Prop1, class Storage1, class Allocator1,
01266             class T2, class Storage2, class Allocator2,
01267             class T3,
01268             class T4, class Storage4, class Allocator4>
01269   void MltAdd(const T0 alpha,
01270               const SeldonTranspose& Trans,
01271               const Matrix<T1, Prop1, Storage1, Allocator1>& M,
01272               const Vector<T2, Storage2, Allocator2>& X,
01273               const T3 beta,
01274               Vector<T4, Storage4, Allocator4>& Y)
01275   {
01276     if (Trans.NoTrans())
01277       {
01278         MltAdd(alpha, M, X, beta, Y);
01279         return;
01280       }
01281     else if (Trans.ConjTrans())
01282       throw WrongArgument("MltAdd(alpha, trans, M, X, beta, Y)",
01283                           "Complex conjugation not supported.");
01284 
01285     int ma = M.GetM();
01286     int na = M.GetN();
01287 
01288 #ifdef SELDON_CHECK_DIMENSIONS
01289     CheckDim(Trans, M, X, Y, "MltAdd(alpha, trans, M, X, beta, Y)");
01290 #endif
01291 
01292     if (beta == T3(0))
01293       Y.Fill(T4(0));
01294     else
01295       Mlt(beta, Y);
01296 
01297     T4 zero(0);
01298     T4 temp;
01299     T4 alpha_(alpha);
01300 
01301     for (int i = 0; i < na; i++)
01302       {
01303         temp = zero;
01304         for (int j = 0; j < ma; j++)
01305           temp += M(j, i) * X(j);
01306         Y(i) += alpha_ * temp;
01307       }
01308   }
01309 
01310 
01311   // MLTADD //
01313 
01314 
01316   // GAUSS //
01317 
01318 
01319   // Solve X = M*Y with Gauss method.
01320   // Warning: M is modified. The results are stored in X.
01321   template <class T0, class Prop0, class Storage0, class Allocator0,
01322             class T1, class Storage1, class Allocator1>
01323   inline void Gauss(Matrix<T0, Prop0, Storage0, Allocator0>& M,
01324                     Vector<T1, Storage1, Allocator1>& X)
01325   {
01326     int i, j, k;
01327     T1 r, S;
01328 
01329     int ma = M.GetM();
01330     int na = M.GetN();
01331 
01332 #ifdef SELDON_CHECK_DIMENSIONS
01333     if (na != ma)
01334       throw WrongDim("Gauss(M, X)",
01335                      "The matrix must be squared.");
01336 
01337     CheckDim(M, X, "Gauss(M, X)");
01338 #endif
01339 
01340     for (k = 0; k < ma - 1; k++)
01341       for (i = k + 1; i < ma; i++)
01342         {
01343           r = M(i, k) / M(k, k);
01344           for (j = k + 1; j < ma; j++)
01345             M(i, j) -= r * M(k, j);
01346           X(i) -= r *= X(k);
01347         }
01348 
01349     X(ma - 1) = X(ma - 1) / M(ma - 1, ma - 1);
01350     for (k = ma - 2; k > -1; k--)
01351       {
01352         S = X(k);
01353         for (j = k + 1; j < ma; j++)
01354           S -= M(k, j) * X(j);
01355         X(k) = S / M(k, k);
01356       }
01357   }
01358 
01359 
01360   // GAUSS //
01362 
01363 
01365   // GAUSS-SEIDEL //
01366 
01367 
01368   // Solve X = M*Y with Gauss-Seidel method.
01369   template <class T0, class Prop0, class Storage0, class Allocator0,
01370             class T1, class Storage1, class Allocator1,
01371             class T2, class Storage2, class Allocator2>
01372   inline void GaussSeidel(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01373                           const Vector<T1, Storage1, Allocator1>& X,
01374                           Vector<T2, Storage2, Allocator2>& Y,
01375                           int iter)
01376   {
01377     int i, j, k;
01378     T1 temp;
01379 
01380     int ma = M.GetM();
01381     int na = M.GetN();
01382 
01383 #ifdef SELDON_CHECK_DIMENSIONS
01384     if (na != ma)
01385       throw WrongDim("GaussSeidel(M, X, Y, iter)",
01386                      "The matrix must be squared.");
01387 
01388     CheckDim(M, X, Y, "GaussSeidel(M, X, Y, iter)");
01389 #endif
01390 
01391     for (i = 0; i < iter; i++)
01392       for (j = 0; j < na; j++)
01393         {
01394           temp = 0;
01395           for (k = 0; k < j; k++)
01396             temp -= M(j, k) * Y(k);
01397           for (k = j + 1; k < na; k++)
01398             temp -= M(j, k) * Y(k);
01399           Y(j) = (X(j) + temp) / M(j, j);
01400         }
01401   }
01402 
01403 
01404   // GAUSS-SEIDEL //
01406 
01407 
01409   // S.O.R. METHOD //
01410 
01411 
01412   // Solve X = M*Y with S.O.R. method.
01413   template <class T0, class Prop0, class Storage0, class Allocator0,
01414             class T1, class Storage1, class Allocator1,
01415             class T2, class Storage2, class Allocator2,
01416             class T3>
01417   inline void SOR(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01418                   const Vector<T1, Storage1, Allocator1>& X,
01419                   Vector<T2, Storage2, Allocator2>& Y,
01420                   T3 omega,
01421                   int iter)
01422   {
01423     int i, j, k;
01424     T1 temp;
01425 
01426     int ma = M.GetM();
01427     int na = M.GetN();
01428 
01429 #ifdef SELDON_CHECK_DIMENSIONS
01430     if (na != ma)
01431       throw WrongDim("SOR(M, X, Y, omega, iter)",
01432                      "The matrix must be squared.");
01433 
01434     CheckDim(M, X, Y, "SOR(M, X, Y, omega, iter)");
01435 #endif
01436 
01437     for (i = 0; i < iter; i++)
01438       for (j = 0; j < na; j++)
01439         {
01440           temp = 0;
01441           for (k = 0; k < j; k++)
01442             temp -= M(j, k) * Y(k);
01443           for (k = j + 1; k < na; k++)
01444             temp -= M(j, k) * Y(k);
01445           Y(j) = (T3(1) - omega) * Y(j) + omega * (X(j) + temp) / M(j, j);
01446         }
01447   }
01448 
01449 
01450   // S.O.R. METHOD //
01452 
01453 
01454 
01456   // SOLVELU //
01457 
01458 
01460 
01472   template <class T0, class Prop0, class Storage0, class Allocator0,
01473             class T1, class Storage1, class Allocator1>
01474   void SolveLU(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01475                Vector<T1, Storage1, Allocator1>& Y)
01476   {
01477     int i, k;
01478     T1 temp;
01479 
01480     int ma = M.GetM();
01481 
01482 #ifdef SELDON_CHECK_DIMENSIONS
01483     int na = M.GetN();
01484     if (na != ma)
01485       throw WrongDim("SolveLU(M, Y)",
01486                      "The matrix must be squared.");
01487 
01488     CheckDim(M, Y, "SolveLU(M, Y)");
01489 #endif
01490 
01491     // Forward substitution.
01492     for (i = 0; i < ma; i++)
01493       {
01494         temp = 0;
01495         for (k = 0; k < i; k++)
01496           temp += M(i, k) * Y(k);
01497         Y(i) = (Y(i) - temp) / M(i, i);
01498       }
01499     // Back substitution.
01500     for (i = ma - 2; i > -1; i--)
01501       {
01502         temp = 0;
01503         for (k = i + 1; k < ma; k++)
01504           temp += M(i, k) * Y(k);
01505         Y(i) -= temp;
01506       }
01507   }
01508 
01509 
01510   // SOLVELU //
01512 
01513 
01515   // SOLVE //
01516 
01517 
01519 
01526   template <class T0, class Prop0, class Storage0, class Allocator0,
01527             class T1, class Storage1, class Allocator1>
01528   void GetAndSolveLU(Matrix<T0, Prop0, Storage0, Allocator0>& M,
01529                      Vector<T1, Storage1, Allocator1>& Y)
01530   {
01531 #ifdef SELDON_WITH_LAPACK
01532     Vector<int> P;
01533     GetLU(M, P);
01534     SolveLU(M, P, Y);
01535 #else
01536     GetLU(M);
01537     SolveLU(M, Y);
01538 #endif
01539   }
01540 
01541 
01542   // SOLVE //
01544 
01545 
01547   // CHECKDIM //
01548 
01549 
01551 
01560   template <class T0, class Prop0, class Storage0, class Allocator0,
01561             class T1, class Storage1, class Allocator1,
01562             class T2, class Storage2, class Allocator2>
01563   void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01564                 const Vector<T1, Storage1, Allocator1>& X,
01565                 const Vector<T2, Storage2, Allocator2>& Y,
01566                 string function)
01567   {
01568     if (X.GetLength() != M.GetN() || Y.GetLength() != M.GetM())
01569       throw WrongDim(function, string("Operation M X + Y -> Y not permitted:")
01570                      + string("\n     M (") + to_str(&M) + string(") is a ")
01571                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01572                      + string(" matrix;\n     X (") + to_str(&X)
01573                      + string(") is vector of length ")
01574                      + to_str(X.GetLength()) + string(";\n     Y (")
01575                      + to_str(&Y) + string(") is vector of length ")
01576                      + to_str(Y.GetLength()) + string("."));
01577   }
01578 
01579 
01581 
01590   template <class T0, class Prop0, class Allocator0,
01591             class T1, class Allocator1,
01592             class T2, class Allocator2>
01593   void CheckDim(const Matrix<T0, Prop0, RowMajorCollection, Allocator0>& M,
01594                 const Vector<T1, Collection, Allocator1>& X,
01595                 const Vector<T2, Collection, Allocator2>& Y,
01596                 string function)
01597   {
01598     if (X.GetNvector() != M.GetNmatrix() || Y.GetNvector() != M.GetMmatrix())
01599       throw WrongDim(function, string("Operation M X + Y -> Y not permitted:")
01600                      + string("\n     M (") + to_str(&M) + string(") is a ")
01601                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01602                      + string(" matrix;\n     X (") + to_str(&X)
01603                      + string(") is vector of length ")
01604                      + to_str(X.GetNvector()) + string(";\n     Y (")
01605                      + to_str(&Y) + string(") is vector of length ")
01606                      + to_str(Y.GetNvector()) + string("."));
01607   }
01608 
01609 
01611 
01620   template <class T0, class Prop0, class Allocator0,
01621             class T1, class Allocator1,
01622             class T2, class Allocator2>
01623   void CheckDim(const Matrix<T0, Prop0, ColMajorCollection, Allocator0>& M,
01624                 const Vector<T1, Collection, Allocator1>& X,
01625                 const Vector<T2, Collection, Allocator2>& Y,
01626                 string function)
01627   {
01628     if (X.GetNvector() != M.GetNmatrix() || Y.GetNvector() != M.GetMmatrix())
01629       throw WrongDim(function, string("Operation M X + Y -> Y not permitted:")
01630                      + string("\n     M (") + to_str(&M) + string(") is a ")
01631                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01632                      + string(" matrix;\n     X (") + to_str(&X)
01633                      + string(") is vector of length ")
01634                      + to_str(X.GetNvector()) + string(";\n     Y (")
01635                      + to_str(&Y) + string(") is vector of length ")
01636                      + to_str(Y.GetNvector()) + string("."));
01637   }
01638 
01639 
01641 
01650   template <class T0, class Prop0, class Storage0, class Allocator0,
01651             class T1, class Allocator1,
01652             class T2, class Storage2, class Allocator2>
01653   void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01654                 const Vector<T1, Collection, Allocator1>& X,
01655                 const Vector<T2, Storage2, Allocator2>& Y,
01656                 string function)
01657   {
01658     if (X.GetLength() != M.GetN() || Y.GetLength() != M.GetM())
01659       throw WrongDim(function, string("Operation M X + Y -> Y not permitted:")
01660                      + string("\n     M (") + to_str(&M) + string(") is a ")
01661                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01662                      + string(" matrix;\n     X (") + to_str(&X)
01663                      + string(") is vector of length ")
01664                      + to_str(X.GetLength()) + string(";\n     Y (")
01665                      + to_str(&Y) + string(") is vector of length ")
01666                      + to_str(Y.GetLength()) + string("."));
01667   }
01668 
01669 
01671 
01683   template <class T0, class Prop0, class Storage0, class Allocator0,
01684             class T1, class Storage1, class Allocator1,
01685             class T2, class Storage2, class Allocator2>
01686   void CheckDim(const SeldonTranspose& trans,
01687                 const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01688                 const Vector<T1, Storage1, Allocator1>& X,
01689                 const Vector<T2, Storage2, Allocator2>& Y,
01690                 string function, string op)
01691   {
01692     if (op == "M X + Y -> Y")
01693       if (trans.Trans())
01694         op = string("Operation M' X + Y -> Y not permitted:");
01695       else if (trans.ConjTrans())
01696         op = string("Operation M* X + Y -> Y not permitted:");
01697       else
01698         op = string("Operation M X + Y -> Y not permitted:");
01699     else
01700       op = string("Operation ") + op + string(" not permitted:");
01701     if (X.GetLength() != M.GetN(trans) || Y.GetLength() != M.GetM(trans))
01702       throw WrongDim(function, op + string("\n     M (") + to_str(&M)
01703                      + string(") is a ") + to_str(M.GetM()) + string(" x ")
01704                      + to_str(M.GetN()) + string(" matrix;\n     X (")
01705                      + to_str(&X) + string(") is vector of length ")
01706                      + to_str(X.GetLength()) + string(";\n     Y (")
01707                      + to_str(&Y) + string(") is vector of length ")
01708                      + to_str(Y.GetLength()) + string("."));
01709   }
01710 
01711 
01713 
01722   template <class T0, class Prop0, class Storage0, class Allocator0,
01723             class T1, class Storage1, class Allocator1>
01724   void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01725                 const Vector<T1, Storage1, Allocator1>& X,
01726                 string function, string op)
01727   {
01728     if (X.GetLength() != M.GetN())
01729       throw WrongDim(function, string("Operation ") + op + " not permitted:"
01730                      + string("\n     M (") + to_str(&M) + string(") is a ")
01731                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01732                      + string(" matrix;\n     X (") + to_str(&X)
01733                      + string(") is vector of length ")
01734                      + to_str(X.GetLength()) + string("."));
01735   }
01736 
01737 
01738   // CHECKDIM //
01740 
01741 
01742 }  // namespace Seldon.
01743 
01744 
01745 #endif