Reputation: 311
INPUT: a logical row vector u
with length n
, say [1,0,1,1,0]
; and a logical matrix M
of size m-by-n, say [1,0,0,1,1;0 0 0 1 1]
.
OUTPUT: a logical matrix of size m-by-n, the first row of which is obtained by applying the first row of matrix M
as "selector", that is, [1,0,0,1,0];
and the second row is, similarly, [0 0 0 1 0]
.
The row vector is 20000 long, and the the matrix is 30-by-20000. This will repeat 1000 times, and I want something costs less than 1 second.
I've tried repmat
, bsxfun
, and element-wise multiplication, no luck. Guess there is a simple way to "choose" these elements all at once, since they are all logical values.
Upvotes: 4
Views: 1012
Reputation: 733
Other solutions are overcomplicating things.
All you need to do is zero out the entries in the non-chosen columns...
M(:,~u)=0;
That's it. Ten measly characters. Chris Taylor's solution using bsxfun with @and is a little slower, other methods are worse.
octave:8> u = logical(rand(1,20000)<0.5);
octave:9> M = logical(rand(30,20000)<0.5);
octave:10> tic, for i=1:1000, N=M; N(:,~u)=0; end, toc
Elapsed time is 0.66 seconds.
octave:11> tic, for i=1:1000, N=M; N=bsxfun(@and,u,N); end, toc
Elapsed time is 0.82 seconds.
octave:12> tic, for i=1:1000, N=bsxfun(@and,u,M); end, toc
Elapsed time is 0.8 seconds.
Note that I've used "N=M" to standardise the result, because this method acts directly on the vector, but the assignment isn't adding anything significant to the time.
Upvotes: 0
Reputation: 47402
The fastest I can give you is 4 seconds at the moment (on my machine). I'm not 100% sure if you've tried this or not, but here you go anyway.
I have an m-file randbool.m
with these contents, to generate the test data.
function x = randbool(m,n)
x = logical(rand(m,n) < 0.5);
Generate the data for testing:
>> u = randbool(1,20000);
>> M = randbool(30,20000);
I can think of three ways to loop over the rows of M (use bsxfun
, use repmat
, use a loop) and two ways to pull out the elements you want (conjunction &
, or pointwise multiplication with .*
). The fastest is the combination of bsxfun
and conjunction:
>> tic, for i=1:1000, bsxfun(@and,u,M); end, toc
Elapsed time is 4.068684 seconds.
>> tic, for i=1:1000, bsxfun(@times,u,M); end, toc
Elapsed time is 4.856784 seconds.
>> tic, for i=1:1000, utmp=repmat(u,30,1); M&utmp; end, toc
Elapsed time is 7.305158 seconds.
>> tic, for i=1:1000, utmp=repmat(u,30,1); M.*utmp; end, toc
Elapsed time is 8.117164 seconds.
>> tic, for i=1:1000, for j = 1:30, out(j,:)=u&M(j,:); end; end, toc
Elapsed time is 7.110872 seconds.
>> tic, for i=1:1000, for j = 1:30, out(j,:)=u.*M(j,:); end; end, toc
Elapsed time is 8.322888 seconds.
Upvotes: 1
Reputation: 39728
This looks like a bitwise and operation. Perhaps something like this would work:
utemp=repmat(u,1,size(m,2));
output=M&utemp;
I should add that for that large of a matrix, you might run into memory problems. Essentially you need 3 copies of the 600K element matrix, which could add up.
Upvotes: 0