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 std::cout << "ocn: " << re << " " << im << std::endl; 00453 result+=re*re+im*im; 00454 } 00455 return sqrt(result); 00456 } 00457 00458 #ifndef DOXYGEN_INTERNAL 00459 00460 protected: 00461 00462 /** \brief Empty constructor provided for use by 00463 ovector_cx_tlate(const ovector_cx_tlate &v) [protected] 00464 */ 00465 ovector_cx_view_tlate() {}; 00466 00467 #endif 00468 00469 }; 00470 00471 /** 00472 \brief A vector of double-precision numbers 00473 00474 If the memory allocation fails, either in the constructor or in 00475 allocate(), then the error handler will be called, partially 00476 allocated memory will be freed, and the size will be reset to 00477 zero. You can test to see if the allocation succeeded using 00478 something like 00479 \code 00480 const size_t n=10; 00481 ovector_cx x(10); 00482 if (x.size()==0) cout << "Failed." << endl; 00483 \endcode 00484 00485 \todo Add subvector_stride, const_subvector_stride 00486 00487 */ 00488 template<class data_t, class vparent_t, class block_t, class complex_t> 00489 class ovector_cx_tlate : 00490 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00491 00492 public: 00493 00494 /// \name Standard constructor 00495 //@{ 00496 /** \brief Create an ovector_cx of size \c n with owner as 'true' */ 00497 ovector_cx_tlate(size_t n=0) { 00498 00499 vparent_t::data=0; 00500 vparent_t::size=0; 00501 vparent_t::stride=0; 00502 00503 // This must be set to 1 even if n=0 so that future 00504 // calls to operator= work properly 00505 vparent_t::owner=1; 00506 00507 if (n>0) { 00508 vparent_t::block=(block_t *)malloc(sizeof(block_t)); 00509 if (vparent_t::block) { 00510 vparent_t::block->data=(data_t *)malloc(2*n*sizeof(data_t)); 00511 if (vparent_t::block->data) { 00512 vparent_t::block->size=n; 00513 vparent_t::data=vparent_t::block->data; 00514 vparent_t::size=n; 00515 vparent_t::stride=1; 00516 } else { 00517 std::free(vparent_t::block); 00518 O2SCL_ERR("No memory for data in ovector_cx_tlate constructor", 00519 gsl_enomem); 00520 } 00521 } else { 00522 O2SCL_ERR("No memory for block in ovector_cx_tlate contructor", 00523 gsl_enomem); 00524 } 00525 } 00526 } 00527 //@} 00528 00529 /// \name Copy constructors 00530 //@{ 00531 /// Deep copy constructor, allocate new space and make a copy 00532 ovector_cx_tlate(const ovector_cx_tlate &v) : 00533 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t>() { 00534 size_t n=v.size(); 00535 if (n>0) { 00536 vparent_t::block=(block_t *)malloc(sizeof(block_t)); 00537 if (vparent_t::block) { 00538 vparent_t::block->data=(data_t *)malloc(2*n*sizeof(data_t)); 00539 if (vparent_t::block->data) { 00540 vparent_t::block->size=n; 00541 vparent_t::data=vparent_t::block->data; 00542 vparent_t::size=n; 00543 vparent_t::stride=1; 00544 vparent_t::owner=1; 00545 for(size_t i=0;i<n;i++) { 00546 vparent_t::data[2*i]=v.data[2*i*v.stride()]; 00547 vparent_t::data[2*i+1]=v.data[2*i*v.stride()+1]; 00548 } 00549 } else { 00550 std::free(vparent_t::block); 00551 O2SCL_ERR("No memory for data in ovector_cx_tlate constructor", 00552 gsl_enomem); 00553 } 00554 } else { 00555 O2SCL_ERR("No memory for block in ovector_cx_tlate contructor", 00556 gsl_enomem); 00557 } 00558 } else { 00559 vparent_t::size=0; 00560 vparent_t::stride=0; 00561 } 00562 } 00563 00564 /// Deep copy constructor, allocate new space and make a copy 00565 ovector_cx_tlate 00566 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &v) : 00567 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t>() { 00568 size_t n=v.size(); 00569 if (n>0) { 00570 vparent_t::block=(block_t *)malloc(sizeof(block_t)); 00571 if (vparent_t::block) { 00572 vparent_t::block->data=(data_t *)malloc(2*n*sizeof(data_t)); 00573 if (vparent_t::block->data) { 00574 vparent_t::block->size=n; 00575 vparent_t::data=vparent_t::block->data; 00576 vparent_t::size=n; 00577 vparent_t::stride=1; 00578 vparent_t::owner=1; 00579 for(size_t i=0;i<n;i++) { 00580 vparent_t::data[2*i]=v.data[2*i*v.stride()]; 00581 vparent_t::data[2*i+1]=v.data[2*i*v.stride()+1]; 00582 } 00583 } else { 00584 std::free(vparent_t::block); 00585 O2SCL_ERR("No memory for data in ovector_cx_tlate constructor", 00586 gsl_enomem); 00587 } 00588 } else { 00589 O2SCL_ERR("No memory for block in ovector_cx_tlate contructor", 00590 gsl_enomem); 00591 } 00592 } else { 00593 vparent_t::size=0; 00594 vparent_t::stride=0; 00595 } 00596 } 00597 00598 /** \brief Deep copy constructor, if owner is true, allocate space and 00599 make a new copy, otherwise, just copy into the view 00600 */ 00601 ovector_cx_tlate& operator=(const ovector_cx_tlate &v) { 00602 00603 // Check for self-assignment 00604 if (this==&v) return *this; 00605 00606 size_t size=v.size; 00607 if (vparent_t::owner) { 00608 allocate(size); 00609 } else { 00610 if (vparent_t::size!=size) { 00611 O2SCL_ERR("Sizes don't match in ovector_cx_tlate::operator=()", 00612 gsl_ebadlen); 00613 return *this; 00614 } 00615 } 00616 for(size_t i=0;i<size;i++) { 00617 vparent_t::data[2*i*vparent_t::stride]=v.data[2*i*v.stride()]; 00618 vparent_t::data[2*i*vparent_t::stride+1]=v.data[2*i*v.stride()+1]; 00619 } 00620 return *this; 00621 } 00622 00623 /** \brief Deep copy constructor, if owner is true, allocate space and 00624 make a new copy, otherwise, just copy into the view 00625 */ 00626 ovector_cx_tlate& operator= 00627 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &v) { 00628 00629 // Check for self-assignment 00630 if (this==&v) return *this; 00631 00632 size_t size=v.size(); 00633 if (vparent_t::owner) { 00634 allocate(size); 00635 } else { 00636 if (vparent_t::size!=size) { 00637 O2SCL_ERR("Sizes don't match in ovector_cx_tlate::operator=()", 00638 gsl_ebadlen); 00639 return *this; 00640 } 00641 } 00642 for(size_t i=0;i<size;i++) { 00643 vparent_t::data[2*i*vparent_t::stride]=v.data[2*i*v.stride()]; 00644 vparent_t::data[2*i*vparent_t::stride+1]=v.data[2*i*v.stride()+1]; 00645 } 00646 return *this; 00647 } 00648 //@} 00649 00650 ~ovector_cx_tlate() { 00651 if (vparent_t::size>0) { 00652 if (vparent_t::owner==1) { 00653 if (vparent_t::block->size>0) { 00654 std::free(vparent_t::block->data); 00655 } 00656 std::free(vparent_t::block); 00657 vparent_t::size=0; 00658 } 00659 } 00660 } 00661 00662 /// \name Memory allocation 00663 //@{ 00664 /** 00665 \brief Allocate memory for size \c n after freeing any memory 00666 presently in use 00667 */ 00668 int allocate(size_t nsize) { 00669 if (vparent_t::size>0) free(); 00670 00671 if (nsize>0) { 00672 vparent_t::block=(block_t *)malloc(sizeof(block_t)); 00673 if (vparent_t::block) { 00674 vparent_t::block->data=(data_t *)malloc(2*nsize*sizeof(data_t)); 00675 if (vparent_t::block->data) { 00676 vparent_t::block->size=nsize; 00677 vparent_t::data=vparent_t::block->data; 00678 vparent_t::size=nsize; 00679 vparent_t::stride=1; 00680 vparent_t::owner=1; 00681 } else { 00682 std::free(vparent_t::block); 00683 O2SCL_ERR_RET("No memory for data in ovector_cx_tlate::allocate()", 00684 gsl_enomem); 00685 } 00686 } else { 00687 O2SCL_ERR_RET("No memory for block in ovector_cx_tlate::allocate()", 00688 gsl_enomem); 00689 } 00690 } else { 00691 O2SCL_ERR_RET("Zero size in ovector_cx::allocate()",gsl_einval); 00692 } 00693 return 0; 00694 } 00695 00696 /** 00697 \brief Free the memory 00698 00699 This function will safely do nothing if used without first 00700 allocating memory or if called multiple times in succession. 00701 */ 00702 int free() { 00703 if (vparent_t::size>0) { 00704 if (vparent_t::owner==1) { 00705 if (vparent_t::block->size>0) { 00706 std::free(vparent_t::block->data); 00707 } 00708 std::free(vparent_t::block); 00709 } 00710 vparent_t::size=0; 00711 vparent_t::stride=0; 00712 } 00713 return 0; 00714 } 00715 //@} 00716 00717 /// \name Other methods 00718 //@{ 00719 /** \brief Return a gsl vector_cx */ 00720 vparent_t *get_gsl_vector_complex() { return this; } 00721 00722 /** \brief Return a gsl vector_cx */ 00723 const vparent_t *get_gsl_vector_complex_const() const 00724 { return this; } 00725 //@} 00726 00727 }; 00728 00729 /** \brief Create a vector from an array 00730 */ 00731 template<class data_t, class vparent_t, class block_t, class complex_t> 00732 class ovector_cx_array_tlate : 00733 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00734 00735 public: 00736 00737 /** \brief Create a vector from \c dat with size \c n */ 00738 ovector_cx_array_tlate(size_t n, complex_t *dat) { 00739 if (n>0) { 00740 vparent_t::block=0; 00741 vparent_t::data=dat; 00742 vparent_t::size=n; 00743 vparent_t::stride=1; 00744 vparent_t::owner=0; 00745 } 00746 } 00747 }; 00748 00749 /** \brief Create a vector from an array with a stride 00750 */ 00751 template<class data_t, class vparent_t, class block_t, class complex_t> 00752 class ovector_cx_array_stride_tlate : 00753 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00754 00755 public: 00756 00757 /** \brief Create a vector from \c dat with size \c n and stride \c s 00758 */ 00759 ovector_cx_array_stride_tlate(size_t n, complex_t *dat, size_t s) { 00760 if (n>0) { 00761 vparent_t::block=0; 00762 vparent_t::data=dat; 00763 vparent_t::size=n; 00764 vparent_t::stride=s; 00765 vparent_t::owner=0; 00766 } 00767 } 00768 }; 00769 00770 /** \brief Create a vector from a subvector of another 00771 */ 00772 template<class data_t, class vparent_t, class block_t, class complex_t> 00773 class ovector_cx_subvector_tlate : 00774 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00775 00776 public: 00777 00778 /** \brief Create a vector from \c orig */ 00779 ovector_cx_subvector_tlate 00780 (ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &orig, 00781 size_t offset, size_t n) { 00782 00783 vparent_t::size=0; 00784 vparent_t::stride=0; 00785 vparent_t::data=0; 00786 00787 if (offset+n-1<orig.size()) { 00788 vparent_t::block=0; 00789 vparent_t::data=orig.data+offset*2*orig.stride(); 00790 vparent_t::size=n; 00791 vparent_t::stride=orig.stride(); 00792 vparent_t::owner=0; 00793 } else { 00794 O2SCL_ERR("Subvector failed in ovector_cx_sub_view().",1); 00795 } 00796 } 00797 }; 00798 00799 /** \brief Create a vector from an array 00800 */ 00801 template<class data_t, class vparent_t, class block_t, class complex_t> 00802 class ovector_cx_const_array_tlate : 00803 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00804 public: 00805 /** \brief Create a vector from \c dat with size \c n */ 00806 ovector_cx_const_array_tlate(size_t n, const complex_t *dat) { 00807 if (n>0) { 00808 vparent_t::block=0; 00809 // We have to do an explicit cast here, but we prevent the 00810 // user from changing the data. 00811 vparent_t::data=(data_t *)dat; 00812 vparent_t::size=n; 00813 vparent_t::stride=1; 00814 vparent_t::owner=0; 00815 } 00816 } 00817 00818 ~ovector_cx_const_array_tlate() {}; 00819 00820 #ifndef DOXYGEN_INTERNAL 00821 00822 protected: 00823 00824 /** \name These are inaccessible to ensure the vector is \c const. 00825 */ 00826 //@{ 00827 data_t &operator[](size_t i) { return vparent_t::data[0]; } 00828 data_t &operator()(size_t i) { return vparent_t::data[0]; } 00829 data_t *get_ptr(size_t i) { return 0; } 00830 int set(size_t i, data_t val) { return 0; } 00831 int set_all(double val) { return 0; } 00832 vparent_t *get_gsl_vector() { return 0; } 00833 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+= 00834 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00835 return *this; 00836 } 00837 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-= 00838 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00839 return *this; 00840 } 00841 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*= 00842 (const data_t &y) { 00843 return *this; 00844 } 00845 //@} 00846 00847 #endif 00848 00849 }; 00850 00851 /** \brief Create a vector from an array_stride 00852 */ 00853 template<class data_t, class vparent_t, class block_t, class complex_t> 00854 class ovector_cx_const_array_stride_tlate : 00855 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00856 00857 public: 00858 00859 /** \brief Create a vector from \c dat with size \c n */ 00860 ovector_cx_const_array_stride_tlate(size_t n, const complex_t *dat, 00861 size_t s) { 00862 if (n>0) { 00863 vparent_t::block=0; 00864 // We have to do an explicit cast here, but we prevent the 00865 // user from changing the data. 00866 vparent_t::data=(data_t *)dat; 00867 vparent_t::size=n; 00868 vparent_t::stride=s; 00869 vparent_t::owner=0; 00870 } 00871 } 00872 00873 #ifndef DOXYGEN_INTERNAL 00874 00875 protected: 00876 00877 /** \name These are inaccessible to ensure the vector is \c const. 00878 */ 00879 //@{ 00880 data_t &operator[](size_t i) { return vparent_t::data[0]; } 00881 data_t &operator()(size_t i) { return vparent_t::data[0]; } 00882 data_t *get_ptr(size_t i) { return 0; } 00883 int set(size_t i, data_t val) { return 0; } 00884 int set_all(double val) { return 0; } 00885 vparent_t *get_gsl_vector() { return 0; } 00886 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator+= 00887 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00888 return *this; 00889 } 00890 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator-= 00891 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &x) { 00892 return *this; 00893 } 00894 ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &operator*= 00895 (const data_t &y) { 00896 return *this; 00897 } 00898 //@} 00899 00900 #endif 00901 00902 }; 00903 00904 /** \brief Create a vector from a subvector of another 00905 */ 00906 template<class data_t, class vparent_t, class block_t, class complex_t> 00907 class ovector_cx_const_subvector_tlate : 00908 public ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> { 00909 00910 public: 00911 00912 /** \brief Create a vector from \c orig 00913 */ 00914 ovector_cx_const_subvector_tlate 00915 (const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &orig, 00916 size_t offset, size_t n) { 00917 if (offset+n-1<orig.size) { 00918 vparent_t::block=0; 00919 vparent_t::data=orig.data+offset*2*orig.stride; 00920 vparent_t::size=n; 00921 vparent_t::stride=orig.stride; 00922 vparent_t::owner=0; 00923 } else { 00924 vparent_t::size=0; 00925 O2SCL_ERR("Subvector failed in ovector_cx_subvector().",1); 00926 } 00927 } 00928 00929 #ifndef DOXYGEN_INTERNAL 00930 00931 protected: 00932 00933 /** \name These are inaccessible to ensure the vector is \c const. 00934 */ 00935 //@{ 00936 data_t &operator[](size_t i) { return vparent_t::data[0]; } 00937 data_t &operator()(size_t i) { return vparent_t::data[0]; } 00938 data_t *get_ptr(size_t i) { return 0; } 00939 int set(size_t i, data_t val) { return 0; } 00940 int set_all(double val) { return 0; } 00941 vparent_t *get_gsl_vector() { return 0; } 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=0; 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=0; 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 complex vector where the memory allocation is performed in 01005 the constructor 01006 */ 01007 #ifdef DOXYGENP 01008 template<size_t N=0> class ofvector_cx : 01009 public ovector_cx_tlate<data_t,vparent_t,block_t,complex_t> 01010 #else 01011 template<size_t N=0> class ofvector_cx : 01012 public ovector_cx_tlate<double,gsl_vector_complex,gsl_block_complex, 01013 gsl_complex> 01014 #endif 01015 { 01016 public: 01017 ofvector_cx() : ovector_cx_tlate<double,gsl_vector_complex, 01018 gsl_block_complex,gsl_complex>(N) { 01019 } 01020 }; 01021 01022 /// ovector_cx typedef 01023 typedef ovector_cx_tlate<double,gsl_vector_complex,gsl_block_complex, 01024 gsl_complex> ovector_cx; 01025 /// ovector_cx_view typedef 01026 typedef ovector_cx_view_tlate<double,gsl_vector_complex,gsl_block_complex, 01027 gsl_complex> ovector_cx_view; 01028 /// ovector_cx_array typedef 01029 typedef ovector_cx_array_tlate<double,gsl_vector_complex,gsl_block_complex, 01030 gsl_complex> ovector_cx_array; 01031 /// ovector_cx_array_stride typedef 01032 typedef ovector_cx_array_stride_tlate<double,gsl_vector_complex, 01033 gsl_block_complex,gsl_complex> 01034 ovector_cx_array_stride; 01035 /// ovector_cx_subvector typedef 01036 typedef ovector_cx_subvector_tlate<double,gsl_vector_complex, 01037 gsl_block_complex,gsl_complex> 01038 ovector_cx_subvector; 01039 /// ovector_cx_const_array typedef 01040 typedef ovector_cx_const_array_tlate<double,gsl_vector_complex, 01041 gsl_block_complex,gsl_complex> 01042 ovector_cx_const_array; 01043 /// ovector_cx_const_array_stride typedef 01044 typedef ovector_cx_const_array_stride_tlate<double,gsl_vector_complex, 01045 gsl_block_complex,gsl_complex> 01046 ovector_cx_const_array_stride; 01047 /// ovector_cx_const_subvector typedef 01048 typedef ovector_cx_const_subvector_tlate<double,gsl_vector_complex, 01049 gsl_block_complex,gsl_complex> 01050 ovector_cx_const_subvector; 01051 /// ovector_cx_real typedef 01052 typedef ovector_cx_real_tlate<double,gsl_vector,gsl_block, 01053 gsl_vector_complex,gsl_block_complex,gsl_complex> ovector_cx_real; 01054 /// ovector_cx_imag typedef 01055 typedef ovector_cx_imag_tlate<double,gsl_vector,gsl_block, 01056 gsl_vector_complex,gsl_block_complex,gsl_complex> ovector_cx_imag; 01057 01058 /** \brief Conjugate a vector */ 01059 template<class data_t,class vparent_t,class block_t, class complex_t> 01060 ovector_cx_tlate<data_t,vparent_t,block_t,complex_t> 01061 conjugate(ovector_cx_tlate<data_t,vparent_t,block_t,complex_t> &v) { 01062 ovector_tlate<data_t,vparent_t,block_t> result(v.size()); 01063 for(size_t i=0;i<v.size();i++) { 01064 double *p=vparent_t::data+i*vparent_t::stride*2+1; 01065 (*p)=-(*p); 01066 } 01067 return result; 01068 } 01069 01070 /** 01071 \brief A operator for naive vector output 01072 01073 This outputs all of the vector elements in the form \c (r,i). 01074 All of these are separated by one space character, though no 01075 trailing space or \c endl is sent to the output. 01076 */ 01077 template<class data_t, class vparent_t, class block_t, class complex_t> 01078 std::ostream &operator<< 01079 (std::ostream &os, 01080 const ovector_cx_view_tlate<data_t,vparent_t,block_t,complex_t> &v) { 01081 for(size_t i=0;i<v.size()-1;i++) { 01082 os << '(' << v.real(i) << ',' << v.imag(i) << ") "; 01083 } 01084 os << '(' << v.real(v.size()-1) << ',' 01085 << v.imag(v.size()-1) << ") "; 01086 return os; 01087 } 01088 01089 #ifndef DOXYGENP 01090 } 01091 #endif 01092 01093 #endif 01094
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page