m-Files

m-Files are appropriately named as they refer to any file with suffix .m. They can be used to define scripts and functions.

Scripts

If you save a sequence of commands to a file name.m, then whenever you type:

>> name

is the same as if you had entered in all the lines of the file name.m at the command line.

This can be used to perform repetitive tasks, such as creating the matrix for a simple linear regression. For example, save the following to a file lr.m:

A = [x, ones(size(x))];
c = A \ y

Then, if in Matlab you type:

>> x = (1:10)';
>> y = [1.30 2.39 3.46 4.36 5.08 6.20 7.46 8.45 9.20 10.44]';
>> lr

c =

    1.0018
    0.3240

You can also use this to set up an environment. For example, if you are regularly using some constants, you could create a file mycons.m:

% MYCONS   Defines some variables

Na = 6.0221367e23;     % Avagadro's number
c = 299792458;         % speed of light
g = 9.80665;           % acceleration due to gravity
mph = .44704;          % 1 mph = 0.44704 m/s
kmph = 5/18.;          % 1 km/h = .27777777 m/s

Idea taken from Recktenwald.

Echoing Scripts

Normally, if you run a .m script, on the output not suppressed by semicolons is shown. If you want to see the input as well as the output, type:

>> echo on
>> name

In this case, the script is saved to the file name.m.

Functions

A function in Matlab takes 0 or more arguments and is called by its name with the arguments in parentheses. For example, sin(3.2).

There are two types of functions: built in and .m functions. Built in functions are programmed into Matlab in C, while .m functions are saved in files with the same name as the function. For example, if you wanted to write a function which evaluated the expression f(x) = x^2 - 4*x*sin(x) + 7*sin(x)^2, you would save the following to a file f.m:

function y = f(x)
% F   Some function.
%   F(X) evaluates the scalar X at X^2-4*X*sin(X)+7*sin(X)^2

y = x^2 - 4*x*sin(x) + 7*sin(x)^2;

Looking at the output, we note the following:

Note, the name of the function and the name of the file must match. If you save a function F to a file called f.m, Matlab will not find it when you type F(3.2).

As expected, a function can have more than one argument. What is interesting is that a function can also have more than one output variable. The following example has two output variables. Save this to a file g.m

function [a, b] = g(x)
% G   Some function G.
%     Evaluate sin(x) and cos(x)

a = sin(x);
b = cos(x);

Note: the comma in row vector is necessary in the definition.

At this point, you can type into matlab:

>> [st ct] = g(3.252)

st =

   -0.1102

ct =

   -0.9939

nargout

If you now type only g(3.252) or st = g(3.252), you only get the first argument assigned to. The other result (cos(3.252)) is discarded.

You may have noted this with the max function. If the output is assigned to two variables, the second variable is assigned the position where the maximum occured.

In this case, the function can determine how many output arguments it is being called with, and may assign the output accordingly. The variable is nargout. In the next example, we will rewrite g so that if it is called with two output variables, it assigns them appropriately, but if it is called with zero or one output variables, it returns a vector with the two answers:

function [a, b] = g(x)
% G   Some function G.
%     Evaluate sin(x) and cos(x)

if nargout == 2
  a = sin(x);
  b = cos(x);
else
  a = [sin(x), cos(x)];
end

Now, when you do:

>> g(3.242) 

ans =

   -0.1002   -0.9950

>> stct = g(3.242) 

stct =

   -0.1002   -0.9950

>> [st ct] = g(3.242)

st =

   -0.1002

ct =

   -0.9950

>> [a b c] = g(3.242)
??? Error using ==> g
Too many output arguments.

In the last example, we assigned the output to three variables, in which case, Matlab raised an error message.

You can see this with the size function. If the output is assigned to either zero or one variables, then a vector of the row and column dimensions is returned. If the output is assigned to two variables, those variables are assigned the row and column dimensions, respectively:

>> A = rand( 10, 20 );
>> size( A )

ans =

    10    20

>> a = size( A )

a =

    10    20

>> [m, n] = size( A )

m =

    10

n =

    20

You may have already seen this with the lu function, for example. If the output of lu(A) is assigned to either zero or one variables, then the sum L - eye(size(A)) + U is returned as one matrix. If the output is assigned to two arguments, then P^-1 * L, U are assigned to the two output variables, and finally, if the output is assigned to three variables, the variables are assigned the L, U, P matrices, respectively.

nargin

A function can also tell how many arguments it is being called with. For example, the diag function behaves differently if it is called with two arguments instead of with just one. You can check for the number of arguments a function is called with by the variable nargin. Save this file to a file called hilbert:

function H = hilbert( N, a )
% HILBERT     Hilbert matrix
%    HILBERT(N) creates the N by N matrix with elements 1/(i+j-1)
%    HILBERT(N, a) creates the N by N matrix with elements 1/(i+j+a)
%    The function HILBERT(N) is identical to HILBERT(N, -1)

H = zeros(N);

if nargin == 1
  aa = -1;
else
  aa = a;
end

% This is inefficient, but good for demonstration purposes

for i=1:N
  for j=1:N
    H(i,j) = 1/(i + j + aa);
  end
end

Use of Semicolons and Comments

Any line of a function which does not have its output suppressed with a semicolon is displayed when the function is run. This is a good way of debugging your code.

Use comments liberally through your code so that next week, when you read your own code, that you remember what you did. For example, the above hilbert code is much more efficiently implemented as:

H = zeros(N);
invs = zeros(1,2*N-1);

for i=1:2*N-1
  invs(i) = 1/(i + 1 + aa);
end

for i=1:N
  H(i,:) = invs(i:(i+N-1));
end

but in two weeks, you'd be hard pressed to remember that that is what this code did.

Out of interest's sake, the optimized version above takes approximately 1 second to create a 1000x1000 Hilbert matrix, whereas the original code (using two for loops) takes approximately 45 seconds.