Implement functions for interpolation of tabulated data.
A mathematical set {xi | i=1,...,n} can be
represented in programming languages in many ways, usually (but not
necessarily) as arrays with syntax x[i] for the element
xi.
For example:
#define RND (double)rand()/RAND_MAX
int n=5;
double v[n]; /* in the stack */
double * w = malloc(n*sizeof(double)); /* in the heap */
for(int i=0;i<n;i++) { v[i]=i, w[i]=v[i]; }
for(int i=0;i<n;i++) printf("%g %g\n",v[i],w[i]);
free(w); /* there should be a free for every alloc */
Note that these arrays are passed as pointers (of the type double*) and do not remember their sizes. The size of the array must be passed together with the array.
(You need to include "stdio.h" and "stdlib.h" for printf, malloc, and rand)
int n=5;
gsl_vector * x = gsl_vector_alloc(n);
for(int i=0; i<x->size; i++) gsl_vector_set(x,i,RND);
for(int i=0; i<x->size; i++) printf("%g\n",gsl_vector_get(x,i));
gsl_vector_free(x);
GSL vectors remember their sizes. You only need to pass the pointer to the vector.
You need to i) install GSL (sudo apt-get install libgsl0-dev);
ii) #include<gsl/gsl_vector.h>, and iii)
put something like this into your makefile
CFLAGS = -Wall -std=gnu99 `gsl-config --cflags`
CXXFLAGS = -Wall -std=c++0x `gsl-config --cflags`
LDLIBS = -lstdc++ `gsl-config --libs`
std::vector<double>
This is a useful container from STL:
int n=5;
vector<double> v(n); /* in the stack */
auto w = new vector<double>(n); /* in the heap */
for(uint i=0; i<v.size(); i++) v[i]=RND;
for(uint i=0; i<v.size(); i++) (*w)[i]=v[i];
for(uint i=0; i<(*w).size(); i++) cout << (*w)[i] <<endl;
delete w;
In Java arrays remember their sizes:
int n=5;
double[] v= new double[n];
for(int i=0; i<v.length; i++) v[i]=Math.random();
for(int i=0; i<v.length; i++) System.out.println(v[i]);
The exercise can be solved using different styles of programming:
Procedural programming (C,Pascal,Fortran-77,...):
struct qspline {int n; double *x,*y,*b,*c};
qspline
typedef struct {int n; double *x, *y, *b, *c;} qspline;
and then in the following instead of struct qspline simply
use qspline.
Implement a routine which allocates the necessary memory,
calculates the spline coefficients c and returns the (pointer
to the) properly filled qspline structure (the name of
this function usually ends with _alloc to underline that
it allocates memory in the heap which then needs to be freed):
struct qspline* qspline_alloc(int n, double* x,double* y);
Implement a routine which—given the precalculated
qspline structure—computes the spline interpolation
function at a given point z:
double qspline_evaluate(struct qslpine* s, double z);
qspline_free, which frees
the memory occupied by structure qspline.
void qspline_free(struct qslpine* s);
Object oriented programming (C++, Java, Python, C#, ...): the structure (or class) holds not only data but also all the appropriate functions (called member functions) which have direct access to the data in the structure:
qspline which holds all the
data for spline; the construction function becomes the constructor
method; the evaluation function becomes the member function; the
qspline_free function becomes the destructor method which
is defined automatically (I think). In C++:
struct qspline {
vector<double> x,y,b,c; /* the data for the spline */
qspline(vector<double> x, vector<double> y); /* constructor */
double evaluate(double z); /* evaluates the interpolation function */
};
std::vector<double>
is a useful container (which remembers its length and can do bounds
checking) in C++.
Functional programming (C++11, Lisp, Haskell, Python, JavaScript, ...): only the function for spline-evaluation is created and returned. This function captures all the needed information in itself (in its environment, to be precise):
function<double(double)> construct_qspline_evaluation_function(vector<double> x, vector<double> y);
double linterp(int n, double *x, double *y, double z);
struct qspline * qspline_alloc(int n, double *x, double *y);
double qspline_evaluate(struct qspline *s, double z);
void qspline_free(struct qspline *s);
for(int i = 0; i < 10; i++)
{ x[i] = i + 0.5 * sin (i); y[i] = i + cos (i * i); }
and plot the two interpolating functions (together with the data points).
Hints:
graph utility from
plotutils (an example of its usage can be found here), or using
pyxplot or gnuplot.
Implement a function which estimates the derivative and the anti-derivative (indefinite integral) of a tabulated function by building a quadratic spline and then differentiating and integrating the spline (analytically!).
The signatures of the functions should be like
double qspline_derivative(struct qspline *s, double z) /* returns s'(z) */
double qspline_integral(struct qspline *s, double z) /* returns \int_{x[0]}^z s(x) dx */
Hint: the integration function should return
| z | ||
| ∫ | S(x)dx | |
| x0 |
Implement a function which makes a polynomial intepolation using not all the points in the table (that would be susceptible to the Runge's phenomenon) but rather only few neighboring points to the right and to the left of the point of interpolation.
The signature of the function should be something like
double piecewise_polynomial(int n, double x[], double y[], double z, int number_of_neighbors_to_use)
Check your implementation on some indicative data of your choice.
Implement also the derivatives and anti-derivatives.
Investigate (analytically) whether this piecewise polynomial has continuous derivatives.
octave, on lifa Octave is
/usr/users/fedorov/bin/octave.