Matrix Compression: Mapping between padded Compressed Row Storage and Compressed Column Storage?

713 Views Asked by At

Context

There are a handful of ways to compress a matrix, $\mathbf{M}$, but Compressed Row Storage (CRS) is fairly popular due to its fast access. Similarly, there exists Compressed Column Storage (CCS), which is equivalent to the CRS of the transpose of the original matrix, i.e. $CRS(\mathbf{M}^\text{T}) = CCS(\mathbf{M})$.

Notably - for CRS - should the original matrix contain a row which is empty, and one wish to maintain the original's dimensions when de-compressing one must pad empty rows: similar for columns if using CCS. This is especially useful if one wants to access the compressed matrix as if it were not compressed.

An example of a dense matrix $\mathbf{M}$ and its transpose $\mathbf{M}^\text{T}$ undergoing CRS is given below: CRS and CCS Matrix Compression Example made by Daniel Sumner Magruder

Thus if one wanted to find $\mathbf{M}[i][j]$:

start = row_pointers[i]   // where row i starts
end = row_pointers[i + 1] // where row i ends
non_empty_columns = column_indexes[start:end] // non-zero column indexes of row i
if j in non_empty_columns:
    return values[start:end][non_empty_columns.index(j)]

Question

It is clear that the CRS of $\mathbf{M}$ and $\mathbf{M}^\text{T}$ are visually distinct. However, is there a mapping, that given only the CRS of $\mathbf{M}$, would return the search of $\mathbf{M}^\text{T}$.

For example, if I wanted all non empty columns of row 1, I could use the above method with just the parameter i:

start = row_pointers[i]   // where row i starts
end = row_pointers[i + 1] // where row i ends
non_empty_columns = column_indexes[start:end] // non-zero column 

but what if I wanted also all non-empty rows for column 1 (e.g. searching for all non-empty columns in the transpose)?

Is there a mapping that would efficiently allow me to find those?