Is it safe to use cumsum!(x, x)
to replace the contents of x
with cumsum(x)
(in order to avoid allocating another vector to hold the result)? Am I relying on implementation details that may change?
You can just write a for
loop instead and guarantee to yourself what the function does.
Seems ok:
julia> r = rand(10);
julia> cumsum(r) == cumsum!(r, r)
true
From a quick test, cumsum!(x, x)
seems to return the same results as cumsum!(copy(x), x)
.
Edit: I’m actually not sure what the below should do — prod!
returns a result of different shape than its input. I was thinking of the cumulative product, which is a different function, and does return the same result in both cases.
Looking at a similar function, prod!(x, x)
does not return the same results as prod!(copy(x), x)
, so the fact that cumsum!
works seems like it’s an implementation detail.
I think the prod!
behavior is a footgun. It should be possible to check for aliasing and either error or revert to a slower algorithm that returns the correct result, rather than quietly returning an incorrect one.
julia> x = [2, 3, 4]
3-element Array{Int64,1}:
2
3
4
julia> prod!(copy(x), x)
3-element Array{Int64,1}:
2
3
4
julia> prod!(x, x)
3-element Array{Int64,1}:
1
1
1
Shouldn’t it be documented if it doesn’t work? I remember seeing this specified in some !
functions, though I cannot remember which ones right now, of course.
That would be better. It would be nice if functions like this always either returned a correct result or threw an error, with clearly documented exceptions when error checking is impossible or too expensive.
Seems safest to write a for
loop as @dpsanders suggested, or to write a single-argument inplace_accumulate!(op, x)
that wraps this for
loop.
Thanks!
Yes, although cumsum
uses pairwise summation for improved accuracy over a simple loop.
Arguably, if it works for input == output
, there should just be a single-argument cumsum!(x)
function. (This should make an easy PR for anyone who wants to take it on.)
(Since the cumsum!
implementation uses each input exactly once, IIRC, then it should indeed be safe to overwrite the input.)
xref
https://github.com/JuliaLang/julia/issues/26412
(Edit: I am on a roll today… my apologies. this is not actually related.)