![]() |
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_OVECTOR_TLATE_H 00024 #define O2SCL_OVECTOR_TLATE_H 00025 00026 /** \file ovector_tlate.h 00027 \brief File for definitions of vectors 00028 00029 \future Clean up maybe by moving, for example, ovector reverse 00030 classes to a different header file 00031 \future Define ovector_uint classes? 00032 */ 00033 00034 #include <iostream> 00035 #include <cstdlib> 00036 #include <cmath> 00037 #include <string> 00038 #include <fstream> 00039 #include <sstream> 00040 #include <vector> 00041 00042 #include <gsl/gsl_vector.h> 00043 #include <gsl/gsl_sys.h> 00044 00045 #include <o2scl/err_hnd.h> 00046 #include <o2scl/string_conv.h> 00047 #include <o2scl/uvector_tlate.h> 00048 #include <o2scl/array.h> 00049 #include <o2scl/vector.h> 00050 00051 #ifndef DOXYGENP 00052 namespace o2scl { 00053 #endif 00054 00055 /** \brief Norm object for gsl vectors 00056 00057 This object is principally for use inside the ovector templates 00058 e.g.. \ref ovector_tlate . For most applications, this object 00059 need not be instantiated directly by the end-user. 00060 00061 For an empty vector, this function returns zero and does not 00062 call the error handler. 00063 */ 00064 class gsl_vector_norm : public gsl_vector { 00065 00066 public: 00067 00068 /// Compute the norm of a gsl_vector 00069 double norm() const { 00070 00071 double scale = 0.0; 00072 double ssq = 1.0; 00073 00074 if (this->size <= 0) { 00075 return 0.0; 00076 } else if (this->size == 1) { 00077 return fabs((this->data)[0]); 00078 } 00079 00080 for (size_t i = 0; i < this->size; i++) { 00081 const double x = (this->data)[i*this->stride]; 00082 00083 if (x != 0.0) { 00084 const double ax = fabs(x); 00085 00086 if (scale < ax) { 00087 ssq = 1.0 + ssq * (scale / ax) * (scale / ax); 00088 scale = ax; 00089 } else { 00090 ssq += (ax / scale) * (ax / scale); 00091 } 00092 } 00093 00094 } 00095 00096 return scale * std::sqrt(ssq); 00097 } 00098 }; 00099 00100 /* Forward declaration of ovector_base_tlate (This is used to allow 00101 the iterator to friend ovector_base; undocumented) 00102 */ 00103 template<class data_t, class vparent_t, class block_t> 00104 class ovector_base_tlate; 00105 00106 /** \brief A const vector view with finite stride 00107 */ 00108 template<class data_t, class vparent_t, class block_t> 00109 class ovector_const_view_tlate : 00110 public vparent_t { 00111 00112 public: 00113 00114 // Forward declaration of iterator class (undocumented) 00115 class iterator; 00116 00117 /** \brief A const iterator for ovectors 00118 00119 \note Experimental. 00120 00121 \todo Default constructor and iterator typedefs 00122 */ 00123 class const_iterator { 00124 00125 protected: 00126 00127 /// Pointer to current 00128 data_t *dp; 00129 00130 /// Stride 00131 size_t stride; 00132 00133 /// Internally create an iterator directly from a pointer 00134 const_iterator(data_t *p, size_t s) { 00135 dp=p; 00136 stride=s; 00137 } 00138 00139 /// Grant access to ovector classes for begin() and end() functions 00140 friend class ovector_const_view_tlate<data_t,vparent_t,block_t>; 00141 00142 /// Grant access to ovector classes for begin() and end() functions 00143 friend class ovector_base_tlate<data_t,vparent_t,block_t>; 00144 00145 public: 00146 /// Copy-constructor for a const iterator 00147 const_iterator(const iterator &it) { 00148 dp=it.dp; 00149 stride=it.stride; 00150 } 00151 00152 /// Equality 00153 bool operator==(const const_iterator &it) const { 00154 return (dp==it.dp); 00155 } 00156 00157 /// Inequality 00158 bool operator!=(const const_iterator &it) const { 00159 return (dp!=it.dp); 00160 } 00161 00162 /// Inequality 00163 bool operator!=(const iterator &it) const { 00164 return (dp!=it.dp); 00165 } 00166 00167 /// Less than 00168 bool operator<(const const_iterator &it) const { 00169 return (dp<it.dp); 00170 } 00171 00172 /// Greater than 00173 bool operator>(const const_iterator &it) const { 00174 return (dp>it.dp); 00175 } 00176 00177 /// Prefix increment 00178 const_iterator operator++() { 00179 dp+=stride; 00180 return *this; 00181 } 00182 00183 /// Prefix decrement 00184 const_iterator operator--() { 00185 dp-=stride; 00186 return *this; 00187 } 00188 00189 /// Postfix increment 00190 const_iterator operator++(int) { 00191 dp+=stride; 00192 return *this; 00193 } 00194 00195 /// Postfix decrement 00196 const_iterator operator--(int) { 00197 dp-=stride; 00198 return *this; 00199 } 00200 00201 /// Dereference - return the corresponding vector element 00202 const data_t operator*() const { 00203 return *dp; 00204 } 00205 00206 /// Move forward 00207 const_iterator operator+=(size_t n) { 00208 dp+=n*stride; 00209 return *this; 00210 } 00211 00212 /// Move backwards 00213 const_iterator operator-=(size_t n) { 00214 dp-=n*stride; 00215 return *this; 00216 } 00217 }; 00218 00219 /** \brief An iterator for ovectors 00220 00221 \note Experimental. 00222 */ 00223 class iterator : public const_iterator { 00224 00225 protected: 00226 00227 /// Internally create an iterator directly from a pointer 00228 iterator(data_t *p, size_t s) : const_iterator(p,s) { 00229 } 00230 00231 /// Grant access to ovector classes for begin() and end() functions 00232 friend class ovector_const_view_tlate<data_t,vparent_t,block_t>; 00233 00234 /// Grant access to ovector classes for begin() and end() functions 00235 friend class ovector_base_tlate<data_t,vparent_t,block_t>; 00236 00237 public: 00238 00239 /// Copy constructor 00240 iterator(const const_iterator &cit) { 00241 this->dp=cit.dp; 00242 this->stride=cit.stride; 00243 } 00244 00245 /// Dereference - return the corresponding vector element 00246 const data_t operator*() const { 00247 return *(this->dp); 00248 } 00249 00250 /// Dereference - return the corresponding vector element 00251 data_t operator*() { 00252 return *(this->dp); 00253 } 00254 }; 00255 00256 /// An iterator for the beginning of the vector 00257 const_iterator begin() const { 00258 return const_iterator(vparent_t::data,vparent_t::stride); 00259 } 00260 00261 /// An iterator for the end of the vector 00262 const_iterator end() const { 00263 return const_iterator(vparent_t::data+vparent_t::size*vparent_t::stride, 00264 vparent_t::stride); 00265 } 00266 00267 /// \name Copy constructors 00268 //@{ 00269 /// Shallow copy constructor - create a new view of the same vector 00270 ovector_const_view_tlate(const ovector_const_view_tlate &v) { 00271 vparent_t::block=0; 00272 vparent_t::data=v.data; 00273 vparent_t::size=v.size(); 00274 vparent_t::stride=v.stride(); 00275 vparent_t::owner=0; 00276 } 00277 00278 /// Shallow copy constructor - create a new view of the same vector 00279 ovector_const_view_tlate& operator=(const ovector_const_view_tlate &v) { 00280 vparent_t::block=0; 00281 vparent_t::data=v.data; 00282 vparent_t::size=v.size(); 00283 vparent_t::stride=v.stride(); 00284 vparent_t::owner=0; 00285 00286 return *this; 00287 } 00288 00289 /** \brief Shallow copy constructor - view a unit-stride vector 00290 */ 00291 ovector_const_view_tlate(const uvector_const_view_tlate<data_t> &v) { 00292 vparent_t::block=0; 00293 vparent_t::data=v.data; 00294 vparent_t::size=v.size(); 00295 vparent_t::stride=1; 00296 vparent_t::owner=0; 00297 } 00298 00299 /// Shallow copy constructor - view a unit-stride vector 00300 ovector_const_view_tlate& operator= 00301 (const uvector_const_view_tlate<data_t> &v) { 00302 vparent_t::block=0; 00303 vparent_t::data=v.data; 00304 vparent_t::size=v.size(); 00305 vparent_t::stride=1; 00306 vparent_t::owner=0; 00307 00308 return *this; 00309 } 00310 //@} 00311 00312 ~ovector_const_view_tlate() {}; 00313 00314 /// \name Get methods 00315 //@{ 00316 /** \brief Array-like indexing (with optional range-checking) 00317 */ 00318 const data_t &operator[](size_t i) const { 00319 #if O2SCL_NO_RANGE_CHECK 00320 #else 00321 if (i>=vparent_t::size) { 00322 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00323 +" in ovector_const_view_tlate::operator[]. Size: "+ 00324 itos(vparent_t::size)+ 00325 " (index should be less than size).").c_str(),gsl_eindex); 00326 return vparent_t::data[0]; 00327 } 00328 #endif 00329 return vparent_t::data[i*vparent_t::stride]; 00330 } 00331 00332 /** \brief Array-like indexing (with optional range-checking) 00333 */ 00334 const data_t &operator()(size_t i) const { 00335 #if O2SCL_NO_RANGE_CHECK 00336 #else 00337 if (i>=vparent_t::size) { 00338 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00339 +" in ovector_const_view_tlate::operator(). Size: "+ 00340 itos(vparent_t::size)+ 00341 " (index should be less than size).").c_str(),gsl_eindex); 00342 return vparent_t::data[0]; 00343 } 00344 #endif 00345 return vparent_t::data[i*vparent_t::stride]; 00346 } 00347 00348 /** \brief Get (with optional range-checking) */ 00349 data_t get(size_t i) const { 00350 #if O2SCL_NO_RANGE_CHECK 00351 #else 00352 if (i>=vparent_t::size) { 00353 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00354 +" in ovector_const_view_tlate::get(). Size: "+ 00355 itos(vparent_t::size)+ 00356 " (index should be less than size).").c_str(),gsl_eindex); 00357 return vparent_t::data[0]; 00358 } 00359 #endif 00360 return vparent_t::data[i*vparent_t::stride]; 00361 } 00362 00363 /** \brief Get pointer (with optional range-checking) */ 00364 const data_t *get_const_ptr(size_t i) const { 00365 #if O2SCL_NO_RANGE_CHECK 00366 #else 00367 if (i>=vparent_t::size) { 00368 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00369 +" in ovector_const_view_tlate::get_const_ptr(). Size: "+ 00370 itos(vparent_t::size)+ 00371 " (index should be less than size).").c_str(),gsl_eindex); 00372 return vparent_t::data; 00373 } 00374 #endif 00375 return (const data_t *)(vparent_t::data+i*vparent_t::stride); 00376 } 00377 00378 /** \brief Method to return vector size 00379 00380 If no memory has been allocated, this will quietly 00381 return zero. 00382 */ 00383 size_t size() const { 00384 return vparent_t::size; 00385 } 00386 00387 /** \brief Method to return capacity 00388 00389 Analogous to <tt>std::vector<>.capacity()</tt>. 00390 */ 00391 size_t capacity() const { 00392 if (vparent_t::block) return vparent_t::block->size; 00393 return 0; 00394 } 00395 00396 /** \brief Method to return vector stride 00397 00398 If no memory has been allocated, this will quietly return 00399 zero. 00400 */ 00401 size_t stride() const { 00402 return vparent_t::stride; 00403 } 00404 //@} 00405 00406 /// \name Other methods 00407 //@{ 00408 /** \brief Return true if this object owns the data it refers to 00409 00410 This can be used to determine if an object is a "vector_view", 00411 or a "vector". If is_owner() is true, then it is an \ref 00412 ovector_tlate object. 00413 00414 If any \o2 class creates a \ref ovector_tlate object in which 00415 \ref is_owner() returns false, then it is a bug and should be 00416 reported. 00417 */ 00418 bool is_owner() const { 00419 if (vparent_t::owner==1) return true; 00420 return false; 00421 } 00422 00423 /** \brief Exhaustively look through the vector for a 00424 particular value and return the closest match 00425 00426 This can only fail if the vector is empty or if \em all of the 00427 entries in the vector are not finite. In these cases the 00428 function calls the error handler and returns 0. 00429 00430 If more than one entry is the same distance from <tt>x0</tt>, 00431 this function returns the entry with smallest index. 00432 */ 00433 size_t lookup(const data_t x0) const { 00434 if (vparent_t::size==0) { 00435 O2SCL_ERR("Empty vector ovector_const_view_tlate::lookup().", 00436 gsl_einval); 00437 return 0; 00438 } 00439 const ovector_const_view_tlate<data_t,vparent_t,block_t> *a=this; 00440 size_t row=0, i=0, nvar=size(); 00441 while(!gsl_finite((*a)[i]) && i<nvar-1) i++; 00442 if (i==nvar-1) { 00443 O2SCL_ERR2("Entire array not finite in ", 00444 "ovector_const_view_tlate::lookup()",gsl_einval); 00445 return 0; 00446 } 00447 data_t best=(*a)[i], bdiff=fabs((*a)[i]-x0); 00448 for(;i<nvar;i++) { 00449 if (gsl_finite((*a)[i]) && fabs((*a)[i]-x0)<bdiff) { 00450 row=i; 00451 best=(*a)[i]; 00452 bdiff=fabs((*a)[i]-x0); 00453 } 00454 } 00455 return row; 00456 } 00457 00458 /** \brief Find the maximum element 00459 00460 This can only fail if \em all of the entries in the array are 00461 not finite or if the vector is empty, in which case it calls 00462 the error handler and returns 0. 00463 */ 00464 data_t max() const { 00465 data_t maxval=0; 00466 if (vparent_t::size>0) { 00467 bool setb=false; 00468 for(size_t i=0;i<vparent_t::size;i++) { 00469 double v=vparent_t::data[i]; 00470 if (gsl_finite(v)) { 00471 if (setb==false) { 00472 maxval=v; 00473 setb=true; 00474 } else if (v>maxval) { 00475 maxval=v; 00476 } 00477 } 00478 } 00479 if (setb==false) { 00480 O2SCL_ERR("No finite values in ovector_const_view_tlate::max().", 00481 gsl_einval); 00482 return 0.0; 00483 } 00484 } else { 00485 O2SCL_ERR("Empty vector in ovector_const_view_tlate::max().", 00486 gsl_einval); 00487 return 0.0; 00488 } 00489 return maxval; 00490 } 00491 00492 /** \brief Find the location of the maximum element 00493 00494 This can only fail if \em all of the entries in the array are 00495 not finite or if the vector is empty, in which case it calls 00496 the error handler and returns 0. 00497 */ 00498 size_t max_index() const { 00499 00500 if (vparent_t::size>0) { 00501 00502 // These next two variables don't need initialization, but 00503 // we do so here to avoid warnings. These initial values 00504 // are essentially ignored by the code below. 00505 data_t maxval=vparent_t::data[0]; 00506 size_t loc=0; 00507 00508 bool setb=false; 00509 for(size_t i=0;i<vparent_t::size;i++) { 00510 double v=vparent_t::data[i]; 00511 if (gsl_finite(v)) { 00512 if (setb==false) { 00513 maxval=v; 00514 loc=i; 00515 setb=true; 00516 } else if (v>maxval) { 00517 maxval=v; 00518 loc=i; 00519 } 00520 } 00521 } 00522 00523 if (setb==false) { 00524 O2SCL_ERR2("No finite values in ", 00525 "ovector_const_view_tlate::max_index().",gsl_einval); 00526 return 0; 00527 } 00528 00529 return loc; 00530 00531 } 00532 00533 O2SCL_ERR("Empty vector ovector_const_view_tlate::max_index().", 00534 gsl_einval); 00535 return 0; 00536 } 00537 00538 /** \brief Find the minimum element 00539 00540 This can only fail if \em all of the entries in the array are 00541 not finite or if the vector is empty, in which case it calls 00542 the error handler and returns 0. 00543 */ 00544 data_t min() const { 00545 data_t minval=0; 00546 if (vparent_t::size>0) { 00547 bool setb=false; 00548 for(size_t i=0;i<vparent_t::size;i++) { 00549 double v=vparent_t::data[i]; 00550 if (gsl_finite(v)) { 00551 if (setb==false) { 00552 minval=v; 00553 setb=true; 00554 } else if (v<minval) { 00555 minval=v; 00556 } 00557 } 00558 } 00559 if (setb==false) { 00560 O2SCL_ERR("No finite values in ovector_const_view_tlate::min().", 00561 gsl_einval); 00562 return 0.0; 00563 } 00564 } else { 00565 O2SCL_ERR("Empty vector ovector_const_view_tlate::min().", 00566 gsl_einval); 00567 return 0.0; 00568 } 00569 return minval; 00570 } 00571 00572 /** \brief Find the location of the minimum element 00573 00574 This can only fail if \em all of the entries in the array are 00575 not finite or if the vector is empty, in which case it calls 00576 the error handler and returns 0. 00577 */ 00578 size_t min_index() const { 00579 00580 if (vparent_t::size>0) { 00581 00582 // These next two variables don't need initialization, but 00583 // we do so here to avoid warnings. These initial values 00584 // are essentially ignored by the code below. 00585 data_t maxval=vparent_t::data[0]; 00586 size_t loc=0; 00587 00588 bool setb=false; 00589 for(size_t i=0;i<vparent_t::size;i++) { 00590 double v=vparent_t::data[i]; 00591 if (gsl_finite(v)) { 00592 if (setb==false) { 00593 maxval=v; 00594 loc=i; 00595 setb=true; 00596 } else if (v<maxval) { 00597 maxval=v; 00598 loc=i; 00599 } 00600 } 00601 } 00602 00603 if (setb==false) { 00604 O2SCL_ERR2("No finite values in ", 00605 "ovector_const_view_tlate::min_index().",gsl_einval); 00606 return 0; 00607 } 00608 00609 return loc; 00610 } 00611 00612 O2SCL_ERR("Empty vector ovector_const_view_tlate::min_index().", 00613 gsl_einval); 00614 return 0; 00615 } 00616 //@} 00617 00618 00619 00620 #ifndef DOXYGEN_INTERNAL 00621 00622 protected: 00623 00624 /** \brief Empty constructor provided for use by 00625 ovector_view_tlate(const ovector_view_tlate &v) 00626 */ 00627 ovector_const_view_tlate() {}; 00628 00629 #endif 00630 00631 }; 00632 00633 /** \brief A base class for ovector and ovector_view 00634 00635 This class provides a base class for ovector and ovector_view, 00636 mostly useful for creating function arguments which accept 00637 either ovector or ovector_view. 00638 */ 00639 template<class data_t, class vparent_t, class block_t> 00640 class ovector_base_tlate : 00641 public ovector_const_view_tlate<data_t,vparent_t,block_t> { 00642 00643 public: 00644 00645 /// Desc 00646 typedef typename ovector_const_view_tlate<data_t, 00647 vparent_t,block_t>::const_iterator const_iterator; 00648 /// Desc 00649 typedef typename ovector_const_view_tlate<data_t, 00650 vparent_t,block_t>::iterator iterator; 00651 00652 /// Desc 00653 const_iterator begin() const { 00654 return const_iterator(vparent_t::data,vparent_t::stride); 00655 } 00656 /// Desc 00657 const_iterator end() const { 00658 return const_iterator(vparent_t::data+vparent_t::size*vparent_t::stride, 00659 vparent_t::stride); 00660 } 00661 /// Desc 00662 iterator begin() { 00663 return iterator(vparent_t::data,vparent_t::stride); 00664 } 00665 /// Desc 00666 iterator end() { 00667 return iterator(vparent_t::data+vparent_t::size*vparent_t::stride, 00668 vparent_t::stride); 00669 } 00670 00671 /// \name Copy constructors 00672 //@{ 00673 00674 /// Shallow copy constructor - create a new view of the same vector 00675 ovector_base_tlate(ovector_base_tlate &v) 00676 : ovector_const_view_tlate<data_t,vparent_t,block_t>() { 00677 vparent_t::block=0; 00678 vparent_t::data=v.data; 00679 vparent_t::size=v.size(); 00680 vparent_t::stride=v.stride(); 00681 vparent_t::owner=0; 00682 } 00683 00684 /// Shallow copy constructor - create a new view of the same vector 00685 ovector_base_tlate& operator=(ovector_base_tlate &v) { 00686 vparent_t::block=0; 00687 vparent_t::data=v.data; 00688 vparent_t::size=v.size(); 00689 vparent_t::stride=v.stride(); 00690 vparent_t::owner=0; 00691 00692 return *this; 00693 } 00694 00695 //@} 00696 00697 ~ovector_base_tlate() {}; 00698 00699 /// \name Get and set methods 00700 //@{ 00701 /** \brief Array-like indexing 00702 */ 00703 const data_t &operator[](size_t i) const { 00704 #if O2SCL_NO_RANGE_CHECK 00705 #else 00706 if (i>=vparent_t::size) { 00707 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00708 +" in ovector_base_tlate::operator[]. Size: "+ 00709 itos(vparent_t::size)+ 00710 " (index should be less than size).").c_str(),gsl_eindex); 00711 return vparent_t::data[0]; 00712 } 00713 #endif 00714 return vparent_t::data[i*vparent_t::stride]; 00715 } 00716 00717 /** \brief Array-like indexing with operator() 00718 */ 00719 const data_t &operator()(size_t i) const { 00720 #if O2SCL_NO_RANGE_CHECK 00721 #else 00722 if (i>=vparent_t::size) { 00723 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00724 +" in ovector_base_tlate::operator(). Size: "+ 00725 itos(vparent_t::size)+ 00726 " (index should be less than size).").c_str(),gsl_eindex); 00727 return vparent_t::data[0]; 00728 } 00729 #endif 00730 return vparent_t::data[i*vparent_t::stride]; 00731 } 00732 00733 /** \brief Array-like indexing 00734 */ 00735 data_t &operator[](size_t i) { 00736 #if O2SCL_NO_RANGE_CHECK 00737 #else 00738 if (i>=vparent_t::size) { 00739 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00740 +" in ovector_base_tlate::operator[]. Size: "+ 00741 itos(vparent_t::size)+ 00742 " (index should be less than size).").c_str(),gsl_eindex); 00743 return vparent_t::data[0]; 00744 } 00745 #endif 00746 return vparent_t::data[i*vparent_t::stride]; 00747 } 00748 00749 /** \brief Array-like indexing with operator() 00750 */ 00751 data_t &operator()(size_t i) { 00752 #if O2SCL_NO_RANGE_CHECK 00753 #else 00754 if (i>=vparent_t::size) { 00755 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00756 +" in ovector_base_tlate::operator(). Size: "+ 00757 itos(vparent_t::size)+ 00758 " (index should be less than size).").c_str(),gsl_eindex); 00759 return vparent_t::data[0]; 00760 } 00761 #endif 00762 return vparent_t::data[i*vparent_t::stride]; 00763 } 00764 00765 /** \brief Get pointer (with optional range-checking) */ 00766 data_t *get_ptr(size_t i) { 00767 #if O2SCL_NO_RANGE_CHECK 00768 #else 00769 if (i>=vparent_t::size) { 00770 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00771 +" in ovector_base_tlate::get_ptr(). Size: "+ 00772 itos(vparent_t::size)+ 00773 " (index should be less than size).").c_str(),gsl_eindex); 00774 return vparent_t::data; 00775 } 00776 #endif 00777 return vparent_t::data+i*vparent_t::stride; 00778 } 00779 00780 /** \brief Set (with optional range-checking) */ 00781 int set(size_t i, data_t val) { 00782 #if O2SCL_NO_RANGE_CHECK 00783 #else 00784 if (i>=vparent_t::size) { 00785 O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds" 00786 +" in ovector_base_tlate::set(). Size: "+ 00787 itos(vparent_t::size)+ 00788 " (index should be less than size).").c_str(), 00789 gsl_eindex); 00790 } 00791 #endif 00792 vparent_t::data[i*vparent_t::stride]=val; 00793 return 0; 00794 } 00795 00796 /** \brief Set all of the value to be the value \c val 00797 00798 If the vector is empty, this function does not perform 00799 any assignment and does not call the error handler. 00800 */ 00801 int set_all(data_t val) { 00802 for(size_t i=0;i<vparent_t::size;i++) { 00803 vparent_t::data[i*vparent_t::stride]=val; 00804 } 00805 return 0; 00806 } 00807 //@} 00808 00809 /** \name Arithmetic */ 00810 //@{ 00811 /** \brief operator+= 00812 00813 This operator only operates on elements which are present 00814 in both vectors, i.e. elements which are present in one vector 00815 but missing in the other will be ignored. If one of the 00816 two vectors is empty, this function does nothing and 00817 does not call the error handler. 00818 */ 00819 ovector_base_tlate<data_t,vparent_t,block_t> &operator+= 00820 (const ovector_base_tlate<data_t,vparent_t,block_t> &x) { 00821 size_t lsize=x.size(); 00822 if (lsize>this->size()) lsize=this->size(); 00823 for(size_t i=0;i<lsize;i++) (*this)[i]+=x[i]; 00824 00825 return *this; 00826 } 00827 00828 /** \brief operator-= 00829 00830 This operator only operates on elements which are present 00831 in both vectors, i.e. elements which are present in one vector 00832 but missing in the other will be ignored. If one of the 00833 two vectors is empty, this function does nothing and 00834 does not call the error handler. 00835 */ 00836 ovector_base_tlate<data_t,vparent_t,block_t> &operator-= 00837 (const ovector_base_tlate<data_t,vparent_t,block_t> &x) { 00838 size_t lsize=x.size(); 00839 if (lsize>this->size()) lsize=this->size(); 00840 for(size_t i=0;i<lsize;i++) (*this)[i]-=x[i]; 00841 00842 return *this; 00843 } 00844 00845 /** \brief operator+= 00846 00847 If the vector is empty, this function does not perform 00848 any modifications and does not call the error handler. 00849 */ 00850 ovector_base_tlate<data_t,vparent_t,block_t> &operator+=(const data_t &x) { 00851 for(size_t i=0;i<this->size();i++) (*this)[i]+=x; 00852 return *this; 00853 } 00854 00855 /** \brief operator-= 00856 00857 If the vector is empty, this function does not perform 00858 any modifications and does not call the error handler. 00859 */ 00860 ovector_base_tlate<data_t,vparent_t,block_t> &operator-=(const data_t &x) { 00861 for(size_t i=0;i<this->size();i++) (*this)[i]-=x; 00862 return *this; 00863 } 00864 00865 /** \brief operator*= 00866 00867 If the vector is empty, this function does not perform 00868 any modifications and does not call the error handler. 00869 */ 00870 ovector_base_tlate<data_t,vparent_t,block_t> &operator*= 00871 (const data_t &y) { 00872 for(size_t i=0;i<this->size();i++) (*this)[i]*=y; 00873 00874 return *this; 00875 } 00876 //@} 00877 00878 /// \name Other methods 00879 //@{ 00880 /** \brief Return a gsl vector */ 00881 vparent_t *get_gsl_vector() { return this; }; 00882 00883 /** \brief Return a \c const gsl vector 00884 */ 00885 const vparent_t *get_gsl_vector_const() const { return this; }; 00886 //@} 00887 00888 protected: 00889 00890 /** \brief Empty constructor for use by children 00891 00892 \comment 00893 This is private because I want to prevent the casual end-user 00894 from creating ovector_base objects. End-users should really be 00895 focused on making normal vectors and views. 00896 \endcomment 00897 */ 00898 ovector_base_tlate() {}; 00899 00900 }; 00901 00902 /** \brief A vector view with finite stride 00903 */ 00904 template<class data_t, class vparent_t, class block_t> 00905 class ovector_view_tlate : 00906 public ovector_base_tlate<data_t,vparent_t,block_t> { 00907 00908 public: 00909 00910 /// \name Copy constructors 00911 //@{ 00912 /// Shallow copy constructor - create a new view of the same vector 00913 ovector_view_tlate(const ovector_view_tlate &v) : 00914 ovector_base_tlate<data_t,vparent_t,block_t>() { 00915 vparent_t::block=0; 00916 vparent_t::data=v.data; 00917 vparent_t::size=v.size(); 00918 vparent_t::stride=v.stride(); 00919 vparent_t::owner=0; 00920 } 00921 00922 /// Shallow copy constructor - create a new view of the same vector 00923 ovector_view_tlate& operator= 00924 (const ovector_view_tlate &v) { 00925 vparent_t::block=0; 00926 vparent_t::data=v.data; 00927 vparent_t::size=v.size(); 00928 vparent_t::stride=v.stride(); 00929 vparent_t::owner=0; 00930 00931 return *this; 00932 } 00933 00934 /// Shallow copy constructor for non-views 00935 ovector_view_tlate(ovector_base_tlate<data_t,vparent_t,block_t> &v) : 00936 ovector_base_tlate<data_t,vparent_t,block_t>() { 00937 vparent_t::block=0; 00938 vparent_t::data=v.data; 00939 vparent_t::size=v.size(); 00940 vparent_t::stride=v.stride(); 00941 vparent_t::owner=0; 00942 } 00943 00944 /// Shallow copy constructor for non-views 00945 ovector_view_tlate& operator= 00946 (ovector_base_tlate<data_t,vparent_t,block_t> &v) { 00947 vparent_t::block=0; 00948 vparent_t::data=v.data; 00949 vparent_t::size=v.size(); 00950 vparent_t::stride=v.stride(); 00951 vparent_t::owner=0; 00952 00953 return *this; 00954 } 00955 00956 /// Shallow copy constructor for unit-stride vectors 00957 ovector_view_tlate 00958 (uvector_base_tlate<data_t> &v) { 00959 vparent_t::block=0; 00960 vparent_t::data=v.data; 00961 vparent_t::size=v.size(); 00962 vparent_t::stride=1; 00963 vparent_t::owner=0; 00964 } 00965 00966 /// Shallow copy constructor for unit-stride vectors 00967 ovector_view_tlate& operator= 00968 (uvector_base_tlate<data_t> &v) { 00969 vparent_t::block=0; 00970 vparent_t::data=v.data; 00971 vparent_t::size=v.size(); 00972 vparent_t::stride=1; 00973 vparent_t::owner=0; 00974 00975 return *this; 00976 } 00977 //@} 00978 00979 /** \name Get and set methods 00980 00981 \comment 00982 We have to redefine these here because they are different than 00983 the forms given in ovector_base. 00984 \endcomment 00985 */ 00986 //@{ 00987 /** \brief Array-like indexing 00988 */ 00989 data_t &operator[](size_t i) const { 00990 #if O2SCL_NO_RANGE_CHECK 00991 #else 00992 if (i>=vparent_t::size) { 00993 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00994 +" in ovector_view_tlate::operator[]. Size: "+ 00995 itos(vparent_t::size)+ 00996 " (index should be less than size).").c_str(),gsl_eindex); 00997 return vparent_t::data[0]; 00998 } 00999 #endif 01000 return vparent_t::data[i*vparent_t::stride]; 01001 } 01002 01003 /** \brief Array-like indexing with operator() 01004 */ 01005 data_t &operator()(size_t i) const { 01006 #if O2SCL_NO_RANGE_CHECK 01007 #else 01008 if (i>=vparent_t::size) { 01009 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 01010 +" in ovector_view_tlate::operator(). Size: "+ 01011 itos(vparent_t::size)+ 01012 " (index should be less than size).").c_str(),gsl_eindex); 01013 return vparent_t::data[0]; 01014 } 01015 #endif 01016 return vparent_t::data[i*vparent_t::stride]; 01017 } 01018 01019 01020 /** \brief Get pointer (with optional range-checking) */ 01021 data_t *get_ptr(size_t i) const { 01022 #if O2SCL_NO_RANGE_CHECK 01023 #else 01024 if (i>=vparent_t::size) { 01025 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 01026 +" in ovector_view_tlate::get_ptr(). Size: "+ 01027 itos(vparent_t::size)+ 01028 " (index should be less than size).").c_str(),gsl_eindex); 01029 return vparent_t::data; 01030 } 01031 #endif 01032 return vparent_t::data+i*vparent_t::stride; 01033 } 01034 01035 /** \brief Set (with optional range-checking) */ 01036 int set(size_t i, data_t val) const { 01037 #if O2SCL_NO_RANGE_CHECK 01038 #else 01039 if (i>=vparent_t::size) { 01040 O2SCL_ERR_RET((((std::string)"Array index ")+itos(i)+" out of bounds" 01041 +" in ovector_view_tlate::set(). Size: "+ 01042 itos(vparent_t::size)+ 01043 " (index should be less than size).").c_str(), 01044 gsl_eindex); 01045 } 01046 #endif 01047 vparent_t::data[i*vparent_t::stride]=val; 01048 return 0; 01049 } 01050 01051 /** \brief Set all of the value to be the value \c val 01052 01053 If the vector is empty, this function does not perform 01054 any assignment and does not call the error handler. 01055 */ 01056 int set_all(double val) const { 01057 for(size_t i=0;i<vparent_t::size;i++) { 01058 vparent_t::data[i*vparent_t::stride]=val; 01059 } 01060 return 0; 01061 } 01062 //@} 01063 01064 #ifndef DOXYGEN_INTERNAL 01065 01066 protected: 01067 01068 /** \brief Empty constructor provided for use by 01069 ovector_view_tlate(const ovector_view_tlate &v) 01070 */ 01071 ovector_view_tlate() {}; 01072 01073 #endif 01074 01075 }; 01076 01077 /** \brief A vector with finite stride 01078 01079 There are several global binary operators associated with 01080 objects of type \ref uvector_tlate. The are documented in the 01081 "Functions" section of \ref ovector_tlate.h. 01082 01083 <b>Design notes</b> 01084 01085 At present, the owner variable can be used to distinguish 01086 between ovectors and ovector_views: for views, owner is always 01087 zero, but for normal ovectors, owner is 1 (even for empty 01088 vectors). 01089 01090 The reserve(), pop_back(), and push_back() methods require the 01091 ability to have empty vectors which still have memory allocated 01092 for them, so the proper test for whether or not memory is 01093 allocated is to test whether or not 'block' is zero. This means 01094 we should never have a case where the block is non-zero (i.e. 01095 there is memory allocated there) but the size of the block is 01096 zero. This is the test used in the destructor and the free() 01097 method. The free method also sets block to zero accordingly. 01098 01099 */ 01100 template<class data_t, class vparent_t, class block_t> 01101 class ovector_tlate : 01102 public ovector_base_tlate<data_t,vparent_t,block_t> { 01103 01104 #ifndef DOXYGEN_INTERNAL 01105 01106 protected: 01107 01108 /// An internal sanity check to ensure correctness 01109 void intl_sanity_check(size_t ix) { 01110 if (vparent_t::owner==0 || (vparent_t::block==0 && vparent_t::size>0) || 01111 (vparent_t::block!=0 && (vparent_t::block->size==0 || 01112 vparent_t::size>vparent_t::block->size))) { 01113 std::cout << "owner: " << vparent_t::owner 01114 << " block: " << vparent_t::block 01115 << " size: " << vparent_t::size 01116 << " bsize: " << vparent_t::block->size << " " 01117 << ix << std::endl; 01118 O2SCL_ERR("Internal error in ovector_tlate.",gsl_esanity); 01119 } 01120 return; 01121 } 01122 01123 /** \brief An internal allocate function 01124 01125 \note This function does nothing if \c nsize is zero. Also, 01126 this does not free any already allocated memory first (unlike 01127 the user-interface version allocate()). 01128 */ 01129 int intl_allocate(size_t nsize) { 01130 01131 #if O2SCL_NO_RANGE_CHECK 01132 #else 01133 intl_sanity_check(0); 01134 #endif 01135 01136 if (nsize>0) { 01137 vparent_t::block=(block_t *)malloc(sizeof(block_t)); 01138 if (vparent_t::block) { 01139 vparent_t::block->data=(data_t *)malloc(nsize*sizeof(data_t)); 01140 if (vparent_t::block->data) { 01141 vparent_t::block->size=nsize; 01142 vparent_t::data=vparent_t::block->data; 01143 vparent_t::size=nsize; 01144 vparent_t::stride=1; 01145 vparent_t::owner=1; 01146 } else { 01147 std::free(vparent_t::block); 01148 // If the block allocation failed, make sure to 01149 // return block to zero so that destructors know 01150 // that memory has not been allocated 01151 vparent_t::block=0; 01152 O2SCL_ERR_RET("No memory for data in ovector::allocate()", 01153 gsl_enomem); 01154 } 01155 } else { 01156 O2SCL_ERR_RET("No memory for block in ovector::allocate()", 01157 gsl_enomem); 01158 } 01159 } 01160 01161 #if O2SCL_NO_RANGE_CHECK 01162 #else 01163 intl_sanity_check(1); 01164 #endif 01165 01166 return 0; 01167 } 01168 01169 /// The internal free function 01170 int intl_free() { 01171 01172 #if O2SCL_NO_RANGE_CHECK 01173 #else 01174 intl_sanity_check(2); 01175 #endif 01176 01177 if (vparent_t::block!=0 && vparent_t::block->size>0) { 01178 std::free(vparent_t::block->data); 01179 vparent_t::block->data=0; 01180 std::free(vparent_t::block); 01181 vparent_t::block=0; 01182 } 01183 vparent_t::size=0; 01184 vparent_t::stride=0; 01185 return 0; 01186 } 01187 01188 01189 /** \brief An internal init() function 01190 01191 This function calls intl_allocate() first, and then copies the 01192 data from the vector \c v. 01193 */ 01194 template<class alt_vec_t> int intl_init(size_t n, alt_vec_t &v) { 01195 01196 int ret=intl_allocate(n); 01197 if (ret==0) { 01198 for(size_t i=0;i<n;i++) { 01199 vparent_t::data[i*vparent_t::stride]=v[i]; 01200 } 01201 } 01202 01203 return ret; 01204 } 01205 01206 /// An internal assignment function for <tt>operator=()</tt> 01207 template<class alt_vec_t> ovector_tlate &intl_assign 01208 (size_t n, alt_vec_t &v) { 01209 01210 #if O2SCL_NO_RANGE_CHECK 01211 #else 01212 intl_sanity_check(3); 01213 #endif 01214 01215 // Check for self-assignment 01216 if (this==&v) return *this; 01217 01218 allocate(n); 01219 for(size_t i=0;i<n;i++) { 01220 vparent_t::data[i*vparent_t::stride]=v[i]; 01221 } 01222 01223 return *this; 01224 } 01225 01226 #endif 01227 01228 public: 01229 01230 /// \name Standard constructor 01231 //@{ 01232 /** \brief Create an ovector of size \c n with owner as 'true' */ 01233 ovector_tlate(size_t n=0) { 01234 01235 // Start with an empty vector (Avoid uninitialized variable errors.) 01236 vparent_t::data=0; 01237 vparent_t::size=0; 01238 vparent_t::stride=0; 01239 vparent_t::block=0; 01240 vparent_t::owner=1; 01241 01242 if (n>0) intl_allocate(n); 01243 01244 } 01245 //@} 01246 01247 /// \name Copy constructors 01248 //@{ 01249 /** \brief Deep copy constructor 01250 01251 \comment 01252 Note I think this has to be separate from the constructor 01253 for ovector_base_tlate objects otherwise the compiler will 01254 synthesize its own. 01255 \endcomment 01256 */ 01257 ovector_tlate(const ovector_tlate &v) : 01258 ovector_base_tlate<data_t,vparent_t,block_t>() { 01259 01260 // Start with an empty vector (Avoid uninitialized variable errors.) 01261 vparent_t::data=0; 01262 vparent_t::size=0; 01263 vparent_t::stride=0; 01264 vparent_t::block=0; 01265 vparent_t::owner=1; 01266 01267 intl_init(v.size(),v); 01268 01269 } 01270 01271 /// Deep copy constructor for generic vectors 01272 template<class alt_vec_t> 01273 ovector_tlate(size_t nv, alt_vec_t &v) : 01274 ovector_base_tlate<data_t,vparent_t,block_t>() { 01275 01276 // Start with an empty vector (Avoid uninitialized variable errors.) 01277 vparent_t::data=0; 01278 vparent_t::size=0; 01279 vparent_t::stride=0; 01280 vparent_t::block=0; 01281 vparent_t::owner=1; 01282 01283 intl_init(nv,v); 01284 01285 } 01286 01287 /// Deep copy constructor for other related vectors 01288 ovector_tlate(const ovector_const_view_tlate<data_t,vparent_t,block_t> &v) : 01289 ovector_base_tlate<data_t,vparent_t,block_t>() { 01290 01291 // Start with an empty vector (Avoid uninitialized variable errors.) 01292 vparent_t::data=0; 01293 vparent_t::size=0; 01294 vparent_t::stride=0; 01295 vparent_t::block=0; 01296 vparent_t::owner=1; 01297 01298 intl_init(v.size(),v); 01299 01300 } 01301 01302 /** \brief Deep copy constructor, if owner is true, allocate 01303 space and make a new copy, otherwise, just copy into the 01304 view 01305 */ 01306 ovector_tlate& operator=(const ovector_tlate &v) { 01307 01308 return intl_assign(v.size(),v); 01309 } 01310 01311 /** \brief Deep copy constructor, if owner is true, allocate 01312 space and make a new copy, otherwise, just copy into the 01313 view 01314 */ 01315 ovector_tlate& operator= 01316 (const ovector_const_view_tlate<data_t,vparent_t,block_t> &v) { 01317 01318 return intl_assign(v.size(),v); 01319 } 01320 01321 /** \brief Deep copy constructor, if owner is true, allocate 01322 space and make a new copy, otherwise, just copy into the 01323 view 01324 */ 01325 ovector_tlate& operator= 01326 (const uvector_const_view_tlate<data_t> &v) { 01327 01328 return intl_assign(v.size(),v); 01329 } 01330 //@} 01331 01332 ~ovector_tlate() { 01333 01334 #if O2SCL_NO_RANGE_CHECK 01335 #else 01336 intl_sanity_check(4); 01337 #endif 01338 01339 if (vparent_t::owner==1) { 01340 if (vparent_t::block!=0 && vparent_t::block->size>0) { 01341 std::free(vparent_t::block->data); 01342 } 01343 if (vparent_t::block!=0) { 01344 std::free(vparent_t::block); 01345 } 01346 } 01347 01348 } 01349 01350 /// \name Memory allocation 01351 //@{ 01352 /** \brief Allocate memory for size \c n after freeing any memory 01353 currently in use 01354 01355 Note that this automatically deallocates any previously 01356 allocated memory before attempting to allocate more. If this 01357 allocation fails (i.e. because we ran out of memory) then the 01358 original vector will still have been deallocated. 01359 */ 01360 int allocate(size_t nsize) { 01361 01362 intl_free(); 01363 intl_allocate(nsize); 01364 01365 return 0; 01366 } 01367 01368 /** \brief Free the memory 01369 01370 This function will safely do nothing if used without first 01371 allocating memory or if called multiple times in succession. 01372 */ 01373 int free() { 01374 return intl_free(); 01375 } 01376 //@} 01377 01378 /// \name Stack-like operations 01379 //@{ 01380 01381 /// Add a value to the end of the vector 01382 int push_back(data_t val) { 01383 01384 #if O2SCL_NO_RANGE_CHECK 01385 #else 01386 intl_sanity_check(6); 01387 #endif 01388 01389 if (vparent_t::block==0) { 01390 01391 // Empty, so make a 1-element vector 01392 allocate(1); 01393 vparent_t::data[0]=val; 01394 01395 } else if (vparent_t::block->size==vparent_t::size) { 01396 01397 // Allocate new memory in vparent_t::block 01398 vparent_t::block->data=(data_t *)malloc 01399 (2*vparent_t::block->size*sizeof(data_t)); 01400 vparent_t::block->size*=2; 01401 01402 // Copy the data to the new memory 01403 for(size_t i=0;i<vparent_t::size;i++) { 01404 vparent_t::block->data[i]=vparent_t::data[i]; 01405 } 01406 01407 // Delete the old memory 01408 std::free(vparent_t::data); 01409 01410 // Reset data to the new memory 01411 vparent_t::data=vparent_t::block->data; 01412 01413 // Add the new value to the end of the array and 01414 // increment size 01415 vparent_t::block->data[vparent_t::size]=val; 01416 vparent_t::size++; 01417 01418 } else { 01419 01420 // Add the new value to the end of the array and 01421 // increment size 01422 vparent_t::block->data[vparent_t::size]=val; 01423 vparent_t::size++; 01424 01425 } 01426 01427 #if O2SCL_NO_RANGE_CHECK 01428 #else 01429 intl_sanity_check(7); 01430 #endif 01431 01432 return 0; 01433 } 01434 01435 /** \brief Reserve memory by increasing capacity 01436 01437 Increase the maximum capacity of the vector so that calls 01438 to push_back() do not need to automatically increase the 01439 capacity. 01440 01441 If the argument \c cap is smaller than the present vector size 01442 given by \ref size(), then this function does nothing and the 01443 error handler is not called. 01444 */ 01445 int reserve(size_t cap) { 01446 01447 #if O2SCL_NO_RANGE_CHECK 01448 #else 01449 intl_sanity_check(8); 01450 #endif 01451 01452 // Do nothing if we are reserving memory for less than the 01453 // current size 01454 01455 if (cap>vparent_t::size) { 01456 01457 bool initially_empty=false; 01458 01459 // If it's initially_empty, we need to allocate a block 01460 if (!vparent_t::block) { 01461 initially_empty=true; 01462 vparent_t::block=(block_t *)malloc(sizeof(block_t)); 01463 } 01464 01465 // If it's empty, or if the block size is too small, 01466 // reserve space. On the other hand, if the block size 01467 // is already large enough, do nothing. 01468 if (initially_empty || vparent_t::block->size<cap) { 01469 01470 // Allocate new memory in vparent_t::block 01471 vparent_t::block->data=(data_t *)malloc(cap*sizeof(data_t)); 01472 vparent_t::block->size=cap; 01473 01474 // Copy the data to the new memory 01475 for(size_t i=0;i<vparent_t::size;i++) { 01476 vparent_t::block->data[i]=vparent_t::data[i]; 01477 } 01478 01479 // Delete the old memory 01480 if (!initially_empty) { 01481 std::free(vparent_t::data); 01482 } 01483 01484 // Reset data to the new memory 01485 vparent_t::data=vparent_t::block->data; 01486 } 01487 } 01488 01489 #if O2SCL_NO_RANGE_CHECK 01490 #else 01491 intl_sanity_check(9); 01492 #endif 01493 01494 return 0; 01495 } 01496 01497 /** \brief Return the last value and shrink the vector size by one 01498 */ 01499 data_t pop_back() { 01500 01501 #if O2SCL_NO_RANGE_CHECK 01502 #else 01503 intl_sanity_check(10); 01504 #endif 01505 01506 if (vparent_t::size==0) { 01507 O2SCL_ERR("Attempted to pop an empty vector in ovector::pop_back().", 01508 gsl_einval); 01509 return 0.0; 01510 } 01511 01512 // Otherwise, just decrease the size by one and return the last 01513 // element 01514 vparent_t::size--; 01515 01516 #if O2SCL_NO_RANGE_CHECK 01517 #else 01518 intl_sanity_check(11); 01519 #endif 01520 01521 return vparent_t::data[vparent_t::size]; 01522 } 01523 //@} 01524 01525 /// \name Other methods 01526 //@{ 01527 /// Remove element with index \c ix and decrease the vector size by one 01528 int erase(size_t ix) { 01529 01530 #if O2SCL_NO_RANGE_CHECK 01531 #else 01532 intl_sanity_check(12); 01533 #endif 01534 01535 if (ix<vparent_t::size) { 01536 for(size_t i=ix+1;i<vparent_t::size;i++) { 01537 vparent_t::data[i-1]=vparent_t::data[i]; 01538 } 01539 vparent_t::size--; 01540 } else { 01541 O2SCL_ERR_RET("Tried to erase() past end in ovector_tlate::erase().", 01542 gsl_einval); 01543 } 01544 01545 #if O2SCL_NO_RANGE_CHECK 01546 #else 01547 intl_sanity_check(13); 01548 #endif 01549 01550 return 0; 01551 } 01552 01553 /** \brief Sort the vector and ensure all elements are unique by 01554 removing duplicates 01555 */ 01556 int sort_unique() { 01557 01558 #if O2SCL_NO_RANGE_CHECK 01559 #else 01560 intl_sanity_check(14); 01561 #endif 01562 01563 o2scl::vector_sort<ovector_tlate<data_t,vparent_t,block_t>,data_t > 01564 (vparent_t::size,*this); 01565 for(size_t i=1;i<vparent_t::size;i++) { 01566 if ((*this)[i]==(*this)[i-1]) { 01567 int ret=erase(i-1); 01568 if (ret!=0) { 01569 O2SCL_ERR2_RET("Erase failed in ", 01570 "ovector_tlate::sort_unique().",gsl_esanity); 01571 } 01572 i--; 01573 } 01574 } 01575 01576 #if O2SCL_NO_RANGE_CHECK 01577 #else 01578 intl_sanity_check(15); 01579 #endif 01580 01581 return 0; 01582 } 01583 //@} 01584 01585 }; 01586 01587 /** \brief Create a vector from an array 01588 */ 01589 template<class data_t, class vparent_t, class block_t> 01590 class ovector_array_tlate : 01591 public ovector_view_tlate<data_t,vparent_t,block_t> { 01592 01593 public: 01594 01595 /** \brief Create a vector from \c dat with size \c n */ 01596 ovector_array_tlate(size_t n, data_t *dat) { 01597 vparent_t::block=0; 01598 vparent_t::owner=0; 01599 if (n>0) { 01600 vparent_t::data=dat; 01601 vparent_t::size=n; 01602 vparent_t::stride=1; 01603 } else { 01604 vparent_t::data=0; 01605 vparent_t::size=0; 01606 vparent_t::stride=0; 01607 } 01608 } 01609 01610 }; 01611 01612 /** \brief Create a vector from an array with a stride 01613 */ 01614 template<class data_t, class vparent_t, class block_t> 01615 class ovector_array_stride_tlate : 01616 public ovector_view_tlate<data_t,vparent_t,block_t> { 01617 01618 public: 01619 01620 /** \brief Create a vector from \c dat with size \c n and stride \c s 01621 */ 01622 ovector_array_stride_tlate(size_t n, data_t *dat, size_t s) { 01623 vparent_t::block=0; 01624 vparent_t::owner=0; 01625 if (n>0) { 01626 vparent_t::data=dat; 01627 vparent_t::size=n; 01628 vparent_t::stride=s; 01629 } else { 01630 vparent_t::data=0; 01631 vparent_t::size=0; 01632 vparent_t::stride=0; 01633 } 01634 } 01635 01636 }; 01637 01638 /** \brief Create a vector from a subvector of another 01639 01640 The constructor will fail if the original vector is empty, or if 01641 the user requests a subvector which includes elements beyond the 01642 end of the original vector. 01643 */ 01644 template<class data_t, class vparent_t, class block_t> 01645 class ovector_subvector_tlate : 01646 public ovector_view_tlate<data_t,vparent_t,block_t> { 01647 public: 01648 /** \brief Create a vector from \c orig 01649 */ 01650 ovector_subvector_tlate 01651 (ovector_base_tlate<data_t,vparent_t,block_t> &orig, 01652 size_t offset, size_t n) { 01653 if (orig.size()>0 && offset+n<orig.size()+1) { 01654 vparent_t::block=0; 01655 vparent_t::data=orig.data+offset*orig.stride(); 01656 vparent_t::size=n; 01657 vparent_t::stride=orig.stride(); 01658 vparent_t::owner=0; 01659 } else { 01660 std::string err="Failed because vector is of size "+ 01661 itos(orig.size())+" but requested size "+itos(n)+ 01662 " with offset "+itos(offset)+" in ovector_subvector "+ 01663 "constructor."; 01664 O2SCL_ERR(err.c_str(),gsl_efailed); 01665 vparent_t::block=0; 01666 vparent_t::data=0; 01667 vparent_t::size=0; 01668 vparent_t::stride=0; 01669 vparent_t::owner=0; 01670 } 01671 } 01672 }; 01673 01674 /** \brief Create a const vector from an array 01675 01676 The constructor will fail if the size argument 01677 \c n is zero or if the pointer \c dat is 0. 01678 */ 01679 template<class data_t, class vparent_t, class block_t> 01680 class ovector_const_array_tlate : 01681 public ovector_const_view_tlate<data_t,vparent_t,block_t> { 01682 01683 public: 01684 01685 /** \brief Create a vector from \c dat with size \c n */ 01686 ovector_const_array_tlate(size_t n, const data_t *dat) { 01687 if (n>0 && dat!=0) { 01688 vparent_t::block=0; 01689 // We have to do an explicit cast here, but we prevent the 01690 // user from changing the data. 01691 vparent_t::data=(data_t *)dat; 01692 vparent_t::size=n; 01693 vparent_t::stride=1; 01694 vparent_t::owner=0; 01695 } else { 01696 O2SCL_ERR2("Empty array in ovector_const_array_tlate() ", 01697 "constructor.",gsl_efailed); 01698 vparent_t::block=0; 01699 vparent_t::data=0; 01700 vparent_t::size=0; 01701 vparent_t::stride=0; 01702 vparent_t::owner=0; 01703 } 01704 } 01705 01706 ~ovector_const_array_tlate() {}; 01707 01708 }; 01709 01710 /** \brief Create a const vector from an array with a stride 01711 01712 The constructor will fail if the size argument \c n is zero, the 01713 stride \c s is zero, or if the pointer \c dat is 0. 01714 */ 01715 template<class data_t, class vparent_t, class block_t> 01716 class ovector_const_array_stride_tlate : 01717 public ovector_const_view_tlate<data_t,vparent_t,block_t> { 01718 01719 public: 01720 01721 /** \brief Create a vector from \c dat with size \c n */ 01722 ovector_const_array_stride_tlate(size_t n, const data_t *dat, size_t s) { 01723 if (n>0 && s>0 && dat!=0) { 01724 vparent_t::block=0; 01725 // We have to do an explicit cast here, but we prevent the 01726 // user from changing the data. 01727 vparent_t::data=(data_t *)dat; 01728 vparent_t::size=n; 01729 vparent_t::stride=s; 01730 vparent_t::owner=0; 01731 } else { 01732 O2SCL_ERR2("Empty array in ovector_const_array_stride_tlate() ", 01733 "constructor.",gsl_efailed); 01734 vparent_t::block=0; 01735 vparent_t::data=0; 01736 vparent_t::size=0; 01737 vparent_t::stride=0; 01738 vparent_t::owner=0; 01739 } 01740 } 01741 01742 }; 01743 01744 /** \brief Create a const vector from a subvector of another vector 01745 */ 01746 template<class data_t, class vparent_t, class block_t> 01747 class ovector_const_subvector_tlate : 01748 public ovector_const_view_tlate<data_t,vparent_t,block_t> { 01749 public: 01750 /** \brief Create a vector from \c orig 01751 */ 01752 ovector_const_subvector_tlate 01753 (const ovector_const_view_tlate<data_t,vparent_t,block_t> &orig, 01754 size_t offset, size_t n) { 01755 if (offset+n-1<orig.size()) { 01756 vparent_t::block=0; 01757 vparent_t::data=orig.data+offset*orig.stride(); 01758 vparent_t::size=n; 01759 vparent_t::stride=orig.stride(); 01760 vparent_t::owner=0; 01761 } else { 01762 std::string err="Failed because vector is of size "+ 01763 itos(orig.size())+" but requested size "+itos(n)+ 01764 " with offset "+itos(offset)+" in ovector_const_subvector "+ 01765 "constructor."; 01766 O2SCL_ERR(err.c_str(),gsl_efailed); 01767 vparent_t::block=0; 01768 vparent_t::data=0; 01769 vparent_t::size=0; 01770 vparent_t::stride=0; 01771 vparent_t::owner=0; 01772 } 01773 } 01774 01775 }; 01776 01777 /// ovector typedef 01778 typedef ovector_tlate<double,gsl_vector_norm,gsl_block> ovector; 01779 /// ovector_base typedef 01780 typedef ovector_base_tlate<double,gsl_vector_norm,gsl_block> 01781 ovector_base; 01782 /// ovector_view typedef 01783 typedef ovector_view_tlate<double,gsl_vector_norm,gsl_block> 01784 ovector_view; 01785 /// ovector_const_view typedef 01786 typedef ovector_const_view_tlate<double,gsl_vector_norm,gsl_block> 01787 ovector_const_view; 01788 /// ovector_array typedef 01789 typedef ovector_array_tlate<double,gsl_vector_norm,gsl_block> ovector_array; 01790 /// ovector_array_stride typedef 01791 typedef ovector_array_stride_tlate<double,gsl_vector_norm,gsl_block> 01792 ovector_array_stride; 01793 /// ovector_subvector typedef 01794 typedef ovector_subvector_tlate<double,gsl_vector_norm,gsl_block> 01795 ovector_subvector; 01796 /// ovector_const_array typedef 01797 typedef ovector_const_array_tlate<double,gsl_vector_norm,gsl_block> 01798 ovector_const_array; 01799 /// ovector_const_array_stride typedef 01800 typedef ovector_const_array_stride_tlate<double,gsl_vector_norm,gsl_block> 01801 ovector_const_array_stride; 01802 /// ovector_const_subvector typedef 01803 typedef ovector_const_subvector_tlate<double,gsl_vector_norm,gsl_block> 01804 ovector_const_subvector; 01805 01806 /// ovector_int typedef 01807 typedef ovector_tlate<int,gsl_vector_int,gsl_block_int> ovector_int; 01808 /// ovector_int_base typedef 01809 typedef ovector_base_tlate<int,gsl_vector_int,gsl_block_int> 01810 ovector_int_base; 01811 /// ovector_int_view typedef 01812 typedef ovector_view_tlate<int,gsl_vector_int,gsl_block_int> 01813 ovector_int_view; 01814 /// ovector_int_const_base typedef 01815 typedef ovector_const_view_tlate<int,gsl_vector_int,gsl_block_int> 01816 ovector_int_const_view; 01817 /// ovector_int_array typedef 01818 typedef ovector_array_tlate<int,gsl_vector_int,gsl_block_int> 01819 ovector_int_array; 01820 /// ovector_int_array_stride typedef 01821 typedef ovector_array_stride_tlate<int,gsl_vector_int,gsl_block_int> 01822 ovector_int_array_stride; 01823 /// ovector_int_subvector typedef 01824 typedef ovector_subvector_tlate<int,gsl_vector_int,gsl_block_int> 01825 ovector_int_subvector; 01826 /// ovector_int_const_array typedef 01827 typedef ovector_const_array_tlate<int,gsl_vector_int,gsl_block_int> 01828 ovector_int_const_array; 01829 /// ovector_int_const_array_stride typedef 01830 typedef ovector_const_array_stride_tlate<int,gsl_vector_int,gsl_block_int> 01831 ovector_int_const_array_stride; 01832 /// ovector_int_const_subvector typedef 01833 typedef ovector_const_subvector_tlate<int,gsl_vector_int,gsl_block_int> 01834 ovector_int_const_subvector; 01835 01836 /** \brief A operator for naive vector output 01837 01838 This outputs all of the vector elements. All of these are 01839 separated by one space character, though no trailing space or \c 01840 endl is sent to the output. If the vector is empty, nothing 01841 is done. 01842 */ 01843 template<class data_t, class vparent_t, class block_t> 01844 std::ostream &operator<< 01845 (std::ostream &os, 01846 const ovector_const_view_tlate<data_t,vparent_t,block_t> &v) { 01847 if (v.size()>0) { 01848 for(size_t i=0;i<v.size()-1;i++) { 01849 os << v[i] << ' '; 01850 } 01851 os << v[v.size()-1]; 01852 } 01853 return os; 01854 } 01855 01856 /** \brief A simple class to provide an \c allocate() function 01857 for \ref ovector 01858 01859 \future Could (or should?) the allocate() functions be adapted to 01860 return an integer error value? 01861 */ 01862 class ovector_alloc { 01863 public: 01864 /// Allocate \c v for \c i elements 01865 void allocate(ovector &o, size_t i) { o.allocate(i); } 01866 /// Free memory 01867 void free(ovector &o) { o.free(); } 01868 }; 01869 01870 /** \brief A simple class to provide an \c allocate() function 01871 for \ref ovector_int 01872 */ 01873 class ovector_int_alloc { 01874 public: 01875 /// Allocate \c v for \c i elements 01876 void allocate(ovector_int &o, size_t i) { o.allocate(i); } 01877 /// Free memory 01878 void free(ovector_int &o) { o.free(); } 01879 }; 01880 01881 /** \brief A vector where the memory allocation is performed in 01882 the constructor 01883 01884 This can be useful, for example to easily make C-style arrays of 01885 \ref ovector objects with a fixed size. For example, 01886 \code 01887 ofvector<8> x[10]; 01888 \endcode 01889 would mean <tt>x</tt> is a 10-dimensional array of 01890 \ref ovector object with initial length 8. 01891 01892 \future Consider making allocate() and free() functions 01893 private for this class? 01894 */ 01895 #ifdef DOXYGENP 01896 template<size_t N=0> class ofvector : 01897 public ovector_tlate 01898 #else 01899 template<size_t N=0> class ofvector : 01900 public ovector_tlate<double,gsl_vector,gsl_block> 01901 #endif 01902 { 01903 public: 01904 ofvector() : ovector_tlate<double,gsl_vector,gsl_block>(N) { 01905 } 01906 }; 01907 01908 #ifndef DOXYGENP 01909 } 01910 #endif 01911 01912 #endif 01913
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).