Warning: this documentation for the development version is under construction.
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