Hi, I'm new to Rust and in order to learn I decided to start implementing some numeric algorithms I'm familiar with, like Runge Kutta.
I implemented it for the scalar case using f64 types, worked as expected. Now I was trying to make the function use generic types so that it would work on e.g. vector-valued functions. This is where I got stuck...
what I need to tell Rust is that the type V supports addition with other Vs and multiplication with elements of type S, and S can be multiplied and divided with elements of type f64 (or maybe cast all my constants to Float? but that would add a lot of clutter I think).
As of Now I think I'm telling it that V can be added to other Vs and multiplied with other Vs? (which is not what I need) But if I change Mul<Output = V> by Mul<Output = S> it doesn't work either.
use num_traits::Float;
use std::ops::{Add, Mul};
fn runge_kutta_4<V, S>(f: fn(S, V) -> V, y_curr: V, t_curr: S, step_size: S) -> V
where
V: Clone + Add<Output = V> + Mul<S, Output = V>,
S: Float + From<f64> + Mul<Output = S>,
{
let half_step = <S as From<_>>::from(0.5) * step_size;
let k1 = f(t_curr, y_curr.clone());
let k2 = f(t_curr + half_step, y_curr.clone() + k1.clone() * half_step);
let k3 = f(t_curr + half_step, y_curr.clone() + k2.clone() * half_step);
let k4 = f(t_curr + step_size, y_curr.clone() + k3.clone() * step_size);
let two = <S as From<_>>::from(2.0);
y_curr + (k1 + k2 * two + k3 * two + k4) * (step_size / <S as From<_>>::from(6.0))
}
There were quite a few problems:
As you noted, you need to specify that V * S is available, done by specifying the Rhs parameter to the Mul trait.
You were using S * V in a number of places, so I had to reverse the arguments. Multiplication is commutative, but Mul is not.
You can't use literals with generic types, so I had to explicitly require a conversion from f64 -> S. The <S as From<_>> construct is because one of the num_traits traits also defines a from method, so I had to disambiguate.
You re-used Vs in a number of places, so I had to require Clone.
Edit: You know, it would be good if the forum had a more obvious "hey, someone has posted another comment while you've been editing this one" signal.