One vectorized approach could be with a combination of cumsum
and bsxfun
, which could be a little memory intensive though -
blocksize = 250;
valid_idx = bsxfun(@le,[1:max(P)],P');
idx_mat = bsxfun(@plus,cumsum(valid_idx,2),[0:numel(P)-1]'*blocksize);
A(:,idx_mat(valid_idx)) = 1; %// You can replace this with "A(:,unique(idx_mat))=1;"
Another slightly different approach -
blocksize = 250;
maxP = max(P);
valid_idx = bsxfun(@le,[1:maxP],P');
idx_mat = bsxfun(@plus,[0:numel(P)-1]'*blocksize,1:maxP);
A(:,idx_mat(valid_idx))=1;
Please note that to really see the benefits of vectorized solutions, you need to use it when your original loopy code has a lot of iterations going. Otherwise, the overhead associated with the preparatory work to setup vectorized approaches would be a waste. Thus, I am assuming your actual case involves more than just 4 submatrices.
Another cumsum
based approach and this one must be interesting to try out and might even prove to be the best of the lot -
blocksize = 250;
%//Get monotonically increasing labels within each group, defined by limits from idx
array1 = zeros(1,sum(P));
grp_starts = cumsum(P(1:end-1))+1;
array1(grp_starts) = P(1:end-1);
grp_labels = [1:numel(array1)] - cumsum(array1);
%// Get offsetted indices
array2 = zeros(1,sum(P));
array2(grp_starts) = blocksize;
offsetted_grp_labels = grp_labels + cumsum(array2);
A(:,offsetted_grp_labels)=1; %// perform the operation(s)