Using arrayfun to apply two function arguments in each combination
Let i = [1 2]
and j = [3 5]
. Now in the octave:
arrayfun(@(x,y) x+y,i,j)
we get [4 7]
. But I want to apply the function to combinations of i
vs. j
to receive [i(1)+j(1) i(1)+j(2) i(2)+j(1) i(2)+j(2)]=[4 6 5 7]
.
How to do it? I know I can use for-loopsl, but I need vector code because it's faster.
source to share
In Octave, to find the sum between two vectors, you can use a truly vectorial approach with broadcasting
like this -
out = reshape(ii(:).' + jj(:),[],1)
Here's a runtime test ideone
for input size vectors 1 x 100
each -
-------------------- With FOR-LOOP
Elapsed time is 0.148444 seconds.
-------------------- With BROADCASTING
Elapsed time is 0.00038299 seconds.
If you want to keep it general to accommodate operations other than just summing, you can use anonymous functions, like:
func1 = @(I,J) I+J; out = reshape(func1(ii,jj.'),1,[])
In MATLAB, you can do the same with two alternatives bsxfun
as shown below.
I am. bsxfun
with anonymous function -
func1 = @(I,J) I+J; out = reshape(bsxfun(func1,ii(:).',jj(:)),1,[]);
II. bsxfun
with @plus inline -
out = reshape(bsxfun(@plus,ii(:).',jj(:)),1,[]);
With input vectors of size 1 x 10000
each, the runtime at my end was -
-------------------- With FOR-LOOP
Elapsed time is 1.193941 seconds.
-------------------- With BSXFUN ANONYMOUS
Elapsed time is 0.252825 seconds.
-------------------- With BSXFUN BUILTIN
Elapsed time is 0.215066 seconds.
source to share
Firstly, your first example is not the best, because the most efficient way to accomplish what you are doing with arrayfun
would be vectorizing:
a = [1 2];
b = [3 5];
out = a+b
Second, in Matlab at least arrayfun
not necessarily faster than a simple loop for
. arrayfun
is mostly convenience (especially for more advanced options). Try this simple sync example:
a = 1:1e5; b = a+1; y = arrayfun(@(x,y)x+y,a,b); % Warm up tic y = arrayfun(@(x,y)x+y,a,b); toc y = zeros(1,numel(a)); for k = 1:numel(a) y(k) = a(k)+b(k); % Warm up end tic y = zeros(1,numel(a)); for k = 1:numel(a) y(k) = a(k)+b(k); end toc
In Matlab R2015a, the loop method is for
more than 70 times faster to run from the Command window and 260 times faster when run from the M file function. The octave may be different, but you should experiment.
Finally, you can accomplish what you want with meshgrid
:
a = [1 2]; b = [3 5]; [x,y] = meshgrid(a,b); out = x(:).'+y(:).'
which returns [4 6 5 7]
as in your question. You can also use ndgrid
to get the result in a different order.
source to share