array.h

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

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.