sprs icon indicating copy to clipboard operation
sprs copied to clipboard

Diagonal and diagonal view

Open vbarrielle opened this issue 8 years ago • 9 comments

.diagonal would allocate a sparse vector while .diag_view could allocate a lazy diagonal proxy, trading time for memory

vbarrielle avatar Mar 18 '16 22:03 vbarrielle

This would be useful for my use-case. Any reason why this hasn't been implemented yet?

matzhaugen avatar Dec 18 '20 11:12 matzhaugen

@matzhaugen I don't think we have seen enough interest to implement this yet. What would be your use case? Which APIs would you like to see on diagonals? Should we have dense and sparse diagonals?

mulimoen avatar Dec 18 '20 13:12 mulimoen

My use case would be doing something like this

min_elem = my_sparse_matrix.diag_view().fold(1.0, |acc, elem| acc.min(*elem));

or the diag equivalent. Maybe there is a much easier way to do this that I'm not seeing. But just a sparse diagonal would be fine.

Anyway, I made a cheeky PR :p. It's more to get a feel for Rust as I'm new to the language, so feel free to let me know it I'm totally off track.

matzhaugen avatar Dec 18 '20 16:12 matzhaugen

For your use case you want a diagonal iterator I guess, you'll be more efficient since you will avoid allocating. But the PR you made is already a good start!

vbarrielle avatar Dec 18 '20 16:12 vbarrielle

Yes, good point, that seems like a good idea. I can change or add a PR for that, once I learn how to implement iterators in Rust :) . I'm actually not sure how a diag_view method would be implemented though since the constructor of CsVecI takes &[N]and not &[&N] for values. Not sure how to reconcile that.

But and iterator would be even better of course.

matzhaugen avatar Dec 18 '20 16:12 matzhaugen

diag_view would need to return an entirely new type that would need to compute its values on demand for anything that it would be used for. Retrospectively I'm not sure it would be a good idea.

If you want to implement diag_iter in you PR, you're welcome to do so! Writing iterators is a good way to learn rust, and lifetimes in particular.

I think the signature should be something like

pub fn diag_iter(
        &self,
    ) -> impl std::iter::DoubleEndedIterator<Item = (usize, &N)>
           + std::iter::ExactSizeIterator<Item = (usize, &N)>
           + '_

Do not hesitate to look at examples in the codebase, for instance https://github.com/vbarrielle/sprs/blob/6cc2370f685c674886f958994f1d30123c6b0c42/src/sparse/csmat.rs#L1147-L1161 is an example of an Iterator implementation. This is using the impl Trait feature of rust, which is more ergonomic than defining an iterator type by hand.

vbarrielle avatar Dec 18 '20 17:12 vbarrielle

@vbarrielle Could return CsVecBase<Vec<I>, &[N]> if we allow data and indices to have separate lengths.

mulimoen avatar Dec 18 '20 17:12 mulimoen

It could indeed, though that would not really be a view as it would be allocating. But that could definitely be useful, especially a mutable version.

vbarrielle avatar Dec 18 '20 17:12 vbarrielle

Seems that approach would clash with https://docs.rs/sprs/0.9.2/sprs/struct.CsVecBase.html#method.data

mulimoen avatar Dec 18 '20 17:12 mulimoen