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