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