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