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