Saturday, November 15, 2008

M - Files: II


More on Functions

In general, all functions have the form:

function [output1, output2, ...] = myFunctionName(input1, input2, ...)

where output1 refers to the first output, input1 refers to the first input etc.

Any comment lines immediately below the function definition till the first command in the body of the function appear when the help myFunctionName command is used. Try it with the function we created (help maxVal).

nargin & nargout

MATLAB is quite flexible when it comes to specifying inputs and outputs. The function nargin returns the number of input arguments (nargin = number of arguments in) supplied and nargout returns the number of outputs requested (nargout = number of arguments out). 

Inside the body of functions nargin and nargout return the number of input arguments that were used to call the function. As an illustration, say you write a function that iterates until a convergence criteria is met or a maximum number of iterations has been reached. One way to write such a function is to make the convergence criteria and the maximum number of iterations be optional arguments:

function x = SolveIt(a,tol,MaxIters)

if ( lt(nargin, 3) )
MaxIters = 100; 
end

if ( lt(nargin, 2) )
tol = sqrt(eps); 
end

...

NB: the reason I have had to use 'lt' (syntax for 'less than') instead of the symbol '<', is because of blogger. '<' when used within parentheses, seems to ignore any number after '<'. In practice there is no difference. You may use either.

The command 'nargout' works similarly. An example would be:

function [x_sort,x_mean,x_med,x_std] = myMarks(x) 

x_sort = sort(x); 
if nargout > 1, x_mean = mean(x); end 
if nargout > 2, x_med = median(x); end 
if nargout > 3, x_std = std(x); end 

Outside the body of the function (or in command window), the functions nargin and nargout work differently. nargin('fun') and nargout('fun') respectively return the number of declared inputs and outputs for the function 'fun'. For example, in the example discussed previously nargin('maxVal') returns 1 and nargout('maxVal') returns 3. 

varargin & varargout

To specify a variable (not fixed in advance) number of inputs to and outputs from a function argument one can use varargin (variable arguments in) and varargout (variable arguments out). To illustrate, here is an example taken from the Mathworks site:

function vartest(argA, argB, varargin)

optargin = size(varargin,2);
stdargin = nargin - optargin;
fprintf('Number of inputs = %d\n', nargin)
fprintf('Inputs from individual arguments(%d):\n', stdargin)

if stdargin >= 1
fprintf('%d\n', argA)
end

if stdargin == 2
fprintf('%d\n', argB)
end

fprintf('Inputs packaged in varargin(%d):\n', optargin)

for k = 1 : size(varargin, 2) 
fprintf('%d\n', varargin{k})
end

A few points about varargin (& varargout): 

The varargin (varargout) statement is used only inside a function M-file to contain optional input (output) arguments passed to the function. The varargin (varargout) argument must be declared as the last input (output) argument to a function, collecting all the inputs (outputs) from that point onwards. In the declaration, varargin (varargout) must be lowercase.

Here is an example on varargout, again taken from the Mathworks site:

function [s, varargout] = mysize(x)

nout = max(nargout, 1) - 1;
s = size(x);
for k = 1 : nout, varargout(k) = {s(k)}; end

returns the size vector and, optionally, individual sizes.  So

>> [s, rows, cols] = mysize(rand(4,5));

returns s = [4 5], rows = 4, cols = 5

And finally, though I may have mentioned it earlier, name of the M-file takes precedence over the name used in the function definition. That is, a user-defined function is called by the name of the M-file, and not the name given in the function definition. In general, it is always advisable to keep them the same. 

M - Files: I


Scripts and Functions

Although a lot can be done by writing instructions / steps on the command window in MATLAB, often one needs to experiment with a sequence of commands (for example, to see what change in one of the inputs does to a output - say, call option value on change of volatility or interest rate). Also, it would be very inefficient if every time one has to re-enter a particular sequence of commands in course of a project (an example could be comparing short term movements to a long term average by, say, estimating a rolling moving average). 

All of this, and more, can be achieved by what are called M-files. An M-file is just a text-editor (like a notepad) where one can record/type a set of commands and call from the command line. All M-files have a .m extension (just like a notepad has a .txt extension) and they are of two types:

Script M-files (or scripts): They have no input / output arguments and operate on variables on the existing workspace

Function M-files (or functions): They can accept input arguments and return output arguments. They are differentiated from the scripts in that a function contains an explicit function definition at the top of the M-file ( of the kind function [output] = myFunctionName(input) ). Also, internal variable declared within a function are local to the function (unless declared global). 

Both a script and a function enable one to store a sequence of commands / instructions that one may need frequently. Also, in general M-files are a more efficient and neat way of passing instructions as they help keep the command window uncluttered while one fiddles around with inputs and the sequence of commands. 

As an example, let's say we want a function that can find out the location of the maximum value in a matrix:

function [row, col, val] = maxVal(A)

% maxVal(x)
% Finds the location(s) and value of the maximum entry in a matrix
%
% [row, col, val] = maxVal(A)
%
% 'A' is the input matrix
% 'row' gives the row indices of the maxima (in case not unique)
% 'col' gives the column indices of the minima (in case not unique)
%  'val' gives the maximum value

val = max(max(A));
[row, col] = find(A == val);

In this function there are three output arguments and a single input argument. We'll discuss more on multiple inputs and output later. 

It's always advisable to include comment lines after the function definition. This not only makes sure you remember what you were trying to do when you wrote the function in the first place, it also allows for more effective sharing of codes across users.

To see if a function name or a variable already exists as an existing M-file or a MATLAB built-in function, use the command:

>> exist('functionName')

If the function or file doesn't exist, the above command would give an output 0, else a value between 1 - 8. See help exist for details.

One should also avoid using MATLAB keywords for a function name. To see the list of keywords, use the following command:

>> iskeyword

Scripts vs Functions

Scripts, simply stated are just a set of commands written in an M-file instead of the command window. Commands written in a script works on the variables existing in the workspace. Functions in that sense are different. For one, the same variable names as in the workspace can be used within a function without risking any modification of the existing variables in the workspace. Also, any variables created when the function is running are lost when the function completes. [HT: Kevin Sheppard]