00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 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_UVECTOR_CX_TLATE_H 00024 #define O2SCL_UVECTOR_CX_TLATE_H 00025 00026 /** \file uvector_cx_tlate.h 00027 \brief File for definitions of complex unit-stride vectors 00028 */ 00029 00030 #include <iostream> 00031 #include <cstdlib> 00032 #include <string> 00033 #include <fstream> 00034 #include <sstream> 00035 #include <vector> 00036 #include <o2scl/err_hnd.h> 00037 #include <gsl/gsl_vector.h> 00038 00039 #ifndef DOXYGENP 00040 namespace o2scl { 00041 #endif 00042 00043 /** 00044 \brief A vector view of complex numbers with unit stride 00045 00046 \experiment 00047 00048 \todo Write lookup() method, and possible an erase() method. 00049 */ 00050 template<class data_t, class complex_t> class uvector_cx_view_tlate { 00051 00052 #ifndef DOXYGEN_INTERNAL 00053 00054 protected: 00055 00056 /// The data 00057 data_t *data; 00058 /// The vector sz 00059 size_t sz; 00060 /// Zero if memory is owned elsewhere, 1 otherwise 00061 int owner; 00062 00063 #endif 00064 00065 public: 00066 00067 /// \name Copy constructors 00068 //@{ 00069 /// Copy constructor - create a new view of the same vector 00070 uvector_cx_view_tlate(const uvector_cx_view_tlate &v) { 00071 data=v.data; 00072 sz=v.sz; 00073 owner=0; 00074 } 00075 00076 /// Copy constructor - create a new view of the same vector 00077 uvector_cx_view_tlate& operator=(const uvector_cx_view_tlate &v) { 00078 data=v.data; 00079 sz=v.sz; 00080 owner=0; 00081 00082 return *this; 00083 } 00084 //@} 00085 00086 ~uvector_cx_view_tlate() {}; 00087 00088 /// \name Get and set methods 00089 //@{ 00090 /** 00091 \brief Array-like indexing 00092 */ 00093 complex_t &operator[](size_t i) { 00094 #if GSL_RANGE_CHECK 00095 if (i>=sz) { 00096 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00097 +" in uvector_cx_view_tlate::operator[]. Size: "+ 00098 itos(sz)+ 00099 " (index should be less than size).").c_str(),gsl_index); 00100 return *(complex_t *)(data); 00101 } 00102 #endif 00103 return *(complex_t *)(&data[i*2]); 00104 } 00105 00106 /** 00107 \brief Array-like indexing 00108 */ 00109 const complex_t &operator[](size_t i) const { 00110 #if GSL_RANGE_CHECK 00111 if (i>=sz) { 00112 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00113 +" in uvector_cx_view_tlate::operator[] const. Size: "+ 00114 itos(sz)+ 00115 " (index should be less than size).").c_str(),gsl_index); 00116 return *(const complex_t *)(data); 00117 } 00118 #endif 00119 return *(const complex_t *)(&data[i*2]); 00120 } 00121 00122 /** 00123 \brief Array-like indexing 00124 */ 00125 complex_t &operator()(size_t i) { 00126 #if GSL_RANGE_CHECK 00127 if (i>=sz) { 00128 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00129 +" in uvector_cx_view_tlate::operator(). Size: "+ 00130 itos(sz)+ 00131 " (index should be less than size).").c_str(),gsl_index); 00132 return *(complex_t *)(data); 00133 } 00134 #endif 00135 return *(complex_t *)(&data[i*2]); 00136 } 00137 00138 /** 00139 \brief Array-like indexing 00140 */ 00141 const complex_t &operator()(size_t i) const { 00142 #if GSL_RANGE_CHECK 00143 if (i>=sz) { 00144 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00145 +" in uvector_cx_view_tlate::operator() const. Size: "+ 00146 itos(sz)+ 00147 " (index should be less than size).").c_str(),gsl_index); 00148 return *(const complex_t *)(data); 00149 } 00150 #endif 00151 return *(const complex_t *)(&data[i*2]); 00152 } 00153 00154 /** \brief Get (with optional range-checking) */ 00155 complex_t get(size_t i) const { 00156 #if GSL_RANGE_CHECK 00157 if (i>=sz) { 00158 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00159 +" in uvector_cx_view_tlate::get(). Size: "+ 00160 itos(sz)+ 00161 " (index should be less than size).").c_str(),gsl_index); 00162 return *(complex_t *)(data); 00163 } 00164 #endif 00165 return *(complex_t *)(&data[i*2]); 00166 } 00167 00168 /** \brief Get pointer (with optional range-checking) */ 00169 complex_t *get_ptr(size_t i) { 00170 #if GSL_RANGE_CHECK 00171 if (i>=sz) { 00172 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00173 +" in uvector_cx_view_tlate::get_ptr(). Size: "+ 00174 itos(sz)+ 00175 " (index should be less than size).").c_str(),gsl_index); 00176 return (complex_t *)(data); 00177 } 00178 #endif 00179 return (complex_t *)(&data[i*2]); 00180 } 00181 00182 /** \brief Get pointer (with optional range-checking) */ 00183 const complex_t *get_const_ptr(size_t i) const { 00184 #if GSL_RANGE_CHECK 00185 if (i>=sz) { 00186 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00187 +" in uvector_cx_view_tlate::get_const_ptr(). Size: "+ 00188 itos(sz)+ 00189 " (index should be less than size).").c_str(),gsl_index); 00190 return (const complex_t *)(data); 00191 } 00192 #endif 00193 return (const complex_t *)(&data[i*2]); 00194 } 00195 00196 /** \brief Set (with optional range-checking) */ 00197 int set(size_t i, const complex_t &val) { 00198 #if GSL_RANGE_CHECK 00199 if (i>=sz) { 00200 set_err_ret((((std::string)"Array index ")+itos(i)+" out of bounds" 00201 +" in uvector_cx_view_tlate::set(). Size: "+ 00202 itos(sz)+ 00203 " (index should be less than size).").c_str(),gsl_index); 00204 } 00205 #endif 00206 data[2*i]=val.dat[0]; 00207 data[2*i+1]=val.dat[1]; 00208 return 0; 00209 } 00210 00211 /** \brief Set all of the value to be the value \c val */ 00212 int set_all(const complex_t &val) { 00213 double re=val.dat[0]; 00214 double im=val.dat[1]; 00215 for(size_t i=0;i<sz;i++) { 00216 data[2*i]=re; 00217 data[2*i+1]=im; 00218 } 00219 return 0; 00220 } 00221 00222 /** 00223 \brief Method to return vector size 00224 00225 If no memory has been allocated, this will quietly 00226 return zero. 00227 */ 00228 size_t size() const { 00229 return sz; 00230 } 00231 //@} 00232 00233 /// \name Other methods 00234 //@{ 00235 00236 /** \brief Swap vectors */ 00237 int swap(uvector_cx_view_tlate<data_t,complex_t> &x) { 00238 size_t t1; 00239 double *t3; 00240 int t5; 00241 00242 t1=sz; 00243 t3=data; 00244 t5=owner; 00245 00246 sz=x.sz; 00247 data=x.data; 00248 owner=x.owner; 00249 00250 x.sz=t1; 00251 x.data=t3; 00252 x.owner=t5; 00253 00254 return 0; 00255 } 00256 00257 /// Return true if this object owns the data it refers to 00258 bool is_owner() const { 00259 if (owner==1) return true; 00260 return false; 00261 } 00262 00263 /// \name Arithmetic 00264 //@{ 00265 /** \brief operator+= */ 00266 uvector_cx_view_tlate<data_t,complex_t> &operator+= 00267 (const uvector_cx_view_tlate<data_t,complex_t> &x) { 00268 size_t lsz=x.sz; 00269 if (lsz>sz) lsz=sz; 00270 for(size_t i=0;i<lsz;i++) (*this)[i]+=x[i]; 00271 00272 return *this; 00273 } 00274 00275 /** \brief operator-= */ 00276 uvector_cx_view_tlate<data_t,complex_t> &operator-= 00277 (const uvector_cx_view_tlate<data_t,complex_t> &x) { 00278 size_t lsz=x.sz; 00279 if (lsz>sz) lsz=sz; 00280 for(size_t i=0;i<lsz;i++) (*this)[i]-=x[i]; 00281 00282 return *this; 00283 } 00284 00285 /** \brief operator+= */ 00286 uvector_cx_view_tlate<data_t,complex_t> &operator+=(const data_t &y) { 00287 for(size_t i=0;i<sz;i++) (*this)[i]+=y; 00288 00289 return *this; 00290 } 00291 00292 /** \brief operator-= */ 00293 uvector_cx_view_tlate<data_t,complex_t> &operator-=(const data_t &y) { 00294 for(size_t i=0;i<sz;i++) (*this)[i]-=y; 00295 00296 return *this; 00297 } 00298 00299 /** \brief operator*= */ 00300 uvector_cx_view_tlate<data_t,complex_t> &operator*=(const data_t &y) { 00301 for(size_t i=0;i<sz;i++) (*this)[i]*=y; 00302 00303 return *this; 00304 } 00305 00306 /** \brief Norm */ 00307 data_t norm() const { 00308 data_t result=0; 00309 for(size_t i=0;i<sz;i++) { 00310 result+=(*this)[i]*(*this)[i]; 00311 } 00312 return sqrt(result); 00313 } 00314 //@} 00315 00316 #ifndef DOXYGEN_INTERNAL 00317 00318 protected: 00319 00320 /** \brief Empty constructor provided for use by 00321 uvector_cx_tlate(const uvector_cx_tlate &v) 00322 */ 00323 uvector_cx_view_tlate() {}; 00324 00325 #endif 00326 00327 }; 00328 00329 /** 00330 \brief A vector of double-precision numbers with unit stride 00331 00332 There are several global binary operators associated with 00333 objects of type \ref uvector_cx_tlate. The are documented in the 00334 "Functions" section of \ref uvector_cx_tlate.h. 00335 */ 00336 template<class data_t, class complex_t> class uvector_cx_tlate : 00337 public uvector_cx_view_tlate<data_t,complex_t> { 00338 public: 00339 00340 /// \name Standard constructor 00341 //@{ 00342 /** \brief Create an uvector_cx of size \c n with owner as 'true' */ 00343 uvector_cx_tlate(size_t n=0) { 00344 // This must be set to 1 even if n=0 so that future 00345 // calls to operator= work properly 00346 this->owner=1; 00347 if (n>0) { 00348 this->data=(data_t *)malloc(2*n*sizeof(data_t)); 00349 if (this->data) { 00350 this->sz=n; 00351 } else { 00352 set_err("No memory for data in uvector_cx_tlate constructor", 00353 gsl_enomem); 00354 } 00355 } else { 00356 this->sz=0; 00357 } 00358 } 00359 //@} 00360 00361 /// \name Copy constructors 00362 //@{ 00363 /// Deep copy constructor - allocate new space and make a copy 00364 uvector_cx_tlate(const uvector_cx_tlate &v) : 00365 uvector_cx_view_tlate<data_t,complex_t>() { 00366 size_t n=v.sz; 00367 if (n>0) { 00368 this->data=(data_t *)malloc(2*n*sizeof(data_t)); 00369 if (this->data) { 00370 this->sz=n; 00371 this->owner=1; 00372 for(size_t i=0;i<n;i++) { 00373 this->data[2*i]=v[i].dat[0]; 00374 this->data[2*i+1]=v[i].dat[1]; 00375 } 00376 } else { 00377 set_err("No memory for data in uvector_cx_tlate constructor", 00378 gsl_enomem); 00379 } 00380 } else { 00381 this->sz=0; 00382 } 00383 } 00384 00385 /// Deep copy constructor - allocate new space and make a copy 00386 uvector_cx_tlate(const uvector_cx_view_tlate<data_t,complex_t> &v) : 00387 uvector_cx_view_tlate<data_t,complex_t>() { 00388 size_t n=v.sz; 00389 if (n>0) { 00390 this->data=(data_t *)malloc(2*n*sizeof(data_t)); 00391 if (this->data) { 00392 this->sz=n; 00393 this->owner=1; 00394 for(size_t i=0;i<n;i++) { 00395 this->data[2*i]=v[i].dat[0]; 00396 this->data[2*i+1]=v[i].dat[1]; 00397 } 00398 } else { 00399 set_err("No memory for data in uvector_cx_tlate constructor", 00400 gsl_enomem); 00401 } 00402 } else { 00403 this->sz=0; 00404 } 00405 } 00406 00407 /** \brief Deep copy constructor - if owner is true, allocate space and 00408 make a new copy, otherwise, just copy into the view 00409 */ 00410 uvector_cx_tlate& operator=(const uvector_cx_tlate &v) { 00411 size_t sz2=v.sz; 00412 if (this->owner) { 00413 allocate(sz2); 00414 } else { 00415 if (this->sz!=sz2) { 00416 set_err("Sizes don't match in uvector_cx_tlate::operator=()", 00417 gsl_ebadlen); 00418 return *this; 00419 } 00420 } 00421 for(size_t i=0;i<sz2;i++) { 00422 this->data[2*i]=v[i].dat[0]; 00423 this->data[2*i+1]=v[i].dat[1]; 00424 } 00425 return *this; 00426 } 00427 00428 /** \brief Deep copy constructor - if owner is true, allocate space and 00429 make a new copy, otherwise, just copy into the view 00430 */ 00431 uvector_cx_tlate& operator= 00432 (const uvector_cx_view_tlate<data_t,complex_t> &v) { 00433 size_t sz2=v.size(); 00434 if (this->owner) { 00435 allocate(sz2); 00436 } else { 00437 if (this->sz!=sz2) { 00438 set_err("Sizes don't match in uvector_cx_tlate::operator=()", 00439 gsl_ebadlen); 00440 return *this; 00441 } 00442 } 00443 for(size_t i=0;i<sz2;i++) { 00444 this->data[2*i]=v[i].dat[0]; 00445 this->data[2*i+1]=v[i].dat[1]; 00446 } 00447 return *this; 00448 } 00449 //@} 00450 00451 ~uvector_cx_tlate() { 00452 if (this->sz>0) { 00453 if (this->owner==1) { 00454 std::free(this->data); 00455 } 00456 this->sz=0; 00457 } 00458 } 00459 00460 /// \name Memory allocation 00461 //@{ 00462 /** 00463 \brief Allocate memory for size \c n after freeing any memory 00464 presently in use 00465 */ 00466 int allocate(size_t nsize) { 00467 if (this->sz>0) free(); 00468 00469 if (nsize>0) { 00470 this->data=(data_t *)malloc(2*nsize*sizeof(data_t)); 00471 if (this->data) { 00472 this->sz=nsize; 00473 this->owner=1; 00474 } else { 00475 set_err_ret("No memory for data in uvector_cx_tlate::allocate()", 00476 gsl_enomem); 00477 } 00478 } else { 00479 set_err_ret("Zero size in uvector_cx::allocate()",gsl_einval); 00480 } 00481 return 0; 00482 } 00483 00484 /** 00485 \brief Free the memory 00486 00487 This function will safely do nothing if used without first 00488 allocating memory or if called multiple times in succession. 00489 */ 00490 int free() { 00491 if (this->sz>0) { 00492 if (this->owner==1) { 00493 std::free(this->data); 00494 } 00495 this->sz=0; 00496 } 00497 return 0; 00498 } 00499 //@} 00500 00501 }; 00502 00503 /** \brief Create a vector from an array 00504 */ 00505 template<class data_t, class complex_t> class uvector_cx_array_tlate : 00506 public uvector_cx_view_tlate<data_t,complex_t> { 00507 public: 00508 /** \brief Create a vector from \c dat with size \c n */ 00509 uvector_cx_array_tlate(size_t n, data_t *dat) { 00510 if (n>0) { 00511 this->data=dat; 00512 this->sz=n; 00513 this->owner=0; 00514 } 00515 } 00516 }; 00517 00518 /** \brief Create a vector from a subvector of another 00519 */ 00520 template<class data_t, class complex_t> class uvector_cx_subvector_tlate : 00521 public uvector_cx_view_tlate<data_t,complex_t> { 00522 public: 00523 /** \brief Create a vector from \c orig */ 00524 uvector_cx_subvector_tlate(uvector_cx_view_tlate<data_t,complex_t> &orig, 00525 size_t offset, size_t n) { 00526 if (offset+n-1<orig.size) { 00527 this->data=orig.data+offset; 00528 this->sz=n; 00529 this->owner=0; 00530 } else { 00531 this->sz=0; 00532 set_err("Subvector failed in uvector_cx_sub_view().",1); 00533 } 00534 } 00535 }; 00536 00537 /** \brief Create a vector from an array 00538 */ 00539 template<class data_t, class complex_t> class uvector_cx_const_array_tlate : 00540 public uvector_cx_view_tlate<data_t,complex_t> { 00541 public: 00542 /** \brief Create a vector from \c dat with size \c n */ 00543 uvector_cx_const_array_tlate(size_t n, const data_t *dat) { 00544 if (n>0) { 00545 // We have to do an explicit cast here, but we prevent the 00546 // user from changing the data. 00547 this->data=(data_t *)dat; 00548 this->sz=n; 00549 this->owner=0; 00550 } 00551 } 00552 00553 ~uvector_cx_const_array_tlate() {}; 00554 00555 #ifndef DOXYGEN_INTERNAL 00556 00557 protected: 00558 00559 /** \name These are inaccessible to ensure the vector is \c const. 00560 */ 00561 //@{ 00562 data_t &operator[](size_t i) { return this->data[0]; } 00563 data_t &operator()(size_t i) { return this->data[0]; } 00564 data_t *get_ptr(size_t i) { return NULL; } 00565 int set(size_t i, data_t val) { return 0; } 00566 int swap(uvector_cx_view_tlate<data_t,complex_t> &x) { 00567 return 0; 00568 } 00569 int set_all(double val) { return 0; } 00570 uvector_cx_view_tlate<data_t,complex_t> &operator+= 00571 (const uvector_cx_view_tlate<data_t,complex_t> &x) { 00572 return *this; 00573 } 00574 uvector_cx_view_tlate<data_t,complex_t> &operator-= 00575 (const uvector_cx_view_tlate<data_t,complex_t> &x) { 00576 return *this; 00577 } 00578 uvector_cx_view_tlate<data_t,complex_t> &operator*=(const data_t &y) { 00579 return *this; 00580 } 00581 //@} 00582 00583 #endif 00584 00585 }; 00586 00587 /** \brief Create a vector from a subvector of another 00588 */ 00589 template<class data_t, class complex_t> 00590 class uvector_cx_const_subvector_tlate : 00591 public uvector_cx_view_tlate<data_t,complex_t> { 00592 public: 00593 /** \brief Create a vector from \c orig 00594 */ 00595 uvector_cx_const_subvector_tlate 00596 (const uvector_cx_view_tlate<data_t,complex_t> &orig, 00597 size_t offset, size_t n) { 00598 if (offset+n-1<orig.sz) { 00599 this->data=orig.data+offset; 00600 this->sz=n; 00601 this->owner=0; 00602 } else { 00603 this->sz=0; 00604 set_err("Subvector failed in uvector_cx_subvector().",1); 00605 } 00606 } 00607 00608 #ifndef DOXYGENP 00609 00610 protected: 00611 00612 /** \name Ensure \c const by hiding non-const members 00613 */ 00614 //@{ 00615 data_t &operator[](size_t i) { return this->data[0]; } 00616 data_t &operator()(size_t i) { return this->data[0]; } 00617 data_t *get_ptr(size_t i) { return NULL; } 00618 int set(size_t i, data_t val) { return 0; } 00619 int swap(uvector_cx_view_tlate<data_t,complex_t> &x) { 00620 return 0; 00621 } 00622 int set_all(double val) { return 0; } 00623 uvector_cx_view_tlate<data_t,complex_t> &operator+= 00624 (const uvector_cx_view_tlate<data_t,complex_t> &x) { 00625 return *this; 00626 } 00627 uvector_cx_view_tlate<data_t,complex_t> &operator-= 00628 (const uvector_cx_view_tlate<data_t,complex_t> &x) { 00629 return *this; 00630 } 00631 uvector_cx_view_tlate<data_t,complex_t> &operator*=(const data_t &y) { 00632 return *this; 00633 } 00634 //@} 00635 00636 #endif 00637 00638 }; 00639 00640 /// uvector_cx typedef 00641 typedef uvector_cx_tlate<double,gsl_complex> uvector_cx; 00642 /// uvector_cx_view typedef 00643 typedef uvector_cx_view_tlate<double,gsl_complex> uvector_cx_view; 00644 /// uvector_cx_array typedef 00645 typedef uvector_cx_array_tlate<double,gsl_complex> uvector_cx_array; 00646 /// uvector_cx_subvector typedef 00647 typedef uvector_cx_subvector_tlate<double,gsl_complex> uvector_cx_subvector; 00648 /// uvector_cx_const_array typedef 00649 typedef uvector_cx_const_array_tlate<double,gsl_complex> 00650 uvector_cx_const_array; 00651 /// uvector_cx_const_subvector typedef 00652 typedef uvector_cx_const_subvector_tlate<double,gsl_complex> 00653 uvector_cx_const_subvector; 00654 00655 /** 00656 \brief A operator for naive vector output 00657 00658 This outputs all of the vector elements. All of these are 00659 separated by one space character, though no trailing space or \c 00660 endl is sent to the output. 00661 */ 00662 template<class data_t, class complex_t> 00663 std::ostream &operator<< 00664 (std::ostream &os, 00665 const uvector_cx_view_tlate<data_t,complex_t> &v) { 00666 if (v.size()>0) { 00667 for(size_t i=0;i<v.size()-1;i++) { 00668 os << v[i] << ' '; 00669 } 00670 os << v[v.size()-1]; 00671 } else { 00672 os << "<empty>"; 00673 } 00674 return os; 00675 } 00676 00677 #ifndef DOXYGENP 00678 } 00679 #endif 00680 00681 #endif 00682
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