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

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.