array.h

Go to the documentation of this file.
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 SourceForge.net Logo, O2scl Sourceforge Project Page