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