Sum of following elements in array

Is there a faster way to do the following
s = rand(1, 10);
sum_following = zeros(length(s), 1);
for i = 1:length(s)-1
sum_following(i) = sum(s(i+1:end), 'all');
end
without doing
sum_following = sum(s,"all") - cumsum(s);
?

9 Comments

sum_following = sum(s,"all") - cumsum(s);
I doubt there is a faster method than this.
And as the input is a vector, you don't need to specify 'all' for the sum() call.
The point is that doing this is fast but not numerically stable if the last entries of s are close to zero.
Dyuman Joshi
Dyuman Joshi on 9 Dec 2023
Edited: Dyuman Joshi on 9 Dec 2023
Well, the function sum() is instable.
I am referring to another type of instability. Try the following
s = [1, eps].^2
s = 1×2
1.0000 0.0000
sum_following = zeros(length(s), 1);
for i = 1:length(s)-1
sum_following(i) = sum(s(i+1:end), 'all');
end
sum_following
sum_following = 2×1
1.0e-31 * 0.4930 0
sum_following_cumsum = sum(s,"all") - cumsum(s);
sum_following_cumsum
sum_following_cumsum = 1×2
0 0
Yes, that shows that sum() is not stable.
Take a look at the FEX submission I linked.
Technically, this is not "instability". It's just limited precision.
How is that due to limited precision?
Because
1+eps^2 == 1
ans = logical
1
The point is that doing this is fast but not numerically stable if the last entries of s are close to zero.
The loop with
sum(s(i+1:end), 'all');
is not numerically stable either. The trailing suffix [... A B -B -A] is going to come out as -A if abs(A) < eps(B)
Side note: You are using linear indexing. Linear indexing of anything always gives a vector result, and for a vector being added together, 'all' as a parameter does not provide any value.
Linear indexing of row vector: gives a row vector
Linear indexing of column ector: gives a column vector
Linear indexing of non-vectors: gives a result that is the same shape as the indices. Which, for i+1:end would be a row vector.

Sign in to comment.

 Accepted Answer

Matt J
Matt J on 9 Dec 2023
Edited: Matt J on 9 Dec 2023
sum_following = cumsum([s(2:end),0],"reverse");

More Answers (0)

Categories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!