/* --- SOPHYA software - NTools module --- --- Class SLinInterp1D : Simple linear 1D interpolation class R. Ansari , C. Magneville 2000-2010 (C) UPS+LAL IN2P3/CNRS (C) IRFU-SPP/CEA */ #include "slininterp.h" #include namespace SOPHYA { /*! \class SLinInterp1D \ingroup NTools \brief Simple linear interpolation class \code #include "slininterp.h" #include "srandgen.h" ... vector ys; double xmin = 0.5; double xmax = 0.; for(int i=0; i<=12; i++) { xmax = xmin+i*0.1; yreg.push_back(sin(xmax)*cos(2.2*xmax)); } SLinInterp1D interpYR(xmin, xmax, yreg); cout << interpYR for(int i=0; i<=12; i++) { double x = drand01()*2.; cout << " Interpol result for X=" << x << " -> " << interpYR(x) << " ?= " << sin(x)*cos(2.2*x) << endl; } \endcode */ /* --Methode-- */ SLinInterp1D::SLinInterp1D() : xmin_(0.), xmax_(1.), dx_(1.), ksmx_(1), npoints_(0) { xs_.push_back(0.); xs_.push_back(1.); ys_.push_back(0.); ys_.push_back(1.); } /*! \brief Constructor from regularly spaced points in X with Y values defined by yreg \b xmin and \b xmax are the two extreme points in X corresponding to yreg. Example: xmin=1, xmax=10, with yreg.size()=10 , yreg[0]=Y(1) , yreg[1]=Y(2) ... yreg[9]=Y(10) */ SLinInterp1D::SLinInterp1D(double xmin, double xmax, vector& yreg) : xmin_(0.), xmax_(1.), dx_(1.), ksmx_(1), npoints_(0) { DefinePoints(xmin, xmax, yreg); } /*! \brief Constructor from a set of \b (xs[i],ys[i]) pairs. if (npt > 0), interpolates to a finer regularly spaced grid, from \b xmin to \b xmax with npt points. use \b (xs[0],xs[xs.size()-1]) as limits if \b xmax& xs, vector& ys, double xmin, double xmax, size_t npt) : xmin_(0.), xmax_(1.), dx_(1.), ksmx_(1), npoints_(0) { DefinePoints(xs, ys, xmin, xmax, npt); } /* --Methode-- */ double SLinInterp1D::YInterp(double x) const { if (npoints_>0) { // on utilise les points regulierement espace long i = (long)((x-xmin_)/dx_); if (i<0) return ( yreg_[0]+(x-xmin_)*(yreg_[1]-yreg_[0])/dx_ ); if (i>=npoints_) return ( yreg_[npoints_]+(x-xmax_)*(yreg_[npoints_]-yreg_[npoints_-1])/dx_ ); return (yreg_[i]+(x-X(i))/dx_*(yreg_[i+1]-yreg_[i])); } else { // On utilise les points xs_,ys_ directement if (x<=xs_[0]) return ( ys_[0]+(x-xs_[0])*(ys_[1]-ys_[0])/(xs_[1]-xs_[0]) ); if (x>=xs_[ksmx_]) return ( ys_[ksmx_]+(x-xs_[ksmx_])*(ys_[ksmx_]-ys_[ksmx_-1])/(xs_[ksmx_]-xs_[ksmx_-1]) ); size_t k=1; while(x>xs_[k]) k++; if (k>=xs_.size()) { // ne devrait pas arriver ... string emsg = " SLinInterp1D::YInterp() out of range k -> BUG in code "; throw out_of_range(emsg); } double rv=ys_[k-1]+(x-xs_[k-1])*(ys_[k]-ys_[k-1])/(xs_[k]-xs_[k-1]); // cout << " DBG- x=" << x << " k=" << k << " xs[k]=" << xs_[k] << " ys[k]" << ys_[k] // << " rv=" << rv << endl; return rv; } } /*! \brief Defines the interpolation points from regularly spaced points in X with Y values defined by yreg \b xmin and \b xmax are the two extreme points in X corresponding to yreg. Example: xmin=1, xmax=10, with yreg.size()=10 , yreg[0]=Y(1) , yreg[1]=Y(2) ... yreg[9]=Y(10) */ void SLinInterp1D::DefinePoints(double xmin, double xmax, vector& yreg) { if (yreg.size()<2) { string emsg = "SLinInterp1D::DefinePoints(xmin,xmax,yreg) Bad parameters yreg.size()<2 "; throw range_error(emsg); } xmin_ = xmin; xmax_ = xmax; npoints_ = yreg.size()-1; dx_ = (xmax_-xmin_)/(double)npoints_; yreg_ = yreg; } /*! \brief Define the interpolation points from a set of \b (xs[i],ys[i]) pairs. if (npt > 0), interpolates to a finer regularly spaced grid, from \b xmin to \b xmax with npt points. use \b (xs[0],xs[xs.size()-1]) as limits if \b xmax& xs, vector& ys, double xmin, double xmax, size_t npt) { if ((xs.size() != ys.size())||(xs.size()<2)) { string emsg = "SLinInterp1D::DefinePoints() Bad parameters (xs.size() != ys.size())||(xs.size()<2) "; throw range_error(emsg); } for(size_t k=1; k=xs[k]) { string emsg = "SLinInterp1D::DefinePoints() unsorted xs "; throw range_error(emsg); } } xs_=xs; ys_=ys; ksmx_=xs_.size()-1; npoints_ = npt; if (xmin>=xmax) { xmin_ = xs_[0]; xmax_ = xs_[ksmx_]; } else { xmin_ = xmin; xmax_ = xmax; } if (npoints_<1) { dx_=(xmax_-xmin_)/(double)(xs_.size()-1); return; } dx_ = (xmax_-xmin_)/(double)npoints_; yreg_.resize(npoints_+1); // Compute the the y values for regularly spaced x xmin <= x <= xmax // and keep values in the yreg vector yreg_[0] = ys_[0]; yreg_[npoints_] = ys_[ksmx_]; size_t k=1; for(size_t i=0; ixs_[k]) k++; if (k>=xs_.size()) k=xs_.size()-1; yreg_[i] = ys_[k-1]+(x-xs_[k-1])*(ys_[k]-ys_[k-1])/(xs_[k]-xs_[k-1]); //DBG cout << " DBG* i=" << i << " X(i)=" << X(i) << " yreg_[i]= " << yreg_[i] << " X^2= " << X(i)*X(i) //DBG << " k=" << k << " xs[k]=" << xs_[k] << endl; } return; } /*! \brief Read Y values from the file \b filename Read Y values ( one/line) for regularly spaced X's from file \b filename and call DefinePoints(xmin, xmax, yreg). Return the number of Y values read. \param filename : input file name \param xmin,xamx : X range limits \param clm : comment character, lines starting with \b clm are ignored */ size_t SLinInterp1D::ReadYFromFile(string const& filename, double xmin, double xmax, char clm) { ifstream inputFile; inputFile.open(filename.c_str(), ifstream::in); #ifndef __DECCXX // ifstream.is_open() ne passe pas avec OSF-cxx if(! inputFile.is_open()) { string emsg = " SLinInterp1D::ReadYFromFile() problem opening file "; emsg += filename; throw runtime_error(emsg); } #endif vector xsv, ysv; size_t cnt=0; double cola; string eline; while(!inputFile.eof()) { inputFile.clear(); if (inputFile.peek() == (int)clm) { // skip comment lines getline(inputFile, eline); continue; } inputFile >> cola; if ( (!inputFile.good()) || inputFile.eof()) break; inputFile.ignore(1024,'\n'); // make sure we go to the next line //cout << cola<< " "< xsv, ysv; size_t cnt=0; double cola, colb; string eline; while(!inputFile.eof()) { inputFile.clear(); if (inputFile.peek() == (int)clm) { // skip comment lines getline(inputFile, eline); continue; } inputFile >> cola >> colb; if ( (!inputFile.good()) || inputFile.eof()) break; inputFile.ignore(1024,'\n'); // make sure we go to the next line // cout << " DEBUG-GCount " << inputFile.gcount() << endl; // cout << " DEBUG - cnt=" << cnt << " x=" << cola << " y= "< ys[" << i << "]=" << ys_[i] << endl; } if ((lev>0)&&(yreg_.size()>0)) { for(size_t i=0; i yreg_[" << i << "]=" << yreg_[i] << endl; } os << " -----------------------------------------------------------------------" << endl; } } // End namespace SOPHYA