This chapter describes the way that GSL functions report and handle errors.  By examining the status information returned by every GSL function you can determine whether it succeeded or failed, and if it failed you can find out what the precise cause of failure was. You can also define your own error handling functions to modify the default behavior of the library.

Error reporting
===============

GSL follows the thread-safe error reporting conventions of the POSIX Threads library. Functions in GSL return a non-zero error code to indicate an error and 0 to indicate success.

     int status = gsl_function(...)

     if (status) { /* an error occurred */
       .....       /* the value of status specifies the type of error */
     }

GSL routines report an error whenever they cannot perform the task requested of them. For example, a root-finding function would return a non-zero error code if could not converge to the requested accuracy, or exceeded a limit on the number of iterations. Situations like this are a normal occurrence when using any mathematical library and you should check the return status of the GSL functions that you call.

Whenever a GSL routine reports an error the return value specifies the type of error. The return value is analogous to the value of the variable errno in the C library. However, the C library's errno is a global variable, which is not thread-safe (There can be only one instance of a global variable per program. Different threads of execution may overwrite errno simultaneously).  By returning the error number directly we can avoid this problem in a simple, portable way. The caller can examine the return code and decide what action to take, including ignoring the error if it is not considered serious.

The error code numbers are defined in the file gsl_errno.h. They all have the prefix GSL_ and expand to non-zero constant integer values. Many of the error codes use the same base name as a corresponding error code in C library. Here are some of the most common error codes,

 -- Macro: int GSL_EDOM
     Domain error; used by mathematical functions when an argument value does not fall into the domain over which the function is defined (like EDOM in the C library)

 -- Macro: int GSL_ERANGE
     Range error; used by mathematical functions when the result value is not representable because of overflow or underflow (like ERANGE in the C library)

 -- Macro: int GSL_ENOMEM
     No memory available. The system cannot allocate more virtual memory because its capacity is full (like ENOMEM in the C library). This error is reported when a GSL routine encounters problems when trying to allocate memory with malloc.

 -- Macro: int GSL_EINVAL
     Invalid argument. This is used to indicate various kinds of problems with passing the wrong argument to a library function (like EINVAL in the C library).

Here is an example of some code which checks the return value of a function where an error might be reported,

     int status = gsl_fft_complex_radix2_forward (data, length);

     if (status) {
         if (status == GSL_EINVAL) {
            fprintf (stderr, "invalid argument, length=%d\n", length);
         } else {
            fprintf (stderr, "failed, gsl_errno=%d\n", status);
         }
         exit (-1);
     }

The function gsl_fft_complex_radix2 only accepts integer lengths which are a power of two. If the variable length is not a power of two then the call to the library function will return GSL_EINVAL, indicating that the length argument is invalid. The else clause catches any other possible errors.

Error handlers
==============

In addition to reporting errors the library also provides an optional error handler. The error handler is called by library functions when they are about to report an error (for example, just before they return).

The default behavior of the error handler is to print a short message and call abort() whenever an error is reported by the library. If a library routine reports an error then the whole program will core-dump. This is a safe default for lazy programmers who do not check the return status of library routines (we don't encourage you to write programs this way). If you turn off the default error handler or provide your own error handler then it is your responsibility to check the return values of the GSL routines.

All GSL error handlers have the type gsl_error_handler_t, which is defined in gsl_errno.h,

 -- Data Type: void gsl_error_handler_t

     This is the type of GSL error handler functions. An error handler will be passed three arguments, specifying the reason for the error, the source file in which it occurred, and the line number in that file. The source file and line number are set at compile time using the __FILE__ and __LINE__ directives in the preprocessor. An error handler function returns type void. Error handler functions should be defined like this,

          void HANDLER (const char * reason, const char * file, int line)

To request the use of your own error handler you need to call the function gsl_set_error_handler which is also declared in gsl_errno.h,

 -- Function: gsl_error_handler_t gsl_set_error_handler (gsl_error_handler_t NEW_HANDLER)

     This functions sets a new error handler, NEW_HANDLER, for the GSL library routines. The previous handler is returned (so that you can restore it later).  Note that the pointer to a user defined error handler function is stored in a static variable, so there can only be one error handler per program.

          old_handler = gsl_set_error_handler (&my_error_handler);

          .....     /* code uses new handler */

          gsl_set_error_handler (old_handler) ; /* restore old handler */

     To use the default behavior (abort on error) set the error handler to NULL,

          old_handler = gsl_set_error_handler (NULL);

Here is a skeleton outline of a program which defines its own error handler.  Imagine that the program does interactive data analysis -- there is a main loop which reads commands from the user and calls library routines with user-supplied arguments,

     #include <setjmp.h>
     #include <gsl_errno.h>

     jmp_buf main_loop;
     void my_error_handler (const char *reason, const char *file, int line);

     main ()
     {
        gsl_set_error_handler (&my_error_handler);

        while (1)
          {
            .... /* read command from user */

            if (setjmp (main_loop) == 0)
              {
                 .... /* call GSL routines requested by user */
              }
            else
              {
                 .... /* my_error_handler bailed out, GSL gave an error */
              }
          }
     }

     void
     my_error_handler (const char *reason, const char *file, int line)
     {
         fprintf (stderr, "GSL error: %s\n", reason);
         longjmp (main_loop);
     }

Before entering the interactive loop the program uses gsl_set_error_handler to provide its own error handler my_error_handler for GSL error reports. After this point the function my_error_handler will be invoked whenever an error is reported by GSL. The new error handler prints the cause of the error (the string reason) and then does a non-local jump back to the main loop. This would allow the user to fix the command which caused the error and try again.

Error streams
=============

GSL supports the concert of an error stream, which is a place where errors are logged as they occur. An error stream allows the library to report an error message directly to the user rather than to the calling program. This can sometimes be useful because it reduces the amount of error checking that the program needs to do.

For example, many mathematical functions compute floating point numbers or other numerical values. The standard versions of these functions accept a pointer for storing their numerical result, so that the status can be returned separately. For example, to compute the first-order Bessel function J_1(x) for x=1.23 and obtain the status we write,

     double result;
     int status = gsl_sf_bessel_J1_e (1.23, &result);

where gsl_sf_bessel_J1_e is the appropriate function from the special functions (sf) module. The suffix _e appended to the function name indicates that the return value gives the error status. This style of function is safe and avoids any confusion about what the return value means, but requires a lot of error checking.

For many numerical functions it would be more intuitive to write something like y = f(x). The library provides functions with an alternative interface which allows this,

     double result = gsl_sf_bessel_J1 (1.23)

However, in this case there is no way for the calling program to test for an error. Instead if there are any errors (such as underflow) they are logged to the error stream, and can be examined by the user at the end of the run. It is up to the programmer to decide which form is best suited to a given application. For a truly robust program the error checking versions of the functions should be used, since they don't rely on the user examining the error stream.

Manipulating the error stream
=============================

By default the error stream is sent to stderr, and you can redirect it to a file on the command line. There are also two ways to change this within your program. Firstly, the stream can be redirected to another file by providing a suitable file pointer. Alternatively you can set up an error stream handler, which is a function that accepts error message strings. By using an error stream handler function you have complete control over where the messages are stored.

 -- Function: FILE * gsl_set_stream (FILE * NEW_STREAM)
     This function selects the stream used for GSL error messages. After calling gsl_set_stream any further messages sent to the default stream handler will be printed on NEW_STREAM. The previous stream is returned, so that you can close it or restore it later. Note that the stream is stored in a static variable, so there can only be one error stream per program.

 -- Data Type: void gsl_stream_handler_t
     This is the type of GSL stream handler functions. A stream handler will be passed four arguments, specifying a label (such as ERROR or WARNING), the source file in which the error occurred, the line number in that file and a description of the error. The source file and line number are set at compile time using the __FILE__ and __LINE__ directives in the preprocessor. A stream handler function returns type void. Stream handler functions should be defined like this,

          void HANDLER (const char * label, const char * file,
                        int line, const char * reason)

To request the use of your own stream handler you need to call the function gsl_set_stream_handler which is also declared in gsl_errno.h,

 -- Function: gsl_stream_handler_t gsl_set_stream_handler (gsl_stream_handler_t NEW_HANDLER)

     This functions sets a new stream handler, NEW_HANDLER, for the GSL library routines. The previous handler is returned (so that you can restore it later).  Note that the pointer to a user defined stream handler function is stored in a static variable, so there can only be one error handler per program.

          old_handler = gsl_set_stream_handler (&my_error_stream);

          .....     /* code uses new handler */

          gsl_set_stream_handler (old_handler) ; /* restore old handler */

     To use the default behavior (print the message to stderr) set the stream handler to NULL,

          old_handler = gsl_set_stream_handler (NULL);

Using GSL error reporting in your own functions
===============================================

If you are writing numerical functions in a program which also uses GSL code you may find it convenient to adopt the same error reporting conventions as in the library.

To report an error you need to call the function gsl_error with a string describing the error and then return an appropriate error code from gsl_errno.h, or a special value, such as NaN. For convenience gsl_errno.h defines two macros to carry out these steps:

 -- Macro: GSL_ERROR (REASON, GSL_ERRNO)

     This macro reports an error using the GSL conventions and returns a status value of gsl_errno. It expands to the following code fragment,

          gsl_error (reason, __FILE__, __LINE__, gsl_errno) ;
          return gsl_errno ;

     The macro definition in gsl_errno.h actually wraps the code in a do { ... } while (0) block to prevent possible parsing problems.

Here is an example of how the macro could be used to report that a routine did not achieve a requested tolerance. To report the error the routine needs to return the error code GSL_ETOL.

     if (residual > tolerance)
       {
         GSL_ERROR("residual exceeds specified tolerance", GSL_ETOL) ;
       }

 -- Macro: GSL_ERROR_RETURN (REASON, GSL_ERRNO, VALUE)

     This macro is the same as GSL_ERROR but returns a user-defined status value of VALUE instead of an error code. It can be used for mathematical functions that return a floating point value.

Here is an example where a function needs to return a NaN because of a mathematical singularity,

     if (x == 0)
       {
         GSL_ERROR_RETURN("argument lies on singularity", GSL_ERANGE, NAN) ;
       }