How to set up an anonymous function to take vector input in Octave?

442 Views Asked by At

I would like to define an anonymous function that takes a vector, but I am unable to achieve that unless every element in the vector is specified:

Data = 
[ X11 X12;
  X21 X22];

Iteration #1: V -> [X11 X12] (desired row of values to be passed into 'some_func' at each iteration). Iteration #2: V -> [X21 X22]

This works:

good_func_handle = @(a1,a2)  some_func([a1,a2],bla,bla)
output = arrayfun(good_func_handle,Data(:,1),Data(:,2)) -> to avoid having to write a for loop

This doesn't work:

bad_func_handle = @(vec)  some_func(vec,bla,bla)
output = arrayfun(bad_func_handle,Data)

When this is called only the first element X11 is passed in to some_func but not X11 and X12.

Is there a way to set up the function to take a vector variable as input instead of having to specify all elements in the vector?

1

There are 1 best solutions below

5
Cris Luengo On

The problem is in arrayfun, not in the function being called. arrayfun loops over each element of the input array, not each row. In your first solution, you created input arrays such that looping over each element was the right thing to do.

Since arrayfun is just a loop, there is no advantage in time for using it, other than programmer time. It is just supposed to simplify writing a loop over an array. [Qualifications: In MATLAB, arrayfun adds overhead because a function needs to be called for each iteration; this can be significant as shown below. In Octave, arrayfun seems to be a bit more efficient than a plain loop, see smcmi's comments below.]


In response to the comment below by @smcmi, I re-created their experiment as follows:

a = zeros(1, 1e6);

b = method1(a);
c = method2(a);
assert(isequal(b,c))

timeit(@()method1(a))
timeit(@()method2(a))

function out = method1(in)
    out = zeros(size(in));
    for ii=1:numel(in)
        out(ii) = in(ii) * 2;
    end
end

function out = method2(in)
    out = arrayfun(@(x) x * 2, in);
end

Running this using MATLAB Online (which is pretty slow usually) I see this output:

ans =
    0.0036

ans =
    2.5299

That is, the plain loop takes 0.0036 s, whereas arrayfun takes 2.5 s. This is three orders of magnitude difference.

The largest cost in arrayfun is calling a function for every array element. In MATLAB, calling a function still carries a bit of overhead, whereas the loop is completely optimized by the JIT and runs at speeds similar to those seen in any compiled language.

In Octave the timings are quite different, as it has no JIT at all. See comments below this answer for Octave performance.