00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 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 #include <o2scl/interp.h> 00027 00028 #ifndef DOXYGENP 00029 namespace o2scl { 00030 #endif 00031 00032 /** 00033 \brief Smart interpolation class 00034 00035 This class can semi-intelligently handle arrays which are 00036 not-well formed outside the interpolation region. In particular, 00037 if an initial interpolation or derivative calculation fails, the 00038 arrays are searched for the largest neighborhood around the 00039 point \c x for which an interpolation or differentiation will 00040 likely produce a finite result. 00041 00042 */ 00043 template<class vec_t=ovector_view, 00044 class rvec_t=ovector_const_reverse, 00045 class svec_t=ovector_const_subvector, 00046 class srvec_t=ovector_const_subvector_reverse> class smart_interp { 00047 00048 #ifndef DOXYGEN_INTERNAL 00049 00050 protected: 00051 00052 /// \name Storage internally created subvectors 00053 //@{ 00054 const svec_t *sx; 00055 const svec_t *sy; 00056 00057 const srvec_t *srx; 00058 const srvec_t *sry; 00059 //@} 00060 00061 /// \name Pointers to interpolation objects 00062 //@{ 00063 base_interp<vec_t> *rit1; 00064 base_interp<rvec_t> *rit2; 00065 base_interp<svec_t> *rit3; 00066 base_interp<srvec_t> *rit4; 00067 //@} 00068 00069 #endif 00070 00071 public: 00072 00073 smart_interp(base_interp<vec_t> &it1, base_interp<rvec_t> &it2, 00074 base_interp<svec_t> &it3, base_interp<srvec_t> &it4) { 00075 sx=0; 00076 sy=0; 00077 srx=0; 00078 sry=0; 00079 00080 rit1=&it1; 00081 rit2=&it2; 00082 rit3=&it3; 00083 rit4=&it4; 00084 }; 00085 00086 smart_interp() { 00087 sx=0; 00088 sy=0; 00089 srx=0; 00090 sry=0; 00091 00092 rit1=&cit1; 00093 rit2=&cit2; 00094 rit3=&cit3; 00095 rit4=&cit4; 00096 }; 00097 00098 virtual ~smart_interp() { 00099 delete sx; 00100 delete sy; 00101 delete srx; 00102 delete sry; 00103 } 00104 00105 /// \name Default interpolation objects 00106 //@{ 00107 cspline_interp<vec_t> cit1; 00108 cspline_interp<rvec_t> cit2; 00109 cspline_interp<svec_t> cit3; 00110 cspline_interp<srvec_t> cit4; 00111 //@} 00112 00113 /// Give the value of the function \f$ y(x=x_0) \f$ . 00114 virtual double interp(const double x0, size_t n, const vec_t &x, 00115 const vec_t &y) { 00116 00117 bool increasing=true, to_subset=false; 00118 double ret=0.0; 00119 int err0, err1, err2; 00120 00121 err_hnd->reset(); 00122 00123 // Determine if array is increasing or decreasing 00124 00125 if (x[0]==x[n-1]) { 00126 to_subset=true; 00127 } else if (x[0]>x[n-1]) { 00128 increasing=false; 00129 } 00130 00131 if (increasing) { 00132 00133 if (n<rit1->min_size) { 00134 set_err("Vector size too small in interp().",gsl_edom); 00135 return 0.0; 00136 } 00137 err0=rit1->allocate(n); 00138 if (err0==0) { 00139 err1=rit1->init(x,y,n); 00140 if (err1==0) { 00141 err2=rit1->interp(x,y,n,x0,ret); 00142 if (err2!=0) to_subset=true; 00143 } else { 00144 to_subset=true; 00145 } 00146 rit1->free(); 00147 } 00148 00149 } else { 00150 00151 if (n<rit2->min_size) { 00152 set_err("Vector size too small in interp().",gsl_edom); 00153 return 0.0; 00154 } 00155 00156 rvec_t rx(x); 00157 rvec_t ry(y); 00158 00159 err0=rit2->allocate(n); 00160 if (err0==0) { 00161 err1=rit2->init(rx,ry,n); 00162 if (err1==0) { 00163 err2=rit2->interp(rx,ry,n,x0,ret); 00164 if (err2!=0) to_subset=true; 00165 } else { 00166 to_subset=true; 00167 } 00168 rit2->free(); 00169 } 00170 00171 } 00172 00173 if (!finite(ret)) to_subset=true; 00174 00175 if (to_subset) { 00176 00177 size_t nn=0; 00178 find_subset(x0,x0,n,x,y,nn,increasing); 00179 00180 if (nn<=1) { 00181 set_err("Interpolation failed in interp().",gsl_efailed); 00182 return 0; 00183 } 00184 00185 if (increasing) { 00186 if (nn>rit3->min_size) { 00187 err0=rit3->allocate(nn); 00188 if (err0==0) { 00189 err1=rit3->init(*sx,*sy,nn); 00190 if (err1==0) { 00191 err2=rit3->interp(*sx,*sy,nn,x0,ret); 00192 } 00193 rit3->free(); 00194 } 00195 } else { 00196 set_err("Interpolation failed in interp().",gsl_efailed); 00197 } 00198 } else { 00199 if (nn>rit4->min_size) { 00200 err0=rit4->allocate(nn); 00201 if (err0==0) { 00202 err1=rit4->init(*srx,*sry,nn); 00203 if (err1==0) { 00204 err2=rit4->interp(*srx,*sry,nn,x0,ret); 00205 } 00206 rit4->free(); 00207 } 00208 } else { 00209 set_err("Interpolation failed in interp().",gsl_efailed); 00210 } 00211 } 00212 00213 } 00214 00215 return ret; 00216 } 00217 00218 /// Give the value of the derivative \f$ y^{prime}(x=x_0) \f$ . 00219 virtual double deriv(const double x0, size_t n, const vec_t &x, 00220 const vec_t &y) { 00221 00222 bool increasing=true, to_subset=false; 00223 double ret=0.0; 00224 int err0, err1, err2; 00225 00226 err_hnd->reset(); 00227 00228 // Determine if array is increasing or decreasing 00229 00230 if (x[0]==x[n-1]) { 00231 to_subset=true; 00232 } else if (x[0]>x[n-1]) { 00233 increasing=false; 00234 } 00235 00236 if (increasing) { 00237 00238 if (n<rit1->min_size) { 00239 set_err("Vector size too small in deriv().",gsl_edom); 00240 return 0.0; 00241 } 00242 err0=rit1->allocate(n); 00243 if (err0==0) { 00244 err1=rit1->init(x,y,n); 00245 if (err1==0) { 00246 err2=rit1->deriv(x,y,n,x0,ret); 00247 if (err2!=0) to_subset=true; 00248 } else { 00249 to_subset=true; 00250 } 00251 rit1->free(); 00252 } 00253 00254 } else { 00255 00256 if (n<rit2->min_size) { 00257 set_err("Vector size too small in deriv().",gsl_edom); 00258 return 0.0; 00259 } 00260 00261 rvec_t rx(x); 00262 rvec_t ry(y); 00263 00264 err0=rit2->allocate(n); 00265 if (err0==0) { 00266 err1=rit2->init(rx,ry,n); 00267 if (err1==0) { 00268 err2=rit2->deriv(rx,ry,n,x0,ret); 00269 if (err2!=0) to_subset=true; 00270 } else { 00271 to_subset=true; 00272 } 00273 rit2->free(); 00274 } 00275 00276 } 00277 00278 if (!finite(ret)) to_subset=true; 00279 00280 if (to_subset) { 00281 00282 size_t nn=0; 00283 find_subset(x0,x0,n,x,y,nn,increasing); 00284 00285 if (nn<=1) { 00286 set_err("Interpolation failed in deriv().",gsl_efailed); 00287 return 0; 00288 } 00289 00290 if (increasing) { 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->deriv(*sx,*sy,nn,x0,ret); 00297 } 00298 rit3->free(); 00299 } 00300 } else { 00301 set_err("Interpolation failed in deriv().",gsl_efailed); 00302 } 00303 } else { 00304 if (nn>rit4->min_size) { 00305 err0=rit4->allocate(nn); 00306 if (err0==0) { 00307 err1=rit4->init(*srx,*sry,nn); 00308 if (err1==0) { 00309 err2=rit4->deriv(*srx,*sry,nn,x0,ret); 00310 } 00311 rit4->free(); 00312 } 00313 } else { 00314 set_err("Interpolation failed in deriv().",gsl_efailed); 00315 } 00316 } 00317 00318 } 00319 00320 return ret; 00321 } 00322 00323 /** \brief Give the value of the second derivative 00324 \f$ y^{prime \prime}(x=x_0) \f$ . 00325 */ 00326 virtual double deriv2(const double x0, size_t n, const vec_t &x, 00327 const vec_t &y) { 00328 00329 bool increasing=true, to_subset=false; 00330 double ret=0.0; 00331 int err0, err1, err2; 00332 00333 err_hnd->reset(); 00334 00335 // Determine if array is increasing or decreasing 00336 00337 if (x[0]==x[n-1]) { 00338 to_subset=true; 00339 } else if (x[0]>x[n-1]) { 00340 increasing=false; 00341 } 00342 00343 if (increasing) { 00344 00345 if (n<rit1->min_size) { 00346 set_err("Vector size too small in deriv2().",gsl_edom); 00347 return 0.0; 00348 } 00349 err0=rit1->allocate(n); 00350 if (err0==0) { 00351 err1=rit1->init(x,y,n); 00352 if (err1==0) { 00353 err2=rit1->deriv2(x,y,n,x0,ret); 00354 if (err2!=0) to_subset=true; 00355 } else { 00356 to_subset=true; 00357 } 00358 rit1->free(); 00359 } 00360 00361 } else { 00362 00363 if (n<rit2->min_size) { 00364 set_err("Vector size too small in deriv2().",gsl_edom); 00365 return 0.0; 00366 } 00367 00368 rvec_t rx(x); 00369 rvec_t ry(y); 00370 00371 err0=rit2->allocate(n); 00372 if (err0==0) { 00373 err1=rit2->init(rx,ry,n); 00374 if (err1==0) { 00375 err2=rit2->deriv2(rx,ry,n,x0,ret); 00376 if (err2!=0) to_subset=true; 00377 } else { 00378 to_subset=true; 00379 } 00380 rit2->free(); 00381 } 00382 00383 } 00384 00385 if (!finite(ret)) to_subset=true; 00386 00387 if (to_subset) { 00388 00389 size_t nn=0; 00390 find_subset(x0,x0,n,x,y,nn,increasing); 00391 00392 if (nn<=1) { 00393 set_err("Interpolation failed in deriv2().",gsl_efailed); 00394 return 0; 00395 } 00396 00397 if (increasing) { 00398 if (nn>rit3->min_size) { 00399 err0=rit3->allocate(nn); 00400 if (err0==0) { 00401 err1=rit3->init(*sx,*sy,nn); 00402 if (err1==0) { 00403 err2=rit3->deriv2(*sx,*sy,nn,x0,ret); 00404 } 00405 rit3->free(); 00406 } 00407 } else { 00408 set_err("Interpolation failed in deriv2().",gsl_efailed); 00409 } 00410 } else { 00411 if (nn>rit4->min_size) { 00412 err0=rit4->allocate(nn); 00413 if (err0==0) { 00414 err1=rit4->init(*srx,*sry,nn); 00415 if (err1==0) { 00416 err2=rit4->deriv2(*srx,*sry,nn,x0,ret); 00417 } 00418 rit4->free(); 00419 } 00420 } else { 00421 set_err("Interpolation failed in deriv2().",gsl_efailed); 00422 } 00423 } 00424 00425 } 00426 00427 return ret; 00428 } 00429 00430 /// Give the value of the integral \f$ \int_a^{b}y(x)~dx \f$ . 00431 virtual double integ(const double a, const double b, 00432 size_t n, const vec_t &x, const vec_t &y) { 00433 00434 bool increasing=true, to_subset=false; 00435 double ret=0.0; 00436 int err0, err1, err2; 00437 00438 err_hnd->reset(); 00439 00440 // Determine if array is increasing or decreasing 00441 00442 if (x[0]==x[n-1]) { 00443 to_subset=true; 00444 } else if (x[0]>x[n-1]) { 00445 increasing=false; 00446 } 00447 00448 if (increasing) { 00449 00450 if (n<rit1->min_size) { 00451 set_err("Vector size too small in integ().",gsl_edom); 00452 return 0.0; 00453 } 00454 err0=rit1->allocate(n); 00455 if (err0==0) { 00456 err1=rit1->init(x,y,n); 00457 if (err1==0) { 00458 err2=rit1->integ(x,y,n,a,b,ret); 00459 if (err2!=0) to_subset=true; 00460 } else { 00461 to_subset=true; 00462 } 00463 rit1->free(); 00464 } 00465 00466 } else { 00467 00468 if (n<rit2->min_size) { 00469 set_err("Vector size too small in integ().",gsl_edom); 00470 return 0.0; 00471 } 00472 00473 rvec_t rx(x); 00474 rvec_t ry(y); 00475 00476 err0=rit2->allocate(n); 00477 if (err0==0) { 00478 err1=rit2->init(rx,ry,n); 00479 if (err1==0) { 00480 err2=rit2->integ(rx,ry,n,a,b,ret); 00481 if (err2!=0) to_subset=true; 00482 } else { 00483 to_subset=true; 00484 } 00485 rit2->free(); 00486 } 00487 00488 } 00489 00490 if (!finite(ret)) to_subset=true; 00491 00492 if (to_subset) { 00493 00494 size_t nn=0; 00495 find_subset(a,b,n,x,y,nn,increasing); 00496 00497 if (nn<=1) { 00498 set_err("Interpolation failed in integ().",gsl_efailed); 00499 return 0; 00500 } 00501 00502 if (increasing) { 00503 if (nn>rit3->min_size) { 00504 err0=rit3->allocate(nn); 00505 if (err0==0) { 00506 err1=rit3->init(*sx,*sy,nn); 00507 if (err1==0) { 00508 err2=rit3->integ(*sx,*sy,nn,a,b,ret); 00509 } 00510 rit3->free(); 00511 } 00512 } else { 00513 set_err("Interpolation failed in integ().",gsl_efailed); 00514 } 00515 } else { 00516 if (nn>rit4->min_size) { 00517 err0=rit4->allocate(nn); 00518 if (err0==0) { 00519 err1=rit4->init(*srx,*sry,nn); 00520 if (err1==0) { 00521 err2=rit4->integ(*srx,*sry,nn,a,b,ret); 00522 } 00523 rit4->free(); 00524 } 00525 } else { 00526 set_err("Interpolation failed in integ().",gsl_efailed); 00527 } 00528 } 00529 00530 } 00531 00532 return ret; 00533 } 00534 00535 #ifndef DOXGYEN_INTERNAL 00536 00537 protected: 00538 00539 /// A lookup function for generic vectors 00540 size_t local_lookup(size_t n, const vec_t &x, double x0) { 00541 size_t row=0, i=0; 00542 while(!finite(x[i]) && i<n-1) i++; 00543 if (i==n-1) { 00544 return 0; 00545 } 00546 double best=x[i], bdiff=fabs(x[i]-x0); 00547 for(;i<n;i++) { 00548 if (finite(x[i]) && fabs(x[i]-x0)<bdiff) { 00549 row=i; 00550 best=x[i]; 00551 bdiff=fabs(x[i]-x0); 00552 } 00553 } 00554 return row; 00555 } 00556 00557 /** \brief Try to find the largest monotonic and finite region 00558 around the desired location 00559 00560 \todo After row and row2 are set, check to make sure the 00561 entire inside region is monotonic before expanding 00562 */ 00563 int find_subset(const double a, const double b, size_t sz, const vec_t &x, 00564 const vec_t &y, size_t &nsz, bool &increasing) 00565 { 00566 00567 size_t left, right; 00568 00569 // Lookup the point 00570 size_t row=local_lookup(sz,x,a); 00571 if (!finite(x[row]) || !finite(y[row])) { 00572 set_err_ret("find_subset failed to find any valid points.", 00573 gsl_notfound); 00574 } 00575 size_t row2=local_lookup(sz,x,b); 00576 if (!finite(x[row2]) || !finite(y[row2])) { 00577 set_err_ret("find_subset failed to find any valid points.", 00578 gsl_notfound); 00579 } 00580 00581 // Get a neighboring point if necessary 00582 if (row2==row) { 00583 row2=row++; 00584 if (row2>=sz) row2=row-1; 00585 } 00586 00587 // Arrange 00588 if (row<row2) { 00589 left=row; 00590 right=row2; 00591 } else { 00592 left=row2; 00593 right=row; 00594 } 00595 00596 // Establish whether we're increasing or decreasing 00597 increasing=true; 00598 if (row2<row && x[row]<x[row2]) increasing=false; 00599 if (row2>row && x[row2]<x[row]) increasing=false; 00600 00601 // Need to check region between row and row2 here 00602 00603 // Increasing case 00604 00605 if (increasing) { 00606 00607 while(left>0 && x[left-1]<x[left] && 00608 finite(x[left-1]) && finite(y[left-1])) left--; 00609 while(right<sz-1 && x[right]<x[right+1] && 00610 finite(x[right+1]) && finite(y[right+1])) right++; 00611 00612 nsz=right-left+1; 00613 00614 delete sx; 00615 delete sy; 00616 sx=new svec_t(x,left,nsz); 00617 sy=new svec_t(y,left,nsz); 00618 00619 } else { 00620 00621 while(left>0 && x[left-1]>x[left] && 00622 finite(x[left-1]) && finite(y[left-1])) left--; 00623 while(right<sz-1 && x[right]>x[right+1] && 00624 finite(x[right+1]) && finite(y[right+1])) right++; 00625 00626 nsz=right-left+1; 00627 00628 delete srx; 00629 delete sry; 00630 srx=new srvec_t(x,left,nsz); 00631 sry=new srvec_t(y,left,nsz); 00632 00633 } 00634 00635 return 0; 00636 } 00637 00638 #endif 00639 00640 }; 00641 00642 /** 00643 \brief Smart interpolation class with pre-specified vectors 00644 00645 This class can semi-intelligently handle arrays which are 00646 not-well formed outside the interpolation region. In particular, 00647 if an initial interpolation or derivative calculation fails, the 00648 arrays are searched for the largest neighborhood around the 00649 point \c x for which an interpolation or differentiation will 00650 likely produce a finite result. 00651 00652 */ 00653 template<class vec_t, class svec_t, class alloc_vec_t, class alloc_t> 00654 class smart_interp_vec { 00655 00656 #ifndef DOXYGEN_INTERNAL 00657 00658 protected: 00659 00660 /// Storage for internally created subvector 00661 svec_t *sx; 00662 /// Storage for internally created subvector 00663 svec_t *sy; 00664 00665 /// Pointer to base interpolation object 00666 base_interp<vec_t> *rit1; 00667 /// Pointer to base interpolation object 00668 base_interp<svec_t> *rit2; 00669 00670 /// Memory allocator for objects of type \c alloc_vec_t 00671 alloc_t ao; 00672 00673 /// True if the user-specified x vector is increasing 00674 bool inc; 00675 00676 /// Pointer to user-specified vector 00677 const vec_t *lx; 00678 /// Pointer to user-specified vector 00679 const vec_t *ly; 00680 00681 /// Reversed version of vector 00682 alloc_vec_t lrx; 00683 /// Reversed version of vector 00684 alloc_vec_t lry; 00685 00686 /// Size of user-specifed vector 00687 size_t ln; 00688 00689 #endif 00690 00691 public: 00692 00693 /// Create with base interpolation objects \c it and \c rit 00694 smart_interp_vec(size_t n, const vec_t &x, const vec_t &y) { 00695 sx=0; 00696 sy=0; 00697 00698 rit1=&cit1; 00699 rit2=&cit2; 00700 ln=0; 00701 00702 if (n<rit1->min_size) { 00703 set_err("Vector size too small in o2scl_interp_vec().",gsl_edom); 00704 } else { 00705 00706 if (x[0]>x[n-1]) { 00707 00708 ao.allocate(lrx,n); 00709 ao.allocate(lry,n); 00710 00711 for(size_t i=0;i<n;i++) { 00712 lrx[n-1-i]=x[i]; 00713 lry[n-1-i]=y[i]; 00714 } 00715 00716 int r1=rit1->allocate(n); 00717 if (r1==0) { 00718 rit1->init(lrx,lry,n); 00719 ln=n; 00720 inc=false; 00721 } 00722 00723 } else { 00724 00725 int r1=rit1->allocate(n); 00726 if (r1==0) { 00727 rit1->init(x,y,n); 00728 ln=n; 00729 lx=&x; 00730 ly=&y; 00731 inc=true; 00732 } 00733 00734 } 00735 00736 } 00737 00738 00739 } 00740 00741 /// Create with base interpolation objects \c it and \c rit 00742 smart_interp_vec(base_interp<vec_t> &it1, base_interp<svec_t> &it2, 00743 size_t n, const vec_t &x, const vec_t &y) { 00744 sx=0; 00745 sy=0; 00746 00747 rit1=&it1; 00748 rit2=&it2; 00749 ln=0; 00750 00751 if (n<rit1->min_size) { 00752 set_err("Vector size too small in o2scl_interp_vec().",gsl_edom); 00753 } else { 00754 00755 if (x[0]>x[n-1]) { 00756 00757 ao.allocate(lrx,n); 00758 ao.allocate(lry,n); 00759 00760 for(size_t i=0;i<n;i++) { 00761 lrx[n-1-i]=x[i]; 00762 lry[n-1-i]=y[i]; 00763 } 00764 00765 int r1=rit1->allocate(n); 00766 if (r1==0) { 00767 rit1->init(lrx,lry,n); 00768 ln=n; 00769 inc=false; 00770 } 00771 00772 } else { 00773 00774 int r1=rit1->allocate(n); 00775 if (r1==0) { 00776 rit1->init(x,y,n); 00777 ln=n; 00778 lx=&x; 00779 ly=&y; 00780 inc=true; 00781 } 00782 00783 } 00784 00785 } 00786 00787 } 00788 00789 virtual ~smart_interp_vec() { 00790 delete sx; 00791 delete sy; 00792 00793 if (ln>0) { 00794 rit1->free(); 00795 if (inc==false) { 00796 ao.free(lrx); 00797 ao.free(lry); 00798 } 00799 } 00800 } 00801 00802 /// Default base interpolation object 00803 cspline_interp<vec_t> cit1; 00804 00805 /// Default base interpolation object 00806 cspline_interp<svec_t> cit2; 00807 00808 /// Give the value of the function \f$ y(x=x_0) \f$ . 00809 virtual double interp(const double x0) { 00810 double ret=0.0; 00811 int err; 00812 if (ln>0) { 00813 00814 if (inc) { 00815 00816 err=rit1->interp(*lx,*ly,ln,x0,ret); 00817 if (err!=0) { 00818 size_t nn=0; 00819 find_inc_subset(x0,ln,*lx,*ly,nn); 00820 00821 if (nn>1 && nn>=rit2->min_size) { 00822 rit2->allocate(nn); 00823 rit2->init(*sx,*sy,nn); 00824 err=rit2->interp(*sx,*sy,nn,x0,ret); 00825 rit2->free(); 00826 } 00827 } 00828 00829 } else { 00830 00831 err=rit1->interp(lrx,lry,ln,x0,ret); 00832 if (err!=0) { 00833 size_t nn=0; 00834 find_inc_subset(x0,ln,lrx,lry,nn); 00835 00836 if (nn>1 && nn>=rit2->min_size) { 00837 rit2->allocate(nn); 00838 rit2->init(*sx,*sy,nn); 00839 err=rit2->interp(*sx,*sy,nn,x0,ret); 00840 rit2->free(); 00841 } 00842 } 00843 00844 } 00845 00846 } 00847 00848 return ret; 00849 } 00850 00851 /// Give the value of the derivative \f$ y^{prime}(x=x_0) \f$ . 00852 virtual double deriv(const double x0) { 00853 double ret=0.0; 00854 if (ln>0) { 00855 if (inc) rit1->deriv(*lx,*ly,ln,x0,ret); 00856 else rit1->deriv(lrx,lry,ln,x0,ret); 00857 } 00858 return ret; 00859 } 00860 00861 /** \brief Give the value of the second derivative 00862 \f$ y^{prime \prime}(x=x_0) \f$ . 00863 */ 00864 virtual double deriv2(const double x0) { 00865 double ret=0.0; 00866 if (ln>0) { 00867 if (inc) rit1->deriv2(*lx,*ly,ln,x0,ret); 00868 else rit1->deriv2(lrx,lry,ln,x0,ret); 00869 } 00870 return ret; 00871 } 00872 00873 /// Give the value of the integral \f$ \int_a^{b}y(x)~dx \f$ . 00874 virtual double integ(const double x1, const double x2) { 00875 double ret=0.0; 00876 if (ln>0) { 00877 if (inc) rit1->integ(*lx,*ly,ln,x1,x2,ret); 00878 else rit1->integ(lrx,lry,ln,x1,x2,ret); 00879 } 00880 return ret; 00881 } 00882 00883 #ifndef DOXYGEN_INTERNAL 00884 00885 protected: 00886 00887 /// A lookup function for generic vectors 00888 size_t local_lookup(size_t n, const vec_t &x, double x0) { 00889 size_t row=0, i=0; 00890 while(!finite(x[i]) && i<n-1) i++; 00891 if (i==n-1) { 00892 return 0; 00893 } 00894 double best=x[i], bdiff=fabs(x[i]-x0); 00895 for(;i<n;i++) { 00896 if (finite(x[i]) && fabs(x[i]-x0)<bdiff) { 00897 row=i; 00898 best=x[i]; 00899 bdiff=fabs(x[i]-x0); 00900 } 00901 } 00902 return row; 00903 } 00904 00905 /** \brief Try to find the largest monotonic and finite region 00906 around the desired location 00907 */ 00908 int find_inc_subset(const double x0, size_t sz, const vec_t &x, 00909 const vec_t &y, size_t &nsz) { 00910 00911 size_t row=local_lookup(sz,x,x0), row2=row++; 00912 size_t left=row, right=row; 00913 00914 if (row2>sz) row2=row-1; 00915 00916 if (!finite(x[row]) || !finite(y[row])) { 00917 set_err_ret("find_subset failed to find any valid points.", 00918 gsl_notfound); 00919 } 00920 00921 // Increasing case 00922 00923 while(left>0 && x[left-1]<x[left] && 00924 finite(x[left-1]) && finite(y[left-1])) left--; 00925 while(right<sz-1 && x[right]<x[right+1] && 00926 finite(x[right+1]) && finite(y[right+1])) right++; 00927 00928 nsz=right-left+1; 00929 00930 delete sx; 00931 delete sy; 00932 sx=new svec_t(x,left,nsz); 00933 sy=new svec_t(y,left,nsz); 00934 00935 return 0; 00936 } 00937 00938 #endif 00939 00940 }; 00941 00942 /// sm_interp typedef 00943 typedef smart_interp<ovector_view,ovector_const_reverse, 00944 ovector_const_subvector,ovector_const_subvector_reverse> sm_interp; 00945 00946 /// sm_interp_vec typedef 00947 typedef smart_interp_vec<ovector_view,ovector_const_subvector,ovector, 00948 ovector_alloc> sm_interp_vec; 00949 00950 /** \brief A specialization of smart_interp for C-style double arrays 00951 */ 00952 template<size_t n> class sma_interp : 00953 public smart_interp<double[n],array_const_reverse<n>,array_const_subvector, 00954 array_const_subvector_reverse> { 00955 00956 public: 00957 00958 /// Create with base interpolation objects 00959 sma_interp(base_interp<double[n]> &it1, 00960 base_interp<array_const_reverse<n> > &it2, 00961 base_interp<array_const_subvector> &it3, 00962 base_interp<array_const_subvector_reverse> &it4) 00963 : smart_interp<double[n],array_const_reverse<n>, 00964 array_const_subvector,array_const_subvector_reverse>(it1,it2,it3,it4) { 00965 } 00966 00967 /// Create with default interpolation objects 00968 sma_interp() : smart_interp<double[n],array_const_reverse<n>, 00969 array_const_subvector,array_const_subvector_reverse>() { 00970 } 00971 00972 }; 00973 00974 /** 00975 \brief A specialization of smart_interp_vec for C-style arrays 00976 */ 00977 template<class arr_t> class sma_interp_vec : 00978 public smart_interp_vec<arr_t,array_const_subvector,arr_t, 00979 array_alloc<arr_t> > { 00980 00981 public: 00982 00983 /// Create with base interpolation object \c it and \c it2 00984 sma_interp_vec(base_interp<arr_t> &it, 00985 base_interp<array_const_subvector> &it2, 00986 size_t n, const arr_t &x, const arr_t &y) : 00987 smart_interp_vec<arr_t,array_const_subvector,arr_t, 00988 array_alloc<arr_t> >(it,it2,n,x,y) { 00989 } 00990 00991 /// Create with default interpolation objects 00992 sma_interp_vec(size_t n, const arr_t &x, const arr_t &y) : 00993 smart_interp_vec<arr_t,array_const_subvector,arr_t, 00994 array_alloc<arr_t> >(n,x,y) { 00995 } 00996 00997 }; 00998 00999 01000 01001 #ifndef DOXYGENP 01002 } 01003 #endif 01004 01005 #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