Search code examples
matlabfunction-handle

Dynamically generate function for use in function handle


I'd like to dynamically construct a function that can then be referred to with a function handle for later use in Matlab functions such as integral(fun,a,b).

As an example imagine a function with terms:

(x-A)/(D-A) * (x-B)/(D-B) * (x-C)/(D-C)

where x is a variable and A,B,C,D are constants from a vector (call it K=[A,B,C,D]' as an example) generated by a different function.

I could do:

fun = @(x) (x-A)/(D-A) * (x-B)/(D-B) * (x-C)/(D-C)

However, this restricts me to three terms. I'd like to be able to take an arbitrary length vector of constants and generate a function of similar form to the one above. Normally this is easy in Matlab, but it seems like function handles expect 'x' to be a scalar, so something like:

prod( (x - K(1:3)) ./ K(4)-K(1:3) )

returns an error.


Solution

  • It's not true that

    function handles expect 'x' to be a scalar

    The problem is not the function handle, nor the fact that the function is anoymous. The problem is simply the operation you use to define that function: you can't do

    prod( (x - K(1:3)) ./ K(4)-K(1:3) )

    when both x and K are vectors with arbitrary sizes. As a side note, you have a pair of brackets missing in the denominator.

    What you want (if I understand correctly) can be done using bsxfun twice. Assuming both x and K are column vectors, use

    prod(bsxfun(@rdivide, bsxfun(@minus, x.', K(1:end-1)), K(end)-K(1:end-1)))
    

    to compute your function.

    So: first define K and then you can define the anonymous function and its handle as

    fun = @(x) prod(bsxfun(@rdivide,bsxfun(@minus,x.',K(1:end-1)),K(end)-K(1:end-1)))
    

    Note that the value of K is "hardwired" into the anonymous function when you define the latter. The function won't change if you later modify K (unless of course you define the function again with the new K).

    Example:

    >> K = [3 4 5 6].';
    >> fun = @(x)prod(bsxfun(@rdivide,bsxfun(@minus,x.',K(1:end-1)),K(end)-K(1:end-1)));
    >> x = [1 2].';
    >> fun(x)
    ans =
        -4    -1
    

    Check:

    >> prod( (x(1) - K(1:3)) ./ (K(4)-K(1:3)) )
    ans =
        -4
    
    >> prod( (x(2) - K(1:3)) ./ (K(4)-K(1:3)) )
    ans =
        -1