computation/basic_functions/Functions_Vector.cxx

00001 // Copyright (C) 2003-2009 Marc Duruflé
00002 // Copyright (C) 2001-2009 Vivien Mallet
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_VECTOR_CXX
00024 
00025 /*
00026   Functions defined in this file:
00027 
00028   alpha X -> X
00029   Mlt(alpha, X)
00030 
00031   alpha X + Y -> Y
00032   Add(alpha, X, Y)
00033 
00034   X -> Y
00035   Copy(X, Y)
00036 
00037   X <-> Y
00038   Swap(X, Y)
00039 
00040   X.Y
00041   DotProd(X, Y)
00042   DotProdConj(X, Y)
00043 
00044   ||X||
00045   Norm1(X)
00046   Norm2(X)
00047   GetMaxAbsIndex(X)
00048 
00049   Omega X
00050   GenRot(x, y, cos, sin)
00051   ApplyRot(x, y, cos, sin)
00052 
00053 */
00054 
00055 namespace Seldon
00056 {
00057 
00058 
00060   // MLT //
00061 
00062 
00063   template <class T0,
00064             class T1, class Storage1, class Allocator1>
00065   void Mlt(const T0 alpha,
00066            Vector<T1, Storage1, Allocator1>& X)  throw()
00067   {
00068     X *= alpha;
00069   }
00070 
00071 
00072   // MLT //
00074 
00075 
00076 
00078   // ADD //
00079 
00080 
00081   template <class T0,
00082             class T1, class Storage1, class Allocator1,
00083             class T2, class Storage2, class Allocator2>
00084   void Add(const T0 alpha,
00085            const Vector<T1, Storage1, Allocator1>& X,
00086            Vector<T2, Storage2, Allocator2>& Y)  throw(WrongDim, NoMemory)
00087   {
00088     if (alpha != T0(0))
00089       {
00090         T1 alpha_ = alpha;
00091 
00092         int ma = X.GetM();
00093 
00094 #ifdef SELDON_CHECK_DIMENSIONS
00095         CheckDim(X, Y, "Add(alpha, X, Y)");
00096 #endif
00097 
00098         for (int i = 0; i < ma; i++)
00099           Y(i) += alpha_ * X(i);
00100       }
00101   }
00102 
00103 
00104   template <class T0,
00105             class T1, class Allocator1,
00106             class T2, class Allocator2>
00107   void Add(const T0 alpha,
00108            const Vector<T1, VectSparse, Allocator1>& X,
00109            Vector<T2, VectSparse, Allocator2>& Y)  throw(WrongDim, NoMemory)
00110   {
00111     if (alpha != T0(0))
00112       {
00113         Vector<T1, VectSparse, Allocator1> Xalpha = X;
00114         Xalpha *= alpha;
00115         Y.AddInteractionRow(Xalpha.GetSize(),
00116                             Xalpha.GetIndex(), Xalpha.GetData(), true);
00117       }
00118   }
00119 
00120 
00121   template <class T0,
00122             class T1, class Allocator1,
00123             class T2, class Allocator2>
00124   void Add(const T0 alpha,
00125            const Vector<T1, Collection, Allocator1>& X,
00126            Vector<T2, Collection, Allocator2>& Y)
00127   {
00128 
00129 #ifdef SELDON_CHECK_DIMENSIONS
00130     CheckDim(X, Y, "Add(X, Y)", "X + Y");
00131 #endif
00132 
00133     for (int i = 0; i < X.GetNvector(); i++)
00134       Add(alpha, X.GetVector(i), Y.GetVector(i));
00135   }
00136 
00137 
00138   template <class T0,
00139             class T1, template <class U1> class Allocator1,
00140             class T2, template <class U2> class Allocator2>
00141   void Add(const T0 alpha,
00142            const
00143            Vector<FloatDouble, DenseSparseCollection, Allocator1<T1> >& X,
00144            Vector<FloatDouble, DenseSparseCollection, Allocator2<T2> >& Y)
00145   {
00146 
00147 #ifdef SELDON_CHECK_DIMENSIONS
00148     CheckDim(X, Y, "Add(X, Y)");
00149 #endif
00150 
00151     Add(alpha, X.GetFloatDense(), Y.GetFloatDense());
00152     Add(alpha, X.GetFloatSparse(), Y.GetFloatSparse());
00153     Add(alpha, X.GetDoubleDense(), Y.GetDoubleDense());
00154     Add(alpha, X.GetDoubleSparse(), Y.GetDoubleSparse());
00155   }
00156 
00157 
00158   template <class T0,
00159             class T1, template <class U1> class Allocator1,
00160             class T2, class Storage2, class Allocator2>
00161   void Add(const T0 alpha,
00162            const
00163            Vector<FloatDouble, DenseSparseCollection, Allocator1<T1> >& X,
00164            Vector<T2, Storage2, Allocator2>& Y)  throw(WrongDim, NoMemory)
00165   {
00166     if (alpha != T0(0))
00167       {
00168         double alpha_ = alpha;
00169 
00170         int ma = X.GetM();
00171 
00172 #ifdef SELDON_CHECK_DIMENSIONS
00173         CheckDim(X, Y, "Add(alpha, X, Y)");
00174 #endif
00175 
00176         for (int i = 0; i < ma; i++)
00177           Y(i) += alpha_ * X(i);
00178 
00179       }
00180   }
00181 
00182 
00183   // ADD //
00185 
00186 
00187 
00189   // COPY //
00190 
00191 
00192   template <class T1, class Storage1, class Allocator1,
00193             class T2, class Storage2, class Allocator2>
00194   void Copy(const Vector<T1, Storage1, Allocator1>& X,
00195             Vector<T2, Storage2, Allocator2>& Y)
00196   {
00197     Y.Copy(X);
00198   }
00199 
00200 
00201   // COPY //
00203 
00204 
00205 
00207   // SWAP //
00208 
00209 
00210   template <class T, class Storage, class Allocator>
00211   void Swap(Vector<T, Storage, Allocator>& X,
00212             Vector<T, Storage, Allocator>& Y)
00213   {
00214     int nx = X.GetM();
00215     T* data = X.GetData();
00216     X.Nullify();
00217     X.SetData(Y.GetM(), Y.GetData());
00218     Y.Nullify();
00219     Y.SetData(nx, data);
00220   }
00221 
00222 
00223   template <class T, class Allocator>
00224   void Swap(Vector<T, VectSparse, Allocator>& X,
00225             Vector<T, VectSparse, Allocator>& Y)
00226   {
00227     int nx = X.GetM();
00228     T* data = X.GetData();
00229     int* index = X.GetIndex();
00230     X.Nullify();
00231     X.SetData(Y.GetM(), Y.GetData(), Y.GetIndex());
00232     Y.Nullify();
00233     Y.SetData(nx, data, index);
00234   }
00235 
00236 
00237   // SWAP //
00239 
00240 
00241 
00243   // DOTPROD //
00244 
00245 
00247   template<class T1, class Storage1, class Allocator1,
00248            class T2, class Storage2, class Allocator2>
00249   T1 DotProd(const Vector<T1, Storage1, Allocator1>& X,
00250              const Vector<T2, Storage2, Allocator2>& Y)
00251   {
00252     T1 value;
00253     SetComplexZero(value);
00254 
00255 #ifdef SELDON_CHECK_DIMENSIONS
00256     CheckDim(X, Y, "DotProd(X, Y)");
00257 #endif
00258 
00259     for (int i = 0; i < X.GetM(); i++)
00260       value += X(i) * Y(i);
00261 
00262     return value;
00263   }
00264 
00265 
00267   template<class T1, class Allocator1,
00268            class T2, class Allocator2>
00269   typename T1::value_type DotProd(const Vector<T1, Collection, Allocator1>& X,
00270                                   const Vector<T2, Collection, Allocator2>& Y)
00271   {
00272     typename T1::value_type value(0);
00273 
00274 #ifdef SELDON_CHECK_DIMENSIONS
00275     CheckDim(X, Y, "DotProd(X, Y)", "<X, Y>");
00276 #endif
00277 
00278     for (int i = 0; i < X.GetNvector(); i++)
00279       value += DotProd(X.GetVector(i), Y.GetVector(i));
00280     return value;
00281   }
00282 
00283 
00285   template<class T1, template <class U1> class Allocator1,
00286            class T2, template <class U2> class Allocator2>
00287   double
00288   DotProd(const
00289           Vector<FloatDouble, DenseSparseCollection, Allocator1<T1> >& X,
00290           const
00291           Vector<FloatDouble, DenseSparseCollection, Allocator2<T2> >& Y)
00292   {
00293 
00294 #ifdef SELDON_CHECK_DIMENSIONS
00295     CheckDim(X, Y, "DotProd(X, Y)");
00296 #endif
00297 
00298     double value(0.);
00299     value += DotProd(X.GetFloatDense(), Y.GetFloatDense());
00300     value += DotProd(X.GetFloatSparse(), Y.GetFloatSparse());
00301     value += DotProd(X.GetDoubleDense(), Y.GetDoubleDense());
00302     value += DotProd(X.GetDoubleSparse(), Y.GetDoubleSparse());
00303     return value;
00304   }
00305 
00306 
00308   template<class T1, class Storage1, class Allocator1,
00309            class T2, class Storage2, class Allocator2>
00310   T1 DotProdConj(const Vector<T1, Storage1, Allocator1>& X,
00311                  const Vector<T2, Storage2, Allocator2>& Y)
00312   {
00313     return DotProd(X, Y);
00314   }
00315 
00316 
00318   template<class T1, class Storage1, class Allocator1,
00319            class T2, class Storage2, class Allocator2>
00320   complex<T1> DotProdConj(const Vector<complex<T1>, Storage1, Allocator1>& X,
00321                           const Vector<T2, Storage2, Allocator2>& Y)
00322   {
00323     complex<T1> value;
00324     SetComplexZero(value);
00325 
00326 #ifdef SELDON_CHECK_DIMENSIONS
00327     CheckDim(X, Y, "DotProdConj(X, Y)");
00328 #endif
00329 
00330     for (int i = 0; i < X.GetM(); i++)
00331       value += conj(X(i)) * Y(i);
00332 
00333     return value;
00334   }
00335 
00336 
00338   template<class T1, class Allocator1,
00339            class T2, class Allocator2>
00340   T1 DotProd(const Vector<T1, VectSparse, Allocator1>& X,
00341              const Vector<T2, VectSparse, Allocator2>& Y)
00342   {
00343     T1 value;
00344     SetComplexZero(value);
00345 
00346     int size_x = X.GetSize();
00347     int size_y = Y.GetSize();
00348     int kx = 0, ky = 0, pos_x;
00349     while (kx < size_x)
00350       {
00351         pos_x = X.Index(kx);
00352         while (ky < size_y && Y.Index(ky) < pos_x)
00353           ky++;
00354 
00355         if (ky < size_y && Y.Index(ky) == pos_x)
00356           value += X.Value(kx) * Y.Value(ky);
00357 
00358         kx++;
00359       }
00360 
00361     return value;
00362   }
00363 
00364 
00366   template<class T1, class Allocator1,
00367            class T2, class Allocator2>
00368   complex<T1>
00369   DotProdConj(const Vector<complex<T1>, VectSparse, Allocator1>& X,
00370               const Vector<T2, VectSparse, Allocator2>& Y)
00371   {
00372     complex<T1> value(0, 0);
00373 
00374     int size_x = X.GetSize();
00375     int size_y = Y.GetSize();
00376     int kx = 0, ky = 0, pos_x;
00377     while (kx < size_x)
00378       {
00379         pos_x = X.Index(kx);
00380         while (ky < size_y && Y.Index(ky) < pos_x)
00381           ky++;
00382 
00383         if (ky < size_y && Y.Index(ky) == pos_x)
00384           value += conj(X.Value(kx)) * Y.Value(ky);
00385 
00386         kx++;
00387       }
00388 
00389     return value;
00390   }
00391 
00392 
00393   // DOTPROD //
00395 
00396 
00397 
00399   // NORM1 //
00400 
00401 
00402   template<class T1, class Storage1, class Allocator1>
00403   T1 Norm1(const Vector<T1, Storage1, Allocator1>& X)
00404   {
00405     T1 value(0);
00406 
00407     for (int i = 0; i < X.GetM(); i++)
00408       value += abs(X(i));
00409 
00410     return value;
00411   }
00412 
00413 
00414   template<class T1, class Storage1, class Allocator1>
00415   T1 Norm1(const Vector<complex<T1>, Storage1, Allocator1>& X)
00416   {
00417     T1 value(0);
00418 
00419     for (int i = 0; i < X.GetM(); i++)
00420       value += abs(X(i));
00421 
00422     return value;
00423   }
00424 
00425 
00426   template<class T1, class Allocator1>
00427   T1 Norm1(const Vector<T1, VectSparse, Allocator1>& X)
00428   {
00429     T1 value(0);
00430 
00431     for (int i = 0; i < X.GetSize(); i++)
00432       value += abs(X.Value(i));
00433 
00434     return value;
00435   }
00436 
00437 
00438   template<class T1, class Allocator1>
00439   T1 Norm1(const Vector<complex<T1>, VectSparse, Allocator1>& X)
00440   {
00441     T1 value(0);
00442 
00443     for (int i = 0; i < X.GetSize(); i++)
00444       value += abs(X.Value(i));
00445 
00446     return value;
00447   }
00448 
00449 
00450   // NORM1 //
00452 
00453 
00454 
00456   // NORM2 //
00457 
00458 
00459   template<class T1, class Storage1, class Allocator1>
00460   T1 Norm2(const Vector<T1, Storage1, Allocator1>& X)
00461   {
00462     T1 value(0);
00463 
00464     for (int i = 0; i < X.GetM(); i++)
00465       value += X(i) * X(i);
00466 
00467     return sqrt(value);
00468   }
00469 
00470 
00471   template<class T1, class Storage1, class Allocator1>
00472   T1 Norm2(const Vector<complex<T1>, Storage1, Allocator1>& X)
00473   {
00474     T1 value(0);
00475 
00476     for (int i = 0; i < X.GetM(); i++)
00477       value += real(X(i) * conj(X(i)));
00478 
00479     return sqrt(value);
00480   }
00481 
00482 
00483   template<class T1, class Allocator1>
00484   T1 Norm2(const Vector<T1, VectSparse, Allocator1>& X)
00485   {
00486     T1 value(0);
00487 
00488     for (int i = 0; i < X.GetSize(); i++)
00489       value += X.Value(i) * X.Value(i);
00490 
00491     return sqrt(value);
00492   }
00493 
00494 
00495   template<class T1, class Allocator1>
00496   T1 Norm2(const Vector<complex<T1>, VectSparse, Allocator1>& X)
00497   {
00498     T1 value(0);
00499 
00500     for (int i = 0; i < X.GetSize(); i++)
00501       value += real(X.Value(i) * conj(X.Value(i)));
00502 
00503     return sqrt(value);
00504   }
00505 
00506 
00507   // NORM2 //
00509 
00510 
00511 
00513   // GETMAXABSINDEX //
00514 
00515 
00516   template<class T, class Storage, class Allocator>
00517   int GetMaxAbsIndex(const Vector<T, Storage, Allocator>& X)
00518   {
00519     return X.GetNormInfIndex();
00520   }
00521 
00522 
00523   // GETMAXABSINDEX //
00525 
00526 
00527 
00529   // APPLYROT //
00530 
00531 
00533   template<class T>
00534   void GenRot(T& a_in, T& b_in, T& c_, T& s_)
00535   {
00536     // Old BLAS version.
00537     T roe;
00538     if (abs(a_in) > abs(b_in))
00539       roe = a_in;
00540     else
00541       roe = b_in;
00542 
00543     T scal = abs(a_in) + abs(b_in);
00544     T r, z;
00545     if (scal != T(0))
00546       {
00547         T a_scl = a_in / scal;
00548         T b_scl = b_in / scal;
00549         r = scal * sqrt(a_scl * a_scl + b_scl * b_scl);
00550         if (roe < T(0))
00551           r *= T(-1);
00552 
00553         c_ = a_in / r;
00554         s_ = b_in / r;
00555         z = T(1);
00556         if (abs(a_in) > abs(b_in))
00557           z = s_;
00558         else if (abs(b_in) >= abs(a_in) && c_ != T(0))
00559           z = T(1) / c_;
00560       }
00561     else
00562       {
00563         c_ = T(1);
00564         s_ = T(0);
00565         r = T(0);
00566         z = T(0);
00567       }
00568     a_in = r;
00569     b_in = z;
00570   }
00571 
00572 
00574   template<class T>
00575   void GenRot(complex<T>& a_in, complex<T>& b_in, T& c_, complex<T>& s_)
00576   {
00577 
00578     T a = abs(a_in), b = abs(b_in);
00579     if (a == T(0))
00580       {
00581         c_ = T(0);
00582         s_ = complex<T>(1, 0);
00583         a_in = b_in;
00584       }
00585     else
00586       {
00587         T scale = a + b;
00588         T a_scal = abs(a_in / scale);
00589         T b_scal = abs(b_in / scale);
00590         T norm = sqrt(a_scal * a_scal + b_scal * b_scal) * scale;
00591 
00592         c_ = a / norm;
00593         complex<T> alpha = a_in / a;
00594         s_ = alpha * conj(b_in) / norm;
00595         a_in = alpha * norm;
00596       }
00597     b_in = complex<T>(0, 0);
00598   }
00599 
00600 
00602   template<class T>
00603   void ApplyRot(T& x, T& y, const T c_, const T s_)
00604   {
00605     T temp = c_ * x + s_ * y;
00606     y = c_ * y - s_ * x;
00607     x = temp;
00608   }
00609 
00610 
00612   template<class T>
00613   void ApplyRot(complex<T>& x, complex<T>& y,
00614                 const T& c_, const complex<T>& s_)
00615   {
00616     complex<T> temp = s_ * y + c_ * x;
00617     y = -conj(s_) * x + c_ * y;
00618     x = temp;
00619   }
00620 
00621 
00622   // APPLYROT //
00624 
00625 
00626 
00628   // CHECKDIM //
00629 
00630 
00632 
00642   template <class T0, class Storage0, class Allocator0,
00643             class T1, class Storage1, class Allocator1>
00644   void CheckDim(const Vector<T0, Storage0, Allocator0>& X,
00645                 const Vector<T1, Storage1, Allocator1>& Y,
00646                 string function = "", string op = "X + Y")
00647   {
00648     if (X.GetLength() != Y.GetLength())
00649       throw WrongDim(function, string("Operation ") + op
00650                      + string(" not permitted:")
00651                      + string("\n     X (") + to_str(&X) + string(") is a ")
00652                      + string("vector of length ") + to_str(X.GetLength())
00653                      + string(";\n     Y (") + to_str(&Y) + string(") is a ")
00654                      + string("vector of length ") + to_str(Y.GetLength())
00655                      + string("."));
00656   }
00657 
00658 
00660 
00670   template <class T0, class Allocator0,
00671             class T1, class Allocator1>
00672   void CheckDim(const Vector<T0, Vect_Sparse, Allocator0>& X,
00673                 const Vector<T1, Vect_Sparse, Allocator1>& Y,
00674                 string function = "", string op = "X + Y")
00675   {
00676     // The dimension of a Vector<Vect_Sparse> is infinite,
00677     // so no vector dimension checking has to be done.
00678   }
00679 
00680 
00682 
00692   template <class T0, class Allocator0,
00693             class T1, class Allocator1>
00694   void CheckDim(const Vector<T0, Collection, Allocator0>& X,
00695                 const Vector<T1, Collection, Allocator1>& Y,
00696                 string function = "", string op = "X + Y")
00697   {
00698     if (X.GetLength() != Y.GetLength())
00699       throw WrongDim(function, string("Operation ") + op
00700                      + string(" not permitted:")
00701                      + string("\n     X (") + to_str(&X) + string(") is a ")
00702                      + string("vector of length ") + to_str(X.GetLength())
00703                      + string(";\n     Y (") + to_str(&Y) + string(") is a ")
00704                      + string("vector of length ") + to_str(Y.GetLength())
00705                      + string("."));
00706 
00707     if (X.GetNvector() != Y.GetNvector())
00708       throw WrongDim(function, string("Operation ") + op
00709                      + string(" not permitted:")
00710                      + string("\n     X (") + to_str(&X) + string(") is a ")
00711                      + string("vector of length ") + to_str(X.GetNvector())
00712                      + string(";\n     Y (") + to_str(&Y) + string(") is a ")
00713                      + string("vector of length ") + to_str(Y.GetNvector())
00714                      + string("."));
00715   }
00716 
00717 
00719 
00729   template <class T0, class Allocator0, class Allocator00,
00730             class T1, class Allocator1, class Allocator11>
00731   void CheckDim(const Vector<Vector<T0, Vect_Sparse, Allocator0>,
00732                 Collection, Allocator00>& X,
00733                 const Vector<Vector<T1, Vect_Sparse, Allocator1>,
00734                 Collection, Allocator11>& Y,
00735                 string function = "", string op = "X + Y")
00736   {
00737     if (X.GetNvector() != Y.GetNvector())
00738       throw WrongDim(function, string("Operation ") + op
00739                      + string(" not permitted:")
00740                      + string("\n     X (") + to_str(&X) + string(") is a ")
00741                      + string("vector of length ") + to_str(X.GetNvector())
00742                      + string(";\n     Y (") + to_str(&Y) + string(") is a ")
00743                      + string("vector of length ") + to_str(Y.GetNvector())
00744                      + string("."));
00745   }
00746 
00747 
00749 
00759   template <class T0, class Allocator0,
00760             class T1, class Allocator1>
00761   void CheckDim(const Vector<T0, VectFull, Allocator0>& X,
00762                 Vector<T1, Collection, Allocator1>& Y,
00763                 string function = "", string op = "X + Y")
00764   {
00765     if (X.GetLength() != Y.GetM())
00766       throw WrongDim(function, string("Operation ") + op
00767                      + string(" not permitted:")
00768                      + string("\n     X (") + to_str(&X) + string(") is a ")
00769                      + string("vector of length ") + to_str(X.GetLength())
00770                      + string(";\n     Y (") + to_str(&Y) + string(") is a ")
00771                      + string("vector of length ") + to_str(Y.GetM())
00772                      + string("."));
00773   }
00774 
00775 
00777 
00787   template <class T0, template <class U0> class Allocator0,
00788             class T1, template <class U1> class Allocator1>
00789   void
00790   CheckDim(const
00791            Vector<FloatDouble, DenseSparseCollection, Allocator0<T0> >& X,
00792            const
00793            Vector<FloatDouble, DenseSparseCollection, Allocator1<T1> >& Y,
00794            string function = "", string op = "X + Y")
00795   {
00796     if (X.GetNvector() != Y.GetNvector())
00797       throw WrongDim(function, string("Operation ") + op
00798                      + string(" not permitted:")
00799                      + string("\n     X (") + to_str(&X) + string(") is a ")
00800                      + string("vector of length ") + to_str(X.GetNvector())
00801                      + string(";\n     Y (") + to_str(&Y) + string(") is a ")
00802                      + string("vector of length ") + to_str(Y.GetNvector())
00803                      + string("."));
00804   }
00805 
00806 
00807   // CHECKDIM //
00809 
00810 
00811 
00813   // CONJUGATE //
00814 
00815 
00817   template<class T, class Prop, class Allocator>
00818   void Conjugate(Vector<T, Prop, Allocator>& X)
00819   {
00820     for (int i = 0; i < X.GetM(); i++)
00821       X(i) = conj(X(i));
00822   }
00823 
00824 
00826   template<class T, class Allocator>
00827   void Conjugate(Vector<T, VectSparse, Allocator>& X)
00828   {
00829     for (int i = 0; i < X.GetSize(); i++)
00830       X.Value(i) = conj(X.Value(i));
00831   }
00832 
00833 
00834   // CONJUGATE //
00836 
00837 
00838 } // namespace Seldon.
00839 
00840 #define SELDON_FILE_FUNCTIONS_VECTOR_CXX
00841 #endif