# Sparse Matrices: Matrix Storage Modes

The dense linear algebra functions in IDL Analyst require input consisting of matrix dimensions and all values for the matrix entries. This is not practical for sparse linear algebra. Three different storage formats can be used for the functions in the sparse matrix sections. These methods include:

- Sparse Coordinate Storage Format
- Band Storage Format
- Compressed Sparse Column (CSC) Format

## Sparse Coordinate Storage Format

Only the non-zero elements of a sparse matrix need to be communicated to a function. Sparse coordinate storage format stores the value of each matrix entry along with that entry’s row and column index. The following structures are defined by IDL Analyst to make it easy to store sparse matrices:

{imsl_f_sp_elem, row:0L, col:0L, val:float(0.0)}

{imsl_d_sp_elem, row:0L, col:0L, val:double(0.0)}

{imsl_c_sp_elem, row:0L, col:0L, val:complex(0.0)}

{imsl_z_sp_elem, row:0L, col:0L, val:dcomplex(0.0)}

As an example consider the 6 x 6 matrix:

The matrix A has 15 non-zero elements, and its sparse coordinate representation would be:

Since this representation does not rely on order, an equivalent form would be:

There are different ways this data could be used to initialize. Consider the following program fragment:

Both a and b represent the sparse matrix A.

A sparse symmetric or Hermitian matrix is a special case, since it is only necessary to store the diagonal and either the upper or lower triangle. As an example, consider the 5 x 5 linear system:

The Hermitian and symmetric positive definite system solvers in this module expect the diagonal and lower triangle to be specified. The sparse coordinate form for the lower triangle is given by

The following program fragment will initialize H:

A = replicate(imsl_c_sp_elem, 7)

a(*).row = [0, 1, 2, 3, 1, 2, 3]

a(*).col = [0, 1, 2, 3, 0, 1, 2]

a(*).val = [COMPLEX(4, 0), COMPLEX(4, 0), $

COMPLEX(4, 0), COMPLEX(4, 0), $

COMPLEX(1, 1), COMPLEX(1, 1), $

COMPLEX(1, 1)]

There are some important points to note here. Note that H is not symmetric, but rather Hermitian. The functions that accept Hermitian data understand this and operate assuming that:

The Sparse Matrix Module cannot take advantage of the symmetry in matrices that are not positive definite. A symmetric matrix that happens to be indefinite cannot be stored in this compact symmetric form. Rather, both upper and lower triangles must be specified and the sparse general solver called.

## Band Storage Format

A band matrix is an M × N matrix A with all of its non-zero elements “close” to the main diagonal. Specifically, values Aij = 0 if i – j > nlca or j – i > nuca. The integer m = nlca + nuca + 1 is the total band width. The diagonals, other than the main diagonal, are called codiagonals. While any M × N matrix is a band matrix, band storage format is only useful when the number of non-zero codiagonals is much less than N.

In band storage format, the nlca lower codiagonals and the nuca upper codiagonals are stored in the rows of an array of size m × N. The elements are stored in the same column of the array as they are in the matrix. The values Aij inside the band width are stored in the linear array in positions [(i – j + nuca + 1)*i + j]. This results in a row-major, one-dimensional mapping from the two-dimensional notion of the matrix.

For example, consider the 5 x 5 matrix A with 1 lower and 2 upper codiagonals:

In band storage format, the data would be arranged as:

This data would be then be stored contiguously, row-major order, in an array of length 20.

As an example, consider the following tridiagonal matrix:

The following code segment will store this matrix in band storage format:

a = [0, 1, 2, 3, 4, $

10, 20, 30, 40, 50, $

5, 6, 7, 8, 0]

As in the sparse coordinate representation, there is a space saving symmetric version of band storage. As an example, we look at the following 5 x 5 symmetric problem:

In band symmetric storage format, the data would be arranged as:

The following Hermitian example illustrates the procedure:

The following program fragments stores H in h, using band symmetric storage format:

h = complexarr(15)

h(0:1) = 0

h(2:4) = complex(1,1)

h(5) = 0

h(6:9) = complex(1,1)

h(10:14) = 8

## Choosing Between Banded and Coordinate Forms

Any matrix can be stored in either sparse coordinate or band format; which format to use depends on the sparsity pattern of the matrix. A matrix with all non-zero data stored in bands close to the main diagonal is probably a good candidate for band format. If non-zero information is scattered more or less uniformly through the matrix, sparse coordinate format is the best choice. The following two cases are extreme examples. First, consider an n x n matrix with all elements on the main diagonal and the (0,n–1) and (n–1,0) entries non-zero. The sparse coordinate vector would be n + 2 units long. An array of length 2n2 – n would be required to store the band representation, nearly twice as much storage as a dense solver might require.

Second, consider a tridiagonal matrix with all diagonal, superdiagonal, and subdiagonal entries non-zero. In band format, an array of length 3n is needed. In sparse coordinate format, a vector of length 3n – 2 is required. But the problem is that, for instance with floating-point precision on a 32 bit machine, each of those 3n – 2 units in coordinate format requires three times as much storage as any of the 3n units needed for band representation. This is due to carrying the row and column indices in coordinate form. Band storage evades this requirement by being essentially an ordered list, and defining location in the original matrix by position in the list.

## Compressed Sparse Column (CSC) Format

Functions that accept data in coordinate format can also accept data stored in the format described in the Users’ Guide for the Harwell-Boeing Sparse Matrix Collection. The scheme is column oriented, with each column held as a sparse vector, represented by a list of the row indices of the entries in an integer array and a list of the corresponding values in a separate float (double, complex, dcomplex) array. Data for each column are stored consecutively and in order. A separate integer array holds the location of the first entry of each column and the first free location. Only entries in the lower triangle and diagonal are stored for symmetric and Hermitian matrices. All arrays are based at zero, which is in contrast to the Harwell-Boeing test suite’s one-based arrays.

As in the Users’ Guide for the Harwell-Boeing Sparse Matrix Collection, we illustrate the storage scheme with the following example. The 5x5 matrix:

would be stored in the arrays colptr (location of first entry), rowind (row indices), and values (non-zero entries) as follows: