smart_interp.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, 2008, 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 SourceForge.net Logo, O2scl Sourceforge Project Page