Add `clear` methods to sparse matrices
It is sometimes desirable to reuse the data in a sparse matrix, e.g., in an iterative algorithm, to avoid reallocation. Adding a clear method to these types would allow code as in the following:
pub struct IterativeAlgo {
a: CsrMatrix<f64>
}
impl IterativeAlgo {
pub fn run(&mut self) {
loop {
self.run_iter()
}
}
fn run_iter(&mut self) {
self.populate_a_at_iter_start()
// Use `self.a`
}
fn populate_a_at_iter_start(&mut self) {
// Clear existing memory, but don't deallocate
self.a.clear()
// Write to `self.a`
// ...
}
}
I agree that CooMatrix definitely should have this - in fact I thought it already did, but apparently it's not covered yet.
For CsrMatrix and CscMatrix, on the other hand, it doesn't make so much sense with the design we take in nalgebra-sparse, because the sparsity pattern is inherently not modifiable. What's possible, instead, is for a user to call disassemble() in order to retrieve the raw CSR data. This allows low-level re-use of the matrix data in the way you describe.
Yes, that's true. I have been pursuing an approach that uses disassemble(). One difficulty, however, is that disassemble() necessarily consumes self. In my example this would prevent updating self.a with only a & mut self. Instead, It would be necessary to consume self and return a new or updated IterativeAlgo instance.
Still, I recognize that adding a clear() method probably isn't feasibly for immutable sparsity patterns.
If you have a mutable reference, you can swap it with an empty matrix, disassemble it and then swap it back when you're done, like this (not tested, might not compile/be completely valid):
use std::mem::swap;
fn rebuild_matrix(original_matrix: &mut CsrMatrix<f64>) {
let mut new_matrix = CsrMatrix::try_from_triplets(vec![], vec![], vec![]).unwrap();
swap(&mut new_matrix, &mut *original_matrix);
let mut (offsets, indices, values) = new_matrix.disassemble();
// Re-use the buffers and build new matrix
...
let mut new_matrix = CsrMatrix::try_from_triplets(offsets, indices, values).unwrap();
swap(&mut new_matrix, original_matrix)
}
Granted, it's not terribly ergonomic... Happy to hear your thoughts if you have some suggestions for how to improve this use case though!
Also, we should maybe consider a Default impl that gives an empty 0x0 matrix?