I thought I'd implement a toy simulation that I use to get to grips with different languages (see here for other implementations: Comparing simple simulations in Julia, Nim, C++ and R · GitHub). A Gist of my Rust code is here - how does this look in terms of style/performance?
A few things off the top;
-
Don't inline many things, let the compiler decide when to do that, and even then, you usually only apply an inline marker when your function is really small.
-
Cool down on the type annotations, Rust has great type inference and should be taken advantage of.
-
You should make sure to use a
--release
flag when running or building:cargo run --release
-
You don't need to say
extern crate
unless the compiler specifically asks you for it in certain niche cases with weird macro edge cases -
You could use
std::time
for timing, but I'm not 100% sure on the precision of the values you get, so perhaps someone else can answer about that
Also, now that I've taken a look at your other implementations here's a few things you can do:
-
rand
is the goto crate for random numbers and other things - You can use non-ascii symbols in rust for names like you happen to do so in Julia
-
let S: i64 = u[0]; let I: i64 = u[1]; let R: i64 = u[2]; let Y: i64 = u[3];
I might write
let [S, I, R, Y] = *u;
-
sir
doesn't mutateu
. -
1.0 - f64::exp(x)
can be expressed more accurately as-f64::exp_m1(x)
Some comments:
- use rustfmt if possible
-
use std::...
not needed forf64
and such (it is already in the prelude) - you can replace the while loops with simpler for loop
for _ in 0..nsims
,for _ in 0..tf
(not sure why you're using (1..=tf
) - no need to have both
u
anddu
and you don't need amut rng: &mut ...
:
fn sir(u: &[i64; 4], parms: &[f64; 5], rng: &mut Xorshift128) -> [i64; 4] {
// ...
let infection: i64 = randbn(S, ifrac, rng);
let recovery: i64 = randbn(I, rfrac, rng);
// ...
}
// ...
u = sir(&u, &parms, &mut rng);
... and now that we're at it we can optionally simplify numerator
calculation:
let numerator: i64 = (0..nsims)
.map(|_| (1..tf).fold([60, 1, 342, 0], |u, _nxt| sir(&u, &parms, &mut rng))[3])
.sum();
- In
randbn
, you're dividing byn - x
but I think will be 0 after n iteration (ifn>0
), is it ok?
To avoid confusion - this feature is currently only available on the nightly compiler with the #![feature(non_ascii_idents)]
feature flag. Without that, identifiers have to be ASCII (matching the pattern [a-zA-Z][a-zA-Z0-9_]* | _[a-zA-Z0-9_]+
, to be more precise).
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.