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 
00031   template <class T0, class Allocator0, class T1, class Allocator1>
00032   void GetRow(const Matrix<T0, General, RowSparse, Allocator0>& M,
00033               int i, Vector<T1, Vect_Sparse, Allocator1>& X)
00034   {
00035 #ifdef SELDON_CHECK_BOUNDS
00036     int m = M.GetM();
00037     if (i < 0 || i >= m)
00038       throw WrongIndex("GetRow()",
00039                        string("Index should be in [0, ") + to_str(m - 1)
00040                        + "], but is equal to " + to_str(i) + ".");
00041 #endif
00042 
00043     int* ptr = M.GetPtr();
00044     int* ind = M.GetInd();
00045     double* data = M.GetData();
00046     int size_row = ptr[i+1] - ptr[i];
00047 
00048     X.Reallocate(size_row);
00049     int shift = ptr[i];
00050     for (int j = 0; j < size_row; j++)
00051       {
00052         X.Index(j) = ind[shift + j];
00053         X.Value(j) = data[shift + j];
00054       }
00055   }
00056 
00057 
00058   template <class T0, class Prop0, class Storage0, class Allocator0,
00059             class T1, class Storage1, class Allocator1>
00060   void GetRow(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
00061               int i, Vector<T1, Storage1, Allocator1>& X)
00062   {
00063     X.Reallocate(M.GetN());
00064     for (int j = 0; j < M.GetN(); j++)
00065       X(j) = M(i, j);
00066   }
00067 
00068 
00069   template <class T0, class Allocator0, class T1, class Allocator1>
00070   void GetCol(const Matrix<T0, General, RowSparse, Allocator0>& M,
00071               int j, Vector<T1, Vect_Sparse, Allocator1>& X)
00072   {
00073 #ifdef SELDON_CHECK_BOUNDS
00074     int n = M.GetN();
00075     if (j < 0 || j >= n)
00076       throw WrongIndex("GetCol()",
00077                        string("Index should be in [0, ") + to_str(n - 1)
00078                        + "], but is equal to " + to_str(j) + ".");
00079 #endif
00080 
00081     int* ptr = M.GetPtr();
00082     int* ind = M.GetInd();
00083     double* data = M.GetData();
00084     int m = M.GetM();
00085     Vector<int> index;
00086     Vector<double> value;
00087 
00088     for (int i = 0; i < m; i++)
00089       for (int k = ptr[i]; k < ptr[i+1]; k++)
00090         if (ind[k] == j)
00091           {
00092             index.PushBack(i);
00093             value.PushBack(data[k]);
00094           }
00095 
00096     X.SetData(value, index);
00097   }
00098 
00099 
00100   template <class T0, class Prop0, class Storage0, class Allocator0,
00101             class T1, class Storage1, class Allocator1>
00102   void GetCol(const Matrix<T0, Prop0, Storage0, Allocator0>& M,
00103               int j, Vector<T1, Storage1, Allocator1>& X)
00104   {
00105     X.Reallocate(M.GetM());
00106     for (int i = 0; i < M.GetM(); i++)
00107       X(i) = M(i, j);
00108   }
00109 
00110 
00111   template <class T0, class Prop0, class Storage0, class Allocator0,
00112             class T1, class Storage1, class Allocator1>
00113   void SetRow(const Vector<T1, Storage1, Allocator1>& X,
00114               int i, Matrix<T0, Prop0, Storage0, Allocator0>& M)
00115   {
00116     for (int j = 0; j < M.GetN(); j++)
00117       M(i, j) = X(j);
00118   }
00119 
00120 
00121   template <class T0, class Allocator0, class T1, class Allocator1>
00122   void SetRow(const Vector<T1, Vect_Sparse, Allocator1>& X,
00123               int i, Matrix<T0, General, RowSparse, Allocator0>& M)
00124   {
00125     int m = M.GetM();
00126     int n = M.GetN();
00127     int nnz = M.GetDataSize();
00128     int Nx = X.GetSize();
00129 
00130 #ifdef SELDON_CHECK_BOUNDS
00131     if (i < 0 || i >= m)
00132       throw WrongIndex("SetRow(Vector, int, Matrix<RowSparse>)",
00133                        string("Index should be in [0, ") + to_str(m - 1)
00134                        + "], but is equal to " + to_str(i) + ".");
00135 #endif
00136 
00137     int *ptr_vector =  M.GetPtr();
00138     int ptr_i0 =  ptr_vector[i], ptr_i1 = ptr_vector[i + 1];
00139     int row_size_difference = Nx - ptr_i1 + ptr_i0;
00140 
00141     if (row_size_difference == 0)
00142       {
00143         for (int k = 0; k < Nx; k++)
00144           M.GetInd()[k + ptr_i0] = X.Index(k);
00145         for (int k = 0; k < Nx; k++)
00146           M.GetData()[k + ptr_i0] = X.Value(k);
00147         return;
00148       }
00149 
00150     Vector<int, VectFull, CallocAlloc<int> >
00151       new_ind_vector(nnz + row_size_difference);
00152     for (int k = 0; k <  ptr_i0; k++)
00153       new_ind_vector(k) = M.GetInd()[k];
00154     for (int k = 0; k < Nx; k++)
00155       new_ind_vector(k + ptr_i0) = X.Index(k);
00156     for (int k = 0; k < nnz - ptr_i1; k++)
00157       new_ind_vector(k + ptr_i0 + Nx) =  M.GetInd()[k + ptr_i1];
00158 
00159     Vector<T1, VectFull, Allocator0 >
00160       new_data_vector(nnz + row_size_difference);
00161     for (int k = 0; k <  ptr_i0; k++)
00162       new_data_vector(k) = M.GetData()[k];
00163     for (int k = 0; k < Nx; k++)
00164       new_data_vector(k + ptr_i0) = X.Value(k);
00165     for (int k = 0; k < nnz - ptr_i1; k++)
00166       new_data_vector(k + ptr_i0 + Nx) =  M.GetData()[k + ptr_i1];
00167 
00168     Vector<int, VectFull, CallocAlloc<int> > new_ptr_vector(m + 1);
00169     for (int j = 0; j < i + 1; j++)
00170       new_ptr_vector(j) = ptr_vector[j];
00171     for (int j = i + 1; j < m+1; j++)
00172       new_ptr_vector(j) =  ptr_vector[j] + row_size_difference;
00173 
00174     M.SetData(m, n, new_data_vector, new_ptr_vector, new_ind_vector);
00175   }
00176 
00177 
00178   template <class T0, class Prop0, class Storage0, class Allocator0,
00179             class T1, class Storage1, class Allocator1>
00180   void SetCol(const Vector<T1, Storage1, Allocator1>& X,
00181               int j, Matrix<T0, Prop0, Storage0, Allocator0>& M)
00182   {
00183     for (int i = 0; i < M.GetM(); i++)
00184       M(i, j) = X(i);
00185   }
00186 
00187 
00188   template <class T0, class Allocator0, class T1, class Allocator1>
00189   void SetCol(const Vector<T1, VectSparse, Allocator1>& X,
00190               int j, Matrix<T0, General, RowSparse, Allocator0>& M)
00191   {
00192     int m = M.GetM();
00193     int n = M.GetN();
00194     int nnz = M.GetDataSize();
00195     int Nx = X.GetSize();
00196 
00197 #ifdef SELDON_CHECK_BOUNDS
00198     if (j < 0 || j >= n)
00199       throw WrongIndex("SetCol(Vector, int, Matrix<RowSparse>)",
00200                        string("Index should be in [0, ") + to_str(n - 1)
00201                        + "], but is equal to " + to_str(j) + ".");
00202 #endif
00203 
00204     // The column to be changed.
00205     Vector<T1, VectSparse, Allocator1> column_j;
00206     GetCol(M, j, column_j);
00207     int Ncolumn_j = column_j.GetSize();
00208     int column_size_difference = Nx - Ncolumn_j;
00209 
00210     // Built a vector indexed with the rows of column_j and X.
00211     Vector<int, Vect_Sparse> column_j_mask;
00212     Vector<int> index_j(Ncolumn_j);
00213     Vector<int> value_j(Ncolumn_j);
00214     for (int p = 0; p < Ncolumn_j; p++)
00215       index_j(p) = column_j.Index(p);
00216     value_j.Fill(-1);
00217     column_j_mask.SetData(value_j, index_j);
00218     value_j.Nullify();
00219     index_j.Nullify();
00220     Vector<int, Vect_Sparse> X_mask;
00221     Vector<int> index_x(Nx);
00222     Vector<int> value_x(Nx);
00223     for (int p = 0; p < Nx; p++)
00224       index_x(p) = X.Index(p);
00225     value_x.Fill(1);
00226     X_mask.SetData(value_x, index_x);
00227     value_x.Nullify();
00228     index_x.Nullify();
00229     X_mask.AddInteractionRow(column_j_mask.GetSize(),
00230                              column_j_mask.GetIndex(),
00231                              column_j_mask.GetData(), true);
00232 
00233     // Built the new pointer vector.
00234     Vector<int, VectFull, CallocAlloc<int> > ptr_vector;
00235     ptr_vector.SetData(m + 1, M.GetPtr());
00236     Vector<int, VectFull, CallocAlloc<int> > new_ptr_vector(m + 1);
00237     new_ptr_vector.Zero();
00238     for (int p = 0; p < X_mask.GetSize(); p++)
00239       new_ptr_vector(X_mask.Index(p) + 1) = X_mask.Value(p);
00240     for (int p = 0; p < m; p++)
00241       new_ptr_vector(p + 1) += new_ptr_vector(p);
00242 
00243     Add(1, ptr_vector, new_ptr_vector);
00244 
00245     // Built the new index and the new data vectors row by row.
00246     Vector<int, VectFull, CallocAlloc<int> >
00247       new_ind_vector(nnz + column_size_difference);
00248     Vector<T0, VectFull, Allocator0>
00249       new_data_vector(nnz + column_size_difference);
00250 
00251     Vector<T0, Vect_Sparse, Allocator0> working_vector;
00252     int Nworking_vector;
00253 
00254     int line = 0;
00255     for (int interaction = 0; interaction < X_mask.GetSize(); interaction++)
00256       {
00257         int ind_x =  X_mask.Index(interaction);
00258         for (int k = 0; k < ptr_vector(ind_x) -  ptr_vector(line); k++)
00259           new_ind_vector.GetData()[k + new_ptr_vector(line)] =
00260             M.GetInd()[k + ptr_vector(line)];
00261         for (int k = 0; k < ptr_vector(ind_x) -  ptr_vector(line); k++)
00262           new_data_vector.GetData()[k + new_ptr_vector(line)] =
00263             M.GetData()[k + ptr_vector(line)];
00264 
00265         int ind_j;
00266         Nworking_vector = ptr_vector(ind_x + 1) - ptr_vector(ind_x);
00267         working_vector.SetData(Nworking_vector,
00268                                M.GetData() + ptr_vector(ind_x),
00269                                M.GetInd() + ptr_vector(ind_x));
00270         switch(X_mask.Value(interaction))
00271           {
00272             // Collision.
00273           case 0:
00274             working_vector(j) = X(ind_x);
00275             for (int k = 0; k < Nworking_vector; k++)
00276               new_ind_vector.GetData()[k + new_ptr_vector(ind_x)] =
00277                 working_vector.GetIndex()[k];
00278             for (int k = 0; k < Nworking_vector; k++)
00279               new_data_vector.GetData()[k + new_ptr_vector(ind_x)] =
00280                 working_vector.GetData()[k];
00281             break;
00282 
00283             // Suppression.
00284           case -1:
00285             ind_j = 0;
00286             while (ind_j < Nworking_vector &&
00287                    working_vector.Index(ind_j) != j)
00288               ind_j++;
00289 
00290             for (int k = 0; k < ind_j; k++)
00291               new_ind_vector.GetData()[k + new_ptr_vector(ind_x)] =
00292                 working_vector.GetIndex()[k];
00293             for (int k = 0; k < Nworking_vector - ind_j - 1; k++)
00294               new_ind_vector.GetData()[k + new_ptr_vector(ind_x) + ind_j] =
00295                 working_vector.GetIndex()[k + ind_j + 1];
00296 
00297             for (int k = 0; k < ind_j; k++)
00298               new_data_vector.GetData()[k + new_ptr_vector(ind_x)] =
00299                 working_vector.GetData()[k];
00300             for (int k = 0; k < Nworking_vector - ind_j - 1; k++)
00301               new_data_vector.GetData()[k + new_ptr_vector(ind_x) + ind_j] =
00302                 working_vector.GetData()[k + ind_j + 1];
00303             break;
00304 
00305             // Addition.
00306           case 1:
00307             ind_j = 0;
00308             while (ind_j < Nworking_vector &&
00309                    working_vector.Index(ind_j) < j)
00310               ind_j++;
00311             for (int k = 0; k < ind_j; k++)
00312               new_ind_vector.GetData()[k + new_ptr_vector(ind_x)] =
00313                 working_vector.GetIndex()[k];
00314             new_ind_vector.GetData()[new_ptr_vector(ind_x) + ind_j] = j;
00315             for (int k = 0; k < Nworking_vector - ind_j; k++)
00316               new_ind_vector.GetData()[k + new_ptr_vector(ind_x) + ind_j + 1]
00317                 = working_vector.GetIndex()[k + ind_j];
00318 
00319             for (int k = 0; k < ind_j; k++)
00320               new_data_vector.GetData()[k + new_ptr_vector(ind_x)] =
00321                 working_vector.GetData()[k];
00322             new_data_vector.GetData()[new_ptr_vector(ind_x)  + ind_j]
00323               = X(ind_x);
00324             for (int k = 0; k < Nworking_vector - ind_j; k++)
00325               new_data_vector.GetData()[k + new_ptr_vector(ind_x) + ind_j + 1]
00326                 = working_vector.GetData()[k + ind_j];
00327           }
00328 
00329         line = ind_x + 1;
00330         working_vector.Nullify();
00331       }
00332     for (int k = 0; k < ptr_vector(m) -  ptr_vector(line); k++)
00333       new_ind_vector.GetData()[k + new_ptr_vector(line)] =
00334         M.GetInd()[k + ptr_vector(line)];
00335     for (int k = 0; k < ptr_vector(m) -  ptr_vector(line); k++)
00336       new_data_vector.GetData()[k + new_ptr_vector(line)] =
00337         M.GetData()[k + ptr_vector(line)];
00338 
00339     M.SetData(m, n, new_data_vector, new_ptr_vector, new_ind_vector);
00340     ptr_vector.Nullify();
00341     new_data_vector.Nullify();
00342     new_ind_vector.Nullify();
00343     new_ptr_vector.Nullify();
00344   }
00345 
00346 
00348 
00351   template<class T, class Prop, class Allocator>
00352   void ApplyPermutation(Matrix<T, Prop, RowMajor, Allocator>& A,
00353                         const Vector<int>& row_perm,
00354                         const Vector<int>& col_perm,
00355                         int starting_index)
00356   {
00357     Matrix<T, Prop, RowMajor, Allocator> A_copy = A;
00358 
00359     for (int i = 0; i < A.GetM(); i++)
00360       for (int j = 0; j < A.GetN(); j++)
00361         A(i, j) = A_copy(row_perm(i) - starting_index,
00362                          col_perm(j) - starting_index);
00363   }
00364 
00365 
00367 
00370   template<class T, class Prop, class Allocator>
00371   void ApplyPermutation(Matrix<T, Prop, ColMajor, Allocator>& A,
00372                         const Vector<int>& row_perm,
00373                         const Vector<int>& col_perm,
00374                         int starting_index)
00375   {
00376     Matrix<T, Prop, ColMajor, Allocator> A_copy = A;
00377 
00378     for (int j = 0; j < A.GetN(); j++)
00379       for (int i = 0; i < A.GetM(); i++)
00380         A(i, j) = A_copy(row_perm(i) - starting_index,
00381                          col_perm(j) - starting_index);
00382   }
00383 
00384 
00386 
00391   template<class T, class Prop, class Allocator>
00392   void ApplyInversePermutation(Matrix<T, Prop, RowMajor, Allocator>& A,
00393                                const Vector<int>& row_perm,
00394                                const Vector<int>& col_perm,
00395                                int starting_index)
00396   {
00397     Matrix<T, Prop, RowMajor, Allocator> A_copy = A;
00398 
00399     for (int i = 0; i < A.GetM(); i++)
00400       for (int j = 0; j < A.GetN(); j++)
00401         A(row_perm(i) - starting_index, col_perm(j) - starting_index)
00402           = A_copy(i, j);
00403   }
00404 
00405 
00407 
00412   template<class T, class Prop, class Allocator>
00413   void ApplyInversePermutation(Matrix<T, Prop, ColMajor, Allocator>& A,
00414                                const Vector<int>& row_perm,
00415                                const Vector<int>& col_perm,
00416                                int starting_index)
00417   {
00418     Matrix<T, Prop, ColMajor, Allocator> A_copy = A;
00419 
00420     for (int j = 0; j < A.GetN(); j++)
00421       for (int i = 0; i < A.GetM(); i++)
00422         A(row_perm(i) - starting_index, col_perm(j) - starting_index)
00423           = A_copy(i, j);
00424   }
00425 
00426 
00427 } // namespace Seldon.
00428 
00429 #define SELDON_FILE_FUNCTIONS_CXX
00430 #endif