DeltaIV
DeltaIV

Reputation: 5646

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?

Upvotes: 3

Views: 154

Answers (2)

Luis Mendo
Luis Mendo

Reputation: 112659

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.

Upvotes: 2

RdeG
RdeG

Reputation: 83

You could use repmat on weights and Psi to replicate the vectors across the columns of y:

nc = size(y,2);
Coefficients = dot(repmat(weights,1,nc), y.*repmat(Psi,1,nc))/norm;

Upvotes: 1

Related Questions