SparseVector.cxx
1 // Copyright (C) 2003-2011 Marc DuruflĂ©
2 // Copyright (C) 2001-2011 Vivien Mallet
3 //
4 // This file is part of the linear-algebra library Seldon,
5 // http://seldon.sourceforge.net/.
6 //
7 // Seldon is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 2.1 of the License, or (at your option)
10 // any later version.
11 //
12 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 // more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with Seldon. If not, see http://www.gnu.org/licenses/.
19 
20 
21 #ifndef SELDON_FILE_SPARSE_VECTOR_CXX
22 
23 #include "SparseVector.hxx"
24 
25 namespace Seldon
26 {
27 
28  /*********************
29  * MEMORY MANAGEMENT *
30  *********************/
31 
32 
34 
37  template <class T, class Allocator>
39  Vector<T, VectFull, Allocator>(i)
40  {
41 
42 #ifdef SELDON_CHECK_MEMORY
43  try
44  {
45 #endif
46 
47  this->index_ = AllocatorInt::allocate(i, this);
48 
49 #ifdef SELDON_CHECK_MEMORY
50  }
51  catch (...)
52  {
53  this->m_ = 0;
54  this->index_ = NULL;
55  this->data_ = NULL;
56  }
57 
58  if (this->index_ == NULL)
59  {
60  this->m_ = 0;
61  this->data_ = NULL;
62  }
63 
64  if (this->data_ == NULL && i != 0)
65  throw NoMemory("Vector<VectSparse>::Vector(int)",
66  string("Unable to allocate memory for a vector of size ")
67  + to_str(i * sizeof(T)) + " bytes ("
68  + to_str(i) + " elements).");
69 #endif
70 
71  }
72 
73 
75 
79  template <class T, class Allocator>
81  {
82  // 'data_' is released.
83 #ifdef SELDON_CHECK_MEMORY
84  try
85  {
86 #endif
87  if (this->data_ != NULL)
88  {
89  Allocator::deallocate(this->data_, this->m_);
90  this->data_ = NULL;
91  }
92 
93  if (index_ != NULL)
94  {
95  AllocatorInt::deallocate(index_, this->m_);
96  index_ = NULL;
97  }
98 
99  this->m_ = 0;
100 
101 #ifdef SELDON_CHECK_MEMORY
102  }
103  catch (...)
104  {
105  this->data_ = NULL;
106  index_ = NULL;
107  this->m_ = 0;
108  return;
109  }
110 #endif
111 
112  }
113 
114 
116 
122  template <class T, class Allocator>
124  {
125  // function implemented in the aim that explicit specialization
126  // of Reallocate can call ReallocateVector
127  if (i != this->m_)
128  {
129 
130  this->m_ = i;
131 
132 #ifdef SELDON_CHECK_MEMORY
133  try
134  {
135 #endif
136 
137  this->data_ =
138  reinterpret_cast<pointer>(Allocator::
139  reallocate(this->data_, i, this));
140 
141  index_
142  = reinterpret_cast<int*>(AllocatorInt::
143  reallocate(index_, i, this));
144 
145 #ifdef SELDON_CHECK_MEMORY
146  }
147  catch (...)
148  {
149  this->m_ = 0;
150  this->data_ = NULL;
151  this->index_ = NULL;
152  return;
153  }
154  if (this->data_ == NULL)
155  {
156  this->m_ = 0;
157  this->index_ = NULL;
158  return;
159  }
160 #endif
161 
162  }
163  }
164 
165 
167 
172  template <class T, class Allocator>
174  {
175  ResizeVector(n);
176  }
177 
178 
180 
185  template <class T, class Allocator>
187  {
188  // function implemented in the aim that explicit specialization
189  // of Resize can call ResizeVector
190  if (n == this->m_)
191  return;
192 
193  Vector<T, VectFull, Allocator> new_value(n);
194  Vector<int> new_index(n);
195  size_t Nmin = min(this->m_, n);
196  for (size_t i = 0; i < Nmin; i++)
197  {
198  new_value(i) = this->data_[i];
199  new_index(i) = index_[i];
200  }
201 
202  SetData(new_value, new_index);
203  }
204 
205 
222  template <class T, class Allocator>
224  ::SetData(size_t i, T* data, int* index)
225  {
226  this->Clear();
227 
228  this->m_ = i;
229 
230  this->data_ = data;
231  this->index_ = index;
232  }
233 
234 
246  template <class T, class Allocator>
247  template<class Allocator2>
250  {
251 
252 #ifdef SELDON_CHECK_BOUNDS
253  if (data.GetM() != index.GetM())
254  throw WrongDim("Vector<VectSparse>::SetData ",
255  string("The data vector and the index vector should")
256  + " have the same size.\n Size of the data vector: "
257  + to_str(data.GetM()) + "\n Size of index vector: "
258  + to_str(index.GetM()));
259 #endif
260 
261  SetData(data.GetM(), data.GetData(), index.GetData());
262  data.Nullify();
263  index.Nullify();
264  }
265 
266 
278  template <class T, class Allocator>
279  template<class Allocator2>
282  {
283  SetData(V.GetM(), V.GetData(), V.GetIndex());
284  }
285 
286 
288 
293  template <class T, class Allocator>
295  {
296  this->m_ = 0;
297  this->data_ = NULL;
298  this->index_ = NULL;
299  }
300 
301 
302  /**********************************
303  * ELEMENT ACCESS AND AFFECTATION *
304  **********************************/
305 
306 
308 
312  template <class T, class Allocator>
315  {
316  size_t k = 0;
317  T zero;
318  SetComplexZero(zero);
319  // Searching for the entry.
320  while (k < this->m_ && index_[k] < i)
321  k++;
322 
323  if (k >= this->m_ || index_[k] != i)
324  // The entry does not exist, a zero is returned.
325  return zero;
326 
327  return this->data_[k];
328  }
329 
330 
332 
338  template <class T, class Allocator>
341  {
342  size_t k = 0;
343  T zero;
344  SetComplexZero(zero);
345  // Searching for the entry.
346  while (k < this->m_ && index_[k] < i)
347  k++;
348 
349  if (k >= this->m_ || index_[k] != i)
350  // The entry does not exist, a zero is returned.
351  return zero;
352 
353  return this->data_[k];
354  }
355 
356 
358 
364  template <class T, class Allocator>
367  {
368  size_t k = 0;
369  T zero;
370  SetComplexZero(zero);
371  // Searching for the entry.
372  while (k < this->m_ && index_[k] < i)
373  k++;
374 
375  if (k >= this->m_ || index_[k] != i)
376  // The entry does not exist yet, so a zero entry is introduced.
377  AddInteraction(i, zero);
378 
379  return this->data_[k];
380  }
381 
382 
384 
390  template <class T, class Allocator>
393  {
394  size_t k = 0;
395  // Searching for the entry.
396  while (k < this->m_ && index_[k] < i)
397  k++;
398 
399  if (k >= this->m_ || index_[k] != i)
400  throw WrongArgument("Vector<VectSparse>::Val(int)",
401  "No reference to element " + to_str(i)
402  + " can be returned: it is a zero entry.");
403 
404  return this->data_[k];
405  }
406 
407 
409 
414  template <class T, class Allocator>
417  {
418  size_t k = 0;
419  // Searching for the entry.
420  while (k < this->m_ && index_[k] < i)
421  k++;
422 
423  if (k >= this->m_ || index_[k] != i)
424  throw WrongArgument("Vector<VectSparse>::Val(int)",
425  "the entry " + to_str(i) +
426  " does not belong to the sparsity pattern.");
427 
428 
429  return this->data_[k];
430  }
431 
432 
434 
439  template <class T, class Allocator>
442  {
443  size_t k = 0;
444  // Searching for the entry.
445  while (k < this->m_ && index_[k] < i)
446  k++;
447 
448  if (k >= this->m_ || index_[k] != i)
449  throw WrongArgument("Vector<VectSparse>::Val(int)",
450  "the entry " + to_str(i) +
451  " does not belong to the sparsity pattern.");
452 
453  return this->data_[k];
454  }
455 
456 
458 
463  template <class T, class Allocator> template <class T2, class Alloc2>
466  {
467  this->Reallocate(X.GetLength());
468  AllocatorInt::memorycpy(this->index_, X.GetIndex(), this->m_);
469  for (size_t i = 0; i < X.GetLength(); i++)
470  this->Value(i) = X.Value(i);
471  }
472 
473 
474  /************************
475  * CONVENIENT FUNCTIONS *
476  ************************/
477 
478 
480 
483  template <class T, class Allocator>
484  template <class T0>
487  {
488  this->Fill(x);
489 
490  return *this;
491  }
492 
493 
495  template <class T, class Allocator>
497  {
498  for (int i = 0; i < this->GetM(); i++)
499  cout << (Index(i) + 1) << ' ' << Value(i) << '\n';
500  }
501 
502 
504 
508  template <class T, class Allocator>
510  {
511  int new_size = this->m_;
512  Vector<T, VectFull, Allocator> values(new_size);
513  Vector<int> index(new_size);
514  for (int i = 0; i < new_size; i++)
515  {
516  values(i) = this->data_[i];
517  index(i) = index_[i];
518  }
519 
520  Seldon::Assemble(new_size, index, values);
521  index.Resize(new_size);
522  values.Resize(new_size);
523  SetData(values, index);
524  }
525 
526 
528 
532  template <class T, class Allocator> template<class T0>
534  {
535  size_t new_size = this->m_;
536  Vector<T, VectFull, Allocator> values(new_size);
537  Vector<int> index(new_size);
538  new_size = 0;
539  for (size_t i = 0; i < this->m_; i++)
540  if (abs(this->data_[i]) > epsilon)
541  {
542  values(new_size) = this->data_[i];
543  index(new_size) = index_[i];
544  new_size++;
545  }
546 
547  index.Resize(new_size);
548  values.Resize(new_size);
549  SetData(values, index);
550  }
551 
552 
554 
559  template <class T, class Allocator>
561  {
562  // Searching for the position where the entry may be.
563  size_t pos = 0;
564  while (pos < this->m_ && index_[pos] < i)
565  pos++;
566 
567  // If the entry already exists, adds 'val'.
568  if (pos < this->m_ && index_[pos] == i)
569  {
570  this->data_[pos] += val;
571  return;
572  }
573 
574  size_t k;
575 
576  // If the entry does not exist, the vector is reallocated.
577  Resize(this->m_ + 1);
578 
579  if (this->m_ >= 2)
580  for (k = this->m_-1; k > pos; k--)
581  {
582  this->data_[k] = this->data_[k-1];
583  this->index_[k] = this->index_[k-1];
584  }
585 
586  // The new entry.
587  this->index_[pos] = i;
588  this->data_[pos] = val;
589  }
590 
591 
593 
602  template <class T, class Allocator>
604  AddInteractionRow(size_t n, int* index, T* value, bool already_sorted)
605  {
606  Vector<int> ind;
608  ind.SetData(n, index);
609  val.SetData(n, value);
610  AddInteractionRow(n, ind, val, already_sorted);
611  ind.Nullify();
612  val.Nullify();
613  }
614 
615 
617 
626  template <class T, class Allocator>
627  template<class Allocator0>
629  AddInteractionRow(size_t n, const Vector<int>& index2,
630  const Vector<T, VectFull, Allocator0>& value2,
631  bool already_sorted)
632  {
633  Vector<int> index;
635 
636  if (!already_sorted)
637  {
638  // checking if numbers are sorted
639  already_sorted = true;
640  if (n >= 2)
641  for (size_t i = 0; i < n-1; i++)
642  if (index2(i+1) <= index2(i))
643  already_sorted = false;
644  }
645 
646  if (!already_sorted)
647  {
648  index.Reallocate(n);
649  value.Reallocate(n);
650  for (size_t i = 0; i < n; i++)
651  {
652  index(i) = index2(i);
653  value(i) = value2(i);
654  }
655 
656  // Sorts the values to be added according to their indices.
657  int ni = n; Seldon::Assemble(ni, index, value); n = ni;
658  }
659  else
660  {
661  index.SetData(n, index2.GetData());
662  value.SetData(n, value2.GetData());
663  }
664 
665  // Values that already have an entry
666 
667  // Number of values to be added without entry.
668  size_t Nnew = 0;
669  Vector<bool> new_index(n);
670  new_index.Fill(true);
671  size_t k = 0;
672  for (size_t j = 0; j < n; j++)
673  {
674  while (k < this->m_ && index_[k] < index(j))
675  k++;
676 
677  if (k < this->m_ && index(j) == index_[k])
678  {
679  new_index(j) = false;
680  this->data_[k] += value(j);
681  }
682  else
683  Nnew++;
684  }
685 
686  if (Nnew > 0)
687  {
688  // Some values to be added have no entry yet.
689  Vector<T> new_val(this->m_ + Nnew);
690  Vector<int> new_ind(this->m_ + Nnew);
691  int nb = 0;
692  k = 0;
693  for (size_t j = 0; j < n; j++)
694  if (new_index(j))
695  {
696  while (k < this->m_ && index_[k] < index(j))
697  {
698  new_ind(nb) = index_[k];
699  new_val(nb) = this->data_[k];
700  k++;
701  nb++;
702  }
703 
704  // The new entry.
705  new_ind(nb) = index(j);
706  new_val(nb) = value(j);
707  nb++;
708  }
709 
710  // Last entries.
711  while (k < this->m_)
712  {
713  new_ind(nb) = index_[k];
714  new_val(nb) = this->data_[k];
715  k++;
716  nb++;
717  }
718 
719  SetData(new_val, new_ind);
720  }
721 
722  if (already_sorted)
723  {
724  index.Nullify();
725  value.Nullify();
726  }
727  }
728 
729 
731 
734  template <class T, class Allocator>
735  typename ClassComplexType<T>::Treal
737  {
738  typename ClassComplexType<T>::Treal res(0);
739  for (size_t i = 0; i < this->m_; i++)
740  res = max(res, abs(this->data_[i]));
741 
742  return res;
743  }
744 
745 
747 
750  template <class T, class Allocator>
752  {
753 
754 #ifdef SELDON_CHECK_DIMENSIONS
755  if (this->GetLength() == 0)
756  throw WrongDim("Vector<VectSparse>::GetNormInfIndex()",
757  "Vector is null.");
758 #endif
759 
760  typename ClassComplexType<T>::Treal res(0), temp;
761  size_t j = 0;
762  for (size_t i = 0; i < this->GetLength(); i++)
763  {
764  temp = res;
765  res = max(res, abs(this->data_[i]));
766  if (temp != res) j = i;
767  }
768 
769  return this->index_[j];
770  }
771 
772 
773  /**************************
774  * OUTPUT/INPUT FUNCTIONS *
775  **************************/
776 
777 
779 
784  template <class T, class Allocator>
785  void Vector<T, VectSparse, Allocator>::Write(string FileName) const
786  {
787  ofstream FileStream;
788  FileStream.open(FileName.c_str(), ofstream::binary);
789 
790 #ifdef SELDON_CHECK_IO
791  // Checks if the file was opened.
792  if (!FileStream.is_open())
793  throw IOError("Vector<VectSparse>::Write(string FileName)",
794  string("Unable to open file \"") + FileName + "\".");
795 #endif
796 
797  this->Write(FileStream);
798 
799  FileStream.close();
800  }
801 
802 
804 
809  template <class T, class Allocator>
810  void Vector<T, VectSparse, Allocator>::Write(ostream& stream) const
811  {
812 
813 #ifdef SELDON_CHECK_IO
814  // Checks if the stream is ready.
815  if (!stream.good())
816  throw IOError("Vector<VectSparse>::Write(ostream& stream)",
817  "Stream is not ready.");
818 #endif
819 
820  int n = this->m_;
821  stream.write(reinterpret_cast<char*>(&n),
822  sizeof(int));
823 
824  stream.write(reinterpret_cast<char*>(this->index_),
825  this->m_ * sizeof(int));
826 
827  stream.write(reinterpret_cast<char*>(this->data_),
828  this->m_ * sizeof(value_type));
829 
830 #ifdef SELDON_CHECK_IO
831  // Checks if data was written.
832  if (!stream.good())
833  throw IOError("Vector<VectSparse>::Write(ostream& stream)",
834  "Output operation failed.");
835 #endif
836 
837  }
838 
839 
841 
846  template <class T, class Allocator>
848  {
849  ofstream FileStream;
850  FileStream.precision(cout.precision());
851  FileStream.flags(cout.flags());
852  FileStream.open(FileName.c_str());
853 
854 #ifdef SELDON_CHECK_IO
855  // Checks if the file was opened.
856  if (!FileStream.is_open())
857  throw IOError("Vector<VectSparse>::WriteText(string FileName)",
858  string("Unable to open file \"") + FileName + "\".");
859 #endif
860 
861  this->WriteText(FileStream);
862 
863  FileStream.close();
864  }
865 
866 
868 
873  template <class T, class Allocator>
875  {
876 
877 #ifdef SELDON_CHECK_IO
878  // Checks if the stream is ready.
879  if (!stream.good())
880  throw IOError("Vector<VectSparse>::WriteText(ostream& stream)",
881  "Stream is not ready.");
882 #endif
883 
884  // First entries.
885  for (size_t i = 0; i < this->m_; i++)
886  stream << (Index(i) + 1) << " " << Value(i) << '\n';
887 
888 #ifdef SELDON_CHECK_IO
889  // Checks if data was written.
890  if (!stream.good())
891  throw IOError("Vector<VectSparse>::WriteText(ostream& stream)",
892  "Output operation failed.");
893 #endif
894 
895  }
896 
897 
899 
903  template <class T, class Allocator>
905  {
906  ifstream FileStream;
907  FileStream.open(FileName.c_str(), ifstream::binary);
908 
909 #ifdef SELDON_CHECK_IO
910  // Checks if the file was opened.
911  if (!FileStream.is_open())
912  throw IOError("Vector<VectSparse>::Read(string FileName)",
913  string("Unable to open file \"") + FileName + "\".");
914 #endif
915 
916  this->Read(FileStream);
917 
918  FileStream.close();
919  }
920 
921 
923 
927  template <class T, class Allocator>
929  {
930 
931 #ifdef SELDON_CHECK_IO
932  // Checks if the stream is ready.
933  if (!stream.good())
934  throw IOError("Vector<VectSparse>::Read(istream& stream)",
935  "Stream is not ready.");
936 #endif
937 
938  int m;
939  stream.read(reinterpret_cast<char*>(&m), sizeof(int));
940  this->Reallocate(m);
941 
942  stream.read(reinterpret_cast<char*>(this->index_), m * sizeof(int));
943 
944  stream.read(reinterpret_cast<char*>(this->data_),
945  m * sizeof(value_type));
946 
947 #ifdef SELDON_CHECK_IO
948  // Checks if data was read.
949  if (!stream.good())
950  throw IOError("Vector<VectSparse>::Read(istream& stream)",
951  "Input operation failed.");
952 #endif
953 
954  }
955 
956 
958 
962  template <class T, class Allocator>
964  {
965  ifstream FileStream;
966  FileStream.open(FileName.c_str());
967 
968 #ifdef SELDON_CHECK_IO
969  // Checks if the file was opened.
970  if (!FileStream.is_open())
971  throw IOError("Vector<VectSparse>::ReadText(string FileName)",
972  string("Unable to open file \"") + FileName + "\".");
973 #endif
974 
975  this->ReadText(FileStream);
976 
977  FileStream.close();
978  }
979 
980 
982 
986  template <class T, class Allocator>
988  {
989  Clear();
990 
991 #ifdef SELDON_CHECK_IO
992  // Checks if the stream is ready.
993  if (!stream.good())
994  throw IOError("Vector<VectSparse>::ReadText(istream& stream)",
995  "Stream is not ready.");
996 #endif
997 
999  Vector<int> index;
1000  T entry;
1001  int ind = 0;
1002  int nb_elt = 0;
1003  while (!stream.eof())
1004  {
1005  // New entry is read.
1006  stream >> ind >> entry;
1007 
1008  if (stream.fail())
1009  break;
1010  else
1011  {
1012 #ifdef SELDON_CHECK_IO
1013  if (ind < 1)
1014  throw IOError(string("Vector<VectSparse>::ReadText") +
1015  "(istream& stream)",
1016  string("Index should be greater ")
1017  + "than 0 but is equal to " + to_str(ind) + ".");
1018 #endif
1019 
1020  nb_elt++;
1021  ind--;
1022 
1023  // Inserting a new element.
1024  if (nb_elt > values.GetM())
1025  {
1026  values.Resize(2 * nb_elt);
1027  index.Resize(2 * nb_elt);
1028  }
1029 
1030  values(nb_elt - 1) = entry;
1031  index(nb_elt - 1) = ind;
1032  }
1033  }
1034 
1035  if (nb_elt > 0)
1036  {
1037  // Allocating to the right size.
1038  this->Reallocate(nb_elt);
1039  for (int i = 0; i < nb_elt; i++)
1040  {
1041  Index(i) = index(i);
1042  Value(i) = values(i);
1043  }
1044  }
1045  }
1046 
1047 
1049 
1054  template <class T, class Allocator>
1055  ostream& operator << (ostream& out,
1057  {
1058  for (size_t i = 0; i < V.GetLength(); i++)
1059  out << (V.Index(i) + 1) << ' ' << V.Value(i) << '\n';
1060 
1061  return out;
1062  }
1063 
1064 } // namespace Seldon.
1065 
1066 #define SELDON_FILE_SPARSE_VECTOR_CXX
1067 #endif
Seldon::to_str
std::string to_str(const T &input)
Converts most types to string.
Definition: CommonInline.cxx:137
Seldon::Vector_Base::GetM
long GetM() const
Returns the number of elements.
Definition: VectorInline.cxx:131
Seldon::Vector
Definition: SeldonHeader.hxx:207
Seldon::Vector< T, VectFull, Allocator >::Nullify
void Nullify()
Clears the vector without releasing memory.
Definition: VectorInline.cxx:476
Seldon::Vector< T, VectSparse, Allocator >::Index
int & Index(int i)
Access operator.
Definition: SparseVectorInline.cxx:134
Seldon::VectFull
Definition: StorageInline.cxx:74
Seldon::Vector< T, VectFull, Allocator >::Resize
void Resize(size_t i)
Changes the length of the vector, and keeps previous values.
Definition: Vector.cxx:34
Seldon::Vector< T, VectFull, Allocator >
Full vector class.
Definition: Vector.hxx:88
Seldon::Vector_Base::GetLength
size_t GetLength() const
Returns the number of elements.
Definition: VectorInline.cxx:142
Seldon::WrongArgument
Definition: Errors.hxx:76
Seldon::Vector< T, VectSparse, Allocator >
Sparse vector class.
Definition: SparseVector.hxx:29
Seldon::WrongDim
Definition: Errors.hxx:102
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::operator<<
ostream & operator<<(ostream &out, const Array< T, N, Allocator > &A)
operator<< overloaded for a 3D array.
Definition: Array.cxx:1617
Seldon::IOError
Definition: Errors.hxx:150
Seldon::NoMemory
Definition: Errors.hxx:90
Seldon::Vector< T, VectSparse, Allocator >::Value
reference Value(int i)
Access operator.
Definition: SparseVectorInline.cxx:99