Brandon1234
Brandon1234

Reputation: 23

Calling an .m file through another function file in matlab

My professor is having me write a program to perform the bisection routine to find the root of an equation. Before I go on, here are the program files so far:

function [l,r,nf] = bisect(fname,a,b,tol)

nf=0;

if (fname(a)*fname(b))>0
    errflag='Choose an interval (a,b) where f(a)*f(b) is negative'
    root='N/A'
else
    while abs(fname(a)-fname(b))>tol
        p=a+(b-a)/2;
        if (fname(a)*fname(p))<0
            b=p;
        else
            a=p;
        end
    nf=nf+1;
    end
end

nf
l=a
r=b

end 

Aside from the bisect.m file, he had us write a simple program fofx.m to evaluate the equation at whatever point. It looks like:

function [y]=fofx(x)

y=cos(x)-sin(x);

end

He wants us to have the fofx.m entered as an input argument so one can use any generic equation .m file. He has assigned us a test routine to operate the program. The test routine (which I am not allowed to change), is

try 
    delete('prog4run');
end

diary prog4run
format long e

[l,r,nfb] = bisect('fofx',0.7,0.9,1e-6);
p = l+(r-l)/2;
disp(' ')
disp(' ')
disp('   Bisect output:')
disp('root approx:'),p
disp(' ')
disp('error:'),abs(p-pi/4)
disp(' ')
disp('number of fcn evals:'),nfb
disp(' ')
disp(' ')

When I invoke the program in the command window by typing in:

bisect(@fofx,0.7,0.9,1e-6)

Bisect works perfectly. But when his test routine uses the line:

[l,r,nfb] = bisect('fofx',0.7,0.9,1e-6)   

Even if I type this into the command window, I get the error:

Attempted to access fname(0.7); index must be a positive integer or logical.
Error in bisect (line 5)
if (fname(a)*fname(b))>0
Error in SCProg4Test (line 13)
[l,r,nfb] = bisect('fofx',0.7,0.9,1e-6); 

Can anyone help me?

Upvotes: 2

Views: 193

Answers (1)

TroyHaskin
TroyHaskin

Reputation: 8401

str2func

The problem is that the bisect function expects fname to be a function handle. If fname is a string, the parentheses intended to indicate passing arguments are actually indexes to the string array, and if the indexes are not integers or logicals, MALTAB throws that error.

The best thing to do is some upfront input checking before going to the routine. For example:

if ~isa(fname,'function_handle')
  if ischar(fname)
    fname = str2func(fname);
  else
    error('Input ''fname'' must be either a function handle or the name of a valid function.')
  end
end

If fname is a string that is also the name of a file in the current working directory or on the MATLAB path, str2func will convert it into a handle and all will be well. You can check if the string is a valid filename using exist(fname,'file')==2 if you wanted to be sure MATLAB can find the file.


feval

You can also use the feval function which excepts either a function handle or function name (a string) as the first argument and the inputs to the function as subsequent arguments:

vala = feval(fname,a);

I think this is a bit clunkier, but this is the process that the ode suite in the MATLAB uses, which is why the first argument to ode45 can either be a handle or a string.

Upvotes: 2

Related Questions