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():
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>::value_type
00426   Vector<T, VectSparse, Allocator>::operator() (int i) const
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, a zero is returned.
00435       return 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>::reference
00448   Vector<T, VectSparse, Allocator>::Get(int i)
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 yet, so a zero entry is introduced.
00457       AddInteraction(i, T(0));
00458 
00459     return this->data_[k];
00460   }
00461 
00462 
00464 
00470   template <class T, class Allocator>
00471   inline typename Vector<T, VectSparse, Allocator>::const_reference
00472   Vector<T, VectSparse, Allocator>::Get(int i) const
00473   {
00474     int k = 0;
00475     // Searching for the entry.
00476     while (k < this->m_ && index_[k] < i)
00477       k++;
00478 
00479     if (k >= this->m_ || index_[k] != i)
00480       // The entry does not exist, no reference can be returned.
00481       throw WrongArgument("Vector<VectSparse>::Val(int)",
00482                           "No reference to element " + to_str(i)
00483                           + " can be returned: it is a zero entry.");
00484 
00485     return this->data_[k];
00486   }
00487 
00488 
00490 
00496   template <class T, class Allocator>
00497   inline typename Vector<T, VectSparse, Allocator>::reference
00498   Vector<T, VectSparse, Allocator>::Val(int i)
00499   {
00500     int k = 0;
00501     // Searching for the entry.
00502     while (k < this->m_ && index_[k] < i)
00503       k++;
00504 
00505     if (k >= this->m_ || index_[k] != i)
00506       throw WrongArgument("Vector<VectSparse>::Val(int)",
00507                           "the entry " + to_str(i) +
00508                           " does not belong to the sparsity pattern.");
00509 
00510 
00511     return this->data_[k];
00512   }
00513 
00514 
00516 
00522   template <class T, class Allocator>
00523   inline typename Vector<T, VectSparse, Allocator>::const_reference
00524   Vector<T, VectSparse, Allocator>::Val(int i) const
00525   {
00526     int k = 0;
00527     // Searching for the entry.
00528     while (k < this->m_ && index_[k] < i)
00529       k++;
00530 
00531     if (k >= this->m_ || index_[k] != i)
00532       throw WrongArgument("Vector<VectSparse>::Val(int)",
00533                           "the entry " + to_str(i) +
00534                           " does not belong to the sparsity pattern.");
00535 
00536     return this->data_[k];
00537   }
00538 
00539 
00541 
00546   template <class T, class Allocator>
00547   inline Vector<T, VectSparse, Allocator>& Vector<T, VectSparse, Allocator>
00548   ::operator= (const Vector<T, VectSparse, Allocator>& X)
00549   {
00550     this->Copy(X);
00551 
00552     return *this;
00553   }
00554 
00555 
00557 
00562   template <class T, class Allocator>
00563   inline void Vector<T, VectSparse, Allocator>
00564   ::Copy(const Vector<T, VectSparse, Allocator>& X)
00565   {
00566     this->Reallocate(X.GetLength());
00567 
00568     this->vect_allocator_.memorycpy(this->data_, X.GetData(), this->m_);
00569     this->index_allocator_.memorycpy(this->index_, X.GetIndex(), this->m_);
00570   }
00571 
00572 
00573   /*******************
00574    * BASIC FUNCTIONS *
00575    *******************/
00576 
00577 
00583   template <class T, class Allocator>
00584   int* Vector<T, VectSparse, Allocator>::GetIndex() const
00585   {
00586     return this->index_;
00587   }
00588 
00589 
00590   /************************
00591    * CONVENIENT FUNCTIONS *
00592    ************************/
00593 
00594 
00596 
00599   template <class T, class Allocator>
00600   template <class T0>
00601   Vector<T, VectSparse, Allocator>&
00602   Vector<T, VectSparse, Allocator>::operator= (const T0& x)
00603   {
00604     this->Fill(x);
00605 
00606     return *this;
00607   }
00608 
00609 
00611   template <class T, class Allocator>
00612   void Vector<T, VectSparse, Allocator>::Print() const
00613   {
00614     for (int i = 0; i < this->GetLength(); i++)
00615       cout << (Index(i) + 1) << ' ' << Value(i) << '\n';
00616   }
00617 
00618 
00620 
00624   template <class T, class Allocator>
00625   void Vector<T, VectSparse, Allocator>::Assemble()
00626   {
00627     int new_size = this->m_;
00628     Vector<T, VectFull, Allocator> values(new_size);
00629     Vector<int> index(new_size);
00630     for (int i = 0; i < new_size; i++)
00631       {
00632         values(i) = this->data_[i];
00633         index(i) = index_[i];
00634       }
00635 
00636     Seldon::Assemble(new_size, index, values);
00637     index.Resize(new_size);
00638     values.Resize(new_size);
00639     SetData(values, index);
00640   }
00641 
00642 
00644 
00648   template <class T, class Allocator> template<class T0>
00649   void Vector<T, VectSparse, Allocator>::RemoveSmallEntry(const T0& epsilon)
00650   {
00651     int new_size = this->m_;
00652     Vector<T, VectFull, Allocator> values(new_size);
00653     Vector<int> index(new_size);
00654     new_size = 0;
00655     for (int i = 0; i < this->m_; i++)
00656       if (abs(this->data_[i]) > epsilon)
00657         {
00658           values(new_size) = this->data_[i];
00659           index(new_size) = index_[i];
00660           new_size++;
00661         }
00662 
00663     index.Resize(new_size);
00664     values.Resize(new_size);
00665     SetData(values, index);
00666   }
00667 
00668 
00670 
00675   template <class T, class Allocator> inline
00676   void Vector<T, VectSparse, Allocator>::AddInteraction(int i, const T& val)
00677   {
00678     // Searching for the position where the entry may be.
00679     int pos = 0;
00680     while (pos < this->m_ && index_[pos] < i)
00681       pos++;
00682 
00683     // If the entry already exists, adds 'val'.
00684     if (pos < this->m_ && index_[pos] == i)
00685       {
00686         this->data_[pos] += val;
00687         return;
00688       }
00689 
00690     int k;
00691 
00692     // If the entry does not exist, the vector is reallocated.
00693     Vector<T, VectFull, Allocator> new_val(this->m_ + 1);
00694     Vector<int> new_ind(this->m_ + 1);
00695     for (k = 0; k < pos; k++)
00696       {
00697         new_ind(k) = index_[k];
00698         new_val(k) = this->data_[k];
00699       }
00700 
00701     // The new entry.
00702     new_ind(pos) = i;
00703     new_val(pos) = val;
00704 
00705     // Other values in the vector.
00706     for (k = pos + 1; k <= this->m_; k++)
00707       {
00708         new_ind(k) = index_[k - 1];
00709         new_val(k) = this->data_[k - 1];
00710       }
00711 
00712     SetData(new_val, new_ind);
00713   }
00714 
00715 
00717 
00726   template <class T, class Allocator> inline
00727   void Vector<T, VectSparse, Allocator>::
00728   AddInteractionRow(int n, int* index, T* value, bool already_sorted)
00729   {
00730     Vector<int> ind;
00731     Vector<T, VectFull, Allocator> val;
00732     ind.SetData(n, index);
00733     val.SetData(n, value);
00734     AddInteractionRow(n, ind, val, already_sorted);
00735     ind.Nullify();
00736     val.Nullify();
00737   }
00738 
00739 
00741 
00750   template <class T, class Allocator>
00751   template<class Allocator0>
00752   void Vector<T, VectSparse, Allocator>::
00753   AddInteractionRow(int n, Vector<int> index,
00754                     Vector<T, VectFull, Allocator0> value,
00755                     bool already_sorted)
00756   {
00757     if (!already_sorted)
00758       // Sorts the values to be added according to their indices.
00759       Seldon::Assemble(n, index, value);
00760 
00761     /***  Values that already have an entry ***/
00762 
00763     // Number of values to be added without entry.
00764     int Nnew = 0;
00765     Vector<bool> new_index(n);
00766     new_index.Fill(true);
00767     int k = 0;
00768     for (int j = 0; j < n; j++)
00769       {
00770         while (k < this->m_ && index_[k] < index(j))
00771           k++;
00772 
00773         if (k < this->m_ && index(j) == index_[k])
00774           {
00775             new_index(j) = false;
00776             this->data_[k] += value(j);
00777           }
00778         else
00779           Nnew++;
00780       }
00781 
00782     if (Nnew > 0)
00783       {
00784         // Some values to be added have no entry yet.
00785         Vector<T> new_val(this->m_ + Nnew);
00786         Vector<int> new_ind(this->m_ + Nnew);
00787         int nb = 0;
00788         k = 0;
00789         for (int j = 0; j < n; j++)
00790           if (new_index(j))
00791             {
00792               while (k < this->m_ && index_[k] < index(j))
00793                 {
00794                   new_ind(nb) = index_[k];
00795                   new_val(nb) = this->data_[k];
00796                   k++;
00797                   nb++;
00798                 }
00799 
00800               // The new entry.
00801               new_ind(nb) = index(j);
00802               new_val(nb) = value(j);
00803               nb++;
00804             }
00805 
00806         // Last entries.
00807         while (k < this->m_)
00808           {
00809             new_ind(nb) = index_[k];
00810             new_val(nb) = this->data_[k];
00811             k++;
00812             nb++;
00813           }
00814 
00815         SetData(new_val, new_ind);
00816       }
00817   }
00818 
00819 
00820   /**************************
00821    * OUTPUT/INPUT FUNCTIONS *
00822    **************************/
00823 
00824 
00826 
00831   template <class T, class Allocator>
00832   void Vector<T, VectSparse, Allocator>::Write(string FileName) const
00833   {
00834     ofstream FileStream;
00835     FileStream.open(FileName.c_str(), ofstream::binary);
00836 
00837 #ifdef SELDON_CHECK_IO
00838     // Checks if the file was opened.
00839     if (!FileStream.is_open())
00840       throw IOError("Vector<VectSparse>::Write(string FileName)",
00841                     string("Unable to open file \"") + FileName + "\".");
00842 #endif
00843 
00844     this->Write(FileStream);
00845 
00846     FileStream.close();
00847   }
00848 
00849 
00851 
00856   template <class T, class Allocator>
00857   void Vector<T, VectSparse, Allocator>::Write(ostream& stream) const
00858   {
00859 
00860 #ifdef SELDON_CHECK_IO
00861     // Checks if the stream is ready.
00862     if (!stream.good())
00863       throw IOError("Vector<VectSparse>::Write(ostream& stream)",
00864                     "Stream is not ready.");
00865 #endif
00866 
00867     stream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
00868                  sizeof(int));
00869 
00870     stream.write(reinterpret_cast<char*>(this->index_),
00871                  this->m_ * sizeof(int));
00872 
00873     stream.write(reinterpret_cast<char*>(this->data_),
00874                  this->m_ * sizeof(value_type));
00875 
00876 #ifdef SELDON_CHECK_IO
00877     // Checks if data was written.
00878     if (!stream.good())
00879       throw IOError("Vector<VectSparse>::Write(ostream& stream)",
00880                     "Output operation failed.");
00881 #endif
00882 
00883   }
00884 
00885 
00887 
00892   template <class T, class Allocator>
00893   void Vector<T, VectSparse, Allocator>::WriteText(string FileName) const
00894   {
00895     ofstream FileStream;
00896     FileStream.precision(cout.precision());
00897     FileStream.flags(cout.flags());
00898     FileStream.open(FileName.c_str());
00899 
00900 #ifdef SELDON_CHECK_IO
00901     // Checks if the file was opened.
00902     if (!FileStream.is_open())
00903       throw IOError("Vector<VectSparse>::WriteText(string FileName)",
00904                     string("Unable to open file \"") + FileName + "\".");
00905 #endif
00906 
00907     this->WriteText(FileStream);
00908 
00909     FileStream.close();
00910   }
00911 
00912 
00914 
00919   template <class T, class Allocator>
00920   void Vector<T, VectSparse, Allocator>::WriteText(ostream& stream) const
00921   {
00922 
00923 #ifdef SELDON_CHECK_IO
00924     // Checks if the stream is ready.
00925     if (!stream.good())
00926       throw IOError("Vector<VectSparse>::WriteText(ostream& stream)",
00927                     "Stream is not ready.");
00928 #endif
00929 
00930     // First entries.
00931     for (int i = 0; i < this->m_ - 1; i++)
00932       stream << (Index(i) + 1) << " " << Value(i) << '\n';
00933 
00934     // Last entry is a special case: there should be no empty line at the end
00935     // of the stream.
00936     if (this->m_ > 0)
00937       stream << (Index(this->m_ - 1) + 1) << " " << Value(this->m_ - 1);
00938 
00939 #ifdef SELDON_CHECK_IO
00940     // Checks if data was written.
00941     if (!stream.good())
00942       throw IOError("Vector<VectSparse>::WriteText(ostream& stream)",
00943                     "Output operation failed.");
00944 #endif
00945 
00946   }
00947 
00948 
00950 
00954   template <class T, class Allocator>
00955   void Vector<T, VectSparse, Allocator>::Read(string FileName)
00956   {
00957     ifstream FileStream;
00958     FileStream.open(FileName.c_str(), ifstream::binary);
00959 
00960 #ifdef SELDON_CHECK_IO
00961     // Checks if the file was opened.
00962     if (!FileStream.is_open())
00963       throw IOError("Vector<VectSparse>::Read(string FileName)",
00964                     string("Unable to open file \"") + FileName + "\".");
00965 #endif
00966 
00967     this->Read(FileStream);
00968 
00969     FileStream.close();
00970   }
00971 
00972 
00974 
00978   template <class T, class Allocator>
00979   void Vector<T, VectSparse, Allocator>::Read(istream& stream)
00980   {
00981 
00982 #ifdef SELDON_CHECK_IO
00983     // Checks if the stream is ready.
00984     if (!stream.good())
00985       throw IOError("Vector<VectSparse>::Read(istream& stream)",
00986                     "Stream is not ready.");
00987 #endif
00988 
00989     int m;
00990     stream.read(reinterpret_cast<char*>(&m), sizeof(int));
00991     this->Reallocate(m);
00992 
00993     stream.read(reinterpret_cast<char*>(this->index_), m * sizeof(int));
00994 
00995     stream.read(reinterpret_cast<char*>(this->data_),
00996                 m * sizeof(value_type));
00997 
00998 #ifdef SELDON_CHECK_IO
00999     // Checks if data was read.
01000     if (!stream.good())
01001       throw IOError("Vector<VectSparse>::Read(istream& stream)",
01002                     "Input operation failed.");
01003 #endif
01004 
01005   }
01006 
01007 
01009 
01013   template <class T, class Allocator>
01014   void Vector<T, VectSparse, Allocator>::ReadText(string FileName)
01015   {
01016     ifstream FileStream;
01017     FileStream.open(FileName.c_str());
01018 
01019 #ifdef SELDON_CHECK_IO
01020     // Checks if the file was opened.
01021     if (!FileStream.is_open())
01022       throw IOError("Vector<VectSparse>::ReadText(string FileName)",
01023                     string("Unable to open file \"") + FileName + "\".");
01024 #endif
01025 
01026     this->ReadText(FileStream);
01027 
01028     FileStream.close();
01029   }
01030 
01031 
01033 
01037   template <class T, class Allocator>
01038   void Vector<T, VectSparse, Allocator>::ReadText(istream& stream)
01039   {
01040     Clear();
01041 
01042 #ifdef SELDON_CHECK_IO
01043     // Checks if the stream is ready.
01044     if (!stream.good())
01045       throw IOError("Vector<VectSparse>::ReadText(istream& stream)",
01046                     "Stream is not ready.");
01047 #endif
01048 
01049     Vector<T, VectFull, Allocator> values;
01050     Vector<int> index;
01051     T entry;
01052     int ind = 0;
01053     int nb_elt = 0;
01054     while (!stream.eof())
01055       {
01056         // New entry is read.
01057         stream >> ind >> entry;
01058 
01059         if (stream.fail())
01060           break;
01061         else
01062           {
01063 #ifdef SELDON_CHECK_IO
01064             if (ind < 1)
01065               throw IOError(string("Vector<VectSparse>::ReadText") +
01066                             "(istream& stream)",
01067                             string("Index should be greater ")
01068                             + "than 0 but is equal to " + to_str(ind) + ".");
01069 #endif
01070 
01071             nb_elt++;
01072             ind--;
01073 
01074             // Inserting a new element.
01075             if (nb_elt > values.GetM())
01076               {
01077                 values.Resize(2 * nb_elt);
01078                 index.Resize(2 * nb_elt);
01079               }
01080 
01081             values(nb_elt - 1) = entry;
01082             index(nb_elt - 1) = ind;
01083           }
01084       }
01085 
01086     if (nb_elt > 0)
01087       {
01088         // Allocating to the right size.
01089         this->Reallocate(nb_elt);
01090         for (int i = 0; i < nb_elt; i++)
01091           {
01092             Index(i) = index(i);
01093             Value(i) = values(i);
01094           }
01095       }
01096   }
01097 
01098 
01100 
01105   template <class T, class Allocator>
01106   ostream& operator << (ostream& out,
01107                         const Vector<T, VectSparse, Allocator>& V)
01108   {
01109     for (int i = 0; i < V.GetLength(); i++)
01110       out << (V.Index(i) + 1) << ' ' << V.Value(i) << '\n';
01111 
01112     return out;
01113   }
01114 
01115 
01116 } // namespace Seldon.
01117 
01118 #define SELDON_FILE_SPARSE_VECTOR_CXX
01119 #endif