uvector_cx_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_UVECTOR_CX_TLATE_H
00024 #define O2SCL_UVECTOR_CX_TLATE_H
00025 
00026 /** \file uvector_cx_tlate.h
00027     \brief File for definitions of complex unit-stride vectors
00028 */
00029 
00030 #include <iostream>
00031 #include <cstdlib>
00032 #include <string>
00033 #include <fstream>
00034 #include <sstream>
00035 #include <vector>
00036 #include <o2scl/err_hnd.h>
00037 #include <gsl/gsl_vector.h>
00038 
00039 #ifndef DOXYGENP
00040 namespace o2scl {
00041 #endif
00042   
00043   /** 
00044       \brief A vector view of complex numbers with unit stride
00045 
00046       \experiment
00047 
00048       \todo Write lookup() method, and possible an erase() method.
00049   */
00050   template<class data_t, class complex_t> class uvector_cx_view_tlate {
00051     
00052 #ifndef DOXYGEN_INTERNAL
00053 
00054   protected:
00055 
00056     /// The data
00057     data_t *data;
00058     /// The vector sz
00059     size_t sz;
00060     /// Zero if memory is owned elsewhere, 1 otherwise
00061     int owner;
00062     
00063 #endif
00064 
00065   public:
00066 
00067     /// \name Copy constructors
00068     //@{
00069     /// Copy constructor - create a new view of the same vector
00070     uvector_cx_view_tlate(const uvector_cx_view_tlate &v) {
00071       data=v.data;
00072       sz=v.sz;
00073       owner=0;      
00074     }
00075     
00076     /// Copy constructor - create a new view of the same vector
00077     uvector_cx_view_tlate& operator=(const uvector_cx_view_tlate &v) {
00078       data=v.data;
00079       sz=v.sz;
00080       owner=0;      
00081 
00082       return *this;
00083     }
00084     //@}
00085 
00086     ~uvector_cx_view_tlate() {};
00087     
00088     /// \name Get and set methods
00089     //@{
00090     /** 
00091         \brief Array-like indexing 
00092     */
00093     complex_t &operator[](size_t i) {
00094 #if GSL_RANGE_CHECK
00095       if (i>=sz) {
00096         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00097                  +" in uvector_cx_view_tlate::operator[]. Size: "+
00098                  itos(sz)+
00099                  " (index should be less than size).").c_str(),gsl_index);
00100         return *(complex_t *)(data);
00101       }
00102 #endif
00103       return *(complex_t *)(&data[i*2]);
00104     }
00105     
00106     /** 
00107         \brief Array-like indexing 
00108     */
00109     const complex_t &operator[](size_t i) const {
00110 #if GSL_RANGE_CHECK
00111       if (i>=sz) {
00112         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00113                  +" in uvector_cx_view_tlate::operator[] const. Size: "+
00114                  itos(sz)+
00115                  " (index should be less than size).").c_str(),gsl_index);
00116         return *(const complex_t *)(data);
00117       }
00118 #endif
00119       return *(const complex_t *)(&data[i*2]);
00120     }
00121     
00122     /** 
00123         \brief Array-like indexing 
00124     */
00125     complex_t &operator()(size_t i) {
00126 #if GSL_RANGE_CHECK
00127       if (i>=sz) {
00128         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00129                  +" in uvector_cx_view_tlate::operator(). Size: "+
00130                  itos(sz)+
00131                  " (index should be less than size).").c_str(),gsl_index);
00132         return *(complex_t *)(data);
00133       }
00134 #endif
00135       return *(complex_t *)(&data[i*2]);
00136     }
00137     
00138     /** 
00139         \brief Array-like indexing 
00140     */
00141     const complex_t &operator()(size_t i) const {
00142 #if GSL_RANGE_CHECK
00143       if (i>=sz) {
00144         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00145                  +" in uvector_cx_view_tlate::operator() const. Size: "+
00146                  itos(sz)+
00147                  " (index should be less than size).").c_str(),gsl_index);
00148         return *(const complex_t *)(data);
00149       }
00150 #endif
00151       return *(const complex_t *)(&data[i*2]);
00152     }
00153     
00154     /** \brief Get (with optional range-checking) */
00155     complex_t get(size_t i) const {
00156 #if GSL_RANGE_CHECK
00157       if (i>=sz) {
00158         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00159                  +" in uvector_cx_view_tlate::get(). Size: "+
00160                  itos(sz)+
00161                  " (index should be less than size).").c_str(),gsl_index);
00162         return *(complex_t *)(data);
00163       }
00164 #endif
00165       return *(complex_t *)(&data[i*2]);
00166     }
00167     
00168     /** \brief Get pointer (with optional range-checking) */
00169     complex_t *get_ptr(size_t i) {
00170 #if GSL_RANGE_CHECK
00171       if (i>=sz) {
00172         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00173                  +" in uvector_cx_view_tlate::get_ptr(). Size: "+
00174                  itos(sz)+
00175                  " (index should be less than size).").c_str(),gsl_index);
00176         return (complex_t *)(data);
00177       }
00178 #endif
00179       return (complex_t *)(&data[i*2]);
00180     }
00181     
00182     /** \brief Get pointer (with optional range-checking) */
00183     const complex_t *get_const_ptr(size_t i) const {
00184 #if GSL_RANGE_CHECK
00185       if (i>=sz) {
00186         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00187                  +" in uvector_cx_view_tlate::get_const_ptr(). Size: "+
00188                  itos(sz)+
00189                  " (index should be less than size).").c_str(),gsl_index);
00190         return (const complex_t *)(data);
00191       }
00192 #endif
00193       return (const complex_t *)(&data[i*2]);
00194     }
00195     
00196     /** \brief Set (with optional range-checking) */
00197     int set(size_t i, const complex_t &val) {
00198 #if GSL_RANGE_CHECK
00199       if (i>=sz) {
00200         set_err_ret((((std::string)"Array index ")+itos(i)+" out of bounds"
00201                      +" in uvector_cx_view_tlate::set(). Size: "+
00202                      itos(sz)+
00203                      " (index should be less than size).").c_str(),gsl_index);
00204       }
00205 #endif
00206       data[2*i]=val.dat[0];
00207       data[2*i+1]=val.dat[1];
00208       return 0;
00209     }
00210 
00211     /** \brief Set all of the value to be the value \c val */
00212     int set_all(const complex_t &val) {
00213       double re=val.dat[0];
00214       double im=val.dat[1];
00215       for(size_t i=0;i<sz;i++) {
00216         data[2*i]=re;
00217         data[2*i+1]=im;
00218       }
00219       return 0;
00220     }
00221 
00222     /** 
00223         \brief Method to return vector size 
00224         
00225         If no memory has been allocated, this will quietly 
00226         return zero.
00227     */
00228     size_t size() const {
00229       return sz;
00230     }
00231     //@}
00232 
00233     /// \name Other methods
00234     //@{
00235 
00236     /** \brief Swap vectors */
00237     int swap(uvector_cx_view_tlate<data_t,complex_t> &x) {
00238       size_t t1;
00239       double *t3;
00240       int t5;
00241       
00242       t1=sz;
00243       t3=data;
00244       t5=owner;
00245       
00246       sz=x.sz;
00247       data=x.data;
00248       owner=x.owner;
00249 
00250       x.sz=t1;
00251       x.data=t3;
00252       x.owner=t5;
00253 
00254       return 0;
00255     }
00256 
00257     /// Return true if this object owns the data it refers to
00258     bool is_owner() const {
00259       if (owner==1) return true;
00260       return false;
00261     }
00262 
00263     /// \name Arithmetic
00264     //@{
00265     /** \brief operator+= */
00266     uvector_cx_view_tlate<data_t,complex_t> &operator+=
00267       (const uvector_cx_view_tlate<data_t,complex_t> &x) {
00268       size_t lsz=x.sz;
00269       if (lsz>sz) lsz=sz;
00270       for(size_t i=0;i<lsz;i++) (*this)[i]+=x[i];
00271       
00272       return *this;
00273     }
00274     
00275     /** \brief operator-= */
00276     uvector_cx_view_tlate<data_t,complex_t> &operator-=
00277       (const uvector_cx_view_tlate<data_t,complex_t> &x) {
00278       size_t lsz=x.sz;
00279       if (lsz>sz) lsz=sz;
00280       for(size_t i=0;i<lsz;i++) (*this)[i]-=x[i];
00281       
00282       return *this;
00283     }
00284     
00285     /** \brief operator+= */
00286     uvector_cx_view_tlate<data_t,complex_t> &operator+=(const data_t &y) {
00287       for(size_t i=0;i<sz;i++) (*this)[i]+=y;
00288 
00289       return *this;
00290     }
00291 
00292     /** \brief operator-= */
00293     uvector_cx_view_tlate<data_t,complex_t> &operator-=(const data_t &y) {
00294       for(size_t i=0;i<sz;i++) (*this)[i]-=y;
00295 
00296       return *this;
00297     }
00298 
00299     /** \brief operator*= */
00300     uvector_cx_view_tlate<data_t,complex_t> &operator*=(const data_t &y) {
00301       for(size_t i=0;i<sz;i++) (*this)[i]*=y;
00302 
00303       return *this;
00304     }
00305     
00306     /** \brief Norm */
00307     data_t norm() const {
00308       data_t result=0;
00309       for(size_t i=0;i<sz;i++) {
00310         result+=(*this)[i]*(*this)[i];
00311       }
00312       return sqrt(result);
00313     }
00314     //@}
00315     
00316 #ifndef DOXYGEN_INTERNAL
00317 
00318   protected:
00319 
00320     /** \brief Empty constructor provided for use by 
00321         uvector_cx_tlate(const uvector_cx_tlate &v)
00322     */
00323     uvector_cx_view_tlate() {};
00324 
00325 #endif
00326     
00327   };
00328 
00329   /** 
00330       \brief A vector of double-precision numbers with unit stride
00331   
00332       There are several global binary operators associated with
00333       objects of type \ref uvector_cx_tlate. The are documented in the
00334       "Functions" section of \ref uvector_cx_tlate.h.
00335   */
00336   template<class data_t, class complex_t> class uvector_cx_tlate : 
00337   public uvector_cx_view_tlate<data_t,complex_t> {
00338   public:
00339 
00340     /// \name Standard constructor
00341     //@{
00342     /** \brief Create an uvector_cx of size \c n with owner as 'true' */
00343     uvector_cx_tlate(size_t n=0) {
00344       // This must be set to 1 even if n=0 so that future
00345       // calls to operator= work properly
00346       this->owner=1;
00347       if (n>0) {
00348         this->data=(data_t *)malloc(2*n*sizeof(data_t));
00349         if (this->data) {
00350           this->sz=n;
00351         } else {
00352           set_err("No memory for data in uvector_cx_tlate constructor",
00353                   gsl_enomem);
00354         }
00355       } else {
00356         this->sz=0;
00357       }
00358     }
00359     //@}
00360     
00361     /// \name Copy constructors
00362     //@{
00363     /// Deep copy constructor - allocate new space and make a copy
00364     uvector_cx_tlate(const uvector_cx_tlate &v) : 
00365       uvector_cx_view_tlate<data_t,complex_t>() {
00366       size_t n=v.sz;
00367       if (n>0) {
00368         this->data=(data_t *)malloc(2*n*sizeof(data_t));
00369         if (this->data) {
00370           this->sz=n;
00371           this->owner=1;
00372           for(size_t i=0;i<n;i++) {
00373             this->data[2*i]=v[i].dat[0];
00374             this->data[2*i+1]=v[i].dat[1];
00375           }
00376         } else {
00377           set_err("No memory for data in uvector_cx_tlate constructor",
00378                   gsl_enomem);
00379         }
00380       } else {
00381         this->sz=0;
00382       }
00383     }
00384       
00385       /// Deep copy constructor - allocate new space and make a copy
00386       uvector_cx_tlate(const uvector_cx_view_tlate<data_t,complex_t> &v) : 
00387         uvector_cx_view_tlate<data_t,complex_t>() {
00388         size_t n=v.sz;
00389         if (n>0) {
00390           this->data=(data_t *)malloc(2*n*sizeof(data_t));
00391           if (this->data) {
00392             this->sz=n;
00393             this->owner=1;
00394             for(size_t i=0;i<n;i++) {
00395               this->data[2*i]=v[i].dat[0];
00396               this->data[2*i+1]=v[i].dat[1];
00397             }
00398           } else {
00399             set_err("No memory for data in uvector_cx_tlate constructor",
00400                     gsl_enomem);
00401           }
00402         } else {
00403           this->sz=0;
00404         }
00405       }
00406 
00407         /** \brief Deep copy constructor - if owner is true, allocate space and
00408             make a new copy, otherwise, just copy into the view
00409         */
00410         uvector_cx_tlate& operator=(const uvector_cx_tlate &v) {
00411           size_t sz2=v.sz;
00412           if (this->owner) {
00413             allocate(sz2);
00414           } else {
00415             if (this->sz!=sz2) {
00416               set_err("Sizes don't match in uvector_cx_tlate::operator=()",
00417                       gsl_ebadlen);
00418               return *this;
00419             }
00420           }
00421           for(size_t i=0;i<sz2;i++) {
00422             this->data[2*i]=v[i].dat[0];
00423             this->data[2*i+1]=v[i].dat[1];
00424           }
00425           return *this;
00426         }
00427 
00428         /** \brief Deep copy constructor - if owner is true, allocate space and
00429             make a new copy, otherwise, just copy into the view
00430         */
00431         uvector_cx_tlate& operator=
00432           (const uvector_cx_view_tlate<data_t,complex_t> &v) {
00433           size_t sz2=v.size();
00434           if (this->owner) {
00435             allocate(sz2);
00436           } else {
00437             if (this->sz!=sz2) {
00438               set_err("Sizes don't match in uvector_cx_tlate::operator=()",
00439                       gsl_ebadlen);
00440               return *this;
00441             }
00442           }
00443           for(size_t i=0;i<sz2;i++) {
00444             this->data[2*i]=v[i].dat[0];
00445             this->data[2*i+1]=v[i].dat[1];
00446           }
00447           return *this;
00448         }
00449         //@}
00450 
00451         ~uvector_cx_tlate() {
00452           if (this->sz>0) {
00453             if (this->owner==1) {
00454               std::free(this->data);
00455             }
00456             this->sz=0;
00457           }
00458         }
00459 
00460         /// \name Memory allocation
00461         //@{
00462         /** 
00463             \brief Allocate memory for size \c n after freeing any memory 
00464             presently in use
00465         */
00466         int allocate(size_t nsize) {
00467           if (this->sz>0) free();
00468 
00469           if (nsize>0) {
00470             this->data=(data_t *)malloc(2*nsize*sizeof(data_t));
00471             if (this->data) {
00472               this->sz=nsize;
00473               this->owner=1;
00474             } else {
00475               set_err_ret("No memory for data in uvector_cx_tlate::allocate()",
00476                           gsl_enomem);
00477             }
00478           } else {
00479             set_err_ret("Zero size in uvector_cx::allocate()",gsl_einval);
00480           }
00481           return 0;
00482         }
00483 
00484         /** 
00485             \brief Free the memory 
00486     
00487             This function will safely do nothing if used without first
00488             allocating memory or if called multiple times in succession.
00489         */
00490         int free() {
00491           if (this->sz>0) {
00492             if (this->owner==1) {
00493               std::free(this->data);
00494             }
00495             this->sz=0;
00496           }
00497           return 0;
00498         }
00499         //@}
00500 
00501   };
00502 
00503   /** \brief Create a vector from an array 
00504    */
00505   template<class data_t, class complex_t> class uvector_cx_array_tlate : 
00506   public uvector_cx_view_tlate<data_t,complex_t> {
00507   public:
00508     /** \brief Create a vector from \c dat with size \c n */
00509     uvector_cx_array_tlate(size_t n, data_t *dat) {
00510       if (n>0) {
00511         this->data=dat;
00512         this->sz=n;
00513         this->owner=0;
00514       }
00515     }
00516   };
00517 
00518   /** \brief Create a vector from a subvector of another
00519    */
00520   template<class data_t, class complex_t> class uvector_cx_subvector_tlate : 
00521   public uvector_cx_view_tlate<data_t,complex_t> {
00522   public:
00523     /** \brief Create a vector from \c orig      */
00524     uvector_cx_subvector_tlate(uvector_cx_view_tlate<data_t,complex_t> &orig, 
00525                                size_t offset, size_t n) {
00526       if (offset+n-1<orig.size) {
00527         this->data=orig.data+offset;
00528         this->sz=n;
00529         this->owner=0;
00530       } else {
00531         this->sz=0;
00532         set_err("Subvector failed in uvector_cx_sub_view().",1);
00533       }
00534     }
00535   };
00536 
00537   /** \brief Create a vector from an array 
00538    */
00539   template<class data_t, class complex_t> class uvector_cx_const_array_tlate :
00540   public uvector_cx_view_tlate<data_t,complex_t> {
00541   public:
00542     /** \brief Create a vector from \c dat with size \c n */
00543     uvector_cx_const_array_tlate(size_t n, const data_t *dat) {
00544       if (n>0) {
00545         // We have to do an explicit cast here, but we prevent the
00546         // user from changing the data.
00547         this->data=(data_t *)dat;
00548         this->sz=n;
00549         this->owner=0;
00550       }
00551     }
00552     
00553     ~uvector_cx_const_array_tlate() {};
00554     
00555 #ifndef DOXYGEN_INTERNAL
00556 
00557   protected:
00558 
00559     /** \name These are inaccessible to ensure the vector is \c const.
00560      */
00561     //@{
00562     data_t &operator[](size_t i) { return this->data[0]; }
00563     data_t &operator()(size_t i) { return this->data[0]; }
00564     data_t *get_ptr(size_t i) { return NULL; }
00565     int set(size_t i, data_t val) { return 0; }
00566     int swap(uvector_cx_view_tlate<data_t,complex_t> &x) {
00567       return 0; 
00568     }
00569     int set_all(double val) { return 0; }
00570     uvector_cx_view_tlate<data_t,complex_t> &operator+=
00571       (const uvector_cx_view_tlate<data_t,complex_t> &x) {
00572       return *this;
00573     }
00574     uvector_cx_view_tlate<data_t,complex_t> &operator-=
00575       (const uvector_cx_view_tlate<data_t,complex_t> &x) {
00576       return *this;
00577     }
00578     uvector_cx_view_tlate<data_t,complex_t> &operator*=(const data_t &y) {
00579       return *this;
00580     }
00581     //@}
00582 
00583 #endif
00584 
00585   };
00586 
00587   /** \brief Create a vector from a subvector of another
00588    */
00589   template<class data_t, class complex_t> 
00590     class uvector_cx_const_subvector_tlate :
00591   public uvector_cx_view_tlate<data_t,complex_t> {
00592   public:
00593     /** \brief Create a vector from \c orig 
00594      */
00595     uvector_cx_const_subvector_tlate
00596       (const uvector_cx_view_tlate<data_t,complex_t> &orig, 
00597        size_t offset, size_t n) {
00598       if (offset+n-1<orig.sz) {
00599         this->data=orig.data+offset;
00600         this->sz=n;
00601         this->owner=0;
00602       } else {
00603         this->sz=0;
00604         set_err("Subvector failed in uvector_cx_subvector().",1);
00605       }
00606     }
00607 
00608 #ifndef DOXYGENP
00609 
00610   protected:
00611 
00612     /** \name Ensure \c const by hiding non-const members
00613      */
00614     //@{
00615     data_t &operator[](size_t i) { return this->data[0]; }
00616     data_t &operator()(size_t i) { return this->data[0]; }
00617     data_t *get_ptr(size_t i) { return NULL; }
00618     int set(size_t i, data_t val) { return 0; }
00619     int swap(uvector_cx_view_tlate<data_t,complex_t> &x) {
00620       return 0; 
00621     }
00622     int set_all(double val) { return 0; }
00623     uvector_cx_view_tlate<data_t,complex_t> &operator+=
00624       (const uvector_cx_view_tlate<data_t,complex_t> &x) {
00625       return *this;
00626     }
00627     uvector_cx_view_tlate<data_t,complex_t> &operator-=
00628       (const uvector_cx_view_tlate<data_t,complex_t> &x) {
00629       return *this;
00630     }
00631     uvector_cx_view_tlate<data_t,complex_t> &operator*=(const data_t &y) {
00632       return *this;
00633     }
00634     //@}
00635 
00636 #endif
00637 
00638   };
00639 
00640   /// uvector_cx typedef
00641   typedef uvector_cx_tlate<double,gsl_complex> uvector_cx;
00642   /// uvector_cx_view typedef
00643   typedef uvector_cx_view_tlate<double,gsl_complex> uvector_cx_view;
00644   /// uvector_cx_array typedef
00645   typedef uvector_cx_array_tlate<double,gsl_complex> uvector_cx_array;
00646   /// uvector_cx_subvector typedef
00647   typedef uvector_cx_subvector_tlate<double,gsl_complex> uvector_cx_subvector;
00648   /// uvector_cx_const_array typedef
00649   typedef uvector_cx_const_array_tlate<double,gsl_complex> 
00650     uvector_cx_const_array;
00651   /// uvector_cx_const_subvector typedef
00652   typedef uvector_cx_const_subvector_tlate<double,gsl_complex> 
00653     uvector_cx_const_subvector;
00654   
00655   /** 
00656       \brief A operator for naive vector output
00657 
00658       This outputs all of the vector elements. All of these are
00659       separated by one space character, though no trailing space or \c
00660       endl is sent to the output.
00661   */
00662   template<class data_t, class complex_t>
00663     std::ostream &operator<<
00664     (std::ostream &os, 
00665      const uvector_cx_view_tlate<data_t,complex_t> &v) {
00666     if (v.size()>0) {
00667       for(size_t i=0;i<v.size()-1;i++) {
00668         os << v[i] << ' ';
00669       }
00670       os << v[v.size()-1];
00671     } else {
00672       os << "<empty>";
00673     }
00674     return os;
00675   }
00676 
00677 #ifndef DOXYGENP
00678 }
00679 #endif
00680 
00681 #endif
00682 

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