## Batch Insert CSC sparse Matrix in Armadillo C++

## Primer on Compressed Sparse Column Matrices

First, I would recommend reading NVIDIA's post on it. You need 3 elements.

### Column offset

This was the most confusing for me at first. This is sort of a vector that holds the index to the row indices vector. The first value is always a zero as a result of this fact; it points to the first element in the row indices vector. If the first column has 2 non-zero values, the first two elements of this vector would be [0, 2].

Another way to think about it; it is a counter for the number of non-zero values encountered so far. Refer to the graphic in the NVIDIA post. When it comes to the 3 element of the column offset vector, the value is 5. There are a total of 5 non-zero elements up until the start of the 3 column!

The length of this vector matches the total number of columns, not values! This is easy to implement in code.

### Row Indices

For each non-zero value, which row index was it in? Extracting a indices of non-zero elements from a vector is easy, and I will show the code.

### Values

This is straight forward. What is the non-zero value. The length of the values vector and row indices vector must match.

## Armadillo Code

If you haven't already, refer to the Armadillo documentation. We will be using the form 4 of the batch insertion constructor.

```
sp_mat(rowind, colptr, values, n_rows, n_cols, check_for_zeros = true)
```

Shortly, you need to have `std::vector`

for values, row indices and column offset.

```
std::vector<arma::uword> rowind;
std::vector<arma::uword> colptr;
std::vector<double> values;
```

In my example, I have a `std::map`

where each pair is a key with a `arma::vec`

.
It is likely different from how you the reader, are going about it.
Here is how I went about populating the 3 vectors.

```
for (auto& [key, my_vector] : vector_map) {
arma::uvec row_indices = arma::find(my_vector > 0);
colptr.push_back(colptr.back() + row_indices.n_elem);
for (auto& idx : row_indices) {
rowind.push_back(idx);
values.push_back(my_vector(idx));
}
}
```

And finally, to construct the sparse matrix in record time!

```
arma::colvec values_vec = arma::conv_to<arma::colvec>::from(values);
arma::uvec rowind_vec = arma::conv_to<arma::uvec>::from(rowind);
arma::uvec colptr_vec = arma::conv_to<arma::uvec>::from(colptr);
arma::sp_mat final_matrix(rowind_vec, colptr_vec, values_vec, a_matrix.n_rows, a_matrix.n_cols, false);
```

Hope it helped you. Feel free to leave a Disqus comment below.