Using Vectors with GSL

Vectors are created and manipulated in C by calling the various library function in the GSL. Before using a vector, it needs to be created. Function gsl_vector_alloc() creates a vector of the specified length n, and returns a pointer to the vector. When a vector is no longer needed in the program, it is destroyed by calling the GSL function gsl_vector_free().

A vector is manipulated by accessing its elements and changing and/or retrieving the value of the elements. The GSL library function gsl_vector_set() assigns the value specified to the i-th element of a vector. The GSL Function gsl_vector_set_all() sets the value specified to all elements of a vector. The value of individual elements of a vector can be retrieved by calling the GSL function gsl_vector_get(). This function returns the i-th element of a vector. The functions gsl_vector_get() and gsl_vector_set() perform portable range checking and report an error if the index value of an element is outside the allowed range.

The code below is a C program that uses the GSL functions to create and manipulate a vector. Line 18 includes the header file that contains the definitions for calling the GSL functions for vectors. Line 23 calls function gsl_vector_alloc() to create vector pv with N elements. In line 24, all elements of vector pv are set to value 2.5. In line 29, element i of vector pv is set to value 5.25. In line 33 vector pv is destroyed by calling function gsl_vector_free().


The output of the program is shown below:

Operations on vectors are performed with a vector and a scalar or with two vectors. These are performed by calling GSL functions in C. To add a scalar to a vector involves adding the scalar value to every element of the vector. With C and GSL, calling function gsl_vector_add_constant(). This function adds the specified constant value to the elements of the vector specified. In the following portion of code, vector pv is created and then its elements are assigned values. On the fifth line, function gsl_vector_add_constant() is called to add the constant x to all the elements of vector pv.

To add two vectors involves adding the corresponding elements of each vector, and a new vector is created. This addition operation on vectors is only possible if the row vectors (or column vectors) are of the same size. In the following example, vectors pv and qv are both vectors of size N. Calling function gsl_vector_add() adds the elements of vector qv to the elements of vector pv.

In a similar manner, subtracting a scalar from a vector can be specified; subtracting two vectors of the same size. Calling function gsl_vector_sub() subtracts the elements of vector qv from the elements of vector pv. However, if you wish to perform |c> = |a> + |b> on two given vectors |a> and |b> i.e. add them and store the result in a third vector |c>, then you should first make a copy of |a> into |c> and perform gsl_vector_add(). A vector can be copied into another using the function gsl_vector_memcpy(). The final code is:

You can also perform |c> = |a> - |b> in a similar manner. Multiplying a vector by a scalar results in multiplying each element of the vector by the value of the scalar. Function gsl_vector_scale() multiplies the elements of the specified vector by the constant factor specified.

Element by element multiplication, also known as dot multiplication, multiplies the corresponding elements of two vectors. This operation is applied to two vectors of equal size and is performed by calling the GSL function gsl_vector_mul(). This function multiplies the elements of the specified vector by the elements of the second specified vector. In the following function call, vectors pv and qv are dot-multiplied and the results are stored in vector pv.

Element by element division, also known as dot division, divides the corresponding elements of two vectors. This operation is applied to two vectors of equal size and is performed by calling the GSL function gsl_vector_div(). This function divides the elements of the specified vector by the elements of the second specified vector. In the following function call, the elements of vector pv are divided by the elements of vector qv and the results are stored in vector pv.

Finally, gsl_vectors can be read from and written to file pointers directly. To dump the vector to a file, create a pointer to that file (say, *fp), create a gsl_vector (say v) and call gsl_vector_fprintf (fp, v, "%lf") , where the last argument is the format string for each vector element. If you want to write the vector data to the screen, simply use the standard output, i.e. "stdout", for the file pointer. For details, see this.

Vector Views

So far, we have seen how GSL vector objects are created, populated and read from. The data is to be added into a vector item by item, using loops and other explicit code. This is a cumbersome process, especially if the vector data is provided to you as a large, unstructured block like an array. So, for instance, if you want to create a vector of size 10 from the array data below:

You will have to write extra code along the lines of

This is obviously a cumbersome and slow process, especially over large datasets. This is also redundant. All we're doing is copying the same data from one memory block to another. It would be easier if we could just re-cast the data in array_data with a pointer to a gsl_vector. That is what GSL vector views do.

A GSL vector view is a pointer to a structure which can be used to operate on a subset of the raw data that can be put into a vector. This can be any raw data, an array, data from some other structure, data from a file, or data from another gsl_vector. A GSL vector view can be initiated in code with

There are many different ways to create a vector view, depending on how your data is structured. If your data comes from a part of another gsl vector, you will need the function 'gsl_vector_subvector()'. This function, when called, returns a vector view defined as a subvector of another vector. The arguments are: the vector, the start of the new vector is offset by the number of elements from the start of the original vector, and the number of elements of the new vector. The following C statement calls the function and defines vv as a subvector of vector av.

In the above example, the start of the new vector is offset by 'offset' elements from the start of the original vector. The new vector has nsize elements. This procedure is illustrated with two examples below. The right side panels have illustrations of the result of the code on the left side panels.

If your data comes from a regular C array, then you can call the function gsl_vector_view_array(). The arguments are: the base or pointer to the start of the array and the number of elements for the vector.

There are other more sophisticated functions for dealing with vector views of data blocks in GSL. They are documented here. Finally, now that a vector view has been created, what about the actual gsl_vector associated with the view? This is inside the vector_view structure, and can be accessed as &vv.vector, where vv is the vector view. Therefore, the code for setting a vector from an array can be simplified with vector views as: