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 
00219   /*********************
00220    * MEMORY MANAGEMENT *
00221    *********************/
00222 
00223 
00225 
00231   template <class T, class Prop, class Storage, class Allocator>
00232   inline void Matrix_Pointers<T, Prop, Storage, Allocator>
00233   ::Reallocate(int i, int j)
00234   {
00235 
00236     if (i != this->m_ || j != this->n_)
00237       {
00238         this->m_ = i;
00239         this->n_ = j;
00240 
00241 #ifdef SELDON_CHECK_MEMORY
00242         try
00243           {
00244 #endif
00245 
00246             me_ = reinterpret_cast<pointer*>( realloc(me_,
00247                                                       Storage::GetFirst(i, j)
00248                                                       * sizeof(pointer)) );
00249 
00250 #ifdef SELDON_CHECK_MEMORY
00251           }
00252         catch (...)
00253           {
00254             this->m_ = 0;
00255             this->n_ = 0;
00256             me_ = NULL;
00257             this->data_ = NULL;
00258           }
00259         if (me_ == NULL && i != 0 && j != 0)
00260           throw NoMemory("Matrix_Pointers::Reallocate(int, int)",
00261                          string("Unable to reallocate memory for")
00262                          + " a matrix of size "
00263                          + to_str(static_cast<long int>(i)
00264                                   * static_cast<long int>(j)
00265                                   * static_cast<long int>(sizeof(T)))
00266                          + " bytes (" + to_str(i) + " x " + to_str(j)
00267                          + " elements).");
00268 #endif
00269 
00270 #ifdef SELDON_CHECK_MEMORY
00271         try
00272           {
00273 #endif
00274 
00275             this->data_ =
00276               reinterpret_cast<pointer>(this->allocator_
00277                                         .reallocate(this->data_, i * j,
00278                                                     this));
00279 
00280 #ifdef SELDON_CHECK_MEMORY
00281           }
00282         catch (...)
00283           {
00284             this->m_ = 0;
00285             this->n_ = 0;
00286             free(me_);
00287             me_ = NULL;
00288             this->data_ = NULL;
00289           }
00290         if (this->data_ == NULL && i != 0 && j != 0)
00291           throw NoMemory("Matrix_Pointers::Reallocate(int, int)",
00292                          string("Unable to reallocate memory")
00293                          + " for a matrix of size "
00294                          + to_str(static_cast<long int>(i)
00295                                   * static_cast<long int>(j)
00296                                   * static_cast<long int>(sizeof(T)))
00297                          + " bytes (" + to_str(i) + " x " + to_str(j)
00298                          + " elements).");
00299 #endif
00300 
00301         pointer ptr = this->data_;
00302         int lgth = Storage::GetSecond(i, j);
00303         for (int k = 0; k < Storage::GetFirst(i, j); k++, ptr += lgth)
00304           me_[k] = ptr;
00305       }
00306   }
00307 
00308 
00311 
00325   template <class T, class Prop, class Storage, class Allocator>
00326   inline void Matrix_Pointers<T, Prop, Storage, Allocator>
00327   ::SetData(int i, int j,
00328             typename Matrix_Pointers<T, Prop, Storage, Allocator>
00329             ::pointer data)
00330   {
00331     this->Clear();
00332 
00333     this->m_ = i;
00334     this->n_ = j;
00335 
00336 #ifdef SELDON_CHECK_MEMORY
00337     try
00338       {
00339 #endif
00340 
00341         me_ = reinterpret_cast<pointer*>( calloc(Storage::GetFirst(i, j),
00342                                                  sizeof(pointer)) );
00343 
00344 #ifdef SELDON_CHECK_MEMORY
00345       }
00346     catch (...)
00347       {
00348         this->m_ = 0;
00349         this->n_ = 0;
00350         me_ = NULL;
00351         this->data_ = NULL;
00352         return;
00353       }
00354     if (me_ == NULL)
00355       {
00356         this->m_ = 0;
00357         this->n_ = 0;
00358         this->data_ = NULL;
00359         return;
00360       }
00361 #endif
00362 
00363     this->data_ = data;
00364 
00365     pointer ptr = this->data_;
00366     int lgth = Storage::GetSecond(i, j);
00367     for (int k = 0; k < Storage::GetFirst(i, j); k++, ptr += lgth)
00368       me_[k] = ptr;
00369   }
00370 
00371 
00373 
00378   template <class T, class Prop, class Storage, class Allocator>
00379   inline void Matrix_Pointers<T, Prop, Storage, Allocator>::Nullify()
00380   {
00381     this->m_ = 0;
00382     this->n_ = 0;
00383 
00384 #ifdef SELDON_CHECK_MEMORY
00385     try
00386       {
00387 #endif
00388 
00389         if (me_ != NULL)
00390           {
00391             free(me_);
00392             me_ = NULL;
00393           }
00394 
00395 #ifdef SELDON_CHECK_MEMORY
00396       }
00397     catch (...)
00398       {
00399         this->m_ = 0;
00400         this->n_ = 0;
00401         me_ = NULL;
00402       }
00403 #endif
00404 
00405     this->data_ = NULL;
00406   }
00407 
00408 
00410 
00417   template <class T, class Prop, class Storage, class Allocator>
00418   inline void Matrix_Pointers<T, Prop, Storage, Allocator>
00419   ::Resize(int i, int j)
00420   {
00421 
00422     // Storing the old values of the matrix.
00423     int iold = Storage::GetFirst(this->m_, this->n_);
00424     int jold = Storage::GetSecond(this->m_, this->n_);
00425     Vector<value_type, VectFull, Allocator> xold(this->GetDataSize());
00426     for (int k = 0; k < this->GetDataSize(); k++)
00427       xold(k) = this->data_[k];
00428 
00429     // Reallocation.
00430     int inew = Storage::GetFirst(i, j);
00431     int jnew = Storage::GetSecond(i, j);
00432     this->Reallocate(i,j);
00433 
00434     // Filling the matrix with its old values.
00435     int imin = min(iold, inew), jmin = min(jold, jnew);
00436     for (int k = 0; k < imin; k++)
00437       for (int l = 0; l < jmin; l++)
00438         this->data_[k*jnew+l] = xold(l+jold*k);
00439   }
00440 
00441 
00442   /**********************************
00443    * ELEMENT ACCESS AND AFFECTATION *
00444    **********************************/
00445 
00446 
00448 
00454   template <class T, class Prop, class Storage, class Allocator>
00455   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>::reference
00456   Matrix_Pointers<T, Prop, Storage, Allocator>::operator() (int i, int j)
00457   {
00458 
00459 #ifdef SELDON_CHECK_BOUNDS
00460     if (i < 0 || i >= this->m_)
00461       throw WrongRow("Matrix_Pointers::operator()",
00462                      string("Index should be in [0, ")
00463                      + to_str(this->m_-1) + "], but is equal to "
00464                      + to_str(i) + ".");
00465     if (j < 0 || j >= this->n_)
00466       throw WrongCol("Matrix_Pointers::operator()",
00467                      string("Index should be in [0, ")
00468                      + to_str(this->n_-1) + "], but is equal to "
00469                      + to_str(j) + ".");
00470 #endif
00471 
00472     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00473   }
00474 
00475 
00477 
00483   template <class T, class Prop, class Storage, class Allocator>
00484   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>
00485   ::const_reference Matrix_Pointers<T, Prop, Storage, Allocator>
00486   ::operator() (int i, int j) const
00487   {
00488 
00489 #ifdef SELDON_CHECK_BOUNDS
00490     if (i < 0 || i >= this->m_)
00491       throw WrongRow("Matrix_Pointers::operator()",
00492                      string("Index should be in [0, ")
00493                      + to_str(this->m_-1) + "], but is equal to "
00494                      + to_str(i) + ".");
00495     if (j < 0 || j >= this->n_)
00496       throw WrongCol("Matrix_Pointers::operator()",
00497                      string("Index should be in [0, ")
00498                      + to_str(this->n_-1) + "], but is equal to "
00499                      + to_str(j) + ".");
00500 #endif
00501 
00502     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00503   }
00504 
00505 
00507 
00513   template <class T, class Prop, class Storage, class Allocator>
00514   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>::reference
00515   Matrix_Pointers<T, Prop, Storage, Allocator>::Val(int i, int j)
00516   {
00517 
00518 #ifdef SELDON_CHECK_BOUNDS
00519     if (i < 0 || i >= this->m_)
00520       throw WrongRow("Matrix_Pointers::Val(int, int)",
00521                      string("Index should be in [0, ") + to_str(this->m_-1)
00522                      + "], but is equal to " + to_str(i) + ".");
00523     if (j < 0 || j >= this->n_)
00524       throw WrongCol("Matrix_Pointers::Val(int, int)",
00525                      string("Index should be in [0, ") + to_str(this->n_-1)
00526                      + "], but is equal to " + to_str(j) + ".");
00527 #endif
00528 
00529     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00530   }
00531 
00532 
00534 
00540   template <class T, class Prop, class Storage, class Allocator>
00541   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>
00542   ::const_reference
00543   Matrix_Pointers<T, Prop, Storage, Allocator>::Val(int i, int j) const
00544   {
00545 
00546 #ifdef SELDON_CHECK_BOUNDS
00547     if (i < 0 || i >= this->m_)
00548       throw WrongRow("Matrix_Pointers::Val(int, int) const",
00549                      string("Index should be in [0, ") + to_str(this->m_-1)
00550                      + "], but is equal to " + to_str(i) + ".");
00551     if (j < 0 || j >= this->n_)
00552       throw WrongCol("Matrix_Pointers::Val(int, int) const",
00553                      string("Index should be in [0, ") + to_str(this->n_-1)
00554                      + "], but is equal to " + to_str(j) + ".");
00555 #endif
00556 
00557     return me_[Storage::GetFirst(i, j)][Storage::GetSecond(i, j)];
00558   }
00559 
00560 
00562 
00567   template <class T, class Prop, class Storage, class Allocator>
00568   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>::reference
00569   Matrix_Pointers<T, Prop, Storage, Allocator>::operator[] (int i)
00570   {
00571 
00572 #ifdef SELDON_CHECK_BOUNDS
00573     if (i < 0 || i >= this->GetDataSize())
00574       throw WrongIndex("Matrix_Pointers::operator[] (int)",
00575                        string("Index should be in [0, ")
00576                        + to_str(this->GetDataSize()-1) + "], but is equal to "
00577                        + to_str(i) + ".");
00578 #endif
00579 
00580     return this->data_[i];
00581   }
00582 
00583 
00585 
00590   template <class T, class Prop, class Storage, class Allocator>
00591   inline typename Matrix_Pointers<T, Prop, Storage, Allocator>
00592   ::const_reference
00593   Matrix_Pointers<T, Prop, Storage, Allocator>::operator[] (int i) const
00594   {
00595 
00596 #ifdef SELDON_CHECK_BOUNDS
00597     if (i < 0 || i >= this->GetDataSize())
00598       throw WrongIndex("Matrix_Pointers::operator[] (int) const",
00599                        string("Index should be in [0, ")
00600                        + to_str(this->GetDataSize()-1) + "], but is equal to "
00601                        + to_str(i) + ".");
00602 #endif
00603 
00604     return this->data_[i];
00605   }
00606 
00607 
00609 
00614   template <class T, class Prop, class Storage, class Allocator>
00615   inline Matrix_Pointers<T, Prop, Storage, Allocator>&
00616   Matrix_Pointers<T, Prop, Storage, Allocator>
00617   ::operator= (const Matrix_Pointers<T, Prop, Storage, Allocator>& A)
00618   {
00619     this->Copy(A);
00620 
00621     return *this;
00622   }
00623 
00624 
00626 
00631   template <class T, class Prop, class Storage, class Allocator>
00632   inline void Matrix_Pointers<T, Prop, Storage, Allocator>
00633   ::Copy(const Matrix_Pointers<T, Prop, Storage, Allocator>& A)
00634   {
00635     this->Reallocate(A.GetM(), A.GetN());
00636 
00637     this->allocator_.memorycpy(this->data_, A.GetData(), this->GetDataSize());
00638   }
00639 
00640 
00641   /************************
00642    * CONVENIENT FUNCTIONS *
00643    ************************/
00644 
00645 
00647 
00650   template <class T, class Prop, class Storage, class Allocator>
00651   int Matrix_Pointers<T, Prop, Storage, Allocator>::GetLD() const
00652   {
00653     return Storage::GetSecond(this->m_, this->n_);
00654   }
00655 
00656 
00658 
00662   template <class T, class Prop, class Storage, class Allocator>
00663   void Matrix_Pointers<T, Prop, Storage, Allocator>::Zero()
00664   {
00665     this->allocator_.memoryset(this->data_, char(0),
00666                                this->GetDataSize() * sizeof(value_type));
00667   }
00668 
00669 
00671   template <class T, class Prop, class Storage, class Allocator>
00672   void Matrix_Pointers<T, Prop, Storage, Allocator>::SetIdentity()
00673   {
00674     Fill(T(0));
00675 
00676     T one(1);
00677     for (int i = 0; i < min(this->m_, this->n_); i++)
00678       (*this)(i,i) = one;
00679   }
00680 
00681 
00683 
00687   template <class T, class Prop, class Storage, class Allocator>
00688   void Matrix_Pointers<T, Prop, Storage, Allocator>::Fill()
00689   {
00690     for (int i = 0; i < this->GetDataSize(); i++)
00691       this->data_[i] = i;
00692   }
00693 
00694 
00696 
00699   template <class T, class Prop, class Storage, class Allocator>
00700   template <class T0>
00701   void Matrix_Pointers<T, Prop, Storage, Allocator>::Fill(const T0& x)
00702   {
00703     for (int i = 0; i < this->GetDataSize(); i++)
00704       this->data_[i] = x;
00705   }
00706 
00707 
00709 
00712   template <class T, class Prop, class Storage, class Allocator>
00713   template <class T0>
00714   Matrix_Pointers<T, Prop, Storage, Allocator>&
00715   Matrix_Pointers<T, Prop, Storage, Allocator>::operator= (const T0& x)
00716   {
00717     this->Fill(x);
00718 
00719     return *this;
00720   }
00721 
00722 
00724 
00727   template <class T, class Prop, class Storage, class Allocator>
00728   void Matrix_Pointers<T, Prop, Storage, Allocator>::FillRand()
00729   {
00730     srand(time(NULL));
00731     for (int i = 0; i < this->GetDataSize(); i++)
00732       this->data_[i] = rand();
00733   }
00734 
00735 
00737 
00742   template <class T, class Prop, class Storage, class Allocator>
00743   void Matrix_Pointers<T, Prop, Storage, Allocator>::Print() const
00744   {
00745     for (int i = 0; i < this->m_; i++)
00746       {
00747         for (int j = 0; j < this->n_; j++)
00748           cout << (*this)(i, j) << "\t";
00749         cout << endl;
00750       }
00751   }
00752 
00753 
00755 
00766   template <class T, class Prop, class Storage, class Allocator>
00767   void Matrix_Pointers<T, Prop, Storage, Allocator>::Print(int a, int b,
00768                                                            int m, int n) const
00769   {
00770     for (int i = a; i < min(this->m_, a+m); i++)
00771       {
00772         for (int j = b; j < min(this->n_, b+n); j++)
00773           cout << (*this)(i, j) << "\t";
00774         cout << endl;
00775       }
00776   }
00777 
00778 
00780 
00788   template <class T, class Prop, class Storage, class Allocator>
00789   void Matrix_Pointers<T, Prop, Storage, Allocator>::Print(int l) const
00790   {
00791     Print(0, 0, l, l);
00792   }
00793 
00794 
00795   /**************************
00796    * INPUT/OUTPUT FUNCTIONS *
00797    **************************/
00798 
00799 
00801 
00810   template <class T, class Prop, class Storage, class Allocator>
00811   void Matrix_Pointers<T, Prop, Storage, Allocator>
00812   ::Write(string FileName, bool with_size) const
00813   {
00814     ofstream FileStream;
00815     FileStream.open(FileName.c_str());
00816 
00817 #ifdef SELDON_CHECK_IO
00818     // Checks if the file was opened.
00819     if (!FileStream.is_open())
00820       throw IOError("Matrix_Pointers::Write(string FileName)",
00821                     string("Unable to open file \"") + FileName + "\".");
00822 #endif
00823 
00824     this->Write(FileStream, with_size);
00825 
00826     FileStream.close();
00827   }
00828 
00829 
00831 
00840   template <class T, class Prop, class Storage, class Allocator>
00841   void Matrix_Pointers<T, Prop, Storage, Allocator>
00842   ::Write(ostream& FileStream, bool with_size) const
00843   {
00844 
00845 #ifdef SELDON_CHECK_IO
00846     // Checks if the stream is ready.
00847     if (!FileStream.good())
00848       throw IOError("Matrix_Pointers::Write(ostream& FileStream)",
00849                     "The stream is not ready.");
00850 #endif
00851 
00852     if (with_size)
00853       {
00854         FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
00855                          sizeof(int));
00856         FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->n_)),
00857                          sizeof(int));
00858       }
00859 
00860     FileStream.write(reinterpret_cast<char*>(this->data_),
00861                      this->m_ * this->n_ * sizeof(value_type));
00862 
00863 #ifdef SELDON_CHECK_IO
00864     // Checks if data was written.
00865     if (!FileStream.good())
00866       throw IOError("Matrix_Pointers::Write(ostream& FileStream)",
00867                     "Output operation failed.");
00868 #endif
00869 
00870   }
00871 
00872 
00874 
00881   template <class T, class Prop, class Storage, class Allocator>
00882   void Matrix_Pointers<T, Prop, Storage, Allocator>
00883   ::WriteText(string FileName) const
00884   {
00885     ofstream FileStream;
00886     FileStream.precision(cout.precision());
00887     FileStream.flags(cout.flags());
00888     FileStream.open(FileName.c_str());
00889 
00890 #ifdef SELDON_CHECK_IO
00891     // Checks if the file was opened.
00892     if (!FileStream.is_open())
00893       throw IOError("Matrix_Pointers::WriteText(string FileName)",
00894                     string("Unable to open file \"") + FileName + "\".");
00895 #endif
00896 
00897     this->WriteText(FileStream);
00898 
00899     FileStream.close();
00900   }
00901 
00902 
00904 
00911   template <class T, class Prop, class Storage, class Allocator>
00912   void Matrix_Pointers<T, Prop, Storage, Allocator>
00913   ::WriteText(ostream& FileStream) const
00914   {
00915 
00916 #ifdef SELDON_CHECK_IO
00917     // Checks if the file is ready.
00918     if (!FileStream.good())
00919       throw IOError("Matrix_Pointers::WriteText(ostream& FileStream)",
00920                     "The stream is not ready.");
00921 #endif
00922 
00923     int i, j;
00924     for (i = 0; i < this->GetM(); i++)
00925       {
00926         for (j = 0; j < this->GetN(); j++)
00927           FileStream << (*this)(i, j) << '\t';
00928         FileStream << endl;
00929       }
00930 
00931 #ifdef SELDON_CHECK_IO
00932     // Checks if data was written.
00933     if (!FileStream.good())
00934       throw IOError("Matrix_Pointers::WriteText(ostream& FileStream)",
00935                     "Output operation failed.");
00936 #endif
00937 
00938   }
00939 
00940 
00942 
00952   template <class T, class Prop, class Storage, class Allocator>
00953   void Matrix_Pointers<T, Prop, Storage, Allocator>
00954   ::Read(string FileName, bool with_size)
00955   {
00956     ifstream FileStream;
00957     FileStream.open(FileName.c_str());
00958 
00959 #ifdef SELDON_CHECK_IO
00960     // Checks if the file was opened.
00961     if (!FileStream.is_open())
00962       throw IOError("Matrix_Pointers::Read(string FileName)",
00963                     string("Unable to open file \"") + FileName + "\".");
00964 #endif
00965 
00966     this->Read(FileStream, with_size);
00967 
00968     FileStream.close();
00969   }
00970 
00971 
00973 
00983   template <class T, class Prop, class Storage, class Allocator>
00984   void Matrix_Pointers<T, Prop, Storage, Allocator>
00985   ::Read(istream& FileStream, bool with_size)
00986   {
00987 
00988 #ifdef SELDON_CHECK_IO
00989     // Checks if the stream is ready.
00990     if (!FileStream.good())
00991       throw IOError("Matrix_Pointers::Read(istream& FileStream)",
00992                     "The stream is not ready.");
00993 #endif
00994 
00995     if (with_size)
00996       {
00997         int new_m, new_n;
00998         FileStream.read(reinterpret_cast<char*>(&new_m), sizeof(int));
00999         FileStream.read(reinterpret_cast<char*>(&new_n), sizeof(int));
01000         this->Reallocate(new_m, new_n);
01001       }
01002 
01003     FileStream.read(reinterpret_cast<char*>(this->data_),
01004                     this->GetM() * this->GetN() * sizeof(value_type));
01005 
01006 #ifdef SELDON_CHECK_IO
01007     // Checks if data was read.
01008     if (!FileStream.good())
01009       throw IOError("Matrix_Pointers::Read(istream& FileStream)",
01010                     "Input operation failed.");
01011 #endif
01012 
01013   }
01014 
01015 
01017 
01021   template <class T, class Prop, class Storage, class Allocator>
01022   void Matrix_Pointers<T, Prop, Storage, Allocator>::ReadText(string FileName)
01023   {
01024     ifstream FileStream;
01025     FileStream.open(FileName.c_str());
01026 
01027 #ifdef SELDON_CHECK_IO
01028     // Checks if the file was opened.
01029     if (!FileStream.is_open())
01030       throw IOError("Matrix_Pointers::ReadText(string FileName)",
01031                     string("Unable to open file \"") + FileName + "\".");
01032 #endif
01033 
01034     this->ReadText(FileStream);
01035 
01036     FileStream.close();
01037   }
01038 
01039 
01041 
01045   template <class T, class Prop, class Storage, class Allocator>
01046   void Matrix_Pointers<T, Prop, Storage, Allocator>
01047   ::ReadText(istream& FileStream)
01048   {
01049     // Clears the matrix.
01050     Clear();
01051 
01052 #ifdef SELDON_CHECK_IO
01053     // Checks if the stream is ready.
01054     if (!FileStream.good())
01055       throw IOError("Matrix_Pointers::ReadText(istream& FileStream)",
01056                     "The stream is not ready.");
01057 #endif
01058 
01059     // Reads the first line.
01060     string line;
01061     getline(FileStream, line);
01062     if (FileStream.fail())
01063       // Is the file empty?
01064       return;
01065 
01066     // Converts the first line into a vector.
01067     istringstream line_stream(line);
01068     Vector<T> first_row;
01069     first_row.ReadText(line_stream);
01070 
01071     // Now reads all other rows, and puts them in a single vector.
01072     Vector<T> other_row;
01073     other_row.ReadText(FileStream);
01074 
01075     // Number of rows and columns.
01076     int n = first_row.GetM();
01077     int m = 1 + other_row.GetM() / n;
01078 
01079 #ifdef SELDON_CHECK_IO
01080     // Checks that enough elements were read.
01081     if (other_row.GetM() != (m - 1) * n)
01082       throw IOError("Matrix_Pointers::ReadText(istream& FileStream)",
01083                     "Not all rows have the same number of columns.");
01084 #endif
01085 
01086     this->Reallocate(m, n);
01087     // Fills the matrix.
01088     for (int j = 0; j < n; j++)
01089       this->Val(0, j) = first_row(j);
01090 
01091     int k = 0;
01092     for (int i = 1; i < m; i++)
01093       for (int j = 0; j < n; j++)
01094         this->Val(i, j) = other_row(k++);
01095   }
01096 
01097 
01099   // MATRIX<COLMAJOR> //
01101 
01102 
01103   /****************
01104    * CONSTRUCTORS *
01105    ****************/
01106 
01107 
01109 
01112   template <class T, class Prop, class Allocator>
01113   Matrix<T, Prop, ColMajor, Allocator>::Matrix()  throw():
01114     Matrix_Pointers<T, Prop, ColMajor, Allocator>()
01115   {
01116   }
01117 
01118 
01120 
01124   template <class T, class Prop, class Allocator>
01125   Matrix<T, Prop, ColMajor, Allocator>::Matrix(int i, int j):
01126     Matrix_Pointers<T, Prop, ColMajor, Allocator>(i, j)
01127   {
01128   }
01129 
01130 
01132   template <class T, class Prop, class Allocator>
01133   Matrix<T, Prop, ColMajor, Allocator>
01134   ::Matrix(const Matrix<T, Prop, ColMajor, Allocator>& A):
01135     Matrix_Pointers<T, Prop, ColMajor, Allocator>(A)
01136   {
01137   }
01138 
01139 
01140   /*****************
01141    * OTHER METHODS *
01142    *****************/
01143 
01144 
01146 
01149   template <class T, class Prop, class Allocator>
01150   template <class T0>
01151   Matrix<T, Prop, ColMajor, Allocator>&
01152   Matrix<T, Prop, ColMajor, Allocator>::operator= (const T0& x)
01153   {
01154     this->Fill(x);
01155 
01156     return *this;
01157   }
01158 
01159 
01161 
01166   template <class T, class Prop, class Allocator>
01167   inline Matrix<T, Prop, ColMajor, Allocator>&
01168   Matrix<T, Prop, ColMajor, Allocator>
01169   ::operator= (const Matrix<T, Prop, ColMajor, Allocator>& A)
01170   {
01171     this->Copy(A);
01172 
01173     return *this;
01174   }
01175 
01176 
01178 
01181   template <class T, class Prop, class Allocator> template<class T0>
01182   inline Matrix<T, Prop, ColMajor, Allocator>&
01183   Matrix<T, Prop, ColMajor, Allocator>::operator*= (const T0& alpha)
01184   {
01185     for (int i = 0; i < this->m_ * this->n_; i++)
01186       this->data_[i] *= alpha;
01187 
01188     return *this;
01189   }
01190 
01191 
01193   // MATRIX<ROWMAJOR> //
01195 
01196 
01197   /****************
01198    * CONSTRUCTORS *
01199    ****************/
01200 
01201 
01203 
01206   template <class T, class Prop, class Allocator>
01207   Matrix<T, Prop, RowMajor, Allocator>::Matrix()  throw():
01208     Matrix_Pointers<T, Prop, RowMajor, Allocator>()
01209   {
01210   }
01211 
01212 
01214 
01218   template <class T, class Prop, class Allocator>
01219   Matrix<T, Prop, RowMajor, Allocator>::Matrix(int i, int j):
01220     Matrix_Pointers<T, Prop, RowMajor, Allocator>(i, j)
01221   {
01222   }
01223 
01224 
01226   template <class T, class Prop, class Allocator>
01227   Matrix<T, Prop, RowMajor, Allocator>
01228   ::Matrix(const Matrix<T, Prop, RowMajor, Allocator>& A):
01229     Matrix_Pointers<T, Prop, RowMajor, Allocator>(A)
01230   {
01231   }
01232 
01233 
01234   /*****************
01235    * OTHER METHODS *
01236    *****************/
01237 
01238 
01240 
01243   template <class T, class Prop, class Allocator>
01244   template <class T0>
01245   Matrix<T, Prop, RowMajor, Allocator>&
01246   Matrix<T, Prop, RowMajor, Allocator>::operator= (const T0& x)
01247   {
01248     this->Fill(x);
01249 
01250     return *this;
01251   }
01252 
01253 
01255 
01260   template <class T, class Prop, class Allocator>
01261   inline Matrix<T, Prop, RowMajor, Allocator>&
01262   Matrix<T, Prop, RowMajor, Allocator>
01263   ::operator= (const Matrix<T, Prop, RowMajor, Allocator>& A)
01264   {
01265     this->Copy(A);
01266 
01267     return *this;
01268   }
01269 
01270 
01272 
01275   template <class T, class Prop, class Allocator> template<class T0>
01276   inline Matrix<T, Prop, RowMajor, Allocator>&
01277   Matrix<T, Prop, RowMajor, Allocator>::operator*= (const T0& alpha)
01278   {
01279     for (int i = 0; i < this->m_*this->n_; i++)
01280       this->data_[i] *= alpha;
01281 
01282     return *this;
01283   }
01284 
01285 
01286 } // namespace Seldon.
01287 
01288 #define SELDON_FILE_MATRIX_POINTERS_CXX
01289 #endif