matrix/Functions.cxx

00001 // Copyright (C) 2001-2010 INRIA, Vivien Mallet
00002 // Author(s): Marc Fragu, Vivien Mallet
00003 //
00004 // This file is part of the linear-algebra library Seldon,
00005 // http://seldon.sourceforge.net/.
00006 //
00007 // Seldon is free software; you can redistribute it and/or modify it under the
00008 // terms of the GNU Lesser General Public License as published by the Free
00009 // Software Foundation; either version 2.1 of the License, or (at your option)
00010 // any later version.
00011 //
00012 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
00015 // more details.
00016 //
00017 // You should have received a copy of the GNU Lesser General Public License
00018 // along with Seldon. If not, see http://www.gnu.org/licenses/.
00019 
00020 
00021 #ifndef SELDON_FILE_FUNCTIONS_CXX
00022 
00023 #include "Functions.hxx"
00024 
00025 #include "../computation/basic_functions/Functions_Vector.cxx"
00026 
00027 namespace Seldon
00028 {
00029 
00030 
00032 
00037   template <class T0, class Allocator0, class T1, class Allocator1>
00038   void GetRow(const Matrix<T0, General, RowSparse, Allocator0>& M,
00039               int i, Vector<T1, VectSparse, Allocator1>& X)
00040   {
00041 #ifdef SELDON_CHECK_BOUNDS
00042     int m = M.GetM();
00043     if (i < 0 || i >= m)
00044       throw WrongIndex("GetRow()",
00045                        string("Index should be in [0, ") + to_str(m - 1)
00046                        + "], but is equal to " + to_str(i) + ".");
00047 #endif
00048 
00049     int* ptr = M.GetPtr();
00050     int* ind = M.GetInd();
00051     double* data = M.GetData();
00052     int size_row = ptr[i+1] - ptr[i];
00053 
00054     X.Reallocate(size_row);
00055     int shift = ptr[i];
00056     for (int j = 0; j < size_row; j++)
00057       {
00058         X.Index(j) = ind[shift + j];
00059         X.Value(j) = data[shift + j];
00060       }
00061   }
00062 
00063 
00065 
00070   template <class T0, class Prop0, class Storage0, class Allocator0,
00071             class T1, class Storage1, class Allocator1>
00072   void GetRow(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
00073               int i, Vector<T1, Storage1, Allocator1>& X)
00074   {
00075     X.Reallocate(M.GetN());
00076     for (int j = 0; j < M.GetN(); j++)
00077       X(j) = M(i, j);
00078   }
00079 
00080 
00082 
00087   template <class T0, class Allocator0, class T1, class Allocator1>
00088   void GetCol(const Matrix<T0, General, RowSparse, Allocator0>& M,
00089               int j, Vector<T1, VectSparse, Allocator1>& X)
00090   {
00091 #ifdef SELDON_CHECK_BOUNDS
00092     int n = M.GetN();
00093     if (j < 0 || j >= n)
00094       throw WrongIndex("GetCol()",
00095                        string("Index should be in [0, ") + to_str(n - 1)
00096                        + "], but is equal to " + to_str(j) + ".");
00097 #endif
00098 
00099     int* ptr = M.GetPtr();
00100     int* ind = M.GetInd();
00101     double* data = M.GetData();
00102     int m = M.GetM();
00103     Vector<int> index;
00104     Vector<double> value;
00105 
00106     for (int i = 0; i < m; i++)
00107       for (int k = ptr[i]; k < ptr[i+1]; k++)
00108         if (ind[k] == j)
00109           {
00110             index.PushBack(i);
00111             value.PushBack(data[k]);
00112           }
00113 
00114     X.SetData(value, index);
00115   }
00116 
00117 
00119 
00124   template <class T0, class Prop0, class Allocator0,
00125             class T1, class Allocator1>
00126   void GetCol(const Matrix<T0, Prop0, PETScSeqDense, Allocator0>& M,
00127               int j, Vector<T1, PETScSeq, Allocator1>& X)
00128   {
00129     int a, b;
00130     M.GetProcessorRowRange(a, b);
00131     for (int i = a; i < b; i++)
00132       X.SetBuffer(i, M(i, j));
00133     X.Flush();
00134   }
00135 
00136 
00138 
00143   template <class T0, class Prop0, class Allocator0,
00144             class T1, class Allocator1>
00145   void GetCol(const Matrix<T0, Prop0, PETScMPIDense, Allocator0>& M,
00146               int j, Vector<T1, PETScPar, Allocator1>& X)
00147   {
00148     int a, b;
00149     M.GetProcessorRowRange(a, b);
00150     for (int i = a; i < b; i++)
00151       X.SetBuffer(i, M(i, j));
00152     X.Flush();
00153   }
00154 
00155 
00157 
00162   template <class T0, class Prop0, class Storage0, class Allocator0,
00163             class T1, class Storage1, class Allocator1>
00164   void GetCol(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
00165               int j, Vector<T1, Storage1, Allocator1>& X)
00166   {
00167     X.Reallocate(M.GetM());
00168     for (int i = 0; i < M.GetM(); i++)
00169       X(i) = M(i, j);
00170   }
00171 
00172 
00174 
00181   template <class T0, class Prop0, class Storage0, class Allocator0,
00182             class T1, class Prop1, class Storage1, class Allocator1>
00183   void GetCol(const Matrix<T0, Prop0, Storage0, Allocator0>& M_in,
00184               int begin, int end,
00185               Matrix<T1, Prop1, Storage1, Allocator1>& M_out)
00186   {
00187     M_out.Reallocate(M_in.GetM(), end - begin);
00188     for (int i = 0; i < M_in.GetM(); i++)
00189       for (int j = begin, k = 0; j < end; j++, k++)
00190         M_out(i, k) = M_in(i, j);
00191   }
00192 
00193 
00195 
00200   template <class T0, class Prop0, class Storage0, class Allocator0,
00201             class T1, class Storage1, class Allocator1>
00202   void SetRow(const Vector<T1, Storage1, Allocator1>& X,
00203               int i, Matrix<T0, Prop0, Storage0, Allocator0>& M)
00204   {
00205     for (int j = 0; j < M.GetN(); j++)
00206       M.Set(i, j, X(j));
00207   }
00208 
00209 
00211 
00216   template <class T0, class Prop0, class Allocator0,
00217             class T1, class Allocator1>
00218   void SetRow(const Vector<T1, PETScSeq, Allocator1>& X,
00219               int i, Matrix<T0, Prop0, PETScSeqDense, Allocator0>& M)
00220   {
00221     for (int j = 0; j < M.GetN(); j++)
00222       M.SetBuffer(i, j, X(j));
00223     M.Flush();
00224   }
00225 
00226 
00228 
00233   template <class T0, class Prop0, class Allocator0,
00234             class T1, class Allocator1>
00235   void SetRow(const Vector<T1, PETScPar, Allocator1>& X,
00236               int i, Matrix<T0, Prop0, PETScMPIDense, Allocator0>& M)
00237   {
00238     for (int j = 0; j < M.GetN(); j++)
00239       M.SetBuffer(i, j, X(j));
00240     M.Flush();
00241   }
00242 
00243 
00245 
00250   template <class T0, class Allocator0, class T1, class Allocator1>
00251   void SetRow(const Vector<T1, VectSparse, Allocator1>& X,
00252               int i, Matrix<T0, General, RowSparse, Allocator0>& M)
00253   {
00254     int m = M.GetM();
00255     int n = M.GetN();
00256     int nnz = M.GetDataSize();
00257     int Nx = X.GetSize();
00258 
00259 #ifdef SELDON_CHECK_BOUNDS
00260     if (i < 0 || i >= m)
00261       throw WrongIndex("SetRow(Vector, int, Matrix<RowSparse>)",
00262                        string("Index should be in [0, ") + to_str(m - 1)
00263                        + "], but is equal to " + to_str(i) + ".");
00264 #endif
00265 
00266     int *ptr_vector =  M.GetPtr();
00267     int ptr_i0 =  ptr_vector[i], ptr_i1 = ptr_vector[i + 1];
00268     int row_size_difference = Nx - ptr_i1 + ptr_i0;
00269 
00270     if (row_size_difference == 0)
00271       {
00272         for (int k = 0; k < Nx; k++)
00273           M.GetInd()[k + ptr_i0] = X.Index(k);
00274         for (int k = 0; k < Nx; k++)
00275           M.GetData()[k + ptr_i0] = X.Value(k);
00276         return;
00277       }
00278 
00279     Vector<int, VectFull, CallocAlloc<int> >
00280       new_ind_vector(nnz + row_size_difference);
00281     for (int k = 0; k <  ptr_i0; k++)
00282       new_ind_vector(k) = M.GetInd()[k];
00283     for (int k = 0; k < Nx; k++)
00284       new_ind_vector(k + ptr_i0) = X.Index(k);
00285     for (int k = 0; k < nnz - ptr_i1; k++)
00286       new_ind_vector(k + ptr_i0 + Nx) =  M.GetInd()[k + ptr_i1];
00287 
00288     Vector<T1, VectFull, Allocator0 >
00289       new_data_vector(nnz + row_size_difference);
00290     for (int k = 0; k <  ptr_i0; k++)
00291       new_data_vector(k) = M.GetData()[k];
00292     for (int k = 0; k < Nx; k++)
00293       new_data_vector(k + ptr_i0) = X.Value(k);
00294     for (int k = 0; k < nnz - ptr_i1; k++)
00295       new_data_vector(k + ptr_i0 + Nx) =  M.GetData()[k + ptr_i1];
00296 
00297     Vector<int, VectFull, CallocAlloc<int> > new_ptr_vector(m + 1);
00298     for (int j = 0; j < i + 1; j++)
00299       new_ptr_vector(j) = ptr_vector[j];
00300     for (int j = i + 1; j < m+1; j++)
00301       new_ptr_vector(j) =  ptr_vector[j] + row_size_difference;
00302 
00303     M.SetData(m, n, new_data_vector, new_ptr_vector, new_ind_vector);
00304   }
00305 
00306 
00308 
00313   template <class T0, class Prop0, class Storage0, class Allocator0,
00314             class T1, class Storage1, class Allocator1>
00315   void SetCol(const Vector<T1, Storage1, Allocator1>& X,
00316               int j, Matrix<T0, Prop0, Storage0, Allocator0>& M)
00317   {
00318     for (int i = 0; i < M.GetM(); i++)
00319       M.Set(i, j, X(i));
00320   }
00321 
00322 
00324 
00329   template <class T0, class Prop0, class Allocator0,
00330             class T1, class Allocator1>
00331   void SetCol(const Vector<T1, PETScSeq, Allocator1>& X,
00332               int j, Matrix<T0, Prop0, PETScSeqDense, Allocator0>& M)
00333   {
00334     int a, b;
00335     M.GetProcessorRowRange(a, b);
00336     for (int i = a; i < b; i++)
00337       M.SetBuffer(i, j, X(i));
00338     M.Flush();
00339   }
00340 
00341 
00343 
00348   template <class T0, class Prop0, class Allocator0,
00349             class T1, class Allocator1>
00350   void SetCol(const Vector<T1, PETScPar, Allocator1>& X,
00351               int j, Matrix<T0, Prop0, PETScMPIDense, Allocator0>& M)
00352   {
00353     int a, b;
00354     M.GetProcessorRowRange(a, b);
00355     for (int i = a; i < b; i++)
00356       M.SetBuffer(i, j, X(i));
00357     M.Flush();
00358   }
00359 
00360 
00362 
00367   template <class T0, class Allocator0,
00368             class T1, class Allocator1>
00369   void SetCol(const Vector<T1, VectFull, Allocator1>& X,
00370               int j, Matrix<T0, General, RowSparse, Allocator0>& M)
00371   {
00372     Vector<T1, VectSparse, Allocator1> X_sparse;
00373     for (int k = 0; k < X.GetLength(); k++)
00374       {
00375         T1 value = X(k);
00376         if (value != T1(0.))
00377           X_sparse.AddInteraction(k, value);
00378       }
00379 
00380     SetCol(X_sparse, j, M);
00381   }
00382 
00383 
00385 
00390   template <class T0, class Allocator0, class T1, class Allocator1>
00391   void SetCol(const Vector<T1, VectSparse, Allocator1>& X,
00392               int j, Matrix<T0, General, RowSparse, Allocator0>& M)
00393   {
00394     int m = M.GetM();
00395     int n = M.GetN();
00396     int nnz = M.GetDataSize();
00397     int Nx = X.GetSize();
00398 
00399 #ifdef SELDON_CHECK_BOUNDS
00400     if (j < 0 || j >= n)
00401       throw WrongIndex("SetCol(Vector, int, Matrix<RowSparse>)",
00402                        string("Index should be in [0, ") + to_str(n - 1)
00403                        + "], but is equal to " + to_str(j) + ".");
00404 #endif
00405 
00406     // The column to be changed.
00407     Vector<T1, VectSparse, Allocator1> column_j;
00408     GetCol(M, j, column_j);
00409     int Ncolumn_j = column_j.GetSize();
00410     int column_size_difference = Nx - Ncolumn_j;
00411 
00412     // Built a vector indexed with the rows of column_j and X.
00413     Vector<int, VectSparse> column_j_mask;
00414     Vector<int> index_j(Ncolumn_j);
00415     Vector<int> value_j(Ncolumn_j);
00416     for (int p = 0; p < Ncolumn_j; p++)
00417       index_j(p) = column_j.Index(p);
00418     value_j.Fill(-1);
00419     column_j_mask.SetData(value_j, index_j);
00420     value_j.Nullify();
00421     index_j.Nullify();
00422     Vector<int, VectSparse> X_mask;
00423     Vector<int> index_x(Nx);
00424     Vector<int> value_x(Nx);
00425     for (int p = 0; p < Nx; p++)
00426       index_x(p) = X.Index(p);
00427     value_x.Fill(1);
00428     X_mask.SetData(value_x, index_x);
00429     value_x.Nullify();
00430     index_x.Nullify();
00431     X_mask.AddInteractionRow(column_j_mask.GetSize(),
00432                              column_j_mask.GetIndex(),
00433                              column_j_mask.GetData(), true);
00434 
00435     // Built the new pointer vector.
00436     Vector<int, VectFull, CallocAlloc<int> > ptr_vector;
00437     ptr_vector.SetData(m + 1, M.GetPtr());
00438     Vector<int, VectFull, CallocAlloc<int> > new_ptr_vector(m + 1);
00439     new_ptr_vector.Zero();
00440     for (int p = 0; p < X_mask.GetSize(); p++)
00441       new_ptr_vector(X_mask.Index(p) + 1) = X_mask.Value(p);
00442     for (int p = 0; p < m; p++)
00443       new_ptr_vector(p + 1) += new_ptr_vector(p);
00444 
00445     Add(1, ptr_vector, new_ptr_vector);
00446 
00447     // Built the new index and the new data vectors row by row.
00448     Vector<int, VectFull, CallocAlloc<int> >
00449       new_ind_vector(nnz + column_size_difference);
00450     Vector<T0, VectFull, Allocator0>
00451       new_data_vector(nnz + column_size_difference);
00452 
00453     Vector<T0, VectSparse, Allocator0> working_vector;
00454     int Nworking_vector;
00455 
00456     int line = 0;
00457     for (int interaction = 0; interaction < X_mask.GetSize(); interaction++)
00458       {
00459         int ind_x =  X_mask.Index(interaction);
00460         for (int k = 0; k < ptr_vector(ind_x) -  ptr_vector(line); k++)
00461           new_ind_vector.GetData()[k + new_ptr_vector(line)] =
00462             M.GetInd()[k + ptr_vector(line)];
00463         for (int k = 0; k < ptr_vector(ind_x) -  ptr_vector(line); k++)
00464           new_data_vector.GetData()[k + new_ptr_vector(line)] =
00465             M.GetData()[k + ptr_vector(line)];
00466 
00467         int ind_j;
00468         Nworking_vector = ptr_vector(ind_x + 1) - ptr_vector(ind_x);
00469         working_vector.SetData(Nworking_vector,
00470                                M.GetData() + ptr_vector(ind_x),
00471                                M.GetInd() + ptr_vector(ind_x));
00472         switch(X_mask.Value(interaction))
00473           {
00474             // Collision.
00475           case 0:
00476             working_vector.Get(j) = X(ind_x);
00477             for (int k = 0; k < Nworking_vector; k++)
00478               new_ind_vector.GetData()[k + new_ptr_vector(ind_x)] =
00479                 working_vector.GetIndex()[k];
00480             for (int k = 0; k < Nworking_vector; k++)
00481               new_data_vector.GetData()[k + new_ptr_vector(ind_x)] =
00482                 working_vector.GetData()[k];
00483             break;
00484 
00485             // Suppression.
00486           case -1:
00487             ind_j = 0;
00488             while (ind_j < Nworking_vector &&
00489                    working_vector.Index(ind_j) != j)
00490               ind_j++;
00491 
00492             for (int k = 0; k < ind_j; k++)
00493               new_ind_vector.GetData()[k + new_ptr_vector(ind_x)] =
00494                 working_vector.GetIndex()[k];
00495             for (int k = 0; k < Nworking_vector - ind_j - 1; k++)
00496               new_ind_vector.GetData()[k + new_ptr_vector(ind_x) + ind_j] =
00497                 working_vector.GetIndex()[k + ind_j + 1];
00498 
00499             for (int k = 0; k < ind_j; k++)
00500               new_data_vector.GetData()[k + new_ptr_vector(ind_x)] =
00501                 working_vector.GetData()[k];
00502             for (int k = 0; k < Nworking_vector - ind_j - 1; k++)
00503               new_data_vector.GetData()[k + new_ptr_vector(ind_x) + ind_j] =
00504                 working_vector.GetData()[k + ind_j + 1];
00505             break;
00506 
00507             // Addition.
00508           case 1:
00509             ind_j = 0;
00510             while (ind_j < Nworking_vector &&
00511                    working_vector.Index(ind_j) < j)
00512               ind_j++;
00513             for (int k = 0; k < ind_j; k++)
00514               new_ind_vector.GetData()[k + new_ptr_vector(ind_x)] =
00515                 working_vector.GetIndex()[k];
00516             new_ind_vector.GetData()[new_ptr_vector(ind_x) + ind_j] = j;
00517             for (int k = 0; k < Nworking_vector - ind_j; k++)
00518               new_ind_vector.GetData()[k + new_ptr_vector(ind_x) + ind_j + 1]
00519                 = working_vector.GetIndex()[k + ind_j];
00520 
00521             for (int k = 0; k < ind_j; k++)
00522               new_data_vector.GetData()[k + new_ptr_vector(ind_x)] =
00523                 working_vector.GetData()[k];
00524             new_data_vector.GetData()[new_ptr_vector(ind_x)  + ind_j]
00525               = X(ind_x);
00526             for (int k = 0; k < Nworking_vector - ind_j; k++)
00527               new_data_vector.GetData()[k + new_ptr_vector(ind_x) + ind_j + 1]
00528                 = working_vector.GetData()[k + ind_j];
00529           }
00530 
00531         line = ind_x + 1;
00532         working_vector.Nullify();
00533       }
00534     for (int k = 0; k < ptr_vector(m) -  ptr_vector(line); k++)
00535       new_ind_vector.GetData()[k + new_ptr_vector(line)] =
00536         M.GetInd()[k + ptr_vector(line)];
00537     for (int k = 0; k < ptr_vector(m) -  ptr_vector(line); k++)
00538       new_data_vector.GetData()[k + new_ptr_vector(line)] =
00539         M.GetData()[k + ptr_vector(line)];
00540 
00541     M.SetData(m, n, new_data_vector, new_ptr_vector, new_ind_vector);
00542     ptr_vector.Nullify();
00543     new_data_vector.Nullify();
00544     new_ind_vector.Nullify();
00545     new_ptr_vector.Nullify();
00546   }
00547 
00548 
00550 
00553   template<class T, class Prop, class Allocator>
00554   void ApplyPermutation(Matrix<T, Prop, RowMajor, Allocator>& A,
00555                         const Vector<int>& row_perm,
00556                         const Vector<int>& col_perm,
00557                         int starting_index)
00558   {
00559     Matrix<T, Prop, RowMajor, Allocator> A_copy = A;
00560 
00561     for (int i = 0; i < A.GetM(); i++)
00562       for (int j = 0; j < A.GetN(); j++)
00563         A(i, j) = A_copy(row_perm(i) - starting_index,
00564                          col_perm(j) - starting_index);
00565   }
00566 
00567 
00569 
00572   template<class T, class Prop, class Allocator>
00573   void ApplyPermutation(Matrix<T, Prop, ColMajor, Allocator>& A,
00574                         const Vector<int>& row_perm,
00575                         const Vector<int>& col_perm,
00576                         int starting_index)
00577   {
00578     Matrix<T, Prop, ColMajor, Allocator> A_copy = A;
00579 
00580     for (int j = 0; j < A.GetN(); j++)
00581       for (int i = 0; i < A.GetM(); i++)
00582         A(i, j) = A_copy(row_perm(i) - starting_index,
00583                          col_perm(j) - starting_index);
00584   }
00585 
00586 
00588 
00593   template<class T, class Prop, class Allocator>
00594   void ApplyInversePermutation(Matrix<T, Prop, RowMajor, Allocator>& A,
00595                                const Vector<int>& row_perm,
00596                                const Vector<int>& col_perm,
00597                                int starting_index)
00598   {
00599     Matrix<T, Prop, RowMajor, Allocator> A_copy = A;
00600 
00601     for (int i = 0; i < A.GetM(); i++)
00602       for (int j = 0; j < A.GetN(); j++)
00603         A(row_perm(i) - starting_index, col_perm(j) - starting_index)
00604           = A_copy(i, j);
00605   }
00606 
00607 
00609 
00614   template<class T, class Prop, class Allocator>
00615   void ApplyInversePermutation(Matrix<T, Prop, ColMajor, Allocator>& A,
00616                                const Vector<int>& row_perm,
00617                                const Vector<int>& col_perm,
00618                                int starting_index)
00619   {
00620     Matrix<T, Prop, ColMajor, Allocator> A_copy = A;
00621 
00622     for (int j = 0; j < A.GetN(); j++)
00623       for (int i = 0; i < A.GetM(); i++)
00624         A(row_perm(i) - starting_index, col_perm(j) - starting_index)
00625           = A_copy(i, j);
00626   }
00627 
00628 
00629 } // namespace Seldon.
00630 
00631 #define SELDON_FILE_FUNCTIONS_CXX
00632 #endif