Go to the first, previous, next, last section, table of contents.


Using the library

This chapter describes how to compile programs that use GSL, and introduces its conventions.

ANSI C Compliance

The library is written in ANSI C and is intended to conform to the ANSI C standard. It should be portable to any system with a working ANSI C compiler.

The library does not rely on any non-ANSI extensions in the interface it exports to the user. Programs you write using GSL can be ANSI compliant. Extensions which can be used in a way compatible with pure ANSI C are supported, however, via conditional compilation. This allows the library to take advantage of compiler extensions on those platforms which support them.

When an ANSI C feature is known to be broken on a particular system the library will exclude any related functions at compile-time. This should make it impossible to link a program that would use these functions and give incorrect results.

To avoid namespace conflicts all exported function names and variables have the prefix gsl_, while exported macros have the prefix GSL_.

Compiling and Linking

The library header files are installed in their own `gsl' directory. You should write any preprocessor include statements with a `gsl/' directory prefix thus,

#include <gsl/gsl_math.h>

If the directory is not installed on the standard search path of your compiler you will also need to provide its location to the preprocessor as a command line flag. The default location of the `gsl' directory is `/usr/local/include/gsl'.

The library is installed as a single file, `libgsl.a'. A shared version of the library is also installed on systems that support shared libraries. The default location of these files is `/usr/local/lib'. To link against the library you need to specify both the main library and a supporting BLAS library. A suitable blas implementation is provided in `libgslblas' if your system does not provide one. The following example shows how to link an application with the library,

gcc app.o -lgsl -lgslblas -lm

The following command line shows how you would link the same application with an alternative blas library called `libcblas',

gcc app.o -lgsl -lgslblascblas -lcblas -lm

For the best performance an optimized vendor-supplied blas library (if available) should be substituted for -lcblas. The library must conform to the CBLAS standard. For more information see section BLAS Support.

The program gsl-config provides information on the local version of the library. For example, the following command shows that the library has been installed under the directory `/usr/local',

bash$ gsl-config --prefix
/usr/local

Further information is available using the command gsl-config --help.

Shared Libraries

To run a program linked with the shared version of the library it may be necessary to define the shell variable LD_LIBRARY_PATH to include the directory where the library is installed. For example,

LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH ./app

To compile a statically linked version of the program instead, use the -static flag in gcc,

gcc -static app.o -lgsl -lgslblas -lm

Automake macros

The GSL library also provides some useful automake macros to use in your applications. The `gsl.m4' file contains the definitions needed to detect GSL in automatic Makefile generation.

To use the macros simply add the following line to your `configure.in' file:

AM_PATH_GSL(GSL_VERSION,[action-if-found],[action-if-not-found])

where GSL_VERSION is the two or three digit MAJOR.MINOR or MAJOR.MINOR.MICRO version number of the GSL Library release you require. A suitable choice for action-if-not-found is

AC_MSG_ERROR(could not find required version of GSL)

Then, you can add the variables GSL_LIBS and GSL_CFLAGS to your Makefile.am files to obtain the correct compiler flags. GSL_LIBS is equal to the output of the gsl-config --libs command and GSL_CFLAGS is equal to gsl-config --cflags command. For example,

libgsdv_la_LDFLAGS =    \
        $(GTK_LIBDIR) \
        $(GTK_LIBS) -lgsdvgsl $(GSL_LIBS) -lgslblas

Inline functions

The inline keyword is not part of ANSI C and the library does not export any inline function definitions by default. The inline versions of functions can be included by defining the macro HAVE_INLINE when compiling an application.

gcc -c -DHAVE_INLINE app.c

If you use autoconf this macro can be defined automatically. The following test should be placed in your `configure.in' file,

AC_C_INLINE

if test "$ac_cv_c_inline" != no ; then
  AC_DEFINE(HAVE_INLINE,1)
  AC_SUBST(HAVE_INLINE)
fi

and the macro will then be defined in the compilation flags or by including the file `config.h' before any library headers. If you do not define the macro HAVE_INLINE then the slower non-inlined versions of the functions will be used instead.

Long double

The extended numerical type long double is part of the ANSI C standard and should be available in every modern compiler. However, the precision of long double is platform dependent, and this should be considered when using it. The IEEE standard only specifies the minimum precision of extended precision numbers, while double is the same on all platforms.

In some system libraries the stdio.h formatted input/output functions printf and scanf are not implemented correctly for long double. Undefined or incorrect results are avoided by testing these functions during the configure stage of library compilation and eliminating certain GSL functions which depend on them if necessary,

checking whether printf/scanf works with long double... no

Consequently when long double formatted input/output does not work on a given system it will not be possible to link a program which uses GSL functions dependent on this.

If it is necessary to work on a system which does not support formatted long double input/output then the options are to use binary formats or to convert long double results into double for reading and writing.

Portability functions

To help in writing portable applications GSL provides some implementations of functions that are found in other libraries, such as the BSD math library. You can write your application to use the native versions of these functions, and substitute the GSL versions (with a preprocessor macro) if they are unavailable on another platform. The substitution can be made automatically if you use autoconf. For example, to test whether the BSD function hypot is available you can include the following line in the configure file `configure.in' for your application ,

AC_CHECK_FUNCS(hypot)

and place the following macro definitions in the file `config.h.in',

/* Substitute gsl functions for missing system functions */

#ifndef HAVE_HYPOT
#define hypot gsl_hypot
#endif

The application source files can then use the include command #include <config.h> to substitute gsl_hypot for each occurrence of hypot when hypot is not available.

In most circumstances the best strategy is to use the native versions of these functions when available, and fall back to GSL versions otherwise, since this allows your application to take advantage of any platform-specific optimizations in the system library. This is the strategy used within GSL itself.

Alternative optimized functions

The main implementation of some functions in the library will not be optimal on all architectures. For example, there are several ways to compute a Gaussian random variate and their relative speeds are platform-dependent. In cases like this the library provides alternate implementations of these functions with the same interface. If you write your application using calls to the standard implementation you can select an alternative version later via a preprocessor definition. It is also possible to introduce your own optimized functions this way while retaining portability. For example,

#ifdef SPARC
#define gsl_ran_gaussian gsl_ran_gaussian_ratio_method
#endif
#ifdef INTEL
#define gsl_ran_gaussian my_gaussian
#endif

Note that the alternative implementations will not produce bit-for-bit identical results, and in the case of random number distributions will produce an entirely different stream of random variates.

Support for different numeric types

Many functions in the library are defined for different numeric types. This feature is implemented by varying the name of the function with a type-related modifier -- a primitive form of C++ templates. The modifier is inserted into the function name after the initial module prefix. The following table shows the function names defined for all the numeric types of an imaginary module gsl_foo with function fn,

gsl_foo_fn               double        
gsl_foo_long_double_fn   long double   
gsl_foo_float_fn         float         
gsl_foo_long_fn          long          
gsl_foo_ulong_fn         unsigned long 
gsl_foo_int_fn           int           
gsl_foo_uint_fn          unsigned int  
gsl_foo_short_fn         short         
gsl_foo_ushort_fn        unsigned short
gsl_foo_char_fn          char          
gsl_foo_uchar_fn         unsigned char 

The normal numeric precision double is considered the default and does not require a suffix. For example, the function gsl_stats_mean computes the mean of double precision numbers, while the function gsl_stats_int_mean computes the mean of integers.

A corresponding scheme is used for library defined types, such as gsl_vector and gsl_matrix. In this case the modifier is appended to the type name. For example, if a module defines a new type-dependent struct or typedef gsl_foo it is modified for other types in the following way,

gsl_foo                  double        
gsl_foo_long_double      long double   
gsl_foo_float            float         
gsl_foo_long             long          
gsl_foo_ulong            unsigned long 
gsl_foo_int              int           
gsl_foo_uint             unsigned int  
gsl_foo_short            short         
gsl_foo_ushort           unsigned short
gsl_foo_char             char          
gsl_foo_uchar            unsigned char 

When a module contains type-dependent definitions the library provides individual header files for each type. The filenames are modified as shown in the below. For convenience the default header includes the definitions for all the types. To include only the double precision header, or any other specific type, file use its individual filename.

#include <gsl/gsl_foo.h>                  All types listed below
#include <gsl/gsl_foo_double.h>           double        
#include <gsl/gsl_foo_long_double.h>      long double   
#include <gsl/gsl_foo_float.h>            float         
#include <gsl/gsl_foo_long.h>             long          
#include <gsl/gsl_foo_ulong.h>            unsigned long 
#include <gsl/gsl_foo_int.h>              int           
#include <gsl/gsl_foo_uint.h>             unsigned int  
#include <gsl/gsl_foo_short.h>            short         
#include <gsl/gsl_foo_ushort.h>           unsigned short
#include <gsl/gsl_foo_char.h>             char          
#include <gsl/gsl_foo_uchar.h>            unsigned char 

Compatibility with C++

The library header files automatically define functions to have extern "C" linkage when included in C++ programs.

Aliasing of arrays

The library assumes that arrays, vectors and matrices passed as arguments are not aliased and do not overlap. This allows the library to use additional optimizations, and removes the need to handle overlapping memory regions as a special case. If overlapping arguments are used then the results of such functions will be undefined.

Code Reuse

Where possible the routines in the library have been written to avoid dependencies between modules and files. This should make it possible to extract individual functions for use in your own applications, without needing to have the whole library installed. You may need to define certain macros such as GSL_ERROR and remove some #include statements in order to compile the files as standalone units. Reuse the library code in this way is encouraged, subject to the terms of the GNU General Public License.


Go to the first, previous, next, last section, table of contents.