This is gsl-ref.info, produced by makeinfo version 4.2 from
gsl-ref.texi.

INFO-DIR-SECTION Scientific software
START-INFO-DIR-ENTRY
* gsl-ref: (gsl-ref).                   GNU Scientific Library - Reference
END-INFO-DIR-ENTRY


File: gsl-ref.info,  Node: Fitting Examples,  Next: Fitting References and Further Reading,  Prev: Multi-parameter fitting,  Up: Least-Squares Fitting

Examples
========

   The following program computes a least squares straight-line fit to a
simple (fictitious) dataset, and outputs the best-fit line and its
associated one standard-deviation error bars.

     #include <stdio.h>
     #include <gsl/gsl_fit.h>
     
     int
     main (void)
     {
       int i, n = 4;
       double x[4] = { 1970, 1980, 1990, 2000 };
       double y[4] = {   12,   11,   14,   13 };
       double w[4] = {  0.1,  0.2,  0.3,  0.4 };
     
       double c0, c1, cov00, cov01, cov11, chisq;
     
       gsl_fit_wlinear (x, 1, w, 1, y, 1, n,
                        &c0, &c1, &cov00, &cov01, &cov11,
                        &chisq);
     
       printf("# best fit: Y = %g + %g X\n", c0, c1);
       printf("# covariance matrix:\n");
       printf("# [ %g, %g\n#   %g, %g]\n",
              cov00, cov01, cov01, cov11);
       printf("# chisq = %g\n", chisq);
     
       for (i = 0; i < n; i++)
         printf("data: %g %g %g\n",
                       x[i], y[i], 1/sqrt(w[i]));
     
       printf("\n");
     
       for (i = -30; i < 130; i++)
         {
           double xf = x[0] + (i/100.0) * (x[n-1] - x[0]);
           double yf, yf_err;
     
           gsl_fit_linear_est (xf,
                               c0, c1,
                               cov00, cov01, cov11,
                               &yf, &yf_err);
     
           printf("fit: %g %g\n", xf, yf);
           printf("hi : %g %g\n", xf, yf + yf_err);
           printf("lo : %g %g\n", xf, yf - yf_err);
         }
       return 0;
     }

The following commands extract the data from the output of the program
and display it using the GNU plotutils `graph' utility,

     $ ./demo > tmp
     $ more tmp
     # best fit: Y = -106.6 + 0.06 X
     # covariance matrix:
     # [ 39602, -19.9
     #   -19.9, 0.01]
     # chisq = 0.8
     
     $ for n in data fit hi lo ;
        do
          grep "^$n" tmp | cut -d: -f2 > $n ;
        done
     $ graph -T X -X x -Y y -y 0 20 -m 0 -S 2 -Ie data
          -S 0 -I a -m 1 fit -m 2 hi -m 2 lo

   The next program performs a quadratic fit y = c_0 + c_1 x + c_2 x^2
to a weighted dataset using the generalised linear fitting function
`gsl_multifit_wlinear'.  The model matrix X for a quadratic fit is
given by,

     X = [ 1   , x_0  , x_0^2 ;
           1   , x_1  , x_1^2 ;
           1   , x_2  , x_2^2 ;
           ... , ...  , ...   ]

where the column of ones corresponds to the constant term c_0.  The two
remaining columns corresponds to the terms c_1 x and c_2 x^2.

   The program reads N lines of data in the format (X, Y, ERR) where
ERR is the error (standard deviation) in the value Y.

     #include <stdio.h>
     #include <gsl/gsl_multifit.h>
     
     int
     main (int argc, char **argv)
     {
       int i, n;
       double xi, yi, ei, chisq;
       gsl_matrix *X, *cov;
       gsl_vector *y, *w, *c;
     
       if (argc != 2)
         {
           fprintf(stderr,"usage: fit n < data\n");
           exit (-1);
         }
     
       n = atoi(argv[1]);
     
       X = gsl_matrix_alloc (n, 3);
       y = gsl_vector_alloc (n);
       w = gsl_vector_alloc (n);
     
       c = gsl_vector_alloc (3);
       cov = gsl_matrix_alloc (3, 3);
     
       for (i = 0; i < n; i++)
         {
           int count = fscanf(stdin, "%lg %lg %lg",
                              &xi, &yi, &ei);
     
           if (count != 3)
             {
               fprintf(stderr, "error reading file\n");
               exit(-1);
             }
     
           printf("%g %g +/- %g\n", xi, yi, ei);
     
           gsl_matrix_set (X, i, 0, 1.0);
           gsl_matrix_set (X, i, 1, xi);
           gsl_matrix_set (X, i, 2, xi*xi);
     
           gsl_vector_set (y, i, yi);
           gsl_vector_set (w, i, 1.0/(ei*ei));
         }
     
       {
         gsl_multifit_linear_workspace * work
           = gsl_multifit_linear_alloc (n, 3);
         gsl_multifit_wlinear (X, w, y, c, cov,
                               &chisq, work);
         gsl_multifit_linear_free (work);
       }
     
     #define C(i) (gsl_vector_get(c,(i)))
     #define COV(i,j) (gsl_matrix_get(cov,(i),(j)))
     
       {
         printf("# best fit: Y = %g + %g X + %g X^2\n",
                C(0), C(1), C(2));
     
         printf("# covariance matrix:\n");
         printf("[ %+.5e, %+.5e, %+.5e  \n",
                   COV(0,0), COV(0,1), COV(0,2));
         printf("  %+.5e, %+.5e, %+.5e  \n",
                   COV(1,0), COV(1,1), COV(1,2));
         printf("  %+.5e, %+.5e, %+.5e ]\n",
                   COV(2,0), COV(2,1), COV(2,2));
         printf("# chisq = %g\n", chisq);
       }
       return 0;
     }

A suitable set of data for fitting can be generated using the following
program.  It outputs a set of points with gaussian errors from the curve
y = e^x in the region 0 < x < 2.

     #include <stdio.h>
     #include <math.h>
     #include <gsl/gsl_randist.h>
     
     int
     main (void)
     {
       double x;
       const gsl_rng_type * T;
       gsl_rng * r;
     
       gsl_rng_env_setup();
     
       T = gsl_rng_default;
       r = gsl_rng_alloc(T);
     
       for (x = 0.1; x < 2; x+= 0.1)
         {
           double y0 = exp(x);
           double sigma = 0.1*y0;
           double dy = gsl_ran_gaussian(r, sigma);
     
           printf("%g %g %g\n", x, y0 + dy, sigma);
         }
       return 0;
     }

The data can be prepared by running the resulting executable program,

     $ ./generate > exp.dat
     $ more exp.dat
     0.1 0.97935 0.110517
     0.2 1.3359 0.12214
     0.3 1.52573 0.134986
     0.4 1.60318 0.149182
     0.5 1.81731 0.164872
     0.6 1.92475 0.182212
     ....

To fit the data use the previous program, with the number of data points
given as the first argument.  In this case there are 19 data points.

     $ ./fit 19 < exp.dat
     0.1 0.97935 +/- 0.110517
     0.2 1.3359 +/- 0.12214
     ...
     # best fit: Y = 1.02318 + 0.956201 X + 0.876796 X^2
     # covariance matrix:
     [ +1.25612e-02, -3.64387e-02, +1.94389e-02
       -3.64387e-02, +1.42339e-01, -8.48761e-02
       +1.94389e-02, -8.48761e-02, +5.60243e-02 ]
     # chisq = 23.0987

The parameters of the quadratic fit match the coefficients of the
expansion of e^x, taking into account the errors on the parameters and
the O(x^3) difference between the exponential and quadratic functions
for the larger values of x.  The errors on the parameters are given by
the square-root of the corresponding diagonal elements of the
covariance matrix.  The chi-squared per degree of freedom is 1.4,
indicating a reasonable fit to the data.


File: gsl-ref.info,  Node: Fitting References and Further Reading,  Prev: Fitting Examples,  Up: Least-Squares Fitting

References and Further Reading
==============================

A summary of formulas and techniques for least squares fitting can be
found in the "Statistics" chapter of the Annual Review of Particle
Physics prepared by the Particle Data Group.

     `Review of Particle Properties' R.M. Barnett et al., Physical
     Review D54, 1 (1996) <http://pdg.lbl.gov/>

The Review of Particle Physics is available online at the website given
above.

The tests used to prepare these routines are based on the NIST
Statistical Reference Datasets. The datasets and their documentation are
available from NIST at the following website,

           <http://www.nist.gov/itl/div898/strd/index.html>.


File: gsl-ref.info,  Node: Nonlinear Least-Squares Fitting,  Next: Physical Constants,  Prev: Least-Squares Fitting,  Up: Top

Nonlinear Least-Squares Fitting
*******************************

   This chapter describes functions for multidimensional nonlinear
least-squares fitting.  The library provides low level components for a
variety of iterative solvers and convergence tests.  These can be
combined by the user to achieve the desired solution, with full access
to the intermediate steps of the iteration.  Each class of methods uses
the same framework, so that you can switch between solvers at runtime
without needing to recompile your program.  Each instance of a solver
keeps track of its own state, allowing the solvers to be used in
multi-threaded programs.

   The header file `gsl_multifit_nlin.h' contains prototypes for the
multidimensional nonlinear fitting functions and related declarations.

* Menu:

* Overview of Nonlinear Least-Squares Fitting::
* Initializing the Nonlinear Least-Squares Solver::
* Providing the Function to be Minimized::
* Iteration of the Minimization Algorithm::
* Search Stopping Parameters for Minimization Algorithms::
* Minimization Algorithms using Derivatives::
* Minimization Algorithms without Derivatives::
* Computing the covariance matrix of best fit parameters::
* Example programs for Nonlinear Least-Squares Fitting::
* References and Further Reading for Nonlinear Least-Squares Fitting::


File: gsl-ref.info,  Node: Overview of Nonlinear Least-Squares Fitting,  Next: Initializing the Nonlinear Least-Squares Solver,  Up: Nonlinear Least-Squares Fitting

Overview
========

   The problem of multidimensional nonlinear least-squares fitting
requires the minimization of the squared residuals of n functions, f_i,
in p parameters, x_i,

     \Phi(x) = (1/2) \sum_{i=1}^{n} f_i(x_1, ..., x_p)^2
             = (1/2) || F(x) ||^2

All algorithms proceed from an initial guess using the linearization,

     \psi(p) = || F(x+p) || ~=~ || F(x) + J p ||

where x is the initial point, p is the proposed step and J is the
Jacobian matrix J_{ij} = d f_i / d x_j.  Additional strategies are used
to enlarge the region of convergence.  These include requiring a
decrease in the norm ||F|| on each step or using a trust region to
avoid steps which fall outside the linear regime.


File: gsl-ref.info,  Node: Initializing the Nonlinear Least-Squares Solver,  Next: Providing the Function to be Minimized,  Prev: Overview of Nonlinear Least-Squares Fitting,  Up: Nonlinear Least-Squares Fitting

Initializing the Solver
=======================

 - Function: gsl_multifit_fsolver * gsl_multifit_fsolver_alloc (const
          gsl_multifit_fsolver_type * T, size_t N, size_t P)
     This function returns a pointer to a newly allocated instance of a
     solver of type T for N observations and P parameters.

     If there is insufficient memory to create the solver then the
     function returns a null pointer and the error handler is invoked
     with an error code of `GSL_ENOMEM'.

 - Function: gsl_multifit_fdfsolver * gsl_multifit_fdfsolver_alloc
          (const gsl_multifit_fdfsolver_type * T, size_t N, size_t P)
     This function returns a pointer to a newly allocated instance of a
     derivative solver of type T for N observations and P parameters.
     For example, the following code creates an instance of a
     Levenberg-Marquardt solver for 100 data points and 3 parameters,

          const gsl_multifit_fdfsolver_type * T
              = gsl_multifit_fdfsolver_lmder;
          gsl_multifit_fdfsolver * s
              = gsl_multifit_fdfsolver_alloc (T, 100, 3);

     If there is insufficient memory to create the solver then the
     function returns a null pointer and the error handler is invoked
     with an error code of `GSL_ENOMEM'.

 - Function: int gsl_multifit_fsolver_set (gsl_multifit_fsolver * S,
          gsl_multifit_function * F, gsl_vector * X)
     This function initializes, or reinitializes, an existing solver S
     to use the function F and the initial guess X.

 - Function: int gsl_multifit_fdfsolver_set (gsl_multifit_fdfsolver *
          S, gsl_function_fdf * FDF, gsl_vector * X)
     This function initializes, or reinitializes, an existing solver S
     to use the function and derivative FDF and the initial guess X.

 - Function: void gsl_multifit_fsolver_free (gsl_multifit_fsolver * S)
 - Function: void gsl_multifit_fdfsolver_free (gsl_multifit_fdfsolver *
          S)
     These functions free all the memory associated with the solver S.

 - Function: const char * gsl_multifit_fsolver_name (const
          gsl_multifit_fdfsolver * S)
 - Function: const char * gsl_multifit_fdfsolver_name (const
          gsl_multifit_fdfsolver * S)
     These functions return a pointer to the name of the solver.  For
     example,

          printf("s is a '%s' solver\n",
                 gsl_multifit_fdfsolver_name (s));

     would print something like `s is a 'lmder' solver'.


File: gsl-ref.info,  Node: Providing the Function to be Minimized,  Next: Iteration of the Minimization Algorithm,  Prev: Initializing the Nonlinear Least-Squares Solver,  Up: Nonlinear Least-Squares Fitting

Providing the Function to be Minimized
======================================

   You must provide n functions of p variables for the minimization
algorithms to operate on.  In order to allow for general parameters the
functions are defined by the following data types:

 - Data Type: gsl_multifit_function
     This data type defines a general system of functions with
     parameters.

    `int (* f) (const gsl_vector * X, void * PARAMS, gsl_vector * F)'
          this function should store the vector result f(x,params) in F
          for argument X and parameters PARAMS, returning an
          appropriate error code if the function cannot be computed.

    `size_t N'
          the number of functions, i.e. the number of components of the
          vector F

    `size_t P'
          the number of independent variables, i.e. the number of
          components of the vectors X

    `void * PARAMS'
          a pointer to the parameters of the function

 - Data Type: gsl_multifit_function_fdf
     This data type defines a general system of functions with
     parameters and the corresponding Jacobian matrix of derivatives,

    `int (* f) (const gsl_vector * X, void * PARAMS, gsl_vector * F)'
          this function should store the vector result f(x,params) in F
          for argument X and parameters PARAMS, returning an
          appropriate error code if the function cannot be computed.

    `int (* df) (const gsl_vector * X, void * PARAMS, gsl_matrix * J)'
          this function should store the N-by-P matrix result J_ij = d
          f_i(x,params) / d x_j in J for argument X and parameters
          PARAMS, returning an appropriate error code if the function
          cannot be computed.

    `int (* fdf) (const gsl_vector * X, void * PARAMS, gsl_vector * F, gsl_matrix * J)'
          This function should set the values of the F and J as above,
          for arguments X and parameters PARAMS.  This function provides
          an optimization of the separate functions for f(x) and J(x) -
          it is always faster to compute the function and its
          derivative at the same time.

    `size_t N'
          the number of functions, i.e. the number of components of the
          vector F

    `size_t P'
          the number of independent variables, i.e. the number of
          components of the vectors X

    `void * PARAMS'
          a pointer to the parameters of the function


File: gsl-ref.info,  Node: Iteration of the Minimization Algorithm,  Next: Search Stopping Parameters for Minimization Algorithms,  Prev: Providing the Function to be Minimized,  Up: Nonlinear Least-Squares Fitting

Iteration
=========

   The following functions drive the iteration of each algorithm.  Each
function performs one iteration to update the state of any solver of the
corresponding type.  The same functions work for all solvers so that
different methods can be substituted at runtime without modifications to
the code.

 - Function: int gsl_multifit_fsolver_iterate (gsl_multifit_fsolver * S)
 - Function: int gsl_multifit_fdfsolver_iterate (gsl_multifit_fdfsolver
          * S)
     These functions perform a single iteration of the solver S.  If
     the iteration encounters an unexpected problem then an error code
     will be returned.  The solver maintains a current estimate of the
     best-fit parameters at all times. This information can be accessed
     with the following auxiliary functions,

 - Function: gsl_vector * gsl_multifit_fsolver_position (const
          gsl_multifit_fsolver * S)
 - Function: gsl_vector * gsl_multifit_fdfsolver_position (const
          gsl_multifit_fdfsolver * S)
     These functions return the current position (i.e. best-fit
     parameters) of the solver S.


File: gsl-ref.info,  Node: Search Stopping Parameters for Minimization Algorithms,  Next: Minimization Algorithms using Derivatives,  Prev: Iteration of the Minimization Algorithm,  Up: Nonlinear Least-Squares Fitting

Search Stopping Parameters
==========================

   A minimization procedure should stop when one of the following
conditions is true:

   * A minimum has been found to within the user-specified precision.

   * A user-specified maximum number of iterations has been reached.

   * An error has occurred.

The handling of these conditions is under user control.  The functions
below allow the user to test the current estimate of the best-fit
parameters in several standard ways.

 - Function: int gsl_multifit_test_delta (const gsl_vector * DX, const
          gsl_vector * X, double EPSABS, double EPSREL)
     This function tests for the convergence of the sequence by
     comparing the last step DX with the absolute error EPSABS and
     relative error EPSREL to the current position X.  The test returns
     `GSL_SUCCESS' if the following condition is achieved,

          |dx_i| < epsabs + epsrel |x_i|

     for each component of X and returns `GSL_CONTINUE' otherwise.

 - Function: int gsl_multifit_test_gradient (const gsl_vector * G,
          double EPSABS)
     This function tests the residual gradient G against the absolute
     error bound EPSABS.  Mathematically, the gradient should be
     exactly zero at the minimum. The test returns `GSL_SUCCESS' if the
     following condition is achieved,

          \sum_i |g_i| < epsabs

     and returns `GSL_CONTINUE' otherwise.  This criterion is suitable
     for situations where the precise location of the minimum, x, is
     unimportant provided a value can be found where the gradient is
     small enough.

 - Function: int gsl_multifit_gradient (const gsl_matrix * J, const
          gsl_vector * F, gsl_vector * G)
     This function computes the gradient G of \Phi(x) = (1/2)
     ||F(x)||^2 from the Jacobian matrix J and the function values F,
     using the formula g = J^T f.


File: gsl-ref.info,  Node: Minimization Algorithms using Derivatives,  Next: Minimization Algorithms without Derivatives,  Prev: Search Stopping Parameters for Minimization Algorithms,  Up: Nonlinear Least-Squares Fitting

Minimization Algorithms using Derivatives
=========================================

   The minimization algorithms described in this section make use of
both the function and its derivative.  They require an initial guess
for the location of the minimum. There is no absolute guarantee of
convergence - the function must be suitable for this technique and the
initial guess must be sufficiently close to the minimum for it to work.

 - Derivative Solver: gsl_multifit_fdfsolver_lmsder
     This is a robust and efficient version of the Levenberg-Marquardt
     algorithm as implemented in the scaled LMDER routine in MINPACK.
     Minpack was written by Jorge J. More', Burton S. Garbow and
     Kenneth E. Hillstrom.

     The algorithm uses a generalized trust region to keep each step
     under control.  In order to be accepted a proposed new position x'
     must satisfy the condition |D (x' - x)| < \delta, where D is a
     diagonal scaling matrix and \delta is the size of the trust
     region.  The components of D are computed internally, using the
     column norms of the Jacobian to estimate the sensitivity of the
     residual to each component of x.  This improves the behavior of the
     algorithm for badly scaled functions.

     On each iteration the algorithm attempts to minimize the linear
     system |F + J p| subject to the constraint |D p| < \Delta.  The
     solution to this constrained linear system is found using the
     Levenberg-Marquardt method.

     The proposed step is now tested by evaluating the function at the
     resulting point, x'.  If the step reduces the norm of the function
     sufficiently, and follows the predicted behavior of the function
     within the trust region. then it is accepted and size of the trust
     region is increased.  If the proposed step fails to improve the
     solution, or differs significantly from the expected behavior
     within the trust region, then the size of the trust region is
     decreased and another trial step is computed.

     The algorithm also monitors the progress of the solution and
     returns an error if the changes in the solution are smaller than
     the machine precision.  The possible error codes are,

    `GSL_ETOLF'
          the decrease in the function falls below machine precision

    `GSL_ETOLX'
          the change in the position vector falls below machine
          precision

    `GSL_ETOLG'
          the norm of the gradient, relative to the norm of the
          function, falls below machine precision

     These error codes indicate that further iterations will be
     unlikely to change the solution from its current value.


 - Derivative Solver: gsl_multifit_fdfsolver_lmder
     This is an unscaled version of the LMDER algorithm.  The elements
     of the diagonal scaling matrix D are set to 1.  This algorithm may
     be useful in circumstances where the scaled version of LMDER
     converges too slowly, or the function is already scaled
     appropriately.


File: gsl-ref.info,  Node: Minimization Algorithms without Derivatives,  Next: Computing the covariance matrix of best fit parameters,  Prev: Minimization Algorithms using Derivatives,  Up: Nonlinear Least-Squares Fitting

Minimization Algorithms without Derivatives
===========================================

   There are no algorithms implemented in this section at the moment.


File: gsl-ref.info,  Node: Computing the covariance matrix of best fit parameters,  Next: Example programs for Nonlinear Least-Squares Fitting,  Prev: Minimization Algorithms without Derivatives,  Up: Nonlinear Least-Squares Fitting

Computing the covariance matrix of best fit parameters
======================================================

 - Function: int gsl_multifit_covar (const gsl_matrix * J, double
          EPSREL, gsl_matrix * COVAR)
     This function uses the Jacobian matrix J to compute the covariance
     matrix of the best-fit parameters, COVAR.  The parameter EPSREL is
     used to remove linear-dependent columns when J is rank deficient.

     The covariance matrix is given by,

          covar = (J^T J)^{-1}

     and is computed by QR decomposition of J with column-pivoting.  Any
     columns of R which satisfy

          |R_{kk}| <= epsrel |R_{11}|

     are considered linearly-dependent and are excluded from the
     covariance matrix (the corresponding rows and columns of the
     covariance matrix are set to zero).


File: gsl-ref.info,  Node: Example programs for Nonlinear Least-Squares Fitting,  Next: References and Further Reading for Nonlinear Least-Squares Fitting,  Prev: Computing the covariance matrix of best fit parameters,  Up: Nonlinear Least-Squares Fitting

Examples
========

   The following example program fits a weighted exponential model with
background to experimental data, Y = A \exp(-\lambda t) + b. The first
part of the program sets up the functions `expb_f' and `expb_df' to
calculate the model and its Jacobian.  The appropriate fitting function
is given by,

     f_i = ((A \exp(-\lambda t_i) + b) - y_i)/\sigma_i

where we have chosen t_i = i.  The Jacobian matrix J is the derivative
of these functions with respect to the three parameters (A, \lambda,
b).  It is given by,

     J_{ij} = d f_i / d x_j

where x_0 = A, x_1 = \lambda and x_2 = b.

     #include <stdlib.h>
     #include <stdio.h>
     #include <gsl/gsl_rng.h>
     #include <gsl/gsl_randist.h>
     #include <gsl/gsl_vector.h>
     #include <gsl/gsl_blas.h>
     #include <gsl/gsl_multifit_nlin.h>
     
     struct data {
       size_t n;
       double * y;
       double * sigma;
     };
     
     int
     expb_f (const gsl_vector * x, void *params,
             gsl_vector * f)
     {
       size_t n = ((struct data *)params)->n;
       double *y = ((struct data *)params)->y;
       double *sigma = ((struct data *) params)->sigma;
     
       double A = gsl_vector_get (x, 0);
       double lambda = gsl_vector_get (x, 1);
       double b = gsl_vector_get (x, 2);
     
       size_t i;
     
       for (i = 0; i < n; i++)
         {
           /* Model Yi = A * exp(-lambda * i) + b */
           double t = i;
           double Yi = A * exp (-lambda * t) + b;
           gsl_vector_set (f, i, (Yi - y[i])/sigma[i]);
         }
     
       return GSL_SUCCESS;
     }
     
     int
     expb_df (const gsl_vector * x, void *params,
              gsl_matrix * J)
     {
       size_t n = ((struct data *)params)->n;
       double *sigma = ((struct data *) params)->sigma;
     
       double A = gsl_vector_get (x, 0);
       double lambda = gsl_vector_get (x, 1);
     
       size_t i;
     
       for (i = 0; i < n; i++)
         {
           /* Jacobian matrix J(i,j) = dfi / dxj, */
           /* where fi = (Yi - yi)/sigma[i],      */
           /*       Yi = A * exp(-lambda * i) + b  */
           /* and the xj are the parameters (A,lambda,b) */
           double t = i;
           double s = sigma[i];
           double e = exp(-lambda * t);
           gsl_matrix_set (J, i, 0, e/s);
           gsl_matrix_set (J, i, 1, -t * A * e/s);
           gsl_matrix_set (J, i, 2, 1/s);
     
     
         }
       return GSL_SUCCESS;
     }
     
     int
     expb_fdf (const gsl_vector * x, void *params,
               gsl_vector * f, gsl_matrix * J)
     {
       expb_f (x, params, f);
       expb_df (x, params, J);
     
       return GSL_SUCCESS;
     }

The main part of the program sets up a Levenberg-Marquardt solver and
some simulated random data. The data uses the known parameters
(1.0,5.0,0.1) combined with gaussian noise (standard deviation = 0.1)
over a range of 40 timesteps. The initial guess for the parameters is
chosen as (0.0, 1.0, 0.0).

     #define N 40
     
     int
     main (void)
     {
       const gsl_multifit_fdfsolver_type *T;
       gsl_multifit_fdfsolver *s;
     
       int status;
       size_t i, iter = 0;
     
       const size_t n = N;
       const size_t p = 3;
     
       gsl_matrix *covar = gsl_matrix_alloc (p, p);
     
       double y[N], sigma[N];
     
       struct data d = { n, y, sigma};
     
       gsl_multifit_function_fdf f;
     
       double x_init[3] = { 1.0, 0.0, 0.0 };
     
       gsl_vector_view x = gsl_vector_view_array (x_init, p);
     
       const gsl_rng_type * type;
       gsl_rng * r;
     
       gsl_rng_env_setup();
     
       type = gsl_rng_default;
       r = gsl_rng_alloc (type);
     
       f.f = &expb_f;
       f.df = &expb_df;
       f.fdf = &expb_fdf;
       f.n = n;
       f.p = p;
       f.params = &d;
     
       /* This is the data to be fitted */
     
       for (i = 0; i < n; i++)
         {
           double t = i;
           y[i] = 1.0 + 5 * exp (-0.1 * t)
                      + gsl_ran_gaussian(r, 0.1);
           sigma[i] = 0.1;
           printf("data: %d %g %g\n", i, y[i], sigma[i]);
         };
     
     
       T = gsl_multifit_fdfsolver_lmsder;
       s = gsl_multifit_fdfsolver_alloc (T, n, p);
       gsl_multifit_fdfsolver_set (s, &f, &x.vector);
     
       print_state (iter, s);
     
       do
         {
           iter++;
           status = gsl_multifit_fdfsolver_iterate (s);
     
           printf ("status = %s\n", gsl_strerror (status));
     
           print_state (iter, s);
     
           if (status)
             break;
     
           status = gsl_multifit_test_delta (s->dx, s->x,
                                             1e-4, 1e-4);
         }
       while (status == GSL_CONTINUE && iter < 500);
     
       gsl_multifit_covar (s->J, 0.0, covar);
     
       gsl_matrix_fprintf (stdout, covar, "%g");
     
     #define FIT(i) gsl_vector_get(s->x, i)
     #define ERR(i) sqrt(gsl_matrix_get(covar,i,i))
     
       printf("A      = %.5f +/- %.5f\n", FIT(0), ERR(0));
       printf("lambda = %.5f +/- %.5f\n", FIT(1), ERR(1));
       printf("b      = %.5f +/- %.5f\n", FIT(2), ERR(2));
     
       printf ("status = %s\n", gsl_strerror (status));
     
       gsl_multifit_fdfsolver_free (s);
       return 0;
     }
     
     int
     print_state (size_t iter, gsl_multifit_fdfsolver * s)
     {
       printf ("iter: %3u x = % 15.8f % 15.8f % 15.8f "
               "|f(x)| = %g\n",
               iter,
               gsl_vector_get (s->x, 0),
               gsl_vector_get (s->x, 1),
               gsl_vector_get (s->x, 2),
               gsl_blas_dnrm2 (s->f));
     }

The iteration terminates when the change in x is smaller than 0.0001, as
both an absolute and relative change.  Here are the results of running
the program,

     iter: 0 x = 1.00000000 0.00000000 0.00000000 |f(x)| = 118.574
     iter: 1 x = 1.64919392 0.01780040 0.64919392 |f(x)| = 77.2068
     iter: 2 x = 2.86269020 0.08032198 1.45913464 |f(x)| = 38.0579
     iter: 3 x = 4.97908864 0.11510525 1.06649948 |f(x)| = 10.1548
     iter: 4 x = 5.03295496 0.09912462 1.00939075 |f(x)| = 6.4982
     iter: 5 x = 5.05811477 0.10055914 0.99819876 |f(x)| = 6.33121
     iter: 6 x = 5.05827645 0.10051697 0.99756444 |f(x)| = 6.33119
     iter: 7 x = 5.05828006 0.10051819 0.99757710 |f(x)| = 6.33119
     
     A      = 5.05828 +/- 0.05983
     lambda = 0.10052 +/- 0.00309
     b      = 0.99758 +/- 0.03944
     status = success

The approximate values of the parameters are found correctly.  The
errors on the parameters are given by the square roots of the diagonal
elements of the covariance matrix.


File: gsl-ref.info,  Node: References and Further Reading for Nonlinear Least-Squares Fitting,  Prev: Example programs for Nonlinear Least-Squares Fitting,  Up: Nonlinear Least-Squares Fitting

References and Further Reading
==============================

The MINPACK algorithm is described in the following article,

     J.J. More', `The Levenberg-Marquardt Algorithm: Implementation and
     Theory', Lecture Notes in Mathematics, v630 (1978), ed G. Watson.

The following paper is also relevant to the algorithms described in this
section,

     J.J. More', B.S. Garbow, K.E. Hillstrom, "Testing Unconstrained
     Optimization Software", ACM Transactions on Mathematical Software,
     Vol 7, No 1 (1981), p 17-41


File: gsl-ref.info,  Node: Physical Constants,  Next: IEEE floating-point arithmetic,  Prev: Nonlinear Least-Squares Fitting,  Up: Top

Physical Constants
******************

   This chapter describes macros for the values of physical constants,
such as the speed of light, c, and gravitational constant, G.  The
values are available in different unit systems, including the standard
MKS system (meters, kilograms, seconds) and the CGS system
(centimeters, grams, seconds), which is commonly used in Astronomy.

   The definitions of constants in the MKS system are available in the
file `gsl_const_mks.h'.  The constants in the CGS system are defined in
`gsl_const_cgs.h'.  Dimensionless constants, such as the fine structure
constant, which are pure numbers are defined in `gsl_const_num.h'.

* Menu:

* Fundamental Constants::
* Astronomy and Astrophysics::
* Atomic and Nuclear Physics::
* Measurement of Time::
* Imperial Units ::
* Nautical Units::
* Printers Units::
* Volume::
* Mass and Weight ::
* Thermal Energy and Power::
* Pressure::
* Viscosity::
* Light and Illumination::
* Radioactivity::
* Force and Energy::
* Prefixes::
* Physical Constant Examples::
* Physical Constant References and Further Reading::

   The full list of constants is described briefly below.  Consult the
header files themselves for the values of the constants used in the
library.


File: gsl-ref.info,  Node: Fundamental Constants,  Next: Astronomy and Astrophysics,  Up: Physical Constants

Fundamental Constants
=====================

`GSL_CONST_MKS_SPEED_OF_LIGHT'
     The speed of light in vacuum, c.

`GSL_CONST_MKS_VACUUM_PERMEABILITY'
     The permeability of free space, \mu_0

`GSL_CONST_MKS_VACUUM_PERMITTIVITY'
     The permittivity of free space, \epsilon_0.

`GSL_CONST_NUM_AVOGADRO'
     Avogadro's number, N_a.

`GSL_CONST_MKS_FARADAY'
     The molar charge of 1 Faraday.

`GSL_CONST_MKS_BOLTZMANN'
     The Boltzmann constant, k.

`GSL_CONST_MKS_MOLAR_GAS'
     The molar gas constant, R_0.

`GSL_CONST_MKS_STANDARD_GAS_VOLUME'
     The standard gas volume, V_0.

`GSL_CONST_MKS_GAUSS'
     The magnetic field of 1 Gauss.

`GSL_CONST_MKS_MICRON'
     The length of 1 micron.

`GSL_CONST_MKS_HECTARE'
     The area of 1 hectare.

`GSL_CONST_MKS_MILES_PER_HOUR'
     The speed of 1 mile per hour.

`GSL_CONST_MKS_KILOMETERS_PER_HOUR'
     The speed of 1 kilometer per hour.


File: gsl-ref.info,  Node: Astronomy and Astrophysics,  Next: Atomic and Nuclear Physics,  Prev: Fundamental Constants,  Up: Physical Constants

Astronomy and Astrophysics
==========================

`GSL_CONST_MKS_ASTRONOMICAL_UNIT'
     The length of 1 astronomical unit (mean earth-sun distance), au.

`GSL_CONST_MKS_GRAVITATIONAL_CONSTANT'
     The gravitational constant, G.

`GSL_CONST_MKS_LIGHT_YEAR'
     The distance of 1 light-year, ly.

`GSL_CONST_MKS_PARSEC'
     The distance of 1 parsec, pc.

`GSL_CONST_MKS_GRAV_ACCEL'
     The standard gravitational acceleration on Earth, g.

`GSL_CONST_MKS_SOLAR_MASS'
     The mass of the Sun.


File: gsl-ref.info,  Node: Atomic and Nuclear Physics,  Next: Measurement of Time,  Prev: Astronomy and Astrophysics,  Up: Physical Constants

Atomic and Nuclear Physics
==========================

`GSL_CONST_MKS_ELECTRON_CHARGE'
     The charge of the electron, e.

`GSL_CONST_MKS_ELECTRON_VOLT'
     The energy of 1 electron volt, eV.

`GSL_CONST_MKS_UNIFIED_ATOMIC_MASS'
     The unified atomic mass, amu.

`GSL_CONST_MKS_MASS_ELECTRON'
     The mass of the electron, m_e.

`GSL_CONST_MKS_MASS_MUON'
     The mass of the muon, m_\mu.

`GSL_CONST_MKS_MASS_PROTON'
     The mass of the proton, m_p.

`GSL_CONST_MKS_MASS_NEUTRON'
     The mass of the neutron, m_n.

`GSL_CONST_NUM_FINE_STRUCTURE'
     The electromagnetic fine structure constant \alpha.

`GSL_CONST_MKS_RYDBERG'
     The Rydberg constant, Ry, in units of energy.  This is related to
     the Rydberg inverse wavelength R by Ry = h c R.

`GSL_CONST_MKS_BOHR_RADIUS'
     The Bohr radius, a_0.

`GSL_CONST_MKS_ANGSTROM'
     The length of 1 angstrom.

`GSL_CONST_MKS_BARN'
     The area of 1 barn.

`GSL_CONST_MKS_BOHR_MAGNETON'
     The Bohr Magneton, \mu_B.

`GSL_CONST_MKS_NUCLEAR_MAGNETON'
     The Nuclear Magneton, \mu_N.

`GSL_CONST_MKS_ELECTRON_MAGNETIC_MOMENT'
     The absolute value of the magnetic moment of the electron, \mu_e.
     The physical magnetic moment of the election is negative.

`GSL_CONST_MKS_PROTON_MAGNETIC_MOMENT'
     The magnetic moment of the proton, \mu_p.


File: gsl-ref.info,  Node: Measurement of Time,  Next: Imperial Units,  Prev: Atomic and Nuclear Physics,  Up: Physical Constants

Measurement of Time
===================

`GSL_CONST_MKS_MINUTE'
     The number of seconds in 1 minute.

`GSL_CONST_MKS_HOUR'
     The number of seconds in 1 hour.

`GSL_CONST_MKS_DAY'
     The number of seconds in 1 day.

`GSL_CONST_MKS_WEEK'
     The number of seconds in 1 week.


File: gsl-ref.info,  Node: Imperial Units,  Next: Nautical Units,  Prev: Measurement of Time,  Up: Physical Constants

Imperial Units
==============

`GSL_CONST_MKS_INCH'
     The length of 1 inch.

`GSL_CONST_MKS_FOOT'
     The length of 1 foot.

`GSL_CONST_MKS_YARD'
     The length of 1 yard.

`GSL_CONST_MKS_MILE'
     The length of 1 mile.

`GSL_CONST_MKS_MIL'
     The length of 1 mil (1/1000th of an inch).


File: gsl-ref.info,  Node: Nautical Units,  Next: Printers Units,  Prev: Imperial Units,  Up: Physical Constants

Nautical Units
==============

`GSL_CONST_MKS_NAUTICAL_MILE'
     The length of 1 nautical mile.

`GSL_CONST_MKS_FATHOM'
     The length of 1 fathom.

`GSL_CONST_MKS_KNOT'
     The speed of 1 knot.


File: gsl-ref.info,  Node: Printers Units,  Next: Volume,  Prev: Nautical Units,  Up: Physical Constants

Printers Units
==============

`GSL_CONST_MKS_POINT'
     The length of 1 printer's point (1/72 inch).

`GSL_CONST_MKS_TEXPOINT'
     The length of 1 TeX point (1/72.27 inch).


File: gsl-ref.info,  Node: Volume,  Next: Mass and Weight,  Prev: Printers Units,  Up: Physical Constants

Volume
======

`GSL_CONST_MKS_ACRE'
     The area of 1 acre.

`GSL_CONST_MKS_LITER'
     The volume of 1 liter.

`GSL_CONST_MKS_US_GALLON'
     The volume of 1 US gallon.

`GSL_CONST_MKS_CANADIAN_GALLON'
     The volume of 1 Canadian gallon.

`GSL_CONST_MKS_UK_GALLON'
     The volume of 1 UK gallon.

`GSL_CONST_MKS_QUART'
     The volume of 1 quart.

`GSL_CONST_MKS_PINT'
     The volume of 1 pint.


File: gsl-ref.info,  Node: Mass and Weight,  Next: Thermal Energy and Power,  Prev: Volume,  Up: Physical Constants

Mass and Weight
===============

`GSL_CONST_MKS_POUND_MASS'
     The mass of 1 pound.

`GSL_CONST_MKS_OUNCE_MASS'
     The mass of 1 ounce.

`GSL_CONST_MKS_TON'
     The mass of 1 ton.

`GSL_CONST_MKS_METRIC_TON'
     The mass of 1 metric ton (1000 kg).

`GSL_CONST_MKS_UK_TON'
     The mass of 1 UK ton.

`GSL_CONST_MKS_TROY_OUNCE'
     The mass of 1 troy ounce.

`GSL_CONST_MKS_CARAT'
     The mass of 1 carat.

`GSL_CONST_MKS_GRAM_FORCE'
     The force of 1 gram weight.

`GSL_CONST_MKS_POUND_FORCE'
     The force of 1 pound weight.

`GSL_CONST_MKS_KILOPOUND_FORCE'
     The force of 1 kilopound weight.

`GSL_CONST_MKS_POUNDAL'
     The force of 1 poundal.


File: gsl-ref.info,  Node: Thermal Energy and Power,  Next: Pressure,  Prev: Mass and Weight,  Up: Physical Constants

Thermal Energy and Power
========================

`GSL_CONST_MKS_CALORIE'
     The energy of 1 calorie.

`GSL_CONST_MKS_BTU'
     The energy of 1 British Thermal Unit, btu.

`GSL_CONST_MKS_THERM'
     The energy of 1 Therm.

`GSL_CONST_MKS_HORSEPOWER'
     The power of 1 horsepower.


File: gsl-ref.info,  Node: Pressure,  Next: Viscosity,  Prev: Thermal Energy and Power,  Up: Physical Constants

Pressure
========

`GSL_CONST_MKS_BAR'
     The pressure of 1 bar.

`GSL_CONST_MKS_STD_ATMOSPHERE'
     The pressure of 1 standard atmosphere.

`GSL_CONST_MKS_TORR'
     The pressure of 1 torr.

`GSL_CONST_MKS_METER_OF_MERCURY'
     The pressure of 1 meter of mercury.

`GSL_CONST_MKS_INCH_OF_MERCURY'
     The pressure of 1 inch of mercury.

`GSL_CONST_MKS_INCH_OF_WATER'
     The pressure of 1 inch of water.

`GSL_CONST_MKS_PSI'
     The pressure of 1 pound per square inch.


File: gsl-ref.info,  Node: Viscosity,  Next: Light and Illumination,  Prev: Pressure,  Up: Physical Constants

Viscosity
=========

`GSL_CONST_MKS_POISE'
     The dynamic viscosity of 1 poise.

`GSL_CONST_MKS_STOKES'
     The kinematic viscosity of 1 stokes.


File: gsl-ref.info,  Node: Light and Illumination,  Next: Radioactivity,  Prev: Viscosity,  Up: Physical Constants

Light and Illumination
======================

`GSL_CONST_MKS_STILB'
     The luminance of 1 stilb.

`GSL_CONST_MKS_LUMEN'
     The luminous flux of 1 lumen.

`GSL_CONST_MKS_LUX'
     The illuminance of 1 lux.

`GSL_CONST_MKS_PHOT'
     The illuminance of 1 phot.

`GSL_CONST_MKS_FOOTCANDLE'
     The illuminance of 1 footcandle.

`GSL_CONST_MKS_LAMBERT'
     The luminance of 1 lambert.

`GSL_CONST_MKS_FOOTLAMBERT'
     The luminance of 1 footlambert.


File: gsl-ref.info,  Node: Radioactivity,  Next: Force and Energy,  Prev: Light and Illumination,  Up: Physical Constants

Radioactivity
=============

`GSL_CONST_MKS_CURIE'
     The activity of 1 curie.

`GSL_CONST_MKS_ROENTGEN'
     The exposure of 1 roentgen.

`GSL_CONST_MKS_RAD'
     The absorbed dose of 1 rad.


File: gsl-ref.info,  Node: Force and Energy,  Next: Prefixes,  Prev: Radioactivity,  Up: Physical Constants

Force and Energy
================

`GSL_CONST_MKS_NEWTON'
     The SI unit of force, 1 Newton.

`GSL_CONST_MKS_DYNE'
     The force of 1 Dyne = 10^-5 Newton.

`GSL_CONST_MKS_JOULE'
     The SI unit of energy, 1 Joule.

`GSL_CONST_MKS_ERG'
     The energy 1 erg = 10^-7 Joule.


File: gsl-ref.info,  Node: Prefixes,  Next: Physical Constant Examples,  Prev: Force and Energy,  Up: Physical Constants

Prefixes
========

   These constants are dimensionless scaling factors.

`GSL_CONST_NUM_YOTTA'
     10^24

`GSL_CONST_NUM_ZETTA'
     10^21

`GSL_CONST_NUM_EXA'
     10^18

`GSL_CONST_NUM_PETA'
     10^15

`GSL_CONST_NUM_TERA'
     10^12

`GSL_CONST_NUM_GIGA'
     10^9

`GSL_CONST_NUM_MEGA'
     10^6

`GSL_CONST_NUM_KILO'
     10^3

`GSL_CONST_NUM_MILLI'
     10^-3

`GSL_CONST_NUM_MICRO'
     10^-6

`GSL_CONST_NUM_NANO'
     10^-9

`GSL_CONST_NUM_PICO'
     10^-12

`GSL_CONST_NUM_FEMTO'
     10^-15

`GSL_CONST_NUM_ATTO'
     10^-18

`GSL_CONST_NUM_ZEPTO'
     10^-21

`GSL_CONST_NUM_YOCTO'
     10^-24


File: gsl-ref.info,  Node: Physical Constant Examples,  Next: Physical Constant References and Further Reading,  Prev: Prefixes,  Up: Physical Constants

Examples
========

   The following program demonstrates the use of the physical constants
in a calculation.  In this case, the goal is to calculate the range of
light-travel times from Earth to Mars.

   The required data is the average distance of each planet from the
Sun in astronomical units (the eccentricities of the orbits will be
neglected for the purposes of this calculation).  The average radius of
the orbit of Mars is 1.52 astronomical units, and for the orbit of
Earth it is 1 astronomical unit (by definition).  These values are
combined with the MKS values of the constants for the speed of light
and the length of an astronomical unit to produce a result for the
shortest and longest light-travel times in seconds.  The figures are
converted into minutes before being displayed.

     #include <stdio.h>
     #include <gsl/gsl_const_mks.h>
     
     int
     main (void)
     {
       double c  = GSL_CONST_MKS_SPEED_OF_LIGHT;
       double au = GSL_CONST_MKS_ASTRONOMICAL_UNIT;
       double minutes = GSL_CONST_MKS_MINUTE;
     
       /* distance stored in meters */
       double r_earth = 1.00 * au;
       double r_mars  = 1.52 * au;
     
       double t_min, t_max;
     
       t_min = (r_mars - r_earth) / c;
       t_max = (r_mars + r_earth) / c;
     
       printf("light travel time from Earth to Mars:\n");
       printf("minimum = %.1f minutes\n", t_min / minutes);
       printf("maximum = %.1f minutes\n", t_max / minutes);
     
       return 0;
     }

Here is the output from the program,

     light travel time from Earth to Mars:
     minimum = 4.3 minutes
     maximum = 21.0 minutes


File: gsl-ref.info,  Node: Physical Constant References and Further Reading,  Prev: Physical Constant Examples,  Up: Physical Constants

References and Further Reading
==============================

Further information on the values of physical constants is available
from the NIST website,

     <http://www.physics.nist.gov/cuu/Constants/index.html>


File: gsl-ref.info,  Node: IEEE floating-point arithmetic,  Next: Debugging Numerical Programs,  Prev: Physical Constants,  Up: Top

IEEE floating-point arithmetic
******************************

   This chapter describes functions for examining the representation of
floating point numbers and controlling the floating point environment of
your program.  The functions described in this chapter are declared in
the header file `gsl_ieee_utils.h'.

* Menu:

* Representation of floating point numbers::
* Setting up your IEEE environment::
* IEEE References and Further Reading::


File: gsl-ref.info,  Node: Representation of floating point numbers,  Next: Setting up your IEEE environment,  Up: IEEE floating-point arithmetic

Representation of floating point numbers
========================================

   The IEEE Standard for Binary Floating-Point Arithmetic defines binary
formats for single and double precision numbers.  Each number is
composed of three parts: a "sign bit" (s), an "exponent" (E) and a
"fraction" (f).  The numerical value of the combination (s,E,f) is
given by the following formula,

     (-1)^s (1.fffff...) 2^E

The sign bit is either zero or one.  The exponent ranges from a minimum
value E_min to a maximum value E_max depending on the precision.  The
exponent is converted to an unsigned number e, known as the "biased
exponent", for storage by adding a "bias" parameter, e = E + bias.  The
sequence fffff... represents the digits of the binary fraction f.  The
binary digits are stored in "normalized form", by adjusting the
exponent to give a leading digit of 1.  Since the leading digit is
always 1 for normalized numbers it is assumed implicitly and does not
have to be stored.  Numbers smaller than 2^(E_min) are be stored in
"denormalized form" with a leading zero,

     (-1)^s (0.fffff...) 2^(E_min)

This allows gradual underflow down to 2^(E_min - p) for p bits of
precision.  A zero is encoded with the special exponent of 2^(E_min -
1) and infinities with the exponent of 2^(E_max + 1).

The format for single precision numbers uses 32 bits divided in the
following way,

     seeeeeeeefffffffffffffffffffffff
     
     s = sign bit, 1 bit
     e = exponent, 8 bits  (E_min=-126, E_max=127, bias=127)
     f = fraction, 23 bits

The format for double precision numbers uses 64 bits divided in the
following way,

     seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
     
     s = sign bit, 1 bit
     e = exponent, 11 bits  (E_min=-1022, E_max=1023, bias=1023)
     f = fraction, 52 bits

It is often useful to be able to investigate the behavior of a
calculation at the bit-level and the library provides functions for
printing the IEEE representations in a human-readable form.

 - Function: void gsl_ieee_fprintf_float (FILE * STREAM, const float *
          X)
 - Function: void gsl_ieee_fprintf_double (FILE * STREAM, const double
          * X)
     These functions output a formatted version of the IEEE
     floating-point number pointed to by X to the stream STREAM. A
     pointer is used to pass the number indirectly, to avoid any
     undesired promotion from `float' to `double'.  The output takes
     one of the following forms,

    `NaN'
          the Not-a-Number symbol

    `Inf, -Inf'
          positive or negative infinity

    `1.fffff...*2^E, -1.fffff...*2^E'
          a normalized floating point number

    `0.fffff...*2^E, -0.fffff...*2^E'
          a denormalized floating point number

    `0, -0'
          positive or negative zero

     The output can be used directly in GNU Emacs Calc mode by
     preceding it with `2#' to indicate binary.

 - Function: void gsl_ieee_printf_float (const float * X)
 - Function: void gsl_ieee_printf_double (const double * X)
     These functions output a formatted version of the IEEE
     floating-point number pointed to by X to the stream `stdout'.

The following program demonstrates the use of the functions by printing
the single and double precision representations of the fraction 1/3.
For comparison the representation of the value promoted from single to
double precision is also printed.

     #include <stdio.h>
     #include <gsl/gsl_ieee_utils.h>
     
     int
     main (void)
     {
       float f = 1.0/3.0;
       double d = 1.0/3.0;
     
       double fd = f; /* promote from float to double */
     
       printf(" f="); gsl_ieee_printf_float(&f);
       printf("\n");
     
       printf("fd="); gsl_ieee_printf_double(&fd);
       printf("\n");
     
       printf(" d="); gsl_ieee_printf_double(&d);
       printf("\n");
     
       return 0;
     }

The binary representation of 1/3 is 0.01010101... .  The output below
shows that the IEEE format normalizes this fraction to give a leading
digit of 1,

      f= 1.01010101010101010101011*2^-2
     fd= 1.0101010101010101010101100000000000000000000000000000*2^-2
      d= 1.0101010101010101010101010101010101010101010101010101*2^-2

The output also shows that a single-precision number is promoted to
double-precision by adding zeros in the binary representation.

