umatrix_tlate.h

Go to the documentation of this file.
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_UMATRIX_TLATE_H
00024 #define O2SCL_UMATRIX_TLATE_H
00025 
00026 /** \file umatrix_tlate.h
00027     \brief File for definitions of matrices
00028 */
00029 
00030 #include <iostream>
00031 #include <cstdlib>
00032 #include <string>
00033 #include <fstream>
00034 #include <sstream>
00035 
00036 #include <gsl/gsl_matrix.h>
00037 #include <gsl/gsl_ieee_utils.h>
00038 
00039 #include <o2scl/err_hnd.h>
00040 #include <o2scl/uvector_tlate.h>
00041 
00042 #ifndef DOXYGENP
00043 namespace o2scl {
00044 #endif
00045 
00046   //template<class data_t> class umatrix3d_view_tlate;
00047   //template<class data_t> class umatrix3d_tlate;
00048 
00049   /** 
00050       \brief A matrix view of double-precision numbers
00051   */
00052   template<class data_t> class umatrix_view_tlate {
00053     
00054 #ifndef DOXYGEN_INTERNAL
00055 
00056   protected:
00057 
00058     /// The data
00059     data_t *data;
00060     /// The number of rows
00061     size_t size1;
00062     /// The number of columns
00063     size_t size2;
00064     /// Zero if memory is owned elsewhere, 1 otherwise
00065     int owner;
00066 
00067     //friend class umatrix3d_view_tlate<data_t>;
00068     //friend class umatrix3d_tlate<data_t>;
00069 
00070 #endif
00071 
00072   public:
00073 
00074     /// \name Copy constructors
00075     //@{
00076     /// So2scllow copy constructor - create a new view of the same matrix
00077     umatrix_view_tlate(const umatrix_view_tlate &v) {
00078       data=v.data;
00079       size1=v.size1;
00080       size2=v.size2;
00081       owner=0;      
00082     }
00083     
00084     /// So2scllow copy constructor - create a new view of the same matrix
00085     umatrix_view_tlate& operator=(const umatrix_view_tlate &v) {
00086       data=v.data;
00087       size1=v.size1;
00088       size2=v.size2;
00089       owner=0;      
00090 
00091       return *this;
00092     }
00093     //@}
00094 
00095     ~umatrix_view_tlate() {};
00096     
00097     /// \name Get and set methods
00098     //@{
00099     /** 
00100         \brief Array-like indexing 
00101     */
00102     data_t *operator[](size_t i) {
00103 #if O2SCL_NO_RANGE_CHECK
00104 #else
00105       if (i>=size1) {
00106         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00107                  +" in umatrix_view_tlate::operator[]. Size: "+
00108                  itos(size1)+
00109                  " (index should be less than size).").c_str(),gsl_index);
00110         return data;
00111       }
00112 #endif
00113       return data+i*size2;
00114     }
00115     
00116     /** 
00117         \brief Array-like indexing 
00118     */
00119     const data_t *operator[](size_t i) const {
00120 #if O2SCL_NO_RANGE_CHECK
00121 #else
00122       if (i>=size1) {
00123         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00124                  +" in umatrix_view_tlate::operator[] const. Size: "+
00125                  itos(size1)+
00126                  " (index should be less than size).").c_str(),gsl_index);
00127         return data;
00128       }
00129 #endif
00130       return data+i*size2;
00131     }
00132     
00133     /** 
00134         \brief Array-like indexing 
00135     */
00136     data_t &operator()(size_t i, size_t j) {
00137 #if O2SCL_NO_RANGE_CHECK
00138 #else
00139       if (i>=size1 || j>=size2) {
00140         set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+
00141                  ") out of bounds"
00142                  +" in umatrix_view_tlate::operator(). Sizes: ("+
00143                  itos(size1)+","+itos(size2)+
00144                  ") (index should be less than size).").c_str(),gsl_index);
00145         return *data;
00146       }
00147 #endif
00148       return *(data+i*size2+j);
00149     }
00150     
00151     /** 
00152         \brief Array-like indexing 
00153     */
00154     const data_t &operator()(size_t i, size_t j) const {
00155 #if O2SCL_NO_RANGE_CHECK
00156 #else
00157       if (i>=size1 || j>=size2) {
00158         set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+
00159                  ") out of bounds"
00160                  +" in umatrix_view_tlate::operator() const. Sizes: ("+
00161                  itos(size1)+","+itos(size2)+
00162                  ") (index should be less than size).").c_str(),gsl_index);
00163         return *data;
00164       }
00165 #endif
00166       return *(data+i*size2+j);
00167     }
00168     
00169     /** \brief Get (with optional range-checking) */
00170     data_t get(size_t i, size_t j) const {
00171 #if O2SCL_NO_RANGE_CHECK
00172 #else
00173       if (i>=size1 || j>=size2) {
00174         set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+
00175                  ") out of bounds"
00176                  +" in umatrix_view_tlate::get(). Sizes: ("+
00177                  itos(size1)+","+itos(size2)+
00178                  ") (index should be less than size).").c_str(),gsl_index);
00179         return *data;
00180       }
00181 #endif
00182       return (data+i*size2+j);
00183     }
00184     
00185     /** \brief Get pointer (with optional range-checking) */
00186     data_t *get_ptr(size_t i, size_t j) {
00187 #if O2SCL_NO_RANGE_CHECK
00188 #else
00189       if (i>=size1 || j>=size2) {
00190         set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+
00191                  ") out of bounds"
00192                  +" in umatrix_view_tlate::get_ptr(). Sizes: ("+
00193                  itos(size1)+","+itos(size2)+
00194                  ") (index should be less than size).").c_str(),gsl_index);
00195         return data;
00196       }
00197 #endif
00198       return data+i*size2+j;
00199     }
00200     
00201     /** \brief Get pointer (with optional range-checking) */
00202     const data_t *get_const_ptr(size_t i, size_t j) const {
00203 #if O2SCL_NO_RANGE_CHECK
00204 #else
00205       if (i>=size1 || j>=size2) {
00206         set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+
00207                  ") out of bounds"
00208                  +" in umatrix_view_tlate::get_const_ptr(). Sizes: ("+
00209                  itos(size1)+","+itos(size2)+
00210                  ") (index should be less than size).").c_str(),gsl_index);
00211         return (const data_t *)data;
00212       }
00213 #endif
00214       return (const data_t *)(data+i*size2+j);
00215     }
00216     
00217     /** \brief Set (with optional range-checking) */
00218     int set(size_t i, size_t j, data_t val) {
00219 #if O2SCL_NO_RANGE_CHECK
00220 #else
00221       if (i>=size1 || j>=size2) {
00222         set_err_ret((((std::string)"Indices (")+itos(i)+","+itos(j)+
00223                      ") out of bounds"
00224                      +" in umatrix_view_tlate::set(). Sizes: ("+
00225                      itos(size1)+","+itos(size2)+
00226                      ") (index should be less than size).").c_str(),gsl_index);
00227       }
00228 #endif
00229       *(data+i*size2+j)=val;
00230       return 0;
00231     }
00232 
00233     /** \brief Set all of the value to be the value \c val */
00234     int set_all(double val) {
00235       for(size_t i=0;i<size1;i++) {
00236         for(size_t j=0;j<size2;j++) {
00237           *(data+i*size2+j)=val;
00238         }
00239       }
00240       return 0;
00241     }
00242 
00243     /** 
00244         \brief Method to return number of rows
00245         
00246         If no memory has been allocated, this will quietly 
00247         return zero.
00248     */
00249     size_t rows() const {
00250       return size1;
00251     }
00252 
00253     /** 
00254         \brief Method to return number of columns
00255         
00256         If no memory has been allocated, this will quietly 
00257         return zero.
00258     */
00259     size_t cols() const {
00260       return size2;
00261     }
00262     //@}
00263 
00264     /// \name Other methods
00265     //@{
00266     /// Return true if this object owns the data it refers to
00267     bool is_owner() const {
00268       if (owner==1) return true;
00269       return false;
00270     }
00271     //@}
00272 
00273     /// \name Arithmetic 
00274     //@{
00275     /** \brief operator+= */
00276     umatrix_view_tlate<data_t> &operator+=
00277       (const umatrix_view_tlate<data_t> &x) {
00278       size_t lsize=x.size1;
00279       if (lsize>size1) lsize=size1;
00280       size_t lsize2=x.size2;
00281       if (lsize2>size2) lsize2=size2;
00282       for(size_t i=0;i<lsize;i++) {
00283         for(size_t j=0;j<lsize2;j++) {
00284           (*this)[i][j]+=x[i][j];
00285         }
00286       }
00287       
00288       return *this;
00289     }
00290     
00291     /** \brief operator-= */
00292     umatrix_view_tlate<data_t> &operator-=
00293       (const umatrix_view_tlate<data_t> &x) {
00294       size_t lsize=x.size1;
00295       if (lsize>size1) lsize=size1;
00296       size_t lsize2=x.size2;
00297       if (lsize2>size2) lsize2=size2;
00298       for(size_t i=0;i<lsize;i++) {
00299         for(size_t j=0;j<lsize2;j++) {
00300           (*this)[i][j]+=x[i][j];
00301         }
00302       }
00303 
00304       return *this;
00305     }
00306     
00307     /** \brief operator+= */
00308     umatrix_view_tlate<data_t> &operator+=(const data_t &y) {
00309       for(size_t i=0;i<size1;i++) {
00310         for(size_t j=0;j<size2;j++) {
00311           (*this)[i][j]+=y;
00312         }
00313       }
00314       
00315       return *this;
00316     }
00317 
00318     /** \brief operator-= */
00319     umatrix_view_tlate<data_t> &operator-=(const data_t &y) {
00320       for(size_t i=0;i<size1;i++) {
00321         for(size_t j=0;j<size2;j++) {
00322           (*this)[i][j]-=y;
00323         }
00324       }
00325       
00326       return *this;
00327     }
00328 
00329     /** \brief operator*= */
00330     umatrix_view_tlate<data_t> &operator*=(const data_t &y) {
00331       for(size_t i=0;i<size1;i++) {
00332         for(size_t j=0;j<size2;j++) {
00333           (*this)[i][j]*=y;
00334         }
00335       }
00336       
00337       return *this;
00338     }
00339     //@}
00340 
00341 #ifndef DOXYGEN_INTERNAL
00342 
00343   protected:
00344 
00345     /** \brief Empty constructor provided for use by 
00346         umatrix_tlate(const umatrix_tlate &v)
00347     */
00348     umatrix_view_tlate() {};
00349 
00350 #endif
00351     
00352   };
00353 
00354   /** 
00355       \brief A matrix of double-precision numbers
00356   
00357   */
00358   template<class data_t> class umatrix_tlate : 
00359   public umatrix_view_tlate<data_t> {
00360   public:
00361     
00362     /// \name Standard constructor
00363     //@{
00364     /** \brief Create an umatrix of size \c n with owner as 'true' 
00365      */
00366     umatrix_tlate(size_t r=0, size_t c=0) {
00367 
00368       this->data=0;
00369       this->size1=0;
00370       this->size2=0;
00371 
00372       // This must be set to 1 even if n=0 so that future
00373       // calls to operator= work properly
00374       this->owner=1;
00375       
00376       if (r>0 && c>0) {
00377         this->data=(data_t *)malloc(r*c*sizeof(data_t));
00378         if (this->data) {
00379           this->size1=r;
00380           this->size2=c;
00381         } else {
00382           set_err("No memory for data in umatrix_tlate constructor",
00383                   gsl_enomem);
00384         }
00385       }
00386     }
00387     //@}
00388     
00389     /// \name Copy constructors
00390     //@{
00391     /// Deep copy constructor, allocate new space and make a copy
00392     umatrix_tlate(const umatrix_tlate &v) : 
00393       umatrix_view_tlate<data_t>() {
00394       size_t n=v.size1;
00395       size_t n2=v.size2;
00396       if (n>0 && n2>0) {
00397         this->data=(data_t *)malloc(n*n2*sizeof(data_t));
00398         if (this->data) {
00399           this->size1=n;
00400           this->size2=n2;
00401           this->owner=1;
00402           for(size_t i=0;i<n;i++) {
00403             for(size_t j=0;j<n2;j++) {
00404               *(this->data+i*this->size2+j)=v[i][j];
00405             }
00406           }
00407         } else {
00408           set_err("No memory for data in umatrix_tlate constructor",
00409                   gsl_enomem);
00410         }
00411       } else {
00412         this->size1=0;
00413         this->size2=0;
00414       }
00415     }
00416     
00417       /// Deep copy constructor, allocate new space and make a copy
00418       umatrix_tlate
00419         (const umatrix_view_tlate<data_t> &v) : 
00420           umatrix_view_tlate<data_t>() {
00421           size_t r=v.rows();
00422           size_t c=v.cols();
00423           if (r>0 && c>0) {
00424             this->data=(data_t *)malloc(r*c*sizeof(data_t));
00425             if (this->data) {
00426               this->size1=v.size1;
00427               this->size2=v.size2;
00428               this->owner=1;
00429               for(size_t i=0;i<r;i++) {
00430                 for(size_t j=0;i<c;j++) {
00431                   *(this->data+i*this->size2+j)=v[i][j];
00432                 }
00433               }
00434             } else {
00435               set_err("No memory for data in umatrix_tlate constructor",
00436                       gsl_enomem);
00437             }
00438           } else {
00439             this->size1=0;
00440             this->size2=0;
00441           }
00442         }
00443     
00444         /** \brief Deep copy constructor, if owner is true, allocate space and
00445             make a new copy, otherwise, just copy into the view
00446         */
00447         umatrix_tlate& operator=(const umatrix_tlate &v) {
00448           size_t sze=v.size1;
00449           size_t sze2=v.size2;
00450           if (this->owner) {
00451             allocate(sze,sze2);
00452           } else {
00453             if (this->size1!=sze || this->size2!=sze2) {
00454               set_err("Sizes don't match in umatrix_tlate::operator=()",
00455                       gsl_ebadlen);
00456               return *this;
00457             }
00458           }
00459           for(size_t i=0;i<sze;i++) {
00460             for(size_t j=0;j<sze2;j++) {
00461               *(this->data+i*this->size2+j)=v[i][j];
00462             }
00463           }
00464           return *this;
00465         }
00466 
00467         /** \brief Deep copy constructor, if owner is true, allocate space and
00468             make a new copy, otherwise, just copy into the view
00469         */
00470         umatrix_tlate& operator=
00471           (const umatrix_view_tlate<data_t> &v) {
00472           size_t sze=v.rows();
00473           size_t sze2=v.cols();
00474           if (this->owner) {
00475             allocate(sze,sze2);
00476           } else {
00477             if (this->size1!=sze || this->size2!=sze2) {
00478               set_err("Sizes don't match in umatrix_tlate::operator=()",
00479                       gsl_ebadlen);
00480               return *this;
00481             }
00482           }
00483           for(size_t i=0;i<sze;i++) {
00484             for(size_t j=0;j<sze2;j++) {
00485               *(this->data+i*this->size2+j)=v[i][j];
00486             }
00487           }
00488           return *this;
00489         }
00490     
00491         /** \brief Deep copy from an array of uvectors
00492          */
00493         umatrix_tlate(size_t n, uvector_view_tlate<data_t> uva[]) {
00494           if (n>0) {
00495             size_t n2=uva[0];
00496             if (n2>0) {
00497               allocate(n,n2);
00498               for(size_t i=0;i<n;i++) {
00499                 for(size_t j=0;j<n2;j++) {
00500                   (*this)[i][j]=uva[i][j];
00501                 }
00502               }
00503             }
00504           }
00505         }
00506 
00507         /** \brief Deep copy from a C-style 2-d array
00508          */
00509         umatrix_tlate(size_t n, size_t n2, data_t **csa) {
00510           if (n>0 && n2>0) {
00511             allocate(n,n2);
00512             for(size_t i=0;i<n;i++) {
00513               for(size_t j=0;j<n2;j++) {
00514                 (*this)[i][j]=csa[i][j];
00515               }
00516             }
00517           }
00518         }
00519 
00520         //@}
00521     
00522         ~umatrix_tlate() {
00523           if (this->size1>0) {
00524             if (this->owner==1) {
00525               std::free(this->data);
00526               this->size1=0;
00527               this->size2=0;
00528             }
00529           }
00530         }
00531 
00532         /// \name Memory allocation
00533         //@{
00534         /** 
00535             \brief Allocate memory after freeing any memory presently in use
00536         */
00537         int allocate(size_t nrows, size_t ncols) {
00538           if (this->size1>0 || this->size2>0) free();
00539       
00540           if (nrows>0 && ncols>0) {
00541             this->data=(data_t *)malloc(nrows*ncols*sizeof(data_t));
00542             if (this->data) {
00543               this->size1=nrows;
00544               this->size2=ncols;
00545               this->owner=1;
00546             } else {
00547               set_err_ret("No memory for data in umatrix_tlate::allocate()",
00548                           gsl_enomem);
00549             }
00550           } else {
00551             set_err_ret("Zero size in umatrix::allocate()",gsl_einval);
00552           }
00553           return 0;
00554         }
00555 
00556         /** 
00557             \brief Free the memory 
00558     
00559             This function will safely do nothing if used without first
00560             allocating memory or if called multiple times in succession.
00561         */
00562         int free() {
00563           if (this->size1>0) {
00564             if (this->owner==1) {
00565               std::free(this->data);
00566             }
00567             this->size1=0;
00568             this->size2=0;
00569           }
00570           return 0;
00571         }
00572         //@}
00573 
00574         /// \name Other methods
00575         //@{
00576         /// \brief Compute the transpose (even if matrix is not square)
00577         umatrix_tlate<data_t> transpose() {
00578           umatrix_tlate<data_t> result(this->size2,this->size1);
00579           for(size_t i=0;i<this->size1;i++) {
00580             for(size_t j=0;j<this->size2;j++) {
00581               result[j][i]=(*this)[i][j];
00582             }
00583           }
00584         }
00585         //@}
00586     
00587   };
00588 
00589   /** \brief Create a vector from a row of a matrix 
00590    */
00591   template<class data_t> class umatrix_row_tlate : 
00592   public uvector_view_tlate<data_t> {
00593   public:
00594     /** \brief Create a vector from row \c i of matrix \c m */
00595     umatrix_row_tlate(umatrix_view_tlate<data_t> &m, 
00596                       size_t i) {
00597       this->sz=0;
00598       this->data=0;
00599       this->owner=0;
00600       if (i<m.rows()) {
00601         this->sz=m.cols();
00602         this->data=m[0]+m.cols()*i;
00603       }
00604     }
00605   };
00606     
00607   /** \brief Create a const vector from a row of a matrix 
00608    */
00609   template<class data_t> class umatrix_const_row_tlate :
00610   public uvector_view_tlate<data_t> {
00611   public:
00612     /** \brief Create a vector from row \c i of matrix \c m */
00613     umatrix_const_row_tlate
00614       (const umatrix_view_tlate<data_t> &m, 
00615        size_t i) {
00616       if (i<m.size1) {
00617         this->sz=m.cols();
00618         this->data=m[0]+m.cols()*i;
00619         this->owner=0;
00620       }
00621     }
00622   };
00623     
00624   /// umatrix typedef
00625   typedef umatrix_tlate<double> umatrix;
00626   /// umatrix_view typedef
00627   typedef umatrix_view_tlate<double> umatrix_view;
00628   /// umatrix_row typedef
00629   typedef umatrix_row_tlate<double> umatrix_row;
00630   /// umatrix_const_row typedef
00631   typedef umatrix_const_row_tlate<double> umatrix_const_row;
00632 
00633   /// umatrix_int typedef
00634   typedef umatrix_tlate<int> umatrix_int;
00635   /// umatrix_int_view typedef
00636   typedef umatrix_view_tlate<int> umatrix_int_view;
00637   /// umatrix_int_row typedef
00638   typedef umatrix_row_tlate<int> umatrix_int_row;
00639   /// umatrix_int_const_row typedef
00640   typedef umatrix_const_row_tlate<int> umatrix_int_const_row;
00641 
00642   /** \brief A operator for naive matrix output
00643 
00644       
00645       This outputs all of the matrix elements. Each row is output with
00646       an endline character at the end of each row. Positive values are
00647       preceeded by an extra space. A 2x2 example:
00648       \verbatim
00649       -3.751935e-05 -6.785864e-04
00650       -6.785864e-04  1.631984e-02
00651       \endverbatim
00652 
00653       The function \c gsl_ieee_double_to_rep() is used to determine
00654       the sign of a number, so that "-0.0" as distinct from "+0.0" 
00655       is handled correctly.
00656 
00657       \todo This assumes that scientific mode is on and showpos 
00658       is off. It'd be nice to fix this.
00659 
00660   */
00661   template<class data_t> std::ostream &operator<<
00662     (std::ostream &os, const umatrix_view_tlate<data_t> &v) {
00663     size_t i;
00664     gsl_ieee_double_rep r;
00665     for(i=0;i<v.rows()-1;i++) {
00666       for(size_t j=0;j<v.cols();j++) {
00667         gsl_ieee_double_to_rep(&(v[i][j]), &r);
00668         if (r.sign==1) os << v[i][j] << ' ';
00669         else os << ' ' << v[i][j] << ' ';
00670       }
00671       os << '\n';
00672     }
00673     i=v.rows()-1;
00674     if (i>0) {
00675       for(size_t j=0;j<v.cols();j++) {
00676         gsl_ieee_double_to_rep(&(v[i][j]), &r);
00677         if (r.sign==1) os << v[i][j] << ' ';
00678         else os << ' ' << v[i][j] << ' ';
00679       }
00680     }
00681     return os;
00682   }
00683   
00684   /** \brief A simple class to provide an \c allocate() function
00685       for \ref umatrix
00686       
00687 
00688   */
00689   class umatrix_alloc {
00690   public:
00691     /// Allocate \c v for \c i elements
00692     void allocate(umatrix &o, int i, int j) { o.allocate(i,j); }
00693     /// Free memory
00694     void free(umatrix &o) { o.free(); }
00695   };
00696 
00697   /** \brief A matrix where the memory allocation is performed in 
00698       the constructor
00699   */
00700 #ifdef DOXYGENP
00701   template<size_t N, size_t M> class ufmatrix : 
00702   public umatrix_tlate<data_t>
00703 #else  
00704     template<size_t N, size_t M> class ufmatrix :   
00705   public umatrix_tlate<double>
00706 #endif
00707   {
00708   public:
00709     ufmatrix() : umatrix_tlate<double>(N,M) {
00710     }
00711   };
00712   
00713   
00714 #ifndef DOXYGENP
00715 }
00716 #endif
00717 
00718 #endif
00719 
00720 
00721 

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page