Object-oriented Scientific Computing Library: Version 0.910
array.h
Go to the documentation of this file.
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006-2012, 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     For a more general discussion of vectors and matrices in \o2,
00030     see the \ref vecmat_section
00031     of the User's Guide.
00032 
00033     This file contains classes and functions for operating with
00034     C-style 1- or 2-dimensional arrays and pointers to double. For an
00035     example of the usage of the array allocation classes, see the \ref
00036     ex_mroot_sect . For more generic operations on generic vector
00037     objects (including in some cases C-style arrays), see also the
00038     file \ref vector.h . 
00039 
00040     This file contains the allocation classes
00041     - array_alloc
00042     - array_2d_alloc
00043     - pointer_alloc
00044     - pointer_2d_alloc
00045 
00046     the classes for the manipulation of arrays in smart_interp
00047     - array_reverse
00048     - array_subvector
00049     - array_subvector_reverse
00050     - array_const_reverse
00051     - array_const_subvector
00052     - array_const_subvector_reverse 
00053 
00054     the array equivalent of omatrix_row and omatrix_col (see 
00055     usage in <tt>src/ode/ode_it_solve_ts.cpp</tt>)
00056     - array_2d_row
00057     - array_2d_col
00058 
00059     \note The classes 
00060     - array_reverse
00061     - array_subvector
00062     - array_subvector_reverse
00063     - array_const_reverse
00064     - array_const_subvector
00065     - array_const_subvector_reverse 
00066 
00067     can be used with pointers or arrays, but array_alloc and
00068     pointer_alloc are \e not interchangable.
00069 
00070     \future Create a class which views a C-style array
00071     as a matrix and offers an <tt>operator(,)</tt>
00072 
00073 */
00074 #include <iostream>
00075 #include <cmath>
00076 #include <string>
00077 #include <fstream>
00078 #include <sstream>
00079 #include <vector>
00080 #include <map>
00081 #include <o2scl/err_hnd.h>
00082 #include <gsl/gsl_ieee_utils.h>
00083 #include <gsl/gsl_sort.h>
00084 
00085 #ifndef DOXYGENP
00086 namespace o2scl
00087 {
00088 #endif
00089 
00090   /** \brief A simple class to provide an \c allocate() function
00091       for arrays
00092       
00093       The functions here are blank, as fixed-length arrays are
00094       automatically allocated and destroyed by the compiler. This
00095       class is present to provide an analog to \ref pointer_alloc and
00096       \ref ovector_alloc . This class is used, for example, for \ref
00097       sma_interp_vec .
00098 
00099       \future Might it be possible to rework this so that 
00100       it does range checking and ensures that the user
00101       doesn't try to allocate more or less space? I.e.
00102       array_alloc<double[2]> complains if you try an allocate(x,3)?
00103   */
00104   template<class vec_t> class array_alloc {
00105   public:
00106     /// Allocate \c v for \c i elements
00107     void allocate(vec_t &v, size_t i) {}
00108     /// Free memory
00109     void free(vec_t &v) {}
00110   };
00111 
00112   /** \brief A simple class to provide an \c allocate() function
00113       for 2-dimensional arrays
00114       
00115       The functions here are blank, as fixed-length arrays are
00116       automatically allocated and destroyed by the compiler. This
00117       class is present to provide an analog to \ref pointer_2d_alloc
00118       and \ref omatrix_alloc. This class is used in
00119       <tt>gsl_mroot_hybrids_ts.cpp</tt> .
00120   */
00121   template<class mat_t> class array_2d_alloc {
00122   public:
00123     /// Allocate \c v for \c i elements
00124     void allocate(mat_t &v, size_t i, size_t j) {}
00125     /// Free memory
00126     void free(mat_t &v, size_t i) {}
00127   };
00128 
00129   /** \brief A simple class to provide an \c allocate() function
00130       for pointers
00131       
00132       This class uses \c new and \c delete and may throw a C++
00133       exception in the usual way. It contains a simple garbage
00134       collection mechanism to assist in exception safety.
00135       
00136       This class is used in \ref tensor_grid .
00137 
00138       \future There may be a slight issue here if the pointer
00139       allocation succeeds and the list insertion fails, and the user
00140       catches the exception thrown by the list insertion failure, then
00141       a memory leak will ensue. This might be partially ameliorated by
00142       counting allocations and insertions. This failure mechanism is
00143       rarely encountered in practice.
00144   */
00145   template<class base_t> class pointer_alloc {
00146     
00147   protected:
00148 
00149     /// Store allocated pointers
00150     std::vector<base_t *> list;
00151 
00152   public:
00153     
00154     ~pointer_alloc() {
00155       typename std::vector<base_t *>::iterator it;
00156       for (it=list.begin();it!=list.end();it++) {
00157         base_t *v=*it;
00158         delete[] v;
00159       }
00160     }
00161 
00162     /// Allocate \c v for \c i elements
00163     void allocate(base_t *&v, size_t i) { 
00164       v=new base_t[i]; 
00165       list.push_back(v);
00166     }
00167 
00168     /// Free memory
00169     void free(base_t *&v) { 
00170       typename std::vector<base_t *>::iterator it;
00171       for (it=list.begin();it!=list.end();) {
00172         if (*it==v) {
00173           list.erase(it);
00174           it=list.end();
00175         } else {
00176           it++;
00177         }
00178       }
00179       delete[] v; 
00180     }
00181 
00182   };
00183 
00184   /** \brief A simple class to provide an \c allocate() function
00185       for pointers
00186 
00187       This class uses \c new and \c delete and may throw a C++
00188       exception in the usual way. It contains a simple garbage
00189       collection mechanism to assist in exception safety.
00190 
00191       This class is used in \ref columnify and \ref cern_mroot.
00192 
00193       \future There may be a slight issue here if the pointer
00194       allocation succeeds and the list insertion fails, and the user
00195       catches the exception thrown by the list insertion failure, then
00196       a memory leak will ensue. This might be partially ameliorated by
00197       counting allocations and insertions. This failure mechanism is
00198       rarely encountered in practice.
00199   */
00200   template<class base_t> class pointer_2d_alloc {
00201 
00202   protected:
00203 
00204     typedef struct {
00205       /// Return \c p1<p2
00206       bool operator()(base_t ** const &p1, base_t ** const &p2) const {
00207         return p1<p2;
00208       }
00209     } pointer_comp;
00210 
00211     /// Store allocated pointers
00212     std::map<base_t **,size_t,pointer_comp> list;
00213 
00214     /// Iterator type
00215     typedef typename std::map<base_t **,size_t,pointer_comp>::iterator iter;
00216 
00217   public:
00218 
00219     ~pointer_2d_alloc() {
00220       for(iter it=list.begin();it!=list.end();it++) {
00221         base_t **v=it->first;
00222         for(size_t i=0;i<it->second;i++) {
00223           delete[] v[i];
00224         }
00225         delete[] v;
00226       }
00227     }
00228 
00229     /// Allocate \c v for \c i elements
00230     void allocate(base_t **&v, size_t i, size_t j) { 
00231       v=new base_t *[i]; 
00232       size_t cnt=0;
00233       for(size_t m=0;m<i;m++) {
00234         v[m]=new base_t[j];
00235         cnt++;
00236       }
00237       list.insert(make_pair(v,cnt));
00238     }
00239 
00240     /// Free memory
00241     void free(base_t **&v, size_t i) { 
00242       iter it=list.find(v);
00243       size_t cnt=it->second;
00244       if (it!=list.end()) {
00245         list.erase(it);
00246       }
00247       for(size_t m=0;m<cnt;m++) delete[] v[m];
00248       delete[] v; 
00249     }
00250   };
00251 
00252   /** \brief A simple class which reverses the order of an array
00253 
00254       See an example of usage in <tt>interp_ts.cpp</tt> and
00255       <tt>smart_interp_ts.cpp</tt>.
00256    */
00257   template<size_t sz> class array_reverse {
00258     
00259 #ifndef DOXYGEN_INTERNAL
00260 
00261   protected:
00262     
00263     /// The array pointer
00264     double *a;
00265 
00266 #endif
00267 
00268   public:
00269 
00270     /// Create a reversed array from \c arr of size \c sz
00271     array_reverse(double *arr) {
00272       a=arr;
00273     }
00274 
00275     /** \brief Array-like indexing 
00276     */
00277     double &operator[](size_t i) {
00278       return a[sz-1-i];
00279     }
00280     
00281     /** \brief Array-like indexing 
00282     */
00283     const double &operator[](size_t i) const {
00284       return a[sz-1-i];
00285     }
00286     
00287   };
00288 
00289   /** \brief A simple class which reverses the order of an array
00290 
00291       See an example of usage in <tt>interp_ts.cpp</tt> and
00292       <tt>smart_interp_ts.cpp</tt>.
00293    */
00294   template<size_t sz> class array_const_reverse {
00295     
00296 #ifndef DOXYGEN_INTERNAL
00297 
00298   protected:
00299     
00300     /// The array pointer
00301     double *a;
00302 
00303 #endif
00304 
00305   public:
00306 
00307     /// Create a reversed array from \c arr of size \c sz
00308     array_const_reverse(const double *arr) {
00309       a=(double *)arr;
00310     }
00311 
00312     /** \brief Array-like indexing 
00313     */
00314     const double &operator[](size_t i) const {
00315       return a[sz-1-i];
00316     }
00317     
00318   };
00319 
00320   /** \brief A simple subvector class for an array (without error checking)
00321    */
00322   class array_subvector {
00323     
00324 #ifndef DOXYGEN_INTERNAL
00325 
00326   protected:
00327     
00328     /// The array pointer
00329     double *a;
00330 
00331     /// The offset
00332     size_t off;
00333 
00334     /// The subvector length
00335     size_t len;
00336 
00337 #endif
00338 
00339   public:
00340 
00341     /// Create a reversed array from \c arr of size \c sz
00342     array_subvector(double *arr, size_t offset, size_t n) {
00343       a=arr+offset;
00344       off=offset;
00345       len=n;
00346     }
00347 
00348     /** \brief Array-like indexing 
00349     */
00350     double &operator[](size_t i) {
00351       return a[i];
00352     }
00353     
00354     /** \brief Array-like indexing 
00355     */
00356     const double &operator[](size_t i) const {
00357       return a[i];
00358     }
00359     
00360   };
00361 
00362   /** \brief Column of a 2d array
00363 
00364       This works because two-dimensional arrays are always
00365       continguous (as indicated in appendix C of Soustroup's book).
00366   */
00367   template<size_t R, size_t C, class data_t=double> class array_2d_col {
00368     
00369 #ifndef DOXYGEN_INTERNAL
00370     
00371     protected:
00372     
00373     /// The array pointer
00374     data_t *a;
00375     
00376 #endif
00377     
00378     public:
00379     
00380     /// Create an object as the <tt>i</tt>th column of \c mat
00381     array_2d_col(data_t mat[R][C], size_t i) {
00382       a=&(mat[0][i]);
00383     }
00384     
00385     /** \brief Array-like indexing 
00386     */
00387     data_t &operator[](size_t i) {
00388       return a[R*i];
00389     }
00390     
00391     /** \brief Array-like indexing 
00392     */
00393     const data_t &operator[](size_t i) const {
00394       return a[R*i];
00395     }
00396     
00397     };
00398   
00399   /** \brief Row of a 2d array
00400   */
00401   template<class array_2d_t, class data_t=double> class array_2d_row {
00402     
00403 #ifndef DOXYGEN_INTERNAL
00404 
00405   protected:
00406     
00407     /// The array pointer
00408     data_t *a;
00409 
00410 #endif
00411 
00412   public:
00413 
00414     /// Create an object as the <tt>i</tt>th row of \c mat
00415     array_2d_row(array_2d_t &mat, size_t i) {
00416       a=&(mat[i][0]);
00417     }
00418 
00419     /** \brief Array-like indexing, returns the element in the <tt>i</tt>th
00420         column of the chosen row
00421     */
00422     data_t &operator[](size_t i) {
00423       return a[i];
00424     }
00425     
00426     /** \brief Array-like indexing, returns the element in the <tt>i</tt>th
00427         column of the chosen row
00428     */
00429     const data_t &operator[](size_t i) const {
00430       return a[i];
00431     }
00432     
00433   };
00434 
00435   /** \brief A simple subvector class for a const array 
00436       (without error checking)
00437 
00438       \future Make the member data truly const and remove
00439       the extra typecast.
00440    */
00441   class array_const_subvector {
00442     
00443 #ifndef DOXYGEN_INTERNAL
00444 
00445   protected:
00446     
00447     /// The array pointer
00448     double *a;
00449 
00450     /// The offset
00451     size_t off;
00452 
00453     /// The subvector length
00454     size_t len;
00455 
00456 #endif
00457 
00458   public:
00459 
00460     /// Create a reversed array from \c arr of size \c sz
00461     array_const_subvector(const double *arr, size_t offset, size_t n) {
00462       a=(double *)arr+offset;
00463       off=offset;
00464       len=n;
00465     }
00466 
00467     /** \brief Array-like indexing 
00468     */
00469     const double &operator[](size_t i) const {
00470       return a[i];
00471     }
00472     
00473   };
00474 
00475   /** \brief Reverse a subvector of an array
00476    */
00477   class array_subvector_reverse {
00478     
00479 #ifndef DOXYGEN_INTERNAL
00480 
00481   protected:
00482     
00483     /// The array pointer
00484     double *a;
00485 
00486     /// The offset
00487     size_t off;
00488     
00489     /// The subvector length
00490     size_t len;
00491 
00492 #endif
00493 
00494   public:
00495 
00496     /// Create a reversed array from \c arr of size \c sz
00497     array_subvector_reverse(double *arr, size_t offset, size_t n) {
00498       a=arr+offset;
00499       off=offset;
00500       len=n;
00501     }
00502 
00503     /** \brief Array-like indexing 
00504     */
00505     double &operator[](size_t i) {
00506       return a[len-1-i];
00507     }
00508     
00509     /** \brief Array-like indexing 
00510     */
00511     const double &operator[](size_t i) const {
00512       return a[len-1-i];
00513     }
00514     
00515   };
00516 
00517   /** \brief Reverse a subvector of a const array
00518   */
00519   class array_const_subvector_reverse {
00520     
00521 #ifndef DOXYGEN_INTERNAL
00522 
00523   protected:
00524     
00525     /// The array pointer
00526     double *a;
00527 
00528     /// The offset
00529     size_t off;
00530 
00531     /// The subvector length
00532     size_t len;
00533 
00534 #endif
00535 
00536   public:
00537     
00538     /// Create a reversed array from \c arr of size \c sz
00539     array_const_subvector_reverse(const double *arr, size_t offset, 
00540                                   size_t n) {
00541       a=(double *)arr+offset;
00542       off=offset;
00543       len=n;
00544     }
00545 
00546     /** \brief Array-like indexing 
00547     */
00548     const double &operator[](size_t i) const {
00549       return a[len-1-i];
00550     }
00551     
00552   };
00553 
00554 #ifndef DOXYGENP
00555 }
00556 #endif
00557 
00558 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.