![]() |
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_SMART_INTERP_H 00024 #define O2SCL_SMART_INTERP_H 00025 00026 /** \file smart_interp.h 00027 \brief File for "smart" interpolation routines 00028 00029 In addition to the smart interpolation routines, this file 00030 contains the template functions \ref vector_find_level(), \ref 00031 vector_integ_linear() and \ref vector_invert_enclosed_sum(). 00032 */ 00033 00034 #include <o2scl/interp.h> 00035 #include <o2scl/vector.h> 00036 00037 #ifndef DOXYGENP 00038 namespace o2scl { 00039 #endif 00040 00041 /** \brief Smart interpolation class 00042 00043 This class can semi-intelligently handle arrays which are 00044 not-well formed outside the interpolation region. In particular, 00045 if an initial interpolation or derivative calculation fails, the 00046 arrays are searched for the largest neighborhood around the 00047 point \c x for which an interpolation or differentiation will 00048 likely produce a finite result. 00049 */ 00050 template<class vec_t=ovector_const_view, 00051 class svec_t=ovector_const_subvector> class smart_interp { 00052 00053 #ifndef DOXYGEN_INTERNAL 00054 00055 protected: 00056 00057 /// \name Storage internally created subvectors 00058 //@{ 00059 bool sxalloc; 00060 const svec_t *sx; 00061 const svec_t *sy; 00062 //@} 00063 00064 /// \name Pointers to interpolation objects 00065 //@{ 00066 base_interp<vec_t> *rit1; 00067 base_interp<svec_t> *rit3; 00068 //@} 00069 00070 /// \name Pointers to interpolation managers 00071 //@{ 00072 base_interp_mgr<vec_t> *bim1; 00073 base_interp_mgr<svec_t> *bim3; 00074 //@} 00075 00076 #endif 00077 00078 public: 00079 00080 /** \brief Create a new interpolation object with the specified 00081 interpolation managers 00082 */ 00083 smart_interp(base_interp_mgr<vec_t> &im1, 00084 base_interp_mgr<svec_t> &im3) { 00085 00086 sxalloc=false; 00087 sx=0; 00088 sy=0; 00089 00090 bim1=&im1; 00091 bim3=&im3; 00092 00093 rit1=bim1->new_interp(); 00094 rit3=bim3->new_interp(); 00095 }; 00096 00097 /** \brief Create an interpolation object with the default 00098 cubic spline interpolation managers 00099 */ 00100 smart_interp() { 00101 sxalloc=false; 00102 sx=0; 00103 sy=0; 00104 00105 bim1=&dim1; 00106 bim3=&dim3; 00107 00108 rit1=bim1->new_interp(); 00109 rit3=bim3->new_interp(); 00110 }; 00111 00112 virtual ~smart_interp() { 00113 if (sxalloc) { 00114 delete sx; 00115 delete sy; 00116 } 00117 00118 /* 00119 We don't want to use "bim1->free_interp(rit1)" here instead 00120 of "delete rit1" because the pointer "bim1" may refer to 00121 a user-defined interpolation manager, and it may have gone 00122 out of scope earlier. 00123 */ 00124 delete rit1; 00125 delete rit3; 00126 } 00127 00128 /** \brief Give the value of the function \f$ y(x=x_0) \f$ . 00129 00130 \todo After calling find_subset, I think we might need 00131 to double check that \c nn is larger than the minimum 00132 interpolation size. 00133 */ 00134 virtual double interp(const double x0, size_t n, const vec_t &x, 00135 const vec_t &y) { 00136 00137 bool to_subset=false; 00138 double ret=0.0; 00139 int err0, err1, err2; 00140 00141 if (x[0]==x[n-1]) { 00142 to_subset=true; 00143 } 00144 00145 if (n<rit1->min_size) { 00146 O2SCL_ERR("Vector size too small in interp().",gsl_edom); 00147 return 0.0; 00148 } 00149 err0=rit1->allocate(n); 00150 if (err0==0) { 00151 err1=rit1->init(x,y,n); 00152 if (err1==0) { 00153 err2=rit1->interp(x,y,n,x0,ret); 00154 if (err2!=0) to_subset=true; 00155 } else { 00156 to_subset=true; 00157 } 00158 rit1->free(); 00159 } 00160 00161 if (!gsl_finite(ret)) to_subset=true; 00162 00163 if (to_subset) { 00164 00165 size_t nn=0; 00166 int retfs=find_subset(x0,x0,n,x,y,nn); 00167 00168 if (retfs!=0 || nn<=1) { 00169 O2SCL_ERR("Interpolation failed in interp().",gsl_efailed); 00170 return 0; 00171 } 00172 00173 if (nn>=rit3->min_size) { 00174 err0=rit3->allocate(nn); 00175 if (err0==0) { 00176 err1=rit3->init(*sx,*sy,nn); 00177 if (err1==0) { 00178 err2=rit3->interp(*sx,*sy,nn,x0,ret); 00179 } 00180 rit3->free(); 00181 } 00182 } else { 00183 O2SCL_ERR("Interpolation failed in interp().",gsl_efailed); 00184 } 00185 00186 } 00187 00188 return ret; 00189 } 00190 00191 /// Give the value of the derivative \f$ y^{prime}(x=x_0) \f$ . 00192 virtual double deriv(const double x0, size_t n, const vec_t &x, 00193 const vec_t &y) { 00194 00195 bool increasing=true, to_subset=false; 00196 double ret=0.0; 00197 int err0, err1, err2; 00198 00199 if (x[0]==x[n-1]) { 00200 to_subset=true; 00201 } 00202 00203 if (n<rit1->min_size) { 00204 O2SCL_ERR("Vector size too small in deriv().",gsl_edom); 00205 return 0.0; 00206 } 00207 err0=rit1->allocate(n); 00208 if (err0==0) { 00209 err1=rit1->init(x,y,n); 00210 if (err1==0) { 00211 err2=rit1->deriv(x,y,n,x0,ret); 00212 if (err2!=0) to_subset=true; 00213 } else { 00214 to_subset=true; 00215 } 00216 rit1->free(); 00217 } 00218 00219 if (!gsl_finite(ret)) to_subset=true; 00220 00221 if (to_subset) { 00222 00223 size_t nn=0; 00224 int retfs=find_subset(x0,x0,n,x,y,nn); 00225 00226 if (retfs!=0 || nn<=1) { 00227 O2SCL_ERR("Interpolation failed in deriv().",gsl_efailed); 00228 return 0; 00229 } 00230 00231 if (nn>=rit3->min_size) { 00232 err0=rit3->allocate(nn); 00233 if (err0==0) { 00234 err1=rit3->init(*sx,*sy,nn); 00235 if (err1==0) { 00236 err2=rit3->deriv(*sx,*sy,nn,x0,ret); 00237 } 00238 rit3->free(); 00239 } 00240 } else { 00241 O2SCL_ERR("Interpolation failed in deriv().",gsl_efailed); 00242 } 00243 00244 } 00245 00246 return ret; 00247 } 00248 00249 /** \brief Give the value of the second derivative 00250 \f$ y^{prime \prime}(x=x_0) \f$ . 00251 */ 00252 virtual double deriv2(const double x0, size_t n, const vec_t &x, 00253 const vec_t &y) { 00254 00255 bool increasing=true, to_subset=false; 00256 double ret=0.0; 00257 int err0, err1, err2; 00258 00259 if (x[0]==x[n-1]) { 00260 to_subset=true; 00261 } 00262 00263 if (n<rit1->min_size) { 00264 O2SCL_ERR("Vector size too small in deriv2().",gsl_edom); 00265 return 0.0; 00266 } 00267 err0=rit1->allocate(n); 00268 if (err0==0) { 00269 err1=rit1->init(x,y,n); 00270 if (err1==0) { 00271 err2=rit1->deriv2(x,y,n,x0,ret); 00272 if (err2!=0) to_subset=true; 00273 } else { 00274 to_subset=true; 00275 } 00276 rit1->free(); 00277 } 00278 00279 if (!gsl_finite(ret)) to_subset=true; 00280 00281 if (to_subset) { 00282 00283 size_t nn=0; 00284 int retfs=find_subset(x0,x0,n,x,y,nn); 00285 00286 if (retfs!=0 || nn<=1) { 00287 O2SCL_ERR("Interpolation failed in deriv2().",gsl_efailed); 00288 return 0; 00289 } 00290 00291 if (nn>=rit3->min_size) { 00292 err0=rit3->allocate(nn); 00293 if (err0==0) { 00294 err1=rit3->init(*sx,*sy,nn); 00295 if (err1==0) { 00296 err2=rit3->deriv2(*sx,*sy,nn,x0,ret); 00297 } 00298 rit3->free(); 00299 } 00300 } else { 00301 O2SCL_ERR("Interpolation failed in deriv2().",gsl_efailed); 00302 } 00303 00304 } 00305 00306 return ret; 00307 } 00308 00309 /// Give the value of the integral \f$ \int_a^{b}y(x)~dx \f$ . 00310 virtual double integ(const double a, const double b, 00311 size_t n, const vec_t &x, const vec_t &y) { 00312 00313 bool increasing=true, to_subset=false; 00314 double ret=0.0; 00315 int err0, err1, err2; 00316 00317 if (x[0]==x[n-1]) { 00318 to_subset=true; 00319 } 00320 00321 if (n<rit1->min_size) { 00322 O2SCL_ERR("Vector size too small in integ().",gsl_edom); 00323 return 0.0; 00324 } 00325 err0=rit1->allocate(n); 00326 if (err0==0) { 00327 err1=rit1->init(x,y,n); 00328 if (err1==0) { 00329 err2=rit1->integ(x,y,n,a,b,ret); 00330 if (err2!=0) to_subset=true; 00331 } else { 00332 to_subset=true; 00333 } 00334 rit1->free(); 00335 } 00336 00337 if (!gsl_finite(ret)) to_subset=true; 00338 00339 if (to_subset) { 00340 00341 size_t nn=0; 00342 int retfs=find_subset(a,b,n,x,y,nn); 00343 00344 if (retfs!=0 || nn<=1) { 00345 O2SCL_ERR("Interpolation failed in integ().",gsl_efailed); 00346 return 0; 00347 } 00348 00349 00350 if (nn>=rit3->min_size) { 00351 err0=rit3->allocate(nn); 00352 if (err0==0) { 00353 err1=rit3->init(*sx,*sy,nn); 00354 if (err1==0) { 00355 err2=rit3->integ(*sx,*sy,nn,a,b,ret); 00356 } 00357 rit3->free(); 00358 } 00359 } else { 00360 O2SCL_ERR("Interpolation failed in integ().",gsl_efailed); 00361 } 00362 00363 } 00364 00365 return ret; 00366 } 00367 00368 /// \name Default interpolation managers 00369 //@{ 00370 def_interp_mgr<vec_t,cspline_interp> dim1; 00371 def_interp_mgr<svec_t,cspline_interp> dim3; 00372 //@} 00373 00374 #ifndef DOXGYEN_INTERNAL 00375 00376 protected: 00377 00378 /** \brief A lookup function for generic vectors 00379 */ 00380 size_t local_lookup(size_t n, const vec_t &x, double x0) { 00381 size_t row=0, i=0; 00382 while(!gsl_finite(x[i]) && i<n-1) i++; 00383 if (i==n-1) { 00384 return 0; 00385 } 00386 double best=x[i], bdiff=fabs(x[i]-x0); 00387 for(;i<n;i++) { 00388 if (gsl_finite(x[i]) && fabs(x[i]-x0)<bdiff) { 00389 row=i; 00390 best=x[i]; 00391 bdiff=fabs(x[i]-x0); 00392 } 00393 } 00394 return row; 00395 } 00396 00397 /** \brief Try to find the largest monotonic and finite region 00398 around the desired location 00399 00400 This function tries to find the largest monotonic region 00401 enclosing both \c a and \c b in the vector \c x. If it succeeds, 00402 it returns \ref gsl_success, and if it fails, it returns \ref 00403 gsl_efailed. It does not call the error handler. 00404 00405 \todo The error handling is a bit off here, as it can return 00406 a non-zero value even with there is no real "error". We should 00407 just make a new bool reference paramter. 00408 */ 00409 int find_subset(const double a, const double b, size_t sz, const vec_t &x, 00410 const vec_t &y, size_t &nsz) 00411 { 00412 00413 size_t left, right; 00414 00415 bool increasing=true; 00416 if (x[0]>x[sz-1]) increasing=false; 00417 00418 // Lookup the point 00419 size_t row=local_lookup(sz,x,a); 00420 if (!gsl_finite(x[row]) || !gsl_finite(y[row])) { 00421 return gsl_efailed; 00422 } 00423 size_t row2=local_lookup(sz,x,b); 00424 if (!gsl_finite(x[row2]) || !gsl_finite(y[row2])) { 00425 return gsl_efailed; 00426 } 00427 00428 // Get a neighboring point if necessary 00429 if (row2==row) { 00430 row2=row++; 00431 if (row2>=sz) row2=row-1; 00432 } 00433 00434 // Arrange 00435 if (row<row2) { 00436 left=row; 00437 right=row2; 00438 } else { 00439 left=row2; 00440 right=row; 00441 } 00442 00443 // Establish whether we're increasing or decreasing 00444 increasing=true; 00445 if (row2<row && x[row]<x[row2]) increasing=false; 00446 if (row2>row && x[row2]<x[row]) increasing=false; 00447 00448 // Check region between row and row2 00449 00450 if (increasing) { 00451 size_t lo, hi; 00452 if (row2<row) { 00453 lo=row2; 00454 hi=row; 00455 } else { 00456 lo=row; 00457 hi=row2; 00458 } 00459 for(size_t i=lo;i<hi-1;i++) { 00460 if (x[i]>x[i+1]) return gsl_efailed; 00461 } 00462 } else { 00463 size_t lo, hi; 00464 if (row2<row) { 00465 lo=row2; 00466 hi=row; 00467 } else { 00468 lo=row; 00469 hi=row2; 00470 } 00471 for(size_t i=lo;i<hi-1;i++) { 00472 if (x[i]<x[i+1]) return gsl_efailed; 00473 } 00474 } 00475 00476 // Increasing case 00477 00478 if (increasing) { 00479 00480 while(left>0 && x[left-1]<x[left] && 00481 gsl_finite(x[left-1]) && gsl_finite(y[left-1])) left--; 00482 while(right<sz-1 && x[right]<x[right+1] && 00483 gsl_finite(x[right+1]) && gsl_finite(y[right+1])) right++; 00484 00485 nsz=right-left+1; 00486 00487 if (sxalloc) { 00488 delete sx; 00489 delete sy; 00490 } 00491 sx=new svec_t(x,left,nsz); 00492 sy=new svec_t(y,left,nsz); 00493 sxalloc=true; 00494 00495 } else { 00496 00497 while(left>0 && x[left-1]>x[left] && 00498 gsl_finite(x[left-1]) && gsl_finite(y[left-1])) left--; 00499 while(right<sz-1 && x[right]>x[right+1] && 00500 gsl_finite(x[right+1]) && gsl_finite(y[right+1])) right++; 00501 00502 nsz=right-left+1; 00503 00504 if (sxalloc==true) { 00505 delete sx; 00506 delete sy; 00507 } 00508 sx=new svec_t(x,left,nsz); 00509 sy=new svec_t(y,left,nsz); 00510 sxalloc=true; 00511 00512 } 00513 00514 return 0; 00515 } 00516 00517 #endif 00518 00519 }; 00520 00521 /** \brief Smart interpolation class with pre-specified vectors 00522 00523 This class can semi-intelligently handle arrays which are 00524 not-well formed outside the interpolation region. In particular, 00525 if an initial interpolation or derivative calculation fails, the 00526 arrays are searched for the largest neighborhood around the 00527 point \c x for which an interpolation or differentiation will 00528 likely produce a finite result. 00529 00530 \future Properly implement handling of non-monotonic regions in 00531 the derivative functions as well as the interpolation function. 00532 */ 00533 template<class vec_t, class svec_t, class alloc_vec_t, class alloc_t> 00534 class smart_interp_vec { 00535 00536 #ifndef DOXYGEN_INTERNAL 00537 00538 protected: 00539 00540 /// If true, then \ref sx and \ref sy have been allocated 00541 bool sxalloc; 00542 /// Storage for internally created subvector 00543 svec_t *sx; 00544 /// Storage for internally created subvector 00545 svec_t *sy; 00546 00547 /// Pointer to base interpolation object 00548 base_interp<vec_t> *rit1; 00549 /// Pointer to base interpolation object 00550 base_interp<svec_t> *rit2; 00551 00552 /// Pointer to base interpolation manager 00553 base_interp_mgr<vec_t> *bim1; 00554 00555 /// Pointer to base interpolation manager 00556 base_interp_mgr<svec_t> *bim2; 00557 00558 /// Memory allocator for objects of type \c alloc_vec_t 00559 alloc_t ao; 00560 00561 /// True if the user-specified x vector is increasing 00562 bool inc; 00563 00564 /// Pointer to user-specified vector 00565 const vec_t *lx; 00566 /// Pointer to user-specified vector 00567 const vec_t *ly; 00568 00569 /// Size of user-specifed vector 00570 size_t ln; 00571 00572 #endif 00573 00574 public: 00575 00576 /// Create with base interpolation objects \c it and \c rit 00577 smart_interp_vec(size_t n, const vec_t &x, const vec_t &y) { 00578 sx=0; 00579 sy=0; 00580 sxalloc=false; 00581 00582 bim1=&dim1; 00583 bim2=&dim2; 00584 00585 rit1=bim1->new_interp(); 00586 rit2=bim2->new_interp(); 00587 ln=0; 00588 00589 if (n<rit1->min_size || n<rit2->min_size) { 00590 O2SCL_ERR("Vector size too small in o2scl_interp_vec().",gsl_edom); 00591 } else { 00592 00593 int r1=rit1->allocate(n); 00594 if (r1==0) { 00595 rit1->init(x,y,n); 00596 ln=n; 00597 lx=&x; 00598 ly=&y; 00599 inc=true; 00600 } 00601 00602 } 00603 00604 } 00605 00606 /// Create with base interpolation objects \c it and \c rit 00607 smart_interp_vec(base_interp_mgr<vec_t> &it1, 00608 base_interp_mgr<svec_t> &it2, 00609 size_t n, const vec_t &x, const vec_t &y) { 00610 sx=0; 00611 sy=0; 00612 sxalloc=false; 00613 00614 bim1=&it1; 00615 bim2=&it2; 00616 00617 rit1=bim1->new_interp(); 00618 rit2=bim2->new_interp(); 00619 ln=0; 00620 00621 if (n<rit1->min_size || n<rit2->min_size) { 00622 O2SCL_ERR("Vector size too small in o2scl_interp_vec().",gsl_edom); 00623 } else { 00624 00625 int r1=rit1->allocate(n); 00626 if (r1==0) { 00627 rit1->init(x,y,n); 00628 ln=n; 00629 lx=&x; 00630 ly=&y; 00631 inc=true; 00632 } 00633 00634 } 00635 00636 } 00637 00638 virtual ~smart_interp_vec() { 00639 if (sxalloc) { 00640 delete sx; 00641 delete sy; 00642 } 00643 00644 if (ln>0) { 00645 rit1->free(); 00646 } 00647 00648 /* 00649 We don't want to use "bim1->free_interp(rit1)" here instead 00650 of "delete rit1" because the pointer "bim1" may refer to 00651 a user-defined interpolation manager, and it may have gone 00652 out of scope earlier. 00653 */ 00654 delete rit1; 00655 delete rit2; 00656 } 00657 00658 /// Give the value of the function \f$ y(x=x_0) \f$ . 00659 virtual double operator()(const double x0) { 00660 return interp(x0); 00661 } 00662 00663 /// Give the value of the function \f$ y(x=x_0) \f$ . 00664 virtual double interp(const double x0) { 00665 00666 double ret=0.0; 00667 int err; 00668 if (ln>0) { 00669 00670 err=rit1->interp(*lx,*ly,ln,x0,ret); 00671 if (err!=gsl_success) { 00672 size_t nn=0; 00673 int retfs=find_inc_subset(x0,ln,*lx,*ly,nn); 00674 00675 if (retfs==0 && nn>1 && nn>=rit2->min_size) { 00676 rit2->allocate(nn); 00677 rit2->init(*sx,*sy,nn); 00678 err=rit2->interp(*sx,*sy,nn,x0,ret); 00679 rit2->free(); 00680 } else { 00681 O2SCL_ERR2("Interpolation failed in ", 00682 "smart_interp_vec::interp().",gsl_efailed); 00683 return 0.0; 00684 } 00685 00686 } 00687 00688 } 00689 00690 return ret; 00691 } 00692 00693 /// Give the value of the derivative \f$ y^{prime}(x=x_0) \f$ . 00694 virtual double deriv(const double x0) { 00695 double ret=0.0; 00696 if (ln>0) { 00697 rit1->deriv(*lx,*ly,ln,x0,ret); 00698 } 00699 return ret; 00700 } 00701 00702 /** \brief Give the value of the second derivative 00703 \f$ y^{prime \prime}(x=x_0) \f$ . 00704 */ 00705 virtual double deriv2(const double x0) { 00706 double ret=0.0; 00707 if (ln>0) { 00708 rit1->deriv2(*lx,*ly,ln,x0,ret); 00709 } 00710 return ret; 00711 } 00712 00713 /// Give the value of the integral \f$ \int_a^{b}y(x)~dx \f$ . 00714 virtual double integ(const double x1, const double x2) { 00715 double ret=0.0; 00716 if (ln>0) { 00717 rit1->integ(*lx,*ly,ln,x1,x2,ret); 00718 } 00719 return ret; 00720 } 00721 00722 /// Default interpolation manager 00723 def_interp_mgr<vec_t,cspline_interp> dim1; 00724 00725 /// Default interpolation manager 00726 def_interp_mgr<svec_t,cspline_interp> dim2; 00727 00728 #ifndef DOXYGEN_INTERNAL 00729 00730 protected: 00731 00732 /// A lookup function for generic vectors 00733 size_t local_lookup(size_t n, const vec_t &x, double x0) { 00734 size_t row=0, i=0; 00735 while(!gsl_finite(x[i]) && i<n-1) i++; 00736 if (i==n-1) { 00737 return 0; 00738 } 00739 double best=x[i], bdiff=fabs(x[i]-x0); 00740 for(;i<n;i++) { 00741 if (gsl_finite(x[i]) && fabs(x[i]-x0)<bdiff) { 00742 row=i; 00743 best=x[i]; 00744 bdiff=fabs(x[i]-x0); 00745 } 00746 } 00747 return row; 00748 } 00749 00750 /** \brief Try to find the largest monotonically increasing and 00751 finite region around the desired location 00752 00753 This function looks through the vector \c x near the element 00754 closest to \c x0 to find the largest possible monotonic 00755 region. If it succeeds, it returns \ref gsl_success, and if it 00756 fails, it returns \ref gsl_efailed. It does not call the error 00757 handler. 00758 00759 \todo Variables \c row and \c row appear to be unused? (2/17/11) 00760 */ 00761 int find_inc_subset(const double x0, size_t sz, const vec_t &x, 00762 const vec_t &y, size_t &nsz) { 00763 00764 size_t row=local_lookup(sz,x,x0), row2=row++; 00765 size_t left=row, right=row; 00766 00767 if (row2>sz) row2=row-1; 00768 00769 if (!gsl_finite(x[row]) || !gsl_finite(y[row])) { 00770 return gsl_efailed; 00771 } 00772 00773 // Increasing case 00774 00775 while(left>0 && x[left-1]<x[left] && 00776 gsl_finite(x[left-1]) && gsl_finite(y[left-1])) left--; 00777 while(right<sz-1 && x[right]<x[right+1] && 00778 gsl_finite(x[right+1]) && gsl_finite(y[right+1])) right++; 00779 00780 nsz=right-left+1; 00781 00782 if (sxalloc) { 00783 delete sx; 00784 delete sy; 00785 } 00786 sx=new svec_t(x,left,nsz); 00787 sy=new svec_t(y,left,nsz); 00788 sxalloc=true; 00789 00790 return 0; 00791 } 00792 00793 #endif 00794 00795 }; 00796 00797 // sm_interp typedef 00798 typedef smart_interp<ovector_const_view, 00799 ovector_const_subvector> sm_interp; 00800 00801 // sm_interp_vec typedef 00802 typedef smart_interp_vec<ovector_const_view,ovector_const_subvector,ovector, 00803 ovector_alloc> sm_interp_vec; 00804 00805 /** \brief A specialization of smart_interp for C-style double arrays 00806 */ 00807 template<size_t n> class sma_interp : 00808 public smart_interp<double[n],array_const_subvector> { 00809 00810 public: 00811 00812 /** \brief Create an interpolation object with user-specified 00813 interpolation types 00814 */ 00815 sma_interp(base_interp_mgr<double[n]> &it1, 00816 base_interp_mgr<array_const_subvector> &it3) : 00817 smart_interp<double[n],array_const_subvector>(it1,it3) { 00818 } 00819 00820 /// Create an interpolation object with the default interpolation types 00821 sma_interp() : smart_interp<double[n],array_const_subvector>() { 00822 } 00823 00824 }; 00825 00826 /** \brief A specialization of smart_interp_vec for C-style double arrays 00827 */ 00828 template<class arr_t> class sma_interp_vec : 00829 public smart_interp_vec<arr_t,array_const_subvector,arr_t, 00830 array_alloc<arr_t> > 00831 { 00832 00833 public: 00834 00835 00836 /** \brief Create an interpolation object with user-specified 00837 interpolation types 00838 */ 00839 sma_interp_vec(base_interp_mgr<arr_t> &it, 00840 base_interp_mgr<array_const_subvector> &it2, 00841 size_t n, const arr_t &x, const arr_t &y) : 00842 smart_interp_vec<arr_t,array_const_subvector,arr_t, 00843 array_alloc<arr_t> >(it,it2,n,x,y) { 00844 } 00845 00846 /// Create an interpolation object with the default interpolation types 00847 sma_interp_vec(size_t n, const arr_t &x, const arr_t &y) : 00848 smart_interp_vec<arr_t,array_const_subvector,arr_t, 00849 array_alloc<arr_t> >(n,x,y) { 00850 } 00851 00852 }; 00853 00854 /** \brief Perform inverse linear interpolation 00855 00856 This function performs inverse linear interpolation of the data 00857 defined by \c x and \c y, finding all points in \c x which have 00858 the property \f$ \mathrm{level} = y(x) \f$. All points for which 00859 this relation holds are put into the vector \c locs. The 00860 previous information contained in vector \c locs before the 00861 function call is destroyed. 00862 00863 This is the 1-dimensional analog of finding contour levels as 00864 the \ref contour class does for 2 dimensions. 00865 */ 00866 template<class vec_t, class vec2_t> int vector_find_level 00867 (double level, size_t n, vec_t &x, vec2_t &y, ovector &locs) { 00868 00869 if (n<=1) { 00870 O2SCL_ERR2_RET("Need at least two data points in ", 00871 "vector_find_level().",gsl_einval); 00872 } 00873 00874 // Ensure that the location vector is empty 00875 locs.free(); 00876 00877 // Find intersections 00878 for(size_t i=0;i<n-1;i++) { 00879 00880 if ((y[i]<level && y[i+1]>=level) || 00881 (y[i]>level && y[i+1]<=level)) { 00882 // For each intersection, add the location using linear 00883 // interpolation 00884 double x0=x[i]+(x[i+1]-x[i])*(level-y[i])/(y[i+1]-y[i]); 00885 locs.push_back(x0); 00886 } 00887 } 00888 00889 return 0; 00890 } 00891 00892 /// Compute the integral over <tt>y(x)</tt> using linear interpolation 00893 template<class vec_t> double vector_integ_linear(size_t n, vec_t &x, 00894 vec_t &y) { 00895 00896 // Linear interpolation managers 00897 def_interp_mgr<vec_t,linear_interp> lint1; 00898 00899 // Interpolation object 00900 o2scl_interp<vec_t> si(lint1); 00901 00902 // Compute full integral 00903 double total=si.integ(x[0],x[n-1],n,x,y); 00904 00905 return total; 00906 } 00907 00908 /** \brief Compute the endpoints which enclose the regions whose 00909 integral is equal to \c sum 00910 00911 Defining a new function, \f$ g(y_0) \f$ which takes as input any 00912 y-value, \f$ y_0 \f$ from the function \f$ y(x) \f$ (specified 00913 with the parameters \c x and \c y) and outputs the integral of 00914 the function \f$ y(x) \f$ over all regions where \f$ y(x) > y_0 00915 \f$. This function inverts \f$ g(y) \f$, taking the value 00916 of an integral as input, and returns the corresponding y-value 00917 in the variable \c lev. 00918 00919 In order to make sure that the intepretation of the integral is 00920 unambiguous, this function requires that the first and last values 00921 of \c y are equal, i.e. <tt>y[0]==y[n-1]</tt>. 00922 00923 This function is particularly useful, for example, in computing 00924 the region which defines 68\% around a peak of data, thus 00925 providing approximate \f$ 1~\sigma \f$ limits. 00926 00927 Linear interpolation is used to describe the function \f$ g \f$, 00928 and the precision of this function is limited by this assumption. 00929 This function may also sometimes fail if \c sum is very close to 00930 the minimum or maximum value of the function \f$ g \f$. 00931 00932 \comment 00933 Note that the two vector types for x and y must be the 00934 same in order to use o2scl_interp. 00935 \endcomment 00936 */ 00937 template<class vec_t> int vector_invert_enclosed_sum 00938 (double sum, size_t n, vec_t &x, vec_t &y, double &lev) { 00939 00940 if (n<=1) { 00941 O2SCL_ERR2_RET("Need at least two data points in ", 00942 "vector_invert_enclosed_sum().",gsl_einval); 00943 } 00944 00945 if (y[0]!=y[n-1]) { 00946 O2SCL_ERR2_RET("The first and last y-values must be equal in ", 00947 "vector_invert_enclosed_sum().",gsl_einval); 00948 } 00949 00950 // Construct a sorted list of function values 00951 ovector ysort(n); 00952 vector_copy(n,y,ysort); 00953 vector_sort<ovector,double>(ysort.size(),ysort); 00954 00955 // Create list of y-values to perform y-value and integral 00956 // interpolation. We choose values in between the grid points to 00957 // ensure that we don't accidentally land precisely on a peak or 00958 // valley. 00959 ovector ylist; 00960 for(size_t i=0;i<ysort.size()-1;i++) { 00961 if (ysort[i]!=ysort[i+1]) { 00962 ylist.push_back((ysort[i+1]+3.0*ysort[i])/4.0); 00963 ylist.push_back((ysort[i+1]*3.0+ysort[i])/4.0); 00964 } 00965 } 00966 00967 // Linear interpolation managers 00968 def_interp_mgr<vec_t,linear_interp> lint1; 00969 def_interp_mgr<ovector,linear_interp> mint1; 00970 00971 // Interpolation objects. We need two, one for the 00972 // user-specified vector type, and one for ovectors 00973 o2scl_interp<vec_t> si(lint1); 00974 o2scl_interp<ovector> si2(mint1); 00975 00976 // Construct vectors for interpolation 00977 ovector xi, yi; 00978 00979 size_t nfail=0; 00980 00981 for(size_t k=0;k<ylist.size();k++) { 00982 double lev_tmp=ylist[k]; 00983 ovector locs; 00984 vector_find_level(lev_tmp,n,x,y,locs); 00985 if ((locs.size()%2)!=0) { 00986 nfail++; 00987 } else { 00988 double sum_temp=0.0; 00989 for(size_t i=0;i<locs.size()/2;i++) { 00990 double x0=locs[2*i]; 00991 double x1=locs[2*i+1]; 00992 sum_temp+=si.integ(x0,x1,n,x,y); 00993 } 00994 xi.push_back(sum_temp); 00995 yi.push_back(lev_tmp); 00996 } 00997 } 00998 if (nfail>10) { 00999 O2SCL_ERR2_RET("More than 10 failures in ", 01000 "vector_invert_enclosed_sum().",gsl_einval); 01001 } 01002 01003 lev=si2.interp(sum,xi.size(),xi,yi); 01004 01005 return 0; 01006 } 01007 01008 #ifndef DOXYGENP 01009 } 01010 #endif 01011 01012 #endif
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).