00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, 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 /** 00049 \brief A vector view of double-precision numbers 00050 00051 */ 00052 template<class data_t, class vparent_t, class block_t, class complex_t> 00053 class ovector_cx_view_tlate : 00054 public vparent_t { 00055 00056 protected: 00057 00058 public: 00059 00060 /// \name Copy constructors 00061 //@{ 00062 /// Shallow copy constructor - create a new view of the same vector 00063 ovector_cx_view_tlate(const ovector_cx_view_tlate &v) { 00064 vparent_t::block=0; 00065 vparent_t::data=v.data; 00066 vparent_t::size=v.size; 00067 vparent_t::stride=v.stride; 00068 vparent_t::owner=0; 00069 } 00070 00071 /// Shallow copy constructor - create a new view of the same vector 00072 ovector_cx_view_tlate& operator=(const ovector_cx_view_tlate &v) { 00073 vparent_t::block=0; 00074 vparent_t::data=v.data; 00075 vparent_t::size=v.size; 00076 vparent_t::stride=v.stride; 00077 vparent_t::owner=0; 00078 00079 return *this; 00080 } 00081 //@} 00082 00083 ~ovector_cx_view_tlate() {}; 00084 00085 /// \name Get and set methods 00086 //@{ 00087 /** 00088 \brief Array-like indexing 00089 */ 00090 complex_t &operator[](size_t i) { 00091 #if O2SCL_NO_RANGE_CHECK 00092 #else 00093 if (i>=vparent_t::size) { 00094 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00095 +" in ovector_cx_view_tlate::operator[]. Size: "+ 00096 itos(vparent_t::size)+ 00097 " (index should be less than size).").c_str(),gsl_eindex); 00098 return *(complex_t *)vparent_t::data; 00099 } 00100 #endif 00101 return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2); 00102 } 00103 00104 /** 00105 \brief Array-like indexing 00106 */ 00107 const complex_t &operator[](size_t i) const { 00108 #if O2SCL_NO_RANGE_CHECK 00109 #else 00110 if (i>=vparent_t::size) { 00111 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00112 +" in ovector_cx_view_tlate::operator[] const. Size: "+ 00113 itos(vparent_t::size)+ 00114 " (index should be less than size).").c_str(),gsl_eindex); 00115 return *(complex_t *)vparent_t::data; 00116 } 00117 #endif 00118 return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2); 00119 } 00120 00121 /** 00122 \brief Array-like indexing 00123 */ 00124 complex_t &operator()(size_t i) { 00125 #if O2SCL_NO_RANGE_CHECK 00126 #else 00127 if (i>=vparent_t::size) { 00128 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00129 +" in ovector_cx_view_tlate::operator(). Size: "+ 00130 itos(vparent_t::size)+ 00131 " (index should be less than size).").c_str(),gsl_eindex); 00132 return *(complex_t *)vparent_t::data; 00133 } 00134 #endif 00135 return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2); 00136 } 00137 00138 /** 00139 \brief Array-like indexing 00140 */ 00141 const complex_t &operator()(size_t i) const { 00142 #if O2SCL_NO_RANGE_CHECK 00143 #else 00144 if (i>=vparent_t::size) { 00145 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00146 +" in ovector_cx_view_tlate::operator() const. Size: "+ 00147 itos(vparent_t::size)+ 00148 " (index should be less than size).").c_str(),gsl_eindex); 00149 return *(complex_t *)vparent_t::data; 00150 } 00151 #endif 00152 return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2); 00153 } 00154 00155 /** \brief Get (with optional range-checking) */ 00156 complex_t get(size_t i) const { 00157 #if O2SCL_NO_RANGE_CHECK 00158 #else 00159 if (i>=vparent_t::size) { 00160 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00161 +" in ovector_cx_view_tlate::get(). Size: "+ 00162 itos(vparent_t::size)+ 00163 " (index should be less than size).").c_str(),gsl_eindex); 00164 return *(complex_t *)vparent_t::data; 00165 } 00166 #endif 00167 return *(complex_t *)(vparent_t::data+i*vparent_t::stride*2); 00168 } 00169 00170 /** \brief Get real part (with optional range-checking) */ 00171 data_t real(size_t i) const { 00172 #if O2SCL_NO_RANGE_CHECK 00173 #else 00174 if (i>=vparent_t::size) { 00175 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00176 +" in ovector_cx_view_tlate::real(). Size: "+ 00177 itos(vparent_t::size)+ 00178 " (index should be less than size).").c_str(),gsl_eindex); 00179 return *(data_t *)vparent_t::data; 00180 } 00181 #endif 00182 return *(data_t *)(vparent_t::data+i*vparent_t::stride*2); 00183 } 00184 00185 /** \brief Get imaginary part (with optional range-checking) */ 00186 data_t imag(size_t i) const { 00187 #if O2SCL_NO_RANGE_CHECK 00188 #else 00189 if (i>=vparent_t::size) { 00190 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00191 +" in ovector_cx_view_tlate::imag(). Size: "+ 00192 itos(vparent_t::size)+ 00193 " (index should be less than size).").c_str(),gsl_eindex); 00194 return *(data_t *)vparent_t::data; 00195 } 00196 #endif 00197 return *(data_t *)(vparent_t::data+i*vparent_t::stride*2+1); 00198 } 00199 00200 /** \brief Get STL-like complex number (with optional range-checking) */ 00201 std::complex<data_t> get_stl(size_t i) const { 00202 #if O2SCL_NO_RANGE_CHECK 00203 #else 00204 if (i>=vparent_t::size) { 00205 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00206 +" in ovector_cx_view_tlate::get_stl(). Size: "+ 00207 itos(vparent_t::size)+ 00208 " (index should be less than size).").c_str(),gsl_eindex); 00209 std::complex<data_t> zero(0,0); 00210 return zero; 00211 } 00212 #endif 00213 return *(std::complex<data_t> *)(vparent_t::data+i*vparent_t::stride*2); 00214 } 00215 00216 /** \brief Get pointer (with optional range-checking) */ 00217 complex_t *get_ptr(size_t i) { 00218 #if O2SCL_NO_RANGE_CHECK 00219 #else 00220 if (i>=vparent_t::size) { 00221 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00222 +" in ovector_cx_view_tlate::get_ptr(). Size: "+ 00223 itos(vparent_t::size)+ 00224 " (index should be less than size).").c_str(),gsl_eindex); 00225 return (complex_t *)vparent_t::data; 00226 } 00227 #endif 00228 return (complex_t *)(vparent_t::data+i*vparent_t::stride*2); 00229 } 00230 00231 /** \brief Get pointer (with optional range-checking) */ 00232 const complex_t *get_const_ptr(size_t i) const { 00233 #if O2SCL_NO_RANGE_CHECK 00234 #else 00235 if (i>=vparent_t::size) { 00236 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00237 +" in ovector_cx_view_tlate::get_const_ptr(). Size: "+ 00238 itos(vparent_t::size)+ 00239 " (index should be less than size).").c_str(),gsl_eindex); 00240 return (complex_t *)vparent_t::data; 00241 } 00242 #endif 00243 return (const complex_t *)(vparent_t::data+i*vparent_t::stride*2); 00244 } 00245 00246 /** \brief Set (with optional range-checking) */ 00247 int set(size_t i, const complex_t &val) { 00248 #if O2SCL_NO_RANGE_CHECK 00249 #else 00250 if (i>=vparent_t::size) { 00251 O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds" 00252 +" in ovector_cx_view_tlate::set(). Size: "+ 00253 itos(vparent_t::size)+ 00254 " (index should be less than size).").c_str(),gsl_eindex); 00255 } 00256 #endif 00257 vparent_t::data[i*vparent_t::stride*2]=GSL_REAL(val); 00258 vparent_t::data[i*vparent_t::stride*2+1]=GSL_IMAG(val); 00259 return 0; 00260 } 00261 00262 /** \brief Set (with optional range-checking) */ 00263 int set_stl(size_t i, const std::complex<data_t> &d) { 00264 #if O2SCL_NO_RANGE_CHECK 00265 #else 00266 if (i>=vparent_t::size) { 00267 O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds" 00268 +" in ovector_cx_view_tlate::set_stl(). Size: "+ 00269 itos(vparent_t::size)+ 00270 " (index should be less than size).").c_str(),gsl_eindex); 00271 } 00272 #endif 00273 vparent_t::data[i*vparent_t::stride*2]=d.real(); 00274 vparent_t::data[i*vparent_t::stride*2+1]=d.imag(); 00275 return 0; 00276 } 00277 00278 /** \brief Set (with optional range-checking) */ 00279 int set(size_t i, data_t vr, data_t vi) { 00280 #if O2SCL_NO_RANGE_CHECK 00281 #else 00282 if (i>=vparent_t::size) { 00283 O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds" 00284 +" in ovector_cx_view_tlate::set(). Size: "+ 00285 itos(vparent_t::size)+ 00286 " (index should be less than size).").c_str(),gsl_eindex); 00287 } 00288 #endif 00289 vparent_t::data[i*vparent_t::stride*2]=vr; 00290 vparent_t::data[i*vparent_t::stride*2+1]=vi; 00291 return 0; 00292 } 00293 00294 /** \brief Set all of the value to be the value \c val */ 00295 int set_all(const complex_t &g) { 00296 for(size_t i=0;i<vparent_t::size;i++) { 00297 data_t gr=GSL_REAL(g), gi=GSL_IMAG(g); 00298 vparent_t::data[i*vparent_t::stride]=gr; 00299 vparent_t::data[i*vparent_t::stride+1]=gi; 00300 } 00301 return 0; 00302 } 00303 00304 /** 00305 \brief Method to return vector size 00306 00307 If no memory has been allocated, this will quietly 00308 return zero. 00309 */ 00310 size_t size() const { 00311 return vparent_t::size; 00312 } 00313 00314 /** 00315 \brief Method to return vector stride 00316 00317 If no memory has been allocated, this will quietly 00318 return zero. 00319 */ 00320 size_t stride() const { 00321 return vparent_t::stride; 00322 } 00323 //@} 00324 00325 /// \name Other methods 00326 //@{ 00327 /// Return true if this object owns the data it refers to 00328 bool is_owner() const { 00329 if (vparent_t::owner==1) return true; 00330 return false; 00331 } 00332 //@} 00333 00334 /// \name Arithmetic 00335 //@{ 00336 /** \brief operator+= */ 00337 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+= 00338 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00339 size_t lsize=x.size; 00340 if (lsize>size) lsize=size; 00341 for(size_t i=0;i<lsize;i++) { 00342 vparent_t::data[i*vparent_t::stride*2]+=x.data[i*x.stride*2]; 00343 vparent_t::data[i*vparent_t::stride*2+1]+=x.data[i*x.stride*2+1]; 00344 } 00345 00346 return *this; 00347 } 00348 00349 /** \brief operator-= */ 00350 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-= 00351 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00352 size_t lsize=x.size; 00353 if (lsize>size) lsize=size; 00354 for(size_t i=0;i<lsize;i++) { 00355 vparent_t::data[i*vparent_t::stride*2]-=x.data[i*x.stride*2]; 00356 vparent_t::data[i*vparent_t::stride*2+1]-=x.data[i*x.stride*2+1]; 00357 } 00358 00359 return *this; 00360 } 00361 00362 /** \brief operator+= */ 00363 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+= 00364 (const complex_t &x) { 00365 data_t re=*(data_t *)x; 00366 data_t im=*(((data_t *)x)+1); 00367 for(size_t i=0;i<size;i++) { 00368 vparent_t::data[i*vparent_t::stride*2]+=re; 00369 vparent_t::data[i*vparent_t::stride*2+1]+=im; 00370 } 00371 00372 return *this; 00373 } 00374 00375 /** \brief operator-= */ 00376 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-= 00377 (const complex_t &x) { 00378 data_t re=*(data_t *)x; 00379 data_t im=*(((data_t *)x)+1); 00380 for(size_t i=0;i<size;i++) { 00381 vparent_t::data[i*vparent_t::stride*2]-=re; 00382 vparent_t::data[i*vparent_t::stride*2+1]-=im; 00383 } 00384 00385 return *this; 00386 } 00387 00388 /** \brief operator*= */ 00389 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*= 00390 (const complex_t &x) { 00391 data_t re=*(data_t *)x; 00392 data_t im=*(((data_t *)x)+1); 00393 for(size_t i=0;i<size;i++) { 00394 data_t rold=vparent_t::data[i*vparent_t::stride*2]; 00395 data_t iold=vparent_t::data[i*vparent_t::stride*2+1]; 00396 vparent_t::data[i*vparent_t::stride*2]=re*rold-im*iold; 00397 vparent_t::data[i*vparent_t::stride*2+1]=re*iold+im*rold; 00398 } 00399 00400 return *this; 00401 } 00402 00403 /** \brief operator+= */ 00404 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+= 00405 (const data_t &x) { 00406 for(size_t i=0;i<size;i++) { 00407 vparent_t::data[i*vparent_t::stride*2]+=x; 00408 } 00409 00410 return *this; 00411 } 00412 00413 /** \brief operator-= */ 00414 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-= 00415 (const data_t &x) { 00416 for(size_t i=0;i<size;i++) { 00417 vparent_t::data[i*vparent_t::stride*2]-=x; 00418 } 00419 00420 return *this; 00421 } 00422 00423 /** \brief operator*= */ 00424 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*= 00425 (const data_t &x) { 00426 for(size_t i=0;i<size;i++) { 00427 vparent_t::data[i*vparent_t::stride*2]*=x; 00428 vparent_t::data[i*vparent_t::stride*2+1]*=x; 00429 } 00430 00431 return *this; 00432 } 00433 //@} 00434 00435 /// Conjugate the vector 00436 int conjugate() { 00437 size_t sz=vparent_t::size; 00438 for(size_t i=0;i<sz;i++) { 00439 data_t tmp=(*this)[i].dat[1]; 00440 (*this)[i].dat[1]=-tmp; 00441 //vparent_t::data[i*vparent_t::stride*2+1]*=-1.0; 00442 } 00443 return 0; 00444 } 00445 00446 /** \brief Complex norm \f$ v^{\dagger} v \f$ */ 00447 data_t norm() const { 00448 data_t result=0; 00449 for(size_t i=0;i<vparent_t::size;i++) { 00450 data_t re=vparent_t::data[i*vparent_t::stride*2]; 00451 data_t im=vparent_t::data[i*vparent_t::stride*2+1]; 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 00602 // Check for self-assignment 00603 if (this==&v) return *this; 00604 00605 size_t size=v.size; 00606 if (vparent_t::owner) { 00607 allocate(size); 00608 } else { 00609 if (vparent_t::size!=size) { 00610 O2SCL_ERR("Sizes don't match in ovector_cx_tlate::operator=()", 00611 gsl_ebadlen); 00612 return *this; 00613 } 00614 } 00615 for(size_t i=0;i<size;i++) { 00616 vparent_t::data[2*i*vparent_t::stride]=v.data[2*i*v.stride()]; 00617 vparent_t::data[2*i*vparent_t::stride+1]=v.data[2*i*v.stride()+1]; 00618 } 00619 return *this; 00620 } 00621 00622 /** \brief Deep copy constructor, if owner is true, allocate space and 00623 make a new copy, otherwise, just copy into the view 00624 */ 00625 ovector_cx_tlate& operator= 00626 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &v) { 00627 00628 // Check for self-assignment 00629 if (this==&v) return *this; 00630 00631 size_t size=v.size(); 00632 if (vparent_t::owner) { 00633 allocate(size); 00634 } else { 00635 if (vparent_t::size!=size) { 00636 O2SCL_ERR("Sizes don't match in ovector_cx_tlate::operator=()", 00637 gsl_ebadlen); 00638 return *this; 00639 } 00640 } 00641 for(size_t i=0;i<size;i++) { 00642 vparent_t::data[2*i*vparent_t::stride]=v.data[2*i*v.stride()]; 00643 vparent_t::data[2*i*vparent_t::stride+1]=v.data[2*i*v.stride()+1]; 00644 } 00645 return *this; 00646 } 00647 //@} 00648 00649 ~ovector_cx_tlate() { 00650 if (vparent_t::size>0) { 00651 if (vparent_t::owner==1) { 00652 if (vparent_t::block->size>0) { 00653 std::free(vparent_t::block->data); 00654 } 00655 std::free(vparent_t::block); 00656 vparent_t::size=0; 00657 } 00658 } 00659 } 00660 00661 /// \name Memory allocation 00662 //@{ 00663 /** 00664 \brief Allocate memory for size \c n after freeing any memory 00665 presently in use 00666 */ 00667 int allocate(size_t nsize) { 00668 if (vparent_t::size>0) free(); 00669 00670 if (nsize>0) { 00671 vparent_t::block=(block_t *)malloc(sizeof(block_t)); 00672 if (vparent_t::block) { 00673 vparent_t::block->data=(data_t *)malloc(2*nsize*sizeof(data_t)); 00674 if (vparent_t::block->data) { 00675 vparent_t::block->size=nsize; 00676 vparent_t::data=vparent_t::block->data; 00677 vparent_t::size=nsize; 00678 vparent_t::stride=1; 00679 vparent_t::owner=1; 00680 } else { 00681 std::free(vparent_t::block); 00682 O2SCL_ERR_RET("No memory for data in ovector_cx_tlate::allocate()", 00683 gsl_enomem); 00684 } 00685 } else { 00686 O2SCL_ERR_RET("No memory for block in ovector_cx_tlate::allocate()", 00687 gsl_enomem); 00688 } 00689 } else { 00690 O2SCL_ERR_RET("Zero size in ovector_cx::allocate()",gsl_einval); 00691 } 00692 return 0; 00693 } 00694 00695 /** 00696 \brief Free the memory 00697 00698 This function will safely do nothing if used without first 00699 allocating memory or if called multiple times in succession. 00700 */ 00701 int free() { 00702 if (vparent_t::size>0) { 00703 if (vparent_t::owner==1) { 00704 if (vparent_t::block->size>0) { 00705 std::free(vparent_t::block->data); 00706 } 00707 std::free(vparent_t::block); 00708 } 00709 vparent_t::size=0; 00710 vparent_t::stride=0; 00711 } 00712 return 0; 00713 } 00714 //@} 00715 00716 /// \name Other methods 00717 //@{ 00718 /** \brief Return a gsl vector_cx */ 00719 vparent_t *get_gsl_vector_complex() { return this; } 00720 00721 /** \brief Return a gsl vector_cx */ 00722 const vparent_t *get_gsl_vector_complex_const() const 00723 { return this; } 00724 //@} 00725 00726 }; 00727 00728 /** \brief Create a vector from an array 00729 */ 00730 template<class data_t, class vparent_t, class block_t, class complex_t> 00731 class ovector_cx_array_tlate : 00732 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00733 00734 public: 00735 00736 /** \brief Create a vector from \c dat with size \c n */ 00737 ovector_cx_array_tlate(size_t n, complex_t *dat) { 00738 if (n>0) { 00739 vparent_t::block=0; 00740 vparent_t::data=dat; 00741 vparent_t::size=n; 00742 vparent_t::stride=1; 00743 vparent_t::owner=0; 00744 } 00745 } 00746 }; 00747 00748 /** \brief Create a vector from an array with a stride 00749 */ 00750 template<class data_t, class vparent_t, class block_t, class complex_t> 00751 class ovector_cx_array_stride_tlate : 00752 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00753 00754 public: 00755 00756 /** \brief Create a vector from \c dat with size \c n and stride \c s 00757 */ 00758 ovector_cx_array_stride_tlate(size_t n, complex_t *dat, size_t s) { 00759 if (n>0) { 00760 vparent_t::block=0; 00761 vparent_t::data=dat; 00762 vparent_t::size=n; 00763 vparent_t::stride=s; 00764 vparent_t::owner=0; 00765 } 00766 } 00767 }; 00768 00769 /** \brief Create a vector from a subvector of another 00770 */ 00771 template<class data_t, class vparent_t, class block_t, class complex_t> 00772 class ovector_cx_subvector_tlate : 00773 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00774 00775 public: 00776 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=0; 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 O2SCL_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=0; 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 0; } 00829 int set(size_t i, data_t val) { return 0; } 00830 int set_all(double val) { return 0; } 00831 vparent_t *get_gsl_vector() { return 0; } 00832 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+= 00833 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00834 return *this; 00835 } 00836 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-= 00837 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00838 return *this; 00839 } 00840 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*= 00841 (const data_t &y) { 00842 return *this; 00843 } 00844 //@} 00845 00846 #endif 00847 00848 }; 00849 00850 /** \brief Create a vector from an array_stride 00851 */ 00852 template<class data_t, class vparent_t, class block_t, class complex_t> 00853 class ovector_cx_const_array_stride_tlate : 00854 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00855 00856 public: 00857 00858 /** \brief Create a vector from \c dat with size \c n */ 00859 ovector_cx_const_array_stride_tlate(size_t n, const complex_t *dat, 00860 size_t s) { 00861 if (n>0) { 00862 vparent_t::block=0; 00863 // We have to do an explicit cast here, but we prevent the 00864 // user from changing the data. 00865 vparent_t::data=(data_t *)dat; 00866 vparent_t::size=n; 00867 vparent_t::stride=s; 00868 vparent_t::owner=0; 00869 } 00870 } 00871 00872 #ifndef DOXYGEN_INTERNAL 00873 00874 protected: 00875 00876 /** \name These are inaccessible to ensure the vector is \c const. 00877 */ 00878 //@{ 00879 data_t &operator[](size_t i) { return vparent_t::data[0]; } 00880 data_t &operator()(size_t i) { return vparent_t::data[0]; } 00881 data_t *get_ptr(size_t i) { return 0; } 00882 int set(size_t i, data_t val) { return 0; } 00883 int set_all(double val) { return 0; } 00884 vparent_t *get_gsl_vector() { return 0; } 00885 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+= 00886 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00887 return *this; 00888 } 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 data_t &y) { 00895 return *this; 00896 } 00897 //@} 00898 00899 #endif 00900 00901 }; 00902 00903 /** \brief Create a vector from a subvector of another 00904 */ 00905 template<class data_t, class vparent_t, class block_t, class complex_t> 00906 class ovector_cx_const_subvector_tlate : 00907 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00908 00909 public: 00910 00911 /** \brief Create a vector from \c orig 00912 */ 00913 ovector_cx_const_subvector_tlate 00914 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &orig, 00915 size_t offset, size_t n) { 00916 if (offset+n-1<orig.size) { 00917 vparent_t::block=0; 00918 vparent_t::data=orig.data+offset*2*orig.stride; 00919 vparent_t::size=n; 00920 vparent_t::stride=orig.stride; 00921 vparent_t::owner=0; 00922 } else { 00923 vparent_t::size=0; 00924 O2SCL_ERR("Subvector failed in ovector_cx_subvector().",1); 00925 } 00926 } 00927 00928 #ifndef DOXYGEN_INTERNAL 00929 00930 protected: 00931 00932 /** \name These are inaccessible to ensure the vector is \c const. 00933 */ 00934 //@{ 00935 data_t &operator[](size_t i) { return vparent_t::data[0]; } 00936 data_t &operator()(size_t i) { return vparent_t::data[0]; } 00937 data_t *get_ptr(size_t i) { return 0; } 00938 int set(size_t i, data_t val) { return 0; } 00939 int set_all(double val) { return 0; } 00940 vparent_t *get_gsl_vector() { return 0; } 00941 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+= 00942 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00943 return *this; 00944 } 00945 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-= 00946 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00947 return *this; 00948 } 00949 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*= 00950 (const data_t &y) { 00951 return *this; 00952 } 00953 //@} 00954 00955 #endif 00956 00957 }; 00958 00959 /** \brief Create a real vector from the real parts of a complex vector 00960 */ 00961 template<class data_t, class vparent_t, class block_t, 00962 class cvparent_t, class cblock_t, class complex_t> 00963 class ovector_cx_real_tlate : 00964 public ovector_view_tlate<data_t,vparent_t,block_t> { 00965 00966 public: 00967 00968 /** \brief Create a real vector from the real parts of a complex vector 00969 */ 00970 ovector_cx_real_tlate 00971 (ovector_cx_view_tlate<data_t,cvparent_t,cblock_t,complex_t> &x) { 00972 vparent_t::block=0; 00973 vparent_t::data=x.data; 00974 vparent_t::size=x.size; 00975 vparent_t::stride=2*x.stride; 00976 vparent_t::owner=false; 00977 } 00978 }; 00979 00980 /** \brief Create a imaginary vector from the imaginary parts of a 00981 complex vector 00982 */ 00983 template<class data_t, class vparent_t, class block_t, 00984 class cvparent_t, class cblock_t, class complex_t> 00985 class ovector_cx_imag_tlate : 00986 public ovector_view_tlate<data_t,vparent_t,block_t> { 00987 00988 public: 00989 00990 /** \brief Create a imaginary vector from the imaginary parts of a 00991 complex vector 00992 */ 00993 ovector_cx_imag_tlate 00994 (ovector_cx_view_tlate<data_t,cvparent_t,cblock_t,complex_t> &x) { 00995 vparent_t::block=0; 00996 vparent_t::data=x.data+1; 00997 vparent_t::size=x.size; 00998 vparent_t::stride=2*x.stride; 00999 vparent_t::owner=false; 01000 } 01001 }; 01002 01003 /** \brief A complex vector where the memory allocation is performed in 01004 the constructor 01005 */ 01006 #ifdef DOXYGENP 01007 template<size_t N=0> class ofvector_cx : 01008 public ovector_cx_tlate<data_t,vparent_t,block_t,complex_t> 01009 #else 01010 template<size_t N=0> class ofvector_cx : 01011 public ovector_cx_tlate<double,gsl_vector_complex,gsl_block_complex, 01012 gsl_complex> 01013 #endif 01014 { 01015 public: 01016 ofvector_cx() : ovector_cx_tlate<double,gsl_vector_complex, 01017 gsl_block_complex,gsl_complex>(N) { 01018 } 01019 }; 01020 01021 /// ovector_cx typedef 01022 typedef ovector_cx_tlate<double,gsl_vector_complex,gsl_block_complex, 01023 gsl_complex> ovector_cx; 01024 /// ovector_cx_view typedef 01025 typedef ovector_cx_view_tlate<double,gsl_vector_complex,gsl_block_complex, 01026 gsl_complex> ovector_cx_view; 01027 /// ovector_cx_array typedef 01028 typedef ovector_cx_array_tlate<double,gsl_vector_complex,gsl_block_complex, 01029 gsl_complex> ovector_cx_array; 01030 /// ovector_cx_array_stride typedef 01031 typedef ovector_cx_array_stride_tlate<double,gsl_vector_complex, 01032 gsl_block_complex,gsl_complex> 01033 ovector_cx_array_stride; 01034 /// ovector_cx_subvector typedef 01035 typedef ovector_cx_subvector_tlate<double,gsl_vector_complex, 01036 gsl_block_complex,gsl_complex> 01037 ovector_cx_subvector; 01038 /// ovector_cx_const_array typedef 01039 typedef ovector_cx_const_array_tlate<double,gsl_vector_complex, 01040 gsl_block_complex,gsl_complex> 01041 ovector_cx_const_array; 01042 /// ovector_cx_const_array_stride typedef 01043 typedef ovector_cx_const_array_stride_tlate<double,gsl_vector_complex, 01044 gsl_block_complex,gsl_complex> 01045 ovector_cx_const_array_stride; 01046 /// ovector_cx_const_subvector typedef 01047 typedef ovector_cx_const_subvector_tlate<double,gsl_vector_complex, 01048 gsl_block_complex,gsl_complex> 01049 ovector_cx_const_subvector; 01050 /// ovector_cx_real typedef 01051 typedef ovector_cx_real_tlate<double,gsl_vector,gsl_block, 01052 gsl_vector_complex,gsl_block_complex,gsl_complex> ovector_cx_real; 01053 /// ovector_cx_imag typedef 01054 typedef ovector_cx_imag_tlate<double,gsl_vector,gsl_block, 01055 gsl_vector_complex,gsl_block_complex,gsl_complex> ovector_cx_imag; 01056 01057 /** \brief Conjugate a vector */ 01058 template<class data_t,class vparent_t,class block_t, class complex_t> 01059 ovector_cx_tlate<data_t,vparent_t,block_t,complex_t> 01060 conjugate(ovector_cx_tlate<data_t,vparent_t,block_t,complex_t> &v) { 01061 ovector_tlate<data_t,vparent_t,block_t> result(v.size()); 01062 for(size_t i=0;i<v.size();i++) { 01063 double *p=vparent_t::data+i*vparent_t::stride*2+1; 01064 (*p)=-(*p); 01065 } 01066 return result; 01067 } 01068 01069 /** 01070 \brief A operator for naive vector output 01071 01072 This outputs all of the vector elements in the form \c (r,i). 01073 All of these are separated by one space character, though no 01074 trailing space or \c endl is sent to the output. 01075 */ 01076 template<class data_t, class vparent_t, class block_t, class complex_t> 01077 std::ostream &operator<< 01078 (std::ostream &os, 01079 const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &v) { 01080 for(size_t i=0;i<v.size()-1;i++) { 01081 os << '(' << v.real(i) << ',' << v.imag(i) << ") "; 01082 } 01083 os << '(' << v.real(v.size()-1) << ',' 01084 << v.imag(v.size()-1) << ") "; 01085 return os; 01086 } 01087 01088 #ifndef DOXYGENP 01089 } 01090 #endif 01091 01092 #endif 01093
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page