Is there a way to get rid of this for loop and do the entire operation with one line? Playground link.
FYI, I think you wanted 0..11
(0 through 10).
The direct approach would be as follows:
fn main() {
let iny1:[i32;5] = [1,2,3,4,5];
let iny2:[i32;15] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let outy2: Vec<i32> = (0..11).map(|i| {
iny2.iter().skip(i).zip(&iny1).map(|(x,y)|x*y).sum()
}).collect();
for k in outy2.iter() {
println!("{:9}",k);
}
}
However, I recommend using windows
. This is actually how I caught that bug (never mess with indices directly unless you absolutely have to).
fn main() {
let iny1:[i32;5] = [1,2,3,4,5];
let iny2:[i32;15] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let outy2: Vec<i32> = iny2.windows(iny1.len()).map(|window| {
window.iter().zip(&iny1).map(|(x,y)|x*y).sum()
}).collect();
for k in outy2.iter() {
println!("{:9}",k);
}
}
Thank you! I was sure the right answer would have indicies but I didn't see windows in the doc. I lobe the rust community.
For others interested, here it is in the docs: slice - Rust
If I scale this up to signal processing sizes (1024 and 1024^2 instead of 5 and 15) I get a trait bounds error. Looks like std::iter::Iterator is limited to 32 elements. Is there a way around this?
That's a problem with arrays -- we don't have integer generics yet, so most of its traits are manually unrolled up to 32 elements. In this case you're actually missing IntoIterator
. You can get around this by manually slicing it, zip(&iny1[..])
.
But as you get to larger sizes, you're going to run into trouble holding such large data on the stack, and a Vec
will probably serve you better.
Thank you, the vector worked and also somehow nudged the autovectorizer into using SSE.