1

Say I have the following columns vector Z

 1  53  55  57  60  64  68  70  71  72  74  76  77  78  79  80  255

I want to use it to create a matrix such that each row would contain all the number between (and including) 2 adjacent elements in Z

So the output matrix should be something like this:

1 2 3 .... 53
53    54   55
55    56   57
57    58   60
....
80  81 ... 255

I've been searching for something similar but couldn't find it.

Thanks

La bla bla
  • 8,558
  • 13
  • 60
  • 109

2 Answers2

2

See if this works for you -

lens = diff(Z)+1;
mask1 = bsxfun(@le,[1:max(lens)]',lens); %//'
array1 = zeros(size(mask1));
array1(mask1) = sort([1:255 Z(2:end-1)]);
out = array1.'; %//'# out is the desired output
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • 1
    @Lablabla Welcome to the world of vector-processing by the way! :) – Divakar Nov 08 '14 at 19:28
  • @Divakar Is it always worth is to avoid loops? I see that you are really good in vectorization, could you take a look at the comparison I made? Thanks in advance. – rozsasarpi Nov 08 '14 at 20:09
  • @Arpi This probably wasn't the best of cases to use vectorization because the variance between the lengths of row is a bit on the higher side. But I have been in the habit of vectorization it just comes easier I guess. Also, I am interested in GPU and parallel computing and with it vectorization works perfectly, as indexing repeatedly into gpu arrays is really costly. So, at the end of the day, it all depends on what kind of data you are dealing with (most important factor), what your hardware is and few other things. – Divakar Nov 08 '14 at 20:30
2

Try this to break the monotony of bsxfun :) :

d = diff(Z);
N = max(d)+1;

R = zeros(length(Z)-1,N);

for i = 1:length(Z)-1
    R(i,1:1+d(i)) = Z(i):Z(i+1);
end

EDIT:

I know that the general consensus is that one always should try to avoid loops in Matlab, but is this valid for this example? I know that this is a broad question, so lets focus on this particular problem and compare bsxfun to JIT loop. Comparing the two proposed solutions:

enter image description hereenter image description here

the code used for testing:

Z =  [1  53  55 57  60  64  68  70  71  72  74  76  77  78  79  80  255];

%[1  3  4, 6];
nn = round(logspace(1,4,10));
tm1_nn = zeros(length(nn),1);
tm2_nn = zeros(length(nn),1);

for o = 1:length(nn)

    tm1 = zeros(nn(o),1);
    tm2 = zeros(nn(o),1);
    % approach1
    for k = 1:nn(o)+1
        tic
        d = diff(Z);
        N = max(d)+1;

        R = zeros(length(Z)-1,N);

        for i = 1:length(Z)-1
            R(i,1:1+d(i)) = Z(i):Z(i+1);
        end
        tm1(k) = toc;
    end


    %approach 2
    for k = 1:nn(o)+1
        tic
        lens = diff(Z)+1;
        mask1 = bsxfun(@le,[1:max(lens)]',lens); %//'
        array1 = zeros(size(mask1));
        array1(mask1) = sort([1:255 Z(2:end-1)]);
        out = array1.';
        tm2(k) = toc;
    end

    tm1_nn(o) = mean(tm1);%sum(tm1);%mean(tm1);%
    tm2_nn(o) = mean(tm2);%sum(tm2);%mean(tm2);%

end

semilogx(nn,tm1_nn, '-ro', nn,tm2_nn, '-bo')
legend('JIT loop', 'bsxfun')
xlabel('log_1_0(Number of runs)')
%ylabel('Sum execution time')
ylabel('Mean execution time')
grid on

I encountered other tasks previously where the loop was faster. (or I mess up the comparison?)

rozsasarpi
  • 1,621
  • 20
  • 34
  • Looks legit, few things that you could add, which won't necessarily change runtimes in a big way, but would rather make the runtimes more consistent - 1) Warm up `tic/toc` at the start, for which you can look up [here](http://stackoverflow.com/a/26281056/3293881) and 2) Clear variables used in one approach after it ends. – Divakar Nov 08 '14 at 20:49
  • 1
    On the topic of how the variance of lengths of each row decides whether to go for vectorization or not if performance is the topmost criteria, you could try out with a little more consistent ( in terms of having less variance in lengths) input data - `Z = [1:10:255 255]`. With this the vectorized code would work better, so just goes to show how the data plays an important role in that decision. – Divakar Nov 08 '14 at 21:11
  • Interesting, for the suggested `Z`, `bsxfun` and loop switch places compared to the original problem. I will keep in mind this effect of the 'slenderness' of matrix. Thanks! – rozsasarpi Nov 08 '14 at 21:18
  • haha that's a nice term "slenderness", I might use it for future reference! :) Thanks on coining that! – Divakar Nov 08 '14 at 21:20