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_TLATE_H 00024 #define O2SCL_UVECTOR_TLATE_H 00025 00026 /** \file uvector_tlate.h 00027 \brief File for definitions of unit-stride vectors 00028 */ 00029 00030 #include <iostream> 00031 #include <cstdlib> 00032 #include <string> 00033 #include <fstream> 00034 #include <sstream> 00035 #include <vector> 00036 00037 #include <gsl/gsl_vector.h> 00038 00039 #include <o2scl/err_hnd.h> 00040 #include <o2scl/string_conv.h> 00041 #include <o2scl/array.h> 00042 #include <o2scl/vector.h> 00043 00044 #ifndef DOXYGENP 00045 namespace o2scl { 00046 #endif 00047 00048 // Forward declaration 00049 template<class data_t> class uvector_base_tlate; 00050 // Forward declaration 00051 template<class data_t> class uvector_view_tlate; 00052 // Forward declaration 00053 template<class data_t> class uvector_tlate; 00054 00055 /** 00056 \brief A const vector view with unit stride 00057 00058 \future Could allow user-defined specification of 00059 restrict keyword 00060 */ 00061 template<class data_t> class uvector_const_view_tlate { 00062 00063 #ifndef DOXYGEN_INTERNAL 00064 00065 protected: 00066 00067 // Make sure everyone can access the base data 00068 friend class uvector_base_tlate<data_t>; 00069 friend class uvector_view_tlate<data_t>; 00070 friend class uvector_tlate<data_t>; 00071 00072 /// The data 00073 data_t *data; 00074 /// The vector sz 00075 size_t sz; 00076 /// Zero if memory is owned elsewhere, 1 otherwise 00077 int owner; 00078 00079 #endif 00080 00081 public: 00082 00083 /// \name Copy constructors 00084 //@{ 00085 /// Copy constructor - create a new view of the same vector 00086 uvector_const_view_tlate(const uvector_const_view_tlate &v) { 00087 data=v.data; 00088 sz=v.sz; 00089 owner=0; 00090 } 00091 00092 /// Copy constructor - create a new view of the same vector 00093 uvector_const_view_tlate& operator=(const uvector_const_view_tlate &v) { 00094 data=v.data; 00095 sz=v.sz; 00096 owner=0; 00097 00098 return *this; 00099 } 00100 //@} 00101 00102 ~uvector_const_view_tlate() {}; 00103 00104 /// \name Get and set methods 00105 //@{ 00106 /** 00107 \brief Array-like indexing 00108 */ 00109 const data_t &operator[](size_t i) const { 00110 #if O2SCL_NO_RANGE_CHECK 00111 #else 00112 if (i>=sz) { 00113 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00114 +" in uvector_const_view_tlate::operator[] const. Size: "+ 00115 itos(sz)+ 00116 " (index should be less than size).").c_str(),gsl_eindex); 00117 return data[0]; 00118 } 00119 #endif 00120 return data[i]; 00121 } 00122 00123 /** 00124 \brief Array-like indexing 00125 */ 00126 const data_t &operator()(size_t i) const { 00127 #if O2SCL_NO_RANGE_CHECK 00128 #else 00129 if (i>=sz) { 00130 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00131 +" in uvector_const_view_tlate::operator() const. Size: "+ 00132 itos(sz)+ 00133 " (index should be less than size).").c_str(),gsl_eindex); 00134 return data[0]; 00135 } 00136 #endif 00137 return data[i]; 00138 } 00139 00140 /** \brief Get (with optional range-checking) */ 00141 data_t get(size_t i) const { 00142 #if O2SCL_NO_RANGE_CHECK 00143 #else 00144 if (i>=sz) { 00145 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00146 +" in uvector_const_view_tlate::get(). Size: "+ 00147 itos(sz)+ 00148 " (index should be less than size).").c_str(),gsl_eindex); 00149 return data[0]; 00150 } 00151 #endif 00152 return data[i]; 00153 } 00154 00155 /** \brief Get pointer (with optional range-checking) */ 00156 const data_t *get_const_ptr(size_t i) const { 00157 #if O2SCL_NO_RANGE_CHECK 00158 #else 00159 if (i>=sz) { 00160 O2SCL_ERR2("Index out of range in ", 00161 "uvector_const_view::get_const_ptr().",1); 00162 return 0; 00163 } 00164 #endif 00165 return (const data_t *)(data+i); 00166 } 00167 00168 /** 00169 \brief Method to return vector size 00170 00171 If no memory has been allocated, this will quietly 00172 return zero. 00173 */ 00174 size_t size() const { 00175 return sz; 00176 } 00177 //@} 00178 00179 /// \name Other methods 00180 //@{ 00181 00182 /// Return true if this object owns the data it refers to 00183 bool is_owner() const { 00184 if (owner==1) return true; 00185 return false; 00186 } 00187 00188 /** \brief Exhaustively look through the array for a 00189 particular value 00190 00191 This can only fail if \em all of the entries in the array are 00192 not finite, in which case it calls O2SCL_ERR() and returns 00193 0. 00194 00195 If more than one entry is the same distance from <tt>x0</tt>, 00196 this function returns the entry with smallest index. 00197 */ 00198 size_t lookup(const data_t x0) const { 00199 00200 const uvector_const_view_tlate<data_t> *a=this; 00201 size_t row=0, i=0, nvar=size(); 00202 while(!finite((*a)[i]) && i<nvar-1) i++; 00203 if (i==nvar-1) { 00204 O2SCL_ERR("Array not finite in intp_base::lookup()",1); 00205 return 0; 00206 } 00207 data_t best=(*a)[i], bdiff=fabs((*a)[i]-x0); 00208 for(;i<nvar;i++) { 00209 if (finite((*a)[i]) && fabs((*a)[i]-x0)<bdiff) { 00210 row=i; 00211 best=(*a)[i]; 00212 bdiff=fabs((*a)[i]-x0); 00213 } 00214 } 00215 return row; 00216 } 00217 00218 /** \brief Find the maximum element */ 00219 data_t max() const { 00220 data_t maxval; 00221 if (sz>0) { 00222 maxval=data[0]; 00223 for(size_t i=1;i<sz;i++) { 00224 if (data[i]>maxval) { 00225 maxval=data[i]; 00226 } 00227 } 00228 } else { 00229 return 0.0; 00230 } 00231 return maxval; 00232 } 00233 00234 /** \brief Find the minimum element */ 00235 data_t min() const { 00236 data_t minval; 00237 if (sz>0) { 00238 minval=data[0]; 00239 for(size_t i=1;i<sz;i++) { 00240 if (data[i]<minval) { 00241 minval=data[i]; 00242 } 00243 } 00244 } else { 00245 return 0.0; 00246 } 00247 return minval; 00248 } 00249 //@} 00250 00251 /** \brief Norm 00252 00253 \todo Fix this so that norm() is computed as 00254 in ovector and so that integer norms are performed 00255 separately. 00256 */ 00257 data_t norm() const { 00258 data_t result=0; 00259 for(size_t i=0;i<sz;i++) { 00260 result+=(*this)[i]*(*this)[i]; 00261 } 00262 return std::sqrt(result); 00263 } 00264 00265 #ifndef DOXYGEN_INTERNAL 00266 00267 protected: 00268 00269 /** \brief Empty constructor provided for use by 00270 uvector_tlate(const uvector_tlate &v) 00271 */ 00272 uvector_const_view_tlate() {}; 00273 00274 #endif 00275 00276 }; 00277 00278 /// Desc 00279 template<class data_t> class uvector_base_tlate : 00280 public uvector_const_view_tlate<data_t> { 00281 00282 public: 00283 00284 /// \name Copy constructors 00285 //@{ 00286 /// Copy constructor - create a new view of the same vector 00287 uvector_base_tlate(uvector_base_tlate &v) : 00288 uvector_const_view_tlate<data_t>() { 00289 this->data=v.data; 00290 this->sz=v.sz; 00291 this->owner=0; 00292 } 00293 00294 /// Copy constructor - create a new view of the same vector 00295 uvector_base_tlate& operator=(uvector_base_tlate &v) { 00296 this->data=v.data; 00297 this->sz=v.sz; 00298 this->owner=0; 00299 00300 return *this; 00301 } 00302 //@} 00303 00304 /// \name Get and set methods 00305 //@{ 00306 /** 00307 \brief Array-like indexing 00308 */ 00309 data_t &operator[](size_t i) { 00310 #if O2SCL_NO_RANGE_CHECK 00311 #else 00312 if (i>=this->sz) { 00313 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00314 +" in uvector_const_view_tlate::operator[]. Size: "+ 00315 itos(this->sz)+ 00316 " (index should be less than size).").c_str(),gsl_eindex); 00317 return this->data[0]; 00318 } 00319 #endif 00320 return this->data[i]; 00321 } 00322 00323 /** 00324 \brief Array-like indexing 00325 */ 00326 const data_t &operator[](size_t i) const { 00327 #if O2SCL_NO_RANGE_CHECK 00328 #else 00329 if (i>=this->sz) { 00330 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00331 +" in uvector_const_view_tlate::operator[] const. Size: "+ 00332 itos(this->sz)+ 00333 " (index should be less than size).").c_str(),gsl_eindex); 00334 return this->data[0]; 00335 } 00336 #endif 00337 return this->data[i]; 00338 } 00339 00340 /** 00341 \brief Array-like indexing 00342 */ 00343 data_t &operator()(size_t i) { 00344 #if O2SCL_NO_RANGE_CHECK 00345 #else 00346 if (i>=this->sz) { 00347 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00348 +" in uvector_const_view_tlate::operator(). Size: "+ 00349 itos(this->sz)+ 00350 " (index should be less than size).").c_str(),gsl_eindex); 00351 return this->data[0]; 00352 } 00353 #endif 00354 return this->data[i]; 00355 } 00356 00357 /** 00358 \brief Array-like indexing 00359 */ 00360 const data_t &operator()(size_t i) const { 00361 #if O2SCL_NO_RANGE_CHECK 00362 #else 00363 if (i>=this->sz) { 00364 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00365 +" in uvector_const_view_tlate::operator() const. Size: "+ 00366 itos(this->sz)+ 00367 " (index should be less than size).").c_str(),gsl_eindex); 00368 return this->data[0]; 00369 } 00370 #endif 00371 return this->data[i]; 00372 } 00373 00374 /** \brief Get pointer (with optional range-checking) */ 00375 data_t *get_ptr(size_t i) { 00376 #if O2SCL_NO_RANGE_CHECK 00377 #else 00378 if (i>=this->sz) { 00379 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00380 +" in uvector_const_view_tlate::get_ptr(). Size: "+ 00381 itos(this->sz)+ 00382 " (index should be less than size).").c_str(),gsl_eindex); 00383 return this->data; 00384 } 00385 #endif 00386 return this->data+i; 00387 } 00388 00389 /** \brief Set (with optional range-checking) */ 00390 int set(size_t i, data_t val) { 00391 #if O2SCL_NO_RANGE_CHECK 00392 #else 00393 if (i>=this->sz) { 00394 O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds" 00395 +" in uvector_const_view_tlate::set(). Size: "+ 00396 itos(this->sz)+ 00397 " (index should be less than size).").c_str(),gsl_eindex); 00398 } 00399 #endif 00400 this->data[i]=val; 00401 return 0; 00402 } 00403 00404 /** \brief Set all of the value to be the value \c val */ 00405 int set_all(data_t val) { 00406 for(size_t i=0;i<this->sz;i++) { 00407 this->data[i]=val; 00408 } 00409 return 0; 00410 } 00411 00412 //@} 00413 00414 /// \name Arithmetic 00415 //@{ 00416 /** \brief operator+= */ 00417 uvector_base_tlate<data_t> &operator+= 00418 (const uvector_base_tlate<data_t> &x) { 00419 size_t lsz=x.size(); 00420 if (lsz>this->sz) lsz=this->sz; 00421 for(size_t i=0;i<lsz;i++) (*this)[i]+=x[i]; 00422 00423 return *this; 00424 } 00425 00426 /** \brief operator-= */ 00427 uvector_base_tlate<data_t> &operator-= 00428 (const uvector_base_tlate<data_t> &x) { 00429 size_t lsz=x.size(); 00430 if (lsz>this->sz) lsz=this->sz; 00431 for(size_t i=0;i<lsz;i++) (*this)[i]-=x[i]; 00432 00433 return *this; 00434 } 00435 00436 /** \brief operator+= */ 00437 uvector_base_tlate<data_t> &operator+=(const data_t &y) { 00438 for(size_t i=0;i<this->sz;i++) (*this)[i]+=y; 00439 00440 return *this; 00441 } 00442 00443 /** \brief operator-= */ 00444 uvector_base_tlate<data_t> &operator-=(const data_t &y) { 00445 for(size_t i=0;i<this->sz;i++) (*this)[i]-=y; 00446 00447 return *this; 00448 } 00449 00450 /** \brief operator*= */ 00451 uvector_base_tlate<data_t> &operator*=(const data_t &y) { 00452 for(size_t i=0;i<this->sz;i++) (*this)[i]*=y; 00453 00454 return *this; 00455 } 00456 //@} 00457 00458 #ifndef DOXYGEN_INTERNAL 00459 00460 protected: 00461 00462 /** \brief Empty constructor for use by children 00463 00464 \comment 00465 This is private because I want to prevent the casual end-user 00466 from creating uvector_base objects. End-users should really be 00467 focused on making normal vectors and views. 00468 \endcomment 00469 */ 00470 uvector_base_tlate() {} 00471 00472 #endif 00473 00474 }; 00475 00476 #ifdef O2SCL_NEVER_DEFINED 00477 }{ 00478 #endif 00479 00480 /** \brief A base class for uvectors 00481 */ 00482 template<class data_t> class uvector_view_tlate : 00483 public uvector_base_tlate<data_t> { 00484 00485 public: 00486 00487 /// \name Copy constructors 00488 //@{ 00489 /// Copy constructor - create a new view of the same vector 00490 uvector_view_tlate(const uvector_view_tlate &v) : 00491 uvector_base_tlate<data_t>() { 00492 this->data=v.data; 00493 this->sz=v.sz; 00494 this->owner=0; 00495 } 00496 00497 /// Copy constructor - create a new view of the same vector 00498 uvector_view_tlate& operator=(const uvector_view_tlate &v) { 00499 this->data=v.data; 00500 this->sz=v.sz; 00501 this->owner=0; 00502 00503 return *this; 00504 } 00505 00506 /// Copy constructor - create a new view of the same vector 00507 uvector_view_tlate(uvector_base_tlate<data_t> &v) : 00508 uvector_base_tlate<data_t>() { 00509 this->data=v.data; 00510 this->sz=v.sz; 00511 this->owner=0; 00512 } 00513 00514 /// Copy constructor - create a new view of the same vector 00515 uvector_view_tlate& operator=(uvector_base_tlate<data_t> &v) { 00516 this->data=v.data; 00517 this->sz=v.sz; 00518 this->owner=0; 00519 00520 return *this; 00521 } 00522 //@} 00523 00524 /// \name Get and set methods 00525 //@{ 00526 /** 00527 \brief Array-like indexing 00528 */ 00529 data_t &operator[](size_t i) const { 00530 #if O2SCL_NO_RANGE_CHECK 00531 #else 00532 if (i>=this->sz) { 00533 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00534 +" in uvector_view_tlate::operator[]. Size: "+ 00535 itos(this->sz)+ 00536 " (index should be less than size).").c_str(),gsl_eindex); 00537 return this->data[0]; 00538 } 00539 #endif 00540 return this->data[i]; 00541 } 00542 00543 /** 00544 \brief Array-like indexing 00545 */ 00546 data_t &operator()(size_t i) const { 00547 #if O2SCL_NO_RANGE_CHECK 00548 #else 00549 if (i>=this->sz) { 00550 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00551 +" in uvector_view_tlate::operator(). Size: "+ 00552 itos(this->sz)+ 00553 " (index should be less than size).").c_str(),gsl_eindex); 00554 return this->data[0]; 00555 } 00556 #endif 00557 return this->data[i]; 00558 } 00559 00560 /** \brief Get pointer (with optional range-checking) */ 00561 data_t *get_ptr(size_t i) const { 00562 #if O2SCL_NO_RANGE_CHECK 00563 #else 00564 if (i>=this->sz) { 00565 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00566 +" in uvector_view_tlate::get_ptr(). Size: "+ 00567 itos(this->sz)+ 00568 " (index should be less than size).").c_str(),gsl_eindex); 00569 return this->data; 00570 } 00571 #endif 00572 return this->data+i; 00573 } 00574 00575 /** \brief Set (with optional range-checking) */ 00576 int set(size_t i, data_t val) const { 00577 #if O2SCL_NO_RANGE_CHECK 00578 #else 00579 if (i>=this->sz) { 00580 O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds" 00581 +" in uvector_view_tlate::set(). Size: "+ 00582 itos(this->sz)+ 00583 " (index should be less than size).").c_str(),gsl_eindex); 00584 } 00585 #endif 00586 this->data[i]=val; 00587 return 0; 00588 } 00589 00590 /** \brief Set all of the value to be the value \c val */ 00591 int set_all(data_t val) const { 00592 for(size_t i=0;i<this->sz;i++) { 00593 this->data[i]=val; 00594 } 00595 return 0; 00596 } 00597 00598 //@} 00599 00600 #ifndef DOXYGEN_INTERNAL 00601 00602 protected: 00603 00604 /** \brief Empty constructor provided for use by 00605 uvector_view_tlate(const uvector_view_tlate &v) 00606 */ 00607 uvector_view_tlate() {} 00608 00609 #endif 00610 00611 }; 00612 00613 /** 00614 \brief A vector with unit stride 00615 00616 There are several useful methods which are defined in the parent 00617 class, \ref uvector_view_tlate . There is also an << operator 00618 for this class documented "Functions" section of \ref 00619 uvector_tlate.h. 00620 */ 00621 template<class data_t> class uvector_tlate : 00622 public uvector_base_tlate<data_t> { 00623 00624 public: 00625 00626 // This is required so that the uvector_view_tlate constructor 00627 // can access uvector_tlate data. 00628 friend class uvector_view_tlate<data_t>; 00629 00630 /// \name Standard constructor 00631 //@{ 00632 /** \brief Create an uvector of size \c n with owner as 'true' */ 00633 uvector_tlate(size_t n=0) { 00634 00635 this->sz=0; 00636 this->data=0; 00637 00638 // This must be set to 1 even if n=0 so that future 00639 // calls to operator= work properly 00640 this->owner=1; 00641 00642 if (n>0) { 00643 this->data=(data_t *)malloc(n*sizeof(data_t)); 00644 if (this->data) { 00645 this->sz=n; 00646 } else { 00647 O2SCL_ERR("No memory for data in uvector_tlate constructor", 00648 gsl_enomem); 00649 } 00650 } 00651 } 00652 //@} 00653 00654 /// \name Copy constructors 00655 //@{ 00656 /// Deep copy constructor - allocate new space and make a copy 00657 uvector_tlate(const uvector_tlate &v) : 00658 uvector_base_tlate<data_t>() { 00659 00660 this->sz=0; 00661 this->data=0; 00662 this->owner=1; 00663 00664 size_t n=v.sz; 00665 if (n>0) { 00666 this->data=(data_t *)malloc(n*sizeof(data_t)); 00667 if (this->data) { 00668 this->sz=n; 00669 this->owner=1; 00670 for(size_t i=0;i<n;i++) { 00671 this->data[i]=v[i]; 00672 } 00673 } else { 00674 O2SCL_ERR("No memory for data in uvector_tlate constructor", 00675 gsl_enomem); 00676 } 00677 } else { 00678 this->sz=0; 00679 } 00680 } 00681 00682 /// Deep copy constructor - allocate new space and make a copy 00683 uvector_tlate(const uvector_const_view_tlate<data_t> &v) : 00684 uvector_base_tlate<data_t>() { 00685 00686 this->sz=0; 00687 this->data=0; 00688 this->owner=1; 00689 00690 size_t n=v.size(); 00691 if (n>0) { 00692 this->data=(data_t *)malloc(n*sizeof(data_t)); 00693 if (this->data) { 00694 this->sz=n; 00695 this->owner=1; 00696 for(size_t i=0;i<n;i++) { 00697 this->data[i]=v[i]; 00698 } 00699 } else { 00700 O2SCL_ERR("No memory for data in uvector_tlate constructor", 00701 gsl_enomem); 00702 } 00703 } else { 00704 this->sz=0; 00705 } 00706 } 00707 00708 /** \brief Deep copy constructor - if owner is true, allocate space and 00709 make a new copy, otherwise, just copy into the view 00710 */ 00711 uvector_tlate& operator=(const uvector_tlate &v) { 00712 00713 // Check for self-assignment 00714 if (this==&v) return *this; 00715 00716 size_t sz2=v.sz; 00717 this->sz=0; 00718 this->data=0; 00719 if (this->owner) { 00720 allocate(sz2); 00721 } else { 00722 if (this->sz!=sz2) { 00723 O2SCL_ERR("Sizes don't match in uvector_tlate::operator=()", 00724 gsl_ebadlen); 00725 return *this; 00726 } 00727 } 00728 for(size_t i=0;i<sz2;i++) { 00729 this->data[i]=v[i]; 00730 } 00731 return *this; 00732 } 00733 00734 /** \brief Deep copy constructor - if owner is true, allocate space and 00735 make a new copy, otherwise, just copy into the view 00736 */ 00737 uvector_tlate& operator=(const uvector_const_view_tlate<data_t> &v) { 00738 00739 // Check for self-assignment 00740 if (this==&v) return *this; 00741 00742 size_t sz2=v.size(); 00743 this->sz=0; 00744 this->data=0; 00745 if (this->owner) { 00746 allocate(sz2); 00747 } else { 00748 if (this->sz!=sz2) { 00749 O2SCL_ERR("Sizes don't match in uvector_tlate::operator=()", 00750 gsl_ebadlen); 00751 return *this; 00752 } 00753 } 00754 for(size_t i=0;i<sz2;i++) { 00755 this->data[i]=v[i]; 00756 } 00757 return *this; 00758 } 00759 //@} 00760 00761 ~uvector_tlate() { 00762 if (this->sz>0) { 00763 if (this->owner==1) { 00764 std::free(this->data); 00765 } 00766 this->sz=0; 00767 } 00768 } 00769 00770 /// \name Memory allocation 00771 //@{ 00772 /** 00773 \brief Allocate memory for size \c n after freeing any memory 00774 presently in use 00775 00776 If \c nsize is zero, this only frees the memory and allocates 00777 no additional memory. 00778 \comment 00779 9/16/09 - I used to set an error here, but that was causing 00780 problems with std::vector<uvector> type objects, and also 00781 we don't want the user to have to make an extra nsize>0 check 00782 every time they call allocate(), so we don't set an error here. 00783 \endcomment 00784 */ 00785 int allocate(size_t nsize) { 00786 if (this->sz>0) free(); 00787 00788 if (nsize>0) { 00789 this->data=(data_t *)malloc(nsize*sizeof(data_t)); 00790 if (this->data) { 00791 this->sz=nsize; 00792 this->owner=1; 00793 } else { 00794 O2SCL_ERR_RET("No memory for data in uvector_tlate::allocate()", 00795 gsl_enomem); 00796 } 00797 } 00798 return 0; 00799 } 00800 00801 /** 00802 \brief Free the memory 00803 00804 This function will safely do nothing if used without first 00805 allocating memory or if called multiple times in succession. 00806 */ 00807 int free() { 00808 if (this->sz>0) { 00809 if (this->owner==1) { 00810 std::free(this->data); 00811 } 00812 this->sz=0; 00813 } 00814 return 0; 00815 } 00816 //@} 00817 00818 /// \name Other methods 00819 //@{ 00820 /// Erase an element from the array. 00821 int erase(size_t ix) { 00822 00823 // Only proceed if the user gave an element inside the array 00824 if (this->sz>ix) { 00825 00826 // Decrement the size 00827 this->sz--; 00828 00829 // Allocate new space 00830 data_t *newdat=(data_t *)(malloc(this->sz*sizeof(data_t))); 00831 00832 // Copy into the new space 00833 for(size_t i=0;i<this->sz;i++) { 00834 if (i<ix) newdat[i]=this->data[i]; 00835 else newdat[i]=this->data[i+1]; 00836 } 00837 00838 // Free the old space and reset the pointer 00839 std::free(this->data); 00840 this->data=newdat; 00841 00842 } else { 00843 O2SCL_ERR_RET("Cannot erase() beyond end of uvector_tlate.", 00844 gsl_einval); 00845 } 00846 00847 return 0; 00848 } 00849 //@} 00850 00851 /** 00852 \brief Sort the vector and ensure all elements are unique by 00853 removing duplicates 00854 */ 00855 int sort_unique() { 00856 o2scl::vector_sort<uvector_tlate<data_t>,data_t >(this->sz,*this); 00857 for(size_t i=1;i<this->sz;i++) { 00858 if ((*this)[i]==(*this)[i-1]) { 00859 int ret=erase(i-1); 00860 if (ret!=0) { 00861 O2SCL_ERR_RET("Erase failed in uvector_tlate::sort_unique().", 00862 gsl_esanity); 00863 } 00864 i--; 00865 } 00866 } 00867 return 0; 00868 } 00869 //@} 00870 00871 }; 00872 00873 /** \brief Create a vector from an array 00874 */ 00875 template<class data_t> class uvector_array_tlate : 00876 public uvector_view_tlate<data_t> { 00877 public: 00878 /** \brief Create a vector from \c dat with size \c n */ 00879 uvector_array_tlate(size_t n, data_t *dat) { 00880 if (n>0) { 00881 this->data=dat; 00882 this->sz=n; 00883 this->owner=0; 00884 } 00885 } 00886 }; 00887 00888 /** \brief Create a vector from a subvector of another 00889 */ 00890 template<class data_t> class uvector_subvector_tlate : 00891 public uvector_view_tlate<data_t> { 00892 public: 00893 /** \brief Create a vector from \c orig */ 00894 uvector_subvector_tlate(uvector_view_tlate<data_t> &orig, 00895 size_t offset, size_t n) { 00896 if (offset+n-1<orig.size) { 00897 this->data=orig.data+offset; 00898 this->sz=n; 00899 this->owner=0; 00900 } else { 00901 this->sz=0; 00902 O2SCL_ERR("Subvector failed in uvector_sub_view().",1); 00903 } 00904 } 00905 }; 00906 00907 /** \brief Create a vector from an const array 00908 */ 00909 template<class data_t> class uvector_const_array_tlate : 00910 public uvector_const_view_tlate<data_t> { 00911 public: 00912 /** \brief Create a vector from \c dat with size \c n */ 00913 uvector_const_array_tlate(size_t n, const data_t *dat) { 00914 if (n>0) { 00915 // We have to do an explicit cast here, but we prevent the 00916 // user from changing the data. 00917 this->data=(data_t *)dat; 00918 this->sz=n; 00919 this->owner=0; 00920 } 00921 } 00922 00923 ~uvector_const_array_tlate() {}; 00924 00925 }; 00926 00927 /** \brief Create a const vector from a subvector of another vector 00928 */ 00929 template<class data_t> class uvector_const_subvector_tlate : 00930 public uvector_const_view_tlate<data_t> { 00931 public: 00932 /** \brief Create a vector from \c orig 00933 */ 00934 uvector_const_subvector_tlate 00935 (const uvector_view_tlate<data_t> &orig, 00936 size_t offset, size_t n) { 00937 if (offset+n-1<orig.sz) { 00938 this->data=orig.data+offset; 00939 this->sz=n; 00940 this->owner=0; 00941 } else { 00942 this->sz=0; 00943 O2SCL_ERR("Subvector failed in uvector_subvector().",1); 00944 } 00945 } 00946 00947 }; 00948 00949 /// uvector typedef 00950 typedef uvector_tlate<double> uvector; 00951 /// uvector_view typedef 00952 typedef uvector_view_tlate<double> uvector_view; 00953 /// uvector_base typedef 00954 typedef uvector_base_tlate<double> uvector_base; 00955 /// uvector_const_view typedef 00956 typedef uvector_const_view_tlate<double> uvector_const_view; 00957 /// uvector_array typedef 00958 typedef uvector_array_tlate<double> uvector_array; 00959 /// uvector_subvector typedef 00960 typedef uvector_subvector_tlate<double> uvector_subvector; 00961 /// uvector_const_array typedef 00962 typedef uvector_const_array_tlate<double> uvector_const_array; 00963 /// uvector_const_subvector typedef 00964 typedef uvector_const_subvector_tlate<double> uvector_const_subvector; 00965 00966 /// uvector_int typedef 00967 typedef uvector_tlate<int> uvector_int; 00968 /// uvector_int_view typedef 00969 typedef uvector_view_tlate<int> uvector_int_view; 00970 /// uvector_int_array typedef 00971 typedef uvector_array_tlate<int> uvector_int_array; 00972 /// uvector_int_subvector typedef 00973 typedef uvector_subvector_tlate<int> uvector_int_subvector; 00974 /// uvector_int_const_array typedef 00975 typedef uvector_const_array_tlate<int> uvector_int_const_array; 00976 /// uvector_int_const_subvector typedef 00977 typedef uvector_const_subvector_tlate<int> uvector_int_const_subvector; 00978 00979 /** 00980 \brief A operator for naive vector output 00981 00982 This outputs all of the vector elements. All of these are 00983 separated by one space character, though no trailing space or \c 00984 endl is sent to the output. If the vector is empty, nothing 00985 is done. 00986 */ 00987 template<class data_t> 00988 std::ostream &operator<< 00989 (std::ostream &os, 00990 const uvector_const_view_tlate<data_t> &v) { 00991 if (v.size()>0) { 00992 for(size_t i=0;i<v.size()-1;i++) { 00993 os << v[i] << ' '; 00994 } 00995 os << v[v.size()-1]; 00996 } 00997 return os; 00998 } 00999 01000 /** \brief A simple class to provide an \c allocate() function 01001 for \ref uvector 01002 */ 01003 class uvector_alloc { 01004 public: 01005 /// Allocate \c v for \c i elements 01006 void allocate(uvector &o, size_t i) { o.allocate(i); } 01007 /// Free memory 01008 void free(uvector &o) { o.free(); } 01009 }; 01010 01011 /** \brief A simple class to provide an \c allocate() function 01012 for \ref uvector_int 01013 */ 01014 class uvector_int_alloc { 01015 public: 01016 /// Allocate \c v for \c i elements 01017 void allocate(uvector_int &o, size_t i) { o.allocate(i); } 01018 /// Free memory 01019 void free(uvector_int &o) { o.free(); } 01020 }; 01021 01022 /** \brief A vector with unit-stride where the memory allocation is 01023 performed in the constructor 01024 */ 01025 #ifdef DOXYGENP 01026 template<size_t N=0> class ufvector : 01027 public uvector_tlate<data_t> 01028 #else 01029 template<size_t N=0> class ufvector : 01030 public uvector_tlate<double> 01031 #endif 01032 { 01033 public: 01034 ufvector() : uvector_tlate<double>(N) { 01035 } 01036 }; 01037 01038 #ifndef DOXYGENP 01039 } 01040 #endif 01041 01042 #endif 01043
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