computation/basic_functions/Functions_Matrix.cxx

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