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

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