## 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`.