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 
00025 /*
00026   Function defined in this file:
00027 
00028   alpha A -> A
00029   Mlt(alpha, A)
00030 
00031   A B -> C
00032   Mlt(A, B, C)
00033 
00034   alpha A B -> C
00035   Mlt(alpha, A, B, C)
00036 
00037   alpha A B + beta C -> C
00038   MltAdd(alpha, A, B, beta, C)
00039 
00040   alpha A + B -> B
00041   Add(alpha, A, B)
00042 
00043   LU factorization of matrix A without pivoting.
00044   GetLU(A)
00045 
00046   Highest absolute value of A.
00047   MaxAbs(A)
00048 
00049   1-norm of matrix A.
00050   Norm1(A)
00051 
00052   infinity norm of matrix A.
00053   NormInf(A)
00054 
00055   Transpose(A)
00056 */
00057 
00058 namespace Seldon
00059 {
00060 
00061 
00063   // MLT //
00064 
00065 
00067 
00071   template <class T0,
00072             class T1, class Prop1, class Storage1, class Allocator1>
00073   void Mlt(const T0 alpha,
00074            Matrix<T1, Prop1, Storage1, Allocator1>& A)  throw()
00075   {
00076     T1 alpha_ = alpha;
00077 
00078     typename Matrix<T1, Prop1, Storage1, Allocator1>::pointer
00079       data = A.GetData();
00080 
00081     for (int i = 0; i < A.GetDataSize(); i++)
00082       data[i] = alpha_ * data[i];
00083   }
00084 
00085 
00087 
00091   template <class T0,
00092             class T1, class Prop1, class Allocator1>
00093   void Mlt(const T0 alpha,
00094            Matrix<T1, Prop1, ColMajorCollection, Allocator1>& A)
00095   {
00096     typename T1::value_type alpha_ = alpha;
00097     for (int i = 0; i < A.GetMmatrix(); i++)
00098       for (int j = 0; j < A.GetNmatrix(); j++)
00099         Mlt(alpha, A.GetMatrix(i, j));
00100   }
00101 
00102 
00104 
00108   template <class T0,
00109             class T1, class Prop1, class Allocator1>
00110   void Mlt(const T0 alpha,
00111            Matrix<T1, Prop1, RowMajorCollection, Allocator1>& A)
00112   {
00113     typename T1::value_type alpha_ = alpha;
00114     for (int i = 0; i < A.GetMmatrix(); i++)
00115       for (int j = 0; j < A.GetNmatrix(); j++)
00116         Mlt(alpha_, A.GetMatrix(i, j));
00117   }
00118 
00119 
00121 
00125   template <class T0, class Allocator>
00126   void Mlt(const T0 alpha,
00127            Matrix<FloatDouble, General, DenseSparseCollection, Allocator>& A)
00128   {
00129     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator>
00130       ::float_dense_m m0;
00131     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator>
00132       ::float_sparse_m m1;
00133     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator>
00134       ::double_dense_m m2;
00135     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator>
00136       ::double_sparse_m m3;
00137 
00138     for (int i = 0; i < A.GetMmatrix(); i++)
00139       for (int j = 0; j < A.GetNmatrix(); j++)
00140         {
00141           switch (A.GetType(i, j))
00142             {
00143             case 0:
00144               A.GetMatrix(i, j, m0);
00145               Mlt(float(alpha), m0);
00146               A.SetMatrix(i, j, m0);
00147               m0.Nullify();
00148               break;
00149             case 1:
00150               A.GetMatrix(i, j, m1);
00151               Mlt(float(alpha), m1);
00152               A.SetMatrix(i, j, m1);
00153               m1.Nullify();
00154               break;
00155             case 2:
00156               A.GetMatrix(i, j, m2);
00157               Mlt(double(alpha), m2);
00158               A.SetMatrix(i, j, m2);
00159               m2.Nullify();
00160               break;
00161             case 3:
00162               A.GetMatrix(i, j, m3);
00163               Mlt(double(alpha), m3);
00164               A.SetMatrix(i, j, m3);
00165               m3.Nullify();
00166               break;
00167             default:
00168               throw WrongArgument("Mlt(alpha, Matrix<FloatDouble, "
00169                                   "DenseSparseCollection)",
00170                                   "Underlying matrix (" + to_str(i) + " ,"
00171                                   + to_str(j) + " ) not defined.");
00172             }
00173         }
00174   }
00175 
00176 
00178 
00186   template <class T0,
00187             class T1, class Prop1, class Storage1, class Allocator1,
00188             class T2, class Prop2, class Storage2, class Allocator2,
00189             class T3, class Prop3, class Storage3, class Allocator3>
00190   void Mlt(const T0 alpha,
00191            const Matrix<T1, Prop1, Storage1, Allocator1>& A,
00192            const Matrix<T2, Prop2, Storage2, Allocator2>& B,
00193            Matrix<T3, Prop3, Storage3, Allocator3>& C)
00194   {
00195     C.Fill(T3(0));
00196     MltAdd(alpha, A, B, T3(0), C);
00197   }
00198 
00199 
00201 
00207   template <class T0, class Prop0, class Storage0, class Allocator0,
00208             class T1, class Prop1, class Storage1, class Allocator1,
00209             class T2, class Prop2, class Storage2, class Allocator2>
00210   void Mlt(const Matrix<T0, Prop0, Storage0, Allocator0>& A,
00211            const Matrix<T1, Prop1, Storage1, Allocator1>& B,
00212            Matrix<T2, Prop2, Storage2, Allocator2>& C)
00213   {
00214     C.Fill(T2(0));
00215     MltAdd(T0(1), A, B, T2(0), C);
00216   }
00217 
00218 
00220 
00228   template <class T0, class Prop0, class Allocator0,
00229             class T1, class Prop1, class Allocator1,
00230             class T2, class Prop2, class Allocator2>
00231   void Mlt(const Matrix<T0, Prop0, RowSparse, Allocator0>& A,
00232            const Matrix<T1, Prop1, RowSparse, Allocator1>& B,
00233            Matrix<T2, Prop2, RowSparse, Allocator2>& C)
00234   {
00235 #ifdef SELDON_CHECK_DIMENSIONS
00236     CheckDim(A, B, "Mlt(const Matrix<RowSparse>& A, const "
00237              "Matrix<RowSparse>& B, Matrix<RowSparse>& C)");
00238 #endif
00239 
00240     int h, i, k, l, col;
00241     int Nnonzero, Nnonzero_row, Nnonzero_row_max;
00242     IVect column_index;
00243     Vector<T2> row_value;
00244     T1 value;
00245     int m = A.GetM();
00246 
00247     int* c_ptr = NULL;
00248     int* c_ind = NULL;
00249     T2* c_data = NULL;
00250     C.Clear();
00251 
00252 #ifdef SELDON_CHECK_MEMORY
00253     try
00254       {
00255 #endif
00256 
00257         c_ptr = reinterpret_cast<int*>(calloc(m + 1, sizeof(int)));
00258 
00259 #ifdef SELDON_CHECK_MEMORY
00260       }
00261     catch (...)
00262       {
00263         c_ptr = NULL;
00264       }
00265 
00266     if (c_ptr == NULL)
00267       throw NoMemory("Mlt(const Matrix<RowSparse>& A, const "
00268                      "Matrix<RowSparse>& B, Matrix<RowSparse>& C)",
00269                      "Unable to allocate memory for an array of "
00270                      + to_str(m + 1) + " integers.");
00271 #endif
00272 
00273     c_ptr[0] = 0;
00274 
00275     // Number of non-zero elements in C.
00276     Nnonzero = 0;
00277     for (i = 0; i < m; i++)
00278       {
00279         c_ptr[i + 1] = c_ptr[i];
00280 
00281         if (A.GetPtr()[i + 1] != A.GetPtr()[i])
00282           // There are elements in the i-th row of A, so there can be non-zero
00283           // entries in C as well. Checks whether any column in B has an
00284           // element whose row index matches a column index of a non-zero in
00285           // the i-th row of A.
00286           {
00287             // Maximum number of non-zero entry on the i-th row of C.
00288             Nnonzero_row_max = 0;
00289             // For every element in the i-th row.
00290             for (k = A.GetPtr()[i]; k < A.GetPtr()[i + 1]; k++)
00291               {
00292                 col = A.GetInd()[k];
00293                 Nnonzero_row_max += B.GetPtr()[col + 1] - B.GetPtr()[col];
00294               }
00295             // Now gets the column indexes.
00296             column_index.Reallocate(Nnonzero_row_max);
00297             row_value.Reallocate(Nnonzero_row_max);
00298             h = 0;
00299             // For every element in the i-th row.
00300             for (k = A.GetPtr()[i]; k < A.GetPtr()[i + 1]; k++)
00301               {
00302                 // The k-th column index (among the nonzero entries) on the
00303                 // i-th row, and the corresponding value.
00304                 col = A.GetInd()[k];
00305                 value = A.GetData()[k];
00306                 // Loop on all elements in the col-th row in B. These elements
00307                 // are multiplied with the element (i, col) of A.
00308                 for (l = B.GetPtr()[col]; l < B.GetPtr()[col + 1]; l++)
00309                   {
00310                     column_index(h) = B.GetInd()[l];
00311                     row_value(h) = value * B.GetData()[l];
00312                     h++;
00313                   }
00314               }
00315             // Now gathers and sorts all elements on the i-th row of C.
00316             Nnonzero_row = column_index.GetLength();
00317             Assemble(Nnonzero_row, column_index, row_value);
00318 
00319 #ifdef SELDON_CHECK_MEMORY
00320             try
00321               {
00322 #endif
00323 
00324                 // Reallocates 'c_ind' and 'c_data' in order to append the
00325                 // elements of the i-th row of C.
00326                 c_ind = reinterpret_cast<int*>
00327                   (realloc(reinterpret_cast<void*>(c_ind),
00328                            (Nnonzero + Nnonzero_row) * sizeof(int)));
00329                 c_data = reinterpret_cast<T2*>
00330                   (C.GetAllocator().reallocate(c_data,
00331                                                Nnonzero + Nnonzero_row));
00332 
00333 #ifdef SELDON_CHECK_MEMORY
00334               }
00335             catch (...)
00336               {
00337                 c_ind = NULL;
00338                 c_data = NULL;
00339               }
00340 
00341             if ((c_ind == NULL || c_data == NULL)
00342                 && Nnonzero + Nnonzero_row != 0)
00343               throw NoMemory("Mlt(const Matrix<RowSparse>& A, const "
00344                              "Matrix<RowSparse>& B, Matrix<RowSparse>& C)",
00345                              "Unable to allocate memory for an array of "
00346                              + to_str(Nnonzero + Nnonzero_row) + " integers "
00347                              "and for an array of "
00348                              + to_str(sizeof(T2) * (Nnonzero + Nnonzero_row))
00349                              + " bytes.");
00350 #endif
00351 
00352             c_ptr[i + 1] += Nnonzero_row;
00353             for (h = 0; h < Nnonzero_row; h++)
00354               {
00355                 c_ind[Nnonzero + h] = column_index(h);
00356                 c_data[Nnonzero + h] = row_value(h);
00357               }
00358             Nnonzero += Nnonzero_row;
00359           }
00360       }
00361 
00362     C.SetData(A.GetM(), B.GetN(), Nnonzero, c_data, c_ptr, c_ind);
00363   }
00364 
00365 
00367 
00375   template <class T0, class Prop0, class Allocator0,
00376             class T1, class Prop1, class Allocator1,
00377             class T2, class Prop2, class Allocator2>
00378   void MltNoTransTrans(const Matrix<T0, Prop0, RowSparse, Allocator0>& A,
00379                        const Matrix<T1, Prop1, RowSparse, Allocator1>& B,
00380                        Matrix<T2, Prop2, RowSparse, Allocator2>& C)
00381   {
00382 #ifdef SELDON_CHECK_DIMENSIONS
00383     CheckDim(SeldonNoTrans, A, SeldonTrans, B,
00384              "MltNoTransTrans(const Matrix<RowSparse>& A, "
00385              "const Matrix<RowSparse>& B, Matrix<RowSparse>& C)");
00386 #endif
00387 
00388     int h, i, k, col;
00389     int ib, kb;
00390     int Nnonzero_row;
00391     int Nnonzero;
00392 
00393     // 'MallocAlloc' is specified so that reallocations may be efficient.
00394     // There will be no need for 'Resize': 'Reallocate' will do the job.
00395     Vector<int, VectFull, MallocAlloc<int> > column_index;
00396     Vector<T2, VectFull, MallocAlloc<T2> > row_value;
00397     T2 value = 0;
00398 
00399     int m = A.GetM();
00400     int n = B.GetM();
00401 
00402     int* c_ptr = NULL;
00403     int* c_ind = NULL;
00404     T2* c_data = NULL;
00405 
00406 #ifdef SELDON_CHECK_MEMORY
00407     try
00408       {
00409 #endif
00410 
00411         c_ptr = reinterpret_cast<int*>(calloc(m + 1, sizeof(int)));
00412 
00413 #ifdef SELDON_CHECK_MEMORY
00414       }
00415     catch (...)
00416       {
00417         c_ptr = NULL;
00418       }
00419 
00420     if (c_ptr == NULL)
00421       throw NoMemory("MltNoTransTrans(const Matrix<RowSparse>& A, "
00422                      "const Matrix<RowSparse>& B, Matrix<RowSparse>& C)",
00423                      "Unable to allocate memory for an array of "
00424                      + to_str(m + 1) + " integers.");
00425 #endif
00426 
00427     c_ptr[0] = 0;
00428 
00429     // Number of non-zero elements in C.
00430     Nnonzero = 0;
00431 
00432     for (i = 0; i < m; i++)
00433       {
00434         c_ptr[i + 1] = c_ptr[i];
00435 
00436         if (A.GetPtr()[i + 1] != A.GetPtr()[i])
00437           // There are elements in the i-th row of A, so there can be non-zero
00438           // entries in C as well. It is checked below whether any row in B
00439           // has an element whose row index matches a column index of a
00440           // non-zero in the i-th row of A.
00441           {
00442             // For every element in the i-th row.
00443             for (k = A.GetPtr()[i]; k < A.GetPtr()[i + 1]; k++)
00444               {
00445                 col = A.GetInd()[k];
00446                 // For every row in B.
00447                 for (ib = 0; ib < n; ib++)
00448                   {
00449                     for (kb = B.GetPtr()[ib]; kb < B.GetPtr()[ib + 1]; kb++)
00450                       if (col == B.GetInd()[kb])
00451                         value += A.GetData()[k] * B.GetData()[kb];
00452                     if (value != T2(0))
00453                       {
00454                         row_value.Append(value);
00455                         column_index.Append(ib);
00456                         value = T2(0);
00457                       }
00458                   }
00459               }
00460 
00461             Nnonzero_row = column_index.GetLength();
00462             Assemble(Nnonzero_row, column_index, row_value);
00463 
00464 #ifdef SELDON_CHECK_MEMORY
00465             try
00466               {
00467 #endif
00468 
00469                 // Reallocates 'c_ind' and 'c_data' in order to append the
00470                 // elements of the i-th row of C.
00471                 c_ind = reinterpret_cast<int*>
00472                   (realloc(reinterpret_cast<void*>(c_ind),
00473                            (Nnonzero + Nnonzero_row) * sizeof(int)));
00474                 c_data = reinterpret_cast<T2*>
00475                   (C.GetAllocator().reallocate(c_data,
00476                                                Nnonzero + Nnonzero_row));
00477 
00478 #ifdef SELDON_CHECK_MEMORY
00479               }
00480             catch (...)
00481               {
00482                 c_ind = NULL;
00483                 c_data = NULL;
00484               }
00485 
00486             if ((c_ind == NULL || c_data == NULL)
00487                 && Nnonzero_row != 0)
00488               throw NoMemory("MltNoTransTrans(const Matrix<RowSparse>& A, "
00489                              "const Matrix<RowSparse>& B, "
00490                              "Matrix<RowSparse>& C)",
00491                              "Unable to allocate memory for an array of "
00492                              + to_str(Nnonzero + Nnonzero_row) + " integers "
00493                              "and for an array of "
00494                              + to_str(sizeof(T2) * (Nnonzero + Nnonzero_row))
00495                              + " bytes.");
00496 #endif
00497 
00498             c_ptr[i + 1] += Nnonzero_row;
00499             for (h = 0; h < Nnonzero_row; h++)
00500               {
00501                 c_ind[Nnonzero + h] = column_index(h);
00502                 c_data[Nnonzero + h] = row_value(h);
00503               }
00504             Nnonzero += Nnonzero_row;
00505           }
00506 
00507         column_index.Clear();
00508         row_value.Clear();
00509       }
00510 
00511     C.SetData(A.GetM(), B.GetM(), Nnonzero, c_data, c_ptr, c_ind);
00512   }
00513 
00514 
00515   // MLT //
00517 
00518 
00519 
00521   // MLTADD //
00522 
00523 
00525 
00535   template <class T0,
00536             class T1, class Prop1, class Storage1, class Allocator1,
00537             class T2, class Prop2, class Storage2, class Allocator2,
00538             class T3,
00539             class T4, class Prop4, class Storage4, class Allocator4>
00540   void MltAdd(const T0 alpha,
00541               const Matrix<T1, Prop1, Storage1, Allocator1>& A,
00542               const Matrix<T2, Prop2, Storage2, Allocator2>& B,
00543               const T3 beta,
00544               Matrix<T4, Prop4, Storage4, Allocator4>& C)
00545   {
00546     int na = A.GetN();
00547     int mc = C.GetM();
00548     int nc = C.GetN();
00549 
00550 #ifdef SELDON_CHECK_DIMENSIONS
00551     CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)");
00552 #endif
00553 
00554     T4 temp;
00555     T4 alpha_(alpha);
00556     T4 beta_(beta);
00557 
00558     if (beta_ != T4(0))
00559       for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
00560         for (int j = 0; j < Storage4::GetSecond(mc, nc); j++)
00561           C(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
00562             *= beta_;
00563     else
00564       for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
00565         for (int j = 0; j < Storage4::GetSecond(mc, nc); j++)
00566           C(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j)) = T4(0);
00567 
00568     for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
00569       for (int j = 0; j < Storage4::GetSecond(mc, nc); j++)
00570         {
00571           temp = T4(0);
00572           for (int k = 0; k < na; k++)
00573             temp += A(Storage4::GetFirst(i, j), k)
00574               * B(k, Storage4::GetSecond(i, j));
00575           C(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
00576             += alpha_ * temp;
00577         }
00578   }
00579 
00580 
00582 
00592   template <class T0,
00593             class T1, class Prop1, class Allocator1,
00594             class T2, class Prop2, class Allocator2,
00595             class T3,
00596             class T4, class Prop4, class Allocator4>
00597   void MltAdd(const T0 alpha,
00598               const Matrix<T1, Prop1, RowMajorCollection, Allocator1>& A,
00599               const Matrix<T2, Prop2, RowMajorCollection, Allocator2>& B,
00600               const T3 beta,
00601               Matrix<T4, Prop4, RowMajorCollection, Allocator4>& C)
00602   {
00603     int na = A.GetNmatrix();
00604     int mc = C.GetMmatrix();
00605     int nc = C.GetNmatrix();
00606 
00607 #ifdef SELDON_CHECK_DIMENSIONS
00608     CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)");
00609 #endif
00610 
00611     typedef typename T4::value_type value_type;
00612 
00613     Mlt(value_type(beta), C);
00614 
00615     for (int i = 0; i < mc; i++ )
00616       for (int j = 0; j < nc; j++)
00617         for (int k = 0; k < na; k++)
00618           MltAdd(value_type(alpha), A.GetMatrix(i, k), B.GetMatrix(k, j),
00619                  value_type(1), C.GetMatrix(i, j));
00620   }
00621 
00622 
00624 
00634   template <class T0,
00635             class T1, class Prop1, class Allocator1,
00636             class T2, class Prop2, class Allocator2,
00637             class T3,
00638             class T4, class Prop4, class Allocator4>
00639   void MltAdd(const T0 alpha,
00640               const Matrix<T1, Prop1, ColMajorCollection, Allocator1>& A,
00641               const Matrix<T2, Prop2, ColMajorCollection, Allocator2>& B,
00642               const T3 beta,
00643               Matrix<T4, Prop4, ColMajorCollection, Allocator4>& C)
00644   {
00645     int na = A.GetNmatrix();
00646     int mc = C.GetMmatrix();
00647     int nc = C.GetNmatrix();
00648 
00649 #ifdef SELDON_CHECK_DIMENSIONS
00650     CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)");
00651 #endif
00652 
00653     typedef typename T4::value_type value_type;
00654 
00655     Mlt(value_type(beta), C);
00656 
00657     for (int i = 0; i < mc; i++ )
00658       for (int j = 0; j < nc; j++)
00659         for (int k = 0; k < na; k++)
00660           MltAdd(value_type(alpha), A.GetMatrix(i, k), B.GetMatrix(k, j),
00661                  value_type(1), C.GetMatrix(i, j));
00662   }
00663 
00664 
00665   template <class T0,
00666             class T1, class Allocator1,
00667             class T2, class Allocator2,
00668             class T3,
00669             class T4, class Allocator4>
00670   void MltAdd(const T0 alpha,
00671               const Matrix<T1, General, RowMajor, Allocator1>& A,
00672               const Matrix<T2, General, RowMajor, Allocator2>& B,
00673               const T3 beta,
00674               Matrix<T4, General, RowSparse, Allocator4>& C)
00675   {
00676     throw Undefined("void MltAdd(const T0 alpha,"
00677                     "const Matrix<T1, General, RowMajor, Allocator1>& A,"
00678                     "const Matrix<T2, General, RowMajor, Allocator2>& B,"
00679                     "const T3 beta,"
00680                     "Matrix<T4, General, RowSparse, Allocator4>& C)");
00681   }
00682 
00683 
00684   template <class T0,
00685             class T1, class Allocator1,
00686             class T2, class Allocator2,
00687             class T3,
00688             class T4, class Allocator4>
00689   void MltAdd(const T0 alpha,
00690               const Matrix<T1, General, RowMajor, Allocator1>& A,
00691               const Matrix<T2, General, RowSparse, Allocator2>& B,
00692               const T3 beta,
00693               Matrix<T4, General, RowSparse, Allocator4>& C)
00694   {
00695     throw Undefined("void MltAdd(const T0 alpha,"
00696                     "const Matrix<T1, General, RowMajor, Allocator1>& A,"
00697                     "const Matrix<T2, General, RowSparse, Allocator2>& B,"
00698                     "const T3 beta,"
00699                     "Matrix<T4, General, RowSparse, Allocator4>& C)");
00700   }
00701 
00702 
00703   template <class T0,
00704             class T1, class Allocator1,
00705             class T2, class Allocator2,
00706             class T3,
00707             class T4, class Allocator4>
00708   void MltAdd(const T0 alpha,
00709               const Matrix<T1, General, RowSparse, Allocator1>& A,
00710               const Matrix<T2, General, RowMajor, Allocator2>& B,
00711               const T3 beta,
00712               Matrix<T4, General, RowSparse, Allocator4>& C)
00713   {
00714     throw Undefined("void MltAdd(const T0 alpha,"
00715                     "const Matrix<T1, General, RowSparse, Allocator1>& A,"
00716                     "const Matrix<T2, General, RowMajor, Allocator2>& B,"
00717                     "const T3 beta,"
00718                     "Matrix<T4, General, RowSparse, Allocator4>& C)");
00719   }
00720 
00721 
00722   template <class T0,
00723            class Allocator1,
00724            class Allocator2,
00725            class Allocator3,
00726            class T4, class Prop4, class Storage4, class Allocator4>
00727   void MltAdd_heterogeneous(const T0 alpha,
00728                             const Matrix<FloatDouble, General,
00729                             DenseSparseCollection, Allocator1>& A,
00730                             const Matrix<FloatDouble, General,
00731                             DenseSparseCollection, Allocator2>& B,
00732                             Matrix<FloatDouble, General,
00733                             DenseSparseCollection, Allocator3>& C,
00734                             Matrix<T4, Prop4, Storage4, Allocator4>& mc,
00735                             int i, int j)
00736   {
00737     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1>
00738       ::float_dense_m m0a;
00739     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1>
00740       ::float_sparse_m m1a;
00741     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1>
00742       ::double_dense_m m2a;
00743     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1>
00744       ::double_sparse_m m3a;
00745 
00746     int na = A.GetNmatrix();
00747     for (int k = 0; k < na; k++)
00748       {
00749         switch (A.GetType(i, k))
00750           {
00751           case 0:
00752             A.GetMatrix(i, k, m0a);
00753             MltAdd_heterogeneous2(alpha, m0a, B, C, mc, j, k);
00754             m0a.Nullify();
00755             break;
00756           case 1:
00757             A.GetMatrix(i, k, m1a);
00758             MltAdd_heterogeneous2(alpha, m1a, B, C, mc, j, k);
00759             m1a.Nullify();
00760             break;
00761           case 2:
00762             A.GetMatrix(i, k, m2a);
00763             MltAdd_heterogeneous2(alpha, m2a, B, C, mc, j, k);
00764             m2a.Nullify();
00765             break;
00766           case 3:
00767             A.GetMatrix(i, k, m3a);
00768             MltAdd_heterogeneous2(alpha, m3a, B, C, mc, j, k);
00769             m3a.Nullify();
00770             break;
00771           default:
00772             throw WrongArgument("Matrix<FloatDouble, DenseSparseCollection>::"
00773                                 "MltAdd_heterogeneous(alpha, A, B, beta, C) ",
00774                                 "Underlying matrix  A (" + to_str(i) + " ,"
00775                                 + to_str(k) + " ) not defined.");
00776           }
00777       }
00778   }
00779 
00780 
00781   template<class T0,
00782            class T1, class Prop1, class Storage1, class Allocator1,
00783            class Allocator2,
00784            class Allocator3,
00785            class T4, class Prop4, class Storage4, class Allocator4>
00786   void MltAdd_heterogeneous2(const T0 alpha,
00787                              const Matrix<T1, Prop1,
00788                              Storage1, Allocator1>& ma,
00789                              const Matrix<FloatDouble, General,
00790                              DenseSparseCollection, Allocator2>& B,
00791                              Matrix<FloatDouble, General,
00792                              DenseSparseCollection, Allocator3>& C,
00793                              Matrix<T4, Prop4, Storage4, Allocator4>& mc,
00794                              int j, int k)
00795   {
00796     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
00797       ::float_dense_m m0b;
00798     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
00799       ::float_sparse_m m1b;
00800     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
00801       ::double_dense_m m2b;
00802     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
00803       ::double_sparse_m m3b;
00804 
00805     switch (B.GetType(k, j))
00806       {
00807       case 0:
00808         B.GetMatrix(k, j, m0b);
00809         MltAdd(alpha, ma, m0b, 1., mc);
00810         m0b.Nullify();
00811         break;
00812       case 1:
00813         B.GetMatrix(k, j, m1b);
00814         MltAdd(alpha, ma, m1b, 1., mc);
00815         m1b.Nullify();
00816         break;
00817       case 2:
00818         B.GetMatrix(k, j, m2b);
00819         MltAdd(alpha, ma, m2b, 1., mc);
00820         m2b.Nullify();
00821         break;
00822       case 3:
00823         B.GetMatrix(k, j, m3b);
00824         MltAdd(alpha, ma, m3b, 1., mc);
00825         m3b.Nullify();
00826         break;
00827       default:
00828         throw WrongArgument("Matrix<FloatDouble, DenseSparseCollection>"
00829                             "::MltAdd_heterogeneous2(alpha, A, B, beta, C)",
00830                             "Underlying matrix  B (" + to_str(k) + " ,"
00831                             + to_str(j) + " ) not defined.");
00832       }
00833   }
00834 
00835 
00836 
00838 
00842   template <class T0, class Allocator1, class Allocator2, class T3,
00843             class Allocator4>
00844   void MltAdd(const T0 alpha,
00845               const Matrix<FloatDouble, General, DenseSparseCollection,
00846               Allocator1>& A,
00847               const Matrix<FloatDouble, General, DenseSparseCollection,
00848               Allocator2>& B,
00849               const T3 beta,
00850               Matrix<FloatDouble, General, DenseSparseCollection,
00851               Allocator4>& C)
00852   {
00853     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator4>
00854       ::float_dense_m m0c;
00855     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator4>
00856       ::float_sparse_m m1c;
00857     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator4>
00858       ::double_dense_m m2c;
00859     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator4>
00860       ::double_sparse_m m3c;
00861 
00862     Mlt(beta, C);
00863 
00864     int mc = C.GetMmatrix();
00865     int nc = C.GetNmatrix();
00866     for (int i = 0; i < mc; i++ )
00867       for (int j = 0; j < nc; j++)
00868         {
00869           switch (C.GetType(i, j))
00870             {
00871             case 0:
00872               C.GetMatrix(i, j, m0c);
00873               MltAdd_heterogeneous(float(alpha), A, B, C, m0c, i, j);
00874               C.SetMatrix(i, j, m0c);
00875               m0c.Nullify();
00876               break;
00877             case 1:
00878               C.GetMatrix(i, j, m1c);
00879               MltAdd_heterogeneous(float(alpha), A, B, C, m1c, i, j);
00880               C.SetMatrix(i, j, m1c);
00881               m1c.Nullify();
00882               break;
00883             case 2:
00884               C.GetMatrix(i, j, m2c);
00885               MltAdd_heterogeneous(double(alpha), A, B, C, m2c, i, j);
00886               C.SetMatrix(i, j, m2c);
00887               m2c.Nullify();
00888               break;
00889             case 3:
00890               C.GetMatrix(i, j, m3c);
00891               MltAdd_heterogeneous(double(alpha), A, B, C, m3c, i, j);
00892               C.SetMatrix(i, j, m3c);
00893               m3c.Nullify();
00894               break;
00895             default:
00896               throw WrongArgument("Matrix<FloatDouble, DenseSparseCollection>"
00897                                   "::MltAdd(alpha, A, B, beta, C) ",
00898                                   "Underlying matrix  C (" + to_str(i) + " ,"
00899                                   + to_str(j) + " ) not defined.");
00900             }
00901         }
00902   }
00903 
00904 
00906 
00916   template <class T0,
00917             class T1, class Prop1, class Allocator1,
00918             class T2, class Prop2, class Allocator2,
00919             class T3,
00920             class T4, class Prop4, class Allocator4>
00921   void MltAdd(const T0 alpha,
00922               const Matrix<T1, Prop1, RowSparse, Allocator1>& A,
00923               const Matrix<T2, Prop2, RowSparse, Allocator2>& B,
00924               const T3 beta,
00925               Matrix<T4, Prop4, RowSparse, Allocator4>& C)
00926   {
00927     if (beta == T3(0))
00928       {
00929         if (alpha == T0(0))
00930           Mlt(alpha, C);
00931         else
00932           {
00933             Mlt(A, B, C);
00934             if (alpha != T0(1))
00935               Mlt(alpha, C);
00936           }
00937       }
00938     else
00939       {
00940         if (alpha == T0(0))
00941           Mlt(beta, C);
00942         else
00943           {
00944             Matrix<T4, Prop4, RowSparse, Allocator4> tmp;
00945             Mlt(A, B, tmp);
00946             if (beta != T0(1))
00947               Mlt(beta, C);
00948             Add(alpha, tmp, C);
00949           }
00950       }
00951   }
00952 
00953 
00955 
00967   template <class T0,
00968             class T1, class Prop1, class Allocator1,
00969             class T2, class Prop2, class Allocator2,
00970             class T3,
00971             class T4, class Prop4, class Allocator4>
00972   void MltNoTransTransAdd(const T0 alpha,
00973                           const Matrix<T1, Prop1, RowSparse, Allocator1>& A,
00974                           const Matrix<T2, Prop2, RowSparse, Allocator2>& B,
00975                           const T3 beta,
00976                           Matrix<T4, Prop4, RowSparse, Allocator4>& C)
00977   {
00978     if (beta == T3(0))
00979       {
00980         if (alpha == T0(0))
00981           Mlt(alpha, C);
00982         else
00983           {
00984             MltNoTransTrans(A, B, C);
00985             if (alpha != T0(1))
00986               Mlt(alpha, C);
00987           }
00988       }
00989     else
00990       {
00991         if (alpha == T0(0))
00992           Mlt(beta, C);
00993         else
00994           {
00995             Matrix<T4, Prop4, RowSparse, Allocator4> tmp;
00996             MltNoTransTrans(A, B, tmp);
00997             if (beta != T0(1))
00998               Mlt(beta, C);
00999             Add(alpha, tmp, C);
01000           }
01001       }
01002   }
01003 
01004 
01006 
01022   template <class T0,
01023             class T1, class Prop1, class Allocator1,
01024             class T2, class Prop2, class Allocator2,
01025             class T3,
01026             class T4, class Prop4, class Allocator4>
01027   void MltAdd(const T0 alpha,
01028               const SeldonTranspose& TransA,
01029               const Matrix<T1, Prop1, RowSparse, Allocator1>& A,
01030               const SeldonTranspose& TransB,
01031               const Matrix<T2, Prop2, RowSparse, Allocator2>& B,
01032               const T3 beta,
01033               Matrix<T4, Prop4, RowSparse, Allocator4>& C)
01034   {
01035     if (!TransA.NoTrans())
01036       throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, "
01037                           "const Matrix<RowSparse>& A, SeldonTranspose "
01038                           "TransB, const Matrix<RowSparse>& B, T3 beta, "
01039                           "Matrix<RowSparse>& C)",
01040                           "'TransA' must be equal to 'SeldonNoTrans'.");
01041     if (!TransB.NoTrans() && !TransB.Trans())
01042       throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, "
01043                           "const Matrix<RowSparse>& A, SeldonTranspose "
01044                           "TransB, const Matrix<RowSparse>& B, T3 beta, "
01045                           "Matrix<RowSparse>& C)",
01046                           "'TransB' must be equal to 'SeldonNoTrans' or "
01047                           "'SeldonTrans'.");
01048 
01049     if (TransB.Trans())
01050       MltNoTransTransAdd(alpha, A, B, beta, C);
01051     else
01052       MltAdd(alpha, A, B, beta, C);
01053   }
01054 
01055 
01056   // MLTADD //
01058 
01059 
01060 
01062   // ADD //
01063 
01064 
01066 
01073   template<class T0, class T1, class Prop1, class Storage1, class Allocator1,
01074            class T2, class Prop2, class Storage2, class Allocator2>
01075   void Add(const T0& alpha,
01076            const Matrix<T1, Prop1, Storage1, Allocator1>& A,
01077            Matrix<T2, Prop2, Storage2, Allocator2>& B)
01078   {
01079     int i, j;
01080     for (i = 0; i < A.GetM(); i++)
01081       for (j = 0; j < A.GetN(); j++)
01082         B(i, j) += alpha * A(i, j);
01083   }
01084 
01085 
01087 
01094   template<class T0,
01095            class T1, class Prop1, class Allocator1,
01096            class T2, class Prop2, class Allocator2>
01097   void Add(const T0& alpha,
01098            const Matrix<T1, Prop1, RowMajorCollection, Allocator1>& A,
01099            Matrix<T2, Prop2, RowMajorCollection, Allocator2>& B)
01100   {
01101     int na = A.GetNmatrix();
01102     int ma = A.GetMmatrix();
01103 
01104     typedef typename T2::value_type value_type;
01105 
01106     for (int i = 0; i < ma; i++ )
01107       for (int j = 0; j < na; j++)
01108         Add(value_type(alpha), A.GetMatrix(i, j), B.GetMatrix(i, j));
01109   }
01110 
01111 
01113 
01120   template<class T0,
01121            class T1, class Prop1, class Allocator1,
01122            class T2, class Prop2, class Allocator2>
01123   void Add(const T0& alpha,
01124            const Matrix<T1, Prop1, ColMajorCollection, Allocator1>& A,
01125            Matrix<T2, Prop2, ColMajorCollection, Allocator2>& B)
01126   {
01127     int na = A.GetNmatrix();
01128     int ma = A.GetMmatrix();
01129 
01130     typedef typename T2::value_type value_type;
01131 
01132     for (int i = 0; i < ma; i++ )
01133       for (int j = 0; j < na; j++)
01134         Add(value_type(alpha), A.GetMatrix(i, j), B.GetMatrix(i, j));
01135   }
01136 
01137 
01138   template <class T0,
01139             class T1, class Prop1, class Storage1, class Allocator1,
01140             class Allocator2>
01141   void Add_heterogeneous(const T0 alpha,
01142                          const  Matrix<T1, Prop1, Storage1, Allocator1 >& ma,
01143                          Matrix<FloatDouble, General,
01144                          DenseSparseCollection, Allocator2>& B,
01145                          int i, int j)
01146   {
01147     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
01148       ::float_dense_m m0b;
01149     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
01150       ::float_sparse_m m1b;
01151     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
01152       ::double_dense_m m2b;
01153     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
01154       ::double_sparse_m m3b;
01155 
01156     T0 alpha_ = alpha;
01157 
01158     switch (B.GetType(i, j))
01159       {
01160       case 0:
01161         B.GetMatrix(i, j, m0b);
01162         Add(float(alpha_), ma, m0b);
01163         B.SetMatrix(i, j, m0b);
01164         m0b.Nullify();
01165         break;
01166       case 1:
01167         B.GetMatrix(i, j, m1b);
01168         Add(float(alpha_), ma, m1b);
01169         B.SetMatrix(i, j, m1b);
01170         m1b.Nullify();
01171         break;
01172       case 2:
01173         B.GetMatrix(i, j, m2b);
01174         Add(double(alpha_), ma, m2b);
01175         B.SetMatrix(i, j, m2b);
01176         m2b.Nullify();
01177         break;
01178       case 3:
01179         B.GetMatrix(i, j, m3b);
01180         Add(double(alpha_), ma, m3b);
01181         B.SetMatrix(i, j, m3b);
01182         m3b.Nullify();
01183         break;
01184       default:
01185         throw WrongArgument("Add_heterogeneous(alpha, Matrix<FloatDouble, "
01186                             "DenseSparseCollection>, Matrix<FloatDouble,"
01187                             "DenseSparseCollection> )",
01188                             "Underlying matrix (" + to_str(i) + " ,"
01189                             + to_str(j) + " ) not defined.");
01190       }
01191   }
01192 
01193 
01195 
01199   template <class T0, class Allocator1, class Allocator2>
01200   void Add(const T0 alpha,
01201            const Matrix<FloatDouble, General,
01202            DenseSparseCollection, Allocator1>& A,
01203            Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>& B)
01204   {
01205     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
01206       ::float_dense_m m0a;
01207     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
01208       ::float_sparse_m m1a;
01209     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
01210       ::double_dense_m m2a;
01211     typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
01212       ::double_sparse_m m3a;
01213 
01214     T0 alpha_ = alpha;
01215 
01216     for (int i = 0; i < B.GetMmatrix(); i++)
01217       for (int j = 0; j < B.GetNmatrix(); j++)
01218         {
01219           switch (B.GetType(i, j))
01220             {
01221             case 0:
01222               A.GetMatrix(i, j, m0a);
01223               Add_heterogeneous(float(alpha_), m0a, B, i, j);
01224               m0a.Nullify();
01225               break;
01226             case 1:
01227               A.GetMatrix(i, j, m1a);
01228               Add_heterogeneous(float(alpha_), m1a, B, i, j);
01229               m1a.Nullify();
01230               break;
01231             case 2:
01232               A.GetMatrix(i, j, m2a);
01233               Add_heterogeneous(double(alpha_), m2a, B, i, j);
01234               m2a.Nullify();
01235               break;
01236             case 3:
01237               A.GetMatrix(i, j, m3a);
01238               Add_heterogeneous(double(alpha_), m3a, B, i, j);
01239               m3a.Nullify();
01240               break;
01241             default:
01242               throw
01243                 WrongArgument("Add(alpha, Matrix<FloatDouble, "
01244                               "DenseSparseCollection>, Matrix<FloatDouble,"
01245                               "DenseSparseCollection> )",
01246                               "Underlying matrix (" + to_str(i) + " ,"
01247                               + to_str(j) + " ) not defined.");
01248             }
01249         }
01250   }
01251 
01252 
01253   template<class T0, class T1, class Prop1, class Allocator1,
01254            class T2, class Prop2, class Allocator2>
01255   void Add(const T0& alpha,
01256            const Matrix<T1, Prop1, RowMajor, Allocator1>& A,
01257            Matrix<T2, Prop2, RowSparse, Allocator2>& B) throw()
01258   {
01259     throw Undefined("void Add(const T0& alpha,"
01260                     "const Matrix<T1, Prop1, RowMajor, Allocator1>& A,"
01261                     "Matrix<T2, Prop2, RowSparse, Allocator2>& B)");
01262   }
01263 
01264 
01265   template<class T0, class T1, class Prop1, class Allocator1,
01266            class T2, class Prop2, class Allocator2>
01267   void Add(const T0& alpha,
01268            const Matrix<T1, Prop1, ColMajor, Allocator1>& A,
01269            Matrix<T2, Prop2, RowSparse, Allocator2>& B) throw()
01270   {
01271     throw Undefined("void Add(const T0& alpha,"
01272                     "const Matrix<T1, Prop1, RowMajor, Allocator1>& A,"
01273                     "Matrix<T2, Prop2, RowSparse, Allocator2>& B)");
01274   }
01275 
01276 
01277   template<class T0, class T1, class Storage1, class Allocator1,
01278            class T2, class Storage2, class Allocator2>
01279   void Add(const T0& alpha,
01280            const Matrix<T1, Symmetric, Storage1, Allocator1>& A,
01281            Matrix<T2, Symmetric, Storage2, Allocator2>& B)
01282   {
01283     int i, j;
01284     for (i = 0; i < A.GetM(); i++)
01285       for (j = i; j < A.GetN(); j++)
01286         B(i, j) += alpha * A(i, j);
01287   }
01288 
01289 
01291 
01298   template<class T0, class T1, class Prop1, class Allocator1,
01299            class T2, class Prop2, class Allocator2>
01300   void Add(const T0& alpha,
01301            const Matrix<T1, Prop1, RowSparse, Allocator1>& A,
01302            Matrix<T2, Prop2, RowSparse, Allocator2>& B)
01303   {
01304 #ifdef SELDON_CHECK_BOUNDS
01305     if (A.GetM() != B.GetM() || A.GetN() != B.GetN())
01306       throw WrongDim("Add(alpha, const Matrix<RowSparse>& A, "
01307                      "Matrix<RowSparse>& B)",
01308                      "Unable to add a " + to_str(A.GetM()) + " x "
01309                      + to_str(A.GetN()) + " matrix with a "
01310                      + to_str(B.GetM()) + " x " + to_str(B.GetN())
01311                      + " matrix.");
01312 #endif
01313 
01314     int i = 0;
01315     int j = 0;
01316     int k;
01317 
01318     if (A.GetNonZeros() == B.GetNonZeros())
01319       // A and B might have the same structure.
01320       {
01321         // Loop over all non-zeros. If the structures of A and B differ at any
01322         // time, the loop is broken and a different strategy is undertaken.
01323         for (i = 0; i < A.GetM(); i++)
01324           if (A.GetPtr()[i + 1] == B.GetPtr()[i + 1])
01325             {
01326               for (j = A.GetPtr()[i]; j < A.GetPtr()[i + 1]; j++)
01327                 if (A.GetInd()[j] == B.GetInd()[j])
01328                   B.GetData()[j] += alpha * A.GetData()[j];
01329                 else
01330                   break;
01331               if (j != A.GetPtr()[i + 1])
01332                 break;
01333             }
01334           else
01335             break;
01336         // Success: A and B have the same structure.
01337         if (i == A.GetM())
01338           return;
01339       }
01340 
01341     // The addition is performed row by row in the following lines. Thus the
01342     // additions already performed in the current line, if started, should be
01343     // canceled.
01344     for (k = A.GetPtr()[i]; k < j; k++)
01345       if (A.GetInd()[k] == B.GetInd()[k])
01346         B.GetData()[k] -= alpha * A.GetData()[k];
01347 
01348     // Number of non zero entries currently found.
01349     int Nnonzero = A.GetPtr()[i];
01350 
01351     // A and B do not have the same structure. An intermediate matrix will be
01352     // needed. The first i rows have already been added. These computations
01353     // should be preserved.
01354     int* c_ptr = NULL;
01355     int* c_ind = NULL;
01356     T2* c_data = NULL;
01357 
01358 #ifdef SELDON_CHECK_MEMORY
01359     try
01360       {
01361 #endif
01362 
01363         c_ptr = reinterpret_cast<int*>(calloc(A.GetM() + 1, sizeof(int)));
01364 
01365 #ifdef SELDON_CHECK_MEMORY
01366       }
01367     catch (...)
01368       {
01369         c_ptr = NULL;
01370       }
01371 
01372     if (c_ptr == NULL)
01373       throw NoMemory("Add(alpha, const Matrix<RowSparse>& A, "
01374                      "Matrix<RowSparse>& B)",
01375                      "Unable to allocate memory for an array of "
01376                      + to_str(A.GetM() + 1) + " integers.");
01377 #endif
01378 
01379 #ifdef SELDON_CHECK_MEMORY
01380     try
01381       {
01382 #endif
01383 
01384         // Reallocates 'c_ind' and 'c_data' for the first i rows.
01385         c_ind = reinterpret_cast<int*>
01386           (realloc(reinterpret_cast<void*>(c_ind), Nnonzero * sizeof(int)));
01387         c_data = reinterpret_cast<T2*>
01388           (B.GetAllocator().reallocate(c_data, Nnonzero));
01389 
01390 #ifdef SELDON_CHECK_MEMORY
01391       }
01392     catch (...)
01393       {
01394         c_ind = NULL;
01395         c_data = NULL;
01396       }
01397 
01398     if ((c_ind == NULL || c_data == NULL)
01399         && Nnonzero != 0)
01400       throw NoMemory("Add(alpha, const Matrix<RowSparse>& A, "
01401                      "Matrix<RowSparse>& B)",
01402                      "Unable to allocate memory for an array of "
01403                      + to_str(Nnonzero) + " integers and for an array of "
01404                      + to_str(sizeof(T2) * Nnonzero) + " bytes.");
01405 #endif
01406 
01407     // The pointers of the first i rows are correct.
01408     for (k = 0; k < i + 1; k++)
01409       c_ptr[k] = B.GetPtr()[k];
01410 
01411     // Copies the elements from the first i rows, as they were already added.
01412     for (k = 0; k < Nnonzero; k++)
01413       {
01414         c_ind[k] = B.GetInd()[k];
01415         c_data[k] = B.GetData()[k];
01416       }
01417 
01418     int Nnonzero_row_max;
01419     int Nnonzero_max;
01420     int ja, jb(0), ka, kb;
01421     // Now deals with the remaining lines.
01422     for (; i < A.GetM(); i++)
01423       {
01424         Nnonzero_row_max = A.GetPtr()[i + 1] - A.GetPtr()[i]
01425           + B.GetPtr()[i + 1] - B.GetPtr()[i];
01426         // Maximum number of non zero entries up to row i.
01427         Nnonzero_max = Nnonzero + Nnonzero_row_max;
01428 
01429 #ifdef SELDON_CHECK_MEMORY
01430         try
01431           {
01432 #endif
01433 
01434             c_ind = reinterpret_cast<int*>
01435               (realloc(reinterpret_cast<void*>(c_ind),
01436                        Nnonzero_max * sizeof(int)));
01437             c_data = reinterpret_cast<T2*>
01438               (B.GetAllocator().reallocate(c_data, Nnonzero_max));
01439 
01440 #ifdef SELDON_CHECK_MEMORY
01441           }
01442         catch (...)
01443           {
01444             c_ind = NULL;
01445             c_data = NULL;
01446           }
01447 
01448         if ((c_ind == NULL || c_data == NULL)
01449             && Nnonzero_max != 0)
01450           throw NoMemory("Add(alpha, const Matrix<RowSparse>& A, "
01451                          "Matrix<RowSparse>& B)",
01452                          "Unable to allocate memory for an array of "
01453                          + to_str(Nnonzero_max) + " integers and for an "
01454                          "array of "
01455                          + to_str(sizeof(T2) * Nnonzero_max) + " bytes.");
01456 #endif
01457 
01458         kb = B.GetPtr()[i];
01459         if (kb < B.GetPtr()[i + 1])
01460           jb = B.GetInd()[kb];
01461         for (ka = A.GetPtr()[i]; ka < A.GetPtr()[i + 1]; ka++)
01462           {
01463             ja = A.GetInd()[ka];
01464             while (kb < B.GetPtr()[i + 1] && jb < ja)
01465               // For all elements in B that are before the ka-th element of A.
01466               {
01467                 c_ind[Nnonzero] = jb;
01468                 c_data[Nnonzero] = B.GetData()[kb];
01469                 kb++;
01470                 if (kb < B.GetPtr()[i + 1])
01471                   jb = B.GetInd()[kb];
01472                 Nnonzero++;
01473               }
01474 
01475             if (kb < B.GetPtr()[i + 1] && ja == jb)
01476               // The element in A is also in B.
01477               {
01478                 c_ind[Nnonzero] = jb;
01479                 c_data[Nnonzero] = B.GetData()[kb] + alpha * A.GetData()[ka];
01480                 kb++;
01481                 if (kb < B.GetPtr()[i + 1])
01482                   jb = B.GetInd()[kb];
01483               }
01484             else
01485               {
01486                 c_ind[Nnonzero] = ja;
01487                 c_data[Nnonzero] = alpha * A.GetData()[ka];
01488               }
01489             Nnonzero++;
01490           }
01491 
01492         // The remaining elements from B.
01493         while (kb < B.GetPtr()[i + 1])
01494           {
01495             c_ind[Nnonzero] = jb;
01496             c_data[Nnonzero] = B.GetData()[kb];
01497             kb++;
01498             if (kb < B.GetPtr()[i + 1])
01499               jb = B.GetInd()[kb];
01500             Nnonzero++;
01501           }
01502 
01503         c_ptr[i + 1] = Nnonzero;
01504       }
01505 
01506     B.SetData(B.GetM(), B.GetN(), Nnonzero, c_data, c_ptr, c_ind);
01507   }
01508 
01509 
01510   // ADD //
01512 
01513 
01514 
01516   // GETLU //
01517 
01518 
01520 
01530   template <class T0, class Prop0, class Storage0, class Allocator0>
01531   void GetLU(Matrix<T0, Prop0, Storage0, Allocator0>& A)
01532   {
01533     int i, p, q, k;
01534     T0 temp;
01535 
01536     int ma = A.GetM();
01537 
01538 #ifdef SELDON_CHECK_BOUNDS
01539     int na = A.GetN();
01540     if (na != ma)
01541       throw WrongDim("GetLU(A)", "The matrix must be squared.");
01542 #endif
01543 
01544     for (i = 0; i < ma; i++)
01545       {
01546         for (p = i; p < ma; p++)
01547           {
01548             temp = 0;
01549             for (k = 0; k < i; k++)
01550               temp += A(p, k) * A(k, i);
01551             A(p, i) -= temp;
01552           }
01553         for (q = i+1; q < ma; q++)
01554           {
01555             temp = 0;
01556             for (k = 0; k < i; k++)
01557               temp += A(i, k) * A(k, q);
01558             A(i, q) = (A(i,q ) - temp) / A(i, i);
01559           }
01560       }
01561   }
01562 
01563 
01564   // GETLU //
01566 
01567 
01568 
01570   // CHECKDIM //
01571 
01572 
01574 
01583   template <class T0, class Prop0, class Storage0, class Allocator0,
01584             class T1, class Prop1, class Storage1, class Allocator1,
01585             class T2, class Prop2, class Storage2, class Allocator2>
01586   void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& A,
01587                 const Matrix<T1, Prop1, Storage1, Allocator1>& B,
01588                 const Matrix<T2, Prop2, Storage2, Allocator2>& C,
01589                 string function = "")
01590   {
01591     if (B.GetM() != A.GetN() || C.GetM() != A.GetM() || B.GetN() != C.GetN())
01592       throw WrongDim(function, string("Operation A B + C -> C not permitted:")
01593                      + string("\n     A (") + to_str(&A) + string(") is a ")
01594                      + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
01595                      + string(" matrix;\n     B (") + to_str(&B)
01596                      + string(") is a ") + to_str(B.GetM())  + string(" x ")
01597                      + to_str(B.GetN()) + string(" matrix;\n     C (")
01598                      + to_str(&C) + string(") is a ") + to_str(C.GetM())
01599                      + string(" x ") + to_str(C.GetN()) + string(" matrix."));
01600   }
01601 
01602 
01604 
01614   template <class T0, class Prop0, class Storage0, class Allocator0,
01615             class T1, class Prop1, class Storage1, class Allocator1,
01616             class T2, class Prop2, class Storage2, class Allocator2>
01617   void CheckDim(const SeldonSide& side,
01618                 const Matrix<T0, Prop0, Storage0, Allocator0>& A,
01619                 const Matrix<T1, Prop1, Storage1, Allocator1>& B,
01620                 const Matrix<T2, Prop2, Storage2, Allocator2>& C,
01621                 string function = "")
01622   {
01623     if ( SeldonSide(side).Left() &&
01624          (B.GetM() != A.GetN() || C.GetM() != A.GetM()
01625           || B.GetN() != C.GetN()) )
01626       throw WrongDim(function, string("Operation A B + C -> C not permitted:")
01627                      + string("\n     A (") + to_str(&A) + string(") is a ")
01628                      + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
01629                      + string(" matrix;\n     B (") + to_str(&B)
01630                      + string(") is a ") + to_str(B.GetM())  + string(" x ")
01631                      + to_str(B.GetN()) + string(" matrix;\n     C (")
01632                      + to_str(&C) + string(") is a ") + to_str(C.GetM())
01633                      + string(" x ") + to_str(C.GetN()) + string(" matrix."));
01634     else if ( SeldonSide(side).Right() &&
01635               (B.GetN() != A.GetM() || C.GetM() != B.GetM()
01636                || A.GetN() != C.GetN()) )
01637       throw WrongDim(function, string("Operation B A + C -> C not permitted:")
01638                      + string("\n     A (") + to_str(&A) + string(") is a ")
01639                      + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
01640                      + string(" matrix;\n     B (") + to_str(&B)
01641                      + string(") is a ") + to_str(B.GetM())  + string(" x ")
01642                      + to_str(B.GetN()) + string(" matrix;\n     C (")
01643                      + to_str(&C) + string(") is a ") + to_str(C.GetM())
01644                      + string(" x ") + to_str(C.GetN()) + string(" matrix."));
01645   }
01646 
01647 
01649 
01659   template <class T0, class Prop0, class Storage0, class Allocator0,
01660             class T1, class Prop1, class Storage1, class Allocator1>
01661   void CheckDim(const SeldonTranspose& TransA,
01662                 const Matrix<T0, Prop0, Storage0, Allocator0>& A,
01663                 const SeldonTranspose& TransB,
01664                 const Matrix<T1, Prop1, Storage1, Allocator1>& B,
01665                 string function = "")
01666   {
01667     SeldonTranspose status_A(TransA);
01668     SeldonTranspose status_B(TransB);
01669     string op;
01670     if (status_A.Trans())
01671       op = string("A'");
01672     else if (status_A.ConjTrans())
01673       op = string("A*");
01674     else
01675       op = string("A");
01676     if (status_B.Trans())
01677       op += string(" B'");
01678     else if (status_B.ConjTrans())
01679       op += string(" B*");
01680     else
01681       op += string(" B");
01682     op = string("Operation ") + op + string(" not permitted:");
01683     if (B.GetM(status_B) != A.GetN(status_A))
01684       throw WrongDim(function, op
01685                      + string("\n     A (") + to_str(&A) + string(") is a ")
01686                      + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
01687                      + string(" matrix;\n     B (") + to_str(&B)
01688                      + string(") is a ") + to_str(B.GetM())  + string(" x ")
01689                      + to_str(B.GetN()) + string(" matrix."));
01690   }
01691 
01692 
01694 
01705   template <class T0, class Prop0, class Storage0, class Allocator0,
01706             class T1, class Prop1, class Storage1, class Allocator1,
01707             class T2, class Prop2, class Storage2, class Allocator2>
01708   void CheckDim(const SeldonTranspose& TransA,
01709                 const Matrix<T0, Prop0, Storage0, Allocator0>& A,
01710                 const SeldonTranspose& TransB,
01711                 const Matrix<T1, Prop1, Storage1, Allocator1>& B,
01712                 const Matrix<T2, Prop2, Storage2, Allocator2>& C,
01713                 string function = "")
01714   {
01715     string op;
01716     if (TransA.Trans())
01717       op = string("A'");
01718     else if (TransA.ConjTrans())
01719       op = string("A*");
01720     else
01721       op = string("A");
01722     if (TransB.Trans())
01723       op += string(" B' + C");
01724     else if (TransB.ConjTrans())
01725       op += string(" B* + C");
01726     else
01727       op += string(" B + C");
01728     op = string("Operation ") + op + string(" not permitted:");
01729     if (B.GetM(TransB) != A.GetN(TransA) || C.GetM() != A.GetM(TransA)
01730         || B.GetN(TransB) != C.GetN())
01731       throw WrongDim(function, op
01732                      + string("\n     A (") + to_str(&A) + string(") is a ")
01733                      + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
01734                      + string(" matrix;\n     B (") + to_str(&B)
01735                      + string(") is a ") + to_str(B.GetM())  + string(" x ")
01736                      + to_str(B.GetN()) + string(" matrix;\n     C (")
01737                      + to_str(&C) + string(") is a ") + to_str(C.GetM())
01738                      + string(" x ") + to_str(C.GetN()) + string(" matrix."));
01739   }
01740 
01741 
01743 
01751   template <class T0, class Prop0, class Storage0, class Allocator0,
01752             class T1, class Prop1, class Storage1, class Allocator1>
01753   void CheckDim(const Matrix<T0, Prop0, Storage0, Allocator0>& A,
01754                 const Matrix<T1, Prop1, Storage1, Allocator1>& B,
01755                 string function = "")
01756   {
01757     CheckDim(SeldonLeft, A, B, function);
01758   }
01759 
01760 
01762 
01771   template <class T0, class Prop0, class Storage0, class Allocator0,
01772             class T1, class Prop1, class Storage1, class Allocator1>
01773   void CheckDim(const SeldonSide& side,
01774                 const Matrix<T0, Prop0, Storage0, Allocator0>& A,
01775                 const Matrix<T1, Prop1, Storage1, Allocator1>& B,
01776                 string function = "")
01777   {
01778     if (side.Left() && B.GetM() != A.GetN())
01779       throw WrongDim(function, string("Operation A B not permitted:")
01780                      + string("\n     A (") + to_str(&A) + string(") is a ")
01781                      + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
01782                      + string(" matrix;\n     B (") + to_str(&B)
01783                      + string(") is a ") + to_str(B.GetM())  + string(" x ")
01784                      + to_str(B.GetN()) + string(" matrix."));
01785     else if (side.Right() && B.GetN() != A.GetM())
01786       throw WrongDim(function, string("Operation B A not permitted:")
01787                      + string("\n     A (") + to_str(&A) + string(") is a ")
01788                      + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
01789                      + string(" matrix;\n     B (") + to_str(&B)
01790                      + string(") is a ") + to_str(B.GetM())  + string(" x ")
01791                      + to_str(B.GetN()) + string(" matrix."));
01792   }
01793 
01794 
01795   // CHECKDIM //
01797 
01798 
01800   // NORMS //
01801 
01802 
01804 
01808   template <class T, class Prop, class Storage, class Allocator>
01809   T MaxAbs(const Matrix<T, Prop, Storage, Allocator>& A)
01810   {
01811     T res(0);
01812     for (int i = 0; i < A.GetM(); i++)
01813       for (int j = 0; j < A.GetN(); j++)
01814         res = max(res, abs(A(i, j)) );
01815 
01816     return res;
01817   }
01818 
01819 
01821 
01825   template <class T, class Prop, class Storage, class Allocator>
01826   T Norm1(const Matrix<T, Prop, Storage, Allocator>& A)
01827   {
01828     T res(0), sum;
01829     for (int j = 0; j < A.GetN(); j++)
01830       {
01831         sum = T(0);
01832         for (int i = 0; i < A.GetM(); i++)
01833           sum += abs( A(i, j) );
01834 
01835         res = max(res, sum);
01836       }
01837 
01838     return res;
01839   }
01840 
01841 
01843 
01847   template <class T, class Prop, class Storage, class Allocator>
01848   T NormInf(const Matrix<T, Prop, Storage, Allocator>& A)
01849   {
01850     T res(0), sum;
01851     for (int i = 0; i < A.GetM(); i++)
01852       {
01853         sum = T(0);
01854         for (int j = 0; j < A.GetN(); j++)
01855           sum += abs( A(i, j) );
01856 
01857         res = max(res, sum);
01858       }
01859 
01860     return res;
01861   }
01862 
01863 
01865 
01869   template <class T, class Prop, class Storage, class Allocator>
01870   T MaxAbs(const Matrix<complex<T>, Prop, Storage, Allocator>& A)
01871   {
01872     T res(0);
01873     for (int i = 0; i < A.GetM(); i++)
01874       for (int j = 0; j < A.GetN(); j++)
01875         {
01876           res = max(res, abs(A(i, j)) );
01877         }
01878 
01879     return res;
01880   }
01881 
01882 
01884 
01888   template <class T, class Prop, class Storage, class Allocator>
01889   T Norm1(const Matrix<complex<T>, Prop, Storage, Allocator>& A)
01890   {
01891     T res(0), sum;
01892     for (int j = 0; j < A.GetN(); j++)
01893       {
01894         sum = T(0);
01895         for (int i = 0; i < A.GetM(); i++)
01896           sum += abs( A(i, j) );
01897 
01898         res = max(res, sum);
01899       }
01900 
01901     return res;
01902   }
01903 
01904 
01906 
01910   template <class T, class Prop, class Storage, class Allocator>
01911   T NormInf(const Matrix<complex<T>, Prop, Storage, Allocator>& A)
01912   {
01913     T res(0), sum;
01914     for (int i = 0; i < A.GetM(); i++)
01915       {
01916         sum = T(0);
01917         for (int j = 0; j < A.GetN(); j++)
01918           sum += abs( A(i, j) );
01919 
01920         res = max(res, sum);
01921       }
01922 
01923     return res;
01924   }
01925 
01926 
01927   // NORMS //
01929 
01930 
01931 
01933   // TRANSPOSE //
01934 
01935 
01937   template<class T, class Prop, class Storage, class Allocator>
01938   void Transpose(Matrix<T, Prop, Storage, Allocator>& A)
01939   {
01940     int m = A.GetM();
01941     int n = A.GetN();
01942 
01943     if (m == n)
01944       {
01945         T tmp;
01946         for (int i = 0; i < m; i++)
01947           for (int j = 0; j < i; j++)
01948             {
01949               tmp = A(i,j);
01950               A(i,j) = A(j,i);
01951               A(j,i) = tmp;
01952             }
01953       }
01954     else
01955       {
01956         Matrix<T, Prop, Storage, Allocator> B;
01957         B = A;
01958         A.Reallocate(n,m);
01959         for (int i = 0; i < m; i++)
01960           for (int j = 0; j < n; j++)
01961             A(j,i) = B(i,j);
01962       }
01963   }
01964 
01965 
01967   template<class T, class Allocator>
01968   void Transpose(Matrix<T, General, RowSparse, Allocator>& A)
01969   {
01970     int m = A.GetM();
01971     int n = A.GetN();
01972     int nnz = A.GetDataSize();
01973     Vector<int, VectFull, CallocAlloc<int> > ptr_T(n+1), ptr;
01974     Vector<int, VectFull, CallocAlloc<int> > ind_T(nnz), ind;
01975     Vector<T, VectFull, Allocator> data_T(nnz), data;
01976 
01977     ptr.SetData(m+1, A.GetPtr());
01978     ind.SetData(nnz,  A.GetInd());
01979     data.SetData(nnz, A.GetData());
01980 
01981     ptr_T.Zero();
01982     ind_T.Zero();
01983     data_T.Zero();
01984 
01985     // For each column j, computes number of its non-zeroes and stores it in
01986     // ptr_T[j].
01987     for (int i = 0; i < nnz; i++)
01988       ptr_T(ind(i) + 1)++;
01989 
01990     // Computes the required number of non-zeroes ptr_T(j).
01991     for (int j = 1; j < n + 1; j++)
01992       ptr_T(j) += ptr_T(j - 1);
01993 
01994     Vector<int, VectFull, CallocAlloc<int> > row_ind(n+1);
01995     row_ind.Fill(0);
01996     for (int i = 0; i < m; i++)
01997       for (int jp = ptr(i); jp < ptr(i+1); jp++)
01998         {
01999           int j = ind(jp);
02000           int k = ptr_T(j) + row_ind(j);
02001           ++row_ind(j);
02002           data_T(k) = data(jp);
02003           ind_T(k) = i;
02004         }
02005 
02006     A.SetData(n, m, data_T, ptr_T, ind_T);
02007 
02008     data.Nullify();
02009     ptr.Nullify();
02010     ind.Nullify();
02011   }
02012 
02013 
02015   template<class T, class Prop, class Storage, class Allocator>
02016   void TransposeConj(Matrix<T, Prop, Storage, Allocator>& A)
02017   {
02018     int i, j;
02019 
02020     int m = A.GetM();
02021     int n = A.GetN();
02022 
02023     if (m == n)
02024       {
02025         T tmp;
02026         for (i = 0; i < m; i++)
02027           {
02028             // Extra-diagonal part.
02029             for (j = 0; j < i; j++)
02030               {
02031                 tmp = A(i, j);
02032                 A(i, j) = conj(A(j, i));
02033                 A(j, i) = conj(tmp);
02034               }
02035 
02036             // Diagonal part.
02037             A(i, i) = conj(A(i, i));
02038           }
02039       }
02040     else
02041       {
02042         Matrix<T, Prop, Storage, Allocator> B;
02043         B = A;
02044         A.Reallocate(n, m);
02045         for (i = 0; i < m; i++)
02046           for (j = 0; j < n; j++)
02047             A(j, i) = conj(B(i, j));
02048       }
02049   }
02050 
02051 
02052   // TRANSPOSE //
02054 
02055 
02057   // ISSYMMETRICMATRIX //
02058 
02059 
02061   template<class T, class Prop, class Storage, class Allocator>
02062   bool IsSymmetricMatrix(const Matrix<T, Prop, Storage, Allocator>& A)
02063   {
02064     return false;
02065   }
02066 
02067 
02069   template<class T, class Storage, class Allocator>
02070   bool IsSymmetricMatrix(const Matrix<T, Symmetric, Storage, Allocator>& A)
02071   {
02072     return true;
02073   }
02074 
02075 
02076   // ISSYMMETRICMATRIX //
02078 
02079 } // namespace Seldon.
02080 
02081 #define SELDON_FILE_FUNCTIONS_MATRIX_CXX
02082 #endif