Simplify result type declaration in Rust

Hi there!
I am working with nalgebra. When accessing matrix elements one needs to extract a submatrix. To this end, nalgebra provides functions like view and view_mut, for example

let A = DMatrix::from_fn(6, 8, |i, j| (i * 10 + j) as f64);
let subA = A.view((2, 2), (4, 4));

But, it would be more convenient to use slice-like access

let subA = get_block(&A, 1..3, 1..3);
get_block_mut(&A, 1..4, 0..3).copy_from(B);

or even better

let subA = A[1..3, 2..5];
A[1..4, 0..3] = B;

I implemented the function get_block wrapping the call view as

fn get_block<T, R, C, S1>(mat : &Matrix<T, R, C, S1>, yrange : std::ops::Range<usize>, xrange : std::ops::Range<usize>)
 -> Matrix<T, Dyn, Dyn, ViewStorage<'_, T, Dyn, Dyn, <S1 as RawStorage<T, R, C>>::RStride, <S1 as RawStorage<T, R, C>>::CStride>>
where
  C : Dim,
  R : Dim,
  S1 : RawStorage<T, R, C>,
{
  let start = (yrange.start, xrange.start);
  let shape = (yrange.end - yrange.start, xrange.end - xrange.start);
  mat.view(start, shape)
}

The function looks ugly, because I need to specify explicitly the huge resulting type.
I would like to know if there is a better solution?

I don't know of an ideal solution. Maybe something like impl Index with a tuple of ranges could work.

let subA = A[(1..3, 2..5)];
A[(1..4, 0..3)] = B;

On your get_block function:

These are nearly the same constraints that nalgebra itself needs to include on its various implementations. It isn't surprising that the signature has as much complexity, reflecting the complexity of the problem domain.

One simplification is that <S1 as RawStorage<T, R, C>>::RStride can be S1::RStride, and the same for LStride. A use statement for Range would also slightly decrease the source length.

1 Like

Type aliases, perhaps.

type BlockSubMatrixView<'matrix, T, R, C, S1> = ViewStorage<
   'matrix, T, Dyn, Dyn,
   <S1 as RawStorage<T, R, C>>::RStride,
   <S1 as RawStorage<T, R, C>>::CStride,
>;

type BlockSubMatrix<'matrix, T, R, C, S1> =  Matrix<
    T, Dyn, Dyn, BlockSubMatrixView<'matrix, T, R, C, S1>,
>;

fn get_block<T, R, C, S1>(
    mat: &Matrix<T, R, C, S1>,
    yrange: Range<usize>,
    xrange: Range<usize>,
) -> BlockSubMatrix<'_, T, R, C, S1>
where
    C : Dim,
    R : Dim,
    S1 : RawStorage<T, R, C>,
{

Doesn't necessarily help with error message though.

1 Like

Index is a bust (it can only return borrows). But nalgebra::MatrixView is a handy type alias that helps here.

1 Like