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

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