matrix_sparse/Matrix_SymSparse.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_SYMSPARSE_CXX
00022 
00023 #include "Matrix_SymSparse.hxx"
00024 
00025 namespace Seldon
00026 {
00027 
00028 
00029   /****************
00030    * CONSTRUCTORS *
00031    ****************/
00032 
00033 
00035 
00038   template <class T, class Prop, class Storage, class Allocator>
00039   inline Matrix_SymSparse<T, Prop, Storage, Allocator>::Matrix_SymSparse():
00040     Matrix_Base<T, Allocator>()
00041   {
00042     nz_ = 0;
00043     ptr_ = NULL;
00044     ind_ = NULL;
00045   }
00046 
00047 
00049 
00055   template <class T, class Prop, class Storage, class Allocator>
00056   inline Matrix_SymSparse<T, Prop, Storage, Allocator>
00057   ::Matrix_SymSparse(int i, int j): Matrix_Base<T, Allocator>(i, i)
00058   {
00059     nz_ = 0;
00060     ptr_ = NULL;
00061     ind_ = NULL;
00062   }
00063 
00064 
00066 
00075   template <class T, class Prop, class Storage, class Allocator>
00076   inline Matrix_SymSparse<T, Prop, Storage, Allocator>::
00077   Matrix_SymSparse(int i, int j, int nz):
00078     Matrix_Base<T, Allocator>(i, i)
00079   {
00080     this->nz_ = nz;
00081 
00082 #ifdef SELDON_CHECK_DIMENSIONS
00083     if (static_cast<long int>(2 * nz_ - 2) / static_cast<long int>(i + 1)
00084         >= static_cast<long int>(i))
00085       {
00086         this->m_ = 0;
00087         this->n_ = 0;
00088         nz_ = 0;
00089         ptr_ = NULL;
00090         ind_ = NULL;
00091         this->data_ = NULL;
00092         throw WrongDim("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
00093                        string("There are more values (") + to_str(nz)
00094                        + string(" values) than elements in the upper")
00095                        + " part of the matrix ("
00096                        + to_str(i) + " by " + to_str(i) + ").");
00097       }
00098 #endif
00099 
00100 #ifdef SELDON_CHECK_MEMORY
00101     try
00102       {
00103 #endif
00104 
00105         ptr_ = reinterpret_cast<int*>( calloc(i + 1, sizeof(int)) );
00106 
00107 #ifdef SELDON_CHECK_MEMORY
00108       }
00109     catch (...)
00110       {
00111         this->m_ = 0;
00112         this->n_ = 0;
00113         nz_ = 0;
00114         ptr_ = NULL;
00115         ind_ = NULL;
00116         this->data_ = NULL;
00117       }
00118     if (ptr_ == NULL)
00119       {
00120         this->m_ = 0;
00121         this->n_ = 0;
00122         nz_ = 0;
00123         ind_ = NULL;
00124         this->data_ = NULL;
00125       }
00126     if (ptr_ == NULL && i != 0)
00127       throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
00128                      string("Unable to allocate ")
00129                      + to_str(sizeof(int) * (i+1) ) + " bytes to store "
00130                      + to_str(i+1) + " row or column start indices, for a "
00131                      + to_str(i) + " by " + to_str(i) + " matrix.");
00132 #endif
00133 
00134 #ifdef SELDON_CHECK_MEMORY
00135     try
00136       {
00137 #endif
00138 
00139         ind_ = reinterpret_cast<int*>( calloc(nz_, sizeof(int)) );
00140 
00141 #ifdef SELDON_CHECK_MEMORY
00142       }
00143     catch (...)
00144       {
00145         this->m_ = 0;
00146         this->n_ = 0;
00147         nz_ = 0;
00148         free(ptr_);
00149         ptr_ = NULL;
00150         ind_ = NULL;
00151         this->data_ = NULL;
00152       }
00153     if (ind_ == NULL)
00154       {
00155         this->m_ = 0;
00156         this->n_ = 0;
00157         nz_ = 0;
00158         free(ptr_);
00159         ptr_ = NULL;
00160         this->data_ = NULL;
00161       }
00162     if (ind_ == NULL && i != 0)
00163       throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
00164                      string("Unable to allocate ") + to_str(sizeof(int) * nz)
00165                      + " bytes to store " + to_str(nz)
00166                      + " row or column indices, for a "
00167                      + to_str(i) + " by " + to_str(i) + " matrix.");
00168 #endif
00169 
00170 #ifdef SELDON_CHECK_MEMORY
00171     try
00172       {
00173 #endif
00174 
00175         this->data_ = this->allocator_.allocate(nz_, this);
00176 
00177 #ifdef SELDON_CHECK_MEMORY
00178       }
00179     catch (...)
00180       {
00181         this->m_ = 0;
00182         this->n_ = 0;
00183         free(ptr_);
00184         ptr_ = NULL;
00185         free(ind_);
00186         ind_ = NULL;
00187         this->data_ = NULL;
00188       }
00189     if (this->data_ == NULL)
00190       {
00191         this->m_ = 0;
00192         this->n_ = 0;
00193         free(ptr_);
00194         ptr_ = NULL;
00195         free(ind_);
00196         ind_ = NULL;
00197       }
00198     if (this->data_ == NULL && i != 0)
00199       throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
00200                      string("Unable to allocate ") + to_str(sizeof(int) * nz)
00201                      + " bytes to store " + to_str(nz) + " values, for a "
00202                      + to_str(i) + " by " + to_str(i) + " matrix.");
00203 #endif
00204 
00205   }
00206 
00207 
00209 
00221   template <class T, class Prop, class Storage, class Allocator>
00222   template <class Storage0, class Allocator0,
00223             class Storage1, class Allocator1,
00224             class Storage2, class Allocator2>
00225   inline Matrix_SymSparse<T, Prop, Storage, Allocator>::
00226   Matrix_SymSparse(int i, int j,
00227                    Vector<T, Storage0, Allocator0>& values,
00228                    Vector<int, Storage1, Allocator1>& ptr,
00229                    Vector<int, Storage2, Allocator2>& ind):
00230     Matrix_Base<T, Allocator>(i, j)
00231   {
00232     nz_ = values.GetLength();
00233 
00234 #ifdef SELDON_CHECK_DIMENSIONS
00235     // Checks whether vector sizes are acceptable.
00236 
00237     if (ind.GetLength() != nz_)
00238       {
00239         this->m_ = 0;
00240         this->n_ = 0;
00241         nz_ = 0;
00242         ptr_ = NULL;
00243         ind_ = NULL;
00244         this->data_ = NULL;
00245         throw WrongDim(string("Matrix_SymSparse::Matrix_SymSparse(int, int, ")
00246                        + "const Vector&, const Vector&, const Vector&)",
00247                        string("There are ") + to_str(nz_) + " values but "
00248                        + to_str(ind.GetLength()) + " row or column indices.");
00249       }
00250 
00251     if (ptr.GetLength() - 1 != i)
00252       {
00253         this->m_ = 0;
00254         this->n_ = 0;
00255         nz_ = 0;
00256         ptr_ = NULL;
00257         ind_ = NULL;
00258         this->data_ = NULL;
00259         throw WrongDim(string("Matrix_SymSparse::Matrix_SymSparse(int, int, ")
00260                        + "const Vector&, const Vector&, const Vector&)",
00261                        string("The vector of start indices contains ")
00262                        + to_str(ptr.GetLength()-1) + string(" row or column ")
00263                        + string("start  indices (plus the number of non-zero")
00264                        + " entries) but there are " + to_str(i)
00265                        + " rows or columns ("
00266                        + to_str(i) + " by " + to_str(i) + " matrix).");
00267       }
00268 
00269     if (static_cast<long int>(2 * nz_ - 2) / static_cast<long int>(i + 1)
00270         >= static_cast<long int>(i))
00271       {
00272         this->m_ = 0;
00273         this->n_ = 0;
00274         nz_ = 0;
00275         ptr_ = NULL;
00276         ind_ = NULL;
00277         this->data_ = NULL;
00278         throw WrongDim(string("Matrix_SymSparse::Matrix_SymSparse(int, int, ")
00279                        + "const Vector&, const Vector&, const Vector&)",
00280                        string("There are more values (")
00281                        + to_str(values.GetLength())
00282                        + " values) than elements in the matrix ("
00283                        + to_str(i) + " by " + to_str(i) + ").");
00284       }
00285 #endif
00286 
00287     this->ptr_ = ptr.GetData();
00288     this->ind_ = ind.GetData();
00289     this->data_ = values.GetData();
00290 
00291     ptr.Nullify();
00292     ind.Nullify();
00293     values.Nullify();
00294   }
00295 
00296 
00298   template <class T, class Prop, class Storage, class Allocator>
00299   inline Matrix_SymSparse<T, Prop, Storage, Allocator>::
00300   Matrix_SymSparse(const Matrix_SymSparse<T, Prop, Storage, Allocator>& A)
00301   {
00302     this->m_ = 0;
00303     this->n_ = 0;
00304     this->nz_ = 0;
00305     ptr_ = NULL;
00306     ind_ = NULL;
00307     this->Copy(A);
00308   }
00309 
00310 
00311   /**************
00312    * DESTRUCTOR *
00313    **************/
00314 
00315 
00317   template <class T, class Prop, class Storage, class Allocator>
00318   inline Matrix_SymSparse<T, Prop, Storage, Allocator>::~Matrix_SymSparse()
00319   {
00320     this->m_ = 0;
00321     this->n_ = 0;
00322 
00323 #ifdef SELDON_CHECK_MEMORY
00324     try
00325       {
00326 #endif
00327 
00328         if (ptr_ != NULL)
00329           {
00330             free(ptr_);
00331             ptr_ = NULL;
00332           }
00333 
00334 #ifdef SELDON_CHECK_MEMORY
00335       }
00336     catch (...)
00337       {
00338         ptr_ = NULL;
00339       }
00340 #endif
00341 
00342 #ifdef SELDON_CHECK_MEMORY
00343     try
00344       {
00345 #endif
00346 
00347         if (ind_ != NULL)
00348           {
00349             free(ind_);
00350             ind_ = NULL;
00351           }
00352 
00353 #ifdef SELDON_CHECK_MEMORY
00354       }
00355     catch (...)
00356       {
00357         ind_ = NULL;
00358       }
00359 #endif
00360 
00361 #ifdef SELDON_CHECK_MEMORY
00362     try
00363       {
00364 #endif
00365 
00366         if (this->data_ != NULL)
00367           {
00368             this->allocator_.deallocate(this->data_, nz_);
00369             this->data_ = NULL;
00370           }
00371 
00372 #ifdef SELDON_CHECK_MEMORY
00373       }
00374     catch (...)
00375       {
00376         this->nz_ = 0;
00377         this->data_ = NULL;
00378       }
00379 #endif
00380 
00381     this->nz_ = 0;
00382   }
00383 
00384 
00386 
00389   template <class T, class Prop, class Storage, class Allocator>
00390   inline void Matrix_SymSparse<T, Prop, Storage, Allocator>::Clear()
00391   {
00392     this->~Matrix_SymSparse();
00393   }
00394 
00395 
00396   /*********************
00397    * MEMORY MANAGEMENT *
00398    *********************/
00399 
00400 
00402 
00413   template <class T, class Prop, class Storage, class Allocator>
00414   template <class Storage0, class Allocator0,
00415             class Storage1, class Allocator1,
00416             class Storage2, class Allocator2>
00417   void Matrix_SymSparse<T, Prop, Storage, Allocator>::
00418   SetData(int i, int j,
00419           Vector<T, Storage0, Allocator0>& values,
00420           Vector<int, Storage1, Allocator1>& ptr,
00421           Vector<int, Storage2, Allocator2>& ind)
00422   {
00423     this->Clear();
00424     this->m_ = i;
00425     this->n_ = i;
00426     this->nz_ = values.GetLength();
00427 
00428 #ifdef SELDON_CHECK_DIMENSIONS
00429     // Checks whether vector sizes are acceptable.
00430 
00431     if (ind.GetLength() != nz_)
00432       {
00433         this->m_ = 0;
00434         this->n_ = 0;
00435         nz_ = 0;
00436         ptr_ = NULL;
00437         ind_ = NULL;
00438         this->data_ = NULL;
00439         throw WrongDim(string("Matrix_SymSparse::Reallocate(int, int, ")
00440                        + "const Vector&, const Vector&, const Vector&)",
00441                        string("There are ") + to_str(nz_) + " values but "
00442                        + to_str(ind.GetLength()) + " row or column indices.");
00443       }
00444 
00445     if (ptr.GetLength()-1 != i)
00446       {
00447         this->m_ = 0;
00448         this->n_ = 0;
00449         nz_ = 0;
00450         ptr_ = NULL;
00451         ind_ = NULL;
00452         this->data_ = NULL;
00453         throw WrongDim(string("Matrix_SymSparse::Reallocate(int, int, ")
00454                        + "const Vector&, const Vector&, const Vector&)",
00455                        string("The vector of start indices contains ")
00456                        + to_str(ptr.GetLength()-1) + string(" row or column")
00457                        + string(" start indices (plus the number of")
00458                        + string(" non-zero entries) but there are ")
00459                        + to_str(i) + " rows or columns ("
00460                        + to_str(i) + " by " + to_str(i) + " matrix).");
00461       }
00462 
00463     if (static_cast<long int>(2 * nz_ - 2) / static_cast<long int>(i + 1)
00464         >= static_cast<long int>(i))
00465       {
00466         this->m_ = 0;
00467         this->n_ = 0;
00468         nz_ = 0;
00469         ptr_ = NULL;
00470         ind_ = NULL;
00471         this->data_ = NULL;
00472         throw WrongDim(string("Matrix_SymSparse::Reallocate(int, int, ")
00473                        + "const Vector&, const Vector&, const Vector&)",
00474                        string("There are more values (")
00475                        + to_str(values.GetLength())
00476                        + " values) than elements in the matrix ("
00477                        + to_str(i) + " by " + to_str(i) + ").");
00478       }
00479 #endif
00480 
00481     this->ptr_ = ptr.GetData();
00482     this->ind_ = ind.GetData();
00483     this->data_ = values.GetData();
00484 
00485     ptr.Nullify();
00486     ind.Nullify();
00487     values.Nullify();
00488   }
00489 
00490 
00492 
00506   template <class T, class Prop, class Storage, class Allocator>
00507   inline void Matrix_SymSparse<T, Prop, Storage, Allocator>
00508   ::SetData(int i, int j, int nz,
00509             typename Matrix_SymSparse<T, Prop, Storage, Allocator>
00510             ::pointer values,
00511             int* ptr,
00512             int* ind)
00513   {
00514     this->Clear();
00515 
00516     this->m_ = i;
00517     this->n_ = i;
00518 
00519     this->nz_ = nz;
00520 
00521     this->data_ = values;
00522     ind_ = ind;
00523     ptr_ = ptr;
00524   }
00525 
00526 
00528 
00532   template <class T, class Prop, class Storage, class Allocator>
00533   inline void Matrix_SymSparse<T, Prop, Storage, Allocator>::Nullify()
00534   {
00535     this->data_ = NULL;
00536     this->m_ = 0;
00537     this->n_ = 0;
00538     nz_ = 0;
00539     ptr_ = NULL;
00540     ind_ = NULL;
00541   }
00542 
00543 
00545   template <class T, class Prop, class Storage, class Allocator>
00546   inline void Matrix_SymSparse<T, Prop, Storage, Allocator>::
00547   Copy(const Matrix_SymSparse<T, Prop, Storage, Allocator>& A)
00548   {
00549     this->Clear();
00550     int nz = A.GetNonZeros();
00551     int i = A.GetM();
00552     int j = A.GetN();
00553     this->nz_ = nz;
00554     this->m_ = i;
00555     this->n_ = j;
00556     if ((i == 0)||(j == 0))
00557       {
00558         this->m_ = 0;
00559         this->n_ = 0;
00560         this->nz_ = 0;
00561         return;
00562       }
00563 
00564 #ifdef SELDON_CHECK_DIMENSIONS
00565     if (static_cast<long int>(2 * nz_ - 2) / static_cast<long int>(i + 1)
00566         >= static_cast<long int>(i))
00567       {
00568         this->m_ = 0;
00569         this->n_ = 0;
00570         nz_ = 0;
00571         ptr_ = NULL;
00572         ind_ = NULL;
00573         this->data_ = NULL;
00574         throw WrongDim("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
00575                        string("There are more values (") + to_str(nz)
00576                        + string(" values) than elements in the upper")
00577                        + " part of the matrix ("
00578                        + to_str(i) + " by " + to_str(i) + ").");
00579       }
00580 #endif
00581 
00582 #ifdef SELDON_CHECK_MEMORY
00583     try
00584       {
00585 #endif
00586 
00587         ptr_ = reinterpret_cast<int*>( calloc(i + 1, sizeof(int)) );
00588         memcpy(this->ptr_, A.ptr_, (i + 1) * sizeof(int));
00589 
00590 #ifdef SELDON_CHECK_MEMORY
00591       }
00592     catch (...)
00593       {
00594         this->m_ = 0;
00595         this->n_ = 0;
00596         nz_ = 0;
00597         ptr_ = NULL;
00598         ind_ = NULL;
00599         this->data_ = NULL;
00600       }
00601     if (ptr_ == NULL)
00602       {
00603         this->m_ = 0;
00604         this->n_ = 0;
00605         nz_ = 0;
00606         ind_ = NULL;
00607         this->data_ = NULL;
00608       }
00609     if (ptr_ == NULL && i != 0)
00610       throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
00611                      string("Unable to allocate ")
00612                      + to_str(sizeof(int) * (i+1) ) + " bytes to store "
00613                      + to_str(i+1) + " row or column start indices, for a "
00614                      + to_str(i) + " by " + to_str(i) + " matrix.");
00615 #endif
00616 
00617 #ifdef SELDON_CHECK_MEMORY
00618     try
00619       {
00620 #endif
00621 
00622         ind_ = reinterpret_cast<int*>( calloc(nz_, sizeof(int)) );
00623         memcpy(this->ind_, A.ind_, nz_ * sizeof(int));
00624 
00625 #ifdef SELDON_CHECK_MEMORY
00626       }
00627     catch (...)
00628       {
00629         this->m_ = 0;
00630         this->n_ = 0;
00631         nz_ = 0;
00632         free(ptr_);
00633         ptr_ = NULL;
00634         ind_ = NULL;
00635         this->data_ = NULL;
00636       }
00637     if (ind_ == NULL)
00638       {
00639         this->m_ = 0;
00640         this->n_ = 0;
00641         nz_ = 0;
00642         free(ptr_);
00643         ptr_ = NULL;
00644         this->data_ = NULL;
00645       }
00646     if (ind_ == NULL && i != 0)
00647       throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
00648                      string("Unable to allocate ") + to_str(sizeof(int) * nz)
00649                      + " bytes to store " + to_str(nz)
00650                      + " row or column indices, for a "
00651                      + to_str(i) + " by " + to_str(i) + " matrix.");
00652 #endif
00653 
00654 #ifdef SELDON_CHECK_MEMORY
00655     try
00656       {
00657 #endif
00658 
00659         this->data_ = this->allocator_.allocate(nz_, this);
00660         this->allocator_.memorycpy(this->data_, A.data_, nz_);
00661 
00662 #ifdef SELDON_CHECK_MEMORY
00663       }
00664     catch (...)
00665       {
00666         this->m_ = 0;
00667         this->n_ = 0;
00668         free(ptr_);
00669         ptr_ = NULL;
00670         free(ind_);
00671         ind_ = NULL;
00672         this->data_ = NULL;
00673       }
00674     if (this->data_ == NULL)
00675       {
00676         this->m_ = 0;
00677         this->n_ = 0;
00678         free(ptr_);
00679         ptr_ = NULL;
00680         free(ind_);
00681         ind_ = NULL;
00682       }
00683     if (this->data_ == NULL && i != 0)
00684       throw NoMemory("Matrix_SymSparse::Matrix_SymSparse(int, int, int)",
00685                      string("Unable to allocate ") + to_str(sizeof(int) * nz)
00686                      + " bytes to store " + to_str(nz) + " values, for a "
00687                      + to_str(i) + " by " + to_str(i) + " matrix.");
00688 #endif
00689 
00690   }
00691 
00692 
00693   /*******************
00694    * BASIC FUNCTIONS *
00695    *******************/
00696 
00697 
00699 
00703   template <class T, class Prop, class Storage, class Allocator>
00704   int Matrix_SymSparse<T, Prop, Storage, Allocator>::GetNonZeros() const
00705   {
00706     return nz_;
00707   }
00708 
00709 
00711 
00715   template <class T, class Prop, class Storage, class Allocator>
00716   int Matrix_SymSparse<T, Prop, Storage, Allocator>::GetDataSize() const
00717   {
00718     return nz_;
00719   }
00720 
00721 
00723 
00727   template <class T, class Prop, class Storage, class Allocator>
00728   int* Matrix_SymSparse<T, Prop, Storage, Allocator>::GetPtr() const
00729   {
00730     return ptr_;
00731   }
00732 
00733 
00735 
00742   template <class T, class Prop, class Storage, class Allocator>
00743   int* Matrix_SymSparse<T, Prop, Storage, Allocator>::GetInd() const
00744   {
00745     return ind_;
00746   }
00747 
00748 
00750 
00753   template <class T, class Prop, class Storage, class Allocator>
00754   int Matrix_SymSparse<T, Prop, Storage, Allocator>::GetPtrSize() const
00755   {
00756     return (this->m_ + 1);
00757   }
00758 
00759 
00761 
00770   template <class T, class Prop, class Storage, class Allocator>
00771   int Matrix_SymSparse<T, Prop, Storage, Allocator>::GetIndSize() const
00772   {
00773     return nz_;
00774   }
00775 
00776 
00777   /**********************************
00778    * ELEMENT ACCESS AND AFFECTATION *
00779    **********************************/
00780 
00781 
00783 
00789   template <class T, class Prop, class Storage, class Allocator>
00790   inline typename Matrix_SymSparse<T, Prop, Storage, Allocator>::value_type
00791   Matrix_SymSparse<T, Prop, Storage, Allocator>::operator() (int i,
00792                                                              int j) const
00793   {
00794 
00795 #ifdef SELDON_CHECK_BOUNDS
00796     if (i < 0 || i >= this->m_)
00797       throw WrongRow("Matrix_SymSparse::operator()",
00798                      string("Index should be in [0, ") + to_str(this->m_-1)
00799                      + "], but is equal to " + to_str(i) + ".");
00800     if (j < 0 || j >= this->n_)
00801       throw WrongCol("Matrix_SymSparse::operator()",
00802                      string("Index should be in [0, ") + to_str(this->n_-1)
00803                      + "], but is equal to " + to_str(j) + ".");
00804 #endif
00805 
00806     int k, l;
00807     int a, b;
00808 
00809     // Only the upper part is stored.
00810     if (i>j)
00811       {
00812         l = i;
00813         i = j;
00814         j = l;
00815       }
00816 
00817     a = ptr_[Storage::GetFirst(i, j)];
00818     b = ptr_[Storage::GetFirst(i, j) + 1];
00819 
00820     if (a == b)
00821       return T(0);
00822 
00823     l = Storage::GetSecond(i, j);
00824 
00825     for (k = a; (k<b-1) && (ind_[k]<l); k++);
00826 
00827     if (ind_[k] == l)
00828       return this->data_[k];
00829     else
00830       return T(0);
00831   }
00832 
00833 
00835 
00843   template <class T, class Prop, class Storage, class Allocator>
00844   inline typename Matrix_SymSparse<T, Prop, Storage, Allocator>::value_type&
00845   Matrix_SymSparse<T, Prop, Storage, Allocator>::Val(int i, int j)
00846   {
00847 
00848 #ifdef SELDON_CHECK_BOUNDS
00849     if (i < 0 || i >= this->m_)
00850       throw WrongRow("Matrix_SymSparse::Val(int, int)",
00851                      string("Index should be in [0, ") + to_str(this->m_-1)
00852                      + "], but is equal to " + to_str(i) + ".");
00853     if (j < 0 || j >= this->n_)
00854       throw WrongCol("Matrix_SymSparse::Val(int, int)",
00855                      string("Index should be in [0, ") + to_str(this->n_-1)
00856                      + "], but is equal to " + to_str(j) + ".");
00857 #endif
00858 
00859     int k, l;
00860     int a, b;
00861 
00862     // Only the upper part is stored.
00863     if (i>j)
00864       {
00865         l = i;
00866         i = j;
00867         j = l;
00868       }
00869 
00870     a = ptr_[Storage::GetFirst(i, j)];
00871     b = ptr_[Storage::GetFirst(i, j) + 1];
00872 
00873     if (a == b)
00874       throw WrongArgument("Matrix_SymSparse::Val(int, int)",
00875                           "No reference to element (" + to_str(i) + ", "
00876                           + to_str(j)
00877                           + ") can be returned: it is a zero entry.");
00878 
00879     l = Storage::GetSecond(i, j);
00880 
00881     for (k = a; (k<b-1) && (ind_[k]<l); k++);
00882 
00883     if (ind_[k] == l)
00884       return this->data_[k];
00885     else
00886       throw WrongArgument("Matrix_SymSparse::Val(int, int)",
00887                           "No reference to element (" + to_str(i) + ", "
00888                           + to_str(j)
00889                           + ") can be returned: it is a zero entry.");
00890   }
00891 
00892 
00894 
00902   template <class T, class Prop, class Storage, class Allocator>
00903   inline
00904   const typename Matrix_SymSparse<T, Prop, Storage, Allocator>::value_type&
00905   Matrix_SymSparse<T, Prop, Storage, Allocator>::Val(int i, int j) const
00906   {
00907 
00908 #ifdef SELDON_CHECK_BOUNDS
00909     if (i < 0 || i >= this->m_)
00910       throw WrongRow("Matrix_SymSparse::Val(int, int)",
00911                      string("Index should be in [0, ") + to_str(this->m_-1)
00912                      + "], but is equal to " + to_str(i) + ".");
00913     if (j < 0 || j >= this->n_)
00914       throw WrongCol("Matrix_SymSparse::Val(int, int)",
00915                      string("Index should be in [0, ") + to_str(this->n_-1)
00916                      + "], but is equal to " + to_str(j) + ".");
00917 #endif
00918 
00919     int k, l;
00920     int a, b;
00921 
00922     // Only the upper part is stored.
00923     if (i>j)
00924       {
00925         l = i;
00926         i = j;
00927         j = l;
00928       }
00929 
00930     a = ptr_[Storage::GetFirst(i, j)];
00931     b = ptr_[Storage::GetFirst(i, j) + 1];
00932 
00933     if (a == b)
00934       throw WrongArgument("Matrix_SymSparse::Val(int, int)",
00935                           "No reference to element (" + to_str(i) + ", "
00936                           + to_str(j)
00937                           + ") can be returned: it is a zero entry.");
00938 
00939     l = Storage::GetSecond(i, j);
00940 
00941     for (k = a; (k<b-1) && (ind_[k]<l); k++);
00942 
00943     if (ind_[k] == l)
00944       return this->data_[k];
00945     else
00946       throw WrongArgument("Matrix_SymSparse::Val(int, int)",
00947                           "No reference to element (" + to_str(i) + ", "
00948                           + to_str(j)
00949                           + ") can be returned: it is a zero entry.");
00950   }
00951 
00952 
00954 
00959   template <class T, class Prop, class Storage, class Allocator>
00960   inline Matrix_SymSparse<T, Prop, Storage, Allocator>&
00961   Matrix_SymSparse<T, Prop, Storage, Allocator>
00962   ::operator= (const Matrix_SymSparse<T, Prop, Storage, Allocator>& A)
00963   {
00964     this->Copy(A);
00965 
00966     return *this;
00967   }
00968 
00969 
00970   /************************
00971    * CONVENIENT FUNCTIONS *
00972    ************************/
00973 
00974 
00976 
00981   template <class T, class Prop, class Storage, class Allocator>
00982   void Matrix_SymSparse<T, Prop, Storage, Allocator>::Print() const
00983   {
00984     for (int i = 0; i < this->m_; i++)
00985       {
00986         for (int j = 0; j < this->n_; j++)
00987           cout << (*this)(i, j) << "\t";
00988         cout << endl;
00989       }
00990   }
00991 
00992 
00994 
00999   template <class T, class Prop, class Storage, class Allocator>
01000   void Matrix_SymSparse<T, Prop, Storage, Allocator>
01001   ::WriteText(string FileName) const
01002   {
01003     ofstream FileStream; FileStream.precision(14);
01004     FileStream.open(FileName.c_str());
01005 
01006 #ifdef SELDON_CHECK_IO
01007     // Checks if the file was opened.
01008     if (!FileStream.is_open())
01009       throw IOError("Matrix_SymSparse::WriteText(string FileName)",
01010                     string("Unable to open file \"") + FileName + "\".");
01011 #endif
01012 
01013     this->WriteText(FileStream);
01014 
01015     FileStream.close();
01016   }
01017 
01018 
01020 
01025   template <class T, class Prop, class Storage, class Allocator>
01026   void Matrix_SymSparse<T, Prop, Storage, Allocator>
01027   ::WriteText(ostream& FileStream) const
01028   {
01029 
01030 #ifdef SELDON_CHECK_IO
01031     // Checks if the stream is ready.
01032     if (!FileStream.good())
01033       throw IOError("Matrix_SymSparse::WriteText(ofstream& FileStream)",
01034                     "Stream is not ready.");
01035 #endif
01036 
01037     // Conversion to coordinate format (1-index convention).
01038     IVect IndRow, IndCol;
01039     Vector<T> Value;
01040     const Matrix<T, Prop, Storage, Allocator>& leaf_class =
01041       static_cast<const Matrix<T, Prop, Storage, Allocator>& >(*this);
01042 
01043     ConvertMatrix_to_Coordinates(leaf_class, IndRow, IndCol,
01044                                  Value, 1, true);
01045 
01046     for (int i = 0; i < IndRow.GetM(); i++)
01047       FileStream << IndRow(i) << " " << IndCol(i) << " " << Value(i) << '\n';
01048   }
01049 
01050 
01052   // MATRIX<COLSYMSPARSE> //
01054 
01055 
01056   /****************
01057    * CONSTRUCTORS *
01058    ****************/
01059 
01061 
01064   template <class T, class Prop, class Allocator>
01065   Matrix<T, Prop, ColSymSparse, Allocator>::Matrix()  throw():
01066     Matrix_SymSparse<T, Prop, ColSymSparse, Allocator>()
01067   {
01068   }
01069 
01070 
01072 
01076   template <class T, class Prop, class Allocator>
01077   Matrix<T, Prop, ColSymSparse, Allocator>::Matrix(int i, int j):
01078     Matrix_SymSparse<T, Prop, ColSymSparse, Allocator>(i, j, 0)
01079   {
01080   }
01081 
01082 
01084 
01091   template <class T, class Prop, class Allocator>
01092   Matrix<T, Prop, ColSymSparse, Allocator>::Matrix(int i, int j, int nz):
01093     Matrix_SymSparse<T, Prop, ColSymSparse, Allocator>(i, j, nz)
01094   {
01095   }
01096 
01097 
01099 
01111   template <class T, class Prop, class Allocator>
01112   template <class Storage0, class Allocator0,
01113             class Storage1, class Allocator1,
01114             class Storage2, class Allocator2>
01115   Matrix<T, Prop, ColSymSparse, Allocator>::
01116   Matrix(int i, int j,
01117          Vector<T, Storage0, Allocator0>& values,
01118          Vector<int, Storage1, Allocator1>& ptr,
01119          Vector<int, Storage2, Allocator2>& ind):
01120     Matrix_SymSparse<T, Prop, ColSymSparse, Allocator>(i, j, values, ptr, ind)
01121   {
01122   }
01123 
01124 
01125 
01127   // MATRIX<ROWSYMSPARSE> //
01129 
01130 
01131   /****************
01132    * CONSTRUCTORS *
01133    ****************/
01134 
01135 
01137 
01140   template <class T, class Prop, class Allocator>
01141   Matrix<T, Prop, RowSymSparse, Allocator>::Matrix()  throw():
01142     Matrix_SymSparse<T, Prop, RowSymSparse, Allocator>()
01143   {
01144   }
01145 
01146 
01148 
01152   template <class T, class Prop, class Allocator>
01153   Matrix<T, Prop, RowSymSparse, Allocator>::Matrix(int i, int j):
01154     Matrix_SymSparse<T, Prop, RowSymSparse, Allocator>(i, j, 0)
01155   {
01156   }
01157 
01158 
01160 
01167   template <class T, class Prop, class Allocator>
01168   Matrix<T, Prop, RowSymSparse, Allocator>::Matrix(int i, int j, int nz):
01169     Matrix_SymSparse<T, Prop, RowSymSparse, Allocator>(i, j, nz)
01170   {
01171   }
01172 
01173 
01175 
01187   template <class T, class Prop, class Allocator>
01188   template <class Storage0, class Allocator0,
01189             class Storage1, class Allocator1,
01190             class Storage2, class Allocator2>
01191   Matrix<T, Prop, RowSymSparse, Allocator>::
01192   Matrix(int i, int j,
01193          Vector<T, Storage0, Allocator0>& values,
01194          Vector<int, Storage1, Allocator1>& ptr,
01195          Vector<int, Storage2, Allocator2>& ind):
01196     Matrix_SymSparse<T, Prop, RowSymSparse, Allocator>(i, j, values, ptr, ind)
01197   {
01198   }
01199 
01200 
01201 } // namespace Seldon.
01202 
01203 #define SELDON_FILE_MATRIX_SYMSPARSE_CXX
01204 #endif