matrix/Matrix_Hermitian.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_HERMITIAN_CXX
00022 
00023 #include "Matrix_Hermitian.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_Hermitian<T, Prop, Storage, Allocator>::Matrix_Hermitian():
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_Hermitian<T, Prop, Storage, Allocator>
00054   ::Matrix_Hermitian(int i, int j):
00055     Matrix_Base<T, Allocator>(i, i)
00056   {
00057 
00058 #ifdef SELDON_CHECK_MEMORY
00059     try
00060       {
00061 #endif
00062 
00063         me_ = reinterpret_cast<pointer*>(calloc(i, sizeof(pointer)));
00064 
00065 #ifdef SELDON_CHECK_MEMORY
00066       }
00067     catch (...)
00068       {
00069         this->m_ = 0;
00070         this->n_ = 0;
00071         me_ = NULL;
00072         this->data_ = NULL;
00073       }
00074     if (me_ == NULL)
00075       {
00076         this->m_ = 0;
00077         this->n_ = 0;
00078         this->data_ = NULL;
00079       }
00080     if ((me_ == NULL) && (i != 0))
00081       throw NoMemory("Matrix_Hermitian::Matrix_Hermitian(int, int)",
00082                      string("Unable to allocate memory for a matrix of size ")
00083                      + to_str(static_cast<long int>(i)
00084                               * static_cast<long int>(i)
00085                               * static_cast<long int>(sizeof(T)))
00086                      + " bytes (" + to_str(i) + " x " + to_str(i)
00087                      + " elements).");
00088 #endif
00089 
00090 #ifdef SELDON_CHECK_MEMORY
00091     try
00092       {
00093 #endif
00094 
00095         this->data_ = this->allocator_.allocate(i * i, this);
00096 
00097 #ifdef SELDON_CHECK_MEMORY
00098       }
00099     catch (...)
00100       {
00101         this->m_ = 0;
00102         this->n_ = 0;
00103         free(me_);
00104         me_ = NULL;
00105         this->data_ = NULL;
00106       }
00107     if (this->data_ == NULL)
00108       {
00109         this->m_ = 0;
00110         this->n_ = 0;
00111         free(me_);
00112         me_ = NULL;
00113       }
00114     if (this->data_ == NULL && i != 0)
00115       throw NoMemory("Matrix_Hermitian::Matrix_Hermitian(int, int)",
00116                      string("Unable to allocate memory for a matrix of size ")
00117                      + to_str(static_cast<long int>(i)
00118                               * static_cast<long int>(i)
00119                               * static_cast<long int>(sizeof(T)))
00120                      + " bytes (" + to_str(i) + " x " + to_str(i)
00121                      + " elements).");
00122 #endif
00123 
00124     pointer ptr = this->data_;
00125     int lgth = i;
00126     for (int k = 0; k < i; k++, ptr += lgth)
00127       me_[k] = ptr;
00128   }
00129 
00130 
00132   template <class T, class Prop, class Storage, class Allocator>
00133   inline Matrix_Hermitian<T, Prop, Storage, Allocator>
00134   ::Matrix_Hermitian(const Matrix_Hermitian<T, Prop, Storage, Allocator>& A):
00135     Matrix_Base<T, Allocator>()
00136   {
00137     this->m_ = 0;
00138     this->n_ = 0;
00139     this->data_ = NULL;
00140     this->me_ = NULL;
00141 
00142     this->Copy(A);
00143   }
00144 
00145 
00146   /**************
00147    * DESTRUCTOR *
00148    **************/
00149 
00150 
00152   template <class T, class Prop, class Storage, class Allocator>
00153   inline Matrix_Hermitian<T, Prop, Storage, Allocator>::~Matrix_Hermitian()
00154   {
00155 
00156 #ifdef SELDON_CHECK_MEMORY
00157     try
00158       {
00159 #endif
00160 
00161         if (this->data_ != NULL)
00162           {
00163             this->allocator_.deallocate(this->data_, this->m_ * this->n_);
00164             this->data_ = NULL;
00165           }
00166 
00167 #ifdef SELDON_CHECK_MEMORY
00168       }
00169     catch (...)
00170       {
00171         this->data_ = NULL;
00172       }
00173 #endif
00174 
00175 #ifdef SELDON_CHECK_MEMORY
00176     try
00177       {
00178 #endif
00179 
00180         if (me_ != NULL)
00181           {
00182             free(me_);
00183             me_ = NULL;
00184           }
00185 
00186 #ifdef SELDON_CHECK_MEMORY
00187       }
00188     catch (...)
00189       {
00190         this->m_ = 0;
00191         this->n_ = 0;
00192         me_ = NULL;
00193       }
00194 #endif
00195 
00196   }
00197 
00198 
00200 
00204   template <class T, class Prop, class Storage, class Allocator>
00205   inline void Matrix_Hermitian<T, Prop, Storage, Allocator>::Clear()
00206   {
00207     this->~Matrix_Hermitian();
00208     this->m_ = 0;
00209     this->n_ = 0;
00210   }
00211 
00212 
00213   /*******************
00214    * BASIC FUNCTIONS *
00215    *******************/
00216 
00217 
00219 
00225   template <class T, class Prop, class Storage, class Allocator>
00226   int Matrix_Hermitian<T, Prop, Storage, Allocator>::GetDataSize() const
00227   {
00228     return this->m_ * this->n_;
00229   }
00230 
00231 
00232   /*********************
00233    * MEMORY MANAGEMENT *
00234    *********************/
00235 
00236 
00238 
00244   template <class T, class Prop, class Storage, class Allocator>
00245   inline void Matrix_Hermitian<T, Prop, Storage, Allocator>
00246   ::Reallocate(int i, int j)
00247   {
00248 
00249     if (i != this->m_)
00250       {
00251         this->m_ = i;
00252         this->n_ = i;
00253 
00254 #ifdef SELDON_CHECK_MEMORY
00255         try
00256           {
00257 #endif
00258 
00259             me_ = reinterpret_cast<pointer*>( realloc(me_,
00260                                                       i * sizeof(pointer)) );
00261 
00262 #ifdef SELDON_CHECK_MEMORY
00263           }
00264         catch (...)
00265           {
00266             this->m_ = 0;
00267             this->n_ = 0;
00268             me_ = NULL;
00269             this->data_ = NULL;
00270           }
00271         if (me_ == NULL)
00272           {
00273             this->m_ = 0;
00274             this->n_ = 0;
00275             this->data_ = NULL;
00276           }
00277         if (me_ == NULL && i != 0)
00278           throw NoMemory("Matrix_Hermitian::Reallocate(int, int)",
00279                          string("Unable to reallocate memory")
00280                          + " for a matrix of size "
00281                          + to_str(static_cast<long int>(i)
00282                                   * static_cast<long int>(i)
00283                                   * static_cast<long int>(sizeof(T)))
00284                          + " bytes (" + to_str(i) + " x " + to_str(i)
00285                          + " elements).");
00286 #endif
00287 
00288 #ifdef SELDON_CHECK_MEMORY
00289         try
00290           {
00291 #endif
00292 
00293             this->data_ =
00294               reinterpret_cast<pointer>(this->allocator_.reallocate(this->data_,
00295                                                                     i * i,
00296                                                                     this));
00297 
00298 #ifdef SELDON_CHECK_MEMORY
00299           }
00300         catch (...)
00301           {
00302             this->m_ = 0;
00303             this->n_ = 0;
00304             free(me_);
00305             me_ = NULL;
00306             this->data_ = NULL;
00307           }
00308         if (this->data_ == NULL)
00309           {
00310             this->m_ = 0;
00311             this->n_ = 0;
00312             free(me_);
00313             me_ = NULL;
00314           }
00315         if (this->data_ == NULL && i != 0)
00316           throw NoMemory("Matrix_Hermitian::Reallocate(int, int)",
00317                          string("Unable to reallocate memory")
00318                          + " for a matrix of size "
00319                          + to_str(static_cast<long int>(i)
00320                                   * static_cast<long int>(i)
00321                                   * static_cast<long int>(sizeof(T)))
00322                          + " bytes (" + to_str(i) + " x " + to_str(i)
00323                          + " elements).");
00324 #endif
00325 
00326         pointer ptr = this->data_;
00327         int lgth = Storage::GetSecond(i, i);
00328         for (int k = 0; k < Storage::GetFirst(i, i); k++, ptr += lgth)
00329           me_[k] = ptr;
00330       }
00331   }
00332 
00333 
00336 
00350   template <class T, class Prop, class Storage, class Allocator>
00351   inline void Matrix_Hermitian<T, Prop, Storage, Allocator>
00352   ::SetData(int i, int j,
00353             typename Matrix_Hermitian<T, Prop, Storage, Allocator>
00354             ::pointer data)
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_Hermitian<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_Hermitian<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_Hermitian<T, Prop, Storage, Allocator>::value_type
00480   Matrix_Hermitian<T, Prop, Storage, Allocator>
00481   ::operator() (int i, int j) const
00482   {
00483 
00484 #ifdef SELDON_CHECK_BOUNDS
00485     if (i < 0 || i >= this->m_)
00486       throw WrongRow("Matrix_Hermitian::operator() const",
00487                      string("Index should be in [0, ") + to_str(this->m_-1)
00488                      + "], but is equal to " + to_str(i) + ".");
00489     if (j < 0 || j >= this->n_)
00490       throw WrongCol("Matrix_Hermitian::operator() const",
00491                      string("Index should be in [0, ") + to_str(this->n_-1)
00492                      + "], but is equal to " + to_str(j) + ".");
00493 #endif
00494 
00495     if (i > j)
00496       return conj(me_[Storage::GetSecond(i, j)][Storage::GetFirst(i, j)]);
00497     else
00498       return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00499   }
00500 
00501 
00503 
00509   template <class T, class Prop, class Storage, class Allocator>
00510   inline typename Matrix_Hermitian<T, Prop, Storage, Allocator>
00511   ::const_reference
00512   Matrix_Hermitian<T, Prop, Storage, Allocator>::Val(int i, int j) const
00513   {
00514 
00515 #ifdef SELDON_CHECK_BOUNDS
00516     if (i < 0 || i >= this->m_)
00517       throw WrongRow("Matrix_Hermitian::Val(int, int) const",
00518                      string("Index should be in [0, ") + to_str(this->m_-1)
00519                      + "], but is equal to " + to_str(i) + ".");
00520     if (j < 0 || j >= this->n_)
00521       throw WrongCol("Matrix_Hermitian::Val(int, int) const",
00522                      string("Index should be in [0, ") + to_str(this->n_-1)
00523                      + "], but is equal to " + to_str(j) + ".");
00524     if (i > j)
00525       throw WrongRow("Matrix_Hermitian::Val(int, int)",
00526                      string("Attempted to access to element (")
00527                      + to_str(i) + ", " + to_str(j)
00528                      + ") but row index should not be strictly"
00529                      + " greater than column index.");
00530 #endif
00531 
00532     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00533   }
00534 
00535 
00537 
00543   template <class T, class Prop, class Storage, class Allocator>
00544   inline typename Matrix_Hermitian<T, Prop, Storage, Allocator>::reference
00545   Matrix_Hermitian<T, Prop, Storage, Allocator>::Val(int i, int j)
00546   {
00547 
00548 #ifdef SELDON_CHECK_BOUNDS
00549     if (i < 0 || i >= this->m_)
00550       throw WrongRow("Matrix_Hermitian::Val(int, int)",
00551                      string("Index should be in [0, ") + to_str(this->m_-1)
00552                      + "], but is equal to " + to_str(i) + ".");
00553     if (j < 0 || j >= this->n_)
00554       throw WrongCol("Matrix_Hermitian::Val(int, int)",
00555                      string("Index should be in [0, ") + to_str(this->n_-1)
00556                      + "], but is equal to " + to_str(j) + ".");
00557     if (i > j)
00558       throw WrongRow("Matrix_Hermitian::Val(int, int)",
00559                      string("Attempted to access to element (")
00560                      + to_str(i) + ", " + to_str(j)
00561                      + ") but row index should not be strictly"
00562                      + " greater than column index.");
00563 #endif
00564 
00565     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00566   }
00567 
00568 
00570 
00576   template <class T, class Prop, class Storage, class Allocator>
00577   inline typename Matrix_Hermitian<T, Prop, Storage, Allocator>
00578   ::const_reference
00579   Matrix_Hermitian<T, Prop, Storage, Allocator>::Get(int i, int j) const
00580   {
00581 
00582 #ifdef SELDON_CHECK_BOUNDS
00583     if (i < 0 || i >= this->m_)
00584       throw WrongRow("Matrix_Hermitian::Val(int, int) const",
00585                      string("Index should be in [0, ") + to_str(this->m_-1)
00586                      + "], but is equal to " + to_str(i) + ".");
00587     if (j < 0 || j >= this->n_)
00588       throw WrongCol("Matrix_Hermitian::Val(int, int) const",
00589                      string("Index should be in [0, ") + to_str(this->n_-1)
00590                      + "], but is equal to " + to_str(j) + ".");
00591     if (i > j)
00592       throw WrongRow("Matrix_Hermitian::Get(int, int)",
00593                      string("Attempted to access to element (")
00594                      + to_str(i) + ", " + to_str(j)
00595                      + ") but row index should not be strictly"
00596                      + " greater than column index.");
00597 #endif
00598 
00599     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00600   }
00601 
00602 
00604 
00610   template <class T, class Prop, class Storage, class Allocator>
00611   inline typename Matrix_Hermitian<T, Prop, Storage, Allocator>::reference
00612   Matrix_Hermitian<T, Prop, Storage, Allocator>::Get(int i, int j)
00613   {
00614 
00615 #ifdef SELDON_CHECK_BOUNDS
00616     if (i < 0 || i >= this->m_)
00617       throw WrongRow("Matrix_Hermitian::Val(int, int)",
00618                      string("Index should be in [0, ") + to_str(this->m_-1)
00619                      + "], but is equal to " + to_str(i) + ".");
00620     if (j < 0 || j >= this->n_)
00621       throw WrongCol("Matrix_Hermitian::Val(int, int)",
00622                      string("Index should be in [0, ") + to_str(this->n_-1)
00623                      + "], but is equal to " + to_str(j) + ".");
00624     if (i > j)
00625       throw WrongRow("Matrix_Hermitian::Val(int, int)",
00626                      string("Attempted to access to element (")
00627                      + to_str(i) + ", " + to_str(j)
00628                      + ") but row index should not be strictly"
00629                      + " greater than column index.");
00630 #endif
00631 
00632     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00633   }
00634 
00635 
00637 
00642   template <class T, class Prop, class Storage, class Allocator>
00643   inline typename Matrix_Hermitian<T, Prop, Storage, Allocator>::reference
00644   Matrix_Hermitian<T, Prop, Storage, Allocator>::operator[] (int i)
00645   {
00646 
00647 #ifdef SELDON_CHECK_BOUNDS
00648     if (i < 0 || i >= this->GetDataSize())
00649       throw WrongIndex("Matrix_Hermitian::operator[] (int)",
00650                        string("Index should be in [0, ")
00651                        + to_str(this->GetDataSize()-1) + "], but is equal to "
00652                        + to_str(i) + ".");
00653 #endif
00654 
00655     return this->data_[i];
00656   }
00657 
00658 
00660 
00665   template <class T, class Prop, class Storage, class Allocator>
00666   inline typename Matrix_Hermitian<T, Prop, Storage, Allocator>
00667   ::const_reference
00668   Matrix_Hermitian<T, Prop, Storage, Allocator>::operator[] (int i) const
00669   {
00670 
00671 #ifdef SELDON_CHECK_BOUNDS
00672     if (i < 0 || i >= this->GetDataSize())
00673       throw WrongIndex("Matrix_Hermitian::operator[] (int) const",
00674                        string("Index should be in [0, ")
00675                        + to_str(this->GetDataSize()-1) + "], but is equal to "
00676                        + to_str(i) + ".");
00677 #endif
00678 
00679     return this->data_[i];
00680   }
00681 
00682 
00684 
00689   template <class T, class Prop, class Storage, class Allocator>
00690   inline void Matrix_Hermitian<T, Prop, Storage, Allocator>
00691   ::Set(int i, int j, const T& x)
00692   {
00693     if (i > j)
00694       this->Val(j, i) = conj(x);
00695     else
00696       this->Val(i, j) = x;
00697   }
00698 
00699 
00701 
00706   template <class T, class Prop, class Storage, class Allocator>
00707   inline Matrix_Hermitian<T, Prop, Storage, Allocator>&
00708   Matrix_Hermitian<T, Prop, Storage, Allocator>
00709   ::operator=(const Matrix_Hermitian<T, Prop, Storage, Allocator>& A)
00710   {
00711     this->Copy(A);
00712 
00713     return *this;
00714   }
00715 
00716 
00718 
00723   template <class T, class Prop, class Storage, class Allocator>
00724   inline void Matrix_Hermitian<T, Prop, Storage, Allocator>
00725   ::Copy(const Matrix_Hermitian<T, Prop, Storage, Allocator>& A)
00726   {
00727     this->Reallocate(A.GetM(), A.GetN());
00728 
00729     this->allocator_.memorycpy(this->data_, A.GetData(), this->GetDataSize());
00730   }
00731 
00732 
00733   /************************
00734    * CONVENIENT FUNCTIONS *
00735    ************************/
00736 
00737 
00739 
00743   template <class T, class Prop, class Storage, class Allocator>
00744   void Matrix_Hermitian<T, Prop, Storage, Allocator>::Zero()
00745   {
00746     this->allocator_.memoryset(this->data_, char(0),
00747                                this->GetDataSize() * sizeof(value_type));
00748   }
00749 
00750 
00752 
00756   template <class T, class Prop, class Storage, class Allocator>
00757   void Matrix_Hermitian<T, Prop, Storage, Allocator>::SetIdentity()
00758   {
00759     this->Fill(T(0));
00760 
00761     T one;
00762     SetComplexOne(one);
00763     for (int i = 0; i < min(this->m_, this->n_); i++)
00764       this->Val(i, i) = one;
00765   }
00766 
00767 
00769 
00773   template <class T, class Prop, class Storage, class Allocator>
00774   void Matrix_Hermitian<T, Prop, Storage, Allocator>::Fill()
00775   {
00776     for (int i = 0; i < this->GetDataSize(); i++)
00777       this->data_[i] = i;
00778   }
00779 
00780 
00782 
00787   template <class T, class Prop, class Storage, class Allocator>
00788   template <class T0>
00789   void Matrix_Hermitian<T, Prop, Storage, Allocator>::Fill(const T0& x)
00790   {
00791     for (int i = 0; i < this->GetDataSize(); i++)
00792       this->data_[i] = x;
00793   }
00794 
00795 
00797 
00802   template <class T, class Prop, class Storage, class Allocator>
00803   template <class T0>
00804   Matrix_Hermitian<T, Prop, Storage, Allocator>&
00805   Matrix_Hermitian<T, Prop, Storage, Allocator>::operator= (const T0& x)
00806   {
00807     this->Fill(x);
00808 
00809     return *this;
00810   }
00811 
00812 
00814 
00817   template <class T, class Prop, class Storage, class Allocator>
00818   void Matrix_Hermitian<T, Prop, Storage, Allocator>::FillRand()
00819   {
00820     srand(time(NULL));
00821     for (int i = 0; i < this->GetDataSize(); i++)
00822       this->data_[i] = rand();
00823   }
00824 
00825 
00827 
00832   template <class T, class Prop, class Storage, class Allocator>
00833   void Matrix_Hermitian<T, Prop, Storage, Allocator>::Print() const
00834   {
00835     for (int i = 0; i < this->m_; i++)
00836       {
00837         for (int j = 0; j < this->n_; j++)
00838           cout << (*this)(i, j) << "\t";
00839         cout << endl;
00840       }
00841   }
00842 
00843 
00845 
00856   template <class T, class Prop, class Storage, class Allocator>
00857   void Matrix_Hermitian<T, Prop, Storage, Allocator>
00858   ::Print(int a, int b, int m, int n) const
00859   {
00860     for (int i = a; i < min(this->m_, a+m); i++)
00861       {
00862         for (int j = b; j < min(this->n_, b+n); j++)
00863           cout << (*this)(i, j) << "\t";
00864         cout << endl;
00865       }
00866   }
00867 
00868 
00870 
00878   template <class T, class Prop, class Storage, class Allocator>
00879   void Matrix_Hermitian<T, Prop, Storage, Allocator>::Print(int l) const
00880   {
00881     Print(0, 0, l, l);
00882   }
00883 
00884 
00885   /**************************
00886    * INPUT/OUTPUT FUNCTIONS *
00887    **************************/
00888 
00889 
00891 
00898   template <class T, class Prop, class Storage, class Allocator>
00899   void Matrix_Hermitian<T, Prop, Storage, Allocator>
00900   ::Write(string FileName) const
00901   {
00902     ofstream FileStream;
00903     FileStream.open(FileName.c_str(), ofstream::binary);
00904 
00905 #ifdef SELDON_CHECK_IO
00906     // Checks if the file was opened.
00907     if (!FileStream.is_open())
00908       throw IOError("Matrix_Hermitian::Write(string FileName)",
00909                     string("Unable to open file \"") + FileName + "\".");
00910 #endif
00911 
00912     this->Write(FileStream);
00913 
00914     FileStream.close();
00915   }
00916 
00917 
00919 
00926   template <class T, class Prop, class Storage, class Allocator>
00927   void Matrix_Hermitian<T, Prop, Storage, Allocator>
00928   ::Write(ostream& FileStream) const
00929   {
00930 
00931 #ifdef SELDON_CHECK_IO
00932     // Checks if the stream is ready.
00933     if (!FileStream.good())
00934       throw IOError("Matrix_Hermitian::Write(ofstream& FileStream)",
00935                     "Stream is not ready.");
00936 #endif
00937 
00938     FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
00939                      sizeof(int));
00940     FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->n_)),
00941                      sizeof(int));
00942 
00943     FileStream.write(reinterpret_cast<char*>(this->data_),
00944                      this->m_ * this->n_ * sizeof(value_type));
00945 
00946 #ifdef SELDON_CHECK_IO
00947     // Checks if data was written.
00948     if (!FileStream.good())
00949       throw IOError("Matrix_Hermitian::Write(ofstream& FileStream)",
00950                     string("Output operation failed.")
00951                     + string(" The output file may have been removed")
00952                     + " or there is no space left on device.");
00953 #endif
00954 
00955   }
00956 
00957 
00959 
00966   template <class T, class Prop, class Storage, class Allocator>
00967   void Matrix_Hermitian<T, Prop, Storage, Allocator>
00968   ::WriteText(string FileName) const
00969   {
00970     ofstream FileStream;
00971     FileStream.precision(cout.precision());
00972     FileStream.flags(cout.flags());
00973     FileStream.open(FileName.c_str());
00974 
00975 #ifdef SELDON_CHECK_IO
00976     // Checks if the file was opened.
00977     if (!FileStream.is_open())
00978       throw IOError("Matrix_Hermitian::WriteText(string FileName)",
00979                     string("Unable to open file \"") + FileName + "\".");
00980 #endif
00981 
00982     this->WriteText(FileStream);
00983 
00984     FileStream.close();
00985   }
00986 
00987 
00989 
00996   template <class T, class Prop, class Storage, class Allocator>
00997   void Matrix_Hermitian<T, Prop, Storage, Allocator>
00998   ::WriteText(ostream& FileStream) const
00999   {
01000 
01001 #ifdef SELDON_CHECK_IO
01002     // Checks if the file is ready.
01003     if (!FileStream.good())
01004       throw IOError("Matrix_Hermitian::WriteText(ofstream& FileStream)",
01005                     "Stream is not ready.");
01006 #endif
01007 
01008     int i, j;
01009     for (i = 0; i < this->GetM(); i++)
01010       {
01011         for (j = 0; j < this->GetN(); j++)
01012           FileStream << (*this)(i, j) << '\t';
01013         FileStream << endl;
01014       }
01015 
01016 #ifdef SELDON_CHECK_IO
01017     // Checks if data was written.
01018     if (!FileStream.good())
01019       throw IOError("Matrix_Hermitian::WriteText(ofstream& FileStream)",
01020                     string("Output operation failed.")
01021                     + string(" The output file may have been removed")
01022                     + " or there is no space left on device.");
01023 #endif
01024 
01025   }
01026 
01027 
01029 
01036   template <class T, class Prop, class Storage, class Allocator>
01037   void Matrix_Hermitian<T, Prop, Storage, Allocator>::Read(string FileName)
01038   {
01039     ifstream FileStream;
01040     FileStream.open(FileName.c_str(), ifstream::binary);
01041 
01042 #ifdef SELDON_CHECK_IO
01043     // Checks if the file was opened.
01044     if (!FileStream.is_open())
01045       throw IOError("Matrix_Hermitian::Read(string FileName)",
01046                     string("Unable to open file \"") + FileName + "\".");
01047 #endif
01048 
01049     this->Read(FileStream);
01050 
01051     FileStream.close();
01052   }
01053 
01054 
01056 
01063   template <class T, class Prop, class Storage, class Allocator>
01064   void Matrix_Hermitian<T, Prop, Storage, Allocator>
01065   ::Read(istream& FileStream)
01066   {
01067 
01068 #ifdef SELDON_CHECK_IO
01069     // Checks if the stream is ready.
01070     if (!FileStream.good())
01071       throw IOError("Matrix_Hermitian::Read(ifstream& FileStream)",
01072                     "Stream is not ready.");
01073 #endif
01074 
01075     int new_m, new_n;
01076     FileStream.read(reinterpret_cast<char*>(&new_m), sizeof(int));
01077     FileStream.read(reinterpret_cast<char*>(&new_n), sizeof(int));
01078     this->Reallocate(new_m, new_n);
01079 
01080     FileStream.read(reinterpret_cast<char*>(this->data_),
01081                     new_m * new_n * sizeof(value_type));
01082 
01083 #ifdef SELDON_CHECK_IO
01084     // Checks if data was read.
01085     if (!FileStream.good())
01086       throw IOError("Matrix_Hermitian::Read(ifstream& FileStream)",
01087                     string("Input operation failed.")
01088                     + string(" The input file may have been removed")
01089                     + " or may not contain enough data.");
01090 #endif
01091 
01092   }
01093 
01094 
01096 
01100   template <class T, class Prop, class Storage, class Allocator>
01101   void Matrix_Hermitian<T, Prop, Storage, Allocator>::ReadText(string FileName)
01102   {
01103     ifstream FileStream;
01104     FileStream.open(FileName.c_str());
01105 
01106 #ifdef SELDON_CHECK_IO
01107     // Checks if the file was opened.
01108     if (!FileStream.is_open())
01109       throw IOError("Matrix_Pointers::ReadText(string FileName)",
01110                     string("Unable to open file \"") + FileName + "\".");
01111 #endif
01112 
01113     this->ReadText(FileStream);
01114 
01115     FileStream.close();
01116   }
01117 
01118 
01120 
01124   template <class T, class Prop, class Storage, class Allocator>
01125   void Matrix_Hermitian<T, Prop, Storage, Allocator>
01126   ::ReadText(istream& FileStream)
01127   {
01128     // clears previous matrix
01129     Clear();
01130 
01131 #ifdef SELDON_CHECK_IO
01132     // Checks if the stream is ready.
01133     if (!FileStream.good())
01134       throw IOError("Matrix_Pointers::ReadText(ifstream& FileStream)",
01135                     "Stream is not ready.");
01136 #endif
01137 
01138     // we read first line
01139     string line;
01140     getline(FileStream, line);
01141 
01142     if (FileStream.fail())
01143       {
01144         // empty file ?
01145         return;
01146       }
01147 
01148     // converting first line into a vector
01149     istringstream line_stream(line);
01150     Vector<T> first_row;
01151     first_row.ReadText(line_stream);
01152 
01153     // and now the other rows
01154     Vector<T> other_rows;
01155     other_rows.ReadText(FileStream);
01156 
01157     // number of rows and columns
01158     int n = first_row.GetM();
01159     int m = 1 + other_rows.GetM()/n;
01160 
01161 #ifdef SELDON_CHECK_IO
01162     // Checking number of elements
01163     if (other_rows.GetM() != (m-1)*n)
01164       throw IOError("Matrix_Pointers::ReadText(ifstream& FileStream)",
01165                     "The file should contain same number of columns.");
01166 #endif
01167 
01168     this->Reallocate(m,n);
01169     // filling matrix
01170     for (int j = 0; j < n; j++)
01171       this->Val(0, j) = first_row(j);
01172 
01173     int nb = 0;
01174     for (int i = 1; i < m; i++)
01175       {
01176         for (int j = 0; j < i; j++)
01177           nb++;
01178 
01179         for (int j = i; j < n; j++)
01180           this->Val(i, j) = other_rows(nb++);
01181       }
01182   }
01183 
01184 
01185 
01187   // MATRIX<COLHERM> //
01189 
01190 
01191   /****************
01192    * CONSTRUCTORS *
01193    ****************/
01194 
01195 
01197 
01200   template <class T, class Prop, class Allocator>
01201   Matrix<T, Prop, ColHerm, Allocator>::Matrix():
01202     Matrix_Hermitian<T, Prop, ColHerm, Allocator>()
01203   {
01204   }
01205 
01206 
01208 
01212   template <class T, class Prop, class Allocator>
01213   Matrix<T, Prop, ColHerm, Allocator>::Matrix(int i, int j):
01214     Matrix_Hermitian<T, Prop, ColHerm, Allocator>(i, j)
01215   {
01216   }
01217 
01218 
01219   /*****************
01220    * OTHER METHODS *
01221    *****************/
01222 
01223 
01225 
01228   template <class T, class Prop, class Allocator>
01229   template <class T0>
01230   Matrix<T, Prop, ColHerm, Allocator>&
01231   Matrix<T, Prop, ColHerm, Allocator>::operator= (const T0& x)
01232   {
01233     this->Fill(x);
01234 
01235     return *this;
01236   }
01237 
01239 
01244   template <class T, class Prop, class Allocator>
01245   inline Matrix<T, Prop, ColHerm, Allocator>&
01246   Matrix<T, Prop, ColHerm, Allocator>::operator= (const Matrix<T, Prop,
01247                                                   ColHerm,
01248                                                   Allocator>& A)
01249   {
01250     this->Copy(A);
01251     return *this;
01252   }
01253 
01254 
01256 
01261   template <class T, class Prop, class Allocator>
01262   template <class T0>
01263   Matrix<T, Prop, ColHerm, Allocator>&
01264   Matrix<T, Prop, ColHerm, Allocator>::operator*= (const T0& x)
01265   {
01266     for (int i = 0; i < this->GetDataSize();i++)
01267       this->data_[i] *= x;
01268 
01269     return *this;
01270   }
01271 
01272 
01273 
01275   // MATRIX<ROWHERM> //
01277 
01278 
01279   /****************
01280    * CONSTRUCTORS *
01281    ****************/
01282 
01283 
01285 
01288   template <class T, class Prop, class Allocator>
01289   Matrix<T, Prop, RowHerm, Allocator>::Matrix():
01290     Matrix_Hermitian<T, Prop, RowHerm, Allocator>()
01291   {
01292   }
01293 
01294 
01296 
01300   template <class T, class Prop, class Allocator>
01301   Matrix<T, Prop, RowHerm, Allocator>::Matrix(int i, int j):
01302     Matrix_Hermitian<T, Prop, RowHerm, Allocator>(i, j)
01303   {
01304   }
01305 
01306 
01307   /*****************
01308    * OTHER METHODS *
01309    *****************/
01310 
01311 
01313 
01316   template <class T, class Prop, class Allocator>
01317   template <class T0>
01318   Matrix<T, Prop, RowHerm, Allocator>&
01319   Matrix<T, Prop, RowHerm, Allocator>::operator= (const T0& x)
01320   {
01321     this->Fill(x);
01322 
01323     return *this;
01324   }
01325 
01327 
01332   template <class T, class Prop, class Allocator>
01333   inline Matrix<T, Prop, RowHerm, Allocator>&
01334   Matrix<T, Prop, RowHerm, Allocator>::operator= (const Matrix<T, Prop,
01335                                                        RowHerm,
01336                                                        Allocator>& A)
01337   {
01338     this->Copy(A);
01339     return *this;
01340   }
01341 
01342 
01344 
01347   template <class T, class Prop, class Allocator>
01348   template <class T0>
01349   Matrix<T, Prop, RowHerm, Allocator>&
01350   Matrix<T, Prop, RowHerm, Allocator>::operator*= (const T0& x)
01351   {
01352     for (int i = 0; i < this->GetDataSize();i++)
01353       this->data_[i] *= x;
01354 
01355     return *this;
01356   }
01357 
01358 } // namespace Seldon.
01359 
01360 #define SELDON_FILE_MATRIX_HERMITIAN_CXX
01361 #endif