Warning: this documentation for the development version is under construction.
00001 // Copyright (C) 2001-2009 Vivien Mallet 00002 // Copyright (C) 2003-2009 Marc Duruflé 00003 // Copyright (C) 2010 INRIA 00004 // Author(s): Marc Fragu 00005 // 00006 // This file is part of the linear-algebra library Seldon, 00007 // http://seldon.sourceforge.net/. 00008 // 00009 // Seldon is free software; you can redistribute it and/or modify it under the 00010 // terms of the GNU Lesser General Public License as published by the Free 00011 // Software Foundation; either version 2.1 of the License, or (at your option) 00012 // any later version. 00013 // 00014 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY 00015 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00016 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00017 // more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public License 00020 // along with Seldon. If not, see http://www.gnu.org/licenses/. 00021 00022 00023 #ifndef SELDON_FILE_FUNCTIONS_MATRIX_CXX 00024 #define SELDON_FILE_FUNCTIONS_MATRIX_CXX 00025 00026 00027 #include "Functions_Matrix.hxx" 00028 00029 00030 /* 00031 Function defined in this file: 00032 00033 alpha A -> A 00034 Mlt(alpha, A) 00035 00036 A B -> C 00037 Mlt(A, B, C) 00038 00039 alpha A B -> C 00040 Mlt(alpha, A, B, C) 00041 00042 alpha A B + beta C -> C 00043 MltAdd(alpha, A, B, beta, C) 00044 00045 alpha A + B -> B 00046 Add(alpha, A, B) 00047 00048 LU factorization of matrix A without pivoting. 00049 GetLU(A) 00050 00051 Highest absolute value of A. 00052 MaxAbs(A) 00053 00054 1-norm of matrix A. 00055 Norm1(A) 00056 00057 infinity norm of matrix A. 00058 NormInf(A) 00059 00060 Transpose(A) 00061 */ 00062 00063 00064 namespace Seldon 00065 { 00066 00067 00069 // MLT // 00070 00071 00073 00077 template <class T0, 00078 class T1, class Prop1, class Storage1, class Allocator1> 00079 void Mlt(const T0 alpha, Matrix<T1, Prop1, Storage1, Allocator1>& A) 00080 { 00081 T1 alpha_ = alpha; 00082 00083 typename Matrix<T1, Prop1, Storage1, Allocator1>::pointer 00084 data = A.GetData(); 00085 00086 for (int i = 0; i < A.GetDataSize(); i++) 00087 data[i] = alpha_ * data[i]; 00088 } 00089 00090 00092 00096 template <class T0, 00097 class T1, class Prop1, class Allocator1> 00098 void Mlt(const T0 alpha, 00099 Matrix<T1, Prop1, ColMajorCollection, Allocator1>& A) 00100 { 00101 typename T1::value_type alpha_ = alpha; 00102 for (int i = 0; i < A.GetMmatrix(); i++) 00103 for (int j = 0; j < A.GetNmatrix(); j++) 00104 Mlt(alpha, A.GetMatrix(i, j)); 00105 } 00106 00107 00109 00113 template <class T0, 00114 class T1, class Prop1, class Allocator1> 00115 void Mlt(const T0 alpha, 00116 Matrix<T1, Prop1, RowMajorCollection, Allocator1>& A) 00117 { 00118 typename T1::value_type alpha_ = alpha; 00119 for (int i = 0; i < A.GetMmatrix(); i++) 00120 for (int j = 0; j < A.GetNmatrix(); j++) 00121 Mlt(alpha_, A.GetMatrix(i, j)); 00122 } 00123 00124 00126 00130 template <class T0, class Allocator> 00131 void Mlt(const T0 alpha, 00132 Matrix<FloatDouble, General, DenseSparseCollection, Allocator>& A) 00133 { 00134 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator> 00135 ::float_dense_m m0; 00136 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator> 00137 ::float_sparse_m m1; 00138 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator> 00139 ::double_dense_m m2; 00140 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator> 00141 ::double_sparse_m m3; 00142 00143 for (int i = 0; i < A.GetMmatrix(); i++) 00144 for (int j = 0; j < A.GetNmatrix(); j++) 00145 { 00146 switch (A.GetType(i, j)) 00147 { 00148 case 0: 00149 A.GetMatrix(i, j, m0); 00150 Mlt(float(alpha), m0); 00151 A.SetMatrix(i, j, m0); 00152 m0.Nullify(); 00153 break; 00154 case 1: 00155 A.GetMatrix(i, j, m1); 00156 Mlt(float(alpha), m1); 00157 A.SetMatrix(i, j, m1); 00158 m1.Nullify(); 00159 break; 00160 case 2: 00161 A.GetMatrix(i, j, m2); 00162 Mlt(double(alpha), m2); 00163 A.SetMatrix(i, j, m2); 00164 m2.Nullify(); 00165 break; 00166 case 3: 00167 A.GetMatrix(i, j, m3); 00168 Mlt(double(alpha), m3); 00169 A.SetMatrix(i, j, m3); 00170 m3.Nullify(); 00171 break; 00172 default: 00173 throw WrongArgument("Mlt(alpha, Matrix<FloatDouble, " 00174 "DenseSparseCollection)", 00175 "Underlying matrix (" + to_str(i) + " ," 00176 + to_str(j) + " ) not defined."); 00177 } 00178 } 00179 } 00180 00181 00183 00191 template <class T0, 00192 class T1, class Prop1, class Storage1, class Allocator1, 00193 class T2, class Prop2, class Storage2, class Allocator2, 00194 class T3, class Prop3, class Storage3, class Allocator3> 00195 void Mlt(const T0 alpha, 00196 const Matrix<T1, Prop1, Storage1, Allocator1>& A, 00197 const Matrix<T2, Prop2, Storage2, Allocator2>& B, 00198 Matrix<T3, Prop3, Storage3, Allocator3>& C) 00199 { 00200 C.Fill(T3(0)); 00201 MltAdd(alpha, A, B, T3(0), C); 00202 } 00203 00204 00206 00212 template <class T0, class Prop0, class Storage0, class Allocator0, 00213 class T1, class Prop1, class Storage1, class Allocator1, 00214 class T2, class Prop2, class Storage2, class Allocator2> 00215 void Mlt(const Matrix<T0, Prop0, Storage0, Allocator0>& A, 00216 const Matrix<T1, Prop1, Storage1, Allocator1>& B, 00217 Matrix<T2, Prop2, Storage2, Allocator2>& C) 00218 { 00219 C.Fill(T2(0)); 00220 MltAdd(T0(1), A, B, T2(0), C); 00221 } 00222 00223 00225 00233 template <class T0, class Prop0, class Allocator0, 00234 class T1, class Prop1, class Allocator1, 00235 class T2, class Prop2, class Allocator2> 00236 void Mlt(const Matrix<T0, Prop0, RowSparse, Allocator0>& A, 00237 const Matrix<T1, Prop1, RowSparse, Allocator1>& B, 00238 Matrix<T2, Prop2, RowSparse, Allocator2>& C) 00239 { 00240 #ifdef SELDON_CHECK_DIMENSIONS 00241 CheckDim(A, B, "Mlt(const Matrix<RowSparse>& A, const " 00242 "Matrix<RowSparse>& B, Matrix<RowSparse>& C)"); 00243 #endif 00244 00245 int h, i, k, l, col; 00246 int Nnonzero, Nnonzero_row, Nnonzero_row_max; 00247 IVect column_index; 00248 Vector<T2> row_value; 00249 T1 value; 00250 int m = A.GetM(); 00251 00252 int* c_ptr = NULL; 00253 int* c_ind = NULL; 00254 T2* c_data = NULL; 00255 C.Clear(); 00256 00257 #ifdef SELDON_CHECK_MEMORY 00258 try 00259 { 00260 #endif 00261 00262 c_ptr = reinterpret_cast<int*>(calloc(m + 1, sizeof(int))); 00263 00264 #ifdef SELDON_CHECK_MEMORY 00265 } 00266 catch (...) 00267 { 00268 c_ptr = NULL; 00269 } 00270 00271 if (c_ptr == NULL) 00272 throw NoMemory("Mlt(const Matrix<RowSparse>& A, const " 00273 "Matrix<RowSparse>& B, Matrix<RowSparse>& C)", 00274 "Unable to allocate memory for an array of " 00275 + to_str(m + 1) + " integers."); 00276 #endif 00277 00278 c_ptr[0] = 0; 00279 00280 // Number of non-zero elements in C. 00281 Nnonzero = 0; 00282 for (i = 0; i < m; i++) 00283 { 00284 c_ptr[i + 1] = c_ptr[i]; 00285 00286 if (A.GetPtr()[i + 1] != A.GetPtr()[i]) 00287 // There are elements in the i-th row of A, so there can be non-zero 00288 // entries in C as well. Checks whether any column in B has an 00289 // element whose row index matches a column index of a non-zero in 00290 // the i-th row of A. 00291 { 00292 // Maximum number of non-zero entry on the i-th row of C. 00293 Nnonzero_row_max = 0; 00294 // For every element in the i-th row. 00295 for (k = A.GetPtr()[i]; k < A.GetPtr()[i + 1]; k++) 00296 { 00297 col = A.GetInd()[k]; 00298 Nnonzero_row_max += B.GetPtr()[col + 1] - B.GetPtr()[col]; 00299 } 00300 // Now gets the column indexes. 00301 column_index.Reallocate(Nnonzero_row_max); 00302 row_value.Reallocate(Nnonzero_row_max); 00303 h = 0; 00304 // For every element in the i-th row. 00305 for (k = A.GetPtr()[i]; k < A.GetPtr()[i + 1]; k++) 00306 { 00307 // The k-th column index (among the nonzero entries) on the 00308 // i-th row, and the corresponding value. 00309 col = A.GetInd()[k]; 00310 value = A.GetData()[k]; 00311 // Loop on all elements in the col-th row in B. These elements 00312 // are multiplied with the element (i, col) of A. 00313 for (l = B.GetPtr()[col]; l < B.GetPtr()[col + 1]; l++) 00314 { 00315 column_index(h) = B.GetInd()[l]; 00316 row_value(h) = value * B.GetData()[l]; 00317 h++; 00318 } 00319 } 00320 // Now gathers and sorts all elements on the i-th row of C. 00321 Nnonzero_row = column_index.GetLength(); 00322 Assemble(Nnonzero_row, column_index, row_value); 00323 00324 #ifdef SELDON_CHECK_MEMORY 00325 try 00326 { 00327 #endif 00328 00329 // Reallocates 'c_ind' and 'c_data' in order to append the 00330 // elements of the i-th row of C. 00331 c_ind = reinterpret_cast<int*> 00332 (realloc(reinterpret_cast<void*>(c_ind), 00333 (Nnonzero + Nnonzero_row) * sizeof(int))); 00334 c_data = reinterpret_cast<T2*> 00335 (C.GetAllocator().reallocate(c_data, 00336 Nnonzero + Nnonzero_row)); 00337 00338 #ifdef SELDON_CHECK_MEMORY 00339 } 00340 catch (...) 00341 { 00342 c_ind = NULL; 00343 c_data = NULL; 00344 } 00345 00346 if ((c_ind == NULL || c_data == NULL) 00347 && Nnonzero + Nnonzero_row != 0) 00348 throw NoMemory("Mlt(const Matrix<RowSparse>& A, const " 00349 "Matrix<RowSparse>& B, Matrix<RowSparse>& C)", 00350 "Unable to allocate memory for an array of " 00351 + to_str(Nnonzero + Nnonzero_row) + " integers " 00352 "and for an array of " 00353 + to_str(sizeof(T2) * (Nnonzero + Nnonzero_row)) 00354 + " bytes."); 00355 #endif 00356 00357 c_ptr[i + 1] += Nnonzero_row; 00358 for (h = 0; h < Nnonzero_row; h++) 00359 { 00360 c_ind[Nnonzero + h] = column_index(h); 00361 c_data[Nnonzero + h] = row_value(h); 00362 } 00363 Nnonzero += Nnonzero_row; 00364 } 00365 } 00366 00367 C.SetData(A.GetM(), B.GetN(), Nnonzero, c_data, c_ptr, c_ind); 00368 } 00369 00370 00372 00380 template <class T0, class Prop0, class Allocator0, 00381 class T1, class Prop1, class Allocator1, 00382 class T2, class Prop2, class Allocator2> 00383 void Mlt(const Matrix<T0, Prop0, RowMajor, Allocator0>& A, 00384 const Matrix<T1, Prop1, RowSparse, Allocator1>& B, 00385 Matrix<T2, Prop2, RowMajor, Allocator2>& C) 00386 { 00387 #ifdef SELDON_CHECK_DIMENSIONS 00388 CheckDim(A, B, "Mlt(const Matrix<RowMajor>& A, const " 00389 "Matrix<RowSparse>& B, Matrix<RowMajor>& C)"); 00390 #endif 00391 00392 int m = A.GetM(); 00393 int n = A.GetN(); 00394 00395 C.Reallocate(A.GetM(), B.GetN()); 00396 C.Fill(T2(0)); 00397 00398 for (int i = 0; i < m; i++) 00399 { 00400 for (int k = 0; k < n; k++) 00401 { 00402 // Loop on all elements in the k-th row in B. These elements 00403 // are multiplied with the element (i, k) of A. 00404 for (int l = B.GetPtr()[k]; l < B.GetPtr()[k + 1]; l++) 00405 C(i, B.GetInd()[l]) += A(i, k) * B.GetData()[l]; 00406 } 00407 } 00408 } 00409 00410 00412 00420 template <class T0, class Prop0, class Allocator0, 00421 class T1, class Prop1, class Allocator1, 00422 class T2, class Prop2, class Allocator2> 00423 void MltNoTransTrans(const Matrix<T0, Prop0, RowMajor, Allocator0>& A, 00424 const Matrix<T1, Prop1, RowSparse, Allocator1>& B, 00425 Matrix<T2, Prop2, RowMajor, Allocator2>& C) 00426 { 00427 #ifdef SELDON_CHECK_DIMENSIONS 00428 CheckDim(SeldonNoTrans, A, SeldonTrans, B, 00429 "MltNoTransTrans(const Matrix<RowMajor>& A, const " 00430 "Matrix<RowSparse>& B, Matrix<RowMajor>& C)"); 00431 #endif 00432 00433 int m = A.GetM(); 00434 C.Reallocate(A.GetM(), B.GetM()); 00435 C.Fill(T2(0)); 00436 for (int i = 0; i < m; i++) 00437 { 00438 for (int j = 0; j < B.GetM(); j++) 00439 { 00440 // Loop on all elements in the i-th row in B. These elements 00441 // are multiplied with the element (i, k) of A. 00442 for (int l = B.GetPtr()[j]; l < B.GetPtr()[j + 1]; l++) 00443 C(i, j) += A(i, B.GetInd()[l]) * B.GetData()[l]; 00444 } 00445 } 00446 } 00447 00448 00450 00458 template <class T0, class Prop0, class Allocator0, 00459 class T1, class Prop1, class Allocator1, 00460 class T2, class Prop2, class Allocator2> 00461 void MltNoTransTrans(const Matrix<T0, Prop0, RowSparse, Allocator0>& A, 00462 const Matrix<T1, Prop1, RowSparse, Allocator1>& B, 00463 Matrix<T2, Prop2, RowSparse, Allocator2>& C) 00464 { 00465 #ifdef SELDON_CHECK_DIMENSIONS 00466 CheckDim(SeldonNoTrans, A, SeldonTrans, B, 00467 "MltNoTransTrans(const Matrix<RowSparse>& A, " 00468 "const Matrix<RowSparse>& B, Matrix<RowSparse>& C)"); 00469 #endif 00470 00471 int h, i, k, col; 00472 int ib, kb; 00473 int Nnonzero_row; 00474 int Nnonzero; 00475 00476 // 'MallocAlloc' is specified so that reallocations may be efficient. 00477 // There will be no need for 'Resize': 'Reallocate' will do the job. 00478 Vector<int, VectFull, MallocAlloc<int> > column_index; 00479 Vector<T2, VectFull, MallocAlloc<T2> > row_value; 00480 T2 value = 0; 00481 00482 int m = A.GetM(); 00483 int n = B.GetM(); 00484 00485 int* c_ptr = NULL; 00486 int* c_ind = NULL; 00487 T2* c_data = NULL; 00488 00489 #ifdef SELDON_CHECK_MEMORY 00490 try 00491 { 00492 #endif 00493 00494 c_ptr = reinterpret_cast<int*>(calloc(m + 1, sizeof(int))); 00495 00496 #ifdef SELDON_CHECK_MEMORY 00497 } 00498 catch (...) 00499 { 00500 c_ptr = NULL; 00501 } 00502 00503 if (c_ptr == NULL) 00504 throw NoMemory("MltNoTransTrans(const Matrix<RowSparse>& A, " 00505 "const Matrix<RowSparse>& B, Matrix<RowSparse>& C)", 00506 "Unable to allocate memory for an array of " 00507 + to_str(m + 1) + " integers."); 00508 #endif 00509 00510 c_ptr[0] = 0; 00511 00512 // Number of non-zero elements in C. 00513 Nnonzero = 0; 00514 00515 for (i = 0; i < m; i++) 00516 { 00517 c_ptr[i + 1] = c_ptr[i]; 00518 00519 if (A.GetPtr()[i + 1] != A.GetPtr()[i]) 00520 // There are elements in the i-th row of A, so there can be non-zero 00521 // entries in C as well. It is checked below whether any row in B 00522 // has an element whose row index matches a column index of a 00523 // non-zero in the i-th row of A. 00524 { 00525 // For every element in the i-th row. 00526 for (k = A.GetPtr()[i]; k < A.GetPtr()[i + 1]; k++) 00527 { 00528 col = A.GetInd()[k]; 00529 // For every row in B. 00530 for (ib = 0; ib < n; ib++) 00531 { 00532 for (kb = B.GetPtr()[ib]; kb < B.GetPtr()[ib + 1]; kb++) 00533 if (col == B.GetInd()[kb]) 00534 value += A.GetData()[k] * B.GetData()[kb]; 00535 if (value != T2(0)) 00536 { 00537 row_value.Append(value); 00538 column_index.Append(ib); 00539 value = T2(0); 00540 } 00541 } 00542 } 00543 00544 Nnonzero_row = column_index.GetLength(); 00545 Assemble(Nnonzero_row, column_index, row_value); 00546 00547 #ifdef SELDON_CHECK_MEMORY 00548 try 00549 { 00550 #endif 00551 00552 // Reallocates 'c_ind' and 'c_data' in order to append the 00553 // elements of the i-th row of C. 00554 c_ind = reinterpret_cast<int*> 00555 (realloc(reinterpret_cast<void*>(c_ind), 00556 (Nnonzero + Nnonzero_row) * sizeof(int))); 00557 c_data = reinterpret_cast<T2*> 00558 (C.GetAllocator().reallocate(c_data, 00559 Nnonzero + Nnonzero_row)); 00560 00561 #ifdef SELDON_CHECK_MEMORY 00562 } 00563 catch (...) 00564 { 00565 c_ind = NULL; 00566 c_data = NULL; 00567 } 00568 00569 if ((c_ind == NULL || c_data == NULL) 00570 && Nnonzero_row != 0) 00571 throw NoMemory("MltNoTransTrans(const Matrix<RowSparse>& A, " 00572 "const Matrix<RowSparse>& B, " 00573 "Matrix<RowSparse>& C)", 00574 "Unable to allocate memory for an array of " 00575 + to_str(Nnonzero + Nnonzero_row) + " integers " 00576 "and for an array of " 00577 + to_str(sizeof(T2) * (Nnonzero + Nnonzero_row)) 00578 + " bytes."); 00579 #endif 00580 00581 c_ptr[i + 1] += Nnonzero_row; 00582 for (h = 0; h < Nnonzero_row; h++) 00583 { 00584 c_ind[Nnonzero + h] = column_index(h); 00585 c_data[Nnonzero + h] = row_value(h); 00586 } 00587 Nnonzero += Nnonzero_row; 00588 } 00589 00590 column_index.Clear(); 00591 row_value.Clear(); 00592 } 00593 00594 C.SetData(A.GetM(), B.GetM(), Nnonzero, c_data, c_ptr, c_ind); 00595 } 00596 00597 00598 // MLT // 00600 00601 00603 // MLTADD // 00604 00605 00607 00617 template <class T0, 00618 class T1, class Prop1, class Storage1, class Allocator1, 00619 class T2, class Prop2, class Storage2, class Allocator2, 00620 class T3, 00621 class T4, class Prop4, class Storage4, class Allocator4> 00622 void MltAdd(const T0 alpha, 00623 const Matrix<T1, Prop1, Storage1, Allocator1>& A, 00624 const Matrix<T2, Prop2, Storage2, Allocator2>& B, 00625 const T3 beta, 00626 Matrix<T4, Prop4, Storage4, Allocator4>& C) 00627 { 00628 int na = A.GetN(); 00629 int mc = C.GetM(); 00630 int nc = C.GetN(); 00631 00632 #ifdef SELDON_CHECK_DIMENSIONS 00633 CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)"); 00634 #endif 00635 00636 T4 temp; 00637 T4 alpha_(alpha); 00638 T4 beta_(beta); 00639 00640 if (beta_ != T4(0)) 00641 for (int i = 0; i < Storage4::GetFirst(mc, nc); i++) 00642 for (int j = 0; j < Storage4::GetSecond(mc, nc); j++) 00643 C(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j)) 00644 *= beta_; 00645 else 00646 for (int i = 0; i < Storage4::GetFirst(mc, nc); i++) 00647 for (int j = 0; j < Storage4::GetSecond(mc, nc); j++) 00648 C(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j)) = T4(0); 00649 00650 for (int i = 0; i < Storage4::GetFirst(mc, nc); i++) 00651 for (int j = 0; j < Storage4::GetSecond(mc, nc); j++) 00652 { 00653 temp = T4(0); 00654 for (int k = 0; k < na; k++) 00655 temp += A(Storage4::GetFirst(i, j), k) 00656 * B(k, Storage4::GetSecond(i, j)); 00657 C(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j)) 00658 += alpha_ * temp; 00659 } 00660 } 00661 00662 00664 00678 template <class T0, 00679 class T1, class Prop1, class Storage1, class Allocator1, 00680 class T2, class Prop2, class Storage2, class Allocator2, 00681 class T3, 00682 class T4, class Prop4, class Storage4, class Allocator4> 00683 void MltAdd(const T0 alpha, 00684 const SeldonTranspose& TransA, 00685 const Matrix<T1, Prop1, Storage1, Allocator1>& A, 00686 const SeldonTranspose& TransB, 00687 const Matrix<T2, Prop2, Storage2, Allocator2>& B, 00688 const T3 beta, 00689 Matrix<T4, Prop4, Storage4, Allocator4>& C) 00690 { 00691 if (!TransA.NoTrans()) 00692 throw WrongArgument("MltAdd(const T0 alpha, SeldonTranspose TransA, " 00693 "const Matrix<T1, Prop1, Storage1, Allocator1>& A" 00694 "SeldonTranspose TransB," 00695 "const Matrix<T2, Prop2, Storage2, Allocator2>& B," 00696 "const T3 beta," 00697 "Matrix<T4, Prop4, Storage4, Allocator4>& C)", 00698 "'TransA' must be equal to 'SeldonNoTrans'."); 00699 if (!TransB.NoTrans() && !TransB.Trans()) 00700 throw WrongArgument("MltAdd(const T0 alpha, SeldonTranspose TransA, " 00701 "const Matrix<T1, Prop1, Storage1, Allocator1>& A" 00702 "SeldonTranspose TransB," 00703 "const Matrix<T2, Prop2, Storage2, Allocator2>& B," 00704 "const T3 beta," 00705 "Matrix<T4, Prop4, Storage4, Allocator4>& C)", 00706 "'TransB' must be equal to 'SeldonNoTrans' or " 00707 "'SeldonTrans'."); 00708 00709 if (!TransB.Trans()) 00710 MltAdd(alpha, A, B, beta, C); 00711 else 00712 { 00713 00714 int na = A.GetN(); 00715 int mc = C.GetM(); 00716 int nc = C.GetN(); 00717 00718 #ifdef SELDON_CHECK_DIMENSIONS 00719 CheckDim(SeldonNoTrans, A, SeldonTrans, B, C, 00720 "MltAdd(alpha, TransA, A, TransB, B, beta, C)"); 00721 #endif 00722 00723 T4 temp; 00724 T4 alpha_(alpha); 00725 T4 beta_(beta); 00726 00727 if (beta_ != T4(0)) 00728 for (int i = 0; i < Storage4::GetFirst(mc, nc); i++) 00729 for (int j = 0; j < Storage4::GetSecond(mc, nc); j++) 00730 C(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j)) 00731 *= beta_; 00732 else 00733 for (int i = 0; i < Storage4::GetFirst(mc, nc); i++) 00734 for (int j = 0; j < Storage4::GetSecond(mc, nc); j++) 00735 C(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j)) = T4(0); 00736 00737 for (int i = 0; i < Storage4::GetFirst(mc, nc); i++) 00738 for (int j = 0; j < Storage4::GetSecond(mc, nc); j++) 00739 { 00740 temp = T4(0); 00741 for (int k = 0; k < na; k++) 00742 temp += A(Storage4::GetFirst(i, j), k) 00743 * B(Storage4::GetSecond(i, j), k); 00744 C(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j)) 00745 += alpha_ * temp; 00746 } 00747 } 00748 } 00749 00750 00752 00762 template <class T0, 00763 class T1, class Prop1, class Allocator1, 00764 class T2, class Allocator2, 00765 class T3, 00766 class T4, class Prop4, class Allocator4> 00767 void MltAdd(const T0 alpha, 00768 const Matrix<T1, Prop1, PETScMPIDense, Allocator1>& A, 00769 const Matrix<T2, General, RowMajor, Allocator2>& B, 00770 const T3 beta, 00771 Matrix<T4, Prop4, PETScMPIDense, Allocator4>& C) 00772 { 00773 int na = A.GetN(); 00774 int mc = C.GetM(); 00775 int nc = C.GetN(); 00776 00777 #ifdef SELDON_CHECK_DIMENSIONS 00778 CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)"); 00779 #endif 00780 T1 *local_a; 00781 MatGetArray(A.GetPetscMatrix(), &local_a); 00782 int nlocal_A; 00783 int mlocal_A; 00784 MatGetLocalSize(A.GetPetscMatrix(), &mlocal_A, &nlocal_A); 00785 Matrix<T1, Prop1, ColMajor, Allocator1> local_A; 00786 local_A.SetData(mlocal_A, na, local_a); 00787 00788 T4 *local_c; 00789 MatGetArray(C.GetPetscMatrix(), &local_c); 00790 int nlocal_C; 00791 int mlocal_C; 00792 MatGetLocalSize(C.GetPetscMatrix(), &mlocal_C, &nlocal_C); 00793 Matrix<T4, Prop4, ColMajor, Allocator4> local_C; 00794 local_C.SetData(mlocal_C, nc, local_c); 00795 00796 MltAdd(alpha, local_A, B, beta, local_C); 00797 00798 local_A.Nullify(); 00799 MatRestoreArray(A.GetPetscMatrix(), &local_a); 00800 A.Flush(); 00801 00802 local_C.Nullify(); 00803 MatRestoreArray(C.GetPetscMatrix(), &local_c); 00804 C.Flush(); 00805 } 00806 00807 00809 00819 template <class T0, 00820 class T1, class Prop1, class Allocator1, 00821 class T2, class Prop2, class Allocator2, 00822 class T3, 00823 class T4, class Prop4, class Allocator4> 00824 void MltAdd(const T0 alpha, 00825 const Matrix<T1, Prop1, RowMajorCollection, Allocator1>& A, 00826 const Matrix<T2, Prop2, RowMajorCollection, Allocator2>& B, 00827 const T3 beta, 00828 Matrix<T4, Prop4, RowMajorCollection, Allocator4>& C) 00829 { 00830 int na = A.GetNmatrix(); 00831 int mc = C.GetMmatrix(); 00832 int nc = C.GetNmatrix(); 00833 00834 #ifdef SELDON_CHECK_DIMENSIONS 00835 CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)"); 00836 #endif 00837 00838 typedef typename T4::value_type value_type; 00839 00840 Mlt(value_type(beta), C); 00841 00842 for (int i = 0; i < mc; i++ ) 00843 for (int j = 0; j < nc; j++) 00844 for (int k = 0; k < na; k++) 00845 MltAdd(value_type(alpha), A.GetMatrix(i, k), B.GetMatrix(k, j), 00846 value_type(1), C.GetMatrix(i, j)); 00847 } 00848 00849 00851 00861 template <class T0, 00862 class T1, class Prop1, class Allocator1, 00863 class T2, class Prop2, class Allocator2, 00864 class T3, 00865 class T4, class Prop4, class Allocator4> 00866 void MltAdd(const T0 alpha, 00867 const Matrix<T1, Prop1, ColMajorCollection, Allocator1>& A, 00868 const Matrix<T2, Prop2, ColMajorCollection, Allocator2>& B, 00869 const T3 beta, 00870 Matrix<T4, Prop4, ColMajorCollection, Allocator4>& C) 00871 { 00872 int na = A.GetNmatrix(); 00873 int mc = C.GetMmatrix(); 00874 int nc = C.GetNmatrix(); 00875 00876 #ifdef SELDON_CHECK_DIMENSIONS 00877 CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)"); 00878 #endif 00879 00880 typedef typename T4::value_type value_type; 00881 00882 Mlt(value_type(beta), C); 00883 00884 for (int i = 0; i < mc; i++ ) 00885 for (int j = 0; j < nc; j++) 00886 for (int k = 0; k < na; k++) 00887 MltAdd(value_type(alpha), A.GetMatrix(i, k), B.GetMatrix(k, j), 00888 value_type(1), C.GetMatrix(i, j)); 00889 } 00890 00891 00892 template <class T0, 00893 class T1, class Allocator1, 00894 class T2, class Allocator2, 00895 class T3, 00896 class T4, class Allocator4> 00897 void MltAdd(const T0 alpha, 00898 const Matrix<T1, General, RowMajor, Allocator1>& A, 00899 const Matrix<T2, General, RowMajor, Allocator2>& B, 00900 const T3 beta, 00901 Matrix<T4, General, RowSparse, Allocator4>& C) 00902 { 00903 throw Undefined("void MltAdd(const T0 alpha," 00904 "const Matrix<T1, General, RowMajor, Allocator1>& A," 00905 "const Matrix<T2, General, RowMajor, Allocator2>& B," 00906 "const T3 beta," 00907 "Matrix<T4, General, RowSparse, Allocator4>& C)"); 00908 } 00909 00910 00911 template <class T0, 00912 class T1, class Allocator1, 00913 class T2, class Allocator2, 00914 class T3, 00915 class T4, class Allocator4> 00916 void MltAdd(const T0 alpha, 00917 const Matrix<T1, General, RowMajor, Allocator1>& A, 00918 const Matrix<T2, General, RowSparse, Allocator2>& B, 00919 const T3 beta, 00920 Matrix<T4, General, RowSparse, Allocator4>& C) 00921 { 00922 throw Undefined("void MltAdd(const T0 alpha," 00923 "const Matrix<T1, General, RowMajor, Allocator1>& A," 00924 "const Matrix<T2, General, RowSparse, Allocator2>& B," 00925 "const T3 beta," 00926 "Matrix<T4, General, RowSparse, Allocator4>& C)"); 00927 } 00928 00929 00930 template <class T0, 00931 class T1, class Allocator1, 00932 class T2, class Allocator2, 00933 class T3, 00934 class T4, class Allocator4> 00935 void MltAdd(const T0 alpha, 00936 const Matrix<T1, General, RowSparse, Allocator1>& A, 00937 const Matrix<T2, General, RowMajor, Allocator2>& B, 00938 const T3 beta, 00939 Matrix<T4, General, RowSparse, Allocator4>& C) 00940 { 00941 throw Undefined("void MltAdd(const T0 alpha," 00942 "const Matrix<T1, General, RowSparse, Allocator1>& A," 00943 "const Matrix<T2, General, RowMajor, Allocator2>& B," 00944 "const T3 beta," 00945 "Matrix<T4, General, RowSparse, Allocator4>& C)"); 00946 } 00947 00948 00949 template <class T0, 00950 class Allocator1, 00951 class Allocator2, 00952 class Allocator3, 00953 class T4, class Prop4, class Storage4, class Allocator4> 00954 void MltAdd_heterogeneous(const T0 alpha, 00955 const Matrix<FloatDouble, General, 00956 DenseSparseCollection, Allocator1>& A, 00957 const Matrix<FloatDouble, General, 00958 DenseSparseCollection, Allocator2>& B, 00959 Matrix<FloatDouble, General, 00960 DenseSparseCollection, Allocator3>& C, 00961 Matrix<T4, Prop4, Storage4, Allocator4>& mc, 00962 int i, int j) 00963 { 00964 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1> 00965 ::float_dense_m m0a; 00966 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1> 00967 ::float_sparse_m m1a; 00968 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1> 00969 ::double_dense_m m2a; 00970 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1> 00971 ::double_sparse_m m3a; 00972 00973 int na = A.GetNmatrix(); 00974 for (int k = 0; k < na; k++) 00975 { 00976 switch (A.GetType(i, k)) 00977 { 00978 case 0: 00979 A.GetMatrix(i, k, m0a); 00980 MltAdd_heterogeneous2(alpha, m0a, B, C, mc, j, k); 00981 m0a.Nullify(); 00982 break; 00983 case 1: 00984 A.GetMatrix(i, k, m1a); 00985 MltAdd_heterogeneous2(alpha, m1a, B, C, mc, j, k); 00986 m1a.Nullify(); 00987 break; 00988 case 2: 00989 A.GetMatrix(i, k, m2a); 00990 MltAdd_heterogeneous2(alpha, m2a, B, C, mc, j, k); 00991 m2a.Nullify(); 00992 break; 00993 case 3: 00994 A.GetMatrix(i, k, m3a); 00995 MltAdd_heterogeneous2(alpha, m3a, B, C, mc, j, k); 00996 m3a.Nullify(); 00997 break; 00998 default: 00999 throw WrongArgument("Matrix<FloatDouble, DenseSparseCollection>::" 01000 "MltAdd_heterogeneous(alpha, A, B, beta, C) ", 01001 "Underlying matrix A (" + to_str(i) + " ," 01002 + to_str(k) + " ) not defined."); 01003 } 01004 } 01005 } 01006 01007 01008 template<class T0, 01009 class T1, class Prop1, class Storage1, class Allocator1, 01010 class Allocator2, 01011 class Allocator3, 01012 class T4, class Prop4, class Storage4, class Allocator4> 01013 void MltAdd_heterogeneous2(const T0 alpha, 01014 const Matrix<T1, Prop1, 01015 Storage1, Allocator1>& ma, 01016 const Matrix<FloatDouble, General, 01017 DenseSparseCollection, Allocator2>& B, 01018 Matrix<FloatDouble, General, 01019 DenseSparseCollection, Allocator3>& C, 01020 Matrix<T4, Prop4, Storage4, Allocator4>& mc, 01021 int j, int k) 01022 { 01023 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01024 ::float_dense_m m0b; 01025 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01026 ::float_sparse_m m1b; 01027 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01028 ::double_dense_m m2b; 01029 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01030 ::double_sparse_m m3b; 01031 01032 switch (B.GetType(k, j)) 01033 { 01034 case 0: 01035 B.GetMatrix(k, j, m0b); 01036 MltAdd(alpha, ma, m0b, 1., mc); 01037 m0b.Nullify(); 01038 break; 01039 case 1: 01040 B.GetMatrix(k, j, m1b); 01041 MltAdd(alpha, ma, m1b, 1., mc); 01042 m1b.Nullify(); 01043 break; 01044 case 2: 01045 B.GetMatrix(k, j, m2b); 01046 MltAdd(alpha, ma, m2b, 1., mc); 01047 m2b.Nullify(); 01048 break; 01049 case 3: 01050 B.GetMatrix(k, j, m3b); 01051 MltAdd(alpha, ma, m3b, 1., mc); 01052 m3b.Nullify(); 01053 break; 01054 default: 01055 throw WrongArgument("Matrix<FloatDouble, DenseSparseCollection>" 01056 "::MltAdd_heterogeneous2(alpha, A, B, beta, C)", 01057 "Underlying matrix B (" + to_str(k) + " ," 01058 + to_str(j) + " ) not defined."); 01059 } 01060 } 01061 01062 01063 01065 01069 template <class T0, class Allocator1, class Allocator2, class T3, 01070 class Allocator4> 01071 void MltAdd(const T0 alpha, 01072 const Matrix<FloatDouble, General, DenseSparseCollection, 01073 Allocator1>& A, 01074 const Matrix<FloatDouble, General, DenseSparseCollection, 01075 Allocator2>& B, 01076 const T3 beta, 01077 Matrix<FloatDouble, General, DenseSparseCollection, 01078 Allocator4>& C) 01079 { 01080 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator4> 01081 ::float_dense_m m0c; 01082 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator4> 01083 ::float_sparse_m m1c; 01084 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator4> 01085 ::double_dense_m m2c; 01086 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator4> 01087 ::double_sparse_m m3c; 01088 01089 Mlt(beta, C); 01090 01091 int mc = C.GetMmatrix(); 01092 int nc = C.GetNmatrix(); 01093 for (int i = 0; i < mc; i++ ) 01094 for (int j = 0; j < nc; j++) 01095 { 01096 switch (C.GetType(i, j)) 01097 { 01098 case 0: 01099 C.GetMatrix(i, j, m0c); 01100 MltAdd_heterogeneous(float(alpha), A, B, C, m0c, i, j); 01101 C.SetMatrix(i, j, m0c); 01102 m0c.Nullify(); 01103 break; 01104 case 1: 01105 C.GetMatrix(i, j, m1c); 01106 MltAdd_heterogeneous(float(alpha), A, B, C, m1c, i, j); 01107 C.SetMatrix(i, j, m1c); 01108 m1c.Nullify(); 01109 break; 01110 case 2: 01111 C.GetMatrix(i, j, m2c); 01112 MltAdd_heterogeneous(double(alpha), A, B, C, m2c, i, j); 01113 C.SetMatrix(i, j, m2c); 01114 m2c.Nullify(); 01115 break; 01116 case 3: 01117 C.GetMatrix(i, j, m3c); 01118 MltAdd_heterogeneous(double(alpha), A, B, C, m3c, i, j); 01119 C.SetMatrix(i, j, m3c); 01120 m3c.Nullify(); 01121 break; 01122 default: 01123 throw WrongArgument("Matrix<FloatDouble, DenseSparseCollection>" 01124 "::MltAdd(alpha, A, B, beta, C) ", 01125 "Underlying matrix C (" + to_str(i) + " ," 01126 + to_str(j) + " ) not defined."); 01127 } 01128 } 01129 } 01130 01131 01133 01143 template <class T0, 01144 class T1, class Prop1, class Allocator1, 01145 class T2, class Prop2, class Allocator2, 01146 class T3, 01147 class T4, class Prop4, class Allocator4> 01148 void MltAdd(const T0 alpha, 01149 const Matrix<T1, Prop1, RowSparse, Allocator1>& A, 01150 const Matrix<T2, Prop2, RowSparse, Allocator2>& B, 01151 const T3 beta, 01152 Matrix<T4, Prop4, RowSparse, Allocator4>& C) 01153 { 01154 if (beta == T3(0)) 01155 { 01156 if (alpha == T0(0)) 01157 Mlt(alpha, C); 01158 else 01159 { 01160 Mlt(A, B, C); 01161 if (alpha != T0(1)) 01162 Mlt(alpha, C); 01163 } 01164 } 01165 else 01166 { 01167 if (alpha == T0(0)) 01168 Mlt(beta, C); 01169 else 01170 { 01171 Matrix<T4, Prop4, RowSparse, Allocator4> tmp; 01172 Mlt(A, B, tmp); 01173 if (beta != T0(1)) 01174 Mlt(beta, C); 01175 Add(alpha, tmp, C); 01176 } 01177 } 01178 } 01179 01180 01182 01194 template <class T0, 01195 class T1, class Prop1, class Allocator1, 01196 class T2, class Prop2, class Allocator2, 01197 class T3, 01198 class T4, class Prop4, class Allocator4> 01199 void MltNoTransTransAdd(const T0 alpha, 01200 const Matrix<T1, Prop1, RowSparse, Allocator1>& A, 01201 const Matrix<T2, Prop2, RowSparse, Allocator2>& B, 01202 const T3 beta, 01203 Matrix<T4, Prop4, RowSparse, Allocator4>& C) 01204 { 01205 if (beta == T3(0)) 01206 { 01207 if (alpha == T0(0)) 01208 Mlt(alpha, C); 01209 else 01210 { 01211 MltNoTransTrans(A, B, C); 01212 if (alpha != T0(1)) 01213 Mlt(alpha, C); 01214 } 01215 } 01216 else 01217 { 01218 if (alpha == T0(0)) 01219 Mlt(beta, C); 01220 else 01221 { 01222 Matrix<T4, Prop4, RowSparse, Allocator4> tmp; 01223 MltNoTransTrans(A, B, tmp); 01224 if (beta != T0(1)) 01225 Mlt(beta, C); 01226 Add(alpha, tmp, C); 01227 } 01228 } 01229 } 01230 01231 01233 01249 template <class T0, 01250 class T1, class Prop1, class Allocator1, 01251 class T2, class Prop2, class Allocator2, 01252 class T3, 01253 class T4, class Prop4, class Allocator4> 01254 void MltAdd(const T0 alpha, 01255 const SeldonTranspose& TransA, 01256 const Matrix<T1, Prop1, RowSparse, Allocator1>& A, 01257 const SeldonTranspose& TransB, 01258 const Matrix<T2, Prop2, RowSparse, Allocator2>& B, 01259 const T3 beta, 01260 Matrix<T4, Prop4, RowSparse, Allocator4>& C) 01261 { 01262 if (!TransA.NoTrans()) 01263 throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, " 01264 "const Matrix<RowSparse>& A, SeldonTranspose " 01265 "TransB, const Matrix<RowSparse>& B, T3 beta, " 01266 "Matrix<RowSparse>& C)", 01267 "'TransA' must be equal to 'SeldonNoTrans'."); 01268 if (!TransB.NoTrans() && !TransB.Trans()) 01269 throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, " 01270 "const Matrix<RowSparse>& A, SeldonTranspose " 01271 "TransB, const Matrix<RowSparse>& B, T3 beta, " 01272 "Matrix<RowSparse>& C)", 01273 "'TransB' must be equal to 'SeldonNoTrans' or " 01274 "'SeldonTrans'."); 01275 01276 if (TransB.Trans()) 01277 MltNoTransTransAdd(alpha, A, B, beta, C); 01278 else 01279 MltAdd(alpha, A, B, beta, C); 01280 } 01281 01282 01292 template <class T0, 01293 class T1, class Prop1, class Allocator1, 01294 class T2, class Prop2, class Allocator2, 01295 class T3, 01296 class T4, class Prop4, class Allocator4> 01297 void MltAdd(const T0 alpha, 01298 const SeldonTranspose& TransA, 01299 const Matrix<T1, Prop1, RowMajor, Allocator1>& A, 01300 const SeldonTranspose& TransB, 01301 const Matrix<T2, Prop2, RowSparse, Allocator2>& B, 01302 const T3 beta, 01303 Matrix<T4, Prop4, RowMajor, Allocator4>& C) 01304 { 01305 if (!TransA.NoTrans()) 01306 throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, " 01307 "const Matrix<RowMajor>& A, SeldonTranspose " 01308 "TransB, const Matrix<RowSparse>& B, T3 beta, " 01309 "Matrix<RowSparse>& C)", 01310 "'TransA' must be equal to 'SeldonNoTrans'."); 01311 if (!TransB.NoTrans() && !TransB.Trans()) 01312 throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, " 01313 "const Matrix<RowMajor>& A, SeldonTranspose " 01314 "TransB, const Matrix<RowSparse>& B, T3 beta, " 01315 "Matrix<RowMajor>& C)", 01316 "'TransB' must be equal to 'SeldonNoTrans' or " 01317 "'SeldonTrans'."); 01318 01319 #ifdef SELDON_CHECK_DIMENSIONS 01320 CheckDim(SeldonNoTrans, A, SeldonTrans, B, C, 01321 "MltAdd(T0 alpha, const Matrix<RowMajor>& A, const " 01322 "Matrix<RowSparse>& B, T3 beta, Matrix<RowMajor>& C)"); 01323 #endif 01324 01325 if (TransB.Trans()) 01326 { 01327 int m = A.GetM(); 01328 if (beta == 0) 01329 C.Fill(T2(0)); 01330 else 01331 Mlt(beta, C); 01332 if (alpha != 0) 01333 for (int i = 0; i < m; i++) 01334 for (int j = 0; j < B.GetM(); j++) 01335 { 01336 // Loop on all elements in the i-th row in B. These elements 01337 // are multiplied with the element (i, k) of A. 01338 for (int l = B.GetPtr()[j]; l < B.GetPtr()[j + 1]; l++) 01339 C(i, j) += alpha * A(i, B.GetInd()[l]) * B.GetData()[l]; 01340 } 01341 } 01342 else 01343 MltAdd(alpha, A, B, beta, C); 01344 } 01345 01346 01347 // MLTADD // 01349 01350 01351 01353 // ADD // 01354 01355 01357 01364 template<class T0, class T1, class Prop1, class Storage1, class Allocator1, 01365 class T2, class Prop2, class Storage2, class Allocator2> 01366 void Add(const T0& alpha, 01367 const Matrix<T1, Prop1, Storage1, Allocator1>& A, 01368 Matrix<T2, Prop2, Storage2, Allocator2>& B) 01369 { 01370 int i, j; 01371 for (i = 0; i < A.GetM(); i++) 01372 for (j = 0; j < A.GetN(); j++) 01373 B(i, j) += alpha * A(i, j); 01374 } 01375 01376 01378 01385 template<class T0, 01386 class T1, class Prop1, class Allocator1, 01387 class T2, class Prop2, class Allocator2> 01388 void Add(const T0& alpha, 01389 const Matrix<T1, Prop1, RowMajorCollection, Allocator1>& A, 01390 Matrix<T2, Prop2, RowMajorCollection, Allocator2>& B) 01391 { 01392 int na = A.GetNmatrix(); 01393 int ma = A.GetMmatrix(); 01394 01395 typedef typename T2::value_type value_type; 01396 01397 for (int i = 0; i < ma; i++ ) 01398 for (int j = 0; j < na; j++) 01399 Add(value_type(alpha), A.GetMatrix(i, j), B.GetMatrix(i, j)); 01400 } 01401 01402 01404 01411 template<class T0, 01412 class T1, class Prop1, class Allocator1, 01413 class T2, class Prop2, class Allocator2> 01414 void Add(const T0& alpha, 01415 const Matrix<T1, Prop1, ColMajorCollection, Allocator1>& A, 01416 Matrix<T2, Prop2, ColMajorCollection, Allocator2>& B) 01417 { 01418 int na = A.GetNmatrix(); 01419 int ma = A.GetMmatrix(); 01420 01421 typedef typename T2::value_type value_type; 01422 01423 for (int i = 0; i < ma; i++ ) 01424 for (int j = 0; j < na; j++) 01425 Add(value_type(alpha), A.GetMatrix(i, j), B.GetMatrix(i, j)); 01426 } 01427 01428 01429 template <class T0, 01430 class T1, class Prop1, class Storage1, class Allocator1, 01431 class Allocator2> 01432 void Add_heterogeneous(const T0 alpha, 01433 const Matrix<T1, Prop1, Storage1, Allocator1 >& ma, 01434 Matrix<FloatDouble, General, 01435 DenseSparseCollection, Allocator2>& B, 01436 int i, int j) 01437 { 01438 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01439 ::float_dense_m m0b; 01440 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01441 ::float_sparse_m m1b; 01442 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01443 ::double_dense_m m2b; 01444 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01445 ::double_sparse_m m3b; 01446 01447 T0 alpha_ = alpha; 01448 01449 switch (B.GetType(i, j)) 01450 { 01451 case 0: 01452 B.GetMatrix(i, j, m0b); 01453 Add(float(alpha_), ma, m0b); 01454 B.SetMatrix(i, j, m0b); 01455 m0b.Nullify(); 01456 break; 01457 case 1: 01458 B.GetMatrix(i, j, m1b); 01459 Add(float(alpha_), ma, m1b); 01460 B.SetMatrix(i, j, m1b); 01461 m1b.Nullify(); 01462 break; 01463 case 2: 01464 B.GetMatrix(i, j, m2b); 01465 Add(double(alpha_), ma, m2b); 01466 B.SetMatrix(i, j, m2b); 01467 m2b.Nullify(); 01468 break; 01469 case 3: 01470 B.GetMatrix(i, j, m3b); 01471 Add(double(alpha_), ma, m3b); 01472 B.SetMatrix(i, j, m3b); 01473 m3b.Nullify(); 01474 break; 01475 default: 01476 throw WrongArgument("Add_heterogeneous(alpha, Matrix<FloatDouble, " 01477 "DenseSparseCollection>, Matrix<FloatDouble," 01478 "DenseSparseCollection> )", 01479 "Underlying matrix (" + to_str(i) + " ," 01480 + to_str(j) + " ) not defined."); 01481 } 01482 } 01483 01484 01486 01490 template <class T0, class Allocator1, class Allocator2> 01491 void Add(const T0 alpha, 01492 const Matrix<FloatDouble, General, 01493 DenseSparseCollection, Allocator1>& A, 01494 Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>& B) 01495 { 01496 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01497 ::float_dense_m m0a; 01498 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01499 ::float_sparse_m m1a; 01500 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01501 ::double_dense_m m2a; 01502 typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2> 01503 ::double_sparse_m m3a; 01504 01505 T0 alpha_ = alpha; 01506 01507 for (int i = 0; i < B.GetMmatrix(); i++) 01508 for (int j = 0; j < B.GetNmatrix(); j++) 01509 { 01510 switch (B.GetType(i, j)) 01511 { 01512 case 0: 01513 A.GetMatrix(i, j, m0a); 01514 Add_heterogeneous(float(alpha_), m0a, B, i, j); 01515 m0a.Nullify(); 01516 break; 01517 case 1: 01518 A.GetMatrix(i, j, m1a); 01519 Add_heterogeneous(float(alpha_), m1a, B, i, j); 01520 m1a.Nullify(); 01521 break; 01522 case 2: 01523 A.GetMatrix(i, j, m2a); 01524 Add_heterogeneous(double(alpha_), m2a, B, i, j); 01525 m2a.Nullify(); 01526 break; 01527 case 3: 01528 A.GetMatrix(i, j, m3a); 01529 Add_heterogeneous(double(alpha_), m3a, B, i, j); 01530 m3a.Nullify(); 01531 break; 01532 default: 01533 throw 01534 WrongArgument("Add(alpha, Matrix<FloatDouble, " 01535 "DenseSparseCollection>, Matrix<FloatDouble," 01536 "DenseSparseCollection> )", 01537 "Underlying matrix (" + to_str(i) + " ," 01538 + to_str(j) + " ) not defined."); 01539 } 01540 } 01541 } 01542 01543 01544 template<class T0, class T1, class Prop1, class Allocator1, 01545 class T2, class Prop2, class Allocator2> 01546 void Add(const T0& alpha, 01547 const Matrix<T1, Prop1, RowMajor, Allocator1>& A, 01548 Matrix<T2, Prop2, RowSparse, Allocator2>& B) 01549 { 01550 throw Undefined("void Add(const T0& alpha," 01551 "const Matrix<T1, Prop1, RowMajor, Allocator1>& A," 01552 "Matrix<T2, Prop2, RowSparse, Allocator2>& B)"); 01553 } 01554 01555 01556 template<class T0, class T1, class Prop1, class Allocator1, 01557 class T2, class Prop2, class Allocator2> 01558 void Add(const T0& alpha, 01559 const Matrix<T1, Prop1, ColMajor, Allocator1>& A, 01560 Matrix<T2, Prop2, RowSparse, Allocator2>& B) 01561 { 01562 throw Undefined("void Add(const T0& alpha," 01563 "const Matrix<T1, Prop1, RowMajor, Allocator1>& A," 01564 "Matrix<T2, Prop2, RowSparse, Allocator2>& B)"); 01565 } 01566 01567 01568 template<class T0, class T1, class Storage1, class Allocator1, 01569 class T2, class Storage2, class Allocator2> 01570 void Add(const T0& alpha, 01571 const Matrix<T1, Symmetric, Storage1, Allocator1>& A, 01572 Matrix<T2, Symmetric, Storage2, Allocator2>& B) 01573 { 01574 int i, j; 01575 for (i = 0; i < A.GetM(); i++) 01576 for (j = i; j < A.GetN(); j++) 01577 B(i, j) += alpha * A(i, j); 01578 } 01579 01580 01582 01589 template<class T0, class T1, class Prop1, class Allocator1, 01590 class T2, class Prop2, class Allocator2> 01591 void Add(const T0& alpha, 01592 const Matrix<T1, Prop1, RowSparse, Allocator1>& A, 01593 Matrix<T2, Prop2, RowSparse, Allocator2>& B) 01594 { 01595 #ifdef SELDON_CHECK_BOUNDS 01596 if (A.GetM() != B.GetM() || A.GetN() != B.GetN()) 01597 throw WrongDim("Add(alpha, const Matrix<RowSparse>& A, " 01598 "Matrix<RowSparse>& B)", 01599 "Unable to add a " + to_str(A.GetM()) + " x " 01600 + to_str(A.GetN()) + " matrix with a " 01601 + to_str(B.GetM()) + " x " + to_str(B.GetN()) 01602 + " matrix."); 01603 #endif 01604 01605 int i = 0; 01606 int j = 0; 01607 int k; 01608 01609 if (A.GetNonZeros() == B.GetNonZeros()) 01610 // A and B might have the same structure. 01611 { 01612 // Loop over all non-zeros. If the structures of A and B differ at any 01613 // time, the loop is broken and a different strategy is undertaken. 01614 for (i = 0; i < A.GetM(); i++) 01615 if (A.GetPtr()[i + 1] == B.GetPtr()[i + 1]) 01616 { 01617 for (j = A.GetPtr()[i]; j < A.GetPtr()[i + 1]; j++) 01618 if (A.GetInd()[j] == B.GetInd()[j]) 01619 B.GetData()[j] += alpha * A.GetData()[j]; 01620 else 01621 break; 01622 if (j != A.GetPtr()[i + 1]) 01623 break; 01624 } 01625 else 01626 break; 01627 // Success: A and B have the same structure. 01628 if (i == A.GetM()) 01629 return; 01630 } 01631 01632 // The addition is performed row by row in the following lines. Thus the 01633 // additions already performed in the current line, if started, should be 01634 // canceled. 01635 for (k = A.GetPtr()[i]; k < j; k++) 01636 if (A.GetInd()[k] == B.GetInd()[k]) 01637 B.GetData()[k] -= alpha * A.GetData()[k]; 01638 01639 // Number of non zero entries currently found. 01640 int Nnonzero = A.GetPtr()[i]; 01641 01642 // A and B do not have the same structure. An intermediate matrix will be 01643 // needed. The first i rows have already been added. These computations 01644 // should be preserved. 01645 int* c_ptr = NULL; 01646 int* c_ind = NULL; 01647 T2* c_data = NULL; 01648 01649 #ifdef SELDON_CHECK_MEMORY 01650 try 01651 { 01652 #endif 01653 01654 c_ptr = reinterpret_cast<int*>(calloc(A.GetM() + 1, sizeof(int))); 01655 01656 #ifdef SELDON_CHECK_MEMORY 01657 } 01658 catch (...) 01659 { 01660 c_ptr = NULL; 01661 } 01662 01663 if (c_ptr == NULL) 01664 throw NoMemory("Add(alpha, const Matrix<RowSparse>& A, " 01665 "Matrix<RowSparse>& B)", 01666 "Unable to allocate memory for an array of " 01667 + to_str(A.GetM() + 1) + " integers."); 01668 #endif 01669 01670 #ifdef SELDON_CHECK_MEMORY 01671 try 01672 { 01673 #endif 01674 01675 // Reallocates 'c_ind' and 'c_data' for the first i rows. 01676 c_ind = reinterpret_cast<int*> 01677 (realloc(reinterpret_cast<void*>(c_ind), Nnonzero * sizeof(int))); 01678 c_data = reinterpret_cast<T2*> 01679 (B.GetAllocator().reallocate(c_data, Nnonzero)); 01680 01681 #ifdef SELDON_CHECK_MEMORY 01682 } 01683 catch (...) 01684 { 01685 c_ind = NULL; 01686 c_data = NULL; 01687 } 01688 01689 if ((c_ind == NULL || c_data == NULL) 01690 && Nnonzero != 0) 01691 throw NoMemory("Add(alpha, const Matrix<RowSparse>& A, " 01692 "Matrix<RowSparse>& B)", 01693 "Unable to allocate memory for an array of " 01694 + to_str(Nnonzero) + " integers and for an array of " 01695 + to_str(sizeof(T2) * Nnonzero) + " bytes."); 01696 #endif 01697 01698 // The pointers of the first i rows are correct. 01699 for (k = 0; k < i + 1; k++) 01700 c_ptr[k] = B.GetPtr()[k]; 01701 01702 // Copies the elements from the first i rows, as they were already added. 01703 for (k = 0; k < Nnonzero; k++) 01704 { 01705 c_ind[k] = B.GetInd()[k]; 01706 c_data[k] = B.GetData()[k]; 01707 } 01708 01709 int Nnonzero_row_max; 01710 int Nnonzero_max; 01711 int ja, jb(0), ka, kb; 01712 // Now deals with the remaining lines. 01713 for (; i < A.GetM(); i++) 01714 { 01715 Nnonzero_row_max = A.GetPtr()[i + 1] - A.GetPtr()[i] 01716 + B.GetPtr()[i + 1] - B.GetPtr()[i]; 01717 // Maximum number of non zero entries up to row i. 01718 Nnonzero_max = Nnonzero + Nnonzero_row_max; 01719 01720 #ifdef SELDON_CHECK_MEMORY 01721 try 01722 { 01723 #endif 01724 01725 c_ind = reinterpret_cast<int*> 01726 (realloc(reinterpret_cast<void*>(c_ind), 01727 Nnonzero_max * sizeof(int))); 01728 c_data = reinterpret_cast<T2*> 01729 (B.GetAllocator().reallocate(c_data, Nnonzero_max)); 01730 01731 #ifdef SELDON_CHECK_MEMORY 01732 } 01733 catch (...) 01734 { 01735 c_ind = NULL; 01736 c_data = NULL; 01737 } 01738 01739 if ((c_ind == NULL || c_data == NULL) 01740 && Nnonzero_max != 0) 01741 throw NoMemory("Add(alpha, const Matrix<RowSparse>& A, " 01742 "Matrix<RowSparse>& B)", 01743 "Unable to allocate memory for an array of " 01744 + to_str(Nnonzero_max) + " integers and for an " 01745 "array of " 01746 + to_str(sizeof(T2) * Nnonzero_max) + " bytes."); 01747 #endif 01748 01749 kb = B.GetPtr()[i]; 01750 if (kb < B.GetPtr()[i + 1]) 01751 jb = B.GetInd()[kb]; 01752 for (ka = A.GetPtr()[i]; ka < A.GetPtr()[i + 1]; ka++) 01753 { 01754 ja = A.GetInd()[ka]; 01755 while (kb < B.GetPtr()[i + 1] && jb < ja) 01756 // For all elements in B that are before the ka-th element of A. 01757 { 01758 c_ind[Nnonzero] = jb; 01759 c_data[Nnonzero] = B.GetData()[kb]; 01760 kb++; 01761 if (kb < B.GetPtr()[i + 1]) 01762 jb = B.GetInd()[kb]; 01763 Nnonzero++; 01764 } 01765 01766 if (kb < B.GetPtr()[i + 1] && ja == jb) 01767 // The element in A is also in B. 01768 { 01769 c_ind[Nnonzero] = jb; 01770 c_data[Nnonzero] = B.GetData()[kb] + alpha * A.GetData()[ka]; 01771 kb++; 01772 if (kb < B.GetPtr()[i + 1]) 01773 jb = B.GetInd()[kb]; 01774 } 01775 else 01776 { 01777 c_ind[Nnonzero] = ja; 01778 c_data[Nnonzero] = alpha * A.GetData()[ka]; 01779 } 01780 Nnonzero++; 01781 } 01782 01783 // The remaining elements from B. 01784 while (kb < B.GetPtr()[i + 1]) 01785 { 01786 c_ind[Nnonzero] = jb; 01787 c_data[Nnonzero] = B.GetData()[kb]; 01788 kb++; 01789 if (kb < B.GetPtr()[i + 1]) 01790 jb = B.GetInd()[kb]; 01791 Nnonzero++; 01792 } 01793 01794 c_ptr[i + 1] = Nnonzero; 01795 } 01796 01797 B.SetData(B.GetM(), B.GetN(), Nnonzero, c_data, c_ptr, c_ind); 01798 } 01799 01800 01801 // ADD // 01803 01804 01806 // GETLU // 01807 01808 01810 01820 template <class T0, class Prop0, class Storage0, class Allocator0> 01821 void GetLU(Matrix<T0, Prop0, Storage0, Allocator0>& A) 01822 { 01823 int i, p, q, k; 01824 T0 temp; 01825 01826 int ma = A.GetM(); 01827 01828 #ifdef SELDON_CHECK_BOUNDS 01829 int na = A.GetN(); 01830 if (na != ma) 01831 throw WrongDim("GetLU(A)", "The matrix must be squared."); 01832 #endif 01833 01834 for (i = 0; i < ma; i++) 01835 { 01836 for (p = i; p < ma; p++) 01837 { 01838 temp = 0; 01839 for (k = 0; k < i; k++) 01840 temp += A(p, k) * A(k, i); 01841 A(p, i) -= temp; 01842 } 01843 for (q = i+1; q < ma; q++) 01844 { 01845 temp = 0; 01846 for (k = 0; k < i; k++) 01847 temp += A(i, k) * A(k, q); 01848 A(i, q) = (A(i,q ) - temp) / A(i, i); 01849 } 01850 } 01851 } 01852 01853 01854 // GETLU // 01856 01857 01859 // CHECKDIM // 01860 01861 01863 01872 template <class T0, class Prop0, class Storage0, class Allocator0, 01873 class T1, class Prop1, class Storage1, class Allocator1, 01874 class T2, class Prop2, class Storage2, class Allocator2> 01875 void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& A, 01876 const Matrix<T1, Prop1, Storage1, Allocator1>& B, 01877 const Matrix<T2, Prop2, Storage2, Allocator2>& C, 01878 string function) 01879 { 01880 if (B.GetM() != A.GetN() || C.GetM() != A.GetM() || B.GetN() != C.GetN()) 01881 throw WrongDim(function, string("Operation A B + C -> C not permitted:") 01882 + string("\n A (") + to_str(&A) + string(") is a ") 01883 + to_str(A.GetM()) + string(" x ") + to_str(A.GetN()) 01884 + string(" matrix;\n B (") + to_str(&B) 01885 + string(") is a ") + to_str(B.GetM()) + string(" x ") 01886 + to_str(B.GetN()) + string(" matrix;\n C (") 01887 + to_str(&C) + string(") is a ") + to_str(C.GetM()) 01888 + string(" x ") + to_str(C.GetN()) + string(" matrix.")); 01889 } 01890 01891 01893 01903 template <class T0, class Prop0, class Storage0, class Allocator0, 01904 class T1, class Prop1, class Storage1, class Allocator1, 01905 class T2, class Prop2, class Storage2, class Allocator2> 01906 void CheckDim(const SeldonSide& side, 01907 const Matrix<T0, Prop0, Storage0, Allocator0>& A, 01908 const Matrix<T1, Prop1, Storage1, Allocator1>& B, 01909 const Matrix<T2, Prop2, Storage2, Allocator2>& C, 01910 string function) 01911 { 01912 if ( SeldonSide(side).Left() && 01913 (B.GetM() != A.GetN() || C.GetM() != A.GetM() 01914 || B.GetN() != C.GetN()) ) 01915 throw WrongDim(function, string("Operation A B + C -> C not permitted:") 01916 + string("\n A (") + to_str(&A) + string(") is a ") 01917 + to_str(A.GetM()) + string(" x ") + to_str(A.GetN()) 01918 + string(" matrix;\n B (") + to_str(&B) 01919 + string(") is a ") + to_str(B.GetM()) + string(" x ") 01920 + to_str(B.GetN()) + string(" matrix;\n C (") 01921 + to_str(&C) + string(") is a ") + to_str(C.GetM()) 01922 + string(" x ") + to_str(C.GetN()) + string(" matrix.")); 01923 else if ( SeldonSide(side).Right() && 01924 (B.GetN() != A.GetM() || C.GetM() != B.GetM() 01925 || A.GetN() != C.GetN()) ) 01926 throw WrongDim(function, string("Operation B A + C -> C not permitted:") 01927 + string("\n A (") + to_str(&A) + string(") is a ") 01928 + to_str(A.GetM()) + string(" x ") + to_str(A.GetN()) 01929 + string(" matrix;\n B (") + to_str(&B) 01930 + string(") is a ") + to_str(B.GetM()) + string(" x ") 01931 + to_str(B.GetN()) + string(" matrix;\n C (") 01932 + to_str(&C) + string(") is a ") + to_str(C.GetM()) 01933 + string(" x ") + to_str(C.GetN()) + string(" matrix.")); 01934 } 01935 01936 01938 01948 template <class T0, class Prop0, class Storage0, class Allocator0, 01949 class T1, class Prop1, class Storage1, class Allocator1> 01950 void CheckDim(const SeldonTranspose& TransA, 01951 const Matrix<T0, Prop0, Storage0, Allocator0>& A, 01952 const SeldonTranspose& TransB, 01953 const Matrix<T1, Prop1, Storage1, Allocator1>& B, 01954 string function) 01955 { 01956 SeldonTranspose status_A(TransA); 01957 SeldonTranspose status_B(TransB); 01958 string op; 01959 if (status_A.Trans()) 01960 op = string("A'"); 01961 else if (status_A.ConjTrans()) 01962 op = string("A*"); 01963 else 01964 op = string("A"); 01965 if (status_B.Trans()) 01966 op += string(" B'"); 01967 else if (status_B.ConjTrans()) 01968 op += string(" B*"); 01969 else 01970 op += string(" B"); 01971 op = string("Operation ") + op + string(" not permitted:"); 01972 if (B.GetM(status_B) != A.GetN(status_A)) 01973 throw WrongDim(function, op 01974 + string("\n A (") + to_str(&A) + string(") is a ") 01975 + to_str(A.GetM()) + string(" x ") + to_str(A.GetN()) 01976 + string(" matrix;\n B (") + to_str(&B) 01977 + string(") is a ") + to_str(B.GetM()) + string(" x ") 01978 + to_str(B.GetN()) + string(" matrix.")); 01979 } 01980 01981 01983 01994 template <class T0, class Prop0, class Storage0, class Allocator0, 01995 class T1, class Prop1, class Storage1, class Allocator1, 01996 class T2, class Prop2, class Storage2, class Allocator2> 01997 void CheckDim(const SeldonTranspose& TransA, 01998 const Matrix<T0, Prop0, Storage0, Allocator0>& A, 01999 const SeldonTranspose& TransB, 02000 const Matrix<T1, Prop1, Storage1, Allocator1>& B, 02001 const Matrix<T2, Prop2, Storage2, Allocator2>& C, 02002 string function) 02003 { 02004 string op; 02005 if (TransA.Trans()) 02006 op = string("A'"); 02007 else if (TransA.ConjTrans()) 02008 op = string("A*"); 02009 else 02010 op = string("A"); 02011 if (TransB.Trans()) 02012 op += string(" B' + C"); 02013 else if (TransB.ConjTrans()) 02014 op += string(" B* + C"); 02015 else 02016 op += string(" B + C"); 02017 op = string("Operation ") + op + string(" not permitted:"); 02018 if (B.GetM(TransB) != A.GetN(TransA) || C.GetM() != A.GetM(TransA) 02019 || B.GetN(TransB) != C.GetN()) 02020 throw WrongDim(function, op 02021 + string("\n A (") + to_str(&A) + string(") is a ") 02022 + to_str(A.GetM()) + string(" x ") + to_str(A.GetN()) 02023 + string(" matrix;\n B (") + to_str(&B) 02024 + string(") is a ") + to_str(B.GetM()) + string(" x ") 02025 + to_str(B.GetN()) + string(" matrix;\n C (") 02026 + to_str(&C) + string(") is a ") + to_str(C.GetM()) 02027 + string(" x ") + to_str(C.GetN()) + string(" matrix.")); 02028 } 02029 02030 02032 02040 template <class T0, class Prop0, class Storage0, class Allocator0, 02041 class T1, class Prop1, class Storage1, class Allocator1> 02042 void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& A, 02043 const Matrix<T1, Prop1, Storage1, Allocator1>& B, 02044 string function) 02045 { 02046 CheckDim(SeldonLeft, A, B, function); 02047 } 02048 02049 02051 02060 template <class T0, class Prop0, class Storage0, class Allocator0, 02061 class T1, class Prop1, class Storage1, class Allocator1> 02062 void CheckDim(const SeldonSide& side, 02063 const Matrix<T0, Prop0, Storage0, Allocator0>& A, 02064 const Matrix<T1, Prop1, Storage1, Allocator1>& B, 02065 string function) 02066 { 02067 if (side.Left() && B.GetM() != A.GetN()) 02068 throw WrongDim(function, string("Operation A B not permitted:") 02069 + string("\n A (") + to_str(&A) + string(") is a ") 02070 + to_str(A.GetM()) + string(" x ") + to_str(A.GetN()) 02071 + string(" matrix;\n B (") + to_str(&B) 02072 + string(") is a ") + to_str(B.GetM()) + string(" x ") 02073 + to_str(B.GetN()) + string(" matrix.")); 02074 else if (side.Right() && B.GetN() != A.GetM()) 02075 throw WrongDim(function, string("Operation B A not permitted:") 02076 + string("\n A (") + to_str(&A) + string(") is a ") 02077 + to_str(A.GetM()) + string(" x ") + to_str(A.GetN()) 02078 + string(" matrix;\n B (") + to_str(&B) 02079 + string(") is a ") + to_str(B.GetM()) + string(" x ") 02080 + to_str(B.GetN()) + string(" matrix.")); 02081 } 02082 02083 02084 // CHECKDIM // 02086 02087 02089 // NORMS // 02090 02091 02093 02097 template <class T, class Prop, class Storage, class Allocator> 02098 T MaxAbs(const Matrix<T, Prop, Storage, Allocator>& A) 02099 { 02100 T res(0); 02101 for (int i = 0; i < A.GetM(); i++) 02102 for (int j = 0; j < A.GetN(); j++) 02103 res = max(res, abs(A(i, j)) ); 02104 02105 return res; 02106 } 02107 02108 02110 02114 template <class T, class Prop, class Storage, class Allocator> 02115 T Norm1(const Matrix<T, Prop, Storage, Allocator>& A) 02116 { 02117 T res(0), sum; 02118 for (int j = 0; j < A.GetN(); j++) 02119 { 02120 sum = T(0); 02121 for (int i = 0; i < A.GetM(); i++) 02122 sum += abs( A(i, j) ); 02123 02124 res = max(res, sum); 02125 } 02126 02127 return res; 02128 } 02129 02130 02132 02136 template <class T, class Prop, class Storage, class Allocator> 02137 T NormInf(const Matrix<T, Prop, Storage, Allocator>& A) 02138 { 02139 T res(0), sum; 02140 for (int i = 0; i < A.GetM(); i++) 02141 { 02142 sum = T(0); 02143 for (int j = 0; j < A.GetN(); j++) 02144 sum += abs( A(i, j) ); 02145 02146 res = max(res, sum); 02147 } 02148 02149 return res; 02150 } 02151 02152 02154 02158 template <class T, class Prop, class Storage, class Allocator> 02159 T MaxAbs(const Matrix<complex<T>, Prop, Storage, Allocator>& A) 02160 { 02161 T res(0); 02162 for (int i = 0; i < A.GetM(); i++) 02163 for (int j = 0; j < A.GetN(); j++) 02164 { 02165 res = max(res, abs(A(i, j)) ); 02166 } 02167 02168 return res; 02169 } 02170 02171 02173 02177 template <class T, class Prop, class Storage, class Allocator> 02178 T Norm1(const Matrix<complex<T>, Prop, Storage, Allocator>& A) 02179 { 02180 T res(0), sum; 02181 for (int j = 0; j < A.GetN(); j++) 02182 { 02183 sum = T(0); 02184 for (int i = 0; i < A.GetM(); i++) 02185 sum += abs( A(i, j) ); 02186 02187 res = max(res, sum); 02188 } 02189 02190 return res; 02191 } 02192 02193 02195 02199 template <class T, class Prop, class Storage, class Allocator> 02200 T NormInf(const Matrix<complex<T>, Prop, Storage, Allocator>& A) 02201 { 02202 T res(0), sum; 02203 for (int i = 0; i < A.GetM(); i++) 02204 { 02205 sum = T(0); 02206 for (int j = 0; j < A.GetN(); j++) 02207 sum += abs( A(i, j) ); 02208 02209 res = max(res, sum); 02210 } 02211 02212 return res; 02213 } 02214 02215 02216 // NORMS // 02218 02219 02221 // TRANSPOSE // 02222 02223 02225 template<class T, class Prop, class Storage, class Allocator> 02226 void Transpose(Matrix<T, Prop, Storage, Allocator>& A) 02227 { 02228 int m = A.GetM(); 02229 int n = A.GetN(); 02230 02231 if (m == n) 02232 { 02233 T tmp; 02234 for (int i = 0; i < m; i++) 02235 for (int j = 0; j < i; j++) 02236 { 02237 tmp = A(i,j); 02238 A.Get(i,j) = A(j,i); 02239 A.Get(j,i) = tmp; 02240 } 02241 } 02242 else 02243 { 02244 Matrix<T, Prop, Storage, Allocator> B; 02245 B = A; 02246 A.Reallocate(n,m); 02247 for (int i = 0; i < m; i++) 02248 for (int j = 0; j < n; j++) 02249 A.Get(j,i) = B(i,j); 02250 } 02251 } 02252 02253 02255 template<class T, class Allocator> 02256 void Transpose(Matrix<T, General, RowSparse, Allocator>& A) 02257 { 02258 int m = A.GetM(); 02259 int n = A.GetN(); 02260 int nnz = A.GetDataSize(); 02261 Vector<int, VectFull, CallocAlloc<int> > ptr_T(n+1), ptr; 02262 Vector<int, VectFull, CallocAlloc<int> > ind_T(nnz), ind; 02263 Vector<T, VectFull, Allocator> data_T(nnz), data; 02264 02265 ptr.SetData(m+1, A.GetPtr()); 02266 ind.SetData(nnz, A.GetInd()); 02267 data.SetData(nnz, A.GetData()); 02268 02269 ptr_T.Zero(); 02270 ind_T.Zero(); 02271 data_T.Zero(); 02272 02273 // For each column j, computes number of its non-zeroes and stores it in 02274 // ptr_T[j]. 02275 for (int i = 0; i < nnz; i++) 02276 ptr_T(ind(i) + 1)++; 02277 02278 // Computes the required number of non-zeroes ptr_T(j). 02279 for (int j = 1; j < n + 1; j++) 02280 ptr_T(j) += ptr_T(j - 1); 02281 02282 Vector<int, VectFull, CallocAlloc<int> > row_ind(n+1); 02283 row_ind.Fill(0); 02284 for (int i = 0; i < m; i++) 02285 for (int jp = ptr(i); jp < ptr(i+1); jp++) 02286 { 02287 int j = ind(jp); 02288 int k = ptr_T(j) + row_ind(j); 02289 ++row_ind(j); 02290 data_T(k) = data(jp); 02291 ind_T(k) = i; 02292 } 02293 02294 A.SetData(n, m, data_T, ptr_T, ind_T); 02295 02296 data.Nullify(); 02297 ptr.Nullify(); 02298 ind.Nullify(); 02299 } 02300 02301 02303 template<class T, class Prop, class Storage, class Allocator> 02304 void TransposeConj(Matrix<T, Prop, Storage, Allocator>& A) 02305 { 02306 int i, j; 02307 02308 int m = A.GetM(); 02309 int n = A.GetN(); 02310 02311 if (m == n) 02312 { 02313 T tmp; 02314 for (i = 0; i < m; i++) 02315 { 02316 // Extra-diagonal part. 02317 for (j = 0; j < i; j++) 02318 { 02319 tmp = A(i, j); 02320 A(i, j) = conj(A(j, i)); 02321 A(j, i) = conj(tmp); 02322 } 02323 02324 // Diagonal part. 02325 A(i, i) = conj(A(i, i)); 02326 } 02327 } 02328 else 02329 { 02330 Matrix<T, Prop, Storage, Allocator> B; 02331 B = A; 02332 A.Reallocate(n, m); 02333 for (i = 0; i < m; i++) 02334 for (j = 0; j < n; j++) 02335 A(j, i) = conj(B(i, j)); 02336 } 02337 } 02338 02339 02340 // TRANSPOSE // 02342 02343 02345 // ISSYMMETRICMATRIX // 02346 02347 02349 template<class T, class Prop, class Storage, class Allocator> 02350 bool IsSymmetricMatrix(const Matrix<T, Prop, Storage, Allocator>& A) 02351 { 02352 return false; 02353 } 02354 02355 02357 template<class T, class Storage, class Allocator> 02358 bool IsSymmetricMatrix(const Matrix<T, Symmetric, Storage, Allocator>& A) 02359 { 02360 return true; 02361 } 02362 02363 02364 // ISSYMMETRICMATRIX // 02366 02367 02368 } // namespace Seldon. 02369 02370 02371 #endif