vector/SparseVector.cxx

00001 // Copyright (C) 2003-2009 Marc Duruflé
00002 // Copyright (C) 2001-2009 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_SPARSE_VECTOR_CXX
00022 
00023 #include "SparseVector.hxx"
00024 
00025 namespace Seldon
00026 {
00027 
00028 
00029   /****************
00030    * CONSTRUCTORS *
00031    ****************/
00032 
00033 
00035 
00038   template <class T, class Allocator>
00039   Vector<T, VectSparse, Allocator>::Vector()  throw():
00040     Vector<T, VectFull, Allocator>()
00041   {
00042     index_ = NULL;
00043   }
00044 
00045 
00047 
00050   template <class T, class Allocator>
00051   Vector<T, VectSparse, Allocator>::Vector(int i):
00052     Vector<T, VectFull, Allocator>(i)
00053   {
00054 
00055 #ifdef SELDON_CHECK_MEMORY
00056     try
00057       {
00058 #endif
00059 
00060         this->index_ = index_allocator_.allocate(i, this);
00061 
00062 #ifdef SELDON_CHECK_MEMORY
00063       }
00064     catch (...)
00065       {
00066         this->m_ = 0;
00067         this->index_ = NULL;
00068         this->data_ = NULL;
00069       }
00070 
00071     if (this->index_ == NULL)
00072       {
00073         this->m_ = 0;
00074         this->data_ = NULL;
00075       }
00076 
00077     if (this->data_ == NULL && i != 0)
00078       throw NoMemory("Vector<VectSparse>::Vector(int)",
00079                      string("Unable to allocate memory for a vector of size ")
00080                      + to_str(i * sizeof(T)) + " bytes ("
00081                      + to_str(i) + " elements).");
00082 #endif
00083 
00084   }
00085 
00086 
00088 
00091   template <class T, class Allocator>
00092   Vector<T, VectSparse, Allocator>::
00093   Vector(const Vector<T, VectSparse, Allocator>& V) :
00094     Vector<T, VectFull, Allocator>()
00095   {
00096     this->index_ = NULL;
00097     Copy(V);
00098   }
00099 
00100 
00101   /**************
00102    * DESTRUCTOR *
00103    **************/
00104 
00105 
00107   template <class T, class Allocator>
00108   Vector<T, VectSparse, Allocator>::~Vector()
00109   {
00110     // 'data_' is released.
00111 #ifdef SELDON_CHECK_MEMORY
00112     try
00113       {
00114 #endif
00115         if (this->data_ != NULL)
00116           {
00117             this->vect_allocator_.deallocate(this->data_, this->m_);
00118             this->data_ = NULL;
00119           }
00120 
00121         if (index_ != NULL)
00122           {
00123             index_allocator_.deallocate(index_, this->m_);
00124             index_ = NULL;
00125           }
00126 
00127         this->m_ = 0;
00128 
00129 #ifdef SELDON_CHECK_MEMORY
00130       }
00131     catch (...)
00132       {
00133         this->data_ = NULL;
00134         index_ = NULL;
00135         this->m_ = 0;
00136         return;
00137       }
00138 #endif
00139 
00140   }
00141 
00142 
00143   /*********************
00144    * MEMORY MANAGEMENT *
00145    *********************/
00146 
00147 
00149 
00153   template <class T, class Allocator>
00154   inline void Vector<T, VectSparse, Allocator>::Clear()
00155   {
00156     this->~Vector();
00157   }
00158 
00159 
00161 
00167   template <class T, class Allocator>
00168   inline void Vector<T, VectSparse, Allocator>::Reallocate(int i)
00169   {
00170 
00171     if (i != this->m_)
00172       {
00173 
00174         this->m_ = i;
00175 
00176 #ifdef SELDON_CHECK_MEMORY
00177         try
00178           {
00179 #endif
00180 
00181             this->data_ =
00182               reinterpret_cast<pointer>(this->vect_allocator_
00183                                         .reallocate(this->data_, i, this));
00184 
00185             index_
00186               = reinterpret_cast<int*>(this->index_allocator_
00187                                        .reallocate(index_, i, this));
00188 
00189 #ifdef SELDON_CHECK_MEMORY
00190           }
00191         catch (...)
00192           {
00193             this->m_ = 0;
00194             this->data_ = NULL;
00195             this->index_ = NULL;
00196             return;
00197           }
00198         if (this->data_ == NULL)
00199           {
00200             this->m_ = 0;
00201             this->index_ = NULL;
00202             return;
00203           }
00204 #endif
00205 
00206       }
00207   }
00208 
00209 
00211 
00216   template <class T, class Allocator>
00217   inline void Vector<T, VectSparse, Allocator>::Resize(int n)
00218   {
00219 
00220     if (n == this->m_)
00221       return;
00222 
00223     Vector<T, VectFull, Allocator> new_value(n);
00224     Vector<int> new_index(n);
00225     int Nmin = min(this->m_, n);
00226     for (int i = 0; i < Nmin; i++)
00227       {
00228         new_value(i) = this->data_[i];
00229         new_index(i) = index_[i];
00230       }
00231 
00232     SetData(new_value, new_index);
00233   }
00234 
00235 
00252   template <class T, class Allocator>
00253   inline void Vector<T, VectSparse, Allocator>
00254   ::SetData(int i, T* data, int* index)
00255   {
00256     this->Clear();
00257 
00258     this->m_ = i;
00259 
00260     this->data_ = data;
00261     this->index_ = index;
00262   }
00263 
00264 
00276   template <class T, class Allocator>
00277   template<class Allocator2>
00278   void Vector<T, VectSparse, Allocator>
00279   ::SetData(Vector<T, VectFull, Allocator2>& data, Vector<int>& index)
00280   {
00281 
00282 #ifdef SELDON_CHECK_BOUNDS
00283     if (data.GetM() != index.GetM())
00284       throw WrongDim("Vector<VectSparse>::SetData ",
00285                      string("The data vector and the index vector should")
00286                      + " have the same size.\n  Size of the data vector: "
00287                      + to_str(data.GetM()) + "\n  Size of index vector: "
00288                      + to_str(index.GetM()));
00289 #endif
00290 
00291     SetData(data.GetM(), data.GetData(), index.GetData());
00292     data.Nullify();
00293     index.Nullify();
00294   }
00295 
00296 
00308   template <class T, class Allocator>
00309   template<class Allocator2>
00310   void Vector<T, VectSparse, Allocator>
00311   ::SetData(const Vector<T, VectSparse, Allocator2>& V)
00312   {
00313     SetData(V.GetM(), V.GetData(), V.GetIndex());
00314   }
00315 
00316 
00318 
00323   template <class T, class Allocator>
00324   void Vector<T, VectSparse, Allocator>::Nullify()
00325   {
00326     this->m_ = 0;
00327     this->data_ = NULL;
00328     this->index_ = NULL;
00329   }
00330 
00331 
00332   /**********************************
00333    * ELEMENT ACCESS AND AFFECTATION *
00334    **********************************/
00335 
00336 
00338 
00342   template <class T, class Allocator>
00343   inline typename Vector<T, VectSparse, Allocator>::reference
00344   Vector<T, VectSparse, Allocator>::Value(int i)
00345   {
00346 
00347 #ifdef SELDON_CHECK_BOUNDS
00348     if (i < 0 || i >= this->m_)
00349       throw WrongIndex("Vector<VectSparse>::Value(int)",
00350                        string("Index should be in [0, ") + to_str(this->m_-1)
00351                        + "], but is equal to " + to_str(i) + ".");
00352 #endif
00353 
00354     return this->data_[i];
00355   }
00356 
00357 
00359 
00363   template <class T, class Allocator>
00364   inline typename Vector<T, VectSparse, Allocator>::const_reference
00365   Vector<T, VectSparse, Allocator>::Value(int i) const
00366   {
00367 
00368 #ifdef SELDON_CHECK_BOUNDS
00369     if (i < 0 || i >= this->m_)
00370       throw WrongIndex("Vector<VectSparse>::Value(int)",
00371                        string("Index should be in [0, ") + to_str(this->m_-1)
00372                        + "], but is equal to " + to_str(i) + ".");
00373 #endif
00374 
00375     return this->data_[i];
00376   }
00377 
00378 
00380 
00384   template <class T, class Allocator>
00385   inline int& Vector<T, VectSparse, Allocator>::Index(int i)
00386   {
00387 
00388 #ifdef SELDON_CHECK_BOUNDS
00389     if (i < 0 || i >= this->m_)
00390       throw WrongIndex("Vector<VectSparse>::Index(int)",
00391                        string("Index should be in [0, ") + to_str(this->m_-1)
00392                        + "], but is equal to " + to_str(i) + ".");
00393 #endif
00394 
00395     return this->index_[i];
00396   }
00397 
00398 
00400 
00404   template <class T, class Allocator>
00405   inline int Vector<T, VectSparse, Allocator>::Index(int i) const
00406   {
00407 
00408 #ifdef SELDON_CHECK_BOUNDS
00409     if (i < 0 || i >= this->m_)
00410       throw WrongIndex("Vector<VectSparse>::Index(int)",
00411                        string("Index should be in [0, ") + to_str(this->m_-1)
00412                        + "], but is equal to " + to_str(i) + ".");
00413 #endif
00414 
00415     return this->index_[i];
00416   }
00417 
00418 
00420 
00424   template <class T, class Allocator>
00425   inline typename Vector<T, VectSparse, Allocator>::reference
00426   Vector<T, VectSparse, Allocator>::operator() (int i)
00427   {
00428     int k = 0;
00429     // Searching for the entry.
00430     while (k < this->m_ && index_[k] < i)
00431       k++;
00432 
00433     if (k >= this->m_ || index_[k] != i)
00434       // The entry does not exist yet, so a zero entry is introduced.
00435       AddInteraction(i, T(0));
00436 
00437     return this->data_[k];
00438   }
00439 
00440 
00442 
00446   template <class T, class Allocator>
00447   inline typename Vector<T, VectSparse, Allocator>::value_type
00448   Vector<T, VectSparse, Allocator>::operator() (int i) const
00449   {
00450     int k = 0;
00451     // Searching for the entry.
00452     while (k < this->m_ && index_[k] < i)
00453       k++;
00454 
00455     if (k >= this->m_ || index_[k] != i)
00456       // The entry does not exist, a zero is returned.
00457       return T(0);
00458 
00459     return this->data_[k];
00460   }
00461 
00462 
00464 
00468   template <class T, class Allocator>
00469   inline typename Vector<T, VectSparse, Allocator>::reference
00470   Vector<T, VectSparse, Allocator>::Val(int i)
00471   {
00472     return (*this)(i);
00473   }
00474 
00475 
00477 
00483   template <class T, class Allocator>
00484   inline typename Vector<T, VectSparse, Allocator>::const_reference
00485   Vector<T, VectSparse, Allocator>::Val(int i) const
00486   {
00487     int k = 0;
00488     // Searching for the entry.
00489     while (k < this->m_ && index_[k] < i)
00490       k++;
00491 
00492     if (k >= this->m_ || index_[k] != i)
00493       // The entry does not exist, no reference can be returned.
00494       throw WrongArgument("Vector<VectSparse>::Val(int)",
00495                           "No reference to element " + to_str(i)
00496                           + " can be returned: it is a zero entry.");
00497 
00498     return this->data_[k];
00499   }
00500 
00501 
00503 
00508   template <class T, class Allocator>
00509   inline Vector<T, VectSparse, Allocator>& Vector<T, VectSparse, Allocator>
00510   ::operator= (const Vector<T, VectSparse, Allocator>& X)
00511   {
00512     this->Copy(X);
00513 
00514     return *this;
00515   }
00516 
00517 
00519 
00524   template <class T, class Allocator>
00525   inline void Vector<T, VectSparse, Allocator>
00526   ::Copy(const Vector<T, VectSparse, Allocator>& X)
00527   {
00528     this->Reallocate(X.GetLength());
00529 
00530     this->vect_allocator_.memorycpy(this->data_, X.GetData(), this->m_);
00531     this->index_allocator_.memorycpy(this->index_, X.GetIndex(), this->m_);
00532   }
00533 
00534 
00535   /*******************
00536    * BASIC FUNCTIONS *
00537    *******************/
00538 
00539 
00545   template <class T, class Allocator>
00546   int* Vector<T, VectSparse, Allocator>::GetIndex() const
00547   {
00548     return this->index_;
00549   }
00550 
00551 
00552   /************************
00553    * CONVENIENT FUNCTIONS *
00554    ************************/
00555 
00556 
00558 
00561   template <class T, class Allocator>
00562   template <class T0>
00563   Vector<T, VectSparse, Allocator>&
00564   Vector<T, VectSparse, Allocator>::operator= (const T0& x)
00565   {
00566     this->Fill(x);
00567 
00568     return *this;
00569   }
00570 
00571 
00573   template <class T, class Allocator>
00574   void Vector<T, VectSparse, Allocator>::Print() const
00575   {
00576     for (int i = 0; i < this->GetLength(); i++)
00577       cout << (Index(i) + 1) << ' ' << Value(i) << '\n';
00578   }
00579 
00580 
00582 
00586   template <class T, class Allocator>
00587   void Vector<T, VectSparse, Allocator>::Assemble()
00588   {
00589     int new_size = this->m_;
00590     Vector<T, VectFull, Allocator> values(new_size);
00591     Vector<int> index(new_size);
00592     for (int i = 0; i < new_size; i++)
00593       {
00594         values(i) = this->data_[i];
00595         index(i) = index_[i];
00596       }
00597 
00598     Seldon::Assemble(new_size, index, values);
00599     index.Resize(new_size);
00600     values.Resize(new_size);
00601     SetData(values, index);
00602   }
00603 
00604 
00606 
00610   template <class T, class Allocator> template<class T0>
00611   void Vector<T, VectSparse, Allocator>::RemoveSmallEntry(const T0& epsilon)
00612   {
00613     int new_size = this->m_;
00614     Vector<T, VectFull, Allocator> values(new_size);
00615     Vector<int> index(new_size);
00616     new_size = 0;
00617     for (int i = 0; i < this->m_; i++)
00618       if (abs(this->data_[i]) > epsilon)
00619         {
00620           values(new_size) = this->data_[i];
00621           index(new_size) = index_[i];
00622           new_size++;
00623         }
00624 
00625     index.Resize(new_size);
00626     values.Resize(new_size);
00627     SetData(values, index);
00628   }
00629 
00630 
00632 
00637   template <class T, class Allocator> inline
00638   void Vector<T, VectSparse, Allocator>::AddInteraction(int i, const T& val)
00639   {
00640     // Searching for the position where the entry may be.
00641     int pos = 0;
00642     while (pos < this->m_ && index_[pos] < i)
00643       pos++;
00644 
00645     // If the entry already exists, adds 'val'.
00646     if (pos < this->m_ && index_[pos] == i)
00647       {
00648         this->data_[pos] += val;
00649         return;
00650       }
00651 
00652     int k;
00653 
00654     // If the entry does not exist, the vector is reallocated.
00655     Vector<T, VectFull, Allocator> new_val(this->m_ + 1);
00656     Vector<int> new_ind(this->m_ + 1);
00657     for (k = 0; k < pos; k++)
00658       {
00659         new_ind(k) = index_[k];
00660         new_val(k) = this->data_[k];
00661       }
00662 
00663     // The new entry.
00664     new_ind(pos) = i;
00665     new_val(pos) = val;
00666 
00667     // Other values in the vector.
00668     for (k = pos + 1; k <= this->m_; k++)
00669       {
00670         new_ind(k) = index_[k - 1];
00671         new_val(k) = this->data_[k - 1];
00672       }
00673 
00674     SetData(new_val, new_ind);
00675   }
00676 
00677 
00679 
00688   template <class T, class Allocator> inline
00689   void Vector<T, VectSparse, Allocator>::
00690   AddInteractionRow(int n, int* index, T* value, bool already_sorted)
00691   {
00692     Vector<int> ind;
00693     Vector<T, VectFull, Allocator> val;
00694     ind.SetData(n, index);
00695     val.SetData(n, value);
00696     AddInteractionRow(n, ind, val, already_sorted);
00697     ind.Nullify();
00698     val.Nullify();
00699   }
00700 
00701 
00703 
00712   template <class T, class Allocator>
00713   template<class Allocator0>
00714   void Vector<T, VectSparse, Allocator>::
00715   AddInteractionRow(int n, Vector<int> index,
00716                     Vector<T, VectFull, Allocator0> value,
00717                     bool already_sorted)
00718   {
00719     if (!already_sorted)
00720       // Sorts the values to be added according to their indices.
00721       Seldon::Assemble(n, index, value);
00722 
00723     /***  Values that already have an entry ***/
00724 
00725     // Number of values to be added without entry.
00726     int Nnew = 0;
00727     Vector<bool> new_index(n);
00728     new_index.Fill(true);
00729     int k = 0;
00730     for (int j = 0; j < n; j++)
00731       {
00732         while (k < this->m_ && index_[k] < index(j))
00733           k++;
00734 
00735         if (k < this->m_ && index(j) == index_[k])
00736           {
00737             new_index(j) = false;
00738             this->data_[k] += value(j);
00739           }
00740         else
00741           Nnew++;
00742       }
00743 
00744     if (Nnew > 0)
00745       {
00746         // Some values to be added have no entry yet.
00747         Vector<T> new_val(this->m_ + Nnew);
00748         Vector<int> new_ind(this->m_ + Nnew);
00749         int nb = 0;
00750         k = 0;
00751         for (int j = 0; j < n; j++)
00752           if (new_index(j))
00753             {
00754               while (k < this->m_ && index_[k] < index(j))
00755                 {
00756                   new_ind(nb) = index_[k];
00757                   new_val(nb) = this->data_[k];
00758                   k++;
00759                   nb++;
00760                 }
00761 
00762               // The new entry.
00763               new_ind(nb) = index(j);
00764               new_val(nb) = value(j);
00765               nb++;
00766             }
00767 
00768         // Last entries.
00769         while (k < this->m_)
00770           {
00771             new_ind(nb) = index_[k];
00772             new_val(nb) = this->data_[k];
00773             k++;
00774             nb++;
00775           }
00776 
00777         SetData(new_val, new_ind);
00778       }
00779   }
00780 
00781 
00782   /**************************
00783    * OUTPUT/INPUT FUNCTIONS *
00784    **************************/
00785 
00786 
00788 
00793   template <class T, class Allocator>
00794   void Vector<T, VectSparse, Allocator>::Write(string FileName) const
00795   {
00796     ofstream FileStream;
00797     FileStream.open(FileName.c_str());
00798 
00799 #ifdef SELDON_CHECK_IO
00800     // Checks if the file was opened.
00801     if (!FileStream.is_open())
00802       throw IOError("Vector<VectSparse>::Write(string FileName)",
00803                     string("Unable to open file \"") + FileName + "\".");
00804 #endif
00805 
00806     this->Write(FileStream);
00807 
00808     FileStream.close();
00809   }
00810 
00811 
00813 
00818   template <class T, class Allocator>
00819   void Vector<T, VectSparse, Allocator>::Write(ostream& stream) const
00820   {
00821 
00822 #ifdef SELDON_CHECK_IO
00823     // Checks if the stream is ready.
00824     if (!stream.good())
00825       throw IOError("Vector<VectSparse>::Write(ostream& stream)",
00826                     "Stream is not ready.");
00827 #endif
00828 
00829     stream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
00830                  sizeof(int));
00831 
00832     stream.write(reinterpret_cast<char*>(this->index_),
00833                  this->m_ * sizeof(int));
00834 
00835     stream.write(reinterpret_cast<char*>(this->data_),
00836                  this->m_ * sizeof(value_type));
00837 
00838 #ifdef SELDON_CHECK_IO
00839     // Checks if data was written.
00840     if (!stream.good())
00841       throw IOError("Vector<VectSparse>::Write(ostream& stream)",
00842                     "Output operation failed.");
00843 #endif
00844 
00845   }
00846 
00847 
00849 
00854   template <class T, class Allocator>
00855   void Vector<T, VectSparse, Allocator>::WriteText(string FileName) const
00856   {
00857     ofstream FileStream;
00858     FileStream.precision(cout.precision());
00859     FileStream.flags(cout.flags());
00860     FileStream.open(FileName.c_str());
00861 
00862 #ifdef SELDON_CHECK_IO
00863     // Checks if the file was opened.
00864     if (!FileStream.is_open())
00865       throw IOError("Vector<VectSparse>::WriteText(string FileName)",
00866                     string("Unable to open file \"") + FileName + "\".");
00867 #endif
00868 
00869     this->WriteText(FileStream);
00870 
00871     FileStream.close();
00872   }
00873 
00874 
00876 
00881   template <class T, class Allocator>
00882   void Vector<T, VectSparse, Allocator>::WriteText(ostream& stream) const
00883   {
00884 
00885 #ifdef SELDON_CHECK_IO
00886     // Checks if the stream is ready.
00887     if (!stream.good())
00888       throw IOError("Vector<VectSparse>::WriteText(ostream& stream)",
00889                     "Stream is not ready.");
00890 #endif
00891 
00892     // First entries.
00893     for (int i = 0; i < this->m_ - 1; i++)
00894       stream << (Index(i) + 1) << " " << Value(i) << '\n';
00895 
00896     // Last entry is a special case: there should be no empty line at the end
00897     // of the stream.
00898     if (this->m_ > 0)
00899       stream << (Index(this->m_ - 1) + 1) << " " << Value(this->m_ - 1);
00900 
00901 #ifdef SELDON_CHECK_IO
00902     // Checks if data was written.
00903     if (!stream.good())
00904       throw IOError("Vector<VectSparse>::WriteText(ostream& stream)",
00905                     "Output operation failed.");
00906 #endif
00907 
00908   }
00909 
00910 
00912 
00916   template <class T, class Allocator>
00917   void Vector<T, VectSparse, Allocator>::Read(string FileName)
00918   {
00919     ifstream FileStream;
00920     FileStream.open(FileName.c_str());
00921 
00922 #ifdef SELDON_CHECK_IO
00923     // Checks if the file was opened.
00924     if (!FileStream.is_open())
00925       throw IOError("Vector<VectSparse>::Read(string FileName)",
00926                     string("Unable to open file \"") + FileName + "\".");
00927 #endif
00928 
00929     this->Read(FileStream);
00930 
00931     FileStream.close();
00932   }
00933 
00934 
00936 
00940   template <class T, class Allocator>
00941   void Vector<T, VectSparse, Allocator>::Read(istream& stream)
00942   {
00943 
00944 #ifdef SELDON_CHECK_IO
00945     // Checks if the stream is ready.
00946     if (!stream.good())
00947       throw IOError("Vector<VectSparse>::Read(istream& stream)",
00948                     "Stream is not ready.");
00949 #endif
00950 
00951     int m;
00952     stream.read(reinterpret_cast<char*>(&m), sizeof(int));
00953     this->Reallocate(m);
00954 
00955     stream.read(reinterpret_cast<char*>(this->index_), m * sizeof(int));
00956 
00957     stream.read(reinterpret_cast<char*>(this->data_),
00958                 m * sizeof(value_type));
00959 
00960 #ifdef SELDON_CHECK_IO
00961     // Checks if data was read.
00962     if (!stream.good())
00963       throw IOError("Vector<VectSparse>::Read(istream& stream)",
00964                     "Output operation failed.");
00965 #endif
00966 
00967   }
00968 
00969 
00971 
00975   template <class T, class Allocator>
00976   void Vector<T, VectSparse, Allocator>::ReadText(string FileName)
00977   {
00978     ifstream FileStream;
00979     FileStream.open(FileName.c_str());
00980 
00981 #ifdef SELDON_CHECK_IO
00982     // Checks if the file was opened.
00983     if (!FileStream.is_open())
00984       throw IOError("Vector<VectSparse>::ReadText(string FileName)",
00985                     string("Unable to open file \"") + FileName + "\".");
00986 #endif
00987 
00988     this->ReadText(FileStream);
00989 
00990     FileStream.close();
00991   }
00992 
00993 
00995 
00999   template <class T, class Allocator>
01000   void Vector<T, VectSparse, Allocator>::ReadText(istream& stream)
01001   {
01002     Clear();
01003 
01004 #ifdef SELDON_CHECK_IO
01005     // Checks if the stream is ready.
01006     if (!stream.good())
01007       throw IOError("Vector<VectSparse>::ReadText(istream& stream)",
01008                     "Stream is not ready.");
01009 #endif
01010 
01011     Vector<T, VectFull, Allocator> values;
01012     Vector<int> index;
01013     T entry;
01014     int ind = 0;
01015     int nb_elt = 0;
01016     while (!stream.eof())
01017       {
01018         // New entry is read.
01019         stream >> ind >> entry;
01020 
01021         if (stream.fail())
01022           break;
01023         else
01024           {
01025 #ifdef SELDON_CHECK_IO
01026             if (ind < 1)
01027               throw IOError(string("Vector<VectSparse>::ReadText") +
01028                             "(istream& stream)",
01029                             string("Index should be greater ")
01030                             + "than 0 but is equal to " + to_str(ind) + ".");
01031 #endif
01032 
01033             nb_elt++;
01034             ind--;
01035 
01036             // Inserting a new element.
01037             if (nb_elt > values.GetM())
01038               {
01039                 values.Resize(2 * nb_elt);
01040                 index.Resize(2 * nb_elt);
01041               }
01042 
01043             values(nb_elt - 1) = entry;
01044             index(nb_elt - 1) = ind;
01045           }
01046       }
01047 
01048     if (nb_elt > 0)
01049       {
01050         // Allocating to the right size.
01051         this->Reallocate(nb_elt);
01052         for (int i = 0; i < nb_elt; i++)
01053           {
01054             Index(i) = index(i);
01055             Value(i) = values(i);
01056           }
01057       }
01058   }
01059 
01060 
01062 
01067   template <class T, class Allocator>
01068   ostream& operator << (ostream& out,
01069                         const Vector<T, VectSparse, Allocator>& V)
01070   {
01071     for (int i = 0; i < V.GetLength(); i++)
01072       out << (V.Index(i) + 1) << ' ' << V.Value(i) << '\n';
01073 
01074     return out;
01075   }
01076 
01077 
01078 } // namespace Seldon.
01079 
01080 #define SELDON_FILE_SPARSE_VECTOR_CXX
01081 #endif