2

I wrote a code that generates a vector of increasing length, that is later stacked in a matrix row after row. This is a sample of how the code works

    PPR=[0     2     3     5     6     8];
    AI=[ 0    0.7854    0.5236    0.3142    0.2618    0.1963];

    for ii=1:numel(PPR);
        qp=0:PPR(ii);
        xp(ii,1:PPR(ii)+1)=sin(AI(ii)*qp)+1    
    end

How can I vectorize this loop ?

1
  • Do you want to vectorize it because it's slow? If so, you should at least try preallocating first and then storing the results column wise since matlab is column major. Commented Mar 29, 2013 at 0:13

2 Answers 2

1

Here's a fully vectorized way to construct the matrix - no loops, no arrayfun:

PPR=[0     2     3     5     6     8];
AI=[ 0    0.7854    0.5236    0.3142    0.2618    0.1963];


M = ones(length(PPR),PPR(end)+1); #% allocate proper sized matrix of ones
r=1:length(PPR)-1; #% row indices for 1 element past the end of each row vector
c=PPR(1:end-1)+2; #% corresponding column indices
linear_index = sub2ind(size(M),r,c); #% create linear index from r,c
M(linear_index)=nan; #% set those elements to NaN
M2 = cumsum(M,2)-1; #% use cumsum to propagate the NaN values
M3 = bsxfun(@times,M2,AI'); #%'#multiply each row by the appropriate AI value
xp = sin(M3)+1 #% take the sine of the matrix

I've used a bunch of temporary variables for clarity. If you want to avoid cluttering your workspace, you can avoid them since they often aren't used more than once.

Also note: this fills the matrix with NaNs where you haven't specified any other value. If you wish to replace these with some other default (zeros or ones, for example) that is very straightforward to do at the end.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 for the interesting solution. Specially Nan propagation is cool. However I've tested all 3 codes with tic/toc (2012b, win7), and OP's one with the loop is the best (mine is worse as expected). JIT compiler at work.
0

Here is vectorized code. I still had to use ARRAYFUN ones. So test with tic/toc if it's faster than your loop.

n = numel(PPR); % number of rows
m = max(PPR)+1; % number of columns
qp = arrayfun(@(x)[0:PPR(x) nan(1,m-PPR(x)-1)],1:n,'UniformOutput',0);
qp = vertcat(qp{:});
a = ~isnan(qp); % to add ones later
qp(~a) = 0;
xp = sin(bsxfun(@times,AI',qp)) + a;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.