2

It is really stupid all I am trying to do is having a 7 column matrix consisiting all mod 7 numbers and it takes a huge time to generate such a matrix utilizing the following code

to = 7^k;
msgValue = zeros(to,k);
for l=0:to
    for kCounter=0:(k-1)
        msgValue(l+1,kCounter+1)=mod((l/7^kCounter),7);
    end 
end
msgValue = floor(msgValue);

How can I do this faster?

Divakar
  • 218,885
  • 19
  • 262
  • 358
shampoo
  • 1,173
  • 12
  • 22
  • How about `dec2base`? – knedlsepp Apr 25 '15 at 12:28
  • 1
    In addition to the very good answers you got, you could also take [this route](http://stackoverflow.com/questions/21895335/generate-a-matrix-containing-all-combinations-of-elements-taken-from-n-vectors). It should be pretty fast too. – Luis Mendo Apr 25 '15 at 14:46
  • @LuisMendo, when I saw this question I directly went to your `comb` solution to see if it would work for that. It's only when I started to rework your input cell array that I realized that a simple matrix multiplication could do the job directly. I should have mentioned your post anyway, its so often useful that it is good to have references to it. – Hoki Apr 25 '15 at 14:52
  • @Hoki Yes, matrix multiplcation is always a fast approach, when possible. My answer is more general, but is probably slower in this case. Thanks for your comment! – Luis Mendo Apr 25 '15 at 14:56

3 Answers3

3

You can use a vectorized approach with bsxfun -

msgValue = floor(mod(bsxfun(@rdivide,[0:to]',7.^(0:(k-1))),7));

Quick runtime tests for k = 7:

-------------------- With Original Approach
Elapsed time is 1.519023 seconds.
-------------------- With Proposed Approach
Elapsed time is 0.279547 seconds.
Divakar
  • 218,885
  • 19
  • 262
  • 358
3

Or another vectorized approach (direct matrix multiplication):

msgValue = floor( mod( (0:7^k).' * (1./(7.^(0:k-1))),7 ) ) ;

a wee bit faster than the famous bsxfun ;-)

%// For 10000 iterations, k=3
Elapsed time is 2.280774 seconds. %// double loop
Elapsed time is 1.329179 seconds. %// bsxfun
Elapsed time is 0.958945 seconds. %// matrix multiplication
Hoki
  • 11,637
  • 1
  • 24
  • 43
0

I used a submssion from matlab central called rude, which I tend to use from time to time and was able to eliminate one for loop and vectorize the code to some extent.

tic
k=7;
modval = 7;
to=modval^k;
mods = mod(0:(modval-1),modval);
msgValue=zeros(to,k);
for kCounter=1:k
    aux = rude(modval^(kCounter-1)*ones(1,modval),mods)';
    msgValue(:,kCounter) = repmat(aux,to/(7^kCounter),1);
end
toc

The idea behind the code is to make at the beginning of each iteration the building block of the column vector using the rude function. Rude, in turn, uses mods = [0 1 2 3 4 5 6] as a starting point for the manipulation. The real work is done through vectorization.

You did not mention how long your code takes to run. So I timed it just once to give you a rough idea. It ran in 0.43 seconds in my machine, a Windows 7 Ultimate, 2.4 GHz, 4GB Ram, Dual CPU.

Also, the way you defined your loop adds a repetition in your msgValue matrix. The first row consists of zero values throughout all columns, and so the last row, which I also fixed. For a toy example with k=3, your code returns a 344x1 matrix, while you explicitly initialize it as a 7³x1 (343x1) matrix.

brodoll
  • 1,851
  • 5
  • 22
  • 25