You must provide a continuous function of one variable for the root finders to operate on, and, sometimes, its first derivative. In order to allow for general parameters the functions are defined by the following data types:
double (* function) (double x, void * params)
void * params
Here is an example for the general quadratic function,
with @math{a = 3}, @math{b = 2}, @math{c = 1}. The following code
defines a gsl_function
F
which you could pass to a root
finder:
struct my_f_params { double a; double b; double c; }; double my_f (double x, void * p) { struct my_f_params * params = (struct my_f_params *)p; double a = (params->a); double b = (params->b); double c = (params->c); return (a * x + b) * x + c; } gsl_function F; struct my_f_params params = { 3.0, 2.0, 1.0 }; F.function = &my_f; F.params = ¶ms;
The function @math{f(x)} can be evaluated using the following macro,
#define GSL_FN_EVAL(F,x) (*((F)->function))(x,(F)->params)
double (* f) (double x, void * params)
double (* df) (double x, void * params)
void (* fdf) (double x, void * params, double * f, double * df)
void * params
Here is an example where @math{f(x) = 2\exp(2x)}:
double my_f (double x, void * params) { return exp (2 * x); } double my_df (double x, void * params) { return 2 * exp (2 * x); } void my_fdf (double x, void * params, double * f, double * df) { double t = exp (2 * x); *f = t; *df = 2 * t; /* uses existing value */ } gsl_function_fdf FDF; FDF.f = &my_f; FDF.df = &my_df; FDF.fdf = &my_fdf; FDF.params = 0;
The function @math{f(x)} can be evaluated using the following macro,
#define GSL_FN_FDF_EVAL_F(FDF,x) (*((FDF)->f))(x,(FDF)->params)
The derivative @math{f'(x)} can be evaluated using the following macro,
#define GSL_FN_FDF_EVAL_DF(FDF,x) (*((FDF)->df))(x,(FDF)->params)
and both the function @math{y = f(x)} and its derivative @math{dy = f'(x)} can be evaluated at the same time using the following macro,
#define GSL_FN_FDF_EVAL_F_DF(FDF,x,y,dy) (*((FDF)->fdf))(x,(FDF)->params,(y),(dy))
The macro stores @math{f(x)} in its y argument and @math{f'(x)} in
its dy argument -- both of these should be pointers to
double
.