ovector_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_OVECTOR_CX_TLATE_H
00024 #define O2SCL_OVECTOR_CX_TLATE_H
00025 
00026 /** \file ovector_cx_tlate.h
00027     \brief File for definitions of complex vectors
00028 */
00029 
00030 #include <iostream>
00031 #include <cstdlib>
00032 #include <string>
00033 #include <fstream>
00034 #include <sstream>
00035 #include <vector>
00036 #include <complex>
00037 #include <o2scl/err_hnd.h>
00038 #include <o2scl/ovector_tlate.h>
00039 #include <gsl/gsl_vector.h>
00040 #include <gsl/gsl_complex.h>
00041 
00042 #ifndef DOXYGENP
00043 namespace o2scl {
00044 #endif
00045 
00046   /// Convert a complex number to GSL form
00047   extern gsl_complex complex_to_gsl(std::complex<double> &d);
00048   
00049   /// Convert a complex number to STL form
00050   extern std::complex<double> gsl_to_complex(gsl_complex &g);
00051   
00052   /** 
00053       \brief A vector view of double-precision numbers
00054 
00055       \todo Move conversion b/w complex<double> and gsl_complex
00056       to cx_arith.h
00057   */
00058   template<class data_t, class vparent_t, class block_t, class complex_t> 
00059     class ovector_cx_view_tlate : 
00060     public vparent_t {
00061     
00062     protected:
00063 
00064     public:
00065     
00066     /// \name Copy constructors
00067     //@{
00068     /// So2scllow copy constructor - create a new view of the same vector
00069     ovector_cx_view_tlate(const ovector_cx_view_tlate &v) {
00070       vparent_t::block=NULL;
00071       vparent_t::data=v.data;
00072       vparent_t::size=v.size;
00073       vparent_t::stride=v.stride;
00074       vparent_t::owner=0;      
00075     }
00076     
00077     /// So2scllow copy constructor - create a new view of the same vector
00078     ovector_cx_view_tlate& operator=(const ovector_cx_view_tlate &v) {
00079       vparent_t::block=NULL;
00080       vparent_t::data=v.data;
00081       vparent_t::size=v.size;
00082       vparent_t::stride=v.stride;
00083       vparent_t::owner=0;      
00084 
00085       return *this;
00086     }
00087     //@}
00088 
00089     ~ovector_cx_view_tlate() {};
00090     
00091     /// \name Get and set methods
00092     //@{
00093     /** 
00094         \brief Array-like indexing 
00095     */
00096     complex_t &operator[](size_t i) {
00097 #if GSL_RANGE_CHECK
00098       if (i>=vparent_t::size) {
00099         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00100                  +" in ovector_cx_view_tlate::operator[]. Size: "+
00101                  itos(vparent_t::size)+
00102                  " (index should be less than size).").c_str(),gsl_index);
00103         return *(complex_t *)vparent_t::data;
00104       }
00105 #endif
00106       return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2);
00107     }
00108     
00109     /** 
00110         \brief Array-like indexing 
00111     */
00112     const complex_t &operator[](size_t i) const {
00113 #if GSL_RANGE_CHECK
00114       if (i>=vparent_t::size) {
00115         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00116                  +" in ovector_cx_view_tlate::operator[] const. Size: "+
00117                  itos(vparent_t::size)+
00118                  " (index should be less than size).").c_str(),gsl_index);
00119         return *(complex_t *)vparent_t::data;
00120       }
00121 #endif
00122       return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2);
00123     }
00124     
00125     /** 
00126         \brief Array-like indexing 
00127     */
00128     complex_t &operator()(size_t i) {
00129 #if GSL_RANGE_CHECK
00130       if (i>=vparent_t::size) {
00131         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00132                  +" in ovector_cx_view_tlate::operator(). Size: "+
00133                  itos(vparent_t::size)+
00134                  " (index should be less than size).").c_str(),gsl_index);
00135         return *(complex_t *)vparent_t::data;
00136       }
00137 #endif
00138       return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2);
00139     }
00140     
00141     /** 
00142         \brief Array-like indexing 
00143     */
00144     const complex_t &operator()(size_t i) const {
00145 #if GSL_RANGE_CHECK
00146       if (i>=vparent_t::size) {
00147         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00148                  +" in ovector_cx_view_tlate::operator() const. Size: "+
00149                  itos(vparent_t::size)+
00150                  " (index should be less than size).").c_str(),gsl_index);
00151         return *(complex_t *)vparent_t::data;
00152       }
00153 #endif
00154       return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2);
00155     }
00156        
00157     /** \brief Get (with optional range-checking) */
00158     complex_t get(size_t i) const {
00159 #if GSL_RANGE_CHECK
00160       if (i>=vparent_t::size) {
00161         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00162                  +" in ovector_cx_view_tlate::get(). Size: "+
00163                  itos(vparent_t::size)+
00164                  " (index should be less than size).").c_str(),gsl_index);
00165         return *(complex_t *)vparent_t::data;
00166       }
00167 #endif
00168       return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2);
00169     }
00170     
00171     /** \brief Get real part (with optional range-checking) */
00172     data_t real(size_t i) const {
00173 #if GSL_RANGE_CHECK
00174       if (i>=vparent_t::size) {
00175         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00176                  +" in ovector_cx_view_tlate::real(). Size: "+
00177                  itos(vparent_t::size)+
00178                  " (index should be less than size).").c_str(),gsl_index);
00179         return *(data_t *)vparent_t::data;
00180       }
00181 #endif
00182       return *(data_t *)(vparent_t::data+i*vparent_t::stride*2);
00183     }
00184     
00185     /** \brief Get imaginary part (with optional range-checking) */
00186     data_t imag(size_t i) const {
00187 #if GSL_RANGE_CHECK
00188       if (i>=vparent_t::size) {
00189         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00190                  +" in ovector_cx_view_tlate::imag(). Size: "+
00191                  itos(vparent_t::size)+
00192                  " (index should be less than size).").c_str(),gsl_index);
00193         return *(data_t *)vparent_t::data;
00194       }
00195 #endif
00196       return *(data_t *)(vparent_t::data+i*vparent_t::stride*2+1);
00197     }
00198     
00199     /** \brief Get STL-like complex number (with optional range-checking) */
00200     std::complex<data_t> get_stl(size_t i) const {
00201 #if GSL_RANGE_CHECK
00202       if (i>=vparent_t::size) {
00203         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00204                  +" in ovector_cx_view_tlate::get_stl(). Size: "+
00205                  itos(vparent_t::size)+
00206                  " (index should be less than size).").c_str(),gsl_index);
00207         std::complex<data_t> zero(0,0);
00208         return zero;
00209       }
00210 #endif
00211       return *(std::complex<data_t> *)(vparent_t::data+i*vparent_t::stride*2);
00212     }
00213     
00214     /** \brief Get pointer (with optional range-checking) */
00215     complex_t *get_ptr(size_t i) {
00216 #if GSL_RANGE_CHECK
00217       if (i>=vparent_t::size) {
00218         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00219                  +" in ovector_cx_view_tlate::get_ptr(). Size: "+
00220                  itos(vparent_t::size)+
00221                  " (index should be less than size).").c_str(),gsl_index);
00222         return (complex_t *)vparent_t::data;
00223       }
00224 #endif
00225       return (complex_t *)(vparent_t::data+i*vparent_t::stride*2);
00226     }
00227     
00228     /** \brief Get pointer (with optional range-checking) */
00229     const complex_t *get_const_ptr(size_t i) const {
00230 #if GSL_RANGE_CHECK
00231       if (i>=vparent_t::size) {
00232         set_err((((std::string)"Array index ")+itos(i)+" out of bounds"
00233                  +" in ovector_cx_view_tlate::get_const_ptr(). Size: "+
00234                  itos(vparent_t::size)+
00235                  " (index should be less than size).").c_str(),gsl_index);
00236         return (complex_t *)vparent_t::data;
00237       }
00238 #endif
00239       return (const complex_t *)(vparent_t::data+i*vparent_t::stride*2);
00240     }
00241     
00242     /** \brief Set (with optional range-checking) */
00243     int set(size_t i, const complex_t &val) {
00244 #if GSL_RANGE_CHECK
00245       if (i>=vparent_t::size) {
00246         set_err_ret((((std::string)"Array index ")+itos(i)+" out of bounds"
00247                      +" in ovector_cx_view_tlate::set(). Size: "+
00248                      itos(vparent_t::size)+
00249                      " (index should be less than size).").c_str(),gsl_index);
00250       }
00251 #endif
00252       vparent_t::data[i*vparent_t::stride*2]=GSL_REAL(val);
00253       vparent_t::data[i*vparent_t::stride*2+1]=GSL_IMAG(val);
00254       return 0;
00255     }
00256 
00257     /** \brief Set (with optional range-checking) */
00258     int set_stl(size_t i, const std::complex<data_t> &d) {
00259 #if GSL_RANGE_CHECK
00260       if (i>=vparent_t::size) {
00261         set_err_ret((((std::string)"Array index ")+itos(i)+" out of bounds"
00262                      +" in ovector_cx_view_tlate::set_stl(). Size: "+
00263                      itos(vparent_t::size)+
00264                      " (index should be less than size).").c_str(),gsl_index);
00265       }
00266 #endif
00267       vparent_t::data[i*vparent_t::stride*2]=d.real();
00268       vparent_t::data[i*vparent_t::stride*2+1]=d.imag();
00269       return 0;
00270     }
00271 
00272     /** \brief Set (with optional range-checking) */
00273     int set(size_t i, data_t vr, data_t vi) {
00274 #if GSL_RANGE_CHECK
00275       if (i>=vparent_t::size) {
00276         set_err_ret((((std::string)"Array index ")+itos(i)+" out of bounds"
00277                      +" in ovector_cx_view_tlate::set(). Size: "+
00278                      itos(vparent_t::size)+
00279                      " (index should be less than size).").c_str(),gsl_index);
00280       }
00281 #endif
00282       vparent_t::data[i*vparent_t::stride*2]=vr;
00283       vparent_t::data[i*vparent_t::stride*2+1]=vi;
00284       return 0;
00285     }
00286 
00287     /** \brief Set all of the value to be the value \c val */
00288     int set_all(const complex_t &g) {
00289       for(size_t i=0;i<vparent_t::size;i++) {
00290         data_t gr=GSL_REAL(g), gi=GSL_IMAG(g);
00291         vparent_t::data[i*vparent_t::stride]=gr;
00292         vparent_t::data[i*vparent_t::stride+1]=gi;
00293       }
00294       return 0;
00295     }
00296 
00297     /** 
00298         \brief Method to return vector size 
00299         
00300         If no memory has been allocated, this will quietly 
00301         return zero.
00302     */
00303     size_t size() const {
00304       return vparent_t::size;
00305     }
00306 
00307     /** 
00308         \brief Method to return vector stride
00309         
00310         If no memory has been allocated, this will quietly 
00311         return zero.
00312     */
00313     size_t stride() const {
00314       return vparent_t::stride;
00315     }
00316     //@}
00317 
00318     /// \name Other methods
00319     //@{
00320     /// Return true if this object owns the data it refers to
00321     bool is_owner() const {
00322       if (vparent_t::owner==1) return true;
00323       return false;
00324     }
00325     //@}
00326 
00327     /// \name Arithmetic
00328     //@{
00329     /** \brief operator+= */
00330     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+=
00331       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00332       size_t lsize=x.size;
00333       if (lsize>size) lsize=size;
00334       for(size_t i=0;i<lsize;i++) {
00335         vparent_t::data[i*vparent_t::stride*2]+=x.data[i*x.stride*2];
00336         vparent_t::data[i*vparent_t::stride*2+1]+=x.data[i*x.stride*2+1];
00337       }
00338       
00339       return *this;
00340     }
00341     
00342     /** \brief operator-= */
00343     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-=
00344       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00345       size_t lsize=x.size;
00346       if (lsize>size) lsize=size;
00347       for(size_t i=0;i<lsize;i++) {
00348         vparent_t::data[i*vparent_t::stride*2]-=x.data[i*x.stride*2];
00349         vparent_t::data[i*vparent_t::stride*2+1]-=x.data[i*x.stride*2+1];
00350       }
00351       
00352       return *this;
00353     }
00354     
00355     /** \brief operator+= */
00356     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+=
00357       (const complex_t &x) {
00358       data_t re=*(data_t *)x;
00359       data_t im=*(((data_t *)x)+1);
00360       for(size_t i=0;i<size;i++) {
00361         vparent_t::data[i*vparent_t::stride*2]+=re;
00362         vparent_t::data[i*vparent_t::stride*2+1]+=im;
00363       }
00364       
00365       return *this;
00366     }
00367 
00368     /** \brief operator-= */
00369     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-=
00370       (const complex_t &x) {
00371       data_t re=*(data_t *)x;
00372       data_t im=*(((data_t *)x)+1);
00373       for(size_t i=0;i<size;i++) {
00374         vparent_t::data[i*vparent_t::stride*2]-=re;
00375         vparent_t::data[i*vparent_t::stride*2+1]-=im;
00376       }
00377       
00378       return *this;
00379     }
00380 
00381     /** \brief operator*= */
00382     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*=
00383       (const complex_t &x) {
00384       data_t re=*(data_t *)x;
00385       data_t im=*(((data_t *)x)+1);
00386       for(size_t i=0;i<size;i++) {
00387         data_t rold=vparent_t::data[i*vparent_t::stride*2];
00388         data_t iold=vparent_t::data[i*vparent_t::stride*2+1];
00389         vparent_t::data[i*vparent_t::stride*2]=re*rold-im*iold;
00390         vparent_t::data[i*vparent_t::stride*2+1]=re*iold+im*rold;
00391       }
00392       
00393       return *this;
00394     }
00395 
00396     /** \brief operator+= */
00397     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+=
00398       (const data_t &x) {
00399       for(size_t i=0;i<size;i++) {
00400         vparent_t::data[i*vparent_t::stride*2]+=x;
00401       }
00402       
00403       return *this;
00404     }
00405 
00406     /** \brief operator-= */
00407     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-=
00408       (const data_t &x) {
00409       for(size_t i=0;i<size;i++) {
00410         vparent_t::data[i*vparent_t::stride*2]-=x;
00411       }
00412       
00413       return *this;
00414     }
00415 
00416     /** \brief operator*= */
00417     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*=
00418       (const data_t &x) {
00419       for(size_t i=0;i<size;i++) {
00420         vparent_t::data[i*vparent_t::stride*2]*=x;
00421         vparent_t::data[i*vparent_t::stride*2+1]*=x;
00422       }
00423       
00424       return *this;
00425     }
00426     //@}
00427     
00428     /// Conjugate the vector
00429     int conjugate() {
00430       size_t sz=vparent_t::size;
00431       for(size_t i=0;i<sz;i++) {
00432         data_t tmp=(*this)[i].dat[1];
00433         (*this)[i].dat[1]=-tmp;
00434         //vparent_t::data[i*vparent_t::stride*2+1]*=-1.0;
00435       }
00436       return 0;
00437     }
00438 
00439     /** \brief Complex norm \f$ v^{\dagger} v \f$ */
00440     data_t norm() const {
00441       data_t result=0;
00442       for(size_t i=0;i<vparent_t::size;i++) {
00443         data_t re=vparent_t::data[i*vparent_t::stride*2];
00444         data_t im=vparent_t::data[i*vparent_t::stride*2+1];
00445         std::cout << "ocn: " << re << " " << im << std::endl;
00446         result+=re*re+im*im;
00447       }
00448       return sqrt(result);
00449     }
00450 
00451 #ifndef DOXYGEN_INTERNAL
00452 
00453     protected:
00454 
00455     /** \brief Empty constructor provided for use by 
00456         ovector_cx_tlate(const ovector_cx_tlate &v) [protected] 
00457     */
00458     ovector_cx_view_tlate() {};
00459 
00460 #endif
00461     
00462   };
00463 
00464   /** 
00465       \brief A vector of double-precision numbers
00466   
00467       If the memory allocation fails, either in the constructor or in
00468       allocate(), then the error handler will be called, partially
00469       allocated memory will be freed, and the size will be reset to
00470       zero. You can test to see if the allocation succeeded using
00471       something like
00472       \code
00473       const size_t n=10;
00474       ovector_cx x(10);
00475       if (x.size()==0) cout << "Failed." << endl;
00476       \endcode
00477 
00478       \todo There is a slight difference between how this works in
00479       comparison to MV++. The function allocate() operates a little
00480       differently than newsize(), as it will feel free to allocate new
00481       memory when owner is false. It's not clear if this is an
00482       issue, however, since it doesn't appear possible to
00483       create an \ref ovector_cx_tlate with a value of \c owner equal
00484       to zero. This situation ought to be clarified further.
00485 
00486       \todo Add subvector_stride, const_subvector_stride
00487 
00488   */
00489   template<class data_t, class vparent_t, class block_t, class complex_t> 
00490     class ovector_cx_tlate : 
00491     public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> {
00492     public:
00493 
00494     /// \name Standard constructor 
00495     //@{
00496     /** \brief Create an ovector_cx of size \c n with owner as 'true' */
00497     ovector_cx_tlate(size_t n=0) {
00498 
00499       vparent_t::data=0;
00500       vparent_t::size=0;
00501       vparent_t::stride=0;
00502 
00503       // This must be set to 1 even if n=0 so that future
00504       // calls to operator= work properly
00505       vparent_t::owner=1;
00506 
00507       if (n>0) {
00508         vparent_t::block=(block_t *)malloc(sizeof(block_t));
00509         if (vparent_t::block) {
00510           vparent_t::block->data=(data_t *)malloc(2*n*sizeof(data_t));
00511           if (vparent_t::block->data) {
00512             vparent_t::block->size=n;
00513             vparent_t::data=vparent_t::block->data;
00514             vparent_t::size=n;
00515             vparent_t::stride=1;
00516           } else {
00517             std::free(vparent_t::block);
00518             set_err("No memory for data in ovector_cx_tlate constructor",
00519                     gsl_enomem);
00520           }
00521         } else {
00522           set_err("No memory for block in ovector_cx_tlate contructor",
00523                   gsl_enomem);
00524         }
00525       }
00526     }
00527     //@}
00528     
00529     /// \name Copy constructors
00530     //@{
00531     /// Deep copy constructor, allocate new space and make a copy
00532     ovector_cx_tlate(const ovector_cx_tlate &v) : 
00533       ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t>() {
00534       size_t n=v.size();
00535       if (n>0) {
00536         vparent_t::block=(block_t *)malloc(sizeof(block_t));
00537         if (vparent_t::block) {
00538           vparent_t::block->data=(data_t *)malloc(2*n*sizeof(data_t));
00539           if (vparent_t::block->data) {
00540             vparent_t::block->size=n;
00541             vparent_t::data=vparent_t::block->data;
00542             vparent_t::size=n;
00543             vparent_t::stride=1;
00544             vparent_t::owner=1;
00545             for(size_t i=0;i<n;i++) {
00546               vparent_t::data[2*i]=v.data[2*i*v.stride()];
00547               vparent_t::data[2*i+1]=v.data[2*i*v.stride()+1];
00548             }
00549           } else {
00550             std::free(vparent_t::block);
00551             set_err("No memory for data in ovector_cx_tlate constructor",
00552                     gsl_enomem);
00553           }
00554         } else {
00555           set_err("No memory for block in ovector_cx_tlate contructor",
00556                   gsl_enomem);
00557         }
00558       } else {
00559         vparent_t::size=0;
00560         vparent_t::stride=0;
00561       }
00562     }
00563     
00564     /// Deep copy constructor, allocate new space and make a copy
00565     ovector_cx_tlate
00566       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &v) : 
00567       ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t>() {
00568       size_t n=v.size();
00569       if (n>0) {
00570         vparent_t::block=(block_t *)malloc(sizeof(block_t));
00571         if (vparent_t::block) {
00572           vparent_t::block->data=(data_t *)malloc(2*n*sizeof(data_t));
00573           if (vparent_t::block->data) {
00574             vparent_t::block->size=n;
00575             vparent_t::data=vparent_t::block->data;
00576             vparent_t::size=n;
00577             vparent_t::stride=1;
00578             vparent_t::owner=1;
00579             for(size_t i=0;i<n;i++) {
00580               vparent_t::data[2*i]=v.data[2*i*v.stride()];
00581               vparent_t::data[2*i+1]=v.data[2*i*v.stride()+1];
00582             }
00583           } else {
00584             std::free(vparent_t::block);
00585             set_err("No memory for data in ovector_cx_tlate constructor",
00586                     gsl_enomem);
00587           }
00588         } else {
00589           set_err("No memory for block in ovector_cx_tlate contructor",
00590                   gsl_enomem);
00591         }
00592       } else {
00593         vparent_t::size=0;
00594         vparent_t::stride=0;
00595       }
00596     }
00597     
00598     /** \brief Deep copy constructor, if owner is true, allocate space and
00599         make a new copy, otherwise, just copy into the view
00600     */
00601     ovector_cx_tlate& operator=(const ovector_cx_tlate &v) {
00602       size_t size=v.size;
00603       if (vparent_t::owner) {
00604         allocate(size);
00605       } else {
00606         if (vparent_t::size!=size) {
00607           set_err("Sizes don't match in ovector_cx_tlate::operator=()",
00608                   gsl_ebadlen);
00609           return *this;
00610         }
00611       }
00612       for(size_t i=0;i<size;i++) {
00613         vparent_t::data[2*i*vparent_t::stride]=v.data[2*i*v.stride()];
00614         vparent_t::data[2*i*vparent_t::stride+1]=v.data[2*i*v.stride()+1];
00615       }
00616       return *this;
00617     }
00618 
00619     /** \brief Deep copy constructor, if owner is true, allocate space and
00620         make a new copy, otherwise, just copy into the view
00621     */
00622     ovector_cx_tlate& operator=
00623       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &v) {
00624       size_t size=v.size();
00625       if (vparent_t::owner) {
00626         allocate(size);
00627       } else {
00628         if (vparent_t::size!=size) {
00629           set_err("Sizes don't match in ovector_cx_tlate::operator=()",
00630                   gsl_ebadlen);
00631           return *this;
00632         }
00633       }
00634       for(size_t i=0;i<size;i++) {
00635         vparent_t::data[2*i*vparent_t::stride]=v.data[2*i*v.stride()];
00636         vparent_t::data[2*i*vparent_t::stride+1]=v.data[2*i*v.stride()+1];
00637       }
00638       return *this;
00639     }
00640     //@}
00641 
00642     ~ovector_cx_tlate() {
00643       if (vparent_t::size>0) {
00644         if (vparent_t::owner==1) {
00645           if (vparent_t::block->size>0) {
00646             std::free(vparent_t::block->data);
00647           }
00648           std::free(vparent_t::block);
00649           vparent_t::size=0;
00650         }
00651       }
00652     }
00653     
00654     /// \name Memory allocation
00655     //@{
00656     /** 
00657         \brief Allocate memory for size \c n after freeing any memory
00658         presently in use
00659     */
00660     int allocate(size_t nsize) {
00661       if (vparent_t::size>0) free();
00662 
00663       if (nsize>0) {
00664         vparent_t::block=(block_t *)malloc(sizeof(block_t));
00665         if (vparent_t::block) {
00666           vparent_t::block->data=(data_t *)malloc(2*nsize*sizeof(data_t));
00667           if (vparent_t::block->data) {
00668             vparent_t::block->size=nsize;
00669             vparent_t::data=vparent_t::block->data;
00670             vparent_t::size=nsize;
00671             vparent_t::stride=1;
00672             vparent_t::owner=1;
00673           } else {
00674             std::free(vparent_t::block);
00675             set_err_ret("No memory for data in ovector_cx_tlate::allocate()",
00676                         gsl_enomem);
00677           }
00678         } else {
00679           set_err_ret("No memory for block in ovector_cx_tlate::allocate()",
00680                       gsl_enomem);
00681         }
00682       } else {
00683         set_err_ret("Zero size in ovector_cx::allocate()",gsl_einval);
00684       }
00685       return 0;
00686     }
00687 
00688     /** 
00689         \brief Free the memory 
00690     
00691         This function will safely do nothing if used without first
00692         allocating memory or if called multiple times in succession.
00693     */
00694     int free() {
00695       if (vparent_t::size>0) {
00696         if (vparent_t::owner==1) {
00697           if (vparent_t::block->size>0) {
00698             std::free(vparent_t::block->data);
00699           }
00700           std::free(vparent_t::block);
00701         }
00702         vparent_t::size=0;
00703         vparent_t::stride=0;
00704       }
00705       return 0;
00706     }
00707     //@}
00708     
00709     /// \name Other methods
00710     //@{
00711     /** \brief Return a gsl vector_cx */
00712     vparent_t *get_gsl_vector_complex() { return this; }
00713     
00714     /** \brief Return a gsl vector_cx */
00715     const vparent_t *get_gsl_vector_complex_const() const
00716       { return this; }
00717     //@}
00718     
00719   };
00720 
00721   /** \brief Create a vector from an array 
00722   */
00723   template<class data_t, class vparent_t, class block_t, class complex_t> 
00724     class ovector_cx_array_tlate : 
00725     public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> {
00726     public:
00727     /** \brief Create a vector from \c dat with size \c n */
00728     ovector_cx_array_tlate(size_t n, complex_t *dat) {
00729       if (n>0) {
00730         vparent_t::block=NULL;
00731         vparent_t::data=dat;
00732         vparent_t::size=n;
00733         vparent_t::stride=1;
00734         vparent_t::owner=0;
00735       }
00736     }
00737   };
00738 
00739   /** \brief Create a vector from an array with a stride 
00740   */
00741   template<class data_t, class vparent_t, class block_t, class complex_t> 
00742     class ovector_cx_array_stride_tlate : 
00743     public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> {
00744     public:
00745     /** \brief Create a vector from \c dat with size \c n and stride \c s 
00746      */
00747     ovector_cx_array_stride_tlate(size_t n, complex_t *dat, size_t s) {
00748       if (n>0) {
00749         vparent_t::block=NULL;
00750         vparent_t::data=dat;
00751         vparent_t::size=n;
00752         vparent_t::stride=s;
00753         vparent_t::owner=0;
00754       }
00755     }
00756   };
00757 
00758   /** \brief Create a vector from a subvector of another
00759   */
00760   template<class data_t, class vparent_t, class block_t, class complex_t> 
00761     class ovector_cx_subvector_tlate : 
00762     public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> {
00763     public:
00764     /** \brief Create a vector from \c orig      */
00765     ovector_cx_subvector_tlate
00766       (ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &orig, 
00767        size_t offset, size_t n) {
00768       
00769       vparent_t::size=0;
00770       vparent_t::stride=0;
00771       vparent_t::data=0;
00772 
00773       if (offset+n-1<orig.size()) {
00774         vparent_t::block=NULL;
00775         vparent_t::data=orig.data+offset*2*orig.stride();
00776         vparent_t::size=n;
00777         vparent_t::stride=orig.stride();
00778         vparent_t::owner=0;
00779       } else {
00780         set_err("Subvector failed in ovector_cx_sub_view().",1);
00781       }
00782     }
00783   };
00784 
00785   /** \brief Create a vector from an array 
00786   */
00787   template<class data_t, class vparent_t, class block_t, class complex_t> 
00788     class ovector_cx_const_array_tlate :
00789     public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> {
00790     public:
00791     /** \brief Create a vector from \c dat with size \c n */
00792     ovector_cx_const_array_tlate(size_t n, const complex_t *dat) {
00793       if (n>0) {
00794         vparent_t::block=NULL;
00795         // We have to do an explicit cast here, but we prevent the
00796         // user from changing the data.
00797         vparent_t::data=(data_t *)dat;
00798         vparent_t::size=n;
00799         vparent_t::stride=1;
00800         vparent_t::owner=0;
00801       }
00802     }
00803     
00804     ~ovector_cx_const_array_tlate() {};
00805     
00806 #ifndef DOXYGEN_INTERNAL
00807 
00808     protected:
00809     
00810     /** \name These are inaccessible to ensure the vector is \c const.
00811     */
00812     //@{
00813     data_t &operator[](size_t i) { return vparent_t::data[0]; }
00814     data_t &operator()(size_t i) { return vparent_t::data[0]; }
00815     data_t *get_ptr(size_t i) { return NULL; }
00816     int set(size_t i, data_t val) { return 0; }
00817     int swap(ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00818       return 0; 
00819     }
00820     int set_all(double val) { return 0; }
00821     vparent_t *get_gsl_vector() { return NULL; }
00822     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+=
00823       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00824       return *this;
00825     }
00826     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-=
00827       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00828       return *this;
00829     }
00830     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*=
00831       (const data_t &y) {
00832       return *this;
00833     }
00834     //@}
00835       
00836 #endif
00837 
00838   };
00839 
00840   /** \brief Create a vector from an array_stride 
00841   */
00842   template<class data_t, class vparent_t, class block_t, class complex_t> 
00843     class ovector_cx_const_array_stride_tlate : 
00844     public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> {
00845     public:
00846     /** \brief Create a vector from \c dat with size \c n */
00847     ovector_cx_const_array_stride_tlate(size_t n, const complex_t *dat, 
00848                                         size_t s) {
00849       if (n>0) {
00850         vparent_t::block=NULL;
00851         // We have to do an explicit cast here, but we prevent the
00852         // user from changing the data.
00853         vparent_t::data=(data_t *)dat;
00854         vparent_t::size=n;
00855         vparent_t::stride=s;
00856         vparent_t::owner=0;
00857       }
00858     }
00859 
00860 #ifndef DOXYGEN_INTERNAL
00861 
00862     protected:
00863     
00864     /** \name These are inaccessible to ensure the vector is \c const.
00865     */
00866     //@{
00867     data_t &operator[](size_t i) { return vparent_t::data[0]; }
00868     data_t &operator()(size_t i) { return vparent_t::data[0]; }
00869     data_t *get_ptr(size_t i) { return NULL; }
00870     int set(size_t i, data_t val) { return 0; }
00871     int swap(ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00872       return 0; 
00873     }
00874     int set_all(double val) { return 0; }
00875     vparent_t *get_gsl_vector() { return NULL; }
00876     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+=
00877       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00878       return *this;
00879     }
00880     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-=
00881       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00882       return *this;
00883     }
00884     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*=
00885       (const data_t &y) {
00886       return *this;
00887     }
00888     //@}
00889 
00890 #endif
00891 
00892   };
00893 
00894   /** \brief Create a vector from a subvector of another
00895   */
00896   template<class data_t, class vparent_t, class block_t, class complex_t> 
00897     class ovector_cx_const_subvector_tlate :
00898     public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> {
00899     public:
00900     /** \brief Create a vector from \c orig 
00901      */
00902     ovector_cx_const_subvector_tlate
00903       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &orig, 
00904        size_t offset, size_t n) {
00905       if (offset+n-1<orig.size) {
00906         vparent_t::block=NULL;
00907         vparent_t::data=orig.data+offset*2*orig.stride;
00908         vparent_t::size=n;
00909         vparent_t::stride=orig.stride;
00910         vparent_t::owner=0;
00911       } else {
00912         vparent_t::size=0;
00913         set_err("Subvector failed in ovector_cx_subvector().",1);
00914       }
00915     }
00916 
00917 #ifndef DOXYGEN_INTERNAL
00918 
00919   protected:
00920 
00921     /** \name These are inaccessible to ensure the vector is \c const.
00922     */
00923     //@{
00924     data_t &operator[](size_t i) { return vparent_t::data[0]; }
00925     data_t &operator()(size_t i) { return vparent_t::data[0]; }
00926     data_t *get_ptr(size_t i) { return NULL; }
00927     int set(size_t i, data_t val) { return 0; }
00928     int swap(ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00929       return 0; 
00930     }
00931     int set_all(double val) { return 0; }
00932     vparent_t *get_gsl_vector() { return NULL; }
00933     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+=
00934       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00935       return *this;
00936     }
00937     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-=
00938       (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) {
00939       return *this;
00940     }
00941     ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*=
00942       (const data_t &y) {
00943       return *this;
00944     }
00945     //@}
00946 
00947 #endif
00948 
00949   };
00950 
00951   /** \brief Create a real vector from the real parts of a complex vector
00952    */
00953   template<class data_t, class vparent_t, class block_t, 
00954     class cvparent_t, class cblock_t, class complex_t> 
00955     class ovector_cx_real_tlate :
00956     public ovector_view_tlate<data_t,vparent_t,block_t> {
00957     public:
00958     /** \brief Create a real vector from the real parts of a complex vector
00959      */
00960     ovector_cx_real_tlate
00961       (ovector_cx_view_tlate<data_t,cvparent_t,cblock_t,complex_t> &x) {
00962       vparent_t::block=NULL;
00963       vparent_t::data=x.data;
00964       vparent_t::size=x.size;
00965       vparent_t::stride=2*x.stride;
00966       vparent_t::owner=false;
00967     }
00968   };
00969 
00970   /** \brief Create a imaginary vector from the imaginary parts of a 
00971       complex vector
00972    */
00973   template<class data_t, class vparent_t, class block_t, 
00974     class cvparent_t, class cblock_t, class complex_t> 
00975     class ovector_cx_imag_tlate :
00976     public ovector_view_tlate<data_t,vparent_t,block_t> {
00977     public:
00978     /** \brief Create a imaginary vector from the imaginary parts of a 
00979         complex vector
00980      */
00981     ovector_cx_imag_tlate
00982       (ovector_cx_view_tlate<data_t,cvparent_t,cblock_t,complex_t> &x) {
00983       vparent_t::block=NULL;
00984       vparent_t::data=x.data+1;
00985       vparent_t::size=x.size;
00986       vparent_t::stride=2*x.stride;
00987       vparent_t::owner=false;
00988     }
00989   };
00990   
00991   /** \brief A vector where the memory allocation is performed in 
00992       the constructor
00993   */
00994 #ifdef DOXYGENP
00995   template<size_t N=0> class ofvector_cx : 
00996     public ovector_cx_tlate<data_t,vparent_t,block_t,complex_t>
00997 #else
00998     template<size_t N=0> class ofvector_cx : 
00999     public ovector_cx_tlate<double,gsl_vector_complex,gsl_block_complex,
01000     gsl_complex>
01001 #endif
01002     {
01003       public:
01004       ofvector_cx() : ovector_cx_tlate<double,gsl_vector_complex,
01005       gsl_block_complex,gsl_complex>(N) {
01006       }
01007     };
01008 
01009   /// ovector_cx typedef
01010   typedef ovector_cx_tlate<double,gsl_vector_complex,gsl_block_complex,
01011     gsl_complex> ovector_cx;
01012   /// ovector_cx_view typedef
01013   typedef ovector_cx_view_tlate<double,gsl_vector_complex,gsl_block_complex,
01014     gsl_complex> ovector_cx_view;
01015   /// ovector_cx_array typedef
01016   typedef ovector_cx_array_tlate<double,gsl_vector_complex,gsl_block_complex,
01017     gsl_complex> ovector_cx_array;
01018   /// ovector_cx_array_stride typedef
01019   typedef ovector_cx_array_stride_tlate<double,gsl_vector_complex,
01020     gsl_block_complex,gsl_complex> 
01021     ovector_cx_array_stride;
01022   /// ovector_cx_subvector typedef
01023   typedef ovector_cx_subvector_tlate<double,gsl_vector_complex,
01024     gsl_block_complex,gsl_complex> 
01025     ovector_cx_subvector;
01026   /// ovector_cx_const_array typedef
01027   typedef ovector_cx_const_array_tlate<double,gsl_vector_complex,
01028     gsl_block_complex,gsl_complex> 
01029     ovector_cx_const_array;
01030   /// ovector_cx_const_array_stride typedef
01031   typedef ovector_cx_const_array_stride_tlate<double,gsl_vector_complex,
01032     gsl_block_complex,gsl_complex> 
01033     ovector_cx_const_array_stride;
01034   /// ovector_cx_const_subvector typedef
01035   typedef ovector_cx_const_subvector_tlate<double,gsl_vector_complex,
01036     gsl_block_complex,gsl_complex> 
01037     ovector_cx_const_subvector;
01038   /// ovector_cx_real typedef
01039   typedef ovector_cx_real_tlate<double,gsl_vector,gsl_block,
01040     gsl_vector_complex,gsl_block_complex,gsl_complex> ovector_cx_real;
01041   /// ovector_cx_imag typedef
01042   typedef ovector_cx_imag_tlate<double,gsl_vector,gsl_block,
01043     gsl_vector_complex,gsl_block_complex,gsl_complex> ovector_cx_imag;
01044 
01045   /** \brief Conjugate a vector */
01046   template<class data_t,class vparent_t,class block_t, class complex_t>
01047     ovector_cx_tlate<data_t,vparent_t,block_t,complex_t>
01048     conjugate(ovector_cx_tlate<data_t,vparent_t,block_t,complex_t> &v) {
01049     ovector_tlate<data_t,vparent_t,block_t> result(v.size());
01050     for(size_t i=0;i<v.size();i++) {
01051       double *p=vparent_t::data+i*vparent_t::stride*2+1;
01052       (*p)=-(*p);
01053     }
01054     return result;
01055   }
01056 
01057   /** 
01058       \brief A operator for naive vector output
01059 
01060       This outputs all of the vector elements in the form \c (r,i).
01061       All of these are separated by one space character, though no
01062       trailing space or \c endl is sent to the output.
01063   */
01064   template<class data_t, class vparent_t, class block_t, class complex_t> 
01065     std::ostream &operator<<
01066     (std::ostream &os, 
01067      const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &v) {
01068     for(size_t i=0;i<v.size()-1;i++) {
01069       os << '(' << v.real(i) << ',' << v.imag(i) << ") ";
01070     }
01071     os << '(' << v.real(v.size()-1) << ',' 
01072        << v.imag(v.size()-1) << ") ";
01073     return os;
01074   }
01075 
01076 #ifndef DOXYGENP
01077 }
01078 #endif
01079 
01080 #endif
01081 

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