Interpolation

O2scl

Interpolation contents

Interpolation introduction

Basic interpolation of generic vector types is performed by interp and interp_vec. The vector representing the independent variable must be monotonic, but need not be equally-spaced. The difference between the two classes is analogous to the difference between using gsl_interp_eval() and gsl_spline_eval() in GSL. You can create a interp object and use it to interpolate among any pair of chosen vectors. For example, cubic spline interpolation with natural boundary conditions:

boost::numeric::ublas::vector<double> x(20), y(20);
// fill x and y with data
o2scl::interp<> oi(itp_cspline);
double y_half=oi.eval(0.5,20,x,y);

Alternatively, you can create a interp_vec object which can be optimized for a pair of vectors that you specify in advance (now using linear interpolation instead):

boost::numeric::ublas::vector<double> x(20), y(20);
// fill x and y with data
o2scl::interp_vec<> oi(20,x,y,itp_linear);
double y_half=oi.eval(0.5);

These interpolation classes require that the vector x is either monotonically increasing or monotonically decreasing, but these classes do not verify that this is the case. If the vectors or not monotonic, then the interpolation functions are not defined. These classes give identical results to the GSL interpolation routines when the vector is monotonically increasing.

These interpolation classes will extrapolate to regions outside those defined by the user-specified vectors and will not warn you when they do this (this is not the same behavior as in GSL).

The different interpolation types are defined in src/base/interp.h

enumerator itp_linear

Linear.

enumerator itp_cspline

Cubic spline for natural boundary conditions.

enumerator itp_cspline_peri

Cubic spline for periodic boundary conditions.

enumerator itp_akima

Akima spline for natural boundary conditions.

enumerator itp_akima_peri

Akima spline for periodic boundary conditions.

enumerator itp_monotonic

Monotonicity-preserving interpolation (unfinished)

enumerator itp_steffen

Steffen’s monotonic method.

enumerator itp_nearest_neigh

Nearest-neighbor lookup.

Integrals are always computed assuming that if the limits are ordered so that if the upper limit appears earlier in the array x in comparison to the lower limit, that the value of the integral has the opposite sign than if the upper limit appears later in the array x.

The classes interp and interp_vec are based on the lower-level interpolation classes of type interp_base. Also, the interpolation classes based on interp_base and also the class interp_vec also have defined a function operator() which also returns the result of the interpolation.

Two specializations for C-style arrays of double-precision numbers are provided in interp_array and interp_array_vec.

An experimental class for one-dimensional kriging is also provided in interp_krige.

Interpolation example

/* Example: ex_interp.cpp
   -------------------------------------------------------------------
   A simple example for interpolation
*/

#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>

#include <o2scl/interp.h>
#include <o2scl/interp_krige.h>
#include <o2scl/test_mgr.h>
#include <o2scl/hdf_io.h>
#include <o2scl/hdf_file.h>

using namespace std;
using namespace o2scl;
using namespace o2scl_hdf;

typedef boost::numeric::ublas::vector<double> ubvector;

// A function for filling the data and comparing results
double f(double x, const double &mean, const double &sd) {
  return (sin(1.0/(0.3+x))-mean)/sd;
}

int main(void) {
  cout.setf(ios::scientific);

  test_mgr t;
  t.set_output_level(1);

  // Create the sample data

  static const size_t N=20;
  ubvector x(N), y(N);
  x[0]=0.0;
  y[0]=f(x[0],0.0,1.0);
  for(size_t i=1;i<N;i++) {
    x[i]=x[i-1]+pow(((double)i)/40.0,2.0);
    y[i]=f(x[i],0.0,1.0);
  }
  
  table<> tdata;
  tdata.line_of_names("x y");

  double y_mean=vector_mean(y);
  for(size_t i=0;i<N;i++) {
    y[i]-=y_mean;
  }
  double y_sd=vector_stddev(y);
  cout << "Old mean and std. dev.: " << y_mean << " " << y_sd << endl;
  for(size_t i=0;i<N;i++) {
    y[i]/=y_sd;
    double line[2]={x[i],y[i]};
    tdata.line_of_data(2,line);
  }
  double y_mean2=vector_mean(y);
  double y_sd2=vector_stddev(y);
  cout << "New mean and std. dev.: " << y_mean2 << " " << y_sd2 << endl;
  cout << endl;

  interp_vec<ubvector> iv_lin(N,x,y,itp_linear);
  interp_vec<ubvector> iv_csp(N,x,y,itp_cspline);
  interp_vec<ubvector> iv_aki(N,x,y,itp_akima);
  interp_vec<ubvector> iv_mon(N,x,y,itp_monotonic);
  interp_vec<ubvector> iv_stef(N,x,y,itp_steffen);

  interp_krige_optim<ubvector> iko;
  iko.verbose=2;
  iko.nlen=10000;
  iko.mode=interp_krige_optim<ubvector>::mode_loo_cv;
  iko.set_noise(N,x,y,1.0e-10);
  cout << endl;

  interp_krige_optim<ubvector> iko2;
  iko2.verbose=2;
  iko2.nlen=10000;
  iko2.mode=interp_krige_optim<ubvector>::mode_max_lml;
  iko2.set_noise(N,x,y,1.0e-10);
  cout << endl;

  double max=x[x.size()-1];

  cout << "\nx              y             iko           iko2: " << endl;
  for(size_t i=0;i<N;i++) {
    cout.setf(ios::showpos);
    cout << x[i] << " " << f(x[i],y_mean,y_sd) << " "
	 << iko.eval(x[i]) << " "
	 << iko2.eval(x[i]) << endl;
    cout.unsetf(ios::showpos);
  }
  cout << endl;

  cout << "\nx              y             iko           iko2: " << endl;
  size_t N2=N*100;
  table<> tresult;
  tresult.line_of_names("x y ylin ycsp yaki ymon ystef yiko yiko_lml"); 
  for(size_t i=0;i<=N2;i++) {
    double x=((double)i)/((double)N2)*max;
    double line[9]={x,f(x,y_mean,y_sd),iv_lin.eval(x),iv_csp.eval(x),
		    iv_aki.eval(x),iv_mon.eval(x),iv_stef.eval(x),
		    iko.eval(x),iko2.eval(x)};
    tresult.line_of_data(9,line);
    if (i%50==0) {
      cout.setf(ios::showpos);
      cout << x << " " << f(x,y_mean,y_sd) << " " << iko.eval(x) << " "
	   << iko2.eval(x) << endl;
      cout.unsetf(ios::showpos);
    }
  }

  hdf_file hf;
  hf.open_or_create("ex_interp.o2");
  hdf_output(hf,tdata,"tdata");
  hdf_output(hf,tresult,"tresult");
  hf.close();
  
  t.report();
  return 0;
}
// End of example

Todo

Fix the interpolation plot for this example.

Two and higher-dimensional interpolation

Support for multi-dimensional interpolation is documented in Higher-dimensional Interpolation.

Derivatives and integrals on a fixed grid

If the indepedent variable is represented by a uniform (equally-spaced) then the functions in src/deriv/vector_derint.h can provide faster (and occasionally more accurate) results. See: