![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
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
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).