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 
00022 /*
00023   Functions defined in this file:
00024 
00025   M X -> Y
00026   Mlt(M, X, Y)
00027 
00028   alpha M X -> Y
00029   Mlt(alpha, M, X, Y)
00030 
00031   M X -> Y
00032   M^T X -> Y
00033   Mlt(Trans, M, X, Y)
00034 
00035   alpha M X + beta Y -> Y
00036   MltAdd(alpha, M, X, beta, Y)
00037 
00038   Gauss(M, X)
00039 
00040   GaussSeidel(M, X, Y, iter)
00041 
00042   SOR(M, X, Y, omega, iter)
00043 
00044   SolveLU(M, Y)
00045 
00046   Solve(M, Y)
00047 */
00048 
00049 namespace Seldon
00050 {
00051 
00052 
00054   // MLT //
00055 
00056 
00058 
00066   template <class T0, class Prop0, class Storage0, class Allocator0,
00067             class T1, class Storage1, class Allocator1,
00068             class T2, class Storage2, class Allocator2>
00069   void Mlt(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
00070            const Vector<T1, Storage1, Allocator1>& X,
00071            Vector<T2, Storage2, Allocator2>& Y)
00072   {
00073     Y.Fill(T2(0));
00074     MltAdd(T2(1), M, X, T2(0), Y);
00075   }
00076 
00077 
00079 
00090   template <class T1, class Prop1, class Storage1, class Allocator1,
00091             class T2, class Storage2, class Allocator2,
00092             class T3, class Storage3, class Allocator3>
00093   void Mlt(const T3& alpha,
00094            const Matrix<T1, Prop1, Storage1, Allocator1>& M,
00095            const Vector<T2, Storage2, Allocator2>& X,
00096            Vector<T3, Storage3, Allocator3>& Y)
00097   {
00098     Y.Fill(T2(0));
00099     MltAdd(alpha, M, X, T3(0), Y);
00100   }
00101 
00102 
00104 
00114   template <class T1, class Prop1, class Storage1, class Allocator1,
00115             class T2, class Storage2, class Allocator2,
00116             class T3, class Storage3, class Allocator3>
00117   void Mlt(const SeldonTranspose& Trans,
00118            const Matrix<T1, Prop1, Storage1, Allocator1>& M,
00119            const Vector<T2, Storage2, Allocator2>& X,
00120            Vector<T3, Storage3, Allocator3>& Y)
00121   {
00122     Y.Fill(T2(0));
00123     MltAdd(T2(1), Trans, M, X, T3(0), Y);
00124   }
00125     
00126   
00127   // MLT //
00129 
00130 
00131 
00133   // MltAdd //
00134 
00135 
00136   /*** Sparse matrices ***/
00137 
00138 
00139   template <class T0,
00140             class T1, class Prop1, class Allocator1,
00141             class T2, class Storage2, class Allocator2,
00142             class T3,
00143             class T4, class Storage4, class Allocator4>
00144   void MltAdd(const T0 alpha,
00145               const Matrix<T1, Prop1, RowSparse, Allocator1>& M,
00146               const Vector<T2, Storage2, Allocator2>& X,
00147               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00148   {
00149     int ma = M.GetM();
00150 
00151 #ifdef SELDON_CHECK_DIMENSIONS
00152     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00153 #endif
00154 
00155     Mlt(beta, Y);
00156 
00157     T4 zero(0);
00158     T4 temp;
00159 
00160     int* ptr = M.GetPtr();
00161     int* ind = M.GetInd();
00162     typename Matrix<T1, Prop1, RowSparse, Allocator1>::pointer
00163       data = M.GetData();
00164 
00165     for (int i = 0; i < ma; i++)
00166       {
00167         temp = zero;
00168         for (int j = ptr[i]; j < ptr[i+1]; j++)
00169           temp += data[j] * X(ind[j]);
00170         Y(i) += alpha * temp;
00171       }
00172   }
00173 
00174 
00175   /*** Complex sparse matrices ***/
00176 
00177 
00178   template <class T0,
00179             class T1, class Prop1, class Allocator1,
00180             class T2, class Storage2, class Allocator2,
00181             class T3,
00182             class T4, class Storage4, class Allocator4>
00183   void MltAdd(const T0 alpha,
00184               const Matrix<T1, Prop1, RowComplexSparse, Allocator1>& M,
00185               const Vector<T2, Storage2, Allocator2>& X,
00186               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00187   {
00188     int i, j;
00189 
00190     int ma = M.GetM();
00191 
00192 #ifdef SELDON_CHECK_DIMENSIONS
00193     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00194 #endif
00195 
00196     Mlt(beta, Y);
00197 
00198     complex<T1> zero(0);
00199     complex<T1> temp;
00200 
00201     int* real_ptr = M.GetRealPtr();
00202     int* imag_ptr = M.GetImagPtr();
00203     int* real_ind = M.GetRealInd();
00204     int* imag_ind = M.GetImagInd();
00205     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00206       real_data = M.GetRealData();
00207     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00208       imag_data = M.GetImagData();
00209 
00210     for (i = 0; i < ma; i++)
00211       {
00212         temp = zero;
00213         for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00214           temp += real_data[j] * X(real_ind[j]);
00215         Y(i) += alpha * temp;
00216       }
00217 
00218     for (i = 0; i < ma; i++)
00219       {
00220         temp = zero;
00221         for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00222           temp += complex<T1>(T1(0), imag_data[j]) * X(imag_ind[j]);
00223         Y(i) += alpha * temp;
00224       }
00225   }
00226 
00227 
00228   /*** Symmetric sparse matrices ***/
00229 
00230 
00231   template <class T0,
00232             class T1, class Prop1, class Allocator1,
00233             class T2, class Storage2, class Allocator2,
00234             class T3,
00235             class T4, class Storage4, class Allocator4>
00236   void MltAdd(const T0 alpha,
00237               const Matrix<T1, Prop1, RowSymSparse, Allocator1>& M,
00238               const Vector<T2, Storage2, Allocator2>& X,
00239               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00240   {
00241     int ma = M.GetM();
00242 
00243 #ifdef SELDON_CHECK_DIMENSIONS
00244     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00245 #endif
00246 
00247     Mlt(beta, Y);
00248 
00249     int i, j;
00250     T4 zero(0);
00251     T4 temp;
00252 
00253     int* ptr = M.GetPtr();
00254     int* ind = M.GetInd();
00255     typename Matrix<T1, Prop1, RowSymSparse, Allocator1>::pointer
00256       data = M.GetData();
00257 
00258     for (i = 0; i < ma; i++)
00259       {
00260         temp = zero;
00261         for (j = ptr[i]; j < ptr[i + 1]; j++)
00262           temp += data[j] * X(ind[j]);
00263         Y(i) += alpha * temp;
00264       }
00265     for (i = 0; i < ma-1; i++)
00266       for (j = ptr[i]; j < ptr[i + 1]; j++)
00267         if (ind[j] != i)
00268           Y(ind[j]) += alpha * data[j] * X(i);
00269   }
00270 
00271 
00272   /*** Symmetric complex sparse matrices ***/
00273 
00274 
00275   template <class T0,
00276             class T1, class Prop1, class Allocator1,
00277             class T2, class Storage2, class Allocator2,
00278             class T3,
00279             class T4, class Storage4, class Allocator4>
00280   void MltAdd(const T0 alpha,
00281               const Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>& M,
00282               const Vector<T2, Storage2, Allocator2>& X,
00283               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00284   {
00285     int ma = M.GetM();
00286 
00287 #ifdef SELDON_CHECK_DIMENSIONS
00288     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00289 #endif
00290 
00291     Mlt(beta, Y);
00292 
00293     int i, j;
00294     complex<T1> zero(0);
00295     complex<T1> temp;
00296 
00297     int* real_ptr = M.GetRealPtr();
00298     int* imag_ptr = M.GetImagPtr();
00299     int* real_ind = M.GetRealInd();
00300     int* imag_ind = M.GetImagInd();
00301     typename Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>::pointer
00302       real_data = M.GetRealData();
00303     typename Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>::pointer
00304       imag_data = M.GetImagData();
00305 
00306     for (i = 0; i<ma; i++)
00307       {
00308         temp = zero;
00309         for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00310           temp += real_data[j] * X(real_ind[j]);
00311         Y(i) += alpha * temp;
00312       }
00313     for (i = 0; i<ma-1; i++)
00314       for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00315         if (real_ind[j] != i)
00316           Y(real_ind[j]) += alpha * real_data[j] * X(i);
00317 
00318     for (i = 0; i < ma; i++)
00319       {
00320         temp = zero;
00321         for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00322           temp += complex<T1>(T1(0), imag_data[j]) * X(imag_ind[j]);
00323         Y(i) += alpha * temp;
00324       }
00325     for (i = 0; i<ma-1; i++)
00326       for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00327         if (imag_ind[j] != i)
00328           Y(imag_ind[j]) += alpha * complex<T1>(T1(0), imag_data[j]) * X(i);
00329   }
00330 
00331 
00332   /*** Sparse matrices, *Trans ***/
00333 
00334 
00335   // NoTrans.
00336   template <class T0,
00337             class T1, class Prop1, class Allocator1,
00338             class T2, class Storage2, class Allocator2,
00339             class T3,
00340             class T4, class Storage4, class Allocator4>
00341   void MltAdd(const T0 alpha,
00342               const class_SeldonNoTrans& Trans,
00343               const Matrix<T1, Prop1, RowSparse, Allocator1>& M,
00344               const Vector<T2, Storage2, Allocator2>& X,
00345               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00346   {
00347     MltAdd(alpha, M, X, beta, Y);
00348   }
00349 
00350 
00351   // Trans.
00352   template <class T0,
00353             class T1, class Prop1, class Allocator1,
00354             class T2, class Storage2, class Allocator2,
00355             class T3,
00356             class T4, class Storage4, class Allocator4>
00357   void MltAdd(const T0 alpha,
00358               const class_SeldonTrans& Trans,
00359               const Matrix<T1, Prop1, RowSparse, Allocator1>& M,
00360               const Vector<T2, Storage2, Allocator2>& X,
00361               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00362   {
00363     int i, j;
00364 
00365     int ma = M.GetM();
00366 
00367 #ifdef SELDON_CHECK_DIMENSIONS
00368     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonTrans, M, X, beta, Y)");
00369 #endif
00370 
00371     Mlt(beta, Y);
00372 
00373     int* ptr = M.GetPtr();
00374     int* ind = M.GetInd();
00375     typename Matrix<T1, Prop1, RowSparse, Allocator1>::pointer
00376       data = M.GetData();
00377 
00378     for (i = 0; i < ma; i++)
00379       for (j = ptr[i]; j < ptr[i + 1]; j++)
00380         Y(ind[j]) += alpha * data[j] * X(i);
00381   }
00382 
00383 
00384   // ConjTrans.
00385   template <class T0,
00386             class T1, class Prop1, class Allocator1,
00387             class T2, class Storage2, class Allocator2,
00388             class T3,
00389             class T4, class Storage4, class Allocator4>
00390   void MltAdd(const T0 alpha,
00391               const class_SeldonConjTrans& Trans,
00392               const Matrix<complex<T1>, Prop1, RowSparse, Allocator1>& M,
00393               const Vector<T2, Storage2, Allocator2>& X,
00394               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00395   {
00396     int i, j;
00397 
00398     int ma = M.GetM();
00399 
00400 #ifdef SELDON_CHECK_DIMENSIONS
00401     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonConjTrans, M, X, beta, Y)");
00402 #endif
00403 
00404     Mlt(beta, Y);
00405 
00406     int* ptr = M.GetPtr();
00407     int* ind = M.GetInd();
00408     typename Matrix<complex<T1>, Prop1, RowSparse, Allocator1>::pointer
00409       data = M.GetData();
00410 
00411     for (i = 0; i < ma; i++)
00412       for (j = ptr[i]; j < ptr[i + 1]; j++)
00413         Y(ind[j]) += alpha * conj(data[j]) * X(i);
00414   }
00415 
00416 
00417   /*** Complex sparse matrices, *Trans ***/
00418 
00419 
00420   // NoTrans.
00421   template <class T0,
00422             class T1, class Prop1, class Allocator1,
00423             class T2, class Storage2, class Allocator2,
00424             class T3,
00425             class T4, class Storage4, class Allocator4>
00426   void MltAdd(const T0 alpha,
00427               const class_SeldonNoTrans& Trans,
00428               const Matrix<T1, Prop1, RowComplexSparse, Allocator1>& M,
00429               const Vector<T2, Storage2, Allocator2>& X,
00430               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00431   {
00432     MltAdd(alpha, M, X, beta, Y);
00433   }
00434 
00435 
00436   // Trans.
00437   template <class T0,
00438             class T1, class Prop1, class Allocator1,
00439             class T2, class Storage2, class Allocator2,
00440             class T3,
00441             class T4, class Storage4, class Allocator4>
00442   void MltAdd(const T0 alpha,
00443               const class_SeldonTrans& Trans,
00444               const Matrix<T1, Prop1, RowComplexSparse, Allocator1>& M,
00445               const Vector<T2, Storage2, Allocator2>& X,
00446               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00447   {
00448     int i, j;
00449 
00450     int ma = M.GetM();
00451 
00452 #ifdef SELDON_CHECK_DIMENSIONS
00453     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonTrans, M, X, beta, Y)");
00454 #endif
00455 
00456     Mlt(beta, Y);
00457 
00458     int* real_ptr = M.GetRealPtr();
00459     int* imag_ptr = M.GetImagPtr();
00460     int* real_ind = M.GetRealInd();
00461     int* imag_ind = M.GetImagInd();
00462     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00463       real_data = M.GetRealData();
00464     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00465       imag_data = M.GetImagData();
00466 
00467     for (i = 0; i < ma; i++)
00468       for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00469         Y(real_ind[j]) += alpha * real_data[j] * X(i);
00470 
00471     for (i = 0; i < ma; i++)
00472       for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00473         Y(imag_ind[j]) += alpha * complex<T1>(T1(0), imag_data[j]) * X(i);
00474   }
00475 
00476 
00477   // ConjTrans.
00478   template <class T0,
00479             class T1, class Prop1, class Allocator1,
00480             class T2, class Storage2, class Allocator2,
00481             class T3,
00482             class T4, class Storage4, class Allocator4>
00483   void MltAdd(const T0 alpha,
00484               const class_SeldonConjTrans& Trans,
00485               const Matrix<T1, Prop1, RowComplexSparse, Allocator1>& M,
00486               const Vector<T2, Storage2, Allocator2>& X,
00487               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00488   {
00489     int i, j;
00490 
00491     int ma = M.GetM();
00492 
00493 #ifdef SELDON_CHECK_DIMENSIONS
00494     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonConjTrans, M, X, beta, Y)");
00495 #endif
00496 
00497     Mlt(beta, Y);
00498 
00499     int* real_ptr = M.GetRealPtr();
00500     int* imag_ptr = M.GetImagPtr();
00501     int* real_ind = M.GetRealInd();
00502     int* imag_ind = M.GetImagInd();
00503     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00504       real_data = M.GetRealData();
00505     typename Matrix<T1, Prop1, RowComplexSparse, Allocator1>::pointer
00506       imag_data = M.GetImagData();
00507 
00508     for (i = 0; i < ma; i++)
00509       for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00510         Y(real_ind[j]) += alpha * real_data[j] * X(i);
00511 
00512     for (i = 0; i < ma; i++)
00513       for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00514         Y(imag_ind[j]) += alpha * complex<T1>(T1(0), - imag_data[j]) * X(i);
00515   }
00516 
00517 
00518   /*** Symmetric sparse matrices, *Trans ***/
00519 
00520 
00521   // NoTrans.
00522   template <class T0,
00523             class T1, class Prop1, class Allocator1,
00524             class T2, class Storage2, class Allocator2,
00525             class T3,
00526             class T4, class Storage4, class Allocator4>
00527   void MltAdd(const T0 alpha,
00528               const class_SeldonNoTrans& Trans,
00529               const Matrix<T1, Prop1, RowSymSparse, Allocator1>& M,
00530               const Vector<T2, Storage2, Allocator2>& X,
00531               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00532   {
00533     MltAdd(alpha, M, X, beta, Y);
00534   }
00535 
00536 
00537   // Trans.
00538   template <class T0,
00539             class T1, class Prop1, class Allocator1,
00540             class T2, class Storage2, class Allocator2,
00541             class T3,
00542             class T4, class Storage4, class Allocator4>
00543   void MltAdd(const T0 alpha,
00544               const class_SeldonTrans& Trans,
00545               const Matrix<T1, Prop1, RowSymSparse, Allocator1>& M,
00546               const Vector<T2, Storage2, Allocator2>& X,
00547               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00548   {
00549     MltAdd(alpha, M, X, beta, Y);
00550   }
00551 
00552 
00553   // ConjTrans.
00554   template <class T0,
00555             class T1, class Prop1, class Allocator1,
00556             class T2, class Storage2, class Allocator2,
00557             class T3,
00558             class T4, class Storage4, class Allocator4>
00559   void MltAdd(const T0 alpha,
00560               const class_SeldonConjTrans& Trans,
00561               const Matrix<complex<T1>, Prop1, RowSymSparse, Allocator1>& M,
00562               const Vector<T2, Storage2, Allocator2>& X,
00563               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00564   {
00565     int ma = M.GetM();
00566 
00567 #ifdef SELDON_CHECK_DIMENSIONS
00568     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonConjTrans, M, X, beta, Y)");
00569 #endif
00570 
00571     Mlt(beta, Y);
00572 
00573     int i, j;
00574     complex<T1> zero(0);
00575     complex<T1> temp;
00576 
00577     int* ptr = M.GetPtr();
00578     int* ind = M.GetInd();
00579     typename Matrix<complex<T1>, Prop1, RowSymSparse, Allocator1>::pointer
00580       data = M.GetData();
00581 
00582     for (i = 0; i < ma; i++)
00583       {
00584         temp = zero;
00585         for (j = ptr[i]; j < ptr[i + 1]; j++)
00586           temp += conj(data[j]) * X(ind[j]);
00587         Y(i) += temp;
00588       }
00589     for (i = 0; i < ma - 1; i++)
00590       for (j = ptr[i]; j < ptr[i + 1]; j++)
00591         if (ind[j] != i)
00592           Y(ind[j]) += conj(data[j]) * X(i);
00593   }
00594 
00595 
00596   /*** Symmetric complex sparse matrices, *Trans ***/
00597 
00598 
00599   // NoTrans.
00600   template <class T0,
00601             class T1, class Prop1, class Allocator1,
00602             class T2, class Storage2, class Allocator2,
00603             class T3,
00604             class T4, class Storage4, class Allocator4>
00605   void MltAdd(const T0 alpha,
00606               const class_SeldonNoTrans& Trans,
00607               const Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>& M,
00608               const Vector<T2, Storage2, Allocator2>& X,
00609               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00610   {
00611     MltAdd(alpha, M, X, beta, Y);
00612   }
00613 
00614 
00615   // Trans.
00616   template <class T0,
00617             class T1, class Prop1, class Allocator1,
00618             class T2, class Storage2, class Allocator2,
00619             class T3,
00620             class T4, class Storage4, class Allocator4>
00621   void MltAdd(const T0 alpha,
00622               const class_SeldonTrans& Trans,
00623               const Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>& M,
00624               const Vector<T2, Storage2, Allocator2>& X,
00625               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00626   {
00627     MltAdd(alpha, M, X, beta, Y);
00628   }
00629 
00630 
00631   // ConjTrans.
00632   template <class T0,
00633             class T1, class Prop1, class Allocator1,
00634             class T2, class Storage2, class Allocator2,
00635             class T3,
00636             class T4, class Storage4, class Allocator4>
00637   void MltAdd(const T0 alpha,
00638               const class_SeldonConjTrans& Trans,
00639               const Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>& M,
00640               const Vector<T2, Storage2, Allocator2>& X,
00641               const T3 beta, Vector<T4, Storage4, Allocator4>& Y)
00642   {
00643     int ma = M.GetM();
00644 
00645 #ifdef SELDON_CHECK_DIMENSIONS
00646     CheckDim(Trans, M, X, Y, "MltAdd(alpha, SeldonConjTrans, M, X, beta, Y)");
00647 #endif
00648 
00649     Mlt(beta, Y);
00650 
00651     int i, j;
00652     complex<T1> zero(0);
00653     complex<T1> temp;
00654 
00655     int* real_ptr = M.GetRealPtr();
00656     int* imag_ptr = M.GetImagPtr();
00657     int* real_ind = M.GetRealInd();
00658     int* imag_ind = M.GetImagInd();
00659     typename Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>::pointer
00660       real_data = M.GetRealData();
00661     typename Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>::pointer
00662       imag_data = M.GetImagData();
00663 
00664     for (i = 0; i < ma; i++)
00665       {
00666         temp = zero;
00667         for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00668           temp += real_data[j] * X(real_ind[j]);
00669         Y(i) += temp;
00670       }
00671     for (i = 0; i < ma - 1; i++)
00672       for (j = real_ptr[i]; j < real_ptr[i + 1]; j++)
00673         if (real_ind[j] != i)
00674           Y(real_ind[j]) += real_data[j] * X(i);
00675 
00676     for (i = 0; i < ma; i++)
00677       {
00678         temp = zero;
00679         for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00680           temp += complex<T1>(T1(0), - imag_data[j]) * X(imag_ind[j]);
00681         Y(i) += temp;
00682       }
00683     for (i = 0; i < ma - 1; i++)
00684       for (j = imag_ptr[i]; j < imag_ptr[i + 1]; j++)
00685         if (imag_ind[j] != i)
00686           Y(imag_ind[j]) += complex<T1>(T1(0), - imag_data[j]) * X(i);
00687   }
00688 
00689 
00690   // MltAdd //
00692 
00693 
00694 
00696   // MltAdd //
00697 
00698 
00713   template <class T0,
00714             class T1, class Prop1, class Storage1, class Allocator1,
00715             class T2, class Storage2, class Allocator2,
00716             class T3,
00717             class T4, class Storage4, class Allocator4>
00718   void MltAdd(const T0 alpha,
00719               const Matrix<T1, Prop1, Storage1, Allocator1>& M,
00720               const Vector<T2, Storage2, Allocator2>& X,
00721               const T3 beta,
00722               Vector<T4, Storage4, Allocator4>& Y)
00723   {
00724     int ma = M.GetM();
00725     int na = M.GetN();
00726 
00727 #ifdef SELDON_CHECK_DIMENSIONS
00728     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00729 #endif
00730 
00731     Mlt(beta, Y);
00732 
00733     T4 zero(0);
00734     T4 temp;
00735     T4 alpha_(alpha);
00736 
00737     for (int i = 0; i < ma; i++)
00738       {
00739         temp = zero;
00740         for (int j = 0; j < na; j++)
00741           temp += M(i, j) * X(j);
00742         Y(i) += alpha_ * temp;
00743       }
00744   }
00745 
00746 
00761   template <class T0,
00762             class T1, class Prop1, class Allocator1,
00763             class T2, class Allocator2,
00764             class T3,
00765             class T4, class Allocator4>
00766   void MltAdd(const T0 alpha,
00767               const Matrix<T1, Prop1, RowMajorCollection, Allocator1>& M,
00768               const Vector<T2, Collection, Allocator2>& X,
00769               const T3 beta,
00770               Vector<T4, Collection, Allocator4>& Y)
00771   {
00772     int ma = M.GetMmatrix();
00773     int na = M.GetNmatrix();
00774 
00775 #ifdef SELDON_CHECK_DIMENSIONS
00776     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00777 #endif
00778     typedef typename T4::value_type value_type;
00779 
00780     Mlt(value_type(beta), Y);
00781 
00782     for (int i = 0; i < ma; i++)
00783       for (int j = 0; j < na; j++)
00784         MltAdd(alpha, M.GetMatrix(i, j), X.GetVector(j), value_type(1.),
00785                Y.GetVector(i));
00786   }
00787 
00788 
00803   template <class T0,
00804             class T1, class Prop1, class Allocator1,
00805             class T2, class Allocator2,
00806             class T3,
00807             class T4, class Allocator4>
00808   void MltAdd(const T0 alpha,
00809               const Matrix<T1, Prop1, ColMajorCollection, Allocator1>& M,
00810               const Vector<T2, Collection, Allocator2>& X,
00811               const T3 beta,
00812               Vector<T4, Collection, Allocator4>& Y)
00813   {
00814     int ma = M.GetMmatrix();
00815     int na = M.GetNmatrix();
00816 
00817 #ifdef SELDON_CHECK_DIMENSIONS
00818     CheckDim(M, X, Y, "MltAdd(alpha, M, X, beta, Y)");
00819 #endif
00820     typedef typename T4::value_type value_type;
00821 
00822     Mlt(value_type(beta), Y);
00823 
00824     for (int i = 0; i < ma; i++)
00825       for (int j = 0; j < na; j++)
00826         MltAdd(alpha, M.GetMatrix(i, j), X.GetVector(j), value_type(1.),
00827                Y.GetVector(i));
00828   }
00829 
00830 
00850   template <class T0,
00851             class T1, class Prop1, class Storage1, class Allocator1,
00852             class T2, class Storage2, class Allocator2,
00853             class T3,
00854             class T4, class Storage4, class Allocator4>
00855   void MltAdd(const T0 alpha,
00856               const SeldonTranspose& Trans,
00857               const Matrix<T1, Prop1, Storage1, Allocator1>& M,
00858               const Vector<T2, Storage2, Allocator2>& X,
00859               const T3 beta,
00860               Vector<T4, Storage4, Allocator4>& Y)
00861   {
00862     if (Trans.NoTrans())
00863       {
00864         MltAdd(alpha, M, X, beta, Y);
00865         return;
00866       }
00867     else if (Trans.ConjTrans())
00868       throw WrongArgument("MltAdd(alpha, trans, M, X, beta, Y)",
00869                           "Complex conjugation not supported.");
00870 
00871     int ma = M.GetM();
00872     int na = M.GetN();
00873 
00874 #ifdef SELDON_CHECK_DIMENSIONS
00875     CheckDim(Trans, M, X, Y, "MltAdd(alpha, trans, M, X, beta, Y)");
00876 #endif
00877 
00878     if (beta == T3(0))
00879       Y.Fill(T4(0));
00880     else
00881       Mlt(beta, Y);
00882 
00883     T4 zero(0);
00884     T4 temp;
00885     T4 alpha_(alpha);
00886 
00887     for (int i = 0; i < na; i++)
00888       {
00889         temp = zero;
00890         for (int j = 0; j < ma; j++)
00891           temp += M(j, i) * X(j);
00892         Y(i) += alpha_ * temp;
00893       }
00894   }
00895 
00896 
00897   // MltAdd //
00899 
00900 
00902   // Gauss //
00903 
00904 
00905   // Solve X = M*Y with Gauss method.
00906   // Warning: M is modified. The results are stored in X.
00907   template <class T0, class Prop0, class Storage0, class Allocator0,
00908             class T1, class Storage1, class Allocator1>
00909   inline void Gauss(Matrix<T0, Prop0, Storage0, Allocator0>& M,
00910                     Vector<T1, Storage1, Allocator1>& X)
00911   {
00912     int i, j, k;
00913     T1 r, S;
00914 
00915     int ma = M.GetM();
00916     int na = M.GetN();
00917 
00918 #ifdef SELDON_CHECK_DIMENSIONS
00919     if (na != ma)
00920       throw WrongDim("Gauss(M, X)",
00921                      "The matrix must be squared.");
00922 
00923     CheckDim(M, X, "Gauss(M, X)");
00924 #endif
00925 
00926     for (k = 0; k < ma - 1; k++)
00927       for (i = k + 1; i < ma; i++)
00928         {
00929           r = M(i, k) / M(k, k);
00930           for (j = k + 1; j < ma; j++)
00931             M(i, j) -= r * M(k, j);
00932           X(i) -= r *= X(k);
00933         }
00934 
00935     X(ma - 1) = X(ma - 1) / M(ma - 1, ma - 1);
00936     for (k = ma - 2; k > -1; k--)
00937       {
00938         S = X(k);
00939         for (j = k + 1; j < ma; j++)
00940           S -= M(k, j) * X(j);
00941         X(k) = S / M(k, k);
00942       }
00943   }
00944 
00945 
00946   // Gauss //
00948 
00949 
00950 
00952   // Gauss - Seidel //
00953 
00954 
00955   // Solve X = M*Y with Gauss-Seidel method.
00956   template <class T0, class Prop0, class Storage0, class Allocator0,
00957             class T1, class Storage1, class Allocator1,
00958             class T2, class Storage2, class Allocator2>
00959   inline void GaussSeidel(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
00960                           const Vector<T1, Storage1, Allocator1>& X,
00961                           Vector<T2, Storage2, Allocator2>& Y,
00962                           int iter)
00963   {
00964     int i, j, k;
00965     T1 temp;
00966 
00967     int ma = M.GetM();
00968     int na = M.GetN();
00969 
00970 #ifdef SELDON_CHECK_DIMENSIONS
00971     if (na != ma)
00972       throw WrongDim("GaussSeidel(M, X, Y, iter)",
00973                      "The matrix must be squared.");
00974 
00975     CheckDim(M, X, Y, "GaussSeidel(M, X, Y, iter)");
00976 #endif
00977 
00978     for (i = 0; i < iter; i++)
00979       for (j = 0; j < na; j++)
00980         {
00981           temp = 0;
00982           for (k = 0; k < j; k++)
00983             temp -= M(j, k) * Y(k);
00984           for (k = j + 1; k < na; k++)
00985             temp -= M(j, k) * Y(k);
00986           Y(j) = (X(j) + temp) / M(j, j);
00987         }
00988   }
00989 
00990 
00991   // Gauss-Seidel //
00993 
00994 
00995 
00997   // S.O.R. method //
00998 
00999 
01000   // Solve X = M*Y with S.O.R. method.
01001   template <class T0, class Prop0, class Storage0, class Allocator0,
01002             class T1, class Storage1, class Allocator1,
01003             class T2, class Storage2, class Allocator2,
01004             class T3>
01005   inline void SOR(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01006                   const Vector<T1, Storage1, Allocator1>& X,
01007                   Vector<T2, Storage2, Allocator2>& Y,
01008                   T3 omega,
01009                   int iter)
01010   {
01011     int i, j, k;
01012     T1 temp;
01013 
01014     int ma = M.GetM();
01015     int na = M.GetN();
01016 
01017 #ifdef SELDON_CHECK_DIMENSIONS
01018     if (na != ma)
01019       throw WrongDim("SOR(M, X, Y, omega, iter)",
01020                      "The matrix must be squared.");
01021 
01022     CheckDim(M, X, Y, "SOR(M, X, Y, omega, iter)");
01023 #endif
01024 
01025     for (i = 0; i < iter; i++)
01026       for (j = 0; j < na; j++)
01027         {
01028           temp = 0;
01029           for (k = 0; k < j; k++)
01030             temp -= M(j, k) * Y(k);
01031           for (k = j + 1; k < na; k++)
01032             temp -= M(j, k) * Y(k);
01033           Y(j) = (T3(1) - omega) * Y(j) + omega * (X(j) + temp) / M(j, j);
01034         }
01035   }
01036 
01037 
01038   // S.O.R. method //
01040 
01041 
01042 
01044   // SolveLU //
01045 
01046 
01048 
01060   template <class T0, class Prop0, class Storage0, class Allocator0,
01061             class T1, class Storage1, class Allocator1>
01062   void SolveLU(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01063                Vector<T1, Storage1, Allocator1>& Y)
01064   {
01065     int i, k;
01066     T1 temp;
01067 
01068     int ma = M.GetM();
01069 
01070 #ifdef SELDON_CHECK_DIMENSIONS
01071     int na = M.GetN();
01072     if (na != ma)
01073       throw WrongDim("SolveLU(M, Y)",
01074                      "The matrix must be squared.");
01075 
01076     CheckDim(M, Y, "SolveLU(M, Y)");
01077 #endif
01078 
01079     // Forward substitution.
01080     for (i = 0; i < ma; i++)
01081       {
01082         temp = 0;
01083         for (k = 0; k < i; k++)
01084           temp += M(i, k) * Y(k);
01085         Y(i) = (Y(i) - temp) / M(i, i);
01086       }
01087     // Back substitution.
01088     for (i = ma - 2; i > -1; i--)
01089       {
01090         temp = 0;
01091         for (k = i + 1; k < ma; k++)
01092           temp += M(i, k) * Y(k);
01093         Y(i) -= temp;
01094       }
01095   }
01096 
01097 
01098   // SolveLU //
01100 
01101 
01103   // SOLVE //
01104 
01105 
01107 
01114   template <class T0, class Prop0, class Storage0, class Allocator0,
01115             class T1, class Storage1, class Allocator1>
01116   void GetAndSolveLU(Matrix<T0, Prop0, Storage0, Allocator0>& M,
01117                      Vector<T1, Storage1, Allocator1>& Y)
01118   {
01119 #ifdef SELDON_WITH_LAPACK
01120     Vector<int> P;
01121     GetLU(M, P);
01122     SolveLU(M, P, Y);
01123 #else
01124     GetLU(M);
01125     SolveLU(M, Y);
01126 #endif
01127   }
01128 
01129 
01130   // SOLVE //
01132 
01133 
01134 
01136   // CHECKDIM //
01137 
01138 
01140 
01149   template <class T0, class Prop0, class Storage0, class Allocator0,
01150             class T1, class Storage1, class Allocator1,
01151             class T2, class Storage2, class Allocator2>
01152   void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01153                 const Vector<T1, Storage1, Allocator1>& X,
01154                 const Vector<T2, Storage2, Allocator2>& Y,
01155                 string function = "")
01156   {
01157     if (X.GetLength() != M.GetN() || Y.GetLength() != M.GetM())
01158       throw WrongDim(function, string("Operation M X + Y -> Y not permitted:")
01159                      + string("\n     M (") + to_str(&M) + string(") is a ")
01160                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01161                      + string(" matrix;\n     X (") + to_str(&X)
01162                      + string(") is vector of length ")
01163                      + to_str(X.GetLength()) + string(";\n     Y (")
01164                      + to_str(&Y) + string(") is vector of length ")
01165                      + to_str(Y.GetLength()) + string("."));
01166   }
01167 
01168 
01170 
01179   template <class T0, class Prop0, class Allocator0,
01180             class T1, class Allocator1,
01181             class T2, class Allocator2>
01182   void CheckDim(const Matrix<T0, Prop0, RowMajorCollection, Allocator0>& M,
01183                 const Vector<T1, Collection, Allocator1>& X,
01184                 const Vector<T2, Collection, Allocator2>& Y,
01185                 string function = "")
01186   {
01187     if (X.GetNvector() != M.GetNmatrix() || Y.GetNvector() != M.GetMmatrix())
01188       throw WrongDim(function, string("Operation M X + Y -> Y not permitted:")
01189                      + string("\n     M (") + to_str(&M) + string(") is a ")
01190                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01191                      + string(" matrix;\n     X (") + to_str(&X)
01192                      + string(") is vector of length ")
01193                      + to_str(X.GetNvector()) + string(";\n     Y (")
01194                      + to_str(&Y) + string(") is vector of length ")
01195                      + to_str(Y.GetNvector()) + string("."));
01196   }
01197 
01198 
01200 
01209   template <class T0, class Prop0, class Allocator0,
01210             class T1, class Allocator1,
01211             class T2, class Allocator2>
01212   void CheckDim(const Matrix<T0, Prop0, ColMajorCollection, Allocator0>& M,
01213                 const Vector<T1, Collection, Allocator1>& X,
01214                 const Vector<T2, Collection, Allocator2>& Y,
01215                 string function = "")
01216   {
01217     if (X.GetNvector() != M.GetNmatrix() || Y.GetNvector() != M.GetMmatrix())
01218       throw WrongDim(function, string("Operation M X + Y -> Y not permitted:")
01219                      + string("\n     M (") + to_str(&M) + string(") is a ")
01220                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01221                      + string(" matrix;\n     X (") + to_str(&X)
01222                      + string(") is vector of length ")
01223                      + to_str(X.GetNvector()) + string(";\n     Y (")
01224                      + to_str(&Y) + string(") is vector of length ")
01225                      + to_str(Y.GetNvector()) + string("."));
01226   }
01227 
01228 
01230 
01239   template <class T0, class Prop0, class Storage0, class Allocator0,
01240             class T1, class Allocator1,
01241             class T2, class Storage2, class Allocator2>
01242   void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01243                 const Vector<T1, Collection, Allocator1>& X,
01244                 const Vector<T2, Storage2, Allocator2>& Y,
01245                 string function = "")
01246   {
01247     if (X.GetLength() != M.GetN() || Y.GetLength() != M.GetM())
01248       throw WrongDim(function, string("Operation M X + Y -> Y not permitted:")
01249                      + string("\n     M (") + to_str(&M) + string(") is a ")
01250                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01251                      + string(" matrix;\n     X (") + to_str(&X)
01252                      + string(") is vector of length ")
01253                      + to_str(X.GetLength()) + string(";\n     Y (")
01254                      + to_str(&Y) + string(") is vector of length ")
01255                      + to_str(Y.GetLength()) + string("."));
01256   }
01257 
01258 
01260 
01272   template <class T0, class Prop0, class Storage0, class Allocator0,
01273             class T1, class Storage1, class Allocator1,
01274             class T2, class Storage2, class Allocator2>
01275   void CheckDim(const SeldonTranspose& trans,
01276                 const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01277                 const Vector<T1, Storage1, Allocator1>& X,
01278                 const Vector<T2, Storage2, Allocator2>& Y,
01279                 string function = "", string op = "M X + Y -> Y")
01280   {
01281     if (op == "M X + Y -> Y")
01282       if (trans.Trans())
01283         op = string("Operation M' X + Y -> Y not permitted:");
01284       else if (trans.ConjTrans())
01285         op = string("Operation M* X + Y -> Y not permitted:");
01286       else
01287         op = string("Operation M X + Y -> Y not permitted:");
01288     else
01289       op = string("Operation ") + op + string(" not permitted:");
01290     if (X.GetLength() != M.GetN(trans) || Y.GetLength() != M.GetM(trans))
01291       throw WrongDim(function, op + string("\n     M (") + to_str(&M)
01292                      + string(") is a ") + to_str(M.GetM()) + string(" x ")
01293                      + to_str(M.GetN()) + string(" matrix;\n     X (")
01294                      + to_str(&X) + string(") is vector of length ")
01295                      + to_str(X.GetLength()) + string(";\n     Y (")
01296                      + to_str(&Y) + string(") is vector of length ")
01297                      + to_str(Y.GetLength()) + string("."));
01298   }
01299 
01300 
01302 
01311   template <class T0, class Prop0, class Storage0, class Allocator0,
01312             class T1, class Storage1, class Allocator1>
01313   void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
01314                 const Vector<T1, Storage1, Allocator1>& X,
01315                 string function = "", string op = "M X")
01316   {
01317     if (X.GetLength() != M.GetN())
01318       throw WrongDim(function, string("Operation ") + op + " not permitted:"
01319                      + string("\n     M (") + to_str(&M) + string(") is a ")
01320                      + to_str(M.GetM()) + string(" x ") + to_str(M.GetN())
01321                      + string(" matrix;\n     X (") + to_str(&X)
01322                      + string(") is vector of length ")
01323                      + to_str(X.GetLength()) + string("."));
01324   }
01325 
01326 
01327   // CHECKDIM //
01329 
01330 
01331 }  // namespace Seldon.
01332 
01333 #define SELDON_FUNCTIONS_MATVECT_CXX
01334 #endif