Search code examples
arraysmatlabvectorbsxfun

MATLAB: efficient way to run a vector input function with an array input


I have a function HermitePCECoefficients which takes as inputs multiple parameters, including a column vector y, and outputs a column vector Coefficients, the same length as y:

Coefficients=HermitePCECoefficients(grid,weights,indices,y,mu,sigma,normalized)

Suppose now that y is not a column vector, but a 2D array (matrix), and I want to run HermitePCECoefficients on each of its columns, storing the corresponding outputs in a array. Doing it with a for loop is simple and clear, but it takes forever:

Coefficients=zeros(size(y));
for i=1:size(y,2)
    Coefficients(:,i)=HermitePCECoefficients(grid,weights,indices,y(:,i),mu,sigma,normalized);
end
    

Thus, I put bsxfun to the job. Since bsxfun only works with binary functions, I created a "dummy" binary function f, which is really only a function of a single argument:

f=@(a,b) HermitePCECoefficients(grid,weights,indices,a,mu,sigma,normalized); 

Then used bsxfun this way:

Coefficients=bsxfun(f,y,omega_f);

This works fine, and it's much faster than the for loop (don't worry about omega_f, it's just a vector whose length corresponds to the number of columns in y).

Question 1: do you think this is the right way to use bsxfun in this context?

Question 2: maybe a better solution would be to directly modify HermitePCECoefficients, so that it could take a generic array y as input. Inside the function, this is the only line which requires y to be a column vector:

Coefficients(i)=dot(weights,y.*Psi)/norm;

weights and Psi are two column vectors, so if I pass an array y, MATLAB complains. Any suggestions on how to modify it?


Solution

  • Option 2 seems better (but only testing will tell). Just replace

    dot(weights,y.*Psi)/norm
    

    by

    sum(bsxfun(@times, weights.*Psi, y)/norm)
    

    or (probably faster)

    (weights.*Psi).'*y / norm
    

    Either of the above is equivalent to computing the vector [ dot(weights,y(:,1).*Psi)/norm, dot(weights,y(:,2).*Psi)/norm, ... ] for an arbitrary number of columns of y. Each entry of this vector is the result for a column of y.