9

Suppose I have 2 input vectors x and reset of the same size

x = [1 2 3 4 5 6]
reset = [0 0 0 1 0 0]

and an output y which is the cumulative sum of the elements in x. Whenever the value of resets corresponds to 1, the cumulative sum for the elements reset and start all over again just like below

y = [1 3 6 4 9 15]

How would I implement this in Matlab?

Divakar
  • 218,885
  • 19
  • 262
  • 358
Alex
  • 93
  • 4

2 Answers2

8

One approach with diff and cumsum -

%// Setup few arrays: 
cx = cumsum(x)         %// Continuous Cumsumed version
reset_mask = reset==1  %// We want to create a logical array version of 
                       %// reset for use as logical indexing next up

%// Setup ID array of same size as input array and with differences between 
%// cumsumed values of each group placed at places where reset==1, 0s elsewhere
%// The groups are the islands of 0s and bordered at 1s in reset array.
id = zeros(size(reset))
diff_values = x(reset_mask) - cx(reset_mask)
id(reset_mask) = diff([0 diff_values])

%// "Under-compensate" the continuous cumsumed version cx with the 
%// "grouped diffed cumsum version" to get the desired output
y = cx + cumsum(id)
Divakar
  • 218,885
  • 19
  • 262
  • 358
5

Here's a way:

result = accumarray(1+cumsum(reset(:)), x(:), [], @(t) {cumsum(t).'});
result = [result{:}];

This works because if the first input to accumarray is sorted, the order within each group of the second input is preserved (more about this here).

Community
  • 1
  • 1
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147