ovector_cx_tlate.h

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

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