Performing basic operations with nalgebras most generic Matrix type

83 Views Asked by At

I'm trying to figure out how to write functions that take generic nalgebra matrices and vectors as their arguments and perform basic operations on those. I'm especially interested in being generic over fixed-size and dynamically sized matrices.

As an example, the following function is supposed to accept both SVector and DVector arguments and subtract them:

use nalgebra::{DVector, Matrix, U1, Dim, RawStorage, Storage};

fn function<R, S>(a: &Matrix<f64, R, U1, S>, b: &Matrix<f64, R, U1, S>)
    where R: Dim, S: RawStorage<f64, R> + Storage<f64, R>
{
    let c = b - a;
}

fn main() {
    let a = DVector::<f64>::zeros(3);
    let b = DVector::<f64>::zeros(3);
    function(&a, &b);
    
    let a = SVector::<f64, 3>::zeros();
    let b = SVector::<f64, 3>::zeros();
    function(&a, &b);
}

The subtraction however doesn't work and results in the following error:

error[E0369]: cannot subtract `&Matrix<f64, R, Const<1>, S>` from `&Matrix<f64, R, Const<1>, S>`
 --> src/main.rs:6:15
  |
6 |     let c = b - a;
  |             - ^ - &Matrix<f64, R, Const<1>, S>
  |             |
  |             &Matrix<f64, R, Const<1>, S>
  |
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
  |
4 |     where R: Dim, S: RawStorage<f64, R> + Storage<f64, R>, DefaultAllocator: nalgebra::allocator::Allocator<f64, R>
  |                                                          ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

For more information about this error, try `rustc --explain E0369`.

I'm not sure this can be solved by adding more trait bounds, as the compiler suggests, or if the Matrix type just doesn't support those operations at all.

1

There are 1 best solutions below

0
cafce25 On BEST ANSWER

The bound suggested by the compiler will work (that's why it suggested it in the first place), but in such cases I'd go with the literal requirement your code has rather than some obscure bound on the implementation of the desired trait (Sub here):

use nalgebra::{DVector, Matrix, U1, Dim, RawStorage, Storage, SVector};

fn function<'a, R, S>(a: &'a Matrix<f64, R, U1, S>, b: &'a Matrix<f64, R, U1, S>)
where
    R: Dim,
    S: RawStorage<f64, R> + Storage<f64, R>,
    &'a Matrix<f64, R, U1, S>: std::ops::Sub<&'a Matrix<f64, R, U1, S>>,
{
    let c = b - a;
}

fn main() {
    let a = DVector::::zeros(3);
    let b = DVector::::zeros(3);
    function(&a, &b);
    
    let a = SVector::::zeros();
    let b = SVector::::zeros();
    function(&a, &b);
}

And it works as expected.
Playground