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:
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. No range checking is done either.
You need to include <stdio.h> and <stdlib.h> for printf, malloc, and
rand
#define RND (double)rand()/RAND_MAX
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 know their sizes and by default do
range-checking. Rrange-checking can be disabled by recompiling your
program with the preprocessor definition GSL_RANGE_CHECK_OFF.
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`
Something like here.
std::vector<double>
This is a useful container from the
Standard Template Library (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;
for(auto &e : v) cout << e <<endl; /* C++11 */
delete w;
-std=c++11 to compile the range-based for-loop).
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]);
for(double e : v) System.out.println(e); /* 1.5.0 */
However, your own vector/matrix library (like this) may still come usefull as you can define some useful methods like add, subtract, scale, norm etc.
Python has lists as containers although for numerical computaions one often uses arrays from NumPy. However, since an
interpreted language is going to be slow anyway you can just use the built-in lists.
n=5
v=[ i for i in range(n-1) ]
for e in v: print(e)
for i, e in enumerate(v): print(i,e)
However you may want to build your own vector/matrix library (like this) which may come usefull as you can define some useful methods/operators like add, subtract, scale, norm etc.
The exercise can be solved using different styles of programming:
Procedural programming (typically C, Pascal, Fortran):
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 function, typically called qspline_alloc
which allocates the necessary memory, calculates the spline coefficients
b and
c
and returns the (pointer to the) properly filled
qspline structure:
Tthe name of this function usually ends
with
struct qspline * qspline_alloc(int n, double* x,double* y);
_alloc to underline that it allocates memory in the
heap which then needs to be freed.
Implement a function 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); /* C or procedural C++ */
function<double(double)> lspline(vector&x,vector&y); /* functional C++ */
def linterp(x:list, y:list, z:float): # procedural python
struct qspline * qspline_alloc(int n, double *x, double *y); /* builds the quadratic spline */
double qspline_evaluate(struct qspline *s, double z); /* evaluates the spline at point z */
double qspline_derivative(struct qspline *s, double z); /* evaluates the derivative of the spline at point z */
double qspline_integral(struct qspline *s, double z); /* evaluates the integral of the spline from x[0] to z */
void qspline_free(struct qspline *s); /* free memory allocated in qspline_alloc */
function<double(double,int)> qspline(vector<double>& x,vector<double>& y); /* functional style */
or
struct qspline { /* object-oriented style */
vector<double> x,y,b,c;
qspline(vector<double> xtable, vector<double> ytable);
double eval(double z);
double deriv(double z);
double integ(double z);
};
def qspline(x:list,y:list) :
# calculate b[i],c[i]
def eval(z:float, deriv:int=0)
if deriv==1 : # calculate and return derivative
elif deriv==-1 : # calculate and return integral
else : # calculate and return spline
return eval # functional style
Hints:
graph
utility from
plotutils. Install it with sudo apt-get install
plotutils. An example of
graph
usage can be found
here and
here.
You
can also use pyxplot or gnuplot if you like.
(3 points) Cubic spline
(1 points) Vector structure/class/object
typedef struct {int size; double* data;} vector;
vector* vector_alloc(int n);
void vector_free(vector* v);
double vector_get(vector* v, int i); /* v_i */
void vector_set(vector* v, int i, double x); /* v_i = x */
namespace num{
struct vec{
int size;
std::vector<double> data;
vec(int n) : size(n), data(n) {};
double get(int n) {return data[i];};
void set(int i, double value) {data[i]=value;};
double& operator[] (int i) {return data[i];};
double& operator() (int i) {return data[i];};
}
}
import math, array
class vector(object):
def __init__(self, n:int, t:type='d') :
self.size=n
self.data=array.array(t,[0.0]*n)
def get(self,i:int) : return self.data[i]
def set(self,i:int,value): self.data[i]=value
def __getitem__ (self,i:int) : return self.data[i]
def __setitem__ (self,i:int,value) : self.data[i]=value
(0 points) Extra
octave, on lifa Octave is
/usr/users/fedorov/bin/octave.