Warning: this documentation for the development version is under construction.
00001 // Copyright (C) 2001-2009 Vivien Mallet 00002 // Copyright (C) 2003-2009 Marc Duruflé 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_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 * CONSTRUCTORS * 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>() 00063 { 00064 nz_ = 0; 00065 ptr_ = NULL; 00066 ind_ = NULL; 00067 00068 Reallocate(i, j); 00069 } 00070 00071 00073 00080 template <class T, class Prop, class Storage, class Allocator> 00081 inline Matrix_Sparse<T, Prop, Storage, Allocator>:: 00082 Matrix_Sparse(int i, int j, int nz): 00083 Matrix_Base<T, Allocator>() 00084 { 00085 this->nz_ = 0; 00086 ind_ = NULL; 00087 ptr_ = NULL; 00088 00089 Reallocate(i, j, nz); 00090 } 00091 00092 00094 00105 template <class T, class Prop, class Storage, class Allocator> 00106 template <class Storage0, class Allocator0, 00107 class Storage1, class Allocator1, 00108 class Storage2, class Allocator2> 00109 inline Matrix_Sparse<T, Prop, Storage, Allocator>:: 00110 Matrix_Sparse(int i, int j, 00111 Vector<T, Storage0, Allocator0>& values, 00112 Vector<int, Storage1, Allocator1>& ptr, 00113 Vector<int, Storage2, Allocator2>& ind): 00114 Matrix_Base<T, Allocator>(i, j) 00115 { 00116 nz_ = values.GetLength(); 00117 00118 #ifdef SELDON_CHECK_DIMENSIONS 00119 // Checks whether vector sizes are acceptable. 00120 00121 if (ind.GetLength() != nz_) 00122 { 00123 this->m_ = 0; 00124 this->n_ = 0; 00125 nz_ = 0; 00126 ptr_ = NULL; 00127 ind_ = NULL; 00128 this->data_ = NULL; 00129 throw WrongDim(string("Matrix_Sparse::Matrix_Sparse(int, int, ") 00130 + "const Vector&, const Vector&, const Vector&)", 00131 string("There are ") + to_str(nz_) + " values but " 00132 + to_str(ind.GetLength()) + " row or column indices."); 00133 } 00134 00135 if (ptr.GetLength()-1 != Storage::GetFirst(i, j)) 00136 { 00137 this->m_ = 0; 00138 this->n_ = 0; 00139 nz_ = 0; 00140 ptr_ = NULL; 00141 ind_ = NULL; 00142 this->data_ = NULL; 00143 throw WrongDim(string("Matrix_Sparse::Matrix_Sparse(int, int, ") 00144 + "const Vector&, const Vector&, const Vector&)", 00145 string("The vector of start indices contains ") 00146 + to_str(ptr.GetLength()-1) + string(" row or column") 00147 + string(" start indices (plus the number") 00148 + " of non-zero entries) but there are " 00149 + to_str(Storage::GetFirst(i, j)) 00150 + " rows or columns (" + to_str(i) + " by " 00151 + to_str(j) + " matrix)."); 00152 } 00153 00154 if (nz_ > 0 00155 && (j == 0 00156 || static_cast<long int>(nz_-1) / static_cast<long int>(j) 00157 >= static_cast<long int>(i))) 00158 { 00159 this->m_ = 0; 00160 this->n_ = 0; 00161 nz_ = 0; 00162 ptr_ = NULL; 00163 ind_ = NULL; 00164 this->data_ = NULL; 00165 throw WrongDim(string("Matrix_Sparse::Matrix_Sparse(int, int, ") 00166 + "const Vector&, const Vector&, const Vector&)", 00167 string("There are more values (") 00168 + to_str(values.GetLength()) 00169 + " values) than elements in the matrix (" 00170 + to_str(i) + " by " + to_str(j) + ")."); 00171 } 00172 #endif 00173 00174 this->ptr_ = ptr.GetData(); 00175 this->ind_ = ind.GetData(); 00176 this->data_ = values.GetData(); 00177 00178 ptr.Nullify(); 00179 ind.Nullify(); 00180 values.Nullify(); 00181 } 00182 00183 00185 template <class T, class Prop, class Storage, class Allocator> 00186 inline Matrix_Sparse<T, Prop, Storage, Allocator>:: 00187 Matrix_Sparse(const Matrix_Sparse<T, Prop, Storage, Allocator>& A): 00188 Matrix_Base<T, Allocator>(A) 00189 { 00190 this->m_ = 0; 00191 this->n_ = 0; 00192 this->nz_ = 0; 00193 ptr_ = NULL; 00194 ind_ = NULL; 00195 this->Copy(A); 00196 } 00197 00198 00199 /************** 00200 * DESTRUCTOR * 00201 **************/ 00202 00203 00205 template <class T, class Prop, class Storage, class Allocator> 00206 inline Matrix_Sparse<T, Prop, Storage, Allocator>::~Matrix_Sparse() 00207 { 00208 this->m_ = 0; 00209 this->n_ = 0; 00210 00211 #ifdef SELDON_CHECK_MEMORY 00212 try 00213 { 00214 #endif 00215 00216 if (ptr_ != NULL) 00217 { 00218 free(ptr_); 00219 ptr_ = NULL; 00220 } 00221 00222 #ifdef SELDON_CHECK_MEMORY 00223 } 00224 catch (...) 00225 { 00226 ptr_ = NULL; 00227 } 00228 #endif 00229 00230 #ifdef SELDON_CHECK_MEMORY 00231 try 00232 { 00233 #endif 00234 00235 if (ind_ != NULL) 00236 { 00237 free(ind_); 00238 ind_ = NULL; 00239 } 00240 00241 #ifdef SELDON_CHECK_MEMORY 00242 } 00243 catch (...) 00244 { 00245 ind_ = NULL; 00246 } 00247 #endif 00248 00249 #ifdef SELDON_CHECK_MEMORY 00250 try 00251 { 00252 #endif 00253 00254 if (this->data_ != NULL) 00255 { 00256 this->allocator_.deallocate(this->data_, nz_); 00257 this->data_ = NULL; 00258 } 00259 00260 #ifdef SELDON_CHECK_MEMORY 00261 } 00262 catch (...) 00263 { 00264 this->nz_ = 0; 00265 this->data_ = NULL; 00266 } 00267 #endif 00268 00269 this->nz_ = 0; 00270 } 00271 00272 00274 00277 template <class T, class Prop, class Storage, class Allocator> 00278 inline void Matrix_Sparse<T, Prop, Storage, Allocator>::Clear() 00279 { 00280 this->~Matrix_Sparse(); 00281 } 00282 00283 00284 /********************* 00285 * MEMORY MANAGEMENT * 00286 *********************/ 00287 00288 00290 00300 template <class T, class Prop, class Storage, class Allocator> 00301 template <class Storage0, class Allocator0, 00302 class Storage1, class Allocator1, 00303 class Storage2, class Allocator2> 00304 void Matrix_Sparse<T, Prop, Storage, Allocator>:: 00305 SetData(int i, int j, 00306 Vector<T, Storage0, Allocator0>& values, 00307 Vector<int, Storage1, Allocator1>& ptr, 00308 Vector<int, Storage2, Allocator2>& ind) 00309 { 00310 this->Clear(); 00311 this->m_ = i; 00312 this->n_ = j; 00313 this->nz_ = values.GetLength(); 00314 00315 #ifdef SELDON_CHECK_DIMENSIONS 00316 // Checks whether vector sizes are acceptable. 00317 00318 if (ind.GetLength() != nz_) 00319 { 00320 this->m_ = 0; 00321 this->n_ = 0; 00322 nz_ = 0; 00323 ptr_ = NULL; 00324 ind_ = NULL; 00325 this->data_ = NULL; 00326 throw WrongDim(string("Matrix_Sparse::SetData(int, int, ") 00327 + "const Vector&, const Vector&, const Vector&)", 00328 string("There are ") + to_str(nz_) + " values but " 00329 + to_str(ind.GetLength()) + " row or column indices."); 00330 } 00331 00332 if (ptr.GetLength()-1 != Storage::GetFirst(i, j)) 00333 { 00334 this->m_ = 0; 00335 this->n_ = 0; 00336 nz_ = 0; 00337 ptr_ = NULL; 00338 ind_ = NULL; 00339 this->data_ = NULL; 00340 throw WrongDim(string("Matrix_Sparse::SetData(int, int, ") 00341 + "const Vector&, const Vector&, const Vector&)", 00342 string("The vector of start indices contains ") 00343 + to_str(ptr.GetLength()-1) + string(" row or column") 00344 + string(" start indices (plus the number") 00345 + " of non-zero entries) but there are " 00346 + to_str(Storage::GetFirst(i, j)) 00347 + " rows or columns (" + to_str(i) + " by " 00348 + to_str(j) + " matrix)."); 00349 } 00350 00351 if (nz_ > 0 00352 && (j == 0 00353 || static_cast<long int>(nz_-1) / static_cast<long int>(j) 00354 >= static_cast<long int>(i))) 00355 { 00356 this->m_ = 0; 00357 this->n_ = 0; 00358 nz_ = 0; 00359 ptr_ = NULL; 00360 ind_ = NULL; 00361 this->data_ = NULL; 00362 throw WrongDim(string("Matrix_Sparse::SetData(int, int, ") 00363 + "const Vector&, const Vector&, const Vector&)", 00364 string("There are more values (") 00365 + to_str(values.GetLength()) 00366 + " values) than elements in the matrix (" 00367 + to_str(i) + " by " + to_str(j) + ")."); 00368 } 00369 #endif 00370 00371 this->ptr_ = ptr.GetData(); 00372 this->ind_ = ind.GetData(); 00373 this->data_ = values.GetData(); 00374 00375 ptr.Nullify(); 00376 ind.Nullify(); 00377 values.Nullify(); 00378 } 00379 00380 00382 00395 template <class T, class Prop, class Storage, class Allocator> 00396 inline void Matrix_Sparse<T, Prop, Storage, Allocator> 00397 ::SetData(int i, int j, int nz, 00398 typename Matrix_Sparse<T, Prop, Storage, Allocator> 00399 ::pointer values, 00400 int* ptr, int* ind) 00401 { 00402 this->Clear(); 00403 00404 this->m_ = i; 00405 this->n_ = j; 00406 00407 this->nz_ = nz; 00408 00409 this->data_ = values; 00410 ind_ = ind; 00411 ptr_ = ptr; 00412 } 00413 00414 00416 00420 template <class T, class Prop, class Storage, class Allocator> 00421 inline void Matrix_Sparse<T, Prop, Storage, Allocator>::Nullify() 00422 { 00423 this->data_ = NULL; 00424 this->m_ = 0; 00425 this->n_ = 0; 00426 nz_ = 0; 00427 ptr_ = NULL; 00428 ind_ = NULL; 00429 } 00430 00431 00433 00437 template <class T, class Prop, class Storage, class Allocator> 00438 void Matrix_Sparse<T, Prop, Storage, Allocator>::Reallocate(int i, int j) 00439 { 00440 // clearing previous entries 00441 Clear(); 00442 00443 this->m_ = i; 00444 this->n_ = j; 00445 00446 // we try to allocate ptr_ 00447 #ifdef SELDON_CHECK_MEMORY 00448 try 00449 { 00450 #endif 00451 00452 ptr_ = reinterpret_cast<int*>( calloc(Storage::GetFirst(i, j)+1, 00453 sizeof(int)) ); 00454 00455 #ifdef SELDON_CHECK_MEMORY 00456 } 00457 catch (...) 00458 { 00459 this->m_ = 0; 00460 this->n_ = 0; 00461 nz_ = 0; 00462 ptr_ = NULL; 00463 ind_ = NULL; 00464 this->data_ = NULL; 00465 } 00466 if (ptr_ == NULL) 00467 { 00468 this->m_ = 0; 00469 this->n_ = 0; 00470 nz_ = 0; 00471 ind_ = NULL; 00472 this->data_ = NULL; 00473 } 00474 if (ptr_ == NULL && i != 0 && j != 0) 00475 throw NoMemory("Matrix_Sparse::Reallocate(int, int)", 00476 string("Unable to allocate ") 00477 + to_str(sizeof(int) * (Storage::GetFirst(i, j)+1) ) 00478 + " bytes to store " + to_str(Storage::GetFirst(i, j)+1) 00479 + " row or column start indices, for a " 00480 + to_str(i) + " by " + to_str(j) + " matrix."); 00481 #endif 00482 00483 // then filing ptr_ with 0 00484 for (int k = 0; k <= Storage::GetFirst(i, j); k++) 00485 ptr_[k] = 0; 00486 00487 } 00488 00489 00491 00496 template <class T, class Prop, class Storage, class Allocator> 00497 void Matrix_Sparse<T, Prop, Storage, Allocator>::Reallocate(int i, int j, int nz) 00498 { 00499 // clearing previous entries 00500 Clear(); 00501 00502 this->nz_ = nz; 00503 this->m_ = i; 00504 this->n_ = j; 00505 00506 #ifdef SELDON_CHECK_DIMENSIONS 00507 if (nz_ < 0) 00508 { 00509 this->m_ = 0; 00510 this->n_ = 0; 00511 nz_ = 0; 00512 ptr_ = NULL; 00513 ind_ = NULL; 00514 this->data_ = NULL; 00515 throw WrongDim("Matrix_Sparse::Matrix_Sparse(int, int, int)", 00516 "Invalid number of non-zero elements: " + to_str(nz) 00517 + "."); 00518 } 00519 if (nz_ > 0 00520 && (j == 0 00521 || static_cast<long int>(nz_-1) / static_cast<long int>(j) 00522 >= static_cast<long int>(i))) 00523 { 00524 this->m_ = 0; 00525 this->n_ = 0; 00526 nz_ = 0; 00527 ptr_ = NULL; 00528 ind_ = NULL; 00529 this->data_ = NULL; 00530 throw WrongDim("Matrix_Sparse::Matrix_Sparse(int, int, int)", 00531 string("There are more values (") + to_str(nz) 00532 + " values) than elements in the matrix (" 00533 + to_str(i) + " by " + to_str(j) + ")."); 00534 } 00535 #endif 00536 00537 #ifdef SELDON_CHECK_MEMORY 00538 try 00539 { 00540 #endif 00541 00542 ptr_ = reinterpret_cast<int*>( calloc(Storage::GetFirst(i, j)+1, 00543 sizeof(int)) ); 00544 00545 #ifdef SELDON_CHECK_MEMORY 00546 } 00547 catch (...) 00548 { 00549 this->m_ = 0; 00550 this->n_ = 0; 00551 nz_ = 0; 00552 ptr_ = NULL; 00553 ind_ = NULL; 00554 this->data_ = NULL; 00555 } 00556 if (ptr_ == NULL) 00557 { 00558 this->m_ = 0; 00559 this->n_ = 0; 00560 nz_ = 0; 00561 ind_ = NULL; 00562 this->data_ = NULL; 00563 } 00564 if (ptr_ == NULL && i != 0 && j != 0) 00565 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)", 00566 string("Unable to allocate ") 00567 + to_str(sizeof(int) * (Storage::GetFirst(i, j)+1) ) 00568 + " bytes to store " + to_str(Storage::GetFirst(i, j)+1) 00569 + " row or column start indices, for a " 00570 + to_str(i) + " by " + to_str(j) + " matrix."); 00571 #endif 00572 00573 #ifdef SELDON_CHECK_MEMORY 00574 try 00575 { 00576 #endif 00577 00578 ind_ = reinterpret_cast<int*>( calloc(nz_, sizeof(int)) ); 00579 00580 #ifdef SELDON_CHECK_MEMORY 00581 } 00582 catch (...) 00583 { 00584 this->m_ = 0; 00585 this->n_ = 0; 00586 nz_ = 0; 00587 free(ptr_); 00588 ptr_ = NULL; 00589 ind_ = NULL; 00590 this->data_ = NULL; 00591 } 00592 if (ind_ == NULL) 00593 { 00594 this->m_ = 0; 00595 this->n_ = 0; 00596 nz_ = 0; 00597 free(ptr_); 00598 ptr_ = NULL; 00599 this->data_ = NULL; 00600 } 00601 if (ind_ == NULL && i != 0 && j != 0) 00602 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)", 00603 string("Unable to allocate ") + to_str(sizeof(int) * nz) 00604 + " bytes to store " + to_str(nz) 00605 + " row or column indices, for a " 00606 + to_str(i) + " by " + to_str(j) + " matrix."); 00607 #endif 00608 00609 #ifdef SELDON_CHECK_MEMORY 00610 try 00611 { 00612 #endif 00613 00614 this->data_ = this->allocator_.allocate(nz_, this); 00615 00616 #ifdef SELDON_CHECK_MEMORY 00617 } 00618 catch (...) 00619 { 00620 this->m_ = 0; 00621 this->n_ = 0; 00622 free(ptr_); 00623 ptr_ = NULL; 00624 free(ind_); 00625 ind_ = NULL; 00626 this->data_ = NULL; 00627 } 00628 if (this->data_ == NULL) 00629 { 00630 this->m_ = 0; 00631 this->n_ = 0; 00632 free(ptr_); 00633 ptr_ = NULL; 00634 free(ind_); 00635 ind_ = NULL; 00636 } 00637 if (this->data_ == NULL && i != 0 && j != 0) 00638 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)", 00639 string("Unable to allocate ") + to_str(sizeof(int) * nz) 00640 + " bytes to store " + to_str(nz) + " values, for a " 00641 + to_str(i) + " by " + to_str(j) + " matrix."); 00642 #endif 00643 } 00644 00645 00647 00652 template <class T, class Prop, class Storage, class Allocator> 00653 void Matrix_Sparse<T, Prop, Storage, Allocator>::Resize(int i, int j) 00654 { 00655 if (Storage::GetFirst(i, j) < Storage::GetFirst(this->m_, this->n_)) 00656 Resize(i, j, ptr_[Storage::GetFirst(i, j)]); 00657 else 00658 Resize(i, j, nz_); 00659 } 00660 00661 00663 00669 template <class T, class Prop, class Storage, class Allocator> 00670 void Matrix_Sparse<T, Prop, Storage, Allocator> 00671 ::Resize(int i, int j, int nz) 00672 { 00673 00674 #ifdef SELDON_CHECK_DIMENSIONS 00675 if (nz < 0) 00676 { 00677 this->m_ = 0; 00678 this->n_ = 0; 00679 nz_ = 0; 00680 ptr_ = NULL; 00681 ind_ = NULL; 00682 this->data_ = NULL; 00683 throw WrongDim("Matrix_Sparse::Resize(int, int, int)", 00684 "Invalid number of non-zero elements: " + to_str(nz) 00685 + "."); 00686 } 00687 if (nz > 0 00688 && (j == 0 00689 || static_cast<long int>(nz_-1) / static_cast<long int>(j) 00690 >= static_cast<long int>(i))) 00691 { 00692 this->m_ = 0; 00693 this->n_ = 0; 00694 nz_ = 0; 00695 ptr_ = NULL; 00696 ind_ = NULL; 00697 this->data_ = NULL; 00698 throw WrongDim("Matrix_Sparse::Resize(int, int, int)", 00699 string("There are more values (") + to_str(nz) 00700 + " values) than elements in the matrix (" 00701 + to_str(i) + " by " + to_str(j) + ")."); 00702 } 00703 #endif 00704 00705 if (nz != nz_) 00706 { 00707 // trying to resize ind_ and data_ 00708 #ifdef SELDON_CHECK_MEMORY 00709 try 00710 { 00711 #endif 00712 00713 ind_ 00714 = reinterpret_cast<int*>(realloc(reinterpret_cast<void*>(ind_), 00715 nz*sizeof(int))); 00716 00717 #ifdef SELDON_CHECK_MEMORY 00718 } 00719 catch (...) 00720 { 00721 this->m_ = 0; 00722 this->n_ = 0; 00723 nz_ = 0; 00724 free(ptr_); 00725 ptr_ = NULL; 00726 ind_ = NULL; 00727 this->data_ = NULL; 00728 } 00729 if (ind_ == NULL) 00730 { 00731 this->m_ = 0; 00732 this->n_ = 0; 00733 nz_ = 0; 00734 free(ptr_); 00735 ptr_ = NULL; 00736 this->data_ = NULL; 00737 } 00738 if (ind_ == NULL && i != 0 && j != 0) 00739 throw NoMemory("Matrix_Sparse::Resize(int, int, int)", 00740 string("Unable to allocate ") + to_str(sizeof(int) * nz) 00741 + " bytes to store " + to_str(nz) 00742 + " row or column indices, for a " 00743 + to_str(i) + " by " + to_str(j) + " matrix."); 00744 #endif 00745 00746 Vector<T, VectFull, Allocator> val; 00747 val.SetData(nz_, this->data_); 00748 val.Resize(nz); 00749 00750 this->data_ = val.GetData(); 00751 nz_ = nz; 00752 val.Nullify(); 00753 } 00754 00755 00756 if (Storage::GetFirst(this->m_, this->n_) != Storage::GetFirst(i, j)) 00757 { 00758 #ifdef SELDON_CHECK_MEMORY 00759 try 00760 { 00761 #endif 00762 // trying to resize ptr_ 00763 ptr_ = reinterpret_cast<int*>( realloc(ptr_, (Storage::GetFirst(i, j)+1)* 00764 sizeof(int)) ); 00765 00766 #ifdef SELDON_CHECK_MEMORY 00767 } 00768 catch (...) 00769 { 00770 this->m_ = 0; 00771 this->n_ = 0; 00772 nz_ = 0; 00773 ptr_ = NULL; 00774 ind_ = NULL; 00775 this->data_ = NULL; 00776 } 00777 if (ptr_ == NULL) 00778 { 00779 this->m_ = 0; 00780 this->n_ = 0; 00781 nz_ = 0; 00782 ind_ = NULL; 00783 this->data_ = NULL; 00784 } 00785 if (ptr_ == NULL && i != 0 && j != 0) 00786 throw NoMemory("Matrix_Sparse::Resize(int, int)", 00787 string("Unable to allocate ") 00788 + to_str(sizeof(int) * (Storage::GetFirst(i, j)+1) ) 00789 + " bytes to store " + to_str(Storage::GetFirst(i, j)+1) 00790 + " row or column start indices, for a " 00791 + to_str(i) + " by " + to_str(j) + " matrix."); 00792 #endif 00793 00794 // then filing last values of ptr_ with nz_ 00795 for (int k = Storage::GetFirst(this->m_, this->n_); 00796 k <= Storage::GetFirst(i, j); k++) 00797 ptr_[k] = this->nz_; 00798 } 00799 00800 this->m_ = i; 00801 this->n_ = j; 00802 } 00803 00804 00806 template <class T, class Prop, class Storage, class Allocator> 00807 inline void Matrix_Sparse<T, Prop, Storage, Allocator>:: 00808 Copy(const Matrix_Sparse<T, Prop, Storage, Allocator>& A) 00809 { 00810 this->Clear(); 00811 int nz = A.nz_; 00812 int i = A.m_; 00813 int j = A.n_; 00814 this->nz_ = nz; 00815 this->m_ = i; 00816 this->n_ = j; 00817 if ((i == 0)||(j == 0)) 00818 { 00819 this->m_ = 0; 00820 this->n_ = 0; 00821 this->nz_ = 0; 00822 return; 00823 } 00824 00825 #ifdef SELDON_CHECK_DIMENSIONS 00826 if (nz_ > 0 00827 && (j == 0 00828 || static_cast<long int>(nz_-1) / static_cast<long int>(j) 00829 >= static_cast<long int>(i))) 00830 { 00831 this->m_ = 0; 00832 this->n_ = 0; 00833 nz_ = 0; 00834 ptr_ = NULL; 00835 ind_ = NULL; 00836 this->data_ = NULL; 00837 throw WrongDim("Matrix_Sparse::Matrix_Sparse(int, int, int)", 00838 string("There are more values (") + to_str(nz) 00839 + " values) than elements in the matrix (" 00840 + to_str(i) + " by " + to_str(j) + ")."); 00841 } 00842 #endif 00843 00844 #ifdef SELDON_CHECK_MEMORY 00845 try 00846 { 00847 #endif 00848 00849 ptr_ = reinterpret_cast<int*>( calloc(Storage::GetFirst(i, j)+1, 00850 sizeof(int)) ); 00851 memcpy(this->ptr_, A.ptr_, 00852 (Storage::GetFirst(i, j) + 1) * sizeof(int)); 00853 #ifdef SELDON_CHECK_MEMORY 00854 } 00855 catch (...) 00856 { 00857 this->m_ = 0; 00858 this->n_ = 0; 00859 nz_ = 0; 00860 ptr_ = NULL; 00861 ind_ = NULL; 00862 this->data_ = NULL; 00863 } 00864 if (ptr_ == NULL) 00865 { 00866 this->m_ = 0; 00867 this->n_ = 0; 00868 nz_ = 0; 00869 ind_ = NULL; 00870 this->data_ = NULL; 00871 } 00872 if (ptr_ == NULL && i != 0 && j != 0) 00873 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)", 00874 string("Unable to allocate ") 00875 + to_str(sizeof(int) * (Storage::GetFirst(i, j)+1) ) 00876 + " bytes to store " + to_str(Storage::GetFirst(i, j)+1) 00877 + " row or column start indices, for a " 00878 + to_str(i) + " by " + to_str(j) + " matrix."); 00879 #endif 00880 00881 #ifdef SELDON_CHECK_MEMORY 00882 try 00883 { 00884 #endif 00885 00886 ind_ = reinterpret_cast<int*>( calloc(nz_, sizeof(int)) ); 00887 memcpy(this->ind_, A.ind_, nz_ * sizeof(int)); 00888 00889 #ifdef SELDON_CHECK_MEMORY 00890 } 00891 catch (...) 00892 { 00893 this->m_ = 0; 00894 this->n_ = 0; 00895 nz_ = 0; 00896 free(ptr_); 00897 ptr_ = NULL; 00898 ind_ = NULL; 00899 this->data_ = NULL; 00900 } 00901 if (ind_ == NULL) 00902 { 00903 this->m_ = 0; 00904 this->n_ = 0; 00905 nz_ = 0; 00906 free(ptr_); 00907 ptr_ = NULL; 00908 this->data_ = NULL; 00909 } 00910 if (ind_ == NULL && i != 0 && j != 0) 00911 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)", 00912 string("Unable to allocate ") + to_str(sizeof(int) * nz) 00913 + " bytes to store " + to_str(nz) 00914 + " row or column indices, for a " 00915 + to_str(i) + " by " + to_str(j) + " matrix."); 00916 #endif 00917 00918 #ifdef SELDON_CHECK_MEMORY 00919 try 00920 { 00921 #endif 00922 00923 this->data_ = this->allocator_.allocate(nz_, this); 00924 this->allocator_.memorycpy(this->data_, A.data_, nz_); 00925 00926 #ifdef SELDON_CHECK_MEMORY 00927 } 00928 catch (...) 00929 { 00930 this->m_ = 0; 00931 this->n_ = 0; 00932 free(ptr_); 00933 ptr_ = NULL; 00934 free(ind_); 00935 ind_ = NULL; 00936 this->data_ = NULL; 00937 } 00938 if (this->data_ == NULL) 00939 { 00940 this->m_ = 0; 00941 this->n_ = 0; 00942 free(ptr_); 00943 ptr_ = NULL; 00944 free(ind_); 00945 ind_ = NULL; 00946 } 00947 if (this->data_ == NULL && i != 0 && j != 0) 00948 throw NoMemory("Matrix_Sparse::Matrix_Sparse(int, int, int)", 00949 string("Unable to allocate ") + to_str(sizeof(int) * nz) 00950 + " bytes to store " + to_str(nz) + " values, for a " 00951 + to_str(i) + " by " + to_str(j) + " matrix."); 00952 #endif 00953 00954 } 00955 00956 00957 /******************* 00958 * BASIC FUNCTIONS * 00959 *******************/ 00960 00961 00963 00966 template <class T, class Prop, class Storage, class Allocator> 00967 int Matrix_Sparse<T, Prop, Storage, Allocator>::GetNonZeros() const 00968 { 00969 return nz_; 00970 } 00971 00972 00974 00979 template <class T, class Prop, class Storage, class Allocator> 00980 int Matrix_Sparse<T, Prop, Storage, Allocator>::GetDataSize() const 00981 { 00982 return nz_; 00983 } 00984 00985 00987 00991 template <class T, class Prop, class Storage, class Allocator> 00992 int* Matrix_Sparse<T, Prop, Storage, Allocator>::GetPtr() const 00993 { 00994 return ptr_; 00995 } 00996 00997 00999 01006 template <class T, class Prop, class Storage, class Allocator> 01007 int* Matrix_Sparse<T, Prop, Storage, Allocator>::GetInd() const 01008 { 01009 return ind_; 01010 } 01011 01012 01014 01017 template <class T, class Prop, class Storage, class Allocator> 01018 int Matrix_Sparse<T, Prop, Storage, Allocator>::GetPtrSize() const 01019 { 01020 return (Storage::GetFirst(this->m_, this->n_) + 1); 01021 } 01022 01023 01025 01033 template <class T, class Prop, class Storage, class Allocator> 01034 int Matrix_Sparse<T, Prop, Storage, Allocator>::GetIndSize() const 01035 { 01036 return nz_; 01037 } 01038 01039 01040 /********************************** 01041 * ELEMENT ACCESS AND AFFECTATION * 01042 **********************************/ 01043 01044 01046 01052 template <class T, class Prop, class Storage, class Allocator> 01053 inline typename Matrix_Sparse<T, Prop, Storage, Allocator>::value_type 01054 Matrix_Sparse<T, Prop, Storage, Allocator>::operator() (int i, int j) const 01055 { 01056 01057 #ifdef SELDON_CHECK_BOUNDS 01058 if (i < 0 || i >= this->m_) 01059 throw WrongRow("Matrix_Sparse::operator()", 01060 string("Index should be in [0, ") + to_str(this->m_-1) 01061 + "], but is equal to " + to_str(i) + "."); 01062 if (j < 0 || j >= this->n_) 01063 throw WrongCol("Matrix_Sparse::operator()", 01064 string("Index should be in [0, ") + to_str(this->n_-1) 01065 + "], but is equal to " + to_str(j) + "."); 01066 #endif 01067 01068 int k,l; 01069 int a,b; 01070 01071 a = ptr_[Storage::GetFirst(i, j)]; 01072 b = ptr_[Storage::GetFirst(i, j) + 1]; 01073 01074 if (a == b) 01075 return T(0); 01076 01077 l = Storage::GetSecond(i, j); 01078 01079 for (k = a; (k < b-1) && (ind_[k] < l); k++); 01080 01081 if (ind_[k] == l) 01082 return this->data_[k]; 01083 else 01084 return T(0); 01085 } 01086 01087 01089 01097 template <class T, class Prop, class Storage, class Allocator> 01098 inline typename Matrix_Sparse<T, Prop, Storage, Allocator>::value_type& 01099 Matrix_Sparse<T, Prop, Storage, Allocator>::Val(int i, int j) 01100 { 01101 01102 #ifdef SELDON_CHECK_BOUNDS 01103 if (i < 0 || i >= this->m_) 01104 throw WrongRow("Matrix_Sparse::Val(int, int)", 01105 string("Index should be in [0, ") + to_str(this->m_-1) 01106 + "], but is equal to " + to_str(i) + "."); 01107 if (j < 0 || j >= this->n_) 01108 throw WrongCol("Matrix_Sparse::Val(int, int)", 01109 string("Index should be in [0, ") + to_str(this->n_-1) 01110 + "], but is equal to " + to_str(j) + "."); 01111 #endif 01112 01113 int k, l; 01114 int a, b; 01115 01116 a = ptr_[Storage::GetFirst(i, j)]; 01117 b = ptr_[Storage::GetFirst(i, j) + 1]; 01118 01119 if (a == b) 01120 throw WrongArgument("Matrix_Sparse::Val(int, int)", 01121 "No reference to element (" + to_str(i) + ", " 01122 + to_str(j) 01123 + ") can be returned: it is a zero entry."); 01124 01125 l = Storage::GetSecond(i, j); 01126 01127 for (k = a; (k < b-1) && (ind_[k] < l); k++); 01128 01129 if (ind_[k] == l) 01130 return this->data_[k]; 01131 else 01132 throw WrongArgument("Matrix_Sparse::Val(int, int)", 01133 "No reference to element (" + to_str(i) + ", " 01134 + to_str(j) 01135 + ") can be returned: it is a zero entry."); 01136 } 01137 01138 01140 01148 template <class T, class Prop, class Storage, class Allocator> 01149 inline 01150 const typename Matrix_Sparse<T, Prop, Storage, Allocator>::value_type& 01151 Matrix_Sparse<T, Prop, Storage, Allocator>::Val(int i, int j) const 01152 { 01153 01154 #ifdef SELDON_CHECK_BOUNDS 01155 if (i < 0 || i >= this->m_) 01156 throw WrongRow("Matrix_Sparse::Val(int, int)", 01157 string("Index should be in [0, ") + to_str(this->m_-1) 01158 + "], but is equal to " + to_str(i) + "."); 01159 if (j < 0 || j >= this->n_) 01160 throw WrongCol("Matrix_Sparse::Val(int, int)", 01161 string("Index should be in [0, ") + to_str(this->n_-1) 01162 + "], but is equal to " + to_str(j) + "."); 01163 #endif 01164 01165 int k, l; 01166 int a, b; 01167 01168 a = ptr_[Storage::GetFirst(i, j)]; 01169 b = ptr_[Storage::GetFirst(i, j) + 1]; 01170 01171 if (a == b) 01172 throw WrongArgument("Matrix_Sparse::Val(int, int)", 01173 "No reference to element (" + to_str(i) + ", " 01174 + to_str(j) 01175 + ") can be returned: it is a zero entry."); 01176 01177 l = Storage::GetSecond(i, j); 01178 01179 for (k = a; (k < b-1) && (ind_[k] < l); k++); 01180 01181 if (ind_[k] == l) 01182 return this->data_[k]; 01183 else 01184 throw WrongArgument("Matrix_Sparse::Val(int, int)", 01185 "No reference to element (" + to_str(i) + ", " 01186 + to_str(j) 01187 + ") can be returned: it is a zero entry."); 01188 } 01189 01190 01192 01199 template <class T, class Prop, class Storage, class Allocator> 01200 inline typename Matrix_Sparse<T, Prop, Storage, Allocator>::value_type& 01201 Matrix_Sparse<T, Prop, Storage, Allocator>::Get(int i, int j) 01202 { 01203 01204 #ifdef SELDON_CHECK_BOUNDS 01205 if (i < 0 || i >= this->m_) 01206 throw WrongRow("Matrix_Sparse::Get(int, int)", 01207 string("Index should be in [0, ") + to_str(this->m_-1) 01208 + "], but is equal to " + to_str(i) + "."); 01209 if (j < 0 || j >= this->n_) 01210 throw WrongCol("Matrix_Sparse::Get(int, int)", 01211 string("Index should be in [0, ") + to_str(this->n_-1) 01212 + "], but is equal to " + to_str(j) + "."); 01213 #endif 01214 01215 int k, l; 01216 int a, b; 01217 01218 a = ptr_[Storage::GetFirst(i, j)]; 01219 b = ptr_[Storage::GetFirst(i, j) + 1]; 01220 01221 if (a < b) 01222 { 01223 l = Storage::GetSecond(i, j); 01224 01225 for (k = a; (k < b) && (ind_[k] < l); k++); 01226 01227 if ( (k < b) && (ind_[k] == l)) 01228 return this->data_[k]; 01229 } 01230 else 01231 k = a; 01232 01233 // adding a non-zero entry 01234 Resize(this->m_, this->n_, nz_+1); 01235 01236 for (int m = Storage::GetFirst(i, j)+1; 01237 m <= Storage::GetFirst(this->m_, this->n_); m++) 01238 ptr_[m]++; 01239 01240 for (int m = nz_-1; m >= k+1; m--) 01241 { 01242 ind_[m] = ind_[m-1]; 01243 this->data_[m] = this->data_[m-1]; 01244 } 01245 01246 ind_[k] = Storage::GetSecond(i, j); 01247 01248 // value of new non-zero entry is set to 0 01249 SetComplexZero(this->data_[k]); 01250 01251 return this->data_[k]; 01252 } 01253 01254 01256 01261 template <class T, class Prop, class Storage, class Allocator> 01262 inline const typename Matrix_Sparse<T, Prop, Storage, Allocator>::value_type& 01263 Matrix_Sparse<T, Prop, Storage, Allocator>::Get(int i, int j) const 01264 { 01265 return Val(i, j); 01266 } 01267 01268 01270 01277 template <class T, class Prop, class Storage, class Allocator> 01278 inline void Matrix_Sparse<T, Prop, Storage, Allocator> 01279 ::AddInteraction(int i, int j, const T& val) 01280 { 01281 Get(i, j) += val; 01282 } 01283 01284 01286 01291 template <class T, class Prop, class Storage, class Allocator> 01292 inline void Matrix_Sparse<T, Prop, Storage, Allocator> 01293 ::Set(int i, int j, const T& val) 01294 { 01295 Get(i, j) = val; 01296 } 01297 01298 01300 01305 template <class T, class Prop, class Storage, class Allocator> 01306 inline Matrix_Sparse<T, Prop, Storage, Allocator>& 01307 Matrix_Sparse<T, Prop, Storage, Allocator> 01308 ::operator= (const Matrix_Sparse<T, Prop, Storage, Allocator>& A) 01309 { 01310 this->Copy(A); 01311 01312 return *this; 01313 } 01314 01315 01316 /************************ 01317 * CONVENIENT FUNCTIONS * 01318 ************************/ 01319 01320 01322 01323 template <class T, class Prop, class Storage, class Allocator> 01324 void Matrix_Sparse<T, Prop, Storage, Allocator>::Zero() 01325 { 01326 this->allocator_.memoryset(this->data_, char(0), 01327 this->nz_ * sizeof(value_type)); 01328 } 01329 01330 01332 01335 template <class T, class Prop, class Storage, class Allocator> 01336 void Matrix_Sparse<T, Prop, Storage, Allocator>::SetIdentity() 01337 { 01338 int m = this->m_; 01339 int n = this->n_; 01340 int nz = min(m, n); 01341 01342 if (nz == 0) 01343 return; 01344 01345 Clear(); 01346 01347 Vector<T, VectFull, Allocator> values(nz); 01348 Vector<int, VectFull, CallocAlloc<int> > ptr(Storage::GetFirst(m, n) + 1); 01349 Vector<int, VectFull, CallocAlloc<int> > ind(nz); 01350 01351 T one; SetComplexOne(one); 01352 values.Fill(one); 01353 ind.Fill(); 01354 int i; 01355 for (i = 0; i < nz + 1; i++) 01356 ptr(i) = i; 01357 for (i = nz + 1; i < ptr.GetLength(); i++) 01358 ptr(i) = nz; 01359 01360 SetData(m, n, values, ptr, ind); 01361 } 01362 01363 01365 01368 template <class T, class Prop, class Storage, class Allocator> 01369 void Matrix_Sparse<T, Prop, Storage, Allocator>::Fill() 01370 { 01371 for (int i = 0; i < this->GetDataSize(); i++) 01372 this->data_[i] = i; 01373 } 01374 01375 01377 01380 template <class T, class Prop, class Storage, class Allocator> 01381 template <class T0> 01382 void Matrix_Sparse<T, Prop, Storage, Allocator>::Fill(const T0& x) 01383 { 01384 for (int i = 0; i < this->GetDataSize(); i++) 01385 this->data_[i] = x; 01386 } 01387 01388 01390 01393 template <class T, class Prop, class Storage, class Allocator> 01394 void Matrix_Sparse<T, Prop, Storage, Allocator>::FillRand() 01395 { 01396 srand(time(NULL)); 01397 for (int i = 0; i < this->GetDataSize(); i++) 01398 this->data_[i] = rand(); 01399 } 01400 01401 01403 01411 template <class T, class Prop, class Storage, class Allocator> 01412 void Matrix_Sparse<T, Prop, Storage, Allocator> 01413 ::FillRand(int Nelement) 01414 { 01415 if (this->m_ == 0 || this->n_ == 0) 01416 return; 01417 01418 Vector<int> i(Nelement), j(Nelement); 01419 Vector<T> value(Nelement); 01420 01421 set<pair<int, int> > skeleton; 01422 set<pair<int, int> >::iterator it; 01423 01424 srand(time(NULL)); 01425 01426 // generation of triplet (i, j, value) 01427 while (static_cast<int>(skeleton.size()) != Nelement) 01428 skeleton.insert(make_pair(rand() % this->m_, rand() % this->n_)); 01429 01430 int l = 0; 01431 for (it = skeleton.begin(); it != skeleton.end(); it++) 01432 { 01433 i(l) = it->first; 01434 j(l) = it->second; 01435 value(l) = double(rand()); 01436 l++; 01437 } 01438 01439 // then conversion to current sparse matrix 01440 Matrix<T, Prop, Storage, Allocator>& leaf_class = 01441 static_cast<Matrix<T, Prop, Storage, Allocator>& >(*this); 01442 01443 ConvertMatrix_from_Coordinates(i, j, value, leaf_class, 0); 01444 } 01445 01446 01448 01458 template <class T, class Prop, class Storage, class Allocator> 01459 void Matrix_Sparse<T, Prop, Storage, Allocator> 01460 ::FillRand(int Nelement, const T& x) 01461 { 01462 if (this->m_ == 0 || this->n_ == 0) 01463 return; 01464 01465 Vector<int> i(Nelement), j(Nelement); 01466 Vector<T> value(Nelement); 01467 value.Fill(x); 01468 01469 srand(time(NULL)); 01470 for (int l = 0; l < Nelement; l++) 01471 { 01472 i(l) = rand() % this->m_; 01473 j(l) = rand() % this->n_; 01474 } 01475 01476 // then conversion to current sparse matrix 01477 Matrix<T, Prop, Storage, Allocator>& leaf_class = 01478 static_cast<Matrix<T, Prop, Storage, Allocator>& >(*this); 01479 01480 ConvertMatrix_from_Coordinates(i, j, value, leaf_class, 0); 01481 } 01482 01483 01485 01490 template <class T, class Prop, class Storage, class Allocator> 01491 void Matrix_Sparse<T, Prop, Storage, Allocator>::Print() const 01492 { 01493 for (int i = 0; i < this->m_; i++) 01494 { 01495 for (int j = 0; j < this->n_; j++) 01496 cout << (*this)(i, j) << "\t"; 01497 cout << endl; 01498 } 01499 } 01500 01501 01503 01507 template <class T, class Prop, class Storage, class Allocator> 01508 void Matrix_Sparse<T, Prop, Storage, Allocator> 01509 ::Write(string FileName) const 01510 { 01511 ofstream FileStream; 01512 FileStream.open(FileName.c_str()); 01513 01514 #ifdef SELDON_CHECK_IO 01515 // Checks if the file was opened. 01516 if (!FileStream.is_open()) 01517 throw IOError("Matrix_Sparse::Write(string FileName)", 01518 string("Unable to open file \"") + FileName + "\"."); 01519 #endif 01520 01521 this->Write(FileStream); 01522 01523 FileStream.close(); 01524 } 01525 01526 01528 01532 template <class T, class Prop, class Storage, class Allocator> 01533 void Matrix_Sparse<T, Prop, Storage, Allocator> 01534 ::Write(ostream& FileStream) const 01535 { 01536 #ifdef SELDON_CHECK_IO 01537 // Checks if the stream is ready. 01538 if (!FileStream.good()) 01539 throw IOError("Matrix_Sparse::Write(ofstream& FileStream)", 01540 "Stream is not ready."); 01541 #endif 01542 01543 FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)), 01544 sizeof(int)); 01545 FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->n_)), 01546 sizeof(int)); 01547 FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->nz_)), 01548 sizeof(int)); 01549 01550 FileStream.write(reinterpret_cast<char*>(this->ptr_), 01551 sizeof(int)*(Storage::GetFirst(this->m_, this->n_)+1)); 01552 FileStream.write(reinterpret_cast<char*>(this->ind_), 01553 sizeof(int)*this->nz_); 01554 FileStream.write(reinterpret_cast<char*>(this->data_), 01555 sizeof(T)*this->nz_); 01556 } 01557 01558 01560 01566 template <class T, class Prop, class Storage, class Allocator> 01567 void Matrix_Sparse<T, Prop, Storage, Allocator>:: 01568 WriteText(string FileName) const 01569 { 01570 ofstream FileStream; FileStream.precision(14); 01571 FileStream.open(FileName.c_str()); 01572 01573 #ifdef SELDON_CHECK_IO 01574 // Checks if the file was opened. 01575 if (!FileStream.is_open()) 01576 throw IOError("Matrix_Sparse::Write(string FileName)", 01577 string("Unable to open file \"") + FileName + "\"."); 01578 #endif 01579 01580 this->WriteText(FileStream); 01581 01582 FileStream.close(); 01583 } 01584 01585 01587 01593 template <class T, class Prop, class Storage, class Allocator> 01594 void Matrix_Sparse<T, Prop, Storage, Allocator>:: 01595 WriteText(ostream& FileStream) const 01596 { 01597 01598 #ifdef SELDON_CHECK_IO 01599 // Checks if the stream is ready. 01600 if (!FileStream.good()) 01601 throw IOError("Matrix_Sparse::Write(ofstream& FileStream)", 01602 "Stream is not ready."); 01603 #endif 01604 01605 // conversion in coordinate format (1-index convention) 01606 IVect IndRow, IndCol; Vector<T> Value; 01607 const Matrix<T, Prop, Storage, Allocator>& leaf_class = 01608 static_cast<const Matrix<T, Prop, Storage, Allocator>& >(*this); 01609 01610 ConvertMatrix_to_Coordinates(leaf_class, IndRow, IndCol, 01611 Value, 1, true); 01612 01613 for (int i = 0; i < IndRow.GetM(); i++) 01614 FileStream << IndRow(i) << " " << IndCol(i) << " " << Value(i) << '\n'; 01615 01616 } 01617 01618 01620 01624 template <class T, class Prop, class Storage, class Allocator> 01625 void Matrix_Sparse<T, Prop, Storage, Allocator>:: 01626 Read(string FileName) 01627 { 01628 ifstream FileStream; 01629 FileStream.open(FileName.c_str()); 01630 01631 #ifdef SELDON_CHECK_IO 01632 // Checks if the file was opened. 01633 if (!FileStream.is_open()) 01634 throw IOError("Matrix_Sparse::Read(string FileName)", 01635 string("Unable to open file \"") + FileName + "\"."); 01636 #endif 01637 01638 this->Read(FileStream); 01639 01640 FileStream.close(); 01641 } 01642 01643 01645 01649 template <class T, class Prop, class Storage, class Allocator> 01650 void Matrix_Sparse<T, Prop, Storage, Allocator>:: 01651 Read(istream& FileStream) 01652 { 01653 01654 #ifdef SELDON_CHECK_IO 01655 // Checks if the stream is ready. 01656 if (!FileStream.good()) 01657 throw IOError("Matrix_Sparse::Read(istream& FileStream)", 01658 "Stream is not ready."); 01659 #endif 01660 01661 int m, n, nz; 01662 FileStream.read(reinterpret_cast<char*>(&m), sizeof(int)); 01663 FileStream.read(reinterpret_cast<char*>(&n), sizeof(int)); 01664 FileStream.read(reinterpret_cast<char*>(&nz), sizeof(int)); 01665 01666 Reallocate(m, n, nz); 01667 01668 FileStream.read(reinterpret_cast<char*>(ptr_), 01669 sizeof(int)*(Storage::GetFirst(m, n)+1)); 01670 FileStream.read(reinterpret_cast<char*>(ind_), sizeof(int)*nz); 01671 FileStream.read(reinterpret_cast<char*>(this->data_), sizeof(T)*nz); 01672 01673 #ifdef SELDON_CHECK_IO 01674 // Checks if data was read. 01675 if (!FileStream.good()) 01676 throw IOError("Matrix_Sparse::Read(istream& FileStream)", 01677 string("Input operation failed.") 01678 + string(" The input file may have been removed") 01679 + " or may not contain enough data."); 01680 #endif 01681 01682 } 01683 01684 01686 01690 template <class T, class Prop, class Storage, class Allocator> 01691 void Matrix_Sparse<T, Prop, Storage, Allocator>:: 01692 ReadText(string FileName) 01693 { 01694 ifstream FileStream; 01695 FileStream.open(FileName.c_str()); 01696 01697 #ifdef SELDON_CHECK_IO 01698 // Checks if the file was opened. 01699 if (!FileStream.is_open()) 01700 throw IOError("Matrix_Sparse::ReadText(string FileName)", 01701 string("Unable to open file \"") + FileName + "\"."); 01702 #endif 01703 01704 this->ReadText(FileStream); 01705 01706 FileStream.close(); 01707 } 01708 01709 01711 01715 template <class T, class Prop, class Storage, class Allocator> 01716 void Matrix_Sparse<T, Prop, Storage, Allocator>:: 01717 ReadText(istream& FileStream) 01718 { 01719 Matrix<T, Prop, Storage, Allocator>& leaf_class = 01720 static_cast<Matrix<T, Prop, Storage, Allocator>& >(*this); 01721 01722 T zero; int index = 1; 01723 ReadCoordinateMatrix(leaf_class, FileStream, zero, index); 01724 } 01725 01726 01728 // MATRIX<COLSPARSE> // 01730 01731 01732 /**************** 01733 * CONSTRUCTORS * 01734 ****************/ 01735 01737 01740 template <class T, class Prop, class Allocator> 01741 Matrix<T, Prop, ColSparse, Allocator>::Matrix(): 01742 Matrix_Sparse<T, Prop, ColSparse, Allocator>() 01743 { 01744 } 01745 01746 01748 01752 template <class T, class Prop, class Allocator> 01753 Matrix<T, Prop, ColSparse, Allocator>::Matrix(int i, int j): 01754 Matrix_Sparse<T, Prop, ColSparse, Allocator>(i, j, 0) 01755 { 01756 } 01757 01758 01760 01766 template <class T, class Prop, class Allocator> 01767 Matrix<T, Prop, ColSparse, Allocator>::Matrix(int i, int j, int nz): 01768 Matrix_Sparse<T, Prop, ColSparse, Allocator>(i, j, nz) 01769 { 01770 } 01771 01772 01774 01785 template <class T, class Prop, class Allocator> 01786 template <class Storage0, class Allocator0, 01787 class Storage1, class Allocator1, 01788 class Storage2, class Allocator2> 01789 Matrix<T, Prop, ColSparse, Allocator>:: 01790 Matrix(int i, int j, 01791 Vector<T, Storage0, Allocator0>& values, 01792 Vector<int, Storage1, Allocator1>& ptr, 01793 Vector<int, Storage2, Allocator2>& ind): 01794 Matrix_Sparse<T, Prop, ColSparse, Allocator>(i, j, values, ptr, ind) 01795 { 01796 } 01797 01798 01799 01801 // MATRIX<ROWSPARSE> // 01803 01804 01805 /**************** 01806 * CONSTRUCTORS * 01807 ****************/ 01808 01810 01813 template <class T, class Prop, class Allocator> 01814 Matrix<T, Prop, RowSparse, Allocator>::Matrix(): 01815 Matrix_Sparse<T, Prop, RowSparse, Allocator>() 01816 { 01817 } 01818 01819 01821 01825 template <class T, class Prop, class Allocator> 01826 Matrix<T, Prop, RowSparse, Allocator>::Matrix(int i, int j): 01827 Matrix_Sparse<T, Prop, RowSparse, Allocator>(i, j, 0) 01828 { 01829 } 01830 01831 01833 01839 template <class T, class Prop, class Allocator> 01840 Matrix<T, Prop, RowSparse, Allocator>::Matrix(int i, int j, int nz): 01841 Matrix_Sparse<T, Prop, RowSparse, Allocator>(i, j, nz) 01842 { 01843 } 01844 01845 01847 01858 template <class T, class Prop, class Allocator> 01859 template <class Storage0, class Allocator0, 01860 class Storage1, class Allocator1, 01861 class Storage2, class Allocator2> 01862 Matrix<T, Prop, RowSparse, Allocator>:: 01863 Matrix(int i, int j, 01864 Vector<T, Storage0, Allocator0>& values, 01865 Vector<int, Storage1, Allocator1>& ptr, 01866 Vector<int, Storage2, Allocator2>& ind): 01867 Matrix_Sparse<T, Prop, RowSparse, Allocator>(i, j, values, ptr, ind) 01868 { 01869 } 01870 01871 01873 // ReadCoordinateMatrix // 01875 01876 01878 01884 template<class Tint, class AllocInt, class T, class Allocator> 01885 void ReadCoordinateMatrix(istream& FileStream, 01886 Vector<Tint, VectFull, AllocInt>& row_numbers, 01887 Vector<Tint, VectFull, AllocInt>& col_numbers, 01888 Vector<T, VectFull, Allocator>& values) 01889 { 01890 #ifdef SELDON_CHECK_IO 01891 // Checks if the stream is ready. 01892 if (!FileStream.good()) 01893 throw IOError("ReadCoordinateMatrix", "Stream is not ready."); 01894 #endif 01895 01896 T entry; int row = 0, col = 0; 01897 int nb_elt = 0; 01898 SetComplexZero(entry); 01899 01900 while (!FileStream.eof()) 01901 { 01902 // new entry is read (1-index) 01903 FileStream >> row >> col >> entry; 01904 01905 if (FileStream.fail()) 01906 break; 01907 else 01908 { 01909 #ifdef SELDON_CHECK_IO 01910 if (row < 1) 01911 throw IOError(string("ReadCoordinateMatrix"), 01912 string("Error : Row number should be greater ") 01913 + "than 0 but is equal to " + to_str(row)); 01914 01915 if (col < 1) 01916 throw IOError(string("ReadCoordinateMatrix"), 01917 string("Error : Column number should be greater") 01918 + " than 0 but is equal to " + to_str(col)); 01919 #endif 01920 01921 nb_elt++; 01922 01923 // inserting new element 01924 if (nb_elt > values.GetM()) 01925 { 01926 values.Resize(2*nb_elt); 01927 row_numbers.Resize(2*nb_elt); 01928 col_numbers.Resize(2*nb_elt); 01929 } 01930 01931 values(nb_elt-1) = entry; 01932 row_numbers(nb_elt-1) = row; 01933 col_numbers(nb_elt-1) = col; 01934 } 01935 } 01936 01937 if (nb_elt > 0) 01938 { 01939 row_numbers.Resize(nb_elt); 01940 col_numbers.Resize(nb_elt); 01941 values.Resize(nb_elt); 01942 } 01943 } 01944 01945 01947 01956 template<class Matrix1, class T> 01957 void ReadCoordinateMatrix(Matrix1& A, istream& FileStream, T& zero, 01958 int index, int nnz) 01959 { 01960 // previous elements are removed 01961 A.Clear(); 01962 01963 Vector<int> row_numbers, col_numbers; 01964 Vector<T> values; 01965 if (nnz >= 0) 01966 { 01967 values.Reallocate(nnz); 01968 row_numbers.Reallocate(nnz); 01969 col_numbers.Reallocate(nnz); 01970 } 01971 01972 ReadCoordinateMatrix(FileStream, row_numbers, col_numbers, values); 01973 01974 if (row_numbers.GetM() > 0) 01975 ConvertMatrix_from_Coordinates(row_numbers, col_numbers, values, 01976 A, index); 01977 01978 } 01979 01980 } // namespace Seldon. 01981 01982 #define SELDON_FILE_MATRIX_SPARSE_CXX 01983 #endif