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