I'd like to keep you informed of some API evolutions I'm planing in SparseCore (disclaimer, this email is a bit technical and assume some knowledge of Eigen's internals to be followed).
I'm currently refactoring a bit SparseCore to support Ref<> for sparse matrices. My current idea is to specialize Ref<> for SparseMatrix, and to be consistent I'm also specializing Map<> for SparseMatrix. This means that the MappedSparseMatrix class would become deprecated.
Also note that both Ref<> and Map<> accepts three template parameters.
The first one is the similar matrix type, i.e., a Matrix<...>, an Array<> or a SparseMatrix<...>.
The other two are optional and currently they only make sense for dense objects:
- an integer called "Options", currently used to specify alignment.
- a typename called "StrideType" controlling stride for dense objects.
At a first glance, these two parameters are rather cumbersome when talking about sparse matrices, and one could thus prefer to keep MappedSparseMatrix and similarly, add a new SparseRef class instead of specializing Ref<>. On the other hand, reusing Ref<> and Map<> leads to a more consistent API (IMO), and these two template parameters might become handy in the future to provide some compile-time hints (see below). The "Options" parameter is very generic, and the semantic of the last typename can still be completely redefined for SparseMatrix.
I'm also introducing a new base class called SparseCompressedBase<Derived>, which inherits SparseMatrixBase<Derived>, and will be a common base class for Map<SparseMatrix>, Ref<SparseMatrix>, and SparseMatrix. SparseCompressedBase provides direct access to the internal sparse-(un)compressed storage formats, that is, pointers to the inner-indices, values, starting positions of each inner-vectors, and optionally the numbers of non-zeros per inner-vectors (un-compressed case).
While writing this email, I'm thinking that the "Options" template parameter of Ref<> could be used to specify whether someone explicitly wants an object in compressed form? This option would not be needed by Map<SparseMatrix> because the compressed/uncompressed status is resolved at runtime.
The case of Block<SparseMatrix> is still an open-question though. When it represents a set of complete inner-vectors, then it can easily inherit SparseCompressedBase (this case is already handled at compile-time when using middleCols/middleRows and the likes). In the more general case, we have two options:
1 - make it a general _expression_ and implement in Ref<SparseMatrix> a special mechanism for Block<SparseMatrix> where Ref<> would only allocate and compute the respective starting position and per inner-vector number of nnz.
2 - Make Block<SparseMatrix> generates itself these two vectors such that it can also inherit SparseCompressedBase.
Option 2 is preferred when the Block object is used multiple times, but it adds an overhead in the other case. Therefore, I'm tempted by option 1: if one want to use a sub-matrix multiple times, better use a Ref<> to hold it anyways.
Let me know if you see any potential pitfalls with this approach or have better suggestions.