> except maybe for the construction of the matrix
Yep, that’s precisely why I used that thing.
> Most of my time is spent in algebraic operations with immutable matrices.
CSR is probably the way to go then.
Also, if you do that math on CPU and your matrix is not randomly sparse but made of small dense areas of non-zeroes, consider less compressed SIMD-friendly variant of CSR, where instead of individual elements you keep dense SIMD vectors.
For example, if you have AVX and need fp64 precision, keep 4 elements long slices of rows there. This way you can use 256-bit loads and FMA instructions to do that math.
Or if you spending most of time multiplying matrices as opposed to matrix*vector, might be reasonable to keep 2x2 dense blocks as opposed to 4x1.