matrix_sparse/Matrix_Sparse.cxx

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