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

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