GSL C++ Wrappers
The GNU Scientific Library is wicked. It has well-written C code and pretty good documentation for almost every numerical function I've needed so far. However, using raw C functions amongst oject-oriented C++ code can be difficult, ugly or repetitive. I write OO code because I think in terms of objects when I'm programming. So I wrote a few classes to help my translate, and I've used all of them many times in my GMF simulation.
Maximization
aon_maximize.h
aon_maximize.cpp
Usage:
First, define the mathematical function that you wish to maximize (if there are multiple arguments, the one to be maximized goes in 'Arg', the others are passed using a ParamStruct.
double myFunction(double Arg, void* Params)
{
// get the parameters from the void-pointer
myParamStruct myParams = *(myParamStruct *) Params;
double y = myParams.param1;
double z = myParams.param2;
double x = Arg;
// do your function, whatever it is
return x*y*y/exp(-z);
}
Then in your code, create a ParamStruct if necessary and setup the maximization.
myParamStruct myParams;
myParams.param1 = 0.5; myParams.param2 = 77.3;
Maximization myMax;
if (myMax.setFunction (&myFunction, &myParams) )
log_error();
Now, you can easily get the maximum of the function: the arguments to FindMaximum are Guess, LowerLimit and UpperLimit.
cout << "maximum: " << myMax.FindMaximum(25, 0, 50) << endl;
Interpolation
aon_interpolation.h
aon_interpolation.cpp
Usage:
Define a derived class and over-ride the abstract BuildSpline() function to produce the function you wish to interpolate. Pass any extra arguments as a list<double>.
MyInterpClass : public Interpolation
{
public:
MyInterpClass (const int NumPoints,
const gsl_interp_type *InterpType);
virtual int BuildSpline (const double& LowerBound,
const double& UpperBound,
list& ArgList);
};
The constructor is dead simple, choose the right interpretation type and the number of points you want. ( I use gsl_interp_cspline).
MyInterpClass::MyInterpClass(const int NumPoints,
const gsl_interp_type *InterpType)
: Interpolation (NumPoints, InterpType)
{
itsSpline = gsl_spline_alloc (InterpType, NumPoints);
itsAccel = gsl_interp_accel_alloc ();
}
The complicated part is building the spline. Here you have to understand how GSL interpolations work - the object orientation is in the way that you access the interpolation, rather than how you build it.
Create the over-riding BuildSpline function, in which we calculate the values for the spline, then use the gsl function to set it up.
int MyInterpClass::BuildSpline(const double& LowerBound,
const double& UpperBound,
list& ArgList)
{
// Get any arguments you may need from ArgList
double z = ArgList.pop_front();
// create the arrays that will hold our argument/value pairs
double *xa = new double[itsNumPoints];
double *ya = new double[itsNumPoints];
// Fill the arrays using the function y(x, [z1, z2...]) that
// you wish to interpolate
double Arg = LowerBound;
for (int i = 0; i < itsNumPoints; i++)
{
xa[i] = Arg;
ya[i] = some_expensive_operation (x, z);
Arg += (UpperBound - LowerBound)/ (itsNumPoints + 0.0);
}
// call the GSL function that sets up the interpolation
Status = gsl_spline_init (itsSpline, xa, ya, itsNumPoints);
delete []xa;
delete []ya;
if (Status)
return EXIT_FAILURE;
// set the status of the interpolation so that we can use it.
itsInitializedFlag = 1;
return 0;
}
OK, so we spent a long time writing the interpolation - now it is really easy to use:
Create the interpolation
// create interpolation. MyInterpClass MyInterp(1000, gsl_interp_cspline); // call BuildSpline listMyArgList; MyArgList.push_back(z); if ( MyInterp.BuildSpline(LowerBound, UpperBound, MyArgList) ) log_error();
And to access the interpolation:
if ( x < LowerBound )
{
return SomeApproxOfFunction(x);
}
if ( x > UpperBound )
{
return AnotherApproxOfFunction(x);
}
else
{
return MyInterpolation.Evaluate(x);
}
Bessel Functions
gmf_bessel.h
gmf_bessel.cpp
Usage:
This one is really easy - although it does use my debug functions.double K = BesselK(Nu, x);