00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 #ifndef O2SCL_UVECTOR_TLATE_H 00024 #define O2SCL_UVECTOR_TLATE_H 00025 00026 /** \file uvector_tlate.h 00027 \brief File for definitions of unit-stride vectors 00028 */ 00029 00030 #include <iostream> 00031 #include <cstdlib> 00032 #include <string> 00033 #include <fstream> 00034 #include <sstream> 00035 #include <vector> 00036 #include <o2scl/err_hnd.h> 00037 #include <o2scl/string_conv.h> 00038 #include <gsl/gsl_vector.h> 00039 00040 #ifndef DOXYGENP 00041 namespace o2scl { 00042 #endif 00043 00044 /** 00045 \brief A vector view with unit stride 00046 */ 00047 template<class data_t> class uvector_view_tlate { 00048 00049 #ifndef DOXYGEN_INTERNAL 00050 00051 protected: 00052 00053 /// The data 00054 data_t *data; 00055 /// The vector sz 00056 size_t sz; 00057 /// Zero if memory is owned elsewhere, 1 otherwise 00058 int owner; 00059 00060 #endif 00061 00062 public: 00063 00064 /// \name Copy constructors 00065 //@{ 00066 /// Copy constructor - create a new view of the same vector 00067 uvector_view_tlate(const uvector_view_tlate &v) { 00068 data=v.data; 00069 sz=v.sz; 00070 owner=0; 00071 } 00072 00073 /// Copy constructor - create a new view of the same vector 00074 uvector_view_tlate& operator=(const uvector_view_tlate &v) { 00075 data=v.data; 00076 sz=v.sz; 00077 owner=0; 00078 00079 return *this; 00080 } 00081 //@} 00082 00083 ~uvector_view_tlate() {}; 00084 00085 /// \name Get and set methods 00086 //@{ 00087 /** 00088 \brief Array-like indexing 00089 */ 00090 data_t &operator[](size_t i) { 00091 #if GSL_RANGE_CHECK 00092 if (i>=sz) { 00093 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00094 +" in uvector_view_tlate::operator[]. Size: "+ 00095 itos(sz)+ 00096 " (index should be less than size).").c_str(),gsl_index); 00097 return data[0]; 00098 } 00099 #endif 00100 return data[i]; 00101 } 00102 00103 /** 00104 \brief Array-like indexing 00105 */ 00106 const data_t &operator[](size_t i) const { 00107 #if GSL_RANGE_CHECK 00108 if (i>=sz) { 00109 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00110 +" in uvector_view_tlate::operator[] const. Size: "+ 00111 itos(sz)+ 00112 " (index should be less than size).").c_str(),gsl_index); 00113 return data[0]; 00114 } 00115 #endif 00116 return data[i]; 00117 } 00118 00119 /** 00120 \brief Array-like indexing 00121 */ 00122 data_t &operator()(size_t i) { 00123 #if GSL_RANGE_CHECK 00124 if (i>=sz) { 00125 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00126 +" in uvector_view_tlate::operator(). Size: "+ 00127 itos(sz)+ 00128 " (index should be less than size).").c_str(),gsl_index); 00129 return data[0]; 00130 } 00131 #endif 00132 return data[i]; 00133 } 00134 00135 /** 00136 \brief Array-like indexing 00137 */ 00138 const data_t &operator()(size_t i) const { 00139 #if GSL_RANGE_CHECK 00140 if (i>=sz) { 00141 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00142 +" in uvector_view_tlate::operator() const. Size: "+ 00143 itos(sz)+ 00144 " (index should be less than size).").c_str(),gsl_index); 00145 return data[0]; 00146 } 00147 #endif 00148 return data[i]; 00149 } 00150 00151 /** \brief Get (with optional range-checking) */ 00152 data_t get(size_t i) const { 00153 #if GSL_RANGE_CHECK 00154 if (i>=sz) { 00155 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00156 +" in uvector_view_tlate::get(). Size: "+ 00157 itos(sz)+ 00158 " (index should be less than size).").c_str(),gsl_index); 00159 return data[0]; 00160 } 00161 #endif 00162 return data[i]; 00163 } 00164 00165 /** \brief Get pointer (with optional range-checking) */ 00166 data_t *get_ptr(size_t i) { 00167 #if GSL_RANGE_CHECK 00168 if (i>=sz) { 00169 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00170 +" in uvector_view_tlate::get_ptr(). Size: "+ 00171 itos(sz)+ 00172 " (index should be less than size).").c_str(),gsl_index); 00173 return data; 00174 } 00175 #endif 00176 return data+i; 00177 } 00178 00179 /** \brief Get pointer (with optional range-checking) */ 00180 const data_t *get_const_ptr(size_t i) const { 00181 #if GSL_RANGE_CHECK 00182 if (i>=sz) { 00183 set_err("Index out of range in uvector_view::get_const_ptr().",1); 00184 return NULL; 00185 } 00186 #endif 00187 return (const data_t *)(data+i); 00188 } 00189 00190 /** \brief Set (with optional range-checking) */ 00191 int set(size_t i, data_t val) { 00192 #if GSL_RANGE_CHECK 00193 if (i>=sz) { 00194 set_err_ret((((std::string)"Array index ")+itos(i)+" out of bounds" 00195 +" in uvector_view_tlate::set(). Size: "+ 00196 itos(sz)+ 00197 " (index should be less than size).").c_str(),gsl_index); 00198 } 00199 #endif 00200 data[i]=val; 00201 return 0; 00202 } 00203 00204 /** \brief Set all of the value to be the value \c val */ 00205 int set_all(data_t val) { 00206 for(size_t i=0;i<sz;i++) { 00207 data[i]=val; 00208 } 00209 return 0; 00210 } 00211 00212 /** 00213 \brief Method to return vector size 00214 00215 If no memory has been allocated, this will quietly 00216 return zero. 00217 */ 00218 size_t size() const { 00219 return sz; 00220 } 00221 //@} 00222 00223 /// \name Other methods 00224 //@{ 00225 00226 /** \brief Swap vectors */ 00227 int swap(uvector_view_tlate<data_t> &x) { 00228 size_t t1, t2; 00229 double *t3; 00230 int t5; 00231 00232 t1=sz; 00233 t3=data; 00234 t5=owner; 00235 00236 sz=x.sz; 00237 data=x.data; 00238 owner=x.owner; 00239 00240 x.sz=t1; 00241 x.data=t3; 00242 x.owner=t5; 00243 00244 return 0; 00245 } 00246 00247 /// Return true if this object owns the data it refers to 00248 bool is_owner() const { 00249 if (owner==1) return true; 00250 return false; 00251 } 00252 00253 /** \brief Exhaustively look through the array for a 00254 particular value 00255 00256 This can only fail if \em all of the entries in the array are 00257 not finite, in which case it calls set_err() and returns 00258 0. The error handler is reset at the beginning of lookup(). 00259 */ 00260 size_t lookup(const data_t x0) const { 00261 err_hnd->reset(); 00262 const uvector_view_tlate<data_t> *a=this; 00263 size_t row=0, i=0, nvar=size(); 00264 while(!finite((*a)[i]) && i<nvar-1) i++; 00265 if (i==nvar-1) { 00266 set_err("Array not finite in intp_base::lookup()",1); 00267 return 0; 00268 } 00269 data_t best=(*a)[i], bdiff=fabs((*a)[i]-x0); 00270 for(;i<nvar;i++) { 00271 if (finite((*a)[i]) && fabs((*a)[i]-x0)<bdiff) { 00272 row=i; 00273 best=(*a)[i]; 00274 bdiff=fabs((*a)[i]-x0); 00275 } 00276 } 00277 return row; 00278 } 00279 00280 /** \brief Find the maximum element */ 00281 data_t max() const { 00282 data_t maxval; 00283 if (sz>0) { 00284 maxval=data[0]; 00285 for(size_t i=1;i<sz;i++) { 00286 if (data[i]>maxval) { 00287 maxval=data[i]; 00288 } 00289 } 00290 } else { 00291 return 0.0; 00292 } 00293 return maxval; 00294 } 00295 00296 /** \brief Find the minimum element */ 00297 data_t min() const { 00298 data_t minval; 00299 if (sz>0) { 00300 minval=data[0]; 00301 for(size_t i=1;i<sz;i++) { 00302 if (data[i]<minval) { 00303 minval=data[i]; 00304 } 00305 } 00306 } else { 00307 return 0.0; 00308 } 00309 return minval; 00310 } 00311 //@} 00312 00313 /// \name Arithmetic 00314 //@{ 00315 /** \brief operator+= */ 00316 uvector_view_tlate<data_t> &operator+= 00317 (const uvector_view_tlate<data_t> &x) { 00318 size_t lsz=x.sz; 00319 if (lsz>sz) lsz=sz; 00320 for(size_t i=0;i<lsz;i++) (*this)[i]+=x[i]; 00321 00322 return *this; 00323 } 00324 00325 /** \brief operator-= */ 00326 uvector_view_tlate<data_t> &operator-= 00327 (const uvector_view_tlate<data_t> &x) { 00328 size_t lsz=x.sz; 00329 if (lsz>sz) lsz=sz; 00330 for(size_t i=0;i<lsz;i++) (*this)[i]-=x[i]; 00331 00332 return *this; 00333 } 00334 00335 /** \brief operator+= */ 00336 uvector_view_tlate<data_t> &operator+=(const data_t &y) { 00337 for(size_t i=0;i<sz;i++) (*this)[i]+=y; 00338 00339 return *this; 00340 } 00341 00342 /** \brief operator-= */ 00343 uvector_view_tlate<data_t> &operator-=(const data_t &y) { 00344 for(size_t i=0;i<sz;i++) (*this)[i]-=y; 00345 00346 return *this; 00347 } 00348 00349 /** \brief operator*= */ 00350 uvector_view_tlate<data_t> &operator*=(const data_t &y) { 00351 for(size_t i=0;i<sz;i++) (*this)[i]*=y; 00352 00353 return *this; 00354 } 00355 00356 /** \brief Norm */ 00357 data_t norm() const { 00358 data_t result=0; 00359 for(size_t i=0;i<sz;i++) { 00360 result+=(*this)[i]*(*this)[i]; 00361 } 00362 return sqrt(result); 00363 } 00364 //@} 00365 00366 #ifndef DOXYGEN_INTERNAL 00367 00368 protected: 00369 00370 /** \brief Empty constructor provided for use by 00371 uvector_tlate(const uvector_tlate &v) 00372 */ 00373 uvector_view_tlate() {}; 00374 00375 #endif 00376 00377 }; 00378 00379 /** 00380 \brief A vector with unit stride 00381 00382 There are several global binary operators associated with 00383 objects of type \ref uvector_tlate. The are documented in the 00384 "Functions" section of \ref uvector_tlate.h. 00385 */ 00386 template<class data_t> class uvector_tlate : 00387 public uvector_view_tlate<data_t> { 00388 public: 00389 00390 /// \name Standard constructor 00391 //@{ 00392 /** \brief Create an uvector of size \c n with owner as 'true' */ 00393 uvector_tlate(size_t n=0) { 00394 00395 this->sz=0; 00396 this->data=0; 00397 00398 // This must be set to 1 even if n=0 so that future 00399 // calls to operator= work properly 00400 this->owner=1; 00401 00402 if (n>0) { 00403 this->data=(data_t *)malloc(n*sizeof(data_t)); 00404 if (this->data) { 00405 this->sz=n; 00406 } else { 00407 set_err("No memory for data in uvector_tlate constructor", 00408 gsl_enomem); 00409 } 00410 } 00411 } 00412 //@} 00413 00414 /// \name Copy constructors 00415 //@{ 00416 /// Deep copy constructor - allocate new space and make a copy 00417 uvector_tlate(const uvector_tlate &v) : 00418 uvector_view_tlate<data_t>() { 00419 size_t n=v.sz; 00420 this->sz=0; 00421 this->data=0; 00422 if (n>0) { 00423 this->data=(data_t *)malloc(n*sizeof(data_t)); 00424 if (this->data) { 00425 this->sz=n; 00426 this->owner=1; 00427 for(size_t i=0;i<n;i++) { 00428 this->data[i]=v[i]; 00429 } 00430 } else { 00431 set_err("No memory for data in uvector_tlate constructor", 00432 gsl_enomem); 00433 } 00434 } else { 00435 this->sz=0; 00436 } 00437 } 00438 00439 /// Deep copy constructor - allocate new space and make a copy 00440 uvector_tlate(const uvector_view_tlate<data_t> &v) : 00441 uvector_view_tlate<data_t>() { 00442 size_t n=v.size(); 00443 this->sz=0; 00444 this->data=0; 00445 if (n>0) { 00446 this->data=(data_t *)malloc(n*sizeof(data_t)); 00447 if (this->data) { 00448 this->sz=n; 00449 this->owner=1; 00450 for(size_t i=0;i<n;i++) { 00451 this->data[i]=v[i]; 00452 } 00453 } else { 00454 set_err("No memory for data in uvector_tlate constructor", 00455 gsl_enomem); 00456 } 00457 } else { 00458 this->sz=0; 00459 } 00460 } 00461 00462 /** \brief Deep copy constructor - if owner is true, allocate space and 00463 make a new copy, otherwise, just copy into the view 00464 */ 00465 uvector_tlate& operator=(const uvector_tlate &v) { 00466 size_t sz2=v.sz; 00467 this->sz=0; 00468 this->data=0; 00469 if (this->owner) { 00470 allocate(sz2); 00471 } else { 00472 if (this->sz!=sz2) { 00473 set_err("Sizes don't match in uvector_tlate::operator=()", 00474 gsl_ebadlen); 00475 return *this; 00476 } 00477 } 00478 for(size_t i=0;i<sz2;i++) { 00479 this->data[i]=v[i]; 00480 } 00481 return *this; 00482 } 00483 00484 /** \brief Deep copy constructor - if owner is true, allocate space and 00485 make a new copy, otherwise, just copy into the view 00486 */ 00487 uvector_tlate& operator=(const uvector_view_tlate<data_t> &v) { 00488 size_t sz2=v.size(); 00489 this->sz=0; 00490 this->data=0; 00491 if (this->owner) { 00492 allocate(sz2); 00493 } else { 00494 if (this->sz!=sz2) { 00495 set_err("Sizes don't match in uvector_tlate::operator=()", 00496 gsl_ebadlen); 00497 return *this; 00498 } 00499 } 00500 for(size_t i=0;i<sz2;i++) { 00501 this->data[i]=v[i]; 00502 } 00503 return *this; 00504 } 00505 //@} 00506 00507 ~uvector_tlate() { 00508 if (this->sz>0) { 00509 if (this->owner==1) { 00510 std::free(this->data); 00511 } 00512 this->sz=0; 00513 } 00514 } 00515 00516 /// \name Memory allocation 00517 //@{ 00518 /** 00519 \brief Allocate memory for size \c n after freeing any memory 00520 presently in use 00521 */ 00522 int allocate(size_t nsize) { 00523 if (this->sz>0) free(); 00524 00525 if (nsize>0) { 00526 this->data=(data_t *)malloc(nsize*sizeof(data_t)); 00527 if (this->data) { 00528 this->sz=nsize; 00529 this->owner=1; 00530 } else { 00531 set_err_ret("No memory for data in uvector_tlate::allocate()", 00532 gsl_enomem); 00533 } 00534 } else { 00535 set_err_ret("Zero size in uvector::allocate()",gsl_einval); 00536 } 00537 return 0; 00538 } 00539 00540 /** 00541 \brief Free the memory 00542 00543 This function will safely do nothing if used without first 00544 allocating memory or if called multiple times in succession. 00545 */ 00546 int free() { 00547 if (this->sz>0) { 00548 if (this->owner==1) { 00549 std::free(this->data); 00550 } 00551 this->sz=0; 00552 } 00553 return 0; 00554 } 00555 //@} 00556 00557 /// \name Other methods 00558 //@{ 00559 /// Erase an element from the array. 00560 int erase(size_t ix) { 00561 00562 // Only proceed if the user gave an element inside the array 00563 if (this->sz>ix) { 00564 00565 // Decrement the size 00566 this->sz--; 00567 00568 // Allocate new space 00569 data_t *newdat=(data_t *)(malloc(this->sz*sizeof(data_t))); 00570 00571 // Copy into the new space 00572 for(size_t i=0;i<this->sz;i++) { 00573 if (i<ix) newdat[i]=this->data[i]; 00574 else newdat[i]=this->data[i+1]; 00575 } 00576 00577 // Free the old space and reset the pointer 00578 std::free(this->data); 00579 this->data=newdat; 00580 00581 } else { 00582 set_err_ret("Cannot erase() beyond end of uvector_tlate.", 00583 gsl_einval); 00584 } 00585 00586 return 0; 00587 } 00588 //@} 00589 00590 }; 00591 00592 /** \brief Create a vector from an array 00593 */ 00594 template<class data_t> class uvector_array_tlate : 00595 public uvector_view_tlate<data_t> { 00596 public: 00597 /** \brief Create a vector from \c dat with size \c n */ 00598 uvector_array_tlate(size_t n, data_t *dat) { 00599 if (n>0) { 00600 this->data=dat; 00601 this->sz=n; 00602 this->owner=0; 00603 } 00604 } 00605 }; 00606 00607 /** \brief Create a vector from a subvector of another 00608 */ 00609 template<class data_t> class uvector_subvector_tlate : 00610 public uvector_view_tlate<data_t> { 00611 public: 00612 /** \brief Create a vector from \c orig */ 00613 uvector_subvector_tlate(uvector_view_tlate<data_t> &orig, 00614 size_t offset, size_t n) { 00615 if (offset+n-1<orig.size) { 00616 this->data=orig.data+offset; 00617 this->sz=n; 00618 this->owner=0; 00619 } else { 00620 this->sz=0; 00621 set_err("Subvector failed in uvector_sub_view().",1); 00622 } 00623 } 00624 }; 00625 00626 /** \brief Create a vector from an const array 00627 */ 00628 template<class data_t> class uvector_const_array_tlate : 00629 public uvector_view_tlate<data_t> { 00630 public: 00631 /** \brief Create a vector from \c dat with size \c n */ 00632 uvector_const_array_tlate(size_t n, const data_t *dat) { 00633 if (n>0) { 00634 // We have to do an explicit cast here, but we prevent the 00635 // user from changing the data. 00636 this->data=(data_t *)dat; 00637 this->sz=n; 00638 this->owner=0; 00639 } 00640 } 00641 00642 ~uvector_const_array_tlate() {}; 00643 00644 #ifndef DOXYGEN_INTERNAL 00645 00646 protected: 00647 00648 /** \name Ensure \c const by hiding non-const members 00649 */ 00650 //@{ 00651 data_t &operator[](size_t i) { return this->data[0]; } 00652 data_t &operator()(size_t i) { return this->data[0]; } 00653 data_t *get_ptr(size_t i) { return NULL; } 00654 int set(size_t i, data_t val) { return 0; } 00655 int swap(uvector_view_tlate<data_t> &x) { 00656 return 0; 00657 } 00658 int set_all(double val) { return 0; } 00659 uvector_view_tlate<data_t> &operator+= 00660 (const uvector_view_tlate<data_t> &x) { 00661 return *this; 00662 } 00663 uvector_view_tlate<data_t> &operator-= 00664 (const uvector_view_tlate<data_t> &x) { 00665 return *this; 00666 } 00667 uvector_view_tlate<data_t> &operator*=(const data_t &y) { 00668 return *this; 00669 } 00670 //@} 00671 00672 #endif 00673 00674 }; 00675 00676 /** \brief Create a const vector from a subvector of another vector 00677 */ 00678 template<class data_t> class uvector_const_subvector_tlate : 00679 public uvector_view_tlate<data_t> { 00680 public: 00681 /** \brief Create a vector from \c orig 00682 */ 00683 uvector_const_subvector_tlate 00684 (const uvector_view_tlate<data_t> &orig, 00685 size_t offset, size_t n) { 00686 if (offset+n-1<orig.sz) { 00687 this->data=orig.data+offset; 00688 this->sz=n; 00689 this->owner=0; 00690 } else { 00691 this->sz=0; 00692 set_err("Subvector failed in uvector_subvector().",1); 00693 } 00694 } 00695 00696 #ifndef DOXYGENP 00697 00698 protected: 00699 00700 /** \name Ensure \c const by hiding non-const members 00701 */ 00702 //@{ 00703 data_t &operator[](size_t i) { return this->data[0]; } 00704 data_t &operator()(size_t i) { return this->data[0]; } 00705 data_t *get_ptr(size_t i) { return NULL; } 00706 int set(size_t i, data_t val) { return 0; } 00707 int swap(uvector_view_tlate<data_t> &x) { 00708 return 0; 00709 } 00710 int set_all(double val) { return 0; } 00711 uvector_view_tlate<data_t> &operator+= 00712 (const uvector_view_tlate<data_t> &x) { 00713 return *this; 00714 } 00715 uvector_view_tlate<data_t> &operator-= 00716 (const uvector_view_tlate<data_t> &x) { 00717 return *this; 00718 } 00719 uvector_view_tlate<data_t> &operator*=(const data_t &y) { 00720 return *this; 00721 } 00722 //@} 00723 00724 #endif 00725 00726 }; 00727 00728 #ifdef DOXYGENP 00729 /// uvector typedef 00730 typedef uvector_tlate<data_t,size_t> uvector; 00731 /// uvector_view typedef 00732 typedef uvector_view_tlate<data_t,size_t> uvector_view; 00733 /// uvector_array typedef 00734 typedef uvector_array_tlate<data_t,size_t> uvector_array; 00735 /// uvector_subvector typedef 00736 typedef uvector_subvector_tlate<data_t,size_t> uvector_subvector; 00737 /// uvector_const_array typedef 00738 typedef uvector_const_array_tlate<data_t,size_t> uvector_const_array; 00739 /// uvector_const_subvector typedef 00740 typedef uvector_const_subvector_tlate<data_t,size_t> uvector_const_subvector; 00741 #else 00742 /// uvector typedef 00743 typedef uvector_tlate<double> uvector; 00744 /// uvector_view typedef 00745 typedef uvector_view_tlate<double> uvector_view; 00746 /// uvector_array typedef 00747 typedef uvector_array_tlate<double> uvector_array; 00748 /// uvector_subvector typedef 00749 typedef uvector_subvector_tlate<double> uvector_subvector; 00750 /// uvector_const_array typedef 00751 typedef uvector_const_array_tlate<double> uvector_const_array; 00752 /// uvector_const_subvector typedef 00753 typedef uvector_const_subvector_tlate<double> uvector_const_subvector; 00754 #endif 00755 00756 /// uvector_int typedef 00757 typedef uvector_tlate<int> uvector_int; 00758 /// uvector_int_view typedef 00759 typedef uvector_view_tlate<int> uvector_int_view; 00760 /// uvector_int_array typedef 00761 typedef uvector_array_tlate<int> uvector_int_array; 00762 /// uvector_int_subvector typedef 00763 typedef uvector_subvector_tlate<int> uvector_int_subvector; 00764 /// uvector_int_const_array typedef 00765 typedef uvector_const_array_tlate<int> uvector_int_const_array; 00766 /// uvector_int_const_subvector typedef 00767 typedef uvector_const_subvector_tlate<int> uvector_int_const_subvector; 00768 00769 /** 00770 \brief A operator for naive vector output 00771 00772 This outputs all of the vector elements. All of these are 00773 separated by one space character, though no trailing space or \c 00774 endl is sent to the output. 00775 */ 00776 template<class data_t> 00777 std::ostream &operator<< 00778 (std::ostream &os, 00779 const uvector_view_tlate<data_t> &v) { 00780 if (v.size()>0) { 00781 for(size_t i=0;i<v.size()-1;i++) { 00782 os << v[i] << ' '; 00783 } 00784 os << v[v.size()-1]; 00785 } else { 00786 os << "<empty>"; 00787 } 00788 return os; 00789 } 00790 00791 /** \brief A vector with unit-stride where the memory allocation is 00792 performed in the constructor 00793 */ 00794 #ifdef DOXYGENP 00795 template<size_t N=0> class ufvector : 00796 public uvector_tlate<data_t> 00797 #else 00798 template<size_t N=0> class ufvector : 00799 public uvector_tlate<double> 00800 #endif 00801 { 00802 public: 00803 ufvector() : uvector_tlate<double>(N) { 00804 } 00805 }; 00806 00807 #ifndef DOXYGENP 00808 } 00809 #endif 00810 00811 #endif 00812
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