(Starting with a
being 1-by-m or m-by-1)
Solution 1
(Credit to @Cris Luengo)
abs(a-a.')>z
The outer product like behavior requires Matlab 2016b or newer.
Solution 2
Using bsxfun
abs(bsxfun(@minus,a,a.'))>z
Solution 3
Using repmat
A=repmat(a,fliplr(size(a)));
abs(A-A.')>z
To see how to manipulate the results, consult mathwork documentations on logical arrays.
Technically, you only need tril
or triu
of the results.
Regarding speed
Looping is out of my considerations. I've seen it being slow in too many occasions. Even though looping technically saves half the amount of computation, it comes with other overheads. So I still expect vectorized methods to be faster and I do not really see a need to test looping. Even repmat
with its high memory allocation cost should be faster.
See below for timing data in R2018a. You may wish to use a more accurate timer such as this one written in c if you want to do more testing. For full disclosure, while I tested, there was little cpu demand other than Matlab. I did try with and without 'warm up' rounds -- especially since I do have defined boost behaviors for some cores on my cpu -- but 'warming up' actually made the numbers worse in every subsequent 1000 or 10000 runs. Perhaps my RAM wasn't keeping up with repmat
.
Basically, the new syntax (Solution 1) is blazing fast. Time to upgrade if you haven't already. bsxfun
is your next best until you upgrade. repmat
's memory allocation cost scales too poorly. It's best to avoid repmat
.
%%%%%%% 1000 x 1000
>> clear all
>> a = randi([-10, 10], [1, 1000]); z=5; N=1000;
>> T=zeros(N,1);tic; for i=1:N; abs(a-a.')>z;T(i)=toc;end; mean(T),
ans =
0.2680
>> clear all
>> a = randi([-10, 10], [1, 1000]); z=5; N=1000;
>> T=zeros(N,1);tic; for i=1:N; abs(bsxfun(@minus,a,a.'))>z;T(i)=toc;end; mean(T),
ans =
1.3556
>> clear all
>> a = randi([-10, 10], [1, 1000]); z=5; N=1000;
>> T=zeros(N,1);tic; for i=1:N; A=repmat(a,fliplr(size(a))); temp=abs(A-A.')>z;T(i)=toc;end; mean(T),
ans =
4.0573
%%%%%%% 100 x 100
>> clear all
>> a = randi([-10, 10], [1, 100]); z=5; N=10000;
>> T=zeros(N,1);tic; for i=1:N; abs(a-a.')>z;T(i)=toc;end; mean(T),
ans =
0.0610
>> clear all
>> a = randi([-10, 10], [1, 100]); z=5; N=10000;
>> T=zeros(N,1);tic; for i=1:N; abs(bsxfun(@minus,a,a.'))>z;T(i)=toc;end; mean(T),
ans =
0.1537
>> clear all
>> a = randi([-10, 10], [1, 100]); z=5; N=10000;
>> T=zeros(N,1);tic; for i=1:N; A=repmat(a,fliplr(size(a))); temp=abs(A-A.')>z;T(i)=toc;end; mean(T),
ans =
0.1815
% Note: assigning the output to a variable or not does not change the result. At least tic toc is not able to detect it.