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

2 answers

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.




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
y = arrayfun(@(x,y)x+y,a,b);

y = zeros(1,numel(a));
for k = 1:numel(a)
    y(k) = a(k)+b(k); % Warm up
y = zeros(1,numel(a));
for k = 1:numel(a)
    y(k) = a(k)+b(k);


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.



All Articles