Not too hard to roll a simple one (for simple situations) which might be faster than the more generic approach.
function rolling_sum(a, n::Int)
@assert 1<=n<=length(a)
out = similar(a, length(a)-n+1)
out[1] = sum(a[1:n])
for i in eachindex(out)[2:end]
out[i] = out[i-1]-a[i-1]+a[i+n-1]
end
return out
end
This seems to work but no warranty implied, etc.
P.S. Just for fun, here’s a threaded version, which with four threads gives me about 2x performance.
function trolling_sum(a, n::Int)
@assert 1<=n<=length(a)
nseg=4
if nseg*n >= length(a)
return rolling_sum(a,n)
else
out = similar(a, length(a)-n+1)
lseg = (length(out)-1)÷nseg+1
segments = [(i*lseg+1, min(length(out),(i+1)*lseg)) for i in 0:nseg-1]
Threads.@threads for (start, stop) in segments
out[start] = sum(a[start:start+n-1])
for i in start+1:stop
out[i] = out[i-1]-a[i-1]+a[i+n-1]
end
end
return out
end
end
I’m not completely sure about thread safety here. All threads write to out
, but never to the same location in out
.