Warning: this documentation for the development version is under construction.
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