• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files

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