vector/Vector.cxx

00001 // Copyright (C) 2001-2009 Vivien Mallet
00002 // Copyright (C) 2003-2009 Marc Duruflé
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_VECTOR_CXX
00022 
00023 #include "Vector.hxx"
00024 
00025 namespace Seldon
00026 {
00027 
00028 
00030   // C_VECTOR_BASE //
00032 
00033 
00034   /****************
00035    * CONSTRUCTORS *
00036    ****************/
00037 
00038 
00040 
00043   template <class T, class Allocator>
00044   inline Vector_Base<T, Allocator>::Vector_Base()
00045   {
00046     m_ = 0;
00047     data_ = NULL;
00048   }
00049 
00050 
00052 
00056   template <class T, class Allocator>
00057   inline Vector_Base<T, Allocator>::Vector_Base(int i)
00058   {
00059     m_ = i;
00060     data_ = NULL;
00061   }
00062 
00063 
00065 
00069   template <class T, class Allocator>
00070   inline Vector_Base<T, Allocator>::
00071   Vector_Base(const Vector_Base<T, Allocator>& A)
00072   {
00073     m_ = A.GetM();
00074     data_ = NULL;
00075   }
00076 
00077 
00078   /**************
00079    * DESTRUCTOR *
00080    **************/
00081 
00082 
00084   template <class T, class Allocator>
00085   inline Vector_Base<T, Allocator>::~Vector_Base()
00086   {
00087 
00088 #ifdef SELDON_CHECK_MEMORY
00089     try
00090       {
00091 #endif
00092 
00093         if (data_ != NULL)
00094           {
00095             vect_allocator_.deallocate(data_, m_);
00096             m_ = 0;
00097             data_ = NULL;
00098           }
00099 
00100 #ifdef SELDON_CHECK_MEMORY
00101       }
00102     catch (...)
00103       {
00104         m_ = 0;
00105         data_ = NULL;
00106       }
00107 #endif
00108 
00109   }
00110 
00111 
00112   /*******************
00113    * BASIC FUNCTIONS *
00114    *******************/
00115 
00116 
00118 
00121   template <class T, class Allocator>
00122   int Vector_Base<T, Allocator>::GetM() const
00123   {
00124     return m_;
00125   }
00126 
00127 
00129 
00132   template <class T, class Allocator>
00133   int Vector_Base<T, Allocator>::GetLength() const
00134   {
00135     return m_;
00136   }
00137 
00138 
00140 
00143   template <class T, class Allocator>
00144   int Vector_Base<T, Allocator>::GetSize() const
00145   {
00146     return m_;
00147   }
00148 
00149 
00151 
00154   template <class T, class Allocator>
00155   typename Vector_Base<T, Allocator>::pointer
00156   Vector_Base<T, Allocator>::GetData() const
00157   {
00158     return data_;
00159   }
00160 
00161 
00163 
00166   template <class T, class Allocator>
00167   typename Vector_Base<T, Allocator>::const_pointer
00168   Vector_Base<T, Allocator>::GetDataConst() const
00169   {
00170     return reinterpret_cast<typename Vector_Base<T,
00171       Allocator>::const_pointer>(data_);
00172   }
00173 
00174 
00176 
00179   template <class T, class Allocator>
00180   void* Vector_Base<T, Allocator>::GetDataVoid() const
00181   {
00182     return reinterpret_cast<void*>(data_);
00183   }
00184 
00185 
00187 
00190   template <class T, class Allocator>
00191   const void* Vector_Base<T, Allocator>::GetDataConstVoid() const
00192   {
00193     return reinterpret_cast<const void*>(data_);
00194   }
00195 
00196 
00198   // VECTOR<VECT_FULL> //
00200 
00201 
00202   /****************
00203    * CONSTRUCTORS *
00204    ****************/
00205 
00206 
00208 
00211   template <class T, class Allocator>
00212   Vector<T, VectFull, Allocator>::Vector()  throw():
00213     Vector_Base<T, Allocator>()
00214   {
00215   }
00216 
00217 
00219 
00222   template <class T, class Allocator>
00223   Vector<T, VectFull, Allocator>::Vector(int i):
00224     Vector_Base<T, Allocator>(i)
00225   {
00226 
00227 #ifdef SELDON_CHECK_MEMORY
00228     try
00229       {
00230 #endif
00231 
00232         this->data_ = this->vect_allocator_.allocate(i, this);
00233 
00234 #ifdef SELDON_CHECK_MEMORY
00235       }
00236     catch (...)
00237       {
00238         this->m_ = 0;
00239         this->data_ = NULL;
00240       }
00241     if (this->data_ == NULL)
00242       this->m_ = 0;
00243     if (this->data_ == NULL && i != 0)
00244       throw NoMemory("Vector<VectFull>::Vector(int)",
00245                      string("Unable to allocate memory for a vector of size ")
00246                      + to_str(i*sizeof(T)) + " bytes ("
00247                      + to_str(i) + " elements).");
00248 #endif
00249 
00250   }
00251 
00252 
00254 
00264   template <class T, class Allocator>
00265   Vector<T, VectFull, Allocator>
00266   ::Vector(int i, typename Vector<T, VectFull, Allocator>::pointer data):
00267     Vector_Base<T, Allocator>()
00268   {
00269     SetData(i, data);
00270   }
00271 
00272 
00274 
00277   template <class T, class Allocator>
00278   Vector<T, VectFull, Allocator>::
00279   Vector(const Vector<T, VectFull, Allocator>& V):
00280     Vector_Base<T, Allocator>(V)
00281   {
00282 
00283 #ifdef SELDON_CHECK_MEMORY
00284     try
00285       {
00286 #endif
00287 
00288         this->data_ = this->vect_allocator_.allocate(V.GetM(), this);
00289 
00290 #ifdef SELDON_CHECK_MEMORY
00291       }
00292     catch (...)
00293       {
00294         this->m_ = 0;
00295         this->data_ = NULL;
00296       }
00297     if (this->data_ == NULL)
00298       this->m_ = 0;
00299     if (this->data_ == NULL && V.GetM() != 0)
00300       throw NoMemory("Vector<VectFull>::Vector(Vector<VectFull>&)",
00301                      string("Unable to allocate memory for a vector of size ")
00302                      + to_str(V.GetM()*sizeof(T)) + " bytes ("
00303                      + to_str(V.GetM()) + " elements).");
00304 #endif
00305 
00306     this->vect_allocator_.memorycpy(this->data_, V.GetData(), V.GetM());
00307 
00308   }
00309 
00310 
00311   /**************
00312    * DESTRUCTOR *
00313    **************/
00314 
00315 
00317   template <class T, class Allocator>
00318   Vector<T, VectFull, Allocator>::~Vector()
00319   {
00320   }
00321 
00322 
00323   /*********************
00324    * MEMORY MANAGEMENT *
00325    *********************/
00326 
00327 
00329 
00333   template <class T, class Allocator>
00334   inline void Vector<T, VectFull, Allocator>::Clear()
00335   {
00336     this->~Vector();
00337   }
00338 
00339 
00341 
00347   template <class T, class Allocator>
00348   inline void Vector<T, VectFull, Allocator>::Reallocate(int i)
00349   {
00350 
00351     if (i != this->m_)
00352       {
00353 
00354         this->m_ = i;
00355 
00356 #ifdef SELDON_CHECK_MEMORY
00357         try
00358           {
00359 #endif
00360 
00361             this->data_ =
00362               reinterpret_cast<pointer>(this->vect_allocator_
00363                                         .reallocate(this->data_, i, this));
00364 
00365 #ifdef SELDON_CHECK_MEMORY
00366           }
00367         catch (...)
00368           {
00369             this->m_ = 0;
00370             this->data_ = NULL;
00371             return;
00372           }
00373         if (this->data_ == NULL)
00374           {
00375             this->m_ = 0;
00376             return;
00377           }
00378 #endif
00379 
00380       }
00381   }
00382 
00383 
00385 
00389   template <class T, class Allocator>
00390   inline void Vector<T, VectFull, Allocator>::Resize(int n)
00391   {
00392 
00393     if (n == this->m_)
00394       return;
00395 
00396     Vector<T, VectFull, Allocator> X_new(n);
00397     for (int i = 0; i < min(this->m_, n); i++)
00398       X_new(i) = this->data_[i];
00399 
00400     SetData(n, X_new.GetData());
00401     X_new.Nullify();
00402   }
00403 
00404 
00407 
00419   template <class T, class Allocator>
00420   inline void Vector<T, VectFull, Allocator>
00421   ::SetData(int i, typename Vector<T, VectFull, Allocator>::pointer data)
00422   {
00423     this->Clear();
00424 
00425     this->m_ = i;
00426 
00427     this->data_ = data;
00428   }
00429 
00430 
00432 
00443   template <class T, class Allocator>
00444   template <class Allocator0>
00445   inline void Vector<T, VectFull, Allocator>
00446   ::SetData(const Vector<T, VectFull, Allocator0>& V)
00447   {
00448     SetData(V.GetLength(), V.GetData());
00449   }
00450 
00451 
00453 
00458   template <class T, class Allocator>
00459   void Vector<T, VectFull, Allocator>::Nullify()
00460   {
00461     this->m_ = 0;
00462     this->data_ = NULL;
00463   }
00464 
00465 
00466   /**********************************
00467    * ELEMENT ACCESS AND AFFECTATION *
00468    **********************************/
00469 
00470 
00472 
00476   template <class T, class Allocator>
00477   inline typename Vector<T, VectFull, Allocator>::reference
00478   Vector<T, VectFull, Allocator>::operator() (int i)
00479   {
00480 
00481 #ifdef SELDON_CHECK_BOUNDS
00482     if (i < 0 || i >= this->m_)
00483       throw WrongIndex("Vector<VectFull>::operator()",
00484                        string("Index should be in [0, ") + to_str(this->m_-1)
00485                        + "], but is equal to " + to_str(i) + ".");
00486 #endif
00487 
00488     return this->data_[i];
00489   }
00490 
00491 
00493 
00497   template <class T, class Allocator>
00498   inline typename Vector<T, VectFull, Allocator>::const_reference
00499   Vector<T, VectFull, Allocator>::operator() (int i) const
00500   {
00501 
00502 #ifdef SELDON_CHECK_BOUNDS
00503     if (i < 0 || i >= this->m_)
00504       throw WrongIndex("Vector<VectFull>::operator()",
00505                        string("Index should be in [0, ") + to_str(this->m_-1)
00506                        + "], but is equal to " + to_str(i) + ".");
00507 #endif
00508 
00509     return this->data_[i];
00510   }
00511 
00512 
00514 
00519   template <class T, class Allocator>
00520   inline Vector<T, VectFull, Allocator>& Vector<T, VectFull, Allocator>
00521   ::operator= (const Vector<T, VectFull, Allocator>& X)
00522   {
00523     this->Copy(X);
00524 
00525     return *this;
00526   }
00527 
00528 
00530 
00535   template <class T, class Allocator>
00536   inline void Vector<T, VectFull, Allocator>
00537   ::Copy(const Vector<T, VectFull, Allocator>& X)
00538   {
00539     this->Reallocate(X.GetLength());
00540 
00541     this->vect_allocator_.memorycpy(this->data_, X.GetData(), this->m_);
00542   }
00543 
00544 
00546 
00549   template <class T, class Allocator> template<class T0>
00550   inline Vector<T, VectFull, Allocator>& Vector<T, VectFull, Allocator>
00551   ::operator*= (const T0& alpha)
00552   {
00553     for (int i = 0; i < this->m_; i++)
00554       this->data_[i] *= alpha;
00555 
00556     return *this;
00557   }
00558 
00559 
00561 
00566   template <class T, class Allocator>
00567   inline void Vector<T, VectFull, Allocator>::Append(const T& x)
00568   {
00569     int i = this->GetLength();
00570     this->Reallocate(i + 1);
00571     this->data_[i] = x;
00572   }
00573 
00574 
00576 
00579   template <class T, class Allocator> template<class T0>
00580   inline void Vector<T, VectFull, Allocator>::PushBack(const T0& x)
00581   {
00582     Resize(this->m_+1);
00583     this->data_[this->m_-1] = x;
00584   }
00585 
00586 
00588 
00591   template <class T, class Allocator> template<class Allocator0>
00592   inline void Vector<T, VectFull, Allocator>
00593   ::PushBack(const Vector<T, VectFull, Allocator0>& X)
00594   {
00595     int Nold = this->m_;
00596     Resize(this->m_ + X.GetM());
00597     for (int i = 0; i < X.GetM(); i++)
00598       this->data_[Nold+i] = X(i);
00599   }
00600 
00601 
00602   /*******************
00603    * BASIC FUNCTIONS *
00604    *******************/
00605 
00606 
00608 
00611   template <class T, class Allocator>
00612   int Vector<T, VectFull, Allocator>::GetDataSize()
00613   {
00614     return this->m_;
00615   }
00616 
00617 
00618   /************************
00619    * CONVENIENT FUNCTIONS *
00620    ************************/
00621 
00622 
00624 
00628   template <class T, class Allocator>
00629   void Vector<T, VectFull, Allocator>::Zero()
00630   {
00631     this->vect_allocator_.memoryset(this->data_, char(0),
00632                                     this->GetDataSize() * sizeof(value_type));
00633   }
00634 
00635 
00637   template <class T, class Allocator>
00638   void Vector<T, VectFull, Allocator>::Fill()
00639   {
00640     for (int i = 0; i < this->m_; i++)
00641       this->data_[i] = i;
00642   }
00643 
00644 
00646 
00649   template <class T, class Allocator>
00650   template <class T0>
00651   void Vector<T, VectFull, Allocator>::Fill(const T0& x)
00652   {
00653     for (int i = 0; i < this->m_; i++)
00654       this->data_[i] = x;
00655   }
00656 
00657 
00659 
00662   template <class T, class Allocator>
00663   template <class T0>
00664   Vector<T, VectFull, Allocator>&
00665   Vector<T, VectFull, Allocator>::operator= (const T0& x)
00666   {
00667     this->Fill(x);
00668 
00669     return *this;
00670   }
00671 
00672 
00674 
00677   template <class T, class Allocator>
00678   void Vector<T, VectFull, Allocator>::FillRand()
00679   {
00680     srand(time(NULL));
00681     for (int i = 0; i < this->m_; i++)
00682       this->data_[i] = rand();
00683   }
00684 
00685 
00687   template <class T, class Allocator>
00688   void Vector<T, VectFull, Allocator>::Print() const
00689   {
00690     for (int i = 0; i < this->GetLength(); i++)
00691       cout << (*this)(i) << "\t";
00692     cout << endl;
00693   }
00694 
00695 
00696   /*********
00697    * NORMS *
00698    *********/
00699 
00700 
00702 
00705   template <class T, class Allocator>
00706   typename Vector<T, VectFull, Allocator>::value_type
00707   Vector<T, VectFull, Allocator>::GetNormInf() const
00708   {
00709     value_type res = value_type(0);
00710     for (int i = 0; i < this->GetLength(); i++)
00711       {
00712         res = max(res, this->data_[i]);
00713         res = max(res, T(-this->data_[i]));
00714       }
00715 
00716     return res;
00717   }
00718 
00719 
00721 
00724   template <class T, class Allocator>
00725   int Vector<T, VectFull, Allocator>::GetNormInfIndex() const
00726   {
00727 
00728 #ifdef SELDON_CHECK_DIMENSIONS
00729     if (this->GetLength() == 0)
00730       throw WrongDim("Vector<VectFull>::GetNormInfIndex()",
00731                      "Vector is null.");
00732 #endif
00733 
00734     value_type res = value_type(0), temp;
00735     int j = 0;
00736     for (int i = 0; i < this->GetLength(); i++)
00737       {
00738         temp = res;
00739         res = max(res, this->data_[i]);
00740         res = max(res, T(-this->data_[i]));
00741         if (temp != res) j = i;
00742       }
00743 
00744     return j;
00745   }
00746 
00747 
00748   /**************************
00749    * OUTPUT/INPUT FUNCTIONS *
00750    **************************/
00751 
00752 
00754 
00760   template <class T, class Allocator>
00761   void Vector<T, VectFull, Allocator>
00762   ::Write(string FileName, bool with_size) const
00763   {
00764     ofstream FileStream;
00765     FileStream.open(FileName.c_str());
00766 
00767 #ifdef SELDON_CHECK_IO
00768     // Checks if the file was opened.
00769     if (!FileStream.is_open())
00770       throw IOError("Vector<VectFull>::Write(string FileName)",
00771                     string("Unable to open file \"") + FileName + "\".");
00772 #endif
00773 
00774     this->Write(FileStream, with_size);
00775 
00776     FileStream.close();
00777   }
00778 
00779 
00781 
00787   template <class T, class Allocator>
00788   void Vector<T, VectFull, Allocator>
00789   ::Write(ostream& FileStream, bool with_size) const
00790   {
00791 
00792 #ifdef SELDON_CHECK_IO
00793     // Checks if the stream is ready.
00794     if (!FileStream.good())
00795       throw IOError("Vector<VectFull>::Write(ostream& FileStream)",
00796                     "The stream is not ready.");
00797 #endif
00798 
00799     if (with_size)
00800       FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
00801                        sizeof(int));
00802 
00803     FileStream.write(reinterpret_cast<char*>(this->data_),
00804                      this->m_ * sizeof(value_type));
00805 
00806 #ifdef SELDON_CHECK_IO
00807     // Checks if data was written.
00808     if (!FileStream.good())
00809       throw IOError("Vector<VectFull>::Write(ostream& FileStream)",
00810                     "Output operation failed.");
00811 #endif
00812 
00813   }
00814 
00815 
00817 
00822   template <class T, class Allocator>
00823   void Vector<T, VectFull, Allocator>::WriteText(string FileName) const
00824   {
00825     ofstream FileStream;
00826     FileStream.precision(cout.precision());
00827     FileStream.flags(cout.flags());
00828     FileStream.open(FileName.c_str());
00829 
00830 #ifdef SELDON_CHECK_IO
00831     // Checks if the file was opened.
00832     if (!FileStream.is_open())
00833       throw IOError("Vector<VectFull>::WriteText(string FileName)",
00834                     string("Unable to open file \"") + FileName + "\".");
00835 #endif
00836 
00837     this->WriteText(FileStream);
00838 
00839     FileStream.close();
00840   }
00841 
00842 
00844 
00849   template <class T, class Allocator>
00850   void Vector<T, VectFull, Allocator>::WriteText(ostream& FileStream) const
00851   {
00852 
00853 #ifdef SELDON_CHECK_IO
00854     // Checks if the stream is ready.
00855     if (!FileStream.good())
00856       throw IOError("Vector<VectFull>::WriteText(ostream& FileStream)",
00857                     "The stream is not ready.");
00858 #endif
00859 
00860     if (this->GetLength() != 0)
00861       FileStream << (*this)(0);
00862 
00863     for (int i = 1; i < this->GetLength(); i++)
00864       FileStream << "\t" << (*this)(i);
00865 
00866 #ifdef SELDON_CHECK_IO
00867     // Checks if data was written.
00868     if (!FileStream.good())
00869       throw IOError("Vector<VectFull>::WriteText(ostream& FileStream)",
00870                     "Output operation failed.");
00871 #endif
00872 
00873   }
00874 
00875 
00877 
00885   template <class T, class Allocator>
00886   void Vector<T, VectFull, Allocator>
00887   ::Read(string FileName, bool with_size)
00888   {
00889     ifstream FileStream;
00890     FileStream.open(FileName.c_str());
00891 
00892 #ifdef SELDON_CHECK_IO
00893     // Checks if the file was opened.
00894     if (!FileStream.is_open())
00895       throw IOError("Vector<VectFull>::Read(string FileName)",
00896                     string("Unable to open file \"") + FileName + "\".");
00897 #endif
00898 
00899     this->Read(FileStream, with_size);
00900 
00901     FileStream.close();
00902   }
00903 
00904 
00906 
00914   template <class T, class Allocator>
00915   void Vector<T, VectFull, Allocator>
00916   ::Read(istream& FileStream, bool with_size)
00917   {
00918 
00919 #ifdef SELDON_CHECK_IO
00920     // Checks if the stream is ready.
00921     if (!FileStream.good())
00922       throw IOError("Vector<VectFull>::Read(istream& FileStream)",
00923                     "The stream is not ready.");
00924 #endif
00925 
00926     if (with_size)
00927       {
00928         int new_size;
00929         FileStream.read(reinterpret_cast<char*>(&new_size), sizeof(int));
00930         this->Reallocate(new_size);
00931       }
00932 
00933     FileStream.read(reinterpret_cast<char*>(this->data_),
00934                     this->GetLength() * sizeof(value_type));
00935 
00936 #ifdef SELDON_CHECK_IO
00937     // Checks if data was read.
00938     if (!FileStream.good())
00939       throw IOError("Vector<VectFull>::Read(istream& FileStream)",
00940                     "Output operation failed.");
00941 #endif
00942 
00943   }
00944 
00945 
00947 
00952   template <class T, class Allocator>
00953   void Vector<T, VectFull, Allocator>::ReadText(string FileName)
00954   {
00955     ifstream FileStream;
00956     FileStream.open(FileName.c_str());
00957 
00958 #ifdef SELDON_CHECK_IO
00959     // Checks if the file was opened.
00960     if (!FileStream.is_open())
00961       throw IOError("Vector<VectFull>::ReadText(string FileName)",
00962                     string("Unable to open file \"") + FileName + "\".");
00963 #endif
00964 
00965     this->ReadText(FileStream);
00966 
00967     FileStream.close();
00968   }
00969 
00970 
00972 
00977   template <class T, class Allocator>
00978   void Vector<T, VectFull, Allocator>::ReadText(istream& FileStream)
00979   {
00980     // Previous values of the vector are cleared.
00981     Clear();
00982 
00983 #ifdef SELDON_CHECK_IO
00984     // Checks if the stream is ready.
00985     if (!FileStream.good())
00986       throw IOError("Vector<VectFull>::ReadText(istream& FileStream)",
00987                     "The stream is not ready.");
00988 #endif
00989 
00990     T entry;
00991     int number_element = 0;
00992     while (!FileStream.eof())
00993       {
00994         // Reads a new entry.
00995         FileStream >> entry;
00996 
00997         if (FileStream.fail())
00998           break;
00999         else
01000           {
01001             number_element++;
01002 
01003             // If needed, resizes the vector. Its size is already doubled so
01004             // that the vector should be resized a limited number of times.
01005             if (number_element > this->m_)
01006               this->Resize(2 * number_element);
01007 
01008             this->data_[number_element - 1] = entry;
01009           }
01010       }
01011 
01012     // Resizes to the actual size.
01013     if (number_element > 0)
01014       this->Resize(number_element);
01015     else
01016       this->Clear();
01017   }
01018 
01019 
01021 
01026   template <class T, class Storage, class Allocator>
01027   ostream& operator << (ostream& out,
01028                         const Vector<T, Storage, Allocator>& V)
01029   {
01030     for (int i = 0; i < V.GetLength() - 1; i++)
01031       out << V(i) << '\t';
01032     if (V.GetLength() != 0)
01033       out << V(V.GetLength() - 1);
01034 
01035     return out;
01036   }
01037 
01038 
01039 } // namespace Seldon.
01040 
01041 #define SELDON_FILE_VECTOR_CXX
01042 #endif