00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 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_ARRAY_H 00024 #define O2SCL_ARRAY_H 00025 00026 /** \file array.h 00027 \brief Various array classes 00028 00029 This file contains the alloction classes 00030 - array_alloc 00031 - array_2d_alloc 00032 - pointer_alloc 00033 - pointer_2d_alloc 00034 the classes for the manipulation of arrays in smart_interp 00035 - array_reverse 00036 - array_subvector 00037 - array_subvector_reverse 00038 - array_const_reverse 00039 - array_const_subvector 00040 - array_const_subvector_reverse 00041 the array equivalent of omatrix_row or umatrix_row (see 00042 usage proposed in src/ode/ode_it_solve_ts.cpp) 00043 - array_row 00044 an array output function 00045 - vector_out() 00046 00047 For output of matrices rather than vectors, see matrix_out() 00048 and related functions documented in \ref columnify.h. 00049 00050 Note that the classes 00051 - array_reverse 00052 - array_subvector 00053 - array_subvector_reverse 00054 - array_const_reverse 00055 - array_const_subvector 00056 - array_const_subvector_reverse 00057 can be used with pointers or arrays, but array_alloc and 00058 pointer_alloc are \e not interchangable. 00059 00060 \todo Ensure that array_row works, either here or in 00061 src/ode/ode_it_solve_ts.cpp 00062 00063 \todo Document vector_sort, etc. 00064 */ 00065 00066 #include <iostream> 00067 #include <cmath> 00068 #include <string> 00069 #include <fstream> 00070 #include <sstream> 00071 #include <o2scl/err_hnd.h> 00072 #include <gsl/gsl_ieee_utils.h> 00073 #include <gsl/gsl_sort.h> 00074 00075 #ifndef DOXYGENP 00076 namespace o2scl 00077 { 00078 #endif 00079 00080 /** 00081 \brief A simple class to provide an \c allocate() function 00082 for arrays 00083 00084 The functions here are blank, as fixed-length arrays are 00085 automatically allocated and destroyed by the compiler. This 00086 class is present to provide an analog to \ref pointer_alloc and 00087 \ref ovector_alloc. 00088 */ 00089 template<class vec_t> class array_alloc { 00090 public: 00091 /// Allocate \c v for \c i elements 00092 void allocate(vec_t &v, size_t i) {} 00093 /// Free memory 00094 void free(vec_t &v) {} 00095 }; 00096 00097 /** 00098 \brief A simple class to provide an \c allocate() function 00099 for 2-dimensional arrays 00100 00101 The functions here are blank, as fixed-length arrays are 00102 automatically allocated and destroyed by the compiler. This 00103 class is present to provide an analog to \ref pointer_2d_alloc 00104 and \ref omatrix_alloc 00105 */ 00106 template<class mat_t> class array_2d_alloc { 00107 public: 00108 /// Allocate \c v for \c i elements 00109 void allocate(mat_t &v, size_t i, size_t j) {} 00110 /// Free memory 00111 void free(mat_t &v, size_t i) {} 00112 }; 00113 00114 /** 00115 \brief A simple class to provide an \c allocate() function 00116 for pointers 00117 00118 Uses \c new and \c delete. 00119 */ 00120 template<class base_t> class pointer_alloc { 00121 public: 00122 /// Allocate \c v for \c i elements 00123 void allocate(base_t *&v, size_t i) { v=new base_t[i]; } 00124 /// Free memory 00125 void free(base_t *&v) { delete[] v; } 00126 }; 00127 00128 /** 00129 \brief A simple class to provide an \c allocate() function 00130 for pointers 00131 00132 Uses \c new and \c delete. 00133 */ 00134 template<class base_t> class pointer_2d_alloc { 00135 public: 00136 /// Allocate \c v for \c i elements 00137 void allocate(base_t **&v, size_t i, size_t j) { 00138 v=new base_t *[i]; 00139 for(size_t m=0;m<i;m++) v[m]=new base_t[j]; 00140 } 00141 /// Free memory 00142 void free(base_t **&v, size_t i) { 00143 for(size_t m=0;m<i;m++) delete[] v[m]; 00144 delete[] v; 00145 } 00146 }; 00147 00148 /** 00149 \brief A simple class which reverses the order of an array 00150 */ 00151 template<size_t sz> class array_reverse { 00152 00153 #ifndef DOXYGEN_INTERNAL 00154 00155 protected: 00156 00157 /// The array pointer 00158 double *a; 00159 00160 #endif 00161 00162 public: 00163 00164 /// Create a reversed array from \c arr of size \c sz 00165 array_reverse(double *arr) { 00166 a=arr; 00167 } 00168 00169 /** 00170 \brief Array-like indexing 00171 */ 00172 double &operator[](size_t i) { 00173 return a[sz-1-i]; 00174 } 00175 00176 /** 00177 \brief Array-like indexing 00178 */ 00179 const double &operator[](size_t i) const { 00180 return a[sz-1-i]; 00181 } 00182 00183 }; 00184 00185 /** 00186 \brief A simple class which reverses the order of an array 00187 */ 00188 template<size_t sz> class array_const_reverse { 00189 00190 #ifndef DOXYGEN_INTERNAL 00191 00192 protected: 00193 00194 /// The array pointer 00195 double *a; 00196 00197 #endif 00198 00199 public: 00200 00201 /// Create a reversed array from \c arr of size \c sz 00202 array_const_reverse(const double *arr) { 00203 a=(double *)arr; 00204 } 00205 00206 /** 00207 \brief Array-like indexing 00208 */ 00209 const double &operator[](size_t i) const { 00210 return a[sz-1-i]; 00211 } 00212 00213 }; 00214 00215 /** 00216 \brief A simple subvector class for an array (without error checking) 00217 */ 00218 class array_subvector { 00219 00220 #ifndef DOXYGEN_INTERNAL 00221 00222 protected: 00223 00224 /// The array pointer 00225 double *a; 00226 00227 /// The offset 00228 size_t off; 00229 00230 /// The subvector length 00231 size_t len; 00232 00233 #endif 00234 00235 public: 00236 00237 /// Create a reversed array from \c arr of size \c sz 00238 array_subvector(double *arr, size_t offset, size_t n) { 00239 a=arr+offset; 00240 off=offset; 00241 len=n; 00242 } 00243 00244 /** 00245 \brief Array-like indexing 00246 */ 00247 double &operator[](size_t i) { 00248 return a[i]; 00249 } 00250 00251 /** 00252 \brief Array-like indexing 00253 */ 00254 const double &operator[](size_t i) const { 00255 return a[i]; 00256 } 00257 00258 }; 00259 00260 /** \brief A simple subvector class for a const array 00261 (without error checking) 00262 */ 00263 class array_const_subvector { 00264 00265 #ifndef DOXYGEN_INTERNAL 00266 00267 protected: 00268 00269 /// The array pointer 00270 double *a; 00271 00272 /// The offset 00273 size_t off; 00274 00275 /// The subvector length 00276 size_t len; 00277 00278 #endif 00279 00280 public: 00281 00282 /// Create a reversed array from \c arr of size \c sz 00283 array_const_subvector(const double *arr, size_t offset, size_t n) { 00284 a=(double *)arr+offset; 00285 off=offset; 00286 len=n; 00287 } 00288 00289 /** 00290 \brief Array-like indexing 00291 */ 00292 const double &operator[](size_t i) const { 00293 return a[i]; 00294 } 00295 00296 }; 00297 00298 /** 00299 \brief Reverse a subvector of an array 00300 */ 00301 class array_subvector_reverse { 00302 00303 #ifndef DOXYGEN_INTERNAL 00304 00305 protected: 00306 00307 /// The array pointer 00308 double *a; 00309 00310 /// The offset 00311 size_t off; 00312 00313 /// The subvector length 00314 size_t len; 00315 00316 #endif 00317 00318 public: 00319 00320 /// Create a reversed array from \c arr of size \c sz 00321 array_subvector_reverse(double *arr, size_t offset, size_t n) { 00322 a=arr+offset; 00323 off=offset; 00324 len=n; 00325 } 00326 00327 /** 00328 \brief Array-like indexing 00329 */ 00330 double &operator[](size_t i) { 00331 return a[len-1-i]; 00332 } 00333 00334 /** 00335 \brief Array-like indexing 00336 */ 00337 const double &operator[](size_t i) const { 00338 return a[len-1-i]; 00339 } 00340 00341 }; 00342 00343 /** 00344 \brief Reverse a subvector of a const array 00345 */ 00346 class array_const_subvector_reverse { 00347 00348 #ifndef DOXYGEN_INTERNAL 00349 00350 protected: 00351 00352 /// The array pointer 00353 double *a; 00354 00355 /// The offset 00356 size_t off; 00357 00358 /// The subvector length 00359 size_t len; 00360 00361 #endif 00362 00363 public: 00364 00365 /// Create a reversed array from \c arr of size \c sz 00366 array_const_subvector_reverse(const double *arr, size_t offset, size_t n) { 00367 a=(double *)arr+offset; 00368 off=offset; 00369 len=n; 00370 } 00371 00372 /** 00373 \brief Array-like indexing 00374 */ 00375 const double &operator[](size_t i) const { 00376 return a[len-1-i]; 00377 } 00378 00379 }; 00380 00381 /// Extract a row of a C-style 2d-array 00382 template <class data_t, class array_2d_t> class array_row { 00383 public: 00384 data_t *p; 00385 array_row(array_2d_t &a, size_t i) { 00386 p=&(a[i][0]); 00387 } 00388 data_t &operator[](size_t i) { 00389 return p[i]; 00390 } 00391 }; 00392 00393 /** 00394 \brief Output a vector to a stream 00395 00396 No trailing space is output after the last element, and an 00397 endline is output only if \c endline is set to \c true. If the 00398 parameter \c n is zero, this function silently does nothing. 00399 */ 00400 template<class vec_t> 00401 int vector_out(std::ostream &os, size_t n, vec_t &v, 00402 bool endline=false) { 00403 // This next line is important since n-1 is not well-defined if n=0 00404 if (n==0) return 0; 00405 for(size_t i=0;i<n-1;i++) os << v[i] << " "; 00406 os << v[n-1]; 00407 if (endline) os << std::endl; 00408 return 0; 00409 } 00410 00411 /** 00412 \brief Provide a downheap() function for vector_sort() 00413 */ 00414 template<class data_t, class vec_t> 00415 void sort_downheap(vec_t &data, const size_t N, size_t k) { 00416 00417 data_t v=data[k]; 00418 00419 while (k<=N/2) { 00420 size_t j=2*k; 00421 00422 if (j<N && data[j] < data[j+1]) j++; 00423 if (!(v < data[j])) break; 00424 data[k]=data[j]; 00425 k=j; 00426 } 00427 00428 data[k]=v; 00429 } 00430 00431 /** 00432 \brief Sort a vector 00433 00434 This is a generic sorting template function. It will work for 00435 any types \c data_t and \c vec_t for which 00436 - \c data_t has an <tt>operator=</tt> 00437 - \c data_t has a less than operator to compare elements 00438 - <tt>vec_t::operator[]</tt> returns a reference 00439 to an object of type \c data_t 00440 00441 In particular, it will work with \ref ovector, \ref uvector, 00442 \ref ovector_int, \ref uvector_int (and other related O2scl 00443 vector classes), the STL template class <tt>std::vector</tt>, 00444 and arrays and pointers of numeric, character, and string 00445 objects. 00446 00447 For example, 00448 \code 00449 std::string list[3]={"dog","cat","fox"}; 00450 vector_sort<std::string, std::string[3]>(3,list); 00451 \endcode 00452 */ 00453 template<class data_t, class vec_t> 00454 int vector_sort(const size_t n, vec_t &data) { 00455 00456 size_t N; 00457 size_t k; 00458 00459 if (n==0) return 0; 00460 00461 N=n-1; 00462 k=N/2; 00463 k++; 00464 do { 00465 k--; 00466 sort_downheap<data_t,vec_t>(data,N,k); 00467 } while (k > 0); 00468 00469 while (N > 0) { 00470 data_t tmp=data[0]; 00471 data[0]=data[N]; 00472 data[N]=tmp; 00473 N--; 00474 sort_downheap<data_t,vec_t>(data,N,0); 00475 } 00476 00477 return 0; 00478 } 00479 00480 /** 00481 \brief "Rotate" a vector so that the kth element is now the beginning 00482 00483 This is a generic template function which will work for 00484 any types \c data_t and \c vec_t for which 00485 - \c data_t has an <tt>operator=</tt> 00486 - <tt>vec_t::operator[]</tt> returns a reference 00487 to an object of type \c data_t 00488 */ 00489 template<class data_t, class vec_t> 00490 int vector_rotate(const size_t n, vec_t &data, size_t k) { 00491 00492 data_t *tmp=new data_t[n]; 00493 for(size_t i=0;i<n;i++) { 00494 tmp[i]=data[(i+k)%n]; 00495 } 00496 for(size_t i=0;i<n;i++) { 00497 data[i]=tmp[i]; 00498 } 00499 delete[] tmp; 00500 00501 return 0; 00502 } 00503 00504 /// Compute the maximum of the first \c n elements of a vector 00505 template<class data_t, class vec_t> 00506 int vector_max(const size_t n, vec_t &data, data_t &max, size_t &ix) { 00507 00508 if (n==0) { 00509 set_err_ret("Send size=0 to vector_max().",gsl_efailed); 00510 } 00511 ix=0; 00512 max=data[0]; 00513 for(size_t i=1;i<n;i++) { 00514 if (data[i]>max) { 00515 max=data[i]; 00516 ix=i; 00517 } 00518 } 00519 return 0; 00520 } 00521 00522 /// Compute the minimum of the first \c n elements of a vector 00523 template<class data_t, class vec_t> 00524 int vector_min(const size_t n, vec_t &data, data_t &min, size_t &ix) { 00525 00526 if (n==0) { 00527 set_err_ret("Send size=0 to vector_min().",gsl_efailed); 00528 } 00529 ix=0; 00530 min=data[0]; 00531 for(size_t i=1;i<n;i++) { 00532 if (data[i]<min) { 00533 min=data[i]; 00534 ix=i; 00535 } 00536 } 00537 return 0; 00538 } 00539 00540 /** 00541 \brief Compute the sum of the first \c n elements of a vector 00542 00543 If \c n is zero, this will set \c avg to zero and return 00544 \ref gsl_success. 00545 */ 00546 template<class data_t, class vec_t> 00547 int vector_sum(const size_t n, vec_t &data, data_t &sum) { 00548 00549 sum=0; 00550 for(size_t i=0;i<n;i++) { 00551 sum+=data[i]; 00552 } 00553 return 0; 00554 } 00555 00556 /** 00557 \brief Compute the mean of the first \c n elements of a vector 00558 00559 If \c n is zero, this will set \c avg to zero and return 00560 \ref gsl_success. 00561 */ 00562 template<class data_t, class vec_t> 00563 int vector_avg(const size_t n, vec_t &data, data_t &avg) { 00564 00565 avg=0; 00566 for(size_t i=0;i<n;i++) { 00567 avg+=data[i]; 00568 } 00569 avg/=((data_t)n); 00570 return 0; 00571 } 00572 00573 /** \brief Compute the variance of the first \c n elements of a vector 00574 given the mean \c mean. 00575 00576 If \c n is zero, this will set \c avg to zero and return 00577 \ref gsl_success. 00578 */ 00579 template<class data_t, class vec_t> 00580 int vector_variance(const size_t n, vec_t &data, data_t &mean, 00581 data_t &var) { 00582 00583 var=0; 00584 for(size_t i=0;i<n;i++) { 00585 data_t delta=(data[i]-mean); 00586 var+=(delta*delta-var)/((double)(i+1)); 00587 } 00588 return 0; 00589 } 00590 00591 /** \brief Reverse a vector 00592 */ 00593 template<class data_t, class vec_t> 00594 int vector_reverse(const size_t n, vec_t &data) { 00595 data_t tmp; 00596 00597 for(size_t i=0;i<n/2;i++) { 00598 tmp=data[n-1-i]; 00599 data[n-1-i]=data[i]; 00600 data[i]=tmp; 00601 } 00602 return 0; 00603 } 00604 00605 /** \brief Compute the standard deviation of the first \c n elements 00606 of a vector 00607 */ 00608 template<class data_t, class vec_t> 00609 int vector_stdev(const size_t n, vec_t &data, data_t &var) { 00610 00611 data_t mean; 00612 vector_mean(n,data,mean); 00613 var=0; 00614 for(size_t i=0;i<n;i++) { 00615 data_t delta=(data[i]-mean); 00616 var+=(delta*delta-var)/((double)(i+1)); 00617 } 00618 var=sqrt(var*((double)n)/((double)(n-1))); 00619 return 0; 00620 } 00621 00622 #ifndef DOXYGENP 00623 } 00624 #endif 00625 00626 #endif
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