matrix/Matrix_Pointers.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_POINTERS_CXX
00022 
00023 #include "Matrix_Pointers.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_Pointers<T, Prop, Storage, Allocator>::Matrix_Pointers():
00040     Matrix_Base<T, Allocator>()
00041   {
00042     me_ = NULL;
00043   }
00044 
00045 
00047 
00051   template <class T, class Prop, class Storage, class Allocator>
00052   inline Matrix_Pointers<T, Prop, Storage, Allocator>
00053   ::Matrix_Pointers(int i, int j): Matrix_Base<T, Allocator>(i, j)
00054   {
00055 
00056 #ifdef SELDON_CHECK_MEMORY
00057     try
00058       {
00059 #endif
00060 
00061         me_ = reinterpret_cast<pointer*>( calloc(Storage::GetFirst(i, j),
00062                                                  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 && i != 0 && j != 0)
00074       throw NoMemory("Matrix_Pointers::Matrix_Pointers(int, int)",
00075                      string("Unable to allocate memory for a matrix of size ")
00076                      + to_str(static_cast<long int>(i)
00077                               * static_cast<long int>(j)
00078                               * static_cast<long int>(sizeof(T)))
00079                      + " bytes (" + to_str(i) + " x " + to_str(j)
00080                      + " elements).");
00081 #endif
00082 
00083 #ifdef SELDON_CHECK_MEMORY
00084     try
00085       {
00086 #endif
00087 
00088         this->data_ = this->allocator_.allocate(i * j, this);
00089 
00090 #ifdef SELDON_CHECK_MEMORY
00091       }
00092     catch (...)
00093       {
00094         this->m_ = 0;
00095         this->n_ = 0;
00096         free(me_);
00097         me_ = NULL;
00098         this->data_ = NULL;
00099       }
00100     if (this->data_ == NULL && i != 0 && j != 0)
00101       throw NoMemory("Matrix_Pointers::Matrix_Pointers(int, int)",
00102                      string("Unable to allocate memory for a matrix of size ")
00103                      + to_str(static_cast<long int>(i)
00104                               * static_cast<long int>(j)
00105                               * static_cast<long int>(sizeof(T)))
00106                      + " bytes (" + to_str(i) + " x " + to_str(j)
00107                      + " elements).");
00108 #endif
00109 
00110     pointer ptr = this->data_;
00111     int lgth = Storage::GetSecond(i, j);
00112     for (int k = 0; k < Storage::GetFirst(i, j); k++, ptr += lgth)
00113       me_[k] = ptr;
00114 
00115   }
00116 
00117 
00119   template <class T, class Prop, class Storage, class Allocator>
00120   inline Matrix_Pointers<T, Prop, Storage, Allocator>
00121   ::Matrix_Pointers(const Matrix_Pointers<T, Prop, Storage, Allocator>& A):
00122     Matrix_Base<T, Allocator>(A)
00123   {
00124     this->m_ = 0;
00125     this->n_ = 0;
00126     this->data_ = NULL;
00127     this->me_ = NULL;
00128 
00129     this->Copy(A);
00130   }
00131 
00132 
00133   /**************
00134    * DESTRUCTOR *
00135    **************/
00136 
00137 
00139   template <class T, class Prop, class Storage, class Allocator>
00140   inline Matrix_Pointers<T, Prop, Storage, Allocator>::~Matrix_Pointers()
00141   {
00142 
00143 #ifdef SELDON_CHECK_MEMORY
00144     try
00145       {
00146 #endif
00147 
00148         if (this->data_ != NULL)
00149           {
00150             this->allocator_.deallocate(this->data_, this->m_ * this->n_);
00151             this->data_ = NULL;
00152           }
00153 
00154 #ifdef SELDON_CHECK_MEMORY
00155       }
00156     catch (...)
00157       {
00158         this->data_ = NULL;
00159       }
00160 #endif
00161 
00162 #ifdef SELDON_CHECK_MEMORY
00163     try
00164       {
00165 #endif
00166 
00167         if (me_ != NULL)
00168           {
00169             free(me_);
00170             me_ = NULL;
00171           }
00172 
00173 #ifdef SELDON_CHECK_MEMORY
00174       }
00175     catch (...)
00176       {
00177         this->m_ = 0;
00178         this->n_ = 0;
00179         me_ = NULL;
00180       }
00181 #endif
00182 
00183   }
00184 
00185 
00187 
00191   template <class T, class Prop, class Storage, class Allocator>
00192   inline void Matrix_Pointers<T, Prop, Storage, Allocator>::Clear()
00193   {
00194     this->~Matrix_Pointers();
00195     this->m_ = 0;
00196     this->n_ = 0;
00197   }
00198 
00199 
00200   /*******************
00201    * BASIC FUNCTIONS *
00202    *******************/
00203 
00204 
00206 
00212   template <class T, class Prop, class Storage, class Allocator>
00213   int Matrix_Pointers<T, Prop, Storage, Allocator>::GetDataSize() const
00214   {
00215     return this->m_ * this->n_;
00216   }
00217 
00218 
00220 
00225   template <class T, class Prop, class Storage, class Allocator>
00226   typename
00227   Matrix_Pointers<T, Prop, Storage, Allocator>::pointer*
00228   Matrix_Pointers<T, Prop, Storage, Allocator>::GetMe() const
00229   {
00230     return me_;
00231   }
00232 
00233 
00234   /*********************
00235    * MEMORY MANAGEMENT *
00236    *********************/
00237 
00238 
00240 
00246   template <class T, class Prop, class Storage, class Allocator>
00247   inline void Matrix_Pointers<T, Prop, Storage, Allocator>
00248   ::Reallocate(int i, int j)
00249   {
00250 
00251     if (i != this->m_ || j != this->n_)
00252       {
00253         this->m_ = i;
00254         this->n_ = j;
00255 
00256 #ifdef SELDON_CHECK_MEMORY
00257         try
00258           {
00259 #endif
00260 
00261             me_ = reinterpret_cast<pointer*>( realloc(me_,
00262                                                       Storage::GetFirst(i, j)
00263                                                       * sizeof(pointer)) );
00264 
00265 #ifdef SELDON_CHECK_MEMORY
00266           }
00267         catch (...)
00268           {
00269             this->m_ = 0;
00270             this->n_ = 0;
00271             me_ = NULL;
00272             this->data_ = NULL;
00273           }
00274         if (me_ == NULL && i != 0 && j != 0)
00275           throw NoMemory("Matrix_Pointers::Reallocate(int, int)",
00276                          string("Unable to reallocate memory for")
00277                          + " a matrix of size "
00278                          + to_str(static_cast<long int>(i)
00279                                   * static_cast<long int>(j)
00280                                   * static_cast<long int>(sizeof(T)))
00281                          + " bytes (" + to_str(i) + " x " + to_str(j)
00282                          + " elements).");
00283 #endif
00284 
00285 #ifdef SELDON_CHECK_MEMORY
00286         try
00287           {
00288 #endif
00289 
00290             this->data_ =
00291               reinterpret_cast<pointer>(this->allocator_
00292                                         .reallocate(this->data_, i * j,
00293                                                     this));
00294 
00295 #ifdef SELDON_CHECK_MEMORY
00296           }
00297         catch (...)
00298           {
00299             this->m_ = 0;
00300             this->n_ = 0;
00301             free(me_);
00302             me_ = NULL;
00303             this->data_ = NULL;
00304           }
00305         if (this->data_ == NULL && i != 0 && j != 0)
00306           throw NoMemory("Matrix_Pointers::Reallocate(int, int)",
00307                          string("Unable to reallocate memory")
00308                          + " for a matrix of size "
00309                          + to_str(static_cast<long int>(i)
00310                                   * static_cast<long int>(j)
00311                                   * static_cast<long int>(sizeof(T)))
00312                          + " bytes (" + to_str(i) + " x " + to_str(j)
00313                          + " elements).");
00314 #endif
00315 
00316         pointer ptr = this->data_;
00317         int lgth = Storage::GetSecond(i, j);
00318         for (int k = 0; k < Storage::GetFirst(i, j); k++, ptr += lgth)
00319           me_[k] = ptr;
00320       }
00321   }
00322 
00323 
00326 
00340   template <class T, class Prop, class Storage, class Allocator>
00341   inline void Matrix_Pointers<T, Prop, Storage, Allocator>
00342   ::SetData(int i, int j,
00343             typename Matrix_Pointers<T, Prop, Storage, Allocator>
00344             ::pointer data)
00345   {
00346     this->Clear();
00347 
00348     this->m_ = i;
00349     this->n_ = j;
00350 
00351 #ifdef SELDON_CHECK_MEMORY
00352     try
00353       {
00354 #endif
00355 
00356         me_ = reinterpret_cast<pointer*>( calloc(Storage::GetFirst(i, j),
00357                                                  sizeof(pointer)) );
00358 
00359 #ifdef SELDON_CHECK_MEMORY
00360       }
00361     catch (...)
00362       {
00363         this->m_ = 0;
00364         this->n_ = 0;
00365         me_ = NULL;
00366         this->data_ = NULL;
00367         return;
00368       }
00369     if (me_ == NULL)
00370       {
00371         this->m_ = 0;
00372         this->n_ = 0;
00373         this->data_ = NULL;
00374         return;
00375       }
00376 #endif
00377 
00378     this->data_ = data;
00379 
00380     pointer ptr = this->data_;
00381     int lgth = Storage::GetSecond(i, j);
00382     for (int k = 0; k < Storage::GetFirst(i, j); k++, ptr += lgth)
00383       me_[k] = ptr;
00384   }
00385 
00386 
00388 
00393   template <class T, class Prop, class Storage, class Allocator>
00394   inline void Matrix_Pointers<T, Prop, Storage, Allocator>::Nullify()
00395   {
00396     this->m_ = 0;
00397     this->n_ = 0;
00398 
00399 #ifdef SELDON_CHECK_MEMORY
00400     try
00401       {
00402 #endif
00403 
00404         if (me_ != NULL)
00405           {
00406             free(me_);
00407             me_ = NULL;
00408           }
00409 
00410 #ifdef SELDON_CHECK_MEMORY
00411       }
00412     catch (...)
00413       {
00414         this->m_ = 0;
00415         this->n_ = 0;
00416         me_ = NULL;
00417       }
00418 #endif
00419 
00420     this->data_ = NULL;
00421   }
00422 
00423 
00425 
00432   template <class T, class Prop, class Storage, class Allocator>
00433   inline void Matrix_Pointers<T, Prop, Storage, Allocator>
00434   ::Resize(int i, int j)
00435   {
00436 
00437     if (i == this->m_ && j == this->n_)
00438       return;
00439 
00440     // Storing the old values of the matrix.
00441     int iold = Storage::GetFirst(this->m_, this->n_);
00442     int jold = Storage::GetSecond(this->m_, this->n_);
00443     Vector<value_type, VectFull, Allocator> xold(this->GetDataSize());
00444     for (int k = 0; k < this->GetDataSize(); k++)
00445       xold(k) = this->data_[k];
00446 
00447     // Reallocation.
00448     int inew = Storage::GetFirst(i, j);
00449     int jnew = Storage::GetSecond(i, j);
00450     this->Reallocate(i,j);
00451 
00452     // Filling the matrix with its old values.
00453     int imin = min(iold, inew), jmin = min(jold, jnew);
00454     for (int k = 0; k < imin; k++)
00455       for (int l = 0; l < jmin; l++)
00456         this->data_[k*jnew+l] = xold(l+jold*k);
00457   }
00458 
00459 
00460   /**********************************
00461    * ELEMENT ACCESS AND AFFECTATION *
00462    **********************************/
00463 
00464 
00466 
00472   template <class T, class Prop, class Storage, class Allocator>
00473   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>::reference
00474   Matrix_Pointers<T, Prop, Storage, Allocator>::operator() (int i, int j)
00475   {
00476 
00477 #ifdef SELDON_CHECK_BOUNDS
00478     if (i < 0 || i >= this->m_)
00479       throw WrongRow("Matrix_Pointers::operator()",
00480                      string("Index should be in [0, ")
00481                      + to_str(this->m_-1) + "], but is equal to "
00482                      + to_str(i) + ".");
00483     if (j < 0 || j >= this->n_)
00484       throw WrongCol("Matrix_Pointers::operator()",
00485                      string("Index should be in [0, ")
00486                      + to_str(this->n_-1) + "], but is equal to "
00487                      + to_str(j) + ".");
00488 #endif
00489 
00490     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00491   }
00492 
00493 
00495 
00501   template <class T, class Prop, class Storage, class Allocator>
00502   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>
00503   ::const_reference Matrix_Pointers<T, Prop, Storage, Allocator>
00504   ::operator() (int i, int j) const
00505   {
00506 
00507 #ifdef SELDON_CHECK_BOUNDS
00508     if (i < 0 || i >= this->m_)
00509       throw WrongRow("Matrix_Pointers::operator()",
00510                      string("Index should be in [0, ")
00511                      + to_str(this->m_-1) + "], but is equal to "
00512                      + to_str(i) + ".");
00513     if (j < 0 || j >= this->n_)
00514       throw WrongCol("Matrix_Pointers::operator()",
00515                      string("Index should be in [0, ")
00516                      + to_str(this->n_-1) + "], but is equal to "
00517                      + to_str(j) + ".");
00518 #endif
00519 
00520     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00521   }
00522 
00523 
00525 
00531   template <class T, class Prop, class Storage, class Allocator>
00532   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>::reference
00533   Matrix_Pointers<T, Prop, Storage, Allocator>::Val(int i, int j)
00534   {
00535 
00536 #ifdef SELDON_CHECK_BOUNDS
00537     if (i < 0 || i >= this->m_)
00538       throw WrongRow("Matrix_Pointers::Val(int, int)",
00539                      string("Index should be in [0, ") + to_str(this->m_-1)
00540                      + "], but is equal to " + to_str(i) + ".");
00541     if (j < 0 || j >= this->n_)
00542       throw WrongCol("Matrix_Pointers::Val(int, int)",
00543                      string("Index should be in [0, ") + to_str(this->n_-1)
00544                      + "], but is equal to " + to_str(j) + ".");
00545 #endif
00546 
00547     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00548   }
00549 
00550 
00552 
00558   template <class T, class Prop, class Storage, class Allocator>
00559   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>::reference
00560   Matrix_Pointers<T, Prop, Storage, Allocator>::Get(int i, int j)
00561   {
00562     return Val(i, j);
00563   }
00564 
00565 
00567 
00573   template <class T, class Prop, class Storage, class Allocator>
00574   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>
00575   ::const_reference
00576   Matrix_Pointers<T, Prop, Storage, Allocator>::Val(int i, int j) const
00577   {
00578 
00579 #ifdef SELDON_CHECK_BOUNDS
00580     if (i < 0 || i >= this->m_)
00581       throw WrongRow("Matrix_Pointers::Val(int, int) const",
00582                      string("Index should be in [0, ") + to_str(this->m_-1)
00583                      + "], but is equal to " + to_str(i) + ".");
00584     if (j < 0 || j >= this->n_)
00585       throw WrongCol("Matrix_Pointers::Val(int, int) const",
00586                      string("Index should be in [0, ") + to_str(this->n_-1)
00587                      + "], but is equal to " + to_str(j) + ".");
00588 #endif
00589 
00590     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00591   }
00592 
00593 
00595 
00601   template <class T, class Prop, class Storage, class Allocator>
00602   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>
00603   ::const_reference
00604   Matrix_Pointers<T, Prop, Storage, Allocator>::Get(int i, int j) const
00605   {
00606     return Val(i, j);
00607   }
00608 
00609 
00611 
00616   template <class T, class Prop, class Storage, class Allocator>
00617   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>::reference
00618   Matrix_Pointers<T, Prop, Storage, Allocator>::operator[] (int i)
00619   {
00620 
00621 #ifdef SELDON_CHECK_BOUNDS
00622     if (i < 0 || i >= this->GetDataSize())
00623       throw WrongIndex("Matrix_Pointers::operator[] (int)",
00624                        string("Index should be in [0, ")
00625                        + to_str(this->GetDataSize()-1) + "], but is equal to "
00626                        + to_str(i) + ".");
00627 #endif
00628 
00629     return this->data_[i];
00630   }
00631 
00632 
00634 
00639   template <class T, class Prop, class Storage, class Allocator>
00640   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>
00641   ::const_reference
00642   Matrix_Pointers<T, Prop, Storage, Allocator>::operator[] (int i) const
00643   {
00644 
00645 #ifdef SELDON_CHECK_BOUNDS
00646     if (i < 0 || i >= this->GetDataSize())
00647       throw WrongIndex("Matrix_Pointers::operator[] (int) const",
00648                        string("Index should be in [0, ")
00649                        + to_str(this->GetDataSize()-1) + "], but is equal to "
00650                        + to_str(i) + ".");
00651 #endif
00652 
00653     return this->data_[i];
00654   }
00655 
00656 
00658 
00663   template <class T, class Prop, class Storage, class Allocator>
00664   inline void Matrix_Pointers<T, Prop, Storage, Allocator>
00665   ::Set(int i, int j, const T& val)
00666   {
00667     this->Val(i, j) = val;
00668   }
00669 
00670 
00672 
00677   template <class T, class Prop, class Storage, class Allocator>
00678   inline Matrix_Pointers<T, Prop, Storage, Allocator>&
00679   Matrix_Pointers<T, Prop, Storage, Allocator>
00680   ::operator= (const Matrix_Pointers<T, Prop, Storage, Allocator>& A)
00681   {
00682     this->Copy(A);
00683 
00684     return *this;
00685   }
00686 
00687 
00689 
00694   template <class T, class Prop, class Storage, class Allocator>
00695   inline void Matrix_Pointers<T, Prop, Storage, Allocator>
00696   ::Copy(const Matrix_Pointers<T, Prop, Storage, Allocator>& A)
00697   {
00698     this->Reallocate(A.GetM(), A.GetN());
00699 
00700     this->allocator_.memorycpy(this->data_, A.GetData(), this->GetDataSize());
00701   }
00702 
00703 
00704   /************************
00705    * CONVENIENT FUNCTIONS *
00706    ************************/
00707 
00708 
00710 
00713   template <class T, class Prop, class Storage, class Allocator>
00714   int Matrix_Pointers<T, Prop, Storage, Allocator>::GetLD() const
00715   {
00716     return Storage::GetSecond(this->m_, this->n_);
00717   }
00718 
00719 
00721 
00725   template <class T, class Prop, class Storage, class Allocator>
00726   void Matrix_Pointers<T, Prop, Storage, Allocator>::Zero()
00727   {
00728     this->allocator_.memoryset(this->data_, char(0),
00729                                this->GetDataSize() * sizeof(value_type));
00730   }
00731 
00732 
00734   template <class T, class Prop, class Storage, class Allocator>
00735   void Matrix_Pointers<T, Prop, Storage, Allocator>::SetIdentity()
00736   {
00737     Fill(T(0));
00738 
00739     T one(1);
00740     for (int i = 0; i < min(this->m_, this->n_); i++)
00741       (*this)(i,i) = one;
00742   }
00743 
00744 
00746 
00750   template <class T, class Prop, class Storage, class Allocator>
00751   void Matrix_Pointers<T, Prop, Storage, Allocator>::Fill()
00752   {
00753     for (int i = 0; i < this->GetDataSize(); i++)
00754       this->data_[i] = i;
00755   }
00756 
00757 
00759 
00762   template <class T, class Prop, class Storage, class Allocator>
00763   template <class T0>
00764   void Matrix_Pointers<T, Prop, Storage, Allocator>::Fill(const T0& x)
00765   {
00766     for (int i = 0; i < this->GetDataSize(); i++)
00767       this->data_[i] = x;
00768   }
00769 
00770 
00772 
00775   template <class T, class Prop, class Storage, class Allocator>
00776   template <class T0>
00777   Matrix_Pointers<T, Prop, Storage, Allocator>&
00778   Matrix_Pointers<T, Prop, Storage, Allocator>::operator= (const T0& x)
00779   {
00780     this->Fill(x);
00781 
00782     return *this;
00783   }
00784 
00785 
00787 
00790   template <class T, class Prop, class Storage, class Allocator>
00791   void Matrix_Pointers<T, Prop, Storage, Allocator>::FillRand()
00792   {
00793     srand(time(NULL));
00794     for (int i = 0; i < this->GetDataSize(); i++)
00795       this->data_[i] = rand();
00796   }
00797 
00798 
00800 
00805   template <class T, class Prop, class Storage, class Allocator>
00806   void Matrix_Pointers<T, Prop, Storage, Allocator>::Print() const
00807   {
00808     for (int i = 0; i < this->m_; i++)
00809       {
00810         for (int j = 0; j < this->n_; j++)
00811           cout << (*this)(i, j) << "\t";
00812         cout << endl;
00813       }
00814   }
00815 
00816 
00818 
00829   template <class T, class Prop, class Storage, class Allocator>
00830   void Matrix_Pointers<T, Prop, Storage, Allocator>::Print(int a, int b,
00831                                                            int m, int n) const
00832   {
00833     for (int i = a; i < min(this->m_, a+m); i++)
00834       {
00835         for (int j = b; j < min(this->n_, b+n); j++)
00836           cout << (*this)(i, j) << "\t";
00837         cout << endl;
00838       }
00839   }
00840 
00841 
00843 
00851   template <class T, class Prop, class Storage, class Allocator>
00852   void Matrix_Pointers<T, Prop, Storage, Allocator>::Print(int l) const
00853   {
00854     Print(0, 0, l, l);
00855   }
00856 
00857 
00858   /**************************
00859    * INPUT/OUTPUT FUNCTIONS *
00860    **************************/
00861 
00862 #ifdef SELDON_WITH_HDF5
00863 
00864 
00871  template <class T, class Prop, class Storage, class Allocator>
00872   void Matrix_Pointers<T, Prop, Storage, Allocator>
00873  ::WriteHDF5(string FileName, string group_name, string dataset_name) const
00874   {
00875     throw IOError("Matrix_Pointers::WriteHDF5(string FileName)",
00876                   string("Unable to write matrix in \"") + FileName + "\".");
00877   }
00878 #endif
00879 
00880 
00882 
00891   template <class T, class Prop, class Storage, class Allocator>
00892   void Matrix_Pointers<T, Prop, Storage, Allocator>
00893   ::Write(string FileName, bool with_size) const
00894   {
00895     ofstream FileStream;
00896     FileStream.open(FileName.c_str(), ofstream::binary);
00897 
00898 #ifdef SELDON_CHECK_IO
00899     // Checks if the file was opened.
00900     if (!FileStream.is_open())
00901       throw IOError("Matrix_Pointers::Write(string FileName)",
00902                     string("Unable to open file \"") + FileName + "\".");
00903 #endif
00904 
00905     this->Write(FileStream, with_size);
00906 
00907     FileStream.close();
00908   }
00909 
00910 
00912 
00921   template <class T, class Prop, class Storage, class Allocator>
00922   void Matrix_Pointers<T, Prop, Storage, Allocator>
00923   ::Write(ostream& FileStream, bool with_size) const
00924   {
00925 
00926 #ifdef SELDON_CHECK_IO
00927     // Checks if the stream is ready.
00928     if (!FileStream.good())
00929       throw IOError("Matrix_Pointers::Write(ostream& FileStream)",
00930                     "The stream is not ready.");
00931 #endif
00932 
00933     if (with_size)
00934       {
00935         FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
00936                          sizeof(int));
00937         FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->n_)),
00938                          sizeof(int));
00939       }
00940 
00941     FileStream.write(reinterpret_cast<char*>(this->data_),
00942                      this->m_ * this->n_ * sizeof(value_type));
00943 
00944 #ifdef SELDON_CHECK_IO
00945     // Checks if data was written.
00946     if (!FileStream.good())
00947       throw IOError("Matrix_Pointers::Write(ostream& FileStream)",
00948                     "Output operation failed.");
00949 #endif
00950 
00951   }
00952 
00953 
00955 
00962   template <class T, class Prop, class Storage, class Allocator>
00963   void Matrix_Pointers<T, Prop, Storage, Allocator>
00964   ::WriteText(string FileName) const
00965   {
00966     ofstream FileStream;
00967     FileStream.precision(cout.precision());
00968     FileStream.flags(cout.flags());
00969     FileStream.open(FileName.c_str());
00970 
00971 #ifdef SELDON_CHECK_IO
00972     // Checks if the file was opened.
00973     if (!FileStream.is_open())
00974       throw IOError("Matrix_Pointers::WriteText(string FileName)",
00975                     string("Unable to open file \"") + FileName + "\".");
00976 #endif
00977 
00978     this->WriteText(FileStream);
00979 
00980     FileStream.close();
00981   }
00982 
00983 
00985 
00992   template <class T, class Prop, class Storage, class Allocator>
00993   void Matrix_Pointers<T, Prop, Storage, Allocator>
00994   ::WriteText(ostream& FileStream) const
00995   {
00996 
00997 #ifdef SELDON_CHECK_IO
00998     // Checks if the file is ready.
00999     if (!FileStream.good())
01000       throw IOError("Matrix_Pointers::WriteText(ostream& FileStream)",
01001                     "The stream is not ready.");
01002 #endif
01003 
01004     int i, j;
01005     for (i = 0; i < this->GetM(); i++)
01006       {
01007         for (j = 0; j < this->GetN(); j++)
01008           FileStream << (*this)(i, j) << '\t';
01009         FileStream << endl;
01010       }
01011 
01012 #ifdef SELDON_CHECK_IO
01013     // Checks if data was written.
01014     if (!FileStream.good())
01015       throw IOError("Matrix_Pointers::WriteText(ostream& FileStream)",
01016                     "Output operation failed.");
01017 #endif
01018 
01019   }
01020 
01021 
01023 
01033   template <class T, class Prop, class Storage, class Allocator>
01034   void Matrix_Pointers<T, Prop, Storage, Allocator>
01035   ::Read(string FileName, bool with_size)
01036   {
01037     ifstream FileStream;
01038     FileStream.open(FileName.c_str(), ifstream::binary);
01039 
01040 #ifdef SELDON_CHECK_IO
01041     // Checks if the file was opened.
01042     if (!FileStream.is_open())
01043       throw IOError("Matrix_Pointers::Read(string FileName)",
01044                     string("Unable to open file \"") + FileName + "\".");
01045 #endif
01046 
01047     this->Read(FileStream, with_size);
01048 
01049     FileStream.close();
01050   }
01051 
01052 
01054 
01064   template <class T, class Prop, class Storage, class Allocator>
01065   void Matrix_Pointers<T, Prop, Storage, Allocator>
01066   ::Read(istream& FileStream, bool with_size)
01067   {
01068 
01069 #ifdef SELDON_CHECK_IO
01070     // Checks if the stream is ready.
01071     if (!FileStream.good())
01072       throw IOError("Matrix_Pointers::Read(istream& FileStream)",
01073                     "The stream is not ready.");
01074 #endif
01075 
01076     if (with_size)
01077       {
01078         int new_m, new_n;
01079         FileStream.read(reinterpret_cast<char*>(&new_m), sizeof(int));
01080         FileStream.read(reinterpret_cast<char*>(&new_n), sizeof(int));
01081         this->Reallocate(new_m, new_n);
01082       }
01083 
01084     FileStream.read(reinterpret_cast<char*>(this->data_),
01085                     this->GetM() * this->GetN() * sizeof(value_type));
01086 
01087 #ifdef SELDON_CHECK_IO
01088     // Checks if data was read.
01089     if (!FileStream.good())
01090       throw IOError("Matrix_Pointers::Read(istream& FileStream)",
01091                     "Input operation failed.");
01092 #endif
01093 
01094   }
01095 
01096 
01098 
01102   template <class T, class Prop, class Storage, class Allocator>
01103   void Matrix_Pointers<T, Prop, Storage, Allocator>::ReadText(string FileName)
01104   {
01105     ifstream FileStream;
01106     FileStream.open(FileName.c_str());
01107 
01108 #ifdef SELDON_CHECK_IO
01109     // Checks if the file was opened.
01110     if (!FileStream.is_open())
01111       throw IOError("Matrix_Pointers::ReadText(string FileName)",
01112                     string("Unable to open file \"") + FileName + "\".");
01113 #endif
01114 
01115     this->ReadText(FileStream);
01116 
01117     FileStream.close();
01118   }
01119 
01120 
01122 
01126   template <class T, class Prop, class Storage, class Allocator>
01127   void Matrix_Pointers<T, Prop, Storage, Allocator>
01128   ::ReadText(istream& FileStream)
01129   {
01130     // Clears the matrix.
01131     Clear();
01132 
01133 #ifdef SELDON_CHECK_IO
01134     // Checks if the stream is ready.
01135     if (!FileStream.good())
01136       throw IOError("Matrix_Pointers::ReadText(istream& FileStream)",
01137                     "The stream is not ready.");
01138 #endif
01139 
01140     // Reads the first line.
01141     string line;
01142     getline(FileStream, line);
01143     if (FileStream.fail())
01144       // Is the file empty?
01145       return;
01146 
01147     // Converts the first line into a vector.
01148     istringstream line_stream(line);
01149     Vector<T> first_row;
01150     first_row.ReadText(line_stream);
01151 
01152     // Now reads all other rows, and puts them in a single vector.
01153     Vector<T> other_row;
01154     other_row.ReadText(FileStream);
01155 
01156     // Number of rows and columns.
01157     int n = first_row.GetM();
01158     int m = 1 + other_row.GetM() / n;
01159 
01160 #ifdef SELDON_CHECK_IO
01161     // Checks that enough elements were read.
01162     if (other_row.GetM() != (m - 1) * n)
01163       throw IOError("Matrix_Pointers::ReadText(istream& FileStream)",
01164                     "Not all rows have the same number of columns.");
01165 #endif
01166 
01167     this->Reallocate(m, n);
01168     // Fills the matrix.
01169     for (int j = 0; j < n; j++)
01170       this->Val(0, j) = first_row(j);
01171 
01172     int k = 0;
01173     for (int i = 1; i < m; i++)
01174       for (int j = 0; j < n; j++)
01175         this->Val(i, j) = other_row(k++);
01176   }
01177 
01178 
01180   // MATRIX<COLMAJOR> //
01182 
01183 
01184   /****************
01185    * CONSTRUCTORS *
01186    ****************/
01187 
01188 
01190 
01193   template <class T, class Prop, class Allocator>
01194   Matrix<T, Prop, ColMajor, Allocator>::Matrix():
01195     Matrix_Pointers<T, Prop, ColMajor, Allocator>()
01196   {
01197   }
01198 
01199 
01201 
01205   template <class T, class Prop, class Allocator>
01206   Matrix<T, Prop, ColMajor, Allocator>::Matrix(int i, int j):
01207     Matrix_Pointers<T, Prop, ColMajor, Allocator>(i, j)
01208   {
01209   }
01210 
01211 
01213   template <class T, class Prop, class Allocator>
01214   Matrix<T, Prop, ColMajor, Allocator>
01215   ::Matrix(const Matrix<T, Prop, ColMajor, Allocator>& A):
01216     Matrix_Pointers<T, Prop, ColMajor, Allocator>(A)
01217   {
01218   }
01219 
01220 
01221   /*****************
01222    * OTHER METHODS *
01223    *****************/
01224 
01225 
01227 
01230   template <class T, class Prop, class Allocator>
01231   template <class T0>
01232   Matrix<T, Prop, ColMajor, Allocator>&
01233   Matrix<T, Prop, ColMajor, Allocator>::operator= (const T0& x)
01234   {
01235     this->Fill(x);
01236 
01237     return *this;
01238   }
01239 
01240 
01242 
01247   template <class T, class Prop, class Allocator>
01248   inline Matrix<T, Prop, ColMajor, Allocator>&
01249   Matrix<T, Prop, ColMajor, Allocator>
01250   ::operator= (const Matrix<T, Prop, ColMajor, Allocator>& A)
01251   {
01252     this->Copy(A);
01253 
01254     return *this;
01255   }
01256 
01257 
01259 
01262   template <class T, class Prop, class Allocator> template<class T0>
01263   inline Matrix<T, Prop, ColMajor, Allocator>&
01264   Matrix<T, Prop, ColMajor, Allocator>::operator*= (const T0& alpha)
01265   {
01266     for (int i = 0; i < this->m_ * this->n_; i++)
01267       this->data_[i] *= alpha;
01268 
01269     return *this;
01270   }
01271 
01272 
01274   // MATRIX<ROWMAJOR> //
01276 
01277 
01278   /****************
01279    * CONSTRUCTORS *
01280    ****************/
01281 
01282 
01284 
01287   template <class T, class Prop, class Allocator>
01288   Matrix<T, Prop, RowMajor, Allocator>::Matrix():
01289     Matrix_Pointers<T, Prop, RowMajor, Allocator>()
01290   {
01291   }
01292 
01293 
01295 
01299   template <class T, class Prop, class Allocator>
01300   Matrix<T, Prop, RowMajor, Allocator>::Matrix(int i, int j):
01301     Matrix_Pointers<T, Prop, RowMajor, Allocator>(i, j)
01302   {
01303   }
01304 
01305 
01307   template <class T, class Prop, class Allocator>
01308   Matrix<T, Prop, RowMajor, Allocator>
01309   ::Matrix(const Matrix<T, Prop, RowMajor, Allocator>& A):
01310     Matrix_Pointers<T, Prop, RowMajor, Allocator>(A)
01311   {
01312   }
01313 
01314 
01315   /*****************
01316    * OTHER METHODS *
01317    *****************/
01318 
01319 
01321 
01324   template <class T, class Prop, class Allocator>
01325   template <class T0>
01326   Matrix<T, Prop, RowMajor, Allocator>&
01327   Matrix<T, Prop, RowMajor, Allocator>::operator= (const T0& x)
01328   {
01329     this->Fill(x);
01330 
01331     return *this;
01332   }
01333 
01334 
01336 
01341   template <class T, class Prop, class Allocator>
01342   inline Matrix<T, Prop, RowMajor, Allocator>&
01343   Matrix<T, Prop, RowMajor, Allocator>
01344   ::operator= (const Matrix<T, Prop, RowMajor, Allocator>& A)
01345   {
01346     this->Copy(A);
01347 
01348     return *this;
01349   }
01350 
01351 
01353 
01356   template <class T, class Prop, class Allocator> template<class T0>
01357   inline Matrix<T, Prop, RowMajor, Allocator>&
01358   Matrix<T, Prop, RowMajor, Allocator>::operator*= (const T0& alpha)
01359   {
01360     for (int i = 0; i < this->m_*this->n_; i++)
01361       this->data_[i] *= alpha;
01362 
01363     return *this;
01364   }
01365 
01366 
01367 } // namespace Seldon.
01368 
01369 #define SELDON_FILE_MATRIX_POINTERS_CXX
01370 #endif