00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, 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 */ 00071 #include <iostream> 00072 #include <cmath> 00073 #include <string> 00074 #include <fstream> 00075 #include <sstream> 00076 #include <new> 00077 #include <o2scl/err_hnd.h> 00078 #include <gsl/gsl_ieee_utils.h> 00079 #include <gsl/gsl_sort.h> 00080 00081 #ifndef DOXYGENP 00082 namespace o2scl 00083 { 00084 #endif 00085 00086 /** 00087 \brief A simple class to provide an \c allocate() function 00088 for arrays 00089 00090 The functions here are blank, as fixed-length arrays are 00091 automatically allocated and destroyed by the compiler. This 00092 class is present to provide an analog to \ref pointer_alloc and 00093 \ref ovector_alloc . This class is used, for example, for \ref 00094 sma_interp_vec . 00095 00096 \future Might it be possible to rework this so that 00097 it does range checking and ensures that the user 00098 doesn't try to allocate more or less space? I.e. 00099 array_alloc<double[2]> complains if you try an allocate(x,3)? 00100 */ 00101 template<class vec_t> class array_alloc { 00102 public: 00103 /// Allocate \c v for \c i elements 00104 void allocate(vec_t &v, size_t i) {} 00105 /// Free memory 00106 void free(vec_t &v) {} 00107 }; 00108 00109 /** 00110 \brief A simple class to provide an \c allocate() function 00111 for 2-dimensional arrays 00112 00113 The functions here are blank, as fixed-length arrays are 00114 automatically allocated and destroyed by the compiler. This 00115 class is present to provide an analog to \ref pointer_2d_alloc 00116 and \ref omatrix_alloc . This class is used in 00117 <tt>gsl_mroot_hybrids_ts.cpp</tt> . 00118 */ 00119 template<class mat_t> class array_2d_alloc { 00120 public: 00121 /// Allocate \c v for \c i elements 00122 void allocate(mat_t &v, size_t i, size_t j) {} 00123 /// Free memory 00124 void free(mat_t &v, size_t i) {} 00125 }; 00126 00127 /** 00128 \brief A simple class to provide an \c allocate() function 00129 for pointers 00130 00131 This class is used in \ref tensor_grid . 00132 00133 This class uses \c new and \c delete and may throw a C++ 00134 exception in the usual way. 00135 */ 00136 template<class base_t> class pointer_alloc { 00137 public: 00138 00139 /// Allocate \c v for \c i elements 00140 void allocate(base_t *&v, size_t i) { v=new base_t[i]; } 00141 /// Free memory 00142 void free(base_t *&v) { delete[] v; } 00143 }; 00144 00145 /** 00146 \brief A simple class to provide an \c allocate() function 00147 for pointers 00148 00149 This class uses \c new and \c delete and may throw a C++ 00150 exception in the usual way. 00151 */ 00152 template<class base_t> class pointer_2d_alloc { 00153 public: 00154 /// Allocate \c v for \c i elements 00155 void allocate(base_t **&v, size_t i, size_t j) { 00156 v=new base_t *[i]; 00157 for(size_t m=0;m<i;m++) v[m]=new base_t[j]; 00158 } 00159 /// Free memory 00160 void free(base_t **&v, size_t i) { 00161 for(size_t m=0;m<i;m++) delete[] v[m]; 00162 delete[] v; 00163 } 00164 }; 00165 00166 /** 00167 \brief A simple class which reverses the order of an array 00168 00169 See an example of usage in <tt>interp_ts.cpp</tt> and 00170 <tt>smart_interp_ts.cpp</tt>. 00171 */ 00172 template<size_t sz> class array_reverse { 00173 00174 #ifndef DOXYGEN_INTERNAL 00175 00176 protected: 00177 00178 /// The array pointer 00179 double *a; 00180 00181 #endif 00182 00183 public: 00184 00185 /// Create a reversed array from \c arr of size \c sz 00186 array_reverse(double *arr) { 00187 a=arr; 00188 } 00189 00190 /** 00191 \brief Array-like indexing 00192 */ 00193 double &operator[](size_t i) { 00194 return a[sz-1-i]; 00195 } 00196 00197 /** 00198 \brief Array-like indexing 00199 */ 00200 const double &operator[](size_t i) const { 00201 return a[sz-1-i]; 00202 } 00203 00204 }; 00205 00206 /** 00207 \brief A simple class which reverses the order of an array 00208 00209 See an example of usage in <tt>interp_ts.cpp</tt> and 00210 <tt>smart_interp_ts.cpp</tt>. 00211 */ 00212 template<size_t sz> class array_const_reverse { 00213 00214 #ifndef DOXYGEN_INTERNAL 00215 00216 protected: 00217 00218 /// The array pointer 00219 double *a; 00220 00221 #endif 00222 00223 public: 00224 00225 /// Create a reversed array from \c arr of size \c sz 00226 array_const_reverse(const double *arr) { 00227 a=(double *)arr; 00228 } 00229 00230 /** 00231 \brief Array-like indexing 00232 */ 00233 const double &operator[](size_t i) const { 00234 return a[sz-1-i]; 00235 } 00236 00237 }; 00238 00239 /** 00240 \brief A simple subvector class for an array (without error checking) 00241 */ 00242 class array_subvector { 00243 00244 #ifndef DOXYGEN_INTERNAL 00245 00246 protected: 00247 00248 /// The array pointer 00249 double *a; 00250 00251 /// The offset 00252 size_t off; 00253 00254 /// The subvector length 00255 size_t len; 00256 00257 #endif 00258 00259 public: 00260 00261 /// Create a reversed array from \c arr of size \c sz 00262 array_subvector(double *arr, size_t offset, size_t n) { 00263 a=arr+offset; 00264 off=offset; 00265 len=n; 00266 } 00267 00268 /** 00269 \brief Array-like indexing 00270 */ 00271 double &operator[](size_t i) { 00272 return a[i]; 00273 } 00274 00275 /** 00276 \brief Array-like indexing 00277 */ 00278 const double &operator[](size_t i) const { 00279 return a[i]; 00280 } 00281 00282 }; 00283 00284 /** 00285 \brief Column of a 2d array 00286 00287 This works because two-dimensional arrays are always 00288 continguous (as indicated in appendix C of Soustroup's book). 00289 */ 00290 template<size_t R, size_t C, class data_t=double> class array_2d_col 00291 { 00292 00293 #ifndef DOXYGEN_INTERNAL 00294 00295 protected: 00296 00297 /// The array pointer 00298 data_t *a; 00299 00300 #endif 00301 00302 public: 00303 00304 /// Create an object as the <tt>i</tt>th column of \c mat 00305 array_2d_col(data_t mat[R][C], size_t i) { 00306 a=&(mat[0][i]); 00307 } 00308 00309 /** 00310 \brief Array-like indexing 00311 */ 00312 data_t &operator[](size_t i) { 00313 return a[R*i]; 00314 } 00315 00316 /** 00317 \brief Array-like indexing 00318 */ 00319 const data_t &operator[](size_t i) const { 00320 return a[R*i]; 00321 } 00322 00323 }; 00324 00325 /** 00326 \brief Row of a 2d array 00327 */ 00328 template<class array_2d_t, class data_t=double> class array_2d_row { 00329 00330 #ifndef DOXYGEN_INTERNAL 00331 00332 protected: 00333 00334 /// The array pointer 00335 data_t *a; 00336 00337 #endif 00338 00339 public: 00340 00341 /// Create an object as the <tt>i</tt>th row of \c mat 00342 array_2d_row(array_2d_t &mat, size_t i) { 00343 a=&(mat[i][0]); 00344 } 00345 00346 /** 00347 \brief Array-like indexing, returns the element in the <tt>i</tt>th 00348 column of the chosen row 00349 */ 00350 data_t &operator[](size_t i) { 00351 return a[i]; 00352 } 00353 00354 /** 00355 \brief Array-like indexing, returns the element in the <tt>i</tt>th 00356 column of the chosen row 00357 */ 00358 const data_t &operator[](size_t i) const { 00359 return a[i]; 00360 } 00361 00362 }; 00363 00364 /** \brief A simple subvector class for a const array 00365 (without error checking) 00366 00367 \future Make the member data truly const and remove 00368 the extra typecast. 00369 */ 00370 class array_const_subvector { 00371 00372 #ifndef DOXYGEN_INTERNAL 00373 00374 protected: 00375 00376 /// The array pointer 00377 double *a; 00378 00379 /// The offset 00380 size_t off; 00381 00382 /// The subvector length 00383 size_t len; 00384 00385 #endif 00386 00387 public: 00388 00389 /// Create a reversed array from \c arr of size \c sz 00390 array_const_subvector(const double *arr, size_t offset, size_t n) { 00391 a=(double *)arr+offset; 00392 off=offset; 00393 len=n; 00394 } 00395 00396 /** 00397 \brief Array-like indexing 00398 */ 00399 const double &operator[](size_t i) const { 00400 return a[i]; 00401 } 00402 00403 }; 00404 00405 /** 00406 \brief Reverse a subvector of an array 00407 */ 00408 class array_subvector_reverse { 00409 00410 #ifndef DOXYGEN_INTERNAL 00411 00412 protected: 00413 00414 /// The array pointer 00415 double *a; 00416 00417 /// The offset 00418 size_t off; 00419 00420 /// The subvector length 00421 size_t len; 00422 00423 #endif 00424 00425 public: 00426 00427 /// Create a reversed array from \c arr of size \c sz 00428 array_subvector_reverse(double *arr, size_t offset, size_t n) { 00429 a=arr+offset; 00430 off=offset; 00431 len=n; 00432 } 00433 00434 /** 00435 \brief Array-like indexing 00436 */ 00437 double &operator[](size_t i) { 00438 return a[len-1-i]; 00439 } 00440 00441 /** 00442 \brief Array-like indexing 00443 */ 00444 const double &operator[](size_t i) const { 00445 return a[len-1-i]; 00446 } 00447 00448 }; 00449 00450 /** 00451 \brief Reverse a subvector of a const array 00452 */ 00453 class array_const_subvector_reverse { 00454 00455 #ifndef DOXYGEN_INTERNAL 00456 00457 protected: 00458 00459 /// The array pointer 00460 double *a; 00461 00462 /// The offset 00463 size_t off; 00464 00465 /// The subvector length 00466 size_t len; 00467 00468 #endif 00469 00470 public: 00471 00472 /// Create a reversed array from \c arr of size \c sz 00473 array_const_subvector_reverse(const double *arr, size_t offset, size_t n) { 00474 a=(double *)arr+offset; 00475 off=offset; 00476 len=n; 00477 } 00478 00479 /** 00480 \brief Array-like indexing 00481 */ 00482 const double &operator[](size_t i) const { 00483 return a[len-1-i]; 00484 } 00485 00486 }; 00487 00488 /** 00489 \brief Create a new C-style 1-dimensional array 00490 00491 This function is convenient because it automatically calls the 00492 \o2 error handler in case the allocation fails. 00493 */ 00494 template<class type> type *new_array(size_t n) { 00495 if (n==0) { 00496 O2SCL_ERR2("Tried to allocate array of size zero ", 00497 "in new_array().",gsl_einval); 00498 return 0; 00499 } 00500 type *t=new(std::nothrow) type[n]; 00501 if (t==0) O2SCL_ERR("Allocation failed in new_array().",gsl_enomem); 00502 return t; 00503 } 00504 00505 /** 00506 \brief Free the memory for a C-style 1-dimensional array 00507 00508 This function never calls the error handler, but may create 00509 a segmentation fault if improperly called multiple times. 00510 */ 00511 template<class type> void delete_array(type *t) { 00512 delete[] t; 00513 return; 00514 } 00515 00516 /** 00517 \brief Create a new C-style 2-dimensional array 00518 00519 This function is convenient because it automatically calls the 00520 \o2 error handler in case the allocation fails, and will free 00521 the portions of the memory which were successfully allocated. 00522 */ 00523 template<class type> type **new_2d_array(size_t nr, size_t nc) { 00524 if (nr==0 || nc==0) { 00525 O2SCL_ERR2("Tried to allocate 2-d array of size zero ", 00526 "in new_2d_array().",gsl_einval); 00527 return 0; 00528 } 00529 type **t; 00530 t=new(std::nothrow) type *[nr]; 00531 if (t==0) O2SCL_ERR("Allocation failed in new_2d_array().",gsl_enomem); 00532 for(size_t i=0;i<nr;i++) { 00533 t[i]=new(std::nothrow) type[nc]; 00534 if (t[i]==0) { 00535 for(size_t j=0;j<i;j++) delete[] t[j]; 00536 delete[] t; 00537 O2SCL_ERR("Allocation failed in new_2d_array().",gsl_enomem); 00538 return 0; 00539 } 00540 } 00541 return t; 00542 } 00543 00544 /** 00545 \brief Free the memory for a C-style 2-dimensional array 00546 00547 This function never calls the error handler, but may create 00548 a segmentation fault if improperly called multiple times. 00549 */ 00550 template<class type> void delete_2d_array(type **t, size_t nr) { 00551 for(size_t i=0;i<nr;i++) delete[] t[i]; 00552 delete[] t; 00553 return; 00554 } 00555 00556 #ifndef DOXYGENP 00557 } 00558 #endif 00559 00560 #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