I'm trying to implement the exp function for a generic square MatrixMN
pub fn exp<N, R>(m: &MatrixMN<N, R, R>, k: usize) -> MatrixMN<N, R, R>
where
N: Scalar + One + Zero,
R: DimName + DimNameAdd<R>,
<R as DimName>::Value: Mul<<R as DimName>::Value>,
<<R as DimName>::Value as Mul<<R as DimName>::Value>>::Output: generic_array::ArrayLength<N>,
{
let mut i = MatrixMN::<N, R, R>::identity();
i.add(&m)
}
But I keep getting this errors like this.
error[E0599]: no method named `add` found for struct `nalgebra::base::matrix::Matrix<N, R, R, nalgebra::base::array_storage::ArrayStorage<N, R, R>>` in the current scope
--> src/state_extrapolation.rs:24:7
|
24 | i.add(&m)
| ^^^ method not found in `nalgebra::base::matrix::Matrix<N, R, R, nalgebra::base::array_storage::ArrayStorage<N, R, R>>`
|
= note: the method `add` exists but the following trait bounds were not satisfied:
`&mut nalgebra::base::matrix::Matrix<N, R, R, nalgebra::base::array_storage::ArrayStorage<N, R, R>> : nalgebra::base::dimension::DimNameAdd<_>`
`&nalgebra::base::matrix::Matrix<N, R, R, nalgebra::base::array_storage::ArrayStorage<N, R, R>> : nalgebra::base::dimension::DimNameAdd<_>`
`nalgebra::base::matrix::Matrix<N, R, R, nalgebra::base::array_storage::ArrayStorage<N, R, R>> : nalgebra::base::dimension::DimNameAdd<_>`
Is there a better way to pass generic matrices to functions?
I've also tried with something like this
pub fn exp2<M>(m: &M, k: usize) -> M
where
M: nalgebra::base::Matrix<_, _, _, _>,
{
let mut i = M::identity();
i.add(&m)
}
But cannot come up with good traits for M.
It's easy to get lost in the traits when making things fully generic. My tips are:
DefaultAllocator: Allocator<N, R, R>
from here allows getting rid of many constraintsScalar
, if it's going to be floats you will calculate with, it's easier to use RealField
which gives you Scalar
plus many other useful properties (like One
and Zero
required for the identity()
function)use std::ops::Add
, which made it work in the end.Here is the code, playground:
use nalgebra::{
base::allocator::Allocator, DefaultAllocator, DimName, DimNameAdd, MatrixN, RealField,
};
use std::ops::Add;
fn exp<N, R>(m: &MatrixN<N, R>, k: usize) -> MatrixN<N, R>
where
N: RealField,
R: DimName + DimNameAdd<R>,
DefaultAllocator: Allocator<N, R, R>,
{
let i = MatrixN::<N, R>::identity();
m.add(i)
}