this guide may be outdated for MacOS versions beyond 10.14 Mojave (and implied Xcode versions)
Table of Contents
The GNU Scientific library (GSL) is a powerful C
/C++
numerical library.
This guide assumes you already have a working C
/C++
compiler - check by entering gcc --version
in Terminal. OSX's default Clang
compiler is fine, otherwise this page describes how to install gcc 4.9
.
Apparently GSL can be installed through Homebrew via
brew install gsl
though installing it manually is just as simple, which we now describe.
- Download gsl-latest.tar.gz from the GSL ftp site and unzip it anywhere (e.g. /Downloads)
- Open the unzipped
gsl
folder in Terminal (e.g.cd ~/Downloads/gsl-2.4
- Run
sudo ./configure && make && make install
If the above gives a "permission denied" error, instead try
sudo make clean
sudo chown -R $USER .
./configure && make
make install
You'll now be able to include GSL into your code from anywhere.
sudo apt-get install libgsl-dev
You'll now be able to include GSL into your code from anywhere.
Oh wait, explore the use of...
module load gsl/1.15 module load gsl/1.16 module load gsl/2.1
In the ARCUS terminal, download GSL anywhere
wget "ftp://ftp.gnu.org/gnu/gsl/gsl-latest.tar.gz"
and unzip it
tar -xf gsl-latest.tar.gz
then open the new folder e.g.
cd gsl-2.4
To install without admin permissions, we'll keep the GSL files in a folder called gsl
.
Note some newer versions off gcc (e.g. 8) seem incompatible. Use an older version (e.g. gcc/5.3.0
) and first call
module load binutils libtool
Replace YOURUSERNAME
below with your ARCUS-B username (e.g. abcd1234
) and run
export gsdir=/data/oums-quantopo/YOURUSERNAME/gsl
mkdir $gsdir
./configure --prefix=$gsdir && make && make install
We'll need to remember this location when compiling
Compiling GSL with our code is easy; we simply add library flags -lm -lgsl -lgslcblas
to our calls to gcc
.
For example, we'd adapt the QuEST makefile to include
#
# --- libraries
#
LIBS = -lm -lgsl -lgslcblas
Exactly as above for OSX.
Before compiling on ARCUS-B, we must extend LD_LIBRARY
to include our gsl folder (replace YOURUSERNAME
below)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/oums-quantopo/YOURUSERNAME/gsl/lib
This need only be done once each time we SSH into ARCUS.
Our compilation must additionally include the -lm -lgsl -lgslcblas
libraries and flags -I/data/oums-quantopo/YOURUSERNAME/gsl/include
and -L/data/oums-quantopo/YOURUSERNAME/gsl/lib
.
For example, we'd modify the QuEST makefile to include
#
# --- libraries
#
LIBS = -lm -lgsl -lgslcblas
and just after that, insert
#
# --- GSL link
#
GSL_INCLUDE = -I/data/oums-quantopo/YOURUSERNAME/gsl/include
GSL_LINK = -L/data/oums-quantopo/YOURUSERNAME/gsl/lib
and modify the rules list
#
# --- rules
#
%.o: %.c
$(CC) $(CFLAGS) $(CFLAGS_OMP) $(GSL_INCLUDE) -c $<
%.o: $(QUEST_DIR)/%.c
$(CC) $(CFLAGS) $(CFLAGS_OMP) $(GSL_INCLUDE) -c $<
and finally the build commands
#
# --- build
#
default: $(EXE)
$(EXE): $(OBJ)
$(CC) $(CFLAGS) $(CFLAGS_OMP) $(GSL_INCLUDE) -o $(EXE) $(OBJ) $(LIBS) $(GSL_LINK)
See a complete example of my QuEST & gsl makefile here.
The many different GSL functions are available in different source files.
For example, to use the matrix, linear equation solver, and matrix multiplication functionalities, respectively include
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_blas.h>
View available functions and their necessary header files can be found here.
Sometimes GSL is so powerful, it's confusing to figure out how to do some simple things. So here are some examples
Matrices are dynamic objects, indexed from 0, which must be allocated before, and freed after, their use.
#include <gsl/gsl_matrix.h>
gsl_matrix* myMatr = gsl_matrix_alloc(10,20);
// matrix of 8s
for (int i=0; i < 10; i++)
for (int j=0; j < 20; j++)
gsl_matrix_set(myMatr, i, j, 8);
int elem = gsl_matrix_get(myMatr, 3, 4);
gsl_matrix_free(myMatr);
For a vector, replace matrix
above with vector
.
GSL's matrix operations come under 'Basic Linear Algebra Subprograms' (BLAS), listed here
#include <gsl/gsl_blas.h>
To multiply matrices matrA
and matrB
and store the result in matrC
(all of which must be previously allocated by gsl_matrix_alloc
), call:
gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, matrA, matrB, 0.0, matrC);
In the name gsl_blas_dgemm
, the d
refers to double-precision matrices, and the final m
refers to matrix. The other arguments are explained here.
To multiply a matrix matrA
and a vector vecB
and store the result in vecC
(previously allocated by gsl_matrix_alloc
and gsl_vector_alloc
), call:
gsl_blas_dgemv(CblasNoTrans, 1.0, matrA, vecB, 0.0, vecC);
Linear algebra operations are provided by
#include <gsl/gsl_linalg.h>
Here's how to solve A x = b (or matrA vecX = vecB) for x by LU decomposition, which involves creating an intermediate permutation
structure
gsl_permutation* perm = gsl_permutation_alloc(vecB->size);
int swaps;
gsl_linalg_LU_decomp(matrA, perm, &swaps);
gsl_linalg_LU_solve(matrA, perm, vecB, vecX);
gsl_permutation_free(perm);
By default, a numerical error (e.g. attempting to invert a non-invertible matrix) will cause an error message and execution to stop. To instead detect and handle numerical errors, include
#include <gsl/gsl_errno.h>
and call
gsl_set_error_handler_off();
before calling any numerical functions. Then functions (e.g. gsl_linalg_LU_solve
) will return an integer 0
for success, otherwise an errorcode of those listed here (e.g. GSL_ERANGE
, GSL_EIVANL
).
Thank you for these clear, concise, and correct install instructions on OSX.