00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef SELDON_FILE_SPARSE_VECTOR_CXX
00022
00023 #include "SparseVector.hxx"
00024
00025 namespace Seldon
00026 {
00027
00028
00029
00030
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
00103
00104
00105
00107 template <class T, class Allocator>
00108 Vector<T, VectSparse, Allocator>::~Vector()
00109 {
00110
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
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
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
00430 while (k < this->m_ && index_[k] < i)
00431 k++;
00432
00433 if (k >= this->m_ || index_[k] != i)
00434
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
00452 while (k < this->m_ && index_[k] < i)
00453 k++;
00454
00455 if (k >= this->m_ || index_[k] != i)
00456
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
00476 while (k < this->m_ && index_[k] < i)
00477 k++;
00478
00479 if (k >= this->m_ || index_[k] != i)
00480
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
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
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
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
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
00679 int pos = 0;
00680 while (pos < this->m_ && index_[pos] < i)
00681 pos++;
00682
00683
00684 if (pos < this->m_ && index_[pos] == i)
00685 {
00686 this->data_[pos] += val;
00687 return;
00688 }
00689
00690 int k;
00691
00692
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
00702 new_ind(pos) = i;
00703 new_val(pos) = val;
00704
00705
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
00759 Seldon::Assemble(n, index, value);
00760
00761
00762
00763
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
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
00801 new_ind(nb) = index(j);
00802 new_val(nb) = value(j);
00803 nb++;
00804 }
00805
00806
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
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
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
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
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
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
00925 if (!stream.good())
00926 throw IOError("Vector<VectSparse>::WriteText(ostream& stream)",
00927 "Stream is not ready.");
00928 #endif
00929
00930
00931 for (int i = 0; i < this->m_ - 1; i++)
00932 stream << (Index(i) + 1) << " " << Value(i) << '\n';
00933
00934
00935
00936 if (this->m_ > 0)
00937 stream << (Index(this->m_ - 1) + 1) << " " << Value(this->m_ - 1);
00938
00939 #ifdef SELDON_CHECK_IO
00940
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
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
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
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
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
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
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
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
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 }
01117
01118 #define SELDON_FILE_SPARSE_VECTOR_CXX
01119 #endif