Matrix_SymSparse.cxx
1 // Copyright (C) 2001-2011 Vivien Mallet
2 // Copyright (C) 2003-2011 Marc DuruflĂ©
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_MATRIX_SYMSPARSE_CXX
22 
23 #include "Matrix_SymSparse.hxx"
24 
25 namespace Seldon
26 {
27 
28 
29  /*********************
30  * MEMORY MANAGEMENT *
31  *********************/
32 
33 
35 
47  template <class T, class Prop, class Storage, class Allocator>
48  template <class Storage0, class Allocator0,
49  class Storage1, class Allocator1,
50  class Storage2, class Allocator2>
52  Matrix_SymSparse(int i, int j,
56  Matrix_Base<T, Allocator>(i, j)
57  {
58  nz_ = values.GetLength();
59 
60 #ifdef SELDON_CHECK_DIMENSIONS
61  // Checks whether vector sizes are acceptable.
62 
63  if (ind.GetLength() != nz_)
64  {
65  this->m_ = 0;
66  this->n_ = 0;
67  nz_ = 0;
68  ptr_ = NULL;
69  ind_ = NULL;
70  this->data_ = NULL;
71  throw WrongDim(string("Matrix_SymSparse::Matrix_SymSparse(int, int, ")
72  + "const Vector&, const Vector&, const Vector&)",
73  string("There are ") + to_str(nz_) + " values but "
74  + to_str(ind.GetLength()) + " row or column indices.");
75  }
76 
77  if (ptr.GetLength() - 1 != i)
78  {
79  this->m_ = 0;
80  this->n_ = 0;
81  nz_ = 0;
82  ptr_ = NULL;
83  ind_ = NULL;
84  this->data_ = NULL;
85  throw WrongDim(string("Matrix_SymSparse::Matrix_SymSparse(int, int, ")
86  + "const Vector&, const Vector&, const Vector&)",
87  string("The vector of start indices contains ")
88  + to_str(ptr.GetLength()-1) + string(" row or column ")
89  + string("start indices (plus the number of non-zero")
90  + " entries) but there are " + to_str(i)
91  + " rows or columns ("
92  + to_str(i) + " by " + to_str(i) + " matrix).");
93  }
94 
95  if (static_cast<long int>(2 * nz_ - 2) / static_cast<long int>(i + 1)
96  >= static_cast<long int>(i))
97  {
98  this->m_ = 0;
99  this->n_ = 0;
100  nz_ = 0;
101  ptr_ = NULL;
102  ind_ = NULL;
103  this->data_ = NULL;
104  throw WrongDim(string("Matrix_SymSparse::Matrix_SymSparse(int, int, ")
105  + "const Vector&, const Vector&, const Vector&)",
106  string("There are more values (")
107  + to_str(values.GetLength())
108  + " values) than elements in the matrix ("
109  + to_str(i) + " by " + to_str(i) + ").");
110  }
111 #endif
112 
113  this->ptr_ = ptr.GetData();
114  this->ind_ = ind.GetData();
115  this->data_ = values.GetData();
116 
117  ptr.Nullify();
118  ind.Nullify();
119  values.Nullify();
120  }
121 
122 
124  template <class T, class Prop, class Storage, class Allocator>
127  : Matrix_Base<T, Allocator>()
128  {
129  this->m_ = 0;
130  this->n_ = 0;
131  this->nz_ = 0;
132  ptr_ = NULL;
133  ind_ = NULL;
134  this->Copy(A);
135  }
136 
137 
139 
142  template <class T, class Prop, class Storage, class Allocator>
144  {
145 #ifdef SELDON_CHECK_MEMORY
146  try
147  {
148 #endif
149 
150  if (ptr_ != NULL)
151  {
152  AllocatorLong::deallocate(ptr_, this->m_+1);
153  ptr_ = NULL;
154  }
155 
156 #ifdef SELDON_CHECK_MEMORY
157  }
158  catch (...)
159  {
160  ptr_ = NULL;
161  }
162 #endif
163 
164 #ifdef SELDON_CHECK_MEMORY
165  try
166  {
167 #endif
168 
169  if (ind_ != NULL)
170  {
171  AllocatorInt::deallocate(ind_, this->nz_);
172  ind_ = NULL;
173  }
174 
175 #ifdef SELDON_CHECK_MEMORY
176  }
177  catch (...)
178  {
179  ind_ = NULL;
180  }
181 #endif
182 
183 #ifdef SELDON_CHECK_MEMORY
184  try
185  {
186 #endif
187 
188  if (this->data_ != NULL)
189  {
190  Allocator::deallocate(this->data_, nz_);
191  this->data_ = NULL;
192  }
193 
194 #ifdef SELDON_CHECK_MEMORY
195  }
196  catch (...)
197  {
198  this->nz_ = 0;
199  this->data_ = NULL;
200  }
201 #endif
202 
203  this->m_ = 0;
204  this->n_ = 0;
205  this->nz_ = 0;
206  }
207 
208 
210 
221  template <class T, class Prop, class Storage, class Allocator>
222  template <class Storage0, class Allocator0,
223  class Storage1, class Allocator1,
224  class Storage2, class Allocator2>
226  SetData(int i, int j,
230  {
231  this->Clear();
232  this->m_ = i;
233  this->n_ = i;
234  this->nz_ = values.GetLength();
235 
236 #ifdef SELDON_CHECK_DIMENSIONS
237  // Checks whether vector sizes are acceptable.
238 
239  if (ind.GetM() != nz_)
240  {
241  this->m_ = 0;
242  this->n_ = 0;
243  nz_ = 0;
244  ptr_ = NULL;
245  ind_ = NULL;
246  this->data_ = NULL;
247  throw WrongDim(string("Matrix_SymSparse::Reallocate(int, int, ")
248  + "const Vector&, const Vector&, const Vector&)",
249  string("There are ") + to_str(nz_) + " values but "
250  + to_str(ind.GetLength()) + " row or column indices.");
251  }
252 
253  if (ptr.GetM()-1 != i)
254  {
255  this->m_ = 0;
256  this->n_ = 0;
257  nz_ = 0;
258  ptr_ = NULL;
259  ind_ = NULL;
260  this->data_ = NULL;
261  throw WrongDim(string("Matrix_SymSparse::Reallocate(int, int, ")
262  + "const Vector&, const Vector&, const Vector&)",
263  string("The vector of start indices contains ")
264  + to_str(ptr.GetLength()-1) + string(" row or column")
265  + string(" start indices (plus the number of")
266  + string(" non-zero entries) but there are ")
267  + to_str(i) + " rows or columns ("
268  + to_str(i) + " by " + to_str(i) + " matrix).");
269  }
270 
271  if (static_cast<long int>(2 * nz_ - 2) / static_cast<long int>(i + 1)
272  >= static_cast<long int>(i))
273  {
274  this->m_ = 0;
275  this->n_ = 0;
276  nz_ = 0;
277  ptr_ = NULL;
278  ind_ = NULL;
279  this->data_ = NULL;
280  throw WrongDim(string("Matrix_SymSparse::Reallocate(int, int, ")
281  + "const Vector&, const Vector&, const Vector&)",
282  string("There are more values (")
283  + to_str(values.GetLength())
284  + " values) than elements in the matrix ("
285  + to_str(i) + " by " + to_str(i) + ").");
286  }
287 #endif
288 
289  this->ptr_ = ptr.GetData();
290  this->ind_ = ind.GetData();
291  this->data_ = values.GetData();
292 
293  ptr.Nullify();
294  ind.Nullify();
295  values.Nullify();
296  }
297 
298 
300 
314  template <class T, class Prop, class Storage, class Allocator>
316  ::SetData(int i, int j, long nz,
318  ::pointer values, long* ptr, int* ind)
319  {
320  this->Clear();
321 
322  this->m_ = i;
323  this->n_ = i;
324 
325  this->nz_ = nz;
326 
327  this->data_ = values;
328  ind_ = ind;
329  ptr_ = ptr;
330  }
331 
332 
334 
338  template <class T, class Prop, class Storage, class Allocator>
340  {
341  this->data_ = NULL;
342  this->m_ = 0;
343  this->n_ = 0;
344  nz_ = 0;
345  ptr_ = NULL;
346  ind_ = NULL;
347  }
348 
349 
351 
355  template <class T, class Prop, class Storage, class Allocator>
357  {
358  // clearing previous entries
359  Clear();
360 
361  this->m_ = i;
362  this->n_ = i;
363 
364  // we try to allocate ptr_
365 #ifdef SELDON_CHECK_MEMORY
366  try
367  {
368 #endif
369 
370  ptr_ = reinterpret_cast<long*>( AllocatorLong::
371  allocate(i+1, this) );
372 
373 #ifdef SELDON_CHECK_MEMORY
374  }
375  catch (...)
376  {
377  this->m_ = 0;
378  this->n_ = 0;
379  nz_ = 0;
380  ptr_ = NULL;
381  ind_ = NULL;
382  this->data_ = NULL;
383  }
384  if (ptr_ == NULL)
385  {
386  this->m_ = 0;
387  this->n_ = 0;
388  nz_ = 0;
389  ind_ = NULL;
390  this->data_ = NULL;
391  }
392  if (ptr_ == NULL && i != 0 && j != 0)
393  throw NoMemory("Matrix_SymSparse::Reallocate(int, int)",
394  string("Unable to allocate ")
395  + to_str(sizeof(int) * (i+1) )
396  + " bytes to store " + to_str(i+1)
397  + " row or column start indices, for a "
398  + to_str(i) + " by " + to_str(i) + " matrix.");
399 #endif
400 
401  // then filing ptr_ with 0
402  for (int k = 0; k <= i; k++)
403  ptr_[k] = 0;
404  }
405 
406 
408 
413  template <class T, class Prop, class Storage, class Allocator>
415  ::Reallocate(int i, int j, long nz)
416  {
417  // clearing previous entries
418  Clear();
419 
420  this->nz_ = nz;
421  this->m_ = i;
422  this->n_ = i;
423 
424 #ifdef SELDON_CHECK_DIMENSIONS
425  if (static_cast<long int>(2 * nz_ - 2) / static_cast<long int>(i + 1)
426  >= static_cast<long int>(i))
427  {
428  this->m_ = 0;
429  this->n_ = 0;
430  nz_ = 0;
431  ptr_ = NULL;
432  ind_ = NULL;
433  this->data_ = NULL;
434  throw WrongDim("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
435  string("There are more values (") + to_str(nz)
436  + string(" values) than elements in the upper")
437  + " part of the matrix ("
438  + to_str(i) + " by " + to_str(i) + ").");
439  }
440 #endif
441 
442 #ifdef SELDON_CHECK_MEMORY
443  try
444  {
445 #endif
446 
447  ptr_ = reinterpret_cast<long*>( AllocatorLong::
448  allocate(i + 1, this) );
449 
450 #ifdef SELDON_CHECK_MEMORY
451  }
452  catch (...)
453  {
454  this->m_ = 0;
455  this->n_ = 0;
456  nz_ = 0;
457  ptr_ = NULL;
458  ind_ = NULL;
459  this->data_ = NULL;
460  }
461  if (ptr_ == NULL)
462  {
463  this->m_ = 0;
464  this->n_ = 0;
465  nz_ = 0;
466  ind_ = NULL;
467  this->data_ = NULL;
468  }
469  if (ptr_ == NULL && i != 0)
470  throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
471  string("Unable to allocate ")
472  + to_str(sizeof(int) * (i+1) ) + " bytes to store "
473  + to_str(i+1) + " row or column start indices, for a "
474  + to_str(i) + " by " + to_str(i) + " matrix.");
475 #endif
476 
477 #ifdef SELDON_CHECK_MEMORY
478  try
479  {
480 #endif
481 
482  ind_ = reinterpret_cast<int*>( AllocatorInt::
483  allocate(nz_, this) );
484 
485 #ifdef SELDON_CHECK_MEMORY
486  }
487  catch (...)
488  {
489  this->m_ = 0;
490  this->n_ = 0;
491  nz_ = 0;
492  AllocatorLong::deallocate(ptr_, i+1);
493  ptr_ = NULL;
494  ind_ = NULL;
495  this->data_ = NULL;
496  }
497  if (ind_ == NULL)
498  {
499  this->m_ = 0;
500  this->n_ = 0;
501  nz_ = 0;
502  AllocatorLong::deallocate(ptr_, i+1);
503  ptr_ = NULL;
504  this->data_ = NULL;
505  }
506  if (ind_ == NULL && i != 0)
507  throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
508  string("Unable to allocate ") + to_str(sizeof(int) * nz)
509  + " bytes to store " + to_str(nz)
510  + " row or column indices, for a "
511  + to_str(i) + " by " + to_str(i) + " matrix.");
512 #endif
513 
514 #ifdef SELDON_CHECK_MEMORY
515  try
516  {
517 #endif
518 
519  this->data_ = Allocator::allocate(nz_, this);
520 
521 #ifdef SELDON_CHECK_MEMORY
522  }
523  catch (...)
524  {
525  this->m_ = 0;
526  this->n_ = 0;
527  AllocatorLong::deallocate(ptr_, i+1);
528  ptr_ = NULL;
529  AllocatorInt::deallocate(ind_, nz);
530  ind_ = NULL;
531  this->data_ = NULL;
532  }
533  if (this->data_ == NULL)
534  {
535  this->m_ = 0;
536  this->n_ = 0;
537  AllocatorLong::deallocate(ptr_, i+1);
538  ptr_ = NULL;
539  AllocatorInt::deallocate(ind_, nz);
540  ind_ = NULL;
541  }
542  if (this->data_ == NULL && i != 0)
543  throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
544  string("Unable to allocate ") + to_str(sizeof(int) * nz)
545  + " bytes to store " + to_str(nz) + " values, for a "
546  + to_str(i) + " by " + to_str(i) + " matrix.");
547 #endif
548 
549  // then filing ptr_ with 0
550  for (int k = 0; k <= i; k++)
551  ptr_[k] = 0;
552  }
553 
554 
556 
560  template <class T, class Prop, class Storage, class Allocator>
562  {
563  if (i < this->m_)
564  Resize(i, i, ptr_[i]);
565  else
566  Resize(i, i, nz_);
567  }
568 
569 
571 
576  template <class T, class Prop, class Storage, class Allocator>
578  ::Resize(int i, int j, long nz)
579  {
580 
581 #ifdef SELDON_CHECK_DIMENSIONS
582  if (static_cast<long int>(2 * nz - 2) / static_cast<long int>(i + 1)
583  >= static_cast<long int>(i))
584  {
585  this->m_ = 0;
586  this->n_ = 0;
587  nz_ = 0;
588  ptr_ = NULL;
589  ind_ = NULL;
590  this->data_ = NULL;
591  throw WrongDim("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
592  string("There are more values (") + to_str(nz)
593  + string(" values) than elements in the upper")
594  + " part of the matrix ("
595  + to_str(i) + " by " + to_str(i) + ").");
596  }
597 #endif
598 
599  if (nz != nz_)
600  {
601  // trying to resize ind_ and data_
602 #ifdef SELDON_CHECK_MEMORY
603  try
604  {
605 #endif
606 
607  ind_ = reinterpret_cast<int*>( AllocatorInt::reallocate(ind_, nz) );
608 
609 #ifdef SELDON_CHECK_MEMORY
610  }
611  catch (...)
612  {
613  this->m_ = 0;
614  this->n_ = 0;
615  nz_ = 0;
616  AllocatorLong::deallocate(ptr_, i+1);
617  ptr_ = NULL;
618  ind_ = NULL;
619  this->data_ = NULL;
620  }
621  if (ind_ == NULL)
622  {
623  this->m_ = 0;
624  this->n_ = 0;
625  nz_ = 0;
626  AllocatorLong::deallocate(ptr_, i+1);
627  ptr_ = NULL;
628  this->data_ = NULL;
629  }
630  if (ind_ == NULL && i != 0 && j != 0)
631  throw NoMemory("Matrix_SymSparse::Resize(int, int, int)",
632  string("Unable to allocate ") + to_str(sizeof(int) * nz)
633  + " bytes to store " + to_str(nz)
634  + " row or column indices, for a "
635  + to_str(i) + " by " + to_str(j) + " matrix.");
636 #endif
637 
639  val.SetData(nz_, this->data_);
640  val.Resize(nz);
641 
642  this->data_ = val.GetData();
643  nz_ = nz;
644  val.Nullify();
645  }
646 
647 
648  if (this->m_ != i)
649  {
650 #ifdef SELDON_CHECK_MEMORY
651  try
652  {
653 #endif
654  // trying to resize ptr_
655  ptr_ = reinterpret_cast<long*>( AllocatorLong::reallocate(ptr_, i+1) );
656 
657 #ifdef SELDON_CHECK_MEMORY
658  }
659  catch (...)
660  {
661  this->m_ = 0;
662  this->n_ = 0;
663  nz_ = 0;
664  ptr_ = NULL;
665  ind_ = NULL;
666  this->data_ = NULL;
667  }
668  if (ptr_ == NULL)
669  {
670  this->m_ = 0;
671  this->n_ = 0;
672  nz_ = 0;
673  ind_ = NULL;
674  this->data_ = NULL;
675  }
676  if (ptr_ == NULL && i != 0 && j != 0)
677  throw NoMemory("Matrix_SymSparse::Resize(int, int)",
678  string("Unable to allocate ")
679  + to_str(sizeof(int) * (i+1) )
680  + " bytes to store " + to_str(i+1)
681  + " row or column start indices, for a "
682  + to_str(i) + " by " + to_str(i) + " matrix.");
683 #endif
684 
685  // then filing last values of ptr_ with nz_
686  for (int k = this->m_; k <= i; k++)
687  ptr_[k] = this->nz_;
688  }
689 
690  this->m_ = i;
691  this->n_ = i;
692  }
693 
694 
696  template <class T, class Prop, class Storage, class Allocator>
699  {
700  this->Clear();
701  long nz = A.GetNonZeros();
702  int i = A.GetM();
703  int j = A.GetN();
704  this->nz_ = nz;
705  this->m_ = i;
706  this->n_ = j;
707  if ((i == 0)||(j == 0))
708  {
709  this->m_ = 0;
710  this->n_ = 0;
711  this->nz_ = 0;
712  return;
713  }
714 
715 #ifdef SELDON_CHECK_DIMENSIONS
716  if (static_cast<long int>(2 * nz_ - 2) / static_cast<long int>(i + 1)
717  >= static_cast<long int>(i))
718  {
719  this->m_ = 0;
720  this->n_ = 0;
721  nz_ = 0;
722  ptr_ = NULL;
723  ind_ = NULL;
724  this->data_ = NULL;
725  throw WrongDim("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
726  string("There are more values (") + to_str(nz)
727  + string(" values) than elements in the upper")
728  + " part of the matrix ("
729  + to_str(i) + " by " + to_str(i) + ").");
730  }
731 #endif
732 
733 #ifdef SELDON_CHECK_MEMORY
734  try
735  {
736 #endif
737 
738  ptr_ = reinterpret_cast<long*>( AllocatorLong::allocate(i + 1, this) );
739  AllocatorLong::memorycpy(this->ptr_, A.ptr_, (i + 1));
740 
741 #ifdef SELDON_CHECK_MEMORY
742  }
743  catch (...)
744  {
745  this->m_ = 0;
746  this->n_ = 0;
747  nz_ = 0;
748  ptr_ = NULL;
749  ind_ = NULL;
750  this->data_ = NULL;
751  }
752  if (ptr_ == NULL)
753  {
754  this->m_ = 0;
755  this->n_ = 0;
756  nz_ = 0;
757  ind_ = NULL;
758  this->data_ = NULL;
759  }
760  if (ptr_ == NULL && i != 0)
761  throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
762  string("Unable to allocate ")
763  + to_str(sizeof(int) * (i+1) ) + " bytes to store "
764  + to_str(i+1) + " row or column start indices, for a "
765  + to_str(i) + " by " + to_str(i) + " matrix.");
766 #endif
767 
768 #ifdef SELDON_CHECK_MEMORY
769  try
770  {
771 #endif
772 
773  ind_ = reinterpret_cast<int*>( AllocatorInt::allocate(nz_, this) );
774  AllocatorInt::memorycpy(this->ind_, A.ind_, nz_);
775 
776 #ifdef SELDON_CHECK_MEMORY
777  }
778  catch (...)
779  {
780  this->m_ = 0;
781  this->n_ = 0;
782  nz_ = 0;
783  AllocatorLong::deallocate(ptr_, i+1);
784  ptr_ = NULL;
785  ind_ = NULL;
786  this->data_ = NULL;
787  }
788  if (ind_ == NULL)
789  {
790  this->m_ = 0;
791  this->n_ = 0;
792  nz_ = 0;
793  AllocatorLong::deallocate(ptr_, i+1);
794  ptr_ = NULL;
795  this->data_ = NULL;
796  }
797  if (ind_ == NULL && i != 0)
798  throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
799  string("Unable to allocate ") + to_str(sizeof(int) * nz)
800  + " bytes to store " + to_str(nz)
801  + " row or column indices, for a "
802  + to_str(i) + " by " + to_str(i) + " matrix.");
803 #endif
804 
805 #ifdef SELDON_CHECK_MEMORY
806  try
807  {
808 #endif
809 
810  this->data_ = Allocator::allocate(nz_, this);
811  Allocator::memorycpy(this->data_, A.data_, nz_);
812 
813 #ifdef SELDON_CHECK_MEMORY
814  }
815  catch (...)
816  {
817  this->m_ = 0;
818  this->n_ = 0;
819  AllocatorLong::deallocate(ptr_, i+1);
820  ptr_ = NULL;
821  AllocatorInt::deallocate(ind_, nz);
822  ind_ = NULL;
823  this->data_ = NULL;
824  }
825  if (this->data_ == NULL)
826  {
827  this->m_ = 0;
828  this->n_ = 0;
829  AllocatorLong::deallocate(ptr_, i+1);
830  ptr_ = NULL;
831  AllocatorInt::deallocate(ind_, nz);
832  ind_ = NULL;
833  }
834  if (this->data_ == NULL && i != 0)
835  throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
836  string("Unable to allocate ") + to_str(sizeof(int) * nz)
837  + " bytes to store " + to_str(nz) + " values, for a "
838  + to_str(i) + " by " + to_str(i) + " matrix.");
839 #endif
840 
841  }
842 
843 
845  template<class T, class Prop, class Storage, class Allocator>
847  {
848  size_t taille = sizeof(*this) + this->GetPtrSize()*sizeof(long);
849  int coef = sizeof(T) + sizeof(int); // for each non-zero entry
850  taille += coef*size_t(this->nz_);
851  return taille;
852  }
853 
854 
856  template<class T, class Prop, class Storage, class Allocator>
858  {
859  Ptr.Reallocate(this->m_+1);
860  for (int i = 0; i <= this->m_; i++)
861  Ptr(i) = ptr_[i];
862  }
863 
864 
865  /**********************************
866  * ELEMENT ACCESS AND AFFECTATION *
867  **********************************/
868 
869 
871 
877  template <class T, class Prop, class Storage, class Allocator>
878  const typename
879  Matrix_SymSparse<T, Prop, Storage, Allocator>::value_type
881  int j) const
882  {
883 
884 #ifdef SELDON_CHECK_BOUNDS
885  if (i < 0 || i >= this->m_)
886  throw WrongRow("Matrix_SymSparse::operator()",
887  string("Index should be in [0, ") + to_str(this->m_-1)
888  + "], but is equal to " + to_str(i) + ".");
889  if (j < 0 || j >= this->n_)
890  throw WrongCol("Matrix_SymSparse::operator()",
891  string("Index should be in [0, ") + to_str(this->n_-1)
892  + "], but is equal to " + to_str(j) + ".");
893 #endif
894 
895  long k, l;
896  long a, b;
897  T zero;
898  SetComplexZero(zero);
899 
900  // Only the upper part is stored.
901  if (i > j)
902  {
903  l = i;
904  i = j;
905  j = l;
906  }
907 
908  a = ptr_[Storage::GetFirst(i, j)];
909  b = ptr_[Storage::GetFirst(i, j) + 1];
910 
911  if (a == b)
912  return zero;
913 
914  l = Storage::GetSecond(i, j);
915 
916  for (k = a; (k<b-1) && (ind_[k]<l); k++);
917 
918  if (ind_[k] == l)
919  return this->data_[k];
920  else
921  return zero;
922  }
923 
924 
926 
934  template <class T, class Prop, class Storage, class Allocator>
935  typename Matrix_SymSparse<T, Prop, Storage, Allocator>::value_type&
937  {
938 
939 #ifdef SELDON_CHECK_BOUNDS
940  if (i < 0 || i >= this->m_)
941  throw WrongRow("Matrix_SymSparse::Val(int, int)",
942  string("Index should be in [0, ") + to_str(this->m_-1)
943  + "], but is equal to " + to_str(i) + ".");
944  if (j < 0 || j >= this->n_)
945  throw WrongCol("Matrix_SymSparse::Val(int, int)",
946  string("Index should be in [0, ") + to_str(this->n_-1)
947  + "], but is equal to " + to_str(j) + ".");
948 #endif
949 
950  long k, l;
951  long a, b;
952 
953  // Only the upper part is stored.
954  if (i > j)
955  {
956  l = i;
957  i = j;
958  j = l;
959  }
960 
961  a = ptr_[Storage::GetFirst(i, j)];
962  b = ptr_[Storage::GetFirst(i, j) + 1];
963 
964  if (a == b)
965  throw WrongArgument("Matrix_SymSparse::Val(int, int)",
966  "No reference to element (" + to_str(i) + ", "
967  + to_str(j)
968  + ") can be returned: it is a zero entry.");
969 
970  l = Storage::GetSecond(i, j);
971 
972  for (k = a; (k<b-1) && (ind_[k]<l); k++);
973 
974  if (ind_[k] == l)
975  return this->data_[k];
976  else
977  throw WrongArgument("Matrix_SymSparse::Val(int, int)",
978  "No reference to element (" + to_str(i) + ", "
979  + to_str(j)
980  + ") can be returned: it is a zero entry.");
981  }
982 
983 
985 
993  template <class T, class Prop, class Storage, class Allocator>
994  const typename Matrix_SymSparse<T, Prop, Storage, Allocator>::value_type&
996  {
997 
998 #ifdef SELDON_CHECK_BOUNDS
999  if (i < 0 || i >= this->m_)
1000  throw WrongRow("Matrix_SymSparse::Val(int, int)",
1001  string("Index should be in [0, ") + to_str(this->m_-1)
1002  + "], but is equal to " + to_str(i) + ".");
1003  if (j < 0 || j >= this->n_)
1004  throw WrongCol("Matrix_SymSparse::Val(int, int)",
1005  string("Index should be in [0, ") + to_str(this->n_-1)
1006  + "], but is equal to " + to_str(j) + ".");
1007 #endif
1008 
1009  long k, l;
1010  long a, b;
1011 
1012  // Only the upper part is stored.
1013  if (i > j)
1014  {
1015  l = i;
1016  i = j;
1017  j = l;
1018  }
1019 
1020  a = ptr_[Storage::GetFirst(i, j)];
1021  b = ptr_[Storage::GetFirst(i, j) + 1];
1022 
1023  if (a == b)
1024  throw WrongArgument("Matrix_SymSparse::Val(int, int)",
1025  "No reference to element (" + to_str(i) + ", "
1026  + to_str(j)
1027  + ") can be returned: it is a zero entry.");
1028 
1029  l = Storage::GetSecond(i, j);
1030 
1031  for (k = a; (k<b-1) && (ind_[k]<l); k++);
1032 
1033  if (ind_[k] == l)
1034  return this->data_[k];
1035  else
1036  throw WrongArgument("Matrix_SymSparse::Val(int, int)",
1037  "No reference to element (" + to_str(i) + ", "
1038  + to_str(j)
1039  + ") can be returned: it is a zero entry.");
1040  }
1041 
1042 
1044 
1051  template <class T, class Prop, class Storage, class Allocator>
1052  typename Matrix_SymSparse<T, Prop, Storage, Allocator>::value_type&
1054  {
1055 
1056 #ifdef SELDON_CHECK_BOUNDS
1057  if (i < 0 || i >= this->m_)
1058  throw WrongRow("Matrix_SymSparse::Get(int, int)",
1059  string("Index should be in [0, ") + to_str(this->m_-1)
1060  + "], but is equal to " + to_str(i) + ".");
1061  if (j < 0 || j >= this->n_)
1062  throw WrongCol("Matrix_SymSparse::Get(int, int)",
1063  string("Index should be in [0, ") + to_str(this->n_-1)
1064  + "], but is equal to " + to_str(j) + ".");
1065 #endif
1066 
1067  long k, l;
1068  long a, b;
1069  // Only the upper part is stored.
1070  if (i > j)
1071  {
1072  l = i;
1073  i = j;
1074  j = l;
1075  }
1076 
1077  a = ptr_[Storage::GetFirst(i, j)];
1078  b = ptr_[Storage::GetFirst(i, j) + 1];
1079 
1080  if (a < b)
1081  {
1082  l = Storage::GetSecond(i, j);
1083 
1084  for (k = a; (k < b) && (ind_[k] < l); k++);
1085 
1086  if ( (k < b) && (ind_[k] == l))
1087  return this->data_[k];
1088  }
1089  else
1090  k = a;
1091 
1092  // adding a non-zero entry
1093  Resize(this->m_, this->n_, nz_+1);
1094 
1095  for (int m = Storage::GetFirst(i, j)+1; m <= this->m_; m++)
1096  ptr_[m]++;
1097 
1098  for (long m = nz_-1; m >= k+1; m--)
1099  {
1100  ind_[m] = ind_[m-1];
1101  this->data_[m] = this->data_[m-1];
1102  }
1103 
1104  ind_[k] = Storage::GetSecond(i, j);
1105 
1106  // value of new non-zero entry is set to 0
1107  SetComplexZero(this->data_[k]);
1108 
1109  return this->data_[k];
1110  }
1111 
1112 
1113  /************************
1114  * CONVENIENT FUNCTIONS *
1115  ************************/
1116 
1117 
1119 
1120  template <class T, class Prop, class Storage, class Allocator>
1122  {
1123  Allocator::memoryset(this->data_, char(0),
1124  this->nz_ * sizeof(value_type));
1125  }
1126 
1127 
1129 
1131  template <class T, class Prop, class Storage, class Allocator>
1133  {
1134  int m = this->m_;
1135  int nz = this->m_;
1136  T one;
1137  SetComplexOne(one);
1138 
1139  if (nz == 0)
1140  return;
1141 
1142  Clear();
1143 
1144  Vector<T, VectFull, Allocator> values(nz);
1145  Vector<long> ptr(m + 1);
1146  Vector<int> ind(nz);
1147 
1148  values.Fill(one);
1149  ind.Fill();
1150  ptr.Fill();
1151 
1152  SetData(m, m, values, ptr, ind);
1153  }
1154 
1155 
1157 
1160  template <class T, class Prop, class Storage, class Allocator>
1162  {
1163  for (long i = 0; i < this->GetDataSize(); i++)
1164  SetComplexReal(i, this->data_[i]);
1165  }
1166 
1167 
1169 
1172  template <class T, class Prop, class Storage, class Allocator>
1173  template <class T0>
1175  {
1176  T x_;
1177  SetComplexReal(x, x_);
1178  for (long i = 0; i < this->GetDataSize(); i++)
1179  this->data_[i] = x_;
1180  }
1181 
1182 
1184 
1187  template <class T, class Prop, class Storage, class Allocator>
1189  {
1190 #ifndef SELDON_WITHOUT_REINIT_RANDOM
1191  srand(time(NULL));
1192 #endif
1193  for (long i = 0; i < this->GetDataSize(); i++)
1194  SetComplexReal(rand(), this->data_[i]);
1195  }
1196 
1197 
1199 
1204  template <class T, class Prop, class Storage, class Allocator>
1206  {
1207  for (int i = 0; i < this->m_; i++)
1208  {
1209  for (int j = 0; j < this->n_; j++)
1210  cout << (*this)(i, j) << "\t";
1211  cout << endl;
1212  }
1213  }
1214 
1215 
1217 
1221  template <class T, class Prop, class Storage, class Allocator>
1223  ::Write(string FileName) const
1224  {
1225  ofstream FileStream;
1226  FileStream.open(FileName.c_str(), ofstream::binary);
1227 
1228 #ifdef SELDON_CHECK_IO
1229  // Checks if the file was opened.
1230  if (!FileStream.is_open())
1231  throw IOError("Matrix_SymSparse::Write(string FileName)",
1232  string("Unable to open file \"") + FileName + "\".");
1233 #endif
1234 
1235  this->Write(FileStream);
1236 
1237  FileStream.close();
1238  }
1239 
1240 
1242 
1246  template <class T, class Prop, class Storage, class Allocator>
1248  ::Write(ostream& FileStream) const
1249  {
1250 #ifdef SELDON_CHECK_IO
1251  // Checks if the stream is ready.
1252  if (!FileStream.good())
1253  throw IOError("Matrix_SymSparse::Write(ofstream& FileStream)",
1254  "Stream is not ready.");
1255 #endif
1256 
1257  FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
1258  sizeof(int));
1259  FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
1260  sizeof(int));
1261  FileStream.write(reinterpret_cast<char*>(const_cast<long*>(&this->nz_)),
1262  sizeof(long));
1263 
1264  FileStream.write(reinterpret_cast<char*>(this->ptr_),
1265  sizeof(long)*(this->m_+1));
1266  FileStream.write(reinterpret_cast<char*>(this->ind_),
1267  sizeof(int)*this->nz_);
1268  FileStream.write(reinterpret_cast<char*>(this->data_),
1269  sizeof(T)*this->nz_);
1270  }
1271 
1272 
1274 
1282  template <class T, class Prop, class Storage, class Allocator>
1284  ::WriteText(string FileName, bool cplx) const
1285  {
1286  ofstream FileStream; FileStream.precision(14);
1287  FileStream.open(FileName.c_str());
1288 
1289  // changing precision
1290  FileStream.precision(cout.precision());
1291 
1292 #ifdef SELDON_CHECK_IO
1293  // Checks if the file was opened.
1294  if (!FileStream.is_open())
1295  throw IOError("Matrix_SymSparse::WriteText(string FileName)",
1296  string("Unable to open file \"") + FileName + "\".");
1297 #endif
1298 
1299  this->WriteText(FileStream, cplx);
1300 
1301  FileStream.close();
1302  }
1303 
1304 
1306 
1314  template <class T, class Prop, class Storage, class Allocator>
1316  ::WriteText(ostream& FileStream, bool cplx) const
1317  {
1318 
1319 #ifdef SELDON_CHECK_IO
1320  // Checks if the stream is ready.
1321  if (!FileStream.good())
1322  throw IOError("Matrix_SymSparse::WriteText(ofstream& FileStream)",
1323  "Stream is not ready.");
1324 #endif
1325 
1326  // Conversion to coordinate format (1-index convention).
1327  const Matrix<T, Prop, Storage, Allocator>& leaf_class =
1328  static_cast<const Matrix<T, Prop, Storage, Allocator>& >(*this);
1329 
1330  T zero; int index = 1;
1331  WriteCoordinateMatrix(leaf_class, FileStream, zero, index, cplx);
1332  }
1333 
1334 
1336 
1340  template <class T, class Prop, class Storage, class Allocator>
1342  ::Read(string FileName)
1343  {
1344  ifstream FileStream;
1345  FileStream.open(FileName.c_str(), ifstream::binary);
1346 
1347 #ifdef SELDON_CHECK_IO
1348  // Checks if the file was opened.
1349  if (!FileStream.is_open())
1350  throw IOError("Matrix_SymSparse::Read(string FileName)",
1351  string("Unable to open file \"") + FileName + "\".");
1352 #endif
1353 
1354  this->Read(FileStream);
1355 
1356  FileStream.close();
1357  }
1358 
1359 
1361 
1365  template <class T, class Prop, class Storage, class Allocator>
1367  Read(istream& FileStream)
1368  {
1369 
1370 #ifdef SELDON_CHECK_IO
1371  // Checks if the stream is ready.
1372  if (!FileStream.good())
1373  throw IOError("Matrix_SymSparse::Read(ofstream& FileStream)",
1374  "Stream is not ready.");
1375 #endif
1376 
1377  int m, n; long nz;
1378  FileStream.read(reinterpret_cast<char*>(&m), sizeof(int));
1379  FileStream.read(reinterpret_cast<char*>(&n), sizeof(int));
1380  FileStream.read(reinterpret_cast<char*>(&nz), sizeof(long));
1381 
1382  Reallocate(m, m, nz);
1383 
1384  FileStream.read(reinterpret_cast<char*>(ptr_),
1385  sizeof(long)*(m+1));
1386  FileStream.read(reinterpret_cast<char*>(ind_), sizeof(int)*nz);
1387  FileStream.read(reinterpret_cast<char*>(this->data_), sizeof(T)*nz);
1388 
1389 #ifdef SELDON_CHECK_IO
1390  // Checks if data was read.
1391  if (!FileStream.good())
1392  throw IOError("Matrix_SymSparse::Read(istream& FileStream)",
1393  string("Input operation failed.")
1394  + string(" The input file may have been removed")
1395  + " or may not contain enough data.");
1396 #endif
1397 
1398  }
1399 
1400 
1402 
1409  template <class T, class Prop, class Storage, class Allocator>
1411  ::ReadText(string FileName, bool cplx)
1412  {
1413  ifstream FileStream;
1414  FileStream.open(FileName.c_str());
1415 
1416 #ifdef SELDON_CHECK_IO
1417  // Checks if the file was opened.
1418  if (!FileStream.is_open())
1419  throw IOError("Matrix_SymSparse::ReadText(string FileName)",
1420  string("Unable to open file \"") + FileName + "\".");
1421 #endif
1422 
1423  this->ReadText(FileStream, cplx);
1424 
1425  FileStream.close();
1426  }
1427 
1428 
1430 
1437  template <class T, class Prop, class Storage, class Allocator>
1439  ReadText(istream& FileStream, bool cplx)
1440  {
1442  static_cast<Matrix<T, Prop, Storage, Allocator>& >(*this);
1443 
1444  T zero; int index = 1;
1445  ReadCoordinateMatrix(leaf_class, FileStream, zero, index, -1, cplx);
1446  }
1447 
1448 
1449 } // namespace Seldon.
1450 
1451 #define SELDON_FILE_MATRIX_SYMSPARSE_CXX
1452 #endif
Seldon::Matrix_Base
Base class for all matrices.
Definition: Matrix_Base.hxx:143
Seldon::to_str
std::string to_str(const T &input)
Converts most types to string.
Definition: CommonInline.cxx:137
Seldon::WrongCol
Definition: Errors.hxx:138
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::Matrix
Definition: SeldonHeader.hxx:226
Seldon::Matrix_SymSparse
Symmetric sparse-matrix class.
Definition: Matrix_SymSparse.hxx:46
Seldon::WrongRow
Definition: Errors.hxx:126
Seldon::VirtualMatrix::GetN
int GetN() const
Returns the number of columns.
Definition: Matrix_BaseInline.cxx:80
Seldon::VirtualMatrix::GetM
int GetM() const
Returns the number of rows.
Definition: Matrix_BaseInline.cxx:69
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::WrongArgument
Definition: Errors.hxx:76
Seldon::Matrix_SymSparse::GetNonZeros
long GetNonZeros() const
Returns the number of elements stored in memory.
Definition: Matrix_SymSparseInline.cxx:114
Seldon::Matrix_SymSparse::Matrix_SymSparse
Matrix_SymSparse()
Default constructor.
Definition: Matrix_SymSparseInline.cxx:39
Seldon::WrongDim
Definition: Errors.hxx:102
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::IOError
Definition: Errors.hxx:150
Seldon::NoMemory
Definition: Errors.hxx:90
Seldon::Vector< T, VectFull, Allocator >::Fill
void Fill()
Fills the vector with 0, 1, 2, ...
Definition: VectorInline.cxx:736
Seldon::SetComplexReal
void SetComplexReal(int n, std::complex< T > &number)
Sets a complex number to (n, 0).
Definition: CommonInline.cxx:234
Seldon::Vector_Base::GetData
pointer GetData() const
Returns a pointer to data_ (stored data).
Definition: VectorInline.cxx:177