As an example from my code, if I specify the type as f64, I get no compile errors, and + and * are implemented for `f64, Vector3<f64>, and Matrix3<f64>`

.

```
pub struct Inertia {
mass: f64,
center_of_mass: Vector3<f64>,
inertia: Matrix3<f64>,
value: Matrix6<f64>,
}
impl<T> Inertia<T>
where
T: Float + Scalar + fmt::Debug,
{
fn new(mass: T, center_of_mass: Vector3<T>, inertia: Matrix3<T>) -> Self {
let c = skew(¢er_of_mass);
let ct = c.transpose();
let b1 = inertia + (mass * ( c * ct) );
let b2 = mass * ct;
let b3 = mass * c;
let b4 = Matrix3::from_diagonal_element(mass);
let value = concat_block_2x2(&b1, &b2, &b3, &b4);
Self {
mass,
center_of_mass,
inertia,
value: value,
}
}
}
```

However, when I switch to a generic type, which for now I just want to restrict to f32 or f64 as an exercise (though in the future it could be custom types for uncertainty or derivative propagation), then it no longer finds + and * as implemented operations.

```
pub struct Inertia<T> {
mass: T,
center_of_mass: Vector3<T>,
inertia: Matrix3<T>,
value: Matrix6<T>,
}
impl<T> Inertia<T>
where
T: Float + Scalar + fmt::Debug,
{
fn new(mass: T, center_of_mass: Vector3<T>, inertia: Matrix3<T>) -> Self {
let c = skew(¢er_of_mass);
let ct = c.transpose();
let b1 = inertia + (mass * c * ct);
let b2 = mass * ct;
let b3 = mass * c;
let b4 = Matrix3::from_diagonal_element(mass);
let value = concat_block_2x2(&b1, &b2, &b3, &b4);
Self {
mass,
center_of_mass,
inertia,
value: value,
}
}
}
// on the + in inertia + (mass * c * ct);
cannot add `T` to `Matrix<T, Const<3>, Const<3>, ArrayStorage<T, 3, 3>>`rustcClick for full compiler diagnostic
spatial.rs(154, 18): Matrix<T, Const<3>, Const<3>, ArrayStorage<T, 3, 3>>
spatial.rs(154, 28): T
spatial.rs(149, 13): consider extending the `where` clause, but there might be an alternative better way to express this requirement: `, Matrix<T, Const<3>, Const<3>, ArrayStorage<T, 3, 3>>: Add<T>`
// on the c in inertia + (mass * c * ct);
mismatched types
expected type parameter `T`
found struct `Matrix<T, Const<3>, Const<3>, ArrayStorage<T, 3, 3>>`rustcClick for full compiler diagnostic
spatial.rs(147, 6): expected this type parameter
spatial.rs(154, 29): expected because this is `T`
let c: Matrix<T, Const<3>, Const<3>, ArrayStorage<T, 3, 3>>
// on the call to concat_block_2x2
arguments to this function are incorrect
expected reference `&Matrix<T, Const<3>, Const<3>, ArrayStorage<T, 3, 3>>`
found reference `&T`
expected reference `&Matrix<T, Const<3>, Const<3>, ArrayStorage<T, 3, 3>>`
found reference `&T`rustcClick for full compiler diagnostic
spatial.rs(150, 6): found this type parameter
spatial.rs(150, 6): found this type parameter
spatial.rs(161, 43): expected `&Matrix<T, Const<3>, Const<3>, ...>`, found `&T`
spatial.rs(161, 48): expected `&Matrix<T, Const<3>, Const<3>, ...>`, found `&T`
spatial.rs(97, 4): function defined here
```

In the end I was able to work through all the trait bounds and compile errors to achieve something that worked.

```
pub struct Inertia<T> {
mass: T,
center_of_mass: Vector3<T>,
inertia: Matrix3<T>,
value: Matrix6<T>,
}
impl<T> Inertia<T>
where
T: Float + Scalar + fmt::Debug + std::ops::AddAssign + std::ops::MulAssign,
{
pub fn new(mass: T, center_of_mass: Vector3<T>, inertia: Matrix3<T>) -> Self {
let c = skew(¢er_of_mass);
let ct = c.transpose();
let m = Matrix3::from_element(mass);
let b1 = inertia + m.component_mul(&(c * ct));
let b2 = m.component_mul(&ct);
let b3 = m.component_mul(&c);
let b4 = Matrix3::from_diagonal_element(mass);
let value = concat_block_2x2(&b1, &b2, &b3, &b4);
Self {
mass,
center_of_mass,
inertia,
value: value,
}
}
}
```

Forgive my ignorance here. I'm an aerospace engineer rather than a comp sci guy who has spent all of my career in either Matlab or other scripting languages. Rust would be my first big boy language, and I think I'm having a little bit of sticker shock that I can't figure out how to do simple operations knowing the type can only be of float without frankensteining the code. Is my final implementation the expected solution, or am I just doing something obviously wrong? I suspect it's the latter.