00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef SELDON_FILE_MATRIX_SPARSE_CXX
00022
00023 #include "Matrix_Sparse.hxx"
00024
00025 #include "../vector/Functions_Arrays.cxx"
00026
00027 #include <set>
00028
00029
00030 namespace Seldon
00031 {
00032
00033
00034
00035
00036
00037
00038
00040
00043 template <class T, class Prop, class Storage, class Allocator>
00044 inline Matrix_Sparse<T, Prop, Storage, Allocator>::Matrix_Sparse():
00045 Matrix_Base<T, Allocator>()
00046 {
00047 nz_ = 0;
00048 ptr_ = NULL;
00049 ind_ = NULL;
00050 }
00051
00052
00054
00059 template <class T, class Prop, class Storage, class Allocator>
00060 inline Matrix_Sparse<T, Prop, Storage, Allocator>::Matrix_Sparse(int i,
00061 int j):
00062 Matrix_Base<T, Allocator>(i, j)
00063 {
00064 nz_ = 0;
00065 ptr_ = NULL;
00066 ind_ = NULL;
00067 }
00068
00069
00071
00078 template <class T, class Prop, class Storage, class Allocator>
00079 inline Matrix_Sparse<T, Prop, Storage, Allocator>::
00080 Matrix_Sparse(int i, int j, int nz):
00081 Matrix_Base<T, Allocator>(i, j)
00082 {
00083
00084 this->nz_ = nz;
00085
00086 #ifdef SELDON_CHECK_DIMENSIONS
00087 if (nz_ < 0)
00088 {
00089 this->m_ = 0;
00090 this->n_ = 0;
00091 nz_ = 0;
00092 ptr_ = NULL;
00093 ind_ = NULL;
00094 this->data_ = NULL;
00095 throw WrongDim("Matrix_Sparse::Matrix_Sparse(int, int, int)",
00096 "Invalid number of non-zero elements: " + to_str(nz)
00097 + ".");
00098 }
00099 if (nz_ > 0
00100 && (j == 0
00101 || static_cast<long int>(nz_-1) / static_cast<long int>(j)
00102 >= static_cast<long int>(i)))
00103 {
00104 this->m_ = 0;
00105 this->n_ = 0;
00106 nz_ = 0;
00107 ptr_ = NULL;
00108 ind_ = NULL;
00109 this->data_ = NULL;
00110 throw WrongDim("Matrix_Sparse::Matrix_Sparse(int, int, int)",
00111 string("There are more values (") + to_str(nz)
00112 + " values) than elements in the matrix ("
00113 + to_str(i) + " by " + to_str(j) + ").");
00114 }
00115 #endif
00116
00117 #ifdef SELDON_CHECK_MEMORY
00118 try
00119 {
00120 #endif
00121
00122 ptr_ = reinterpret_cast<int*>( calloc(Storage::GetFirst(i, j)+1,
00123 sizeof(int)) );
00124
00125 #ifdef SELDON_CHECK_MEMORY
00126 }
00127 catch (...)
00128 {
00129 this->m_ = 0;
00130 this->n_ = 0;
00131 nz_ = 0;
00132 ptr_ = NULL;
00133 ind_ = NULL;
00134 this->data_ = NULL;
00135 }
00136 if (ptr_ == NULL)
00137 {
00138 this->m_ = 0;
00139 this->n_ = 0;
00140 nz_ = 0;
00141 ind_ = NULL;
00142 this->data_ = NULL;
00143 }
00144 if (ptr_ == NULL && i != 0 && j != 0)
00145 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)",
00146 string("Unable to allocate ")
00147 + to_str(sizeof(int) * (Storage::GetFirst(i, j)+1) )
00148 + " bytes to store " + to_str(Storage::GetFirst(i, j)+1)
00149 + " row or column start indices, for a "
00150 + to_str(i) + " by " + to_str(j) + " matrix.");
00151 #endif
00152
00153 #ifdef SELDON_CHECK_MEMORY
00154 try
00155 {
00156 #endif
00157
00158 ind_ = reinterpret_cast<int*>( calloc(nz_, sizeof(int)) );
00159
00160 #ifdef SELDON_CHECK_MEMORY
00161 }
00162 catch (...)
00163 {
00164 this->m_ = 0;
00165 this->n_ = 0;
00166 nz_ = 0;
00167 free(ptr_);
00168 ptr_ = NULL;
00169 ind_ = NULL;
00170 this->data_ = NULL;
00171 }
00172 if (ind_ == NULL)
00173 {
00174 this->m_ = 0;
00175 this->n_ = 0;
00176 nz_ = 0;
00177 free(ptr_);
00178 ptr_ = NULL;
00179 this->data_ = NULL;
00180 }
00181 if (ind_ == NULL && i != 0 && j != 0)
00182 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)",
00183 string("Unable to allocate ") + to_str(sizeof(int) * nz)
00184 + " bytes to store " + to_str(nz)
00185 + " row or column indices, for a "
00186 + to_str(i) + " by " + to_str(j) + " matrix.");
00187 #endif
00188
00189 #ifdef SELDON_CHECK_MEMORY
00190 try
00191 {
00192 #endif
00193
00194 this->data_ = this->allocator_.allocate(nz_, this);
00195
00196 #ifdef SELDON_CHECK_MEMORY
00197 }
00198 catch (...)
00199 {
00200 this->m_ = 0;
00201 this->n_ = 0;
00202 free(ptr_);
00203 ptr_ = NULL;
00204 free(ind_);
00205 ind_ = NULL;
00206 this->data_ = NULL;
00207 }
00208 if (this->data_ == NULL)
00209 {
00210 this->m_ = 0;
00211 this->n_ = 0;
00212 free(ptr_);
00213 ptr_ = NULL;
00214 free(ind_);
00215 ind_ = NULL;
00216 }
00217 if (this->data_ == NULL && i != 0 && j != 0)
00218 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)",
00219 string("Unable to allocate ") + to_str(sizeof(int) * nz)
00220 + " bytes to store " + to_str(nz) + " values, for a "
00221 + to_str(i) + " by " + to_str(j) + " matrix.");
00222 #endif
00223
00224 }
00225
00226
00228
00239 template <class T, class Prop, class Storage, class Allocator>
00240 template <class Storage0, class Allocator0,
00241 class Storage1, class Allocator1,
00242 class Storage2, class Allocator2>
00243 inline Matrix_Sparse<T, Prop, Storage, Allocator>::
00244 Matrix_Sparse(int i, int j,
00245 Vector<T, Storage0, Allocator0>& values,
00246 Vector<int, Storage1, Allocator1>& ptr,
00247 Vector<int, Storage2, Allocator2>& ind):
00248 Matrix_Base<T, Allocator>(i, j)
00249 {
00250 nz_ = values.GetLength();
00251
00252 #ifdef SELDON_CHECK_DIMENSIONS
00253
00254
00255 if (ind.GetLength() != nz_)
00256 {
00257 this->m_ = 0;
00258 this->n_ = 0;
00259 nz_ = 0;
00260 ptr_ = NULL;
00261 ind_ = NULL;
00262 this->data_ = NULL;
00263 throw WrongDim(string("Matrix_Sparse::Matrix_Sparse(int, int, ")
00264 + "const Vector&, const Vector&, const Vector&)",
00265 string("There are ") + to_str(nz_) + " values but "
00266 + to_str(ind.GetLength()) + " row or column indices.");
00267 }
00268
00269 if (ptr.GetLength()-1 != Storage::GetFirst(i, j))
00270 {
00271 this->m_ = 0;
00272 this->n_ = 0;
00273 nz_ = 0;
00274 ptr_ = NULL;
00275 ind_ = NULL;
00276 this->data_ = NULL;
00277 throw WrongDim(string("Matrix_Sparse::Matrix_Sparse(int, int, ")
00278 + "const Vector&, const Vector&, const Vector&)",
00279 string("The vector of start indices contains ")
00280 + to_str(ptr.GetLength()-1) + string(" row or column")
00281 + string(" start indices (plus the number")
00282 + " of non-zero entries) but there are "
00283 + to_str(Storage::GetFirst(i, j))
00284 + " rows or columns (" + to_str(i) + " by "
00285 + to_str(j) + " matrix).");
00286 }
00287
00288 if (nz_ > 0
00289 && (j == 0
00290 || static_cast<long int>(nz_-1) / static_cast<long int>(j)
00291 >= static_cast<long int>(i)))
00292 {
00293 this->m_ = 0;
00294 this->n_ = 0;
00295 nz_ = 0;
00296 ptr_ = NULL;
00297 ind_ = NULL;
00298 this->data_ = NULL;
00299 throw WrongDim(string("Matrix_Sparse::Matrix_Sparse(int, int, ")
00300 + "const Vector&, const Vector&, const Vector&)",
00301 string("There are more values (")
00302 + to_str(values.GetLength())
00303 + " values) than elements in the matrix ("
00304 + to_str(i) + " by " + to_str(j) + ").");
00305 }
00306 #endif
00307
00308 this->ptr_ = ptr.GetData();
00309 this->ind_ = ind.GetData();
00310 this->data_ = values.GetData();
00311
00312 ptr.Nullify();
00313 ind.Nullify();
00314 values.Nullify();
00315 }
00316
00317
00319 template <class T, class Prop, class Storage, class Allocator>
00320 inline Matrix_Sparse<T, Prop, Storage, Allocator>::
00321 Matrix_Sparse(const Matrix_Sparse<T, Prop, Storage, Allocator>& A)
00322 {
00323 this->m_ = 0;
00324 this->n_ = 0;
00325 this->nz_ = 0;
00326 ptr_ = NULL;
00327 ind_ = NULL;
00328 this->Copy(A);
00329 }
00330
00331
00332
00333
00334
00335
00336
00338 template <class T, class Prop, class Storage, class Allocator>
00339 inline Matrix_Sparse<T, Prop, Storage, Allocator>::~Matrix_Sparse()
00340 {
00341 this->m_ = 0;
00342 this->n_ = 0;
00343
00344 #ifdef SELDON_CHECK_MEMORY
00345 try
00346 {
00347 #endif
00348
00349 if (ptr_ != NULL)
00350 {
00351 free(ptr_);
00352 ptr_ = NULL;
00353 }
00354
00355 #ifdef SELDON_CHECK_MEMORY
00356 }
00357 catch (...)
00358 {
00359 ptr_ = NULL;
00360 }
00361 #endif
00362
00363 #ifdef SELDON_CHECK_MEMORY
00364 try
00365 {
00366 #endif
00367
00368 if (ind_ != NULL)
00369 {
00370 free(ind_);
00371 ind_ = NULL;
00372 }
00373
00374 #ifdef SELDON_CHECK_MEMORY
00375 }
00376 catch (...)
00377 {
00378 ind_ = NULL;
00379 }
00380 #endif
00381
00382 #ifdef SELDON_CHECK_MEMORY
00383 try
00384 {
00385 #endif
00386
00387 if (this->data_ != NULL)
00388 {
00389 this->allocator_.deallocate(this->data_, nz_);
00390 this->data_ = NULL;
00391 }
00392
00393 #ifdef SELDON_CHECK_MEMORY
00394 }
00395 catch (...)
00396 {
00397 this->nz_ = 0;
00398 this->data_ = NULL;
00399 }
00400 #endif
00401
00402 this->nz_ = 0;
00403 }
00404
00405
00407
00410 template <class T, class Prop, class Storage, class Allocator>
00411 inline void Matrix_Sparse<T, Prop, Storage, Allocator>::Clear()
00412 {
00413 this->~Matrix_Sparse();
00414 }
00415
00416
00417
00418
00419
00420
00421
00423
00433 template <class T, class Prop, class Storage, class Allocator>
00434 template <class Storage0, class Allocator0,
00435 class Storage1, class Allocator1,
00436 class Storage2, class Allocator2>
00437 void Matrix_Sparse<T, Prop, Storage, Allocator>::
00438 SetData(int i, int j,
00439 Vector<T, Storage0, Allocator0>& values,
00440 Vector<int, Storage1, Allocator1>& ptr,
00441 Vector<int, Storage2, Allocator2>& ind)
00442 {
00443 this->Clear();
00444 this->m_ = i;
00445 this->n_ = j;
00446 this->nz_ = values.GetLength();
00447
00448 #ifdef SELDON_CHECK_DIMENSIONS
00449
00450
00451 if (ind.GetLength() != nz_)
00452 {
00453 this->m_ = 0;
00454 this->n_ = 0;
00455 nz_ = 0;
00456 ptr_ = NULL;
00457 ind_ = NULL;
00458 this->data_ = NULL;
00459 throw WrongDim(string("Matrix_Sparse::SetData(int, int, ")
00460 + "const Vector&, const Vector&, const Vector&)",
00461 string("There are ") + to_str(nz_) + " values but "
00462 + to_str(ind.GetLength()) + " row or column indices.");
00463 }
00464
00465 if (ptr.GetLength()-1 != Storage::GetFirst(i, j))
00466 {
00467 this->m_ = 0;
00468 this->n_ = 0;
00469 nz_ = 0;
00470 ptr_ = NULL;
00471 ind_ = NULL;
00472 this->data_ = NULL;
00473 throw WrongDim(string("Matrix_Sparse::SetData(int, int, ")
00474 + "const Vector&, const Vector&, const Vector&)",
00475 string("The vector of start indices contains ")
00476 + to_str(ptr.GetLength()-1) + string(" row or column")
00477 + string(" start indices (plus the number")
00478 + " of non-zero entries) but there are "
00479 + to_str(Storage::GetFirst(i, j))
00480 + " rows or columns (" + to_str(i) + " by "
00481 + to_str(j) + " matrix).");
00482 }
00483
00484 if (nz_ > 0
00485 && (j == 0
00486 || static_cast<long int>(nz_-1) / static_cast<long int>(j)
00487 >= static_cast<long int>(i)))
00488 {
00489 this->m_ = 0;
00490 this->n_ = 0;
00491 nz_ = 0;
00492 ptr_ = NULL;
00493 ind_ = NULL;
00494 this->data_ = NULL;
00495 throw WrongDim(string("Matrix_Sparse::SetData(int, int, ")
00496 + "const Vector&, const Vector&, const Vector&)",
00497 string("There are more values (")
00498 + to_str(values.GetLength())
00499 + " values) than elements in the matrix ("
00500 + to_str(i) + " by " + to_str(j) + ").");
00501 }
00502 #endif
00503
00504 this->ptr_ = ptr.GetData();
00505 this->ind_ = ind.GetData();
00506 this->data_ = values.GetData();
00507
00508 ptr.Nullify();
00509 ind.Nullify();
00510 values.Nullify();
00511 }
00512
00513
00515
00528 template <class T, class Prop, class Storage, class Allocator>
00529 inline void Matrix_Sparse<T, Prop, Storage, Allocator>
00530 ::SetData(int i, int j, int nz,
00531 typename Matrix_Sparse<T, Prop, Storage, Allocator>
00532 ::pointer values,
00533 int* ptr, int* ind)
00534 {
00535 this->Clear();
00536
00537 this->m_ = i;
00538 this->n_ = j;
00539
00540 this->nz_ = nz;
00541
00542 this->data_ = values;
00543 ind_ = ind;
00544 ptr_ = ptr;
00545 }
00546
00547
00549
00553 template <class T, class Prop, class Storage, class Allocator>
00554 inline void Matrix_Sparse<T, Prop, Storage, Allocator>::Nullify()
00555 {
00556 this->data_ = NULL;
00557 this->m_ = 0;
00558 this->n_ = 0;
00559 nz_ = 0;
00560 ptr_ = NULL;
00561 ind_ = NULL;
00562 }
00563
00564
00566 template <class T, class Prop, class Storage, class Allocator>
00567 inline void Matrix_Sparse<T, Prop, Storage, Allocator>::
00568 Copy(const Matrix_Sparse<T, Prop, Storage, Allocator>& A)
00569 {
00570 this->Clear();
00571 int nz = A.nz_;
00572 int i = A.m_;
00573 int j = A.n_;
00574 this->nz_ = nz;
00575 this->m_ = i;
00576 this->n_ = j;
00577 if ((i == 0)||(j == 0))
00578 {
00579 this->m_ = 0;
00580 this->n_ = 0;
00581 this->nz_ = 0;
00582 return;
00583 }
00584
00585 #ifdef SELDON_CHECK_DIMENSIONS
00586 if (nz_ > 0
00587 && (j == 0
00588 || static_cast<long int>(nz_-1) / static_cast<long int>(j)
00589 >= static_cast<long int>(i)))
00590 {
00591 this->m_ = 0;
00592 this->n_ = 0;
00593 nz_ = 0;
00594 ptr_ = NULL;
00595 ind_ = NULL;
00596 this->data_ = NULL;
00597 throw WrongDim("Matrix_Sparse::Matrix_Sparse(int, int, int)",
00598 string("There are more values (") + to_str(nz)
00599 + " values) than elements in the matrix ("
00600 + to_str(i) + " by " + to_str(j) + ").");
00601 }
00602 #endif
00603
00604 #ifdef SELDON_CHECK_MEMORY
00605 try
00606 {
00607 #endif
00608
00609 ptr_ = reinterpret_cast<int*>( calloc(Storage::GetFirst(i, j)+1,
00610 sizeof(int)) );
00611 memcpy(this->ptr_, A.ptr_,
00612 (Storage::GetFirst(i, j) + 1) * sizeof(int));
00613 #ifdef SELDON_CHECK_MEMORY
00614 }
00615 catch (...)
00616 {
00617 this->m_ = 0;
00618 this->n_ = 0;
00619 nz_ = 0;
00620 ptr_ = NULL;
00621 ind_ = NULL;
00622 this->data_ = NULL;
00623 }
00624 if (ptr_ == NULL)
00625 {
00626 this->m_ = 0;
00627 this->n_ = 0;
00628 nz_ = 0;
00629 ind_ = NULL;
00630 this->data_ = NULL;
00631 }
00632 if (ptr_ == NULL && i != 0 && j != 0)
00633 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)",
00634 string("Unable to allocate ")
00635 + to_str(sizeof(int) * (Storage::GetFirst(i, j)+1) )
00636 + " bytes to store " + to_str(Storage::GetFirst(i, j)+1)
00637 + " row or column start indices, for a "
00638 + to_str(i) + " by " + to_str(j) + " matrix.");
00639 #endif
00640
00641 #ifdef SELDON_CHECK_MEMORY
00642 try
00643 {
00644 #endif
00645
00646 ind_ = reinterpret_cast<int*>( calloc(nz_, sizeof(int)) );
00647 memcpy(this->ind_, A.ind_, nz_ * sizeof(int));
00648
00649 #ifdef SELDON_CHECK_MEMORY
00650 }
00651 catch (...)
00652 {
00653 this->m_ = 0;
00654 this->n_ = 0;
00655 nz_ = 0;
00656 free(ptr_);
00657 ptr_ = NULL;
00658 ind_ = NULL;
00659 this->data_ = NULL;
00660 }
00661 if (ind_ == NULL)
00662 {
00663 this->m_ = 0;
00664 this->n_ = 0;
00665 nz_ = 0;
00666 free(ptr_);
00667 ptr_ = NULL;
00668 this->data_ = NULL;
00669 }
00670 if (ind_ == NULL && i != 0 && j != 0)
00671 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)",
00672 string("Unable to allocate ") + to_str(sizeof(int) * nz)
00673 + " bytes to store " + to_str(nz)
00674 + " row or column indices, for a "
00675 + to_str(i) + " by " + to_str(j) + " matrix.");
00676 #endif
00677
00678 #ifdef SELDON_CHECK_MEMORY
00679 try
00680 {
00681 #endif
00682
00683 this->data_ = this->allocator_.allocate(nz_, this);
00684 this->allocator_.memorycpy(this->data_, A.data_, nz_);
00685
00686 #ifdef SELDON_CHECK_MEMORY
00687 }
00688 catch (...)
00689 {
00690 this->m_ = 0;
00691 this->n_ = 0;
00692 free(ptr_);
00693 ptr_ = NULL;
00694 free(ind_);
00695 ind_ = NULL;
00696 this->data_ = NULL;
00697 }
00698 if (this->data_ == NULL)
00699 {
00700 this->m_ = 0;
00701 this->n_ = 0;
00702 free(ptr_);
00703 ptr_ = NULL;
00704 free(ind_);
00705 ind_ = NULL;
00706 }
00707 if (this->data_ == NULL && i != 0 && j != 0)
00708 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)",
00709 string("Unable to allocate ") + to_str(sizeof(int) * nz)
00710 + " bytes to store " + to_str(nz) + " values, for a "
00711 + to_str(i) + " by " + to_str(j) + " matrix.");
00712 #endif
00713
00714 }
00715
00716
00717
00718
00719
00720
00721
00723
00726 template <class T, class Prop, class Storage, class Allocator>
00727 int Matrix_Sparse<T, Prop, Storage, Allocator>::GetNonZeros() const
00728 {
00729 return nz_;
00730 }
00731
00732
00734
00739 template <class T, class Prop, class Storage, class Allocator>
00740 int Matrix_Sparse<T, Prop, Storage, Allocator>::GetDataSize() const
00741 {
00742 return nz_;
00743 }
00744
00745
00747
00751 template <class T, class Prop, class Storage, class Allocator>
00752 int* Matrix_Sparse<T, Prop, Storage, Allocator>::GetPtr() const
00753 {
00754 return ptr_;
00755 }
00756
00757
00759
00766 template <class T, class Prop, class Storage, class Allocator>
00767 int* Matrix_Sparse<T, Prop, Storage, Allocator>::GetInd() const
00768 {
00769 return ind_;
00770 }
00771
00772
00774
00777 template <class T, class Prop, class Storage, class Allocator>
00778 int Matrix_Sparse<T, Prop, Storage, Allocator>::GetPtrSize() const
00779 {
00780 return (Storage::GetFirst(this->m_, this->n_) + 1);
00781 }
00782
00783
00785
00793 template <class T, class Prop, class Storage, class Allocator>
00794 int Matrix_Sparse<T, Prop, Storage, Allocator>::GetIndSize() const
00795 {
00796 return nz_;
00797 }
00798
00799
00800
00801
00802
00803
00804
00806
00812 template <class T, class Prop, class Storage, class Allocator>
00813 inline typename Matrix_Sparse<T, Prop, Storage, Allocator>::value_type
00814 Matrix_Sparse<T, Prop, Storage, Allocator>::operator() (int i, int j) const
00815 {
00816
00817 #ifdef SELDON_CHECK_BOUNDS
00818 if (i < 0 || i >= this->m_)
00819 throw WrongRow("Matrix_Sparse::operator()",
00820 string("Index should be in [0, ") + to_str(this->m_-1)
00821 + "], but is equal to " + to_str(i) + ".");
00822 if (j < 0 || j >= this->n_)
00823 throw WrongCol("Matrix_Sparse::operator()",
00824 string("Index should be in [0, ") + to_str(this->n_-1)
00825 + "], but is equal to " + to_str(j) + ".");
00826 #endif
00827
00828 int k,l;
00829 int a,b;
00830
00831 a = ptr_[Storage::GetFirst(i, j)];
00832 b = ptr_[Storage::GetFirst(i, j) + 1];
00833
00834 if (a == b)
00835 return T(0);
00836
00837 l = Storage::GetSecond(i, j);
00838
00839 for (k = a; (k < b-1) && (ind_[k] < l); k++);
00840
00841 if (ind_[k] == l)
00842 return this->data_[k];
00843 else
00844 return T(0);
00845 }
00846
00847
00849
00857 template <class T, class Prop, class Storage, class Allocator>
00858 inline typename Matrix_Sparse<T, Prop, Storage, Allocator>::value_type&
00859 Matrix_Sparse<T, Prop, Storage, Allocator>::Val(int i, int j)
00860 {
00861
00862 #ifdef SELDON_CHECK_BOUNDS
00863 if (i < 0 || i >= this->m_)
00864 throw WrongRow("Matrix_Sparse::Val(int, int)",
00865 string("Index should be in [0, ") + to_str(this->m_-1)
00866 + "], but is equal to " + to_str(i) + ".");
00867 if (j < 0 || j >= this->n_)
00868 throw WrongCol("Matrix_Sparse::Val(int, int)",
00869 string("Index should be in [0, ") + to_str(this->n_-1)
00870 + "], but is equal to " + to_str(j) + ".");
00871 #endif
00872
00873 int k, l;
00874 int a, b;
00875
00876 a = ptr_[Storage::GetFirst(i, j)];
00877 b = ptr_[Storage::GetFirst(i, j) + 1];
00878
00879 if (a == b)
00880 throw WrongArgument("Matrix_Sparse::Val(int, int)",
00881 "No reference to element (" + to_str(i) + ", "
00882 + to_str(j)
00883 + ") can be returned: it is a zero entry.");
00884
00885 l = Storage::GetSecond(i, j);
00886
00887 for (k = a; (k < b-1) && (ind_[k] < l); k++);
00888
00889 if (ind_[k] == l)
00890 return this->data_[k];
00891 else
00892 throw WrongArgument("Matrix_Sparse::Val(int, int)",
00893 "No reference to element (" + to_str(i) + ", "
00894 + to_str(j)
00895 + ") can be returned: it is a zero entry.");
00896 }
00897
00898
00900
00908 template <class T, class Prop, class Storage, class Allocator>
00909 inline
00910 const typename Matrix_Sparse<T, Prop, Storage, Allocator>::value_type&
00911 Matrix_Sparse<T, Prop, Storage, Allocator>::Val(int i, int j) const
00912 {
00913
00914 #ifdef SELDON_CHECK_BOUNDS
00915 if (i < 0 || i >= this->m_)
00916 throw WrongRow("Matrix_Sparse::Val(int, int)",
00917 string("Index should be in [0, ") + to_str(this->m_-1)
00918 + "], but is equal to " + to_str(i) + ".");
00919 if (j < 0 || j >= this->n_)
00920 throw WrongCol("Matrix_Sparse::Val(int, int)",
00921 string("Index should be in [0, ") + to_str(this->n_-1)
00922 + "], but is equal to " + to_str(j) + ".");
00923 #endif
00924
00925 int k, l;
00926 int a, b;
00927
00928 a = ptr_[Storage::GetFirst(i, j)];
00929 b = ptr_[Storage::GetFirst(i, j) + 1];
00930
00931 if (a == b)
00932 throw WrongArgument("Matrix_Sparse::Val(int, int)",
00933 "No reference to element (" + to_str(i) + ", "
00934 + to_str(j)
00935 + ") can be returned: it is a zero entry.");
00936
00937 l = Storage::GetSecond(i, j);
00938
00939 for (k = a; (k < b-1) && (ind_[k] < l); k++);
00940
00941 if (ind_[k] == l)
00942 return this->data_[k];
00943 else
00944 throw WrongArgument("Matrix_Sparse::Val(int, int)",
00945 "No reference to element (" + to_str(i) + ", "
00946 + to_str(j)
00947 + ") can be returned: it is a zero entry.");
00948 }
00949
00950
00952
00958 template <class T, class Prop, class Storage, class Allocator>
00959 inline void Matrix_Sparse<T, Prop, Storage, Allocator>
00960 ::AddInteraction(int i, int j, const T& val)
00961 {
00962 Val(i, j) += val;
00963 }
00964
00965
00967
00972 template <class T, class Prop, class Storage, class Allocator>
00973 inline Matrix_Sparse<T, Prop, Storage, Allocator>&
00974 Matrix_Sparse<T, Prop, Storage, Allocator>
00975 ::operator= (const Matrix_Sparse<T, Prop, Storage, Allocator>& A)
00976 {
00977 this->Copy(A);
00978
00979 return *this;
00980 }
00981
00982
00983
00984
00985
00986
00987
00989
00990 template <class T, class Prop, class Storage, class Allocator>
00991 void Matrix_Sparse<T, Prop, Storage, Allocator>::Zero()
00992 {
00993 this->allocator_.memoryset(this->data_, char(0),
00994 this->nz_ * sizeof(value_type));
00995 }
00996
00997
00999
01002 template <class T, class Prop, class Storage, class Allocator>
01003 void Matrix_Sparse<T, Prop, Storage, Allocator>::SetIdentity()
01004 {
01005 int m = this->m_;
01006 int n = this->n_;
01007 int nz = min(m, n);
01008
01009 if (nz == 0)
01010 return;
01011
01012 Clear();
01013
01014 Vector<T, VectFull, Allocator> values(nz);
01015 Vector<int, VectFull, CallocAlloc<int> > ptr(Storage::GetFirst(m, n) + 1);
01016 Vector<int, VectFull, CallocAlloc<int> > ind(nz);
01017
01018 values.Fill(T(1));
01019 ind.Fill();
01020 int i;
01021 for (i = 0; i < nz + 1; i++)
01022 ptr(i) = i;
01023 for (i = nz + 1; i < ptr.GetLength(); i++)
01024 ptr(i) = nz;
01025
01026 SetData(m, n, values, ptr, ind);
01027 }
01028
01029
01031
01034 template <class T, class Prop, class Storage, class Allocator>
01035 void Matrix_Sparse<T, Prop, Storage, Allocator>::Fill()
01036 {
01037 for (int i = 0; i < this->GetDataSize(); i++)
01038 this->data_[i] = i;
01039 }
01040
01041
01043
01046 template <class T, class Prop, class Storage, class Allocator>
01047 template <class T0>
01048 void Matrix_Sparse<T, Prop, Storage, Allocator>::Fill(const T0& x)
01049 {
01050 for (int i = 0; i < this->GetDataSize(); i++)
01051 this->data_[i] = x;
01052 }
01053
01054
01056
01059 template <class T, class Prop, class Storage, class Allocator>
01060 void Matrix_Sparse<T, Prop, Storage, Allocator>::FillRand()
01061 {
01062 srand(time(NULL));
01063 for (int i = 0; i < this->GetDataSize(); i++)
01064 this->data_[i] = rand();
01065 }
01066
01067
01069
01074 template <class T, class Prop, class Storage, class Allocator>
01075 void Matrix_Sparse<T, Prop, Storage, Allocator>::Print() const
01076 {
01077 for (int i = 0; i < this->m_; i++)
01078 {
01079 for (int j = 0; j < this->n_; j++)
01080 cout << (*this)(i, j) << "\t";
01081 cout << endl;
01082 }
01083 }
01084
01085
01087
01093 template <class T, class Prop, class Storage, class Allocator>
01094 void Matrix_Sparse<T, Prop, Storage, Allocator>::
01095 WriteText(string FileName) const
01096 {
01097 ofstream FileStream; FileStream.precision(14);
01098 FileStream.open(FileName.c_str());
01099
01100 #ifdef SELDON_CHECK_IO
01101
01102 if (!FileStream.is_open())
01103 throw IOError("Matrix_ArraySparse::Write(string FileName)",
01104 string("Unable to open file \"") + FileName + "\".");
01105 #endif
01106
01107 this->WriteText(FileStream);
01108
01109 FileStream.close();
01110 }
01111
01112
01114
01120 template <class T, class Prop, class Storage, class Allocator>
01121 void Matrix_Sparse<T, Prop, Storage, Allocator>::
01122 WriteText(ostream& FileStream) const
01123 {
01124
01125 #ifdef SELDON_CHECK_IO
01126
01127 if (!FileStream.good())
01128 throw IOError("Matrix_ArraySparse::Write(ofstream& FileStream)",
01129 "Stream is not ready.");
01130 #endif
01131
01132
01133 IVect IndRow, IndCol; Vector<T> Value;
01134 const Matrix<T, Prop, Storage, Allocator>& leaf_class =
01135 static_cast<const Matrix<T, Prop, Storage, Allocator>& >(*this);
01136
01137 ConvertMatrix_to_Coordinates(leaf_class, IndRow, IndCol,
01138 Value, 1, true);
01139
01140 for (int i = 0; i < IndRow.GetM(); i++)
01141 FileStream << IndRow(i) << " " << IndCol(i) << " " << Value(i) << '\n';
01142
01143 }
01144
01145
01147
01149
01150
01151
01152
01153
01154
01156
01159 template <class T, class Prop, class Allocator>
01160 Matrix<T, Prop, ColSparse, Allocator>::Matrix() throw():
01161 Matrix_Sparse<T, Prop, ColSparse, Allocator>()
01162 {
01163 }
01164
01165
01167
01171 template <class T, class Prop, class Allocator>
01172 Matrix<T, Prop, ColSparse, Allocator>::Matrix(int i, int j):
01173 Matrix_Sparse<T, Prop, ColSparse, Allocator>(i, j, 0)
01174 {
01175 }
01176
01177
01179
01185 template <class T, class Prop, class Allocator>
01186 Matrix<T, Prop, ColSparse, Allocator>::Matrix(int i, int j, int nz):
01187 Matrix_Sparse<T, Prop, ColSparse, Allocator>(i, j, nz)
01188 {
01189 }
01190
01191
01193
01204 template <class T, class Prop, class Allocator>
01205 template <class Storage0, class Allocator0,
01206 class Storage1, class Allocator1,
01207 class Storage2, class Allocator2>
01208 Matrix<T, Prop, ColSparse, Allocator>::
01209 Matrix(int i, int j,
01210 Vector<T, Storage0, Allocator0>& values,
01211 Vector<int, Storage1, Allocator1>& ptr,
01212 Vector<int, Storage2, Allocator2>& ind):
01213 Matrix_Sparse<T, Prop, ColSparse, Allocator>(i, j, values, ptr, ind)
01214 {
01215 }
01216
01217
01218
01220
01222
01223
01224
01225
01226
01227
01229
01232 template <class T, class Prop, class Allocator>
01233 Matrix<T, Prop, RowSparse, Allocator>::Matrix() throw():
01234 Matrix_Sparse<T, Prop, RowSparse, Allocator>()
01235 {
01236 }
01237
01238
01240
01244 template <class T, class Prop, class Allocator>
01245 Matrix<T, Prop, RowSparse, Allocator>::Matrix(int i, int j):
01246 Matrix_Sparse<T, Prop, RowSparse, Allocator>(i, j, 0)
01247 {
01248 }
01249
01250
01252
01258 template <class T, class Prop, class Allocator>
01259 Matrix<T, Prop, RowSparse, Allocator>::Matrix(int i, int j, int nz):
01260 Matrix_Sparse<T, Prop, RowSparse, Allocator>(i, j, nz)
01261 {
01262 }
01263
01264
01266
01277 template <class T, class Prop, class Allocator>
01278 template <class Storage0, class Allocator0,
01279 class Storage1, class Allocator1,
01280 class Storage2, class Allocator2>
01281 Matrix<T, Prop, RowSparse, Allocator>::
01282 Matrix(int i, int j,
01283 Vector<T, Storage0, Allocator0>& values,
01284 Vector<int, Storage1, Allocator1>& ptr,
01285 Vector<int, Storage2, Allocator2>& ind):
01286 Matrix_Sparse<T, Prop, RowSparse, Allocator>(i, j, values, ptr, ind)
01287 {
01288 }
01289
01290
01292
01300 template <class T, class Prop, class Allocator>
01301 void Matrix<T, Prop, RowSparse, Allocator>::FillRand(int Nelement)
01302 {
01303 if (this->m_ == 0 || this->n_ == 0)
01304 return;
01305
01306 Vector<int> i(Nelement), j(Nelement);
01307 Vector<T> value(Nelement);
01308
01309 set<pair<int, int> > skeleton;
01310 set<pair<int, int> >::iterator it;
01311
01312 srand(time(NULL));
01313
01314 while (static_cast<int>(skeleton.size()) != Nelement)
01315 skeleton.insert(make_pair(rand() % this->m_, rand() % this->n_));
01316
01317 int l = 0;
01318 for (it = skeleton.begin(); it != skeleton.end(); it++)
01319 {
01320 i(l) = it->first;
01321 j(l) = it->second;
01322 value(l) = double(rand());
01323 l++;
01324 }
01325
01326 ConvertMatrix_from_Coordinates(i, j, value, *this);
01327 }
01328
01329
01331
01341 template <class T, class Prop, class Allocator>
01342 void Matrix<T, Prop, RowSparse, Allocator>
01343 ::FillRand(int Nelement, const T& x)
01344 {
01345 if (this->m_ == 0 || this->n_ == 0)
01346 return;
01347
01348 Vector<int> i(Nelement), j(Nelement);
01349 Vector<T> value(Nelement);
01350 value.Fill(x);
01351
01352 srand(time(NULL));
01353 for (int l = 0; l < Nelement; l++)
01354 {
01355 i(l) = rand() % this->m_;
01356 j(l) = rand() % this->n_;
01357 }
01358
01359 ConvertMatrix_from_Coordinates(i, j, value, *this);
01360 }
01361
01362
01363 }
01364
01365 #define SELDON_FILE_MATRIX_SPARSE_CXX
01366 #endif