Editor's note: This question's example is from a version of Rust prior to 1.0 and references types and methods no longer found in Rust. The answers still contain valuable information.
The following code
let mut numbers = new_serial.as_bytes().iter().map(|&x| (x - 48));
let sum = numbers.sum();
results in the following error:
std::iter::Map<,&u8,u8,std::slice::Items<,u8>>` does not implement any method in scope named `sum`
What must I do to sum an array of bytes?
The following works:
for byte in new_serial.as_bytes().iter() {
sum = sum + (byte - 48);
}
The Vec type allows to access values by index, because it implements the Index trait. An example will be more explicit: let v = vec![ 0, 2, 4, 6]; println!("
In Rust, there are several ways to initialize a vector. In order to initialize a vector via the new() method call, we use the double colon operator: let mut vec = Vec::new();
Iterator::sum
was stabilized in Rust 1.11.0. You can get an iterator from your array/slice/Vec
and then use sum
:
fn main() {
let a = [1, 2, 3, 4, 5];
let sum: u8 = a.iter().sum();
println!("the total sum is: {}", sum);
}
Of special note is that you need to specify the type to sum into (sum: u8
) as the method allows for multiple implementations. See Why can't Rust infer the resulting type of Iterator::sum? for more information.
Applied to your original example:
let new_serial = "01234";
let sum: u8 = new_serial.as_bytes().iter().map(|&x| x - 48).sum();
println!("{}", sum);
As an aside, it's likely more clear if you use b'0'
instead of 48
.
If performance is important, consider using an implementation that helps the compiler at producing SIMD instructions.
For example, for f32
, using 16 lanes (total of 512 bits):
use std::convert::TryInto;
const LANES: usize = 16;
pub fn nonsimd_sum(values: &[f32]) -> f32 {
let chunks = values.chunks_exact(LANES);
let remainder = chunks.remainder();
let sum = chunks.fold([0.0f32; LANES], |mut acc, chunk| {
let chunk: [f32; LANES] = chunk.try_into().unwrap();
for i in 0..LANES {
acc[i] += chunk[i];
}
acc
});
let remainder: f32 = remainder.iter().copied().sum();
let mut reduced = 0.0f32;
for i in 0..LANES {
reduced += sum[i];
}
reduced + remainder
}
pub fn naive_sum(values: &[f32]) -> f32 {
values.iter().sum()
}
for
let values = (0..513).map(|x| x as f32).collect::<Vec<_>>();
the above is 10x faster than values.iter().sum()
on my computer:
nonsimd_sum time: [77.341 ns 77.773 ns 78.378 ns]
naive_sum time: [739.97 ns 740.48 ns 740.97 ns]
and ~10% slower than using packed_simd2
(but it does not require nightly).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With