Out of curiosity, I benchmarked the unsafe sum function and a naive version:
pub fn naive(x: &[i32], y: &[i32], z: &[i32]) -> i32 {
x.iter().zip(y.iter()).zip(z.iter())
.map(flatten) // ((a, b), c) -> (a, b, c)
.fold(0, |a, (x, y, z)| a + *x + *y + *z)
}
And a safe version of the loop:
pub fn naive_loop(x: &[i32], y: &[i32], z: &[i32]) -> i32 {
let n = min(x.len(), min(y.len(), z.len()));
let mut s = 0;
for i in 0..n {
s += x[i] + y[i] + z[i];
}
s
}
Results were:
test tests::naive ... bench: 2094 ns/iter (+/- 106)
test tests::naive_loop ... bench: 1412 ns/iter (+/- 44)
test tests::unsafe_loop ... bench: 360 ns/iter (+/- 16)
I can understand the unsafe one being faster… but the iterator version, which is supposed to avoid bounds checks, being slower than a naive loop? That’s… really less than ideal.
Edit: “compressed” test case on playpen if you want to reproduce. Make sure to read comment on the test data set.