Prof Darren Wilkinson Professor of Stochastic Modelling
School of Mathematics & Statistics
Newcastle University

Getting started with GSL

This covers GSL 0.7

Everything to do with using the functionality of the GNU Scientific Library is very well explained in the documentation - see my list of GSL links. Of course, C itself is also well documented - see my C links. However, if you are very new to Unix and C programming, it may not be entirely clear from the documentation how to get started with compiling your programs. This quick guide should get you started. However, in the latest version of the manual (on the web), there is now a section on compiling and linking, which contains a terse version of most of this guide.

First you need to know about the header files. Whenever you use a GSL function, you need to make sure that you include the relevant header file. On most systems, the header files are in /usr/include/gsl/, so have a look in there. This means that you will have to use the flag -I/usr/include/gsl with gcc, so that the compiler can find the headers. The include directory probably contains something like:

gsl_blas.h gsl_blas_raw.h gsl_blas_raw_L1.h gsl_blas_raw_L2.h gsl_blas_raw_L3.h gsl_blas_raw_cm.h gsl_blas_types.h gsl_block.h gsl_block_char.h gsl_block_complex.h gsl_block_complex_double.h gsl_block_complex_float.h gsl_block_complex_long_double.h gsl_block_double.h gsl_block_float.h gsl_block_int.h gsl_block_long.h gsl_block_long_double.h gsl_block_short.h gsl_block_uchar.h gsl_block_uint.h gsl_block_ulong.h gsl_block_ushort.h gsl_cblas.h gsl_complex.h gsl_complex_math.h gsl_const.h gsl_const_cgs.h gsl_const_mks.h gsl_const_num.h gsl_dft_complex.h gsl_dft_complex_float.h gsl_dht.h gsl_eigen.h gsl_errno.h gsl_fft.h gsl_fft_complex.h gsl_fft_complex_float.h gsl_fft_halfcomplex.h gsl_fft_halfcomplex_float.h gsl_fft_real.h gsl_fft_real_float.h gsl_fit.h gsl_heapsort.h gsl_histogram.h gsl_histogram2d.h gsl_ieee_utils.h gsl_integration.h gsl_interp.h gsl_linalg.h gsl_machine.h gsl_math.h gsl_matrix.h gsl_matrix_char.h gsl_matrix_complex_double.h gsl_matrix_complex_float.h gsl_matrix_complex_long_double.h gsl_matrix_double.h gsl_matrix_float.h gsl_matrix_int.h gsl_matrix_long.h gsl_matrix_long_double.h gsl_matrix_short.h gsl_matrix_uchar.h gsl_matrix_uint.h gsl_matrix_ulong.h gsl_matrix_ushort.h gsl_message.h gsl_min.h gsl_mode.h gsl_monte.h gsl_monte_miser.h gsl_monte_plain.h gsl_monte_vegas.h gsl_multifit.h gsl_multifit_nlin.h gsl_multimin.h gsl_multiroots.h gsl_odeiv.h gsl_permutation.h gsl_permute.h gsl_permute_char.h gsl_permute_double.h gsl_permute_float.h gsl_permute_int.h gsl_permute_long.h gsl_permute_long_double.h gsl_permute_short.h gsl_permute_uchar.h gsl_permute_uint.h gsl_permute_ulong.h gsl_permute_ushort.h gsl_permute_vector.h gsl_permute_vector_char.h gsl_permute_vector_double.h gsl_permute_vector_float.h gsl_permute_vector_int.h gsl_permute_vector_long.h gsl_permute_vector_long_double.h gsl_permute_vector_short.h gsl_permute_vector_uchar.h gsl_permute_vector_uint.h gsl_permute_vector_ulong.h gsl_permute_vector_ushort.h gsl_poly.h gsl_precision.h gsl_qrng.h gsl_randist.h gsl_rng.h gsl_roots.h gsl_sf.h gsl_sf_airy.h gsl_sf_bessel.h gsl_sf_chebyshev.h gsl_sf_clausen.h gsl_sf_coulomb.h gsl_sf_coupling.h gsl_sf_dawson.h gsl_sf_debye.h gsl_sf_dilog.h gsl_sf_elementary.h gsl_sf_ellint.h gsl_sf_elljac.h gsl_sf_erf.h gsl_sf_exp.h gsl_sf_expint.h gsl_sf_fermi_dirac.h gsl_sf_gamma.h gsl_sf_gegenbauer.h gsl_sf_hyperg.h gsl_sf_laguerre.h gsl_sf_legendre.h gsl_sf_log.h gsl_sf_poly.h gsl_sf_pow_int.h gsl_sf_psi.h gsl_sf_result.h gsl_sf_synchrotron.h gsl_sf_transport.h gsl_sf_trig.h gsl_sf_zeta.h gsl_siman.h gsl_sort.h gsl_sort_char.h gsl_sort_double.h gsl_sort_float.h gsl_sort_int.h gsl_sort_long.h gsl_sort_long_double.h gsl_sort_short.h gsl_sort_uchar.h gsl_sort_uint.h gsl_sort_ulong.h gsl_sort_ushort.h gsl_sort_vector.h gsl_sort_vector_char.h gsl_sort_vector_double.h gsl_sort_vector_float.h gsl_sort_vector_int.h gsl_sort_vector_long.h gsl_sort_vector_long_double.h gsl_sort_vector_short.h gsl_sort_vector_uchar.h gsl_sort_vector_uint.h gsl_sort_vector_ulong.h gsl_sort_vector_ushort.h gsl_specfunc.h gsl_statistics.h gsl_statistics_char.h gsl_statistics_double.h gsl_statistics_float.h gsl_statistics_int.h gsl_statistics_long.h gsl_statistics_long_double.h gsl_statistics_short.h gsl_statistics_uchar.h gsl_statistics_uint.h gsl_statistics_ulong.h gsl_statistics_ushort.h gsl_sum.h gsl_test.h gsl_vector.h gsl_vector_char.h gsl_vector_complex.h gsl_vector_complex_double.h gsl_vector_complex_float.h gsl_vector_complex_long_double.h gsl_vector_double.h gsl_vector_float.h gsl_vector_int.h gsl_vector_long.h gsl_vector_long_double.h gsl_vector_short.h gsl_vector_uchar.h gsl_vector_uint.h gsl_vector_ulong.h gsl_vector_ushort.h

Each file declares a collection of GSL functions. It's normally fairly obvious which header files you need to include, but just read the files if you are not sure.

The other thing you need to know about are the dynamic link libraries. These contain the actual GSL code, needed to make your programs run. On most systems, you should be able to make your code link and run, simply by including the options -lgsl -lgslblas in your list of gcc arguments.

Let's see how it works on a trivial example.


Random Number Generation

Consider the following C program, stored in the file gsl_test.c:
#include <stdio.h>
#include <gsl_rng.h>
#include <gsl_randist.h>

int main (int argc, char *argv[])
{
  /* set up GSL RNG */
  gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);
  /* end of GSL setup */

  int i,n;
  double gauss,gamma;  

  n=atoi(argv[1]);
  for (i=0;i<n;i++)
    {
      gauss=gsl_ran_gaussian(r,2.0);
      gamma=gsl_ran_gamma(r,2.0,3.0);
      printf("%2.4f %2.4f\n", gauss,gamma);
    }
  return(0);
}
This program generates some Gaussian and gamma random variates. Notice how the relevant header files are included at the top. To compile this, we need the following command:
gcc -I/usr/include/gsl
    -lgsl -lgslblasnative
    gsl_test.c -o gsl_test
(all on one line). Obviously this is a bit tedious to type, so it's probably worth using the wonderful make program to help compile. The following Makefile can be used for compiling stand-alone C programs like the above:
# Makefile for building C stuff with GSL

CFLAGS=-I/usr/include/gsl
LDFLAGS=-lgsl -lgslblasnative
CC=gcc

%: %.c
        $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@

# eg. do "make gsl_test" to make gsl_test from gsl_test.c
# then run with "gsl_test 10"

clean:
        rm -f *~ *.o core a.out


Matrices and Vectors

Let's now look at an example messing around with matrices and vectors. The same makefile as before can be used, though in general its worth adding a few more C flags to help debugging:
CFLAGS=-I/usr/include/gsl -ansi -Wall -pedantic -g

We will read in a matrix from a data file, so the file gsl_test_matvec.txt is needed, and contains the following:

1.2 1.3 1.4
2.2 2.2 2.2
5.0 5.0 5.0
6.1 7.1 7.2
Now the program itself (gsl_test_matvec.c) follows. It is fairly self explanatory, and gives fairly helpful output. However, it does rely on a basic understanding of C arrays, pointers, structs and memory allocation - if you are new to C, you will need to read up on these before messing around with vectors and matrices.
#include <stdio.h>
#include <gsl_matrix.h>
#include <gsl_statistics.h>

int main (void)
{
  /* declare variables */
  int i,j,rows,cols;
  gsl_matrix *m,*mm;
  gsl_vector *v,vv;
  FILE *f;

  rows=4;cols=3;
  m = gsl_matrix_alloc(rows,cols); /* create a matrix */

  /* initialise a matrix */
  for (i=0;i<rows;i++)
    {
      for (j=0;j<cols;j++)
	{
	  gsl_matrix_set(m,i,j,10.0*i+j);
	}
    }

  /* print matrix the hard way */
  printf("Matrix m\n");
  for (i=0;i<rows;i++)
    {
      for (j=0;j<cols;j++)
	{
	  printf("%f ",gsl_matrix_get(m,i,j));
	}
      printf("\n");
    }
  printf("\n");

  /* read in a matrix from a file */
  mm=gsl_matrix_alloc(rows,cols);
  f=fopen("gsl_test_matvec.txt","r");
  gsl_matrix_fscanf(f,mm);
  fclose(f);

  /* print matrix the easy way */
  printf("Matrix mm\n");
  gsl_matrix_fprintf(stdout,mm,"%f");

  /* put column means into a vector */
  v=gsl_vector_alloc(cols);
  for (i=0;i<cols;i++)
    {      
      vv=gsl_matrix_column(mm,i);
      printf("\nCol %d\n",i);
      gsl_vector_fprintf(stdout,&vv,"%f");
      gsl_vector_set(v,i,gsl_stats_mean(vv.data,vv.stride,vv.size));
    }
  /* print column means */
  printf("\nColumn means\n");
  gsl_vector_fprintf(stdout,v,"%f");
  /* print overall mean */
  printf("\nOverall mean\n");
  printf("%f\n",gsl_stats_mean(v->data,v->stride,v->size));

  /* release memory */
  gsl_matrix_free(m);
  gsl_matrix_free(mm);
  gsl_vector_free(v);
  return(0);
}


Obviously the above is a very brief guide, but it should get you started. Once you are going, start hitting the manuals - they are generally very good.

If you are interested in stochastic simulation, my computer practicals provide examples of the use of the GSL random number library. Also, my software page includes quite a bit of C code which makes heavy use of the GSL.

Feel free to send me any comments or suggestions for improvements.

Darren J Wilkinson Book: Stochastic Modelling for
	      Systems Biology  
darren.wilkinson@ncl.ac.uk
http://www.staff.ncl.ac.uk/d.j.wilkinson/