Next: , Previous: Initializing the Solver, Up: One dimensional Root-Finding


32.4 Providing the function to solve

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:

— Data Type: gsl_function

This data type defines a general function with parameters.

double (* function) (double x, void * params)
this function should return the value f(x,params) for argument x and parameters params
void * params
a pointer to the parameters of the function

Here is an example for the general quadratic function,

     f(x) = a x^2 + b x + c

with a = 3, b = 2, 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 = &params;

The function f(x) can be evaluated using the following macro,

     #define GSL_FN_EVAL(F,x)
         (*((F)->function))(x,(F)->params)
— Data Type: gsl_function_fdf

This data type defines a general function with parameters and its first derivative.

double (* f) (double x, void * params)
this function should return the value of f(x,params) for argument x and parameters params
double (* df) (double x, void * params)
this function should return the value of the derivative of f with respect to x, f'(x,params), for argument x and parameters params
void (* fdf) (double x, void * params, double * f, double * df)
this function should set the values of the function f to f(x,params) and its derivative df to f'(x,params) for argument x and parameters params. This function provides an optimization of the separate functions for f(x) and f'(x)—it is always faster to compute the function and its derivative at the same time.
void * params
a pointer to the parameters of the function

Here is an example where 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 f(x) can be evaluated using the following macro,

     #define GSL_FN_FDF_EVAL_F(FDF,x)
          (*((FDF)->f))(x,(FDF)->params)

The derivative 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 y = f(x) and its derivative 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 f(x) in its y argument and f'(x) in its dy argument—both of these should be pointers to double.