matrix/Matrix_Symmetric.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_SYMMETRIC_CXX
00022 
00023 #include "Matrix_Symmetric.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_Symmetric<T, Prop, Storage, Allocator>::Matrix_Symmetric():
00040     Matrix_Base<T, Allocator>()
00041   {
00042     me_ = NULL;
00043   }
00044 
00045 
00047 
00052   template <class T, class Prop, class Storage, class Allocator>
00053   inline Matrix_Symmetric<T, Prop, Storage, Allocator>
00054   ::Matrix_Symmetric(int i, int j): Matrix_Base<T, Allocator>(i, i)
00055   {
00056 
00057 #ifdef SELDON_CHECK_MEMORY
00058     try
00059       {
00060 #endif
00061 
00062         me_ = reinterpret_cast<pointer*>( calloc(i, sizeof(pointer)) );
00063 
00064 #ifdef SELDON_CHECK_MEMORY
00065       }
00066     catch (...)
00067       {
00068         this->m_ = 0;
00069         this->n_ = 0;
00070         me_ = NULL;
00071         this->data_ = NULL;
00072       }
00073     if (me_ == NULL)
00074       {
00075         this->m_ = 0;
00076         this->n_ = 0;
00077         this->data_ = NULL;
00078       }
00079     if (me_ == NULL && i != 0)
00080       throw NoMemory("Matrix_Symmetric::Matrix_Symmetric(int, int)",
00081                      string("Unable to allocate memory for a matrix of size ")
00082                      + to_str(static_cast<long int>(i)
00083                               * static_cast<long int>(i)
00084                               * static_cast<long int>(sizeof(T)))
00085                      + " bytes (" + to_str(i) + " x " + to_str(i)
00086                      + " elements).");
00087 #endif
00088 
00089 #ifdef SELDON_CHECK_MEMORY
00090     try
00091       {
00092 #endif
00093 
00094         this->data_ = this->allocator_.allocate(i * i, this);
00095 
00096 #ifdef SELDON_CHECK_MEMORY
00097       }
00098     catch (...)
00099       {
00100         this->m_ = 0;
00101         this->n_ = 0;
00102         free(me_);
00103         me_ = NULL;
00104         this->data_ = NULL;
00105       }
00106     if (this->data_ == NULL)
00107       {
00108         this->m_ = 0;
00109         this->n_ = 0;
00110         free(me_);
00111         me_ = NULL;
00112       }
00113     if (this->data_ == NULL && i != 0)
00114       throw NoMemory("Matrix_Symmetric::Matrix_Symmetric(int, int)",
00115                      string("Unable to allocate memory for a matrix of size ")
00116                      + to_str(static_cast<long int>(i)
00117                               * static_cast<long int>(i)
00118                               * static_cast<long int>(sizeof(T)))
00119                      + " bytes (" + to_str(i) + " x " + to_str(i)
00120                      + " elements).");
00121 #endif
00122 
00123     pointer ptr = this->data_;
00124     int lgth = i;
00125     for (int k = 0; k < i; k++, ptr += lgth)
00126       me_[k] = ptr;
00127   }
00128 
00129 
00131   template <class T, class Prop, class Storage, class Allocator>
00132   inline Matrix_Symmetric<T, Prop, Storage, Allocator>
00133   ::Matrix_Symmetric(const Matrix_Symmetric<T, Prop, Storage, Allocator>& A)
00134     : Matrix_Base<T, Allocator>()
00135   {
00136     this->m_ = 0;
00137     this->n_ = 0;
00138     this->data_ = NULL;
00139     this->me_ = NULL;
00140 
00141     this->Copy(A);
00142   }
00143 
00144 
00145   /**************
00146    * DESTRUCTOR *
00147    **************/
00148 
00149 
00151   template <class T, class Prop, class Storage, class Allocator>
00152   inline Matrix_Symmetric<T, Prop, Storage, Allocator>::~Matrix_Symmetric()
00153   {
00154 
00155 #ifdef SELDON_CHECK_MEMORY
00156     try
00157       {
00158 #endif
00159 
00160         if (this->data_ != NULL)
00161           {
00162             this->allocator_.deallocate(this->data_, this->m_ * this->n_);
00163             this->data_ = NULL;
00164           }
00165 
00166 #ifdef SELDON_CHECK_MEMORY
00167       }
00168     catch (...)
00169       {
00170         this->data_ = NULL;
00171       }
00172 #endif
00173 
00174 #ifdef SELDON_CHECK_MEMORY
00175     try
00176       {
00177 #endif
00178 
00179         if (me_ != NULL)
00180           {
00181             free(me_);
00182             me_ = NULL;
00183           }
00184 
00185 #ifdef SELDON_CHECK_MEMORY
00186       }
00187     catch (...)
00188       {
00189         this->m_ = 0;
00190         this->n_ = 0;
00191         me_ = NULL;
00192       }
00193 #endif
00194 
00195   }
00196 
00197 
00199 
00203   template <class T, class Prop, class Storage, class Allocator>
00204   inline void Matrix_Symmetric<T, Prop, Storage, Allocator>::Clear()
00205   {
00206     this->~Matrix_Symmetric();
00207     this->m_ = 0;
00208     this->n_ = 0;
00209   }
00210 
00211 
00212   /*******************
00213    * BASIC FUNCTIONS *
00214    *******************/
00215 
00216 
00218 
00224   template <class T, class Prop, class Storage, class Allocator>
00225   int Matrix_Symmetric<T, Prop, Storage, Allocator>::GetDataSize() const
00226   {
00227     return this->m_ * this->n_;
00228   }
00229 
00230 
00231   /*********************
00232    * MEMORY MANAGEMENT *
00233    *********************/
00234 
00235 
00237 
00243   template <class T, class Prop, class Storage, class Allocator>
00244   inline void Matrix_Symmetric<T, Prop, Storage, Allocator>
00245   ::Reallocate(int i, int j)
00246   {
00247 
00248     if (i != this->m_)
00249       {
00250         this->m_ = i;
00251         this->n_ = i;
00252 
00253 #ifdef SELDON_CHECK_MEMORY
00254         try
00255           {
00256 #endif
00257 
00258             me_ = reinterpret_cast<pointer*>( realloc(me_,
00259                                                       i * sizeof(pointer)) );
00260 
00261 #ifdef SELDON_CHECK_MEMORY
00262           }
00263         catch (...)
00264           {
00265             this->m_ = 0;
00266             this->n_ = 0;
00267             me_ = NULL;
00268             this->data_ = NULL;
00269           }
00270         if (me_ == NULL)
00271           {
00272             this->m_ = 0;
00273             this->n_ = 0;
00274             this->data_ = NULL;
00275           }
00276         if (me_ == NULL && i != 0)
00277           throw NoMemory("Matrix_Symmetric::Reallocate(int, int)",
00278                          string("Unable to reallocate memory")
00279                          + " for a matrix of size "
00280                          + to_str(static_cast<long int>(i)
00281                                   * static_cast<long int>(i)
00282                                   * static_cast<long int>(sizeof(T)))
00283                          + " bytes (" + to_str(i) + " x " + to_str(i)
00284                          + " elements).");
00285 #endif
00286 
00287 #ifdef SELDON_CHECK_MEMORY
00288         try
00289           {
00290 #endif
00291 
00292             this->data_ =
00293               reinterpret_cast<pointer>(this->allocator_.reallocate(this->data_,
00294                                                                     i * i,
00295                                                                     this) );
00296 
00297 #ifdef SELDON_CHECK_MEMORY
00298           }
00299         catch (...)
00300           {
00301             this->m_ = 0;
00302             this->n_ = 0;
00303             free(me_);
00304             me_ = NULL;
00305             this->data_ = NULL;
00306           }
00307         if (this->data_ == NULL)
00308           {
00309             this->m_ = 0;
00310             this->n_ = 0;
00311             free(me_);
00312             me_ = NULL;
00313           }
00314         if (this->data_ == NULL && i != 0)
00315           throw NoMemory("Matrix_Symmetric::Reallocate(int, int)",
00316                          string("Unable to reallocate memory")
00317                          + " for a matrix of size "
00318                          + to_str(static_cast<long int>(i)
00319                                   * static_cast<long int>(i)
00320                                   * static_cast<long int>(sizeof(T)))
00321                          + " bytes (" + to_str(i) + " x " + to_str(i)
00322                          + " elements).");
00323 #endif
00324 
00325         pointer ptr = this->data_;
00326         int lgth = Storage::GetSecond(i, i);
00327         for (int k = 0; k < Storage::GetFirst(i, i); k++, ptr += lgth)
00328           me_[k] = ptr;
00329       }
00330   }
00331 
00332 
00335 
00349   template <class T, class Prop, class Storage, class Allocator>
00350   inline void Matrix_Symmetric<T, Prop, Storage, Allocator>
00351   ::SetData(int i, int j,
00352             typename Matrix_Symmetric<T, Prop, Storage, Allocator>
00353             ::pointer data)
00354   {
00355 
00356     this->Clear();
00357 
00358     this->m_ = i;
00359     this->n_ = i;
00360 
00361 #ifdef SELDON_CHECK_MEMORY
00362     try
00363       {
00364 #endif
00365 
00366         me_ = reinterpret_cast<pointer*>( calloc(i, sizeof(pointer)) );
00367 
00368 #ifdef SELDON_CHECK_MEMORY
00369       }
00370     catch (...)
00371       {
00372         this->m_ = 0;
00373         this->n_ = 0;
00374         me_ = NULL;
00375         this->data_ = NULL;
00376         return;
00377       }
00378     if (me_ == NULL)
00379       {
00380         this->m_ = 0;
00381         this->n_ = 0;
00382         this->data_ = NULL;
00383         return;
00384       }
00385 #endif
00386 
00387     this->data_ = data;
00388 
00389     pointer ptr = this->data_;
00390     int lgth = i;
00391     for (int k = 0; k < i; k++, ptr += lgth)
00392       me_[k] = ptr;
00393   }
00394 
00395 
00397 
00402   template <class T, class Prop, class Storage, class Allocator>
00403   inline void Matrix_Symmetric<T, Prop, Storage, Allocator>::Nullify()
00404   {
00405     this->m_ = 0;
00406     this->n_ = 0;
00407 
00408 #ifdef SELDON_CHECK_MEMORY
00409     try
00410       {
00411 #endif
00412 
00413         if (me_ != NULL)
00414           {
00415             free(me_);
00416             me_ = NULL;
00417           }
00418 
00419 #ifdef SELDON_CHECK_MEMORY
00420       }
00421     catch (...)
00422       {
00423         this->m_ = 0;
00424         this->n_ = 0;
00425         me_ = NULL;
00426       }
00427 #endif
00428 
00429     this->data_ = NULL;
00430   }
00431 
00432 
00434 
00441   template <class T, class Prop, class Storage, class Allocator>
00442   inline void Matrix_Symmetric<T, Prop, Storage, Allocator>
00443   ::Resize(int i, int j)
00444   {
00445 
00446     // Storing the old values of the matrix.
00447     int iold = Storage::GetFirst(this->m_, this->n_);
00448     int jold = Storage::GetSecond(this->m_, this->n_);
00449     Vector<value_type, VectFull, Allocator> xold(this->GetDataSize());
00450     for (int k = 0; k < this->GetDataSize(); k++)
00451       xold(k) = this->data_[k];
00452 
00453     // Reallocation.
00454     int inew = Storage::GetFirst(i, j);
00455     int jnew = Storage::GetSecond(i, j);
00456     this->Reallocate(i, j);
00457 
00458     // Filling the matrix with its old values.
00459     int imin = min(iold, inew), jmin = min(jold, jnew);
00460     for (int k = 0; k < imin; k++)
00461       for (int l = 0; l < jmin; l++)
00462         this->data_[k*jnew+l] = xold(l+jold*k);
00463   }
00464 
00465 
00466   /**********************************
00467    * ELEMENT ACCESS AND AFFECTATION *
00468    **********************************/
00469 
00470 
00472 
00478   template <class T, class Prop, class Storage, class Allocator>
00479   inline typename Matrix_Symmetric<T, Prop, Storage, Allocator>::value_type
00480   Matrix_Symmetric<T, Prop, Storage, Allocator>::operator() (int i, int j)
00481   {
00482 
00483 #ifdef SELDON_CHECK_BOUNDS
00484     if (i < 0 || i >= this->m_)
00485       throw WrongRow("Matrix_Symmetric::operator()",
00486                      string("Index should be in [0, ") + to_str(this->m_-1)
00487                      + "], but is equal to " + to_str(i) + ".");
00488     if (j < 0 || j >= this->n_)
00489       throw WrongCol("Matrix_Symmetric::operator()",
00490                      string("Index should be in [0, ") + to_str(this->n_-1)
00491                      + "], but is equal to " + to_str(j) + ".");
00492 #endif
00493 
00494     if (i > j)
00495       return me_[Storage::GetSecond(i, j)][Storage::GetFirst(i, j)];
00496     else
00497       return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00498   }
00499 
00500 
00502 
00508   template <class T, class Prop, class Storage, class Allocator>
00509   inline typename Matrix_Symmetric<T, Prop, Storage, Allocator>::value_type
00510   Matrix_Symmetric<T, Prop, Storage, Allocator>
00511   ::operator() (int i, int j) const
00512   {
00513 
00514 #ifdef SELDON_CHECK_BOUNDS
00515     if (i < 0 || i >= this->m_)
00516       throw WrongRow("Matrix_Symmetric::operator() const",
00517                      string("Index should be in [0, ") + to_str(this->m_-1)
00518                      + "], but is equal to " + to_str(i) + ".");
00519     if (j < 0 || j >= this->n_)
00520       throw WrongCol("Matrix_Symmetric::operator() const",
00521                      string("Index should be in [0, ") + to_str(this->n_-1)
00522                      + "], but is equal to " + to_str(j) + ".");
00523 #endif
00524 
00525     if (i > j)
00526       return me_[Storage::GetSecond(i, j)][Storage::GetFirst(i, j)];
00527     else
00528       return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00529   }
00530 
00531 
00533 
00539   template <class T, class Prop, class Storage, class Allocator>
00540   inline typename Matrix_Symmetric<T, Prop, Storage, Allocator>
00541   ::const_reference
00542   Matrix_Symmetric<T, Prop, Storage, Allocator>::Val(int i, int j) const
00543   {
00544 
00545 #ifdef SELDON_CHECK_BOUNDS
00546     if (i < 0 || i >= this->m_)
00547       throw WrongRow("Matrix_Symmetric::Val(int, int) const",
00548                      string("Index should be in [0, ") + to_str(this->m_-1)
00549                      + "], but is equal to " + to_str(i) + ".");
00550     if (j < 0 || j >= this->n_)
00551       throw WrongCol("Matrix_Symmetric::Val(int, int) const",
00552                      string("Index should be in [0, ") + to_str(this->n_-1)
00553                      + "], but is equal to " + to_str(j) + ".");
00554 #endif
00555 
00556     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00557   }
00558 
00559 
00561 
00567   template <class T, class Prop, class Storage, class Allocator>
00568   inline typename Matrix_Symmetric<T, Prop, Storage, Allocator>::reference
00569   Matrix_Symmetric<T, Prop, Storage, Allocator>::Val(int i, int j)
00570   {
00571 
00572 #ifdef SELDON_CHECK_BOUNDS
00573     if (i < 0 || i >= this->m_)
00574       throw WrongRow("Matrix_Symmetric::Val(int, int)",
00575                      string("Index should be in [0, ") + to_str(this->m_-1)
00576                      + "], but is equal to " + to_str(i) + ".");
00577     if (j < 0 || j >= this->n_)
00578       throw WrongCol("Matrix_Symmetric::Val(int, int)",
00579                      string("Index should be in [0, ") + to_str(this->n_-1)
00580                      + "], but is equal to " + to_str(j) + ".");
00581 #endif
00582 
00583     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00584   }
00585 
00586 
00588 
00593   template <class T, class Prop, class Storage, class Allocator>
00594   inline typename Matrix_Symmetric<T, Prop, Storage, Allocator>::reference
00595   Matrix_Symmetric<T, Prop, Storage, Allocator>::operator[] (int i)
00596   {
00597 
00598 #ifdef SELDON_CHECK_BOUNDS
00599     if (i < 0 || i >= this->GetDataSize())
00600       throw WrongIndex("Matrix_Symmetric::operator[] (int)",
00601                        string("Index should be in [0, ")
00602                        + to_str(this->GetDataSize()-1) + "], but is equal to "
00603                        + to_str(i) + ".");
00604 #endif
00605 
00606     return this->data_[i];
00607   }
00608 
00609 
00611 
00616   template <class T, class Prop, class Storage, class Allocator>
00617   inline typename Matrix_Symmetric<T, Prop, Storage, Allocator>
00618   ::const_reference
00619   Matrix_Symmetric<T, Prop, Storage, Allocator>::operator[] (int i) const
00620   {
00621 
00622 #ifdef SELDON_CHECK_BOUNDS
00623     if (i < 0 || i >= this->GetDataSize())
00624       throw WrongIndex("Matrix_Symmetric::operator[] (int) const",
00625                        string("Index should be in [0, ")
00626                        + to_str(this->GetDataSize()-1) + "], but is equal to "
00627                        + to_str(i) + ".");
00628 #endif
00629 
00630     return this->data_[i];
00631   }
00632 
00633 
00635 
00640   template <class T, class Prop, class Storage, class Allocator>
00641   inline Matrix_Symmetric<T, Prop, Storage, Allocator>&
00642   Matrix_Symmetric<T, Prop, Storage, Allocator>
00643   ::operator= (const Matrix_Symmetric<T, Prop, Storage, Allocator>& A)
00644   {
00645     this->Copy(A);
00646 
00647     return *this;
00648   }
00649 
00650 
00652 
00657   template <class T, class Prop, class Storage, class Allocator>
00658   inline void Matrix_Symmetric<T, Prop, Storage, Allocator>
00659   ::Copy(const Matrix_Symmetric<T, Prop, Storage, Allocator>& A)
00660   {
00661     this->Reallocate(A.GetM(), A.GetN());
00662 
00663     this->allocator_.memorycpy(this->data_, A.GetData(), this->GetDataSize());
00664   }
00665 
00666 
00667   /************************
00668    * CONVENIENT FUNCTIONS *
00669    ************************/
00670 
00671 
00673 
00677   template <class T, class Prop, class Storage, class Allocator>
00678   void Matrix_Symmetric<T, Prop, Storage, Allocator>::Zero()
00679   {
00680     this->allocator_.memoryset(this->data_, char(0),
00681                                this->GetDataSize() * sizeof(value_type));
00682   }
00683 
00684 
00686   template <class T, class Prop, class Storage, class Allocator>
00687   void Matrix_Symmetric<T, Prop, Storage, Allocator>::SetIdentity()
00688   {
00689     this->Fill(T(0));
00690 
00691     T one(1);
00692     for (int i = 0; i < min(this->m_, this->n_); i++)
00693       this->Val(i, i) = one;
00694   }
00695 
00696 
00698 
00702   template <class T, class Prop, class Storage, class Allocator>
00703   void Matrix_Symmetric<T, Prop, Storage, Allocator>::Fill()
00704   {
00705     for (int i = 0; i < this->GetDataSize(); i++)
00706       this->data_[i] = i;
00707   }
00708 
00709 
00711 
00714   template <class T, class Prop, class Storage, class Allocator>
00715   template <class T0>
00716   void Matrix_Symmetric<T, Prop, Storage, Allocator>::Fill(const T0& x)
00717   {
00718     for (int i = 0; i < this->GetDataSize(); i++)
00719       this->data_[i] = x;
00720   }
00721 
00722 
00724 
00727   template <class T, class Prop, class Storage, class Allocator>
00728   template <class T0>
00729   Matrix_Symmetric<T, Prop, Storage, Allocator>&
00730   Matrix_Symmetric<T, Prop, Storage, Allocator>::operator= (const T0& x)
00731   {
00732     this->Fill(x);
00733 
00734     return *this;
00735   }
00736 
00737 
00739 
00742   template <class T, class Prop, class Storage, class Allocator>
00743   void Matrix_Symmetric<T, Prop, Storage, Allocator>::FillRand()
00744   {
00745     srand(time(NULL));
00746     for (int i = 0; i < this->GetDataSize(); i++)
00747       this->data_[i] = rand();
00748   }
00749 
00750 
00752 
00757   template <class T, class Prop, class Storage, class Allocator>
00758   void Matrix_Symmetric<T, Prop, Storage, Allocator>::Print() const
00759   {
00760     for (int i = 0; i < this->m_; i++)
00761       {
00762         for (int j = 0; j < this->n_; j++)
00763           cout << (*this)(i, j) << "\t";
00764         cout << endl;
00765       }
00766   }
00767 
00768 
00770 
00781   template <class T, class Prop, class Storage, class Allocator>
00782   void Matrix_Symmetric<T, Prop, Storage, Allocator>
00783   ::Print(int a, int b, int m, int n) const
00784   {
00785     for (int i = a; i < min(this->m_, a + m); i++)
00786       {
00787         for (int j = b; j < min(this->n_, b + n); j++)
00788           cout << (*this)(i, j) << "\t";
00789         cout << endl;
00790       }
00791   }
00792 
00793 
00795 
00803   template <class T, class Prop, class Storage, class Allocator>
00804   void Matrix_Symmetric<T, Prop, Storage, Allocator>::Print(int l) const
00805   {
00806     Print(0, 0, l, l);
00807   }
00808 
00809 
00810   /**************************
00811    * INPUT/OUTPUT FUNCTIONS *
00812    **************************/
00813 
00814 
00816 
00823   template <class T, class Prop, class Storage, class Allocator>
00824   void Matrix_Symmetric<T, Prop, Storage, Allocator>
00825   ::Write(string FileName) const
00826   {
00827     ofstream FileStream;
00828     FileStream.open(FileName.c_str());
00829 
00830 #ifdef SELDON_CHECK_IO
00831     // Checks if the file was opened.
00832     if (!FileStream.is_open())
00833       throw IOError("Matrix_Symmetric::Write(string FileName)",
00834                     string("Unable to open file \"") + FileName + "\".");
00835 #endif
00836 
00837     this->Write(FileStream);
00838 
00839     FileStream.close();
00840   }
00841 
00842 
00844 
00851   template <class T, class Prop, class Storage, class Allocator>
00852   void Matrix_Symmetric<T, Prop, Storage, Allocator>
00853   ::Write(ostream& FileStream) const
00854   {
00855 
00856 #ifdef SELDON_CHECK_IO
00857     // Checks if the stream is ready.
00858     if (!FileStream.good())
00859       throw IOError("Matrix_Symmetric::Write(ofstream& FileStream)",
00860                     "Stream is not ready.");
00861 #endif
00862 
00863     FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
00864                      sizeof(int));
00865     FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->n_)),
00866                      sizeof(int));
00867 
00868     FileStream.write(reinterpret_cast<char*>(this->data_),
00869                      this->m_ * this->n_ * sizeof(value_type));
00870 
00871 #ifdef SELDON_CHECK_IO
00872     // Checks if data was written.
00873     if (!FileStream.good())
00874       throw IOError("Matrix_Symmetric::Write(ofstream& FileStream)",
00875                     string("Output operation failed.")
00876                     + string(" The output file may have been removed")
00877                     + " or there is no space left on device.");
00878 #endif
00879 
00880   }
00881 
00882 
00884 
00891   template <class T, class Prop, class Storage, class Allocator>
00892   void Matrix_Symmetric<T, Prop, Storage, Allocator>
00893   ::WriteText(string FileName) const
00894   {
00895     ofstream FileStream;
00896     FileStream.precision(cout.precision());
00897     FileStream.flags(cout.flags());
00898     FileStream.open(FileName.c_str());
00899 
00900 #ifdef SELDON_CHECK_IO
00901     // Checks if the file was opened.
00902     if (!FileStream.is_open())
00903       throw IOError("Matrix_Symmetric::WriteText(string FileName)",
00904                     string("Unable to open file \"") + FileName + "\".");
00905 #endif
00906 
00907     this->WriteText(FileStream);
00908 
00909     FileStream.close();
00910   }
00911 
00912 
00914 
00921   template <class T, class Prop, class Storage, class Allocator>
00922   void Matrix_Symmetric<T, Prop, Storage, Allocator>
00923   ::WriteText(ostream& FileStream) const
00924   {
00925 
00926 #ifdef SELDON_CHECK_IO
00927     // Checks if the file is ready.
00928     if (!FileStream.good())
00929       throw IOError("Matrix_Symmetric::WriteText(ofstream& FileStream)",
00930                     "Stream is not ready.");
00931 #endif
00932 
00933     int i, j;
00934     for (i = 0; i < this->GetM(); i++)
00935       {
00936         for (j = 0; j < this->GetN(); j++)
00937           FileStream << (*this)(i, j) << '\t';
00938         FileStream << endl;
00939       }
00940 
00941 #ifdef SELDON_CHECK_IO
00942     // Checks if data was written.
00943     if (!FileStream.good())
00944       throw IOError("Matrix_Symmetric::WriteText(ofstream& FileStream)",
00945                     string("Output operation failed.")
00946                     + string(" The output file may have been removed")
00947                     + " or there is no space left on device.");
00948 #endif
00949 
00950   }
00951 
00952 
00954 
00961   template <class T, class Prop, class Storage, class Allocator>
00962   void Matrix_Symmetric<T, Prop, Storage, Allocator>::Read(string FileName)
00963   {
00964     ifstream FileStream;
00965     FileStream.open(FileName.c_str());
00966 
00967 #ifdef SELDON_CHECK_IO
00968     // Checks if the file was opened.
00969     if (!FileStream.is_open())
00970       throw IOError("Matrix_Symmetric::Read(string FileName)",
00971                     string("Unable to open file \"") + FileName + "\".");
00972 #endif
00973 
00974     this->Read(FileStream);
00975 
00976     FileStream.close();
00977   }
00978 
00979 
00981 
00988   template <class T, class Prop, class Storage, class Allocator>
00989   void Matrix_Symmetric<T, Prop, Storage, Allocator>
00990   ::Read(istream& FileStream)
00991   {
00992 
00993 #ifdef SELDON_CHECK_IO
00994     // Checks if the stream is ready.
00995     if (!FileStream.good())
00996       throw IOError("Matrix_Symmetric::Read(ifstream& FileStream)",
00997                     "Stream is not ready.");
00998 #endif
00999 
01000     int new_m, new_n;
01001     FileStream.read(reinterpret_cast<char*>(&new_m), sizeof(int));
01002     FileStream.read(reinterpret_cast<char*>(&new_n), sizeof(int));
01003     this->Reallocate(new_m, new_n);
01004 
01005     FileStream.read(reinterpret_cast<char*>(this->data_),
01006                     new_m * new_n * sizeof(value_type));
01007 
01008 #ifdef SELDON_CHECK_IO
01009     // Checks if data was read.
01010     if (!FileStream.good())
01011       throw IOError("Matrix_Symmetric::Read(ifstream& FileStream)",
01012                     string("Output operation failed.")
01013                     + string(" The intput file may have been removed")
01014                     + " or may not contain enough data.");
01015 #endif
01016 
01017   }
01018 
01019 
01021 
01025   template <class T, class Prop, class Storage, class Allocator>
01026   void Matrix_Symmetric<T, Prop, Storage, Allocator>::ReadText(string FileName)
01027   {
01028     ifstream FileStream;
01029     FileStream.open(FileName.c_str());
01030 
01031 #ifdef SELDON_CHECK_IO
01032     // Checks if the file was opened.
01033     if (!FileStream.is_open())
01034       throw IOError("Matrix_Pointers::ReadText(string FileName)",
01035                     string("Unable to open file \"") + FileName + "\".");
01036 #endif
01037 
01038     this->ReadText(FileStream);
01039 
01040     FileStream.close();
01041   }
01042 
01043 
01045 
01049   template <class T, class Prop, class Storage, class Allocator>
01050   void Matrix_Symmetric<T, Prop, Storage, Allocator>
01051   ::ReadText(istream& FileStream)
01052   {
01053     // clears previous matrix
01054     Clear();
01055 
01056 #ifdef SELDON_CHECK_IO
01057     // Checks if the stream is ready.
01058     if (!FileStream.good())
01059       throw IOError("Matrix_Pointers::ReadText(ifstream& FileStream)",
01060                     "Stream is not ready.");
01061 #endif
01062 
01063     // we read first line
01064     string line;
01065     getline(FileStream, line);
01066 
01067     if (FileStream.fail())
01068       {
01069         // empty file ?
01070         return;
01071       }
01072 
01073     // converting first line into a vector
01074     istringstream line_stream(line);
01075     Vector<T> first_row;
01076     first_row.ReadText(line_stream);
01077 
01078     // and now the other rows
01079     Vector<T> other_rows;
01080     other_rows.ReadText(FileStream);
01081 
01082     // number of rows and columns
01083     int n = first_row.GetM();
01084     int m = 1 + other_rows.GetM()/n;
01085 
01086 #ifdef SELDON_CHECK_IO
01087     // Checking number of elements
01088     if (other_rows.GetM() != (m-1)*n)
01089       throw IOError("Matrix_Pointers::ReadText(ifstream& FileStream)",
01090                     "The file should contain same number of columns.");
01091 #endif
01092 
01093     this->Reallocate(m,n);
01094     // filling matrix
01095     for (int j = 0; j < n; j++)
01096       this->Val(0, j) = first_row(j);
01097 
01098     int nb = 0;
01099     for (int i = 1; i < m; i++)
01100       {
01101         for (int j = 0; j < i; j++)
01102           nb++;
01103 
01104         for (int j = i; j < n; j++)
01105           this->Val(i, j) = other_rows(nb++);
01106       }
01107   }
01108 
01109 
01110 
01112   // MATRIX<COLSYM> //
01114 
01115 
01116   /****************
01117    * CONSTRUCTORS *
01118    ****************/
01119 
01120 
01122 
01125   template <class T, class Prop, class Allocator>
01126   Matrix<T, Prop, ColSym, Allocator>::Matrix()  throw():
01127     Matrix_Symmetric<T, Prop, ColSym, Allocator>()
01128   {
01129   }
01130 
01131 
01133 
01137   template <class T, class Prop, class Allocator>
01138   Matrix<T, Prop, ColSym, Allocator>::Matrix(int i, int j):
01139     Matrix_Symmetric<T, Prop, ColSym, Allocator>(i, j)
01140   {
01141   }
01142 
01143 
01144   /*****************
01145    * OTHER METHODS *
01146    *****************/
01147 
01148 
01150 
01153   template <class T, class Prop, class Allocator>
01154   template <class T0>
01155   Matrix<T, Prop, ColSym, Allocator>&
01156   Matrix<T, Prop, ColSym, Allocator>::operator= (const T0& x)
01157   {
01158     this->Fill(x);
01159 
01160     return *this;
01161   }
01162 
01163 
01165 
01168   template <class T, class Prop, class Allocator>
01169   template <class T0>
01170   Matrix<T, Prop, ColSym, Allocator>&
01171   Matrix<T, Prop, ColSym, Allocator>::operator*= (const T0& x)
01172   {
01173     for (int i = 0; i < this->GetDataSize();i++)
01174       this->data_[i] *= x;
01175 
01176     return *this;
01177   }
01178 
01179 
01181   // MATRIX<ROWSYM> //
01183 
01184 
01185   /****************
01186    * CONSTRUCTORS *
01187    ****************/
01188 
01189 
01191 
01194   template <class T, class Prop, class Allocator>
01195   Matrix<T, Prop, RowSym, Allocator>::Matrix()  throw():
01196     Matrix_Symmetric<T, Prop, RowSym, Allocator>()
01197   {
01198   }
01199 
01200 
01202 
01206   template <class T, class Prop, class Allocator>
01207   Matrix<T, Prop, RowSym, Allocator>::Matrix(int i, int j):
01208     Matrix_Symmetric<T, Prop, RowSym, Allocator>(i, j)
01209   {
01210   }
01211 
01212 
01213   /*****************
01214    * OTHER METHODS *
01215    *****************/
01216 
01217 
01219 
01222   template <class T, class Prop, class Allocator>
01223   template <class T0>
01224   Matrix<T, Prop, RowSym, Allocator>&
01225   Matrix<T, Prop, RowSym, Allocator>::operator= (const T0& x)
01226   {
01227     this->Fill(x);
01228 
01229     return *this;
01230   }
01231 
01232 
01234 
01237   template <class T, class Prop, class Allocator>
01238   template <class T0>
01239   Matrix<T, Prop, RowSym, Allocator>&
01240   Matrix<T, Prop, RowSym, Allocator>::operator*= (const T0& x)
01241   {
01242     for (int i = 0; i < this->GetDataSize();i++)
01243       this->data_[i] *= x;
01244 
01245     return *this;
01246   }
01247 
01248 } // namespace Seldon.
01249 
01250 #define SELDON_FILE_MATRIX_SYMMETRIC_CXX
01251 #endif