Crash Course in MATLAB
Crash Course in MATLAB
net/publication/228731809
CITATIONS READS
2 11,275
1 author:
Tobin A Driscoll
University of Delaware
98 PUBLICATIONS 6,026 CITATIONS
SEE PROFILE
All content following this page was uploaded by Tobin A Driscoll on 31 May 2014.
1 Introduction
MATLAB is a software package for computation in engineering, science, and applied mathe-
matics. It offers a powerful programming language, excellent graphics, and a wide range of
expert knowledge. It is published by The MathWorks (www.mathworks.com).
The focus in MATLAB is on computation, not mathematics. Hence symbolic expressions
and manipulations are not possible (except through a clever interface to Maple). All results
are not only numerical but inexact, thanks to the rounding errors inherent in computer arith-
metic. The limitation to numerical computation can be seen as a drawback, but it is a source
of strength too: MATLAB generally runs circles around Maple, Mathematica, and the like
when it comes to numerics.
On the other hand, compared to other numerically oriented languages like C++ and FOR-
TRAN, MATLAB is much easier to use and comes with a huge standard library. The only
major unfavorable comparison here is a gap in execution speed. This gap can often be nar-
rowed or closed with good MATLAB programming(see section 5), but MATLAB is never going
to be the best tool for high-performance computing.
Thus the MATLAB niche is numerical computation on workstations for nonexperts in com-
putation. This is a huge niche—one way to tell is to look at the number of MATLAB-related
books on MathWorks’ web site. Even for hard-core supercomputer users, MATLAB can be
a valuable environment in which to explore and fine-tune algorithms before more laborious
coding in C.
1
In the default desktop you can also see the Launch Pad. The Launch Pad is a window into
the impressive breadth of MATLAB. Individual toolboxes add capability in specific methods
or specialties. Often these represent a great deal of expert knowledge. Most have friendly
demonstrations that hint at their capabilities, and it’s easy to waste a day on these. You
may notice that many toolboxes are related to electrical engineering, which is a large share of
MATLAB’s clientele.
Notice at the top of the desktop that MATLAB has a notion of current directory, just
like UNIX does. In general MATLAB can only “see” files in the current directory and on its
own path. Commands for working with the directory and path include cd, what, addpath,
and pathedit (in addition to widgets and menu items). We will return to this subject in
section 3.
You can also see a tab for the Workspace next to the Launch Pad. The Workspace shows
you what variables are currently defined and some information about their contents. At
startup it is, naturally, empty.
In this document I will often give the names of commands that can be used at the prompt.
In many (maybe most) cases these have equivalents among the menus, buttons, and other
graphical widgets. Take some time to explore these widgets. This is one way to become
familiar with the possibilities in MATLAB.
1.2 Help
MATLAB is a huge package. You can’t learn everything about it at once, or always remember
how you have done things before. It is essential that you learn how to teach yourself more
using the online help.
There are two levels of help:
• If you need quick help on the syntax of a command, use help. For example, help plot
tells you all the ways in which you can use the plot command. (Of course, you have to
know already the name of the command you want.)
• Use helpdesk or the menu/graphical equivalent to get into the Help Browser. This in-
cludes HTML and printable forms of all MATLAB manuals and guides, including toolbox
manuals. The MATLAB: Getting Started and the MATLAB: Using MATLAB manuals
are excellent places to start. The MATLAB Function Reference will always be useful.
If you type in a valid expression and press Enter, MATLAB will immediately execute it and
return the result.
>> 2+2
ans =
4
>> 4ˆ2
2
ans =
16
>> sin(pi/2)
ans =
1
>> 1/0
Warning: Divide by zero.
ans =
Inf
>> exp(i*pi)
ans =
-1.0000 + 0.0000i
√
Notice some of the special expressions here: pi for π, Inf for ∞, and i for −1. Another is
NaN, which stands for not a number. NaN is used to express a lack of a value. For example,
>> Inf/Inf
ans =
NaN
>> x = sqrt(3)
x =
1.7321
>> 3*z
??? Undefined function or variable ’z’.
Observe that variables must have values before they can be used. When an expression returns
a single result that is not assigned to a variable, this result is assigned to ans, which can then
be used like any other variable.
>> atan(x)
ans =
1.0472
>> pi/ans
ans =
3
3
In floating-point arithmetic, you should not expect “equal” values to have a difference of
exactly zero. The built-in number eps tells you the error in arithmetic on your particular
machine. For simple operations, the relative error should be less than this number. For
instance,
>> exp(log(10)) - 10
ans =
1.7764e-15
>> ans/10
ans =
1.7764e-16
>> eps
ans =
2.2204e-16
t =
21
Once variables have been defined, they exist in the workspace. You can see what’s in the
workspace from the desktop or by using
>> who
ans s t x
4
1.5 Exercises
1. Evaluate the following mathematical expressions in MATLAB.
2. What is the name of the built-in function that MATLAB uses to:
5
2 Arrays and matrices
The heart and soul of MATLAB is linear algebra. In fact, “MATLAB” was originally a con-
traction of “matrix laboratory.” More so than any other language, MATLAB encourages and
expects you to make heavy use of arrays, vectors, and matrices.
Some language: An array is a collection of numbers, called elements or entries, refer-
enced by one or more indices running over different index sets. In MATLAB, the index sets
are always sequential integers starting with 1. The dimension of the array is the number of
indices needed to specify an element. The size of an array is a list of the sizes of the index
sets.
A matrix is a two-dimensional array with special rules for addition, multiplication, and
other operations. It represents a mathematical linear transformation. The two dimensions
are called the rows and the columns. A vector is a matrix for which one dimension has only
the index 1. A row vector has only one row and a column vector has only one column.
Although an array is much more general and less mathematical than a matrix, the terms
are often used interchangeably. What’s more, in MATLAB there is really no formal distinction—
not even between a scalar and a 1 × 1 matrix, although these technically behave differently.
The commands below are sorted according to the array/matrix distinction, but MATLAB will
let you mix them freely. The idea (here as elsewhere) is that MATLAB keeps the language
simple and natural. It’s up to you to stay out of trouble.
The simplest way to construct a small array is by enclosing its elements in square brackets.
>> A = [1 2 3; 4 5 6; 7 8 9]
A =
1 2 3
4 5 6
7 8 9
>> b = [0;1;0]
b =
0
1
0
Separate columns by spaces or commas, and rows by semicolons or new lines. Information
about size and dimension is stored with the array.1
>> size(A)
ans =
3 3
1
Because of this, array sizes are not usually passed explicitly to functions as they are in FORTRAN.
6
>> ndims(A)
ans =
2
>> size(b)
ans =
3 1
>> ndims(b)
ans =
2
Notice that there is really no such thing as a one-dimensional array in MATLAB. Even vectors
are technically two-dimensional, with a trivial dimension. Table 1 lists more commands for
obtaining information about an array.
Arrays can be built out of other arrays, as long as the sizes are compatible.
>> [A b]
ans =
1 2 3 0
4 5 6 1
7 8 9 0
>> [A;b]
??? Error using ==> vertcat
All rows in the bracketed expression must have the same
number of columns.
B =
1 2 5
3 4 6
7
An alternative to the bracket notation is the cat function. This is usually needed to
construct arrays of more than two dimensions.
>> cat(3,A,A)
ans(:,:,1) =
1 2 3
4 5 6
7 8 9
ans(:,:,2) =
1 2 3
4 5 6
7 8 9
Bracket constructions are suitable only for very small matrices. For larger ones, there are
many useful functions, some of which are shown in Table 2.
>> 1:8
ans =
1 2 3 4 5 6 7 8
>> 0:2:10
ans =
0 2 4 6 8 10
>> 1:-.5:-1
8
ans =
1.0000 0.5000 0 -0.5000 -1.0000
The format is first:step:last. The result is always a row vector, or the empty matrix if
last < first.
It is frequently necessary to access one or more of the elements of a matrix. Each dimension
is given a single index or vector of indices. The result is a block extracted from the matrix.
Some examples using the definitions above:
>> A(2,3)
ans =
6
ans =
1
ans =
0
0
ans =
2 3
5 6
ans =
2 5
ans =
5
6
ans =
0 0 0 0
1 1 1 1
9
0 0 0 0
The colon is often a useful way to construct these indices. There are some special syntaxes:
end means the largest index in a dimension, and : is short for 1:end—i.e. everything in that
dimension. Note too from the last example that the result need not be a subset of the original
array.
Vectors can be given a single subscript. In fact, any array can be accessed via a single
subscript. Multidimensional arrays are actually stored linearly in memory, varying over the
first dimension, then the second, and so on. (Think of the columns of a matrix being stacked
on top of each other.) In this sense the array is equivalent to a vector, and a single subscript
will be interpreted in this context. (See sub2ind and ind2sub for more details.)
>> A
A =
1 2 3
4 5 6
7 8 9
>> A(2)
ans =
4
>> A(7)
ans =
3
ans =
1 4 7 2
>> A([1;2;3;4])
ans =
1
4
7
2
>> A(:)
ans =
1
4
7
2
5
10
8
3
6
9
The output of this type of index is in the same shape as the index. The potentially ambiguous
A(:) is always a column vector.
Subscript referencing can be used on either side of assignments.
B =
1 2 3
3 4 6
>> C = rand(2,5)
C =
0.8125 0.4054 0.4909 0.5909 0.5943
0.2176 0.5699 0.1294 0.8985 0.3020
C =
0.8125 0.4054 0.4909 0.5943
0.2176 0.5699 0.1294 0.3020
C =
0.8125 0.4054 0.4909 0.5943
0 0 0 0
C =
0.8125 0.4054 0.4909 0.5943
0 0 0 0
3.0000 0 0 0
An array is resized automatically if you delete elements or make assignments outside the
current size. (Any new undefined elements are made zero.) This can be highly convenient,
but it can also cause hard-to-find mistakes.
A different kind of indexing is logical indexing. Logical indices usually arise from a
relational operator (see Table 3). The result of applying a relational operator is a logical
array, whose elements are 0 and 1 with interpretation as “false” and “true.” Using a logical
array as an index returns those values where the index is 1 (in the single-index sense above).
>> B>3
11
ans =
0 0 0
0 1 1
>> B(ans)
ans =
4
6
>> b(b==0)
ans =
0
0
ans =
0
0
0
ans =
0
1
0
The arithmetic operators +,-,*,ˆ are interpreted in a matrix sense. When appropriate, scalars
are “expanded” to match a matrix.2
>> A+A
ans =
2 4 6
8 10 12
2
This gives scalar addition more of an array rather than a matrix interpretation.
12
14 16 18
>> ans-1
ans =
1 3 5
7 9 11
13 15 17
>> 3*B
ans =
3 6 9
9 12 18
>> A*b
ans =
2
5
8
>> B*A
ans =
30 36 42
61 74 87
>> A*B
??? Error using ==> *
Inner matrix dimensions must agree.
>> Aˆ2
ans =
30 36 42
66 81 96
102 126 150
>> A*B’-(B*A’)’
ans =
0 0
0 0
0 0
>> b’*b
ans =
13
1
>> b*b’
ans =
0 0 0
0 1 0
0 0 0
x =
-0.1364
0.3182
0.8182
>> C*x - b
ans =
1.0e-16 *
0.5551
0
0
Several functions from linear algebra are listed in Table 4; there are many others.
Array operations simply act identically on each element of an array. We have already seen
some array operations, namely + and -. But *,’,ˆ,and / have particular matrix interpreta-
tions. To get a elementwise behavior, precede the operator with a dot.
14
>> A
A =
1 2 3
4 5 6
7 8 9
>> C
C =
1 3 -1
2 4 0
6 0 1
>> A.*C
ans =
1 6 -3
8 20 0
42 0 9
>> A*C
ans =
23 11 2
50 32 2
77 53 2
>> A./A
ans =
1 1 1
1 1 1
1 1 1
>> (B+i)’
ans =
-1.0000 - 1.0000i 3.0000 - 1.0000i
-2.0000 - 1.0000i 4.0000 - 1.0000i
-3.0000 - 1.0000i 6.0000 - 1.0000i
>> (B+i).’
ans =
-1.0000 + 1.0000i 3.0000 + 1.0000i
-2.0000 + 1.0000i 4.0000 + 1.0000i
-3.0000 + 1.0000i 6.0000 + 1.0000i
There is no difference between ’ and .’ for real arrays. Most elementary functions, such as
sin, exp, etc., act elementwise.
>> B
15
B =
1 2 3
3 4 6
>> cos(pi*B)
ans =
-1 1 -1
-1 1 1
>> exp(A)
ans =
1.0e+03 *
0.0027 0.0074 0.0201
0.0546 0.1484 0.4034
1.0966 2.9810 8.1031
>> expm(A)
ans =
1.0e+06 *
1.1189 1.3748 1.6307
2.5339 3.1134 3.6929
3.9489 4.8520 5.7552
It’s easy to forget that exp(A) is an array function. Use expm(A) to get the matrix exponen-
tial I + A + A2 /2 + A3 /6 + · · · .
Elementwise operators are often useful in functional expressions. Consider evaluating a
Taylor approximation to sin(t):
>> t = (0:0.25:1)*pi/2
t =
0 0.3927 0.7854 1.1781 1.5708
ans =
0 0.3827 0.7071 0.9245 1.0045
This is easier and better than writing a loop for the calculation. (See section 5.3.)
Another kind of array operation works in parallel along one dimension of the array, re-
turning a result that is one dimension smaller.
>> C
C =
1 3 -1
2 4 0
6 0 1
16
>> sum(C,1)
ans =
9 7 0
>> sum(C,2)
ans =
3
6
7
2.5 Exercises
1. (a) Check the help for diag and use it (maybe more than once) to build the 16 × 16
matrix
−2 1 0 0 ··· 0 1
1 −2
1 0 ··· 0 0
0 1 −2 1 0 ··· 0
..
D=
.. .. .. ..
. . . . .
0 ··· 0 1 −2 1 0
0 0 ··· 0 1 −2 1
1 0 0 ··· 0 1 −2
(b) Now read about toeplitz and use it to build D. (Use the full MATLAB reference
from helpdesk, which has more to say than just help toeplitz.)
(c) Use toeplitz and whatever else you need to build
1 12 13 14
1 2 3 4 4 3 2 1
0 1 2 3 1 1 1 1 3 2 1 2
2 2 3
0 0 1 2 1 1 1 1 2 1 2 3
3 2 2
0 0 0 1 1 1 1 1 2 3 4
4 3 2 1
Do not just enter the elements directly—your solutions should be just as easy to use
if the matrices were 100 × 100.
2. Let A be a random 8 × 8 matrix. Find the maximum values (a) in each column, (b) in
each row, and (c) overall. Also (d) find the row and column indices of all elements that
are larger than 0.25.
17
3. A magic square is an n×n matrix in which each integer 1, 2, . . . , n2 appears once and for
which all the row, column, and diagonal sums are identical. MATLAB has a command
magic that returns magic squares. Check its output at a few sizes and use MATLAB to
verify the summation property. (The “antidiagonal” sum will be the trickiest.)
4. Suppose we represent a standard deck of playing cards by a vector v containing one copy
of each integer from 1 to 52. Show how to “shuffle” v by rearranging its contents in a
random order. (Note: There is one very easy answer to this problem.)
where DN is N × N, for several growing values of N; for example, N = 4, 8, 16, 32. (This is
one approximate representation of the second-derivative operator for periodic functions.
The smallest eigenvalues are integer multiples of a simple number.)
X
K
kAk2F = σ2i ,
i=1
where K = min{m, n}, {σ1 , . . . , σK } are the singular values of A, and k · kF is the Frobenius
norm (root-mean-square of the elements of A).
18
3 Scripts and functions
An M-file is a regular text file containing MATLAB commands, saved with the filename ex-
tension .m. There are two types, scripts and functions. MATLAB comes with a pretty good
editor that is tightly integrated into the environment. Start it using open or edit. However,
you are free to use any text editor.
An M-file should be saved in the path in order to be executed. The path is just a list of
directories (folders) in which MATLAB will look for files. Use editpath or menus to see and
change the path.
There is no need to compile either type of M-file. Simply type in the name of the file (without
the extension) in order to run it. Changes that are saved to disk will be included in the next
call to the function or script. (You can alter this behavior with mlock.)
At the UNIX prompt in the directory of run.m, you would enter (using csh style)
nice +19 matlab < run.m >! run.log &
which would cause your script to run in the background with low priority. The job will con-
tinue to run until finished, even if you log off. The output that would have been typed to the
screen is redirected to run.log. You will usually need at least one save command to save
your results. (Use it often in the script in case of a crash or other interruption.)
3.2 Functions
Functions are the main way to extend the capabilities of MATLAB. Each function must start
with a line such as
function [out1,out2] = myfun(in1,in2,in3)
The variables in1, etc. are input arguments, and out1 etc. are output arguments. You
can have as many as you like of each type (including zero) and call them whatever you want.
The name myfun should match the name of the disk file.
Here is a function that implements (badly, it turns out) the quadratic formula.
19
function [x1,x2] = quadform(a,b,c)
d = sqrt(bˆ2 - 4*a*c);
x1 = (-b + d) / (2*a);
x2 = (-b - d) / (2*a);
r1 =
1
r2 =
1
One of the most important features of a function is its local workspace. Any arguments
or other variables created while the function executes are available only to the executing
function statements. Conversely, variables in the command-line workspace (called the base
workspace) are normally not visible to the function. If during the function execution, more
functions are called, each of those calls also sets up a private workspace. These restrictions
are called scoping, and they make it possible to write complex programs without worrying
about name clashes. The values of the input arguments are copies of the original data, so any
changes you make to them will not change anything outside the function’s scope.3 In general,
the only communication between a function and its caller is through the input and output
arguments.
A single M-file may hold more than one function definition. A new function header line in a
file ends the primary function and starts a new subfunction. As a silly example, consider
function [x1,x2] = quadform(a,b,c)
d = discrim(a,b,c);
x1 = (-b + d) / (2*a);
x2 = (-b - d) / (2*a);
function D = discrim(a,b,c)
D = sqrt(bˆ2 - 4*a*c);
A subfunction has its own workspace; thus, changes made to a inside discrim would not
propagate into the rest of quadform. In addition, the subfunctions themselves have a limited
scope. In the example the subfunction discrim is available only to the primary function
quadform, not to the command line.4
Another important aspect of function M-files is that most of the functions built into MAT-
LAB (except core math functions) are themselves M-files that you can read and copy. This is
an excellent way to learn good programming practice (and dirty tricks).
3
MATLAB does avoid copying (i.e., “passes by reference”) if the function never alters the data.
4
In other words, MATLAB uses only directory listings to see what functions are available at the prompt. How-
ever, see section 3.5.)
20
3.3 Debugging and profiling
Here are Toby’s Fundamental Laws of Computer Programming:
To debug a program that doesn’t work, you can set breakpoints in one or more functions.
(See the Breakpoints menu in the Editor.) When MATLAB reaches a breakpoint, it halts and
lets you inspect and modify all the variables currently in scope. You can continue execution
normally or step by step in order to see just what is happening. It’s also possible to set non-
specific breakpoints for error and warning conditions. See help debug for all the details.
Sometimes a program spends most of its running time on just a few lines of code. These
lines are then obvious candidates for optimization. You can find such lines by profiling,
which keeps track of time spent on every line of every function. Profiling is also a great
way to determine function dependencies (who calls whom). Turn it on by entering profile
on. After running functions of interest, type profile report to get a report in your web
browser. When you don’t need profiling any more, enter profile off to avoid slowing down
execution speed.
You can also define functions of more than one variable, and name the variables explicitly:
>> w = inline(’cos(x - c*t)’,’x’,’t’,’c’)
w =
Inline function: w(x,t,c) = cos(x - c*t)
>> w(pi,1,pi/2)
ans =
6.1232e-17
21
>> fzero(’sin’,3)
ans =
3.1416
>> fzero(’exp(x)-3*x’,1)
ans =
0.6191
If you need to find the root of a more complicated function, or a function with a parameter,
then you can write it in an M-file and pass the name of that function. Say we have
function f = demo(x,a)
exp(x) - a*x;
ans =
0.6191
>> fzero(@demo,1,[],4)
ans =
0.3574
Here we used the empty matrix [] as a placeholder so that fzero knows that the last ar-
gument is a parameter. (The online help tells you that the third argument is reserved for
another use.) Note the new syntax: @demo is called a function handle and it gives fzero
a way to accept your function as an input argument.5 See help funfun to get a list of all of
MATLAB’s function functions for optimization, integration, and differential equations.
Function handles are also a way to get subfunctions passed outside of their parents. Con-
sider this example.
function answer = myfun(data)
% ...blah, blah...
r = fzero(@solveit,x0);
% ...blah, blah...
function f = solveit(x)
f = exp(1+cos(x)) - 1.5;
Ordinarily fzero could not be aware of the subfunction solveit, but when the primary
myfun creates a handle to it, then it can be used anywhere. This allows you to keep related
functions in just one file.
You will probably have to write function functions of your own. Say you want to use the
bisection method of root finding. Here is a (crude) version.
5
You could also use ’demo’, but handles are the preferred way.
22
function x = bisect(f,a,b)
fa = feval(f,a);
fb = feval(f,b);
while (b-a) > 1e-8
m = (a+b)/2;
fm = feval(f,m);
if fa*fm < 0
b = m; fb = fm;
else
a = m; fa = fm;
end
end
x = (a+b)/2;
(The full descriptions of while and if are in section 4.) Note how feval is used to evaluate
the generic function f. The syntax f(a) would produce an error in most cases. Now we can
call
>> bisect(@sin,3,4)
ans =
3.1416
To see how to use optional extra parameters in bisect as we did with fzero, see section 6.2.
3.6 Exercises
1. Write a function quadform2 that implements the quadratic formula differently from
quadform above (page 19). Once d is computed, use it to find
−b − sign(b)d
x1 = ,
2a
which is the root of largest magnitude, and then use the identity x1 x2 = c/a to find x2 .
Use both quadform and quadform2 to find the roots of x2 − (107 + 10−7 )x + 1. Do you
see why quadform2 is better?
23
4 Loops and conditionals
To write programs of any complexity you need to be able to use iteration and decision making.
These elements are available in MATLAB much like they are in any other major language.
For decisions, there are if and switch, and for iteration there are for and while.
The conditions for if statements may involve the relational operators of Table 3, or func-
tions such as isinf that return logical values. Numerical values can also be used, with
nonzero meaning true, but if x˜=0 is better practice than if x.
Individual conditions can be combined using
The switch expression can be a string or a number. The first matching case has its commands
executed.6 If otherwise is present, it gives a default option if no case matches.
6
Execution does not “fall through” as in C.
24
4.2 for and while
This illustrates the most common type of for loop:
>> f = [1 1];
>> for n = 3:10
f(n) = f(n-1) + f(n-2);
end
You can have as many statements as you like in the body of the loop. The value of the index n
will change from 3 to 10, with an execution of the body after each assignment. But remember
that 3:10 is really just a row vector. In fact, you can use any row vector in a for loop, not
just one created by a colon. For example,
>> x = 1:100; s = 0;
>> for j = find(isprime(x))
s = s + x(j);
end
This finds the sum of all primes less than 100. (For a better version, though, see page 29.)
A warning: If you are using complex numbers, you might want to √ avoid using i as the
loop index. Once assigned a value by the loop, i will no longer equal −1. However, you can
always use 1i for the imaginary unit.
As we saw in the bisection program on page 22, it is sometimes necessary to repeat state-
ments based on a condition rather than a fixed number of times. This is done with while.
while x > 1
x = x/2;
end
The condition is evaluated before the body is executed, so it is possible to get zero iterations.
It’s often a good idea to limit the number of repetitions, to avoid infinite loops (as could happen
above if x==Inf). This can be done using break.
n = 0;
while x > 1
x = x/2;
n = n+1;
if n > 50, break, end
end
A break immediately jumps execution to the first statement after the loop.
4.3 Exercises
1. Write a function newton(f,df,x0,tol) that implements Newton’s iteration for rootfind-
ing:
f(xn )
xn+1 = xn − 0
f (xn )
The first two inputs are handles to f and f 0 , and the third input is an initial root estimate.
Continue the iteration until either |f(xn+1 )| or |xn+1 − xn | is less than tol. You might
want a “safety valve” as well.
25
2. Write a function I=trap(f,a,b,n) that implements the trapezoidal quadrature rule:
Zb
h
f(x) dx ≈ f(x0 ) + 2f(x1 ) + 2f(x2 ) + · · · + 2f(xn−1 ) + f(xn ) ,
a 2
where h = (b − a)/n and xi = a + ih. Test your function on sin(x) + cos(x) for 0 ≤ x ≤ π/3.
For a greater challenge, write a function simp for Simpson’s rule,
Zb
h
f(x) dx ≈ f(x0 ) + 4f(x1 ) + 2f(x2 ) + 4f(x3 ) + 2f(x4 ) + · · · + 4f(xn−1 ) + f(xn ) .
a 3
(This formula requires n to be even. You may assume that the input conforms, or try to
check it.)
3. One way to compute the exponential function ex is to use its Taylor series expansion
around x = 0. Unfortunately, many terms are required if |x| is large. But a special
property of the exponential is that e2x = (ex )2 . This leads to a scaling and squaring
method: Divide x by 2 repeatedly until |x| < 1, use a Taylor series (16 terms should be
more than enough), and square the result repeatedly. Write a function expss(x) that
does this. (The functions cumprod and polyval can help with evaluating the Taylor
expansion.) Test your function on x values −30, −3, 3, 30.
4. Let x and y be column vectors of the vertices of a polygon (given in order). Write func-
tions polyperim(x,y) and polyarea(x,y) that compute the perimeter and area of
the polygon. For the area, use a formula based on Green’s theorem:
1 X
n
A= xk yk+1 − xk+1 yk .
2
k=1
Here n is the number of vertices and it’s understood that xn+1 = x1 and yn+1 = y1 .
5. If a data source produces symbol k with probability pk , the first-order entropy of the
source is defined as X
H1 = − pk log2 pk .
k
Essentially H1 is the number of bits needed per symbol to encode a long message;
i.e., it measures the amount of information content (and therefore the potential suc-
cess of compression strategies). The value H1 = 0 corresponds to one symbol only—no
information—while for M symbols of equal probability, H1 = log2 M.
Write a function [H,M] = entropy(v) that computes entropy for a vector v. The prob-
abilities should be computed empirically, by counting occurrences of each unique sym-
bol and dividing by the length of v. (The built-in functions find and unique may be
helpful.) Try your function on some carefully selected examples with different levels of
information content. You can find lots of data sources from help gallery and (if you
have the Image Processing Toolbox) help imdemos. Remember that matrices can be
converted to vectors. You might also want to stick with integer data by using round
appropriately.
26
5 Optimizing performance
One often hears the complaint that “MATLAB is too slow.” While it’s true that even the best
MATLAB code may not keep up with good C code, the gap is not necessarily wide. In fact, on
core linear algebra routines such as matrix multiplication and linear system solution, there
is very little difference in performance. Where MATLAB runs into trouble is on things that
it tries to spare you from doing: compiling, variable declaration, memory allocation, and the
like. By writing good MATLAB programs, you can often nearly recover the speed of compiled
code.7
It’s good to start by profiling your code (section 3.3) to find out where the bottlenecks are.
This takes about 7.3 seconds on a certain computer. Almost all of this time, though, is spent
on a noncomputational task.
When MATLAB encounters the statement y = ones(100,1), it asks the operating sys-
tem for a block of memory to hold 100 numbers. On the first execution of the loop, it becomes
clear that we actually need space to hold 200 numbers, so a new block of this size is requested.
On the next iteration, this also becomes obsolete, and more memory is allocated. The little
program above requires 1001 memory allocations of increasing size, and this task occupies
most of the execution time. Also, the obsoleted space is wasted on the machine, because MAT-
LAB generally can’t give it back to the operating system.
Changing the second line to y = ones(100,1001) changes none of the mathematics but
does all the required memory allocation at once. This is called preallocation. With preallo-
cation the program takes about 0.4 seconds on the same computer as before.
7
In a pinch, you can write a time-consuming function alone in C and link the compiled code into MATLAB. See
the online help under “Application program interface.”
27
5.3 Vectorize
The problem with for and while loops in MATLAB is that they execute slowly. You are
strongly encouraged to write code with as few loops as possible!
The simplest type of vectorization is to use elementwise operators (section 2.4) appropri-
ately. These often occur when you evaluate mathematical expressions for all elements of a
vector, such as t.*sin(t.ˆ2) for t sin(t2 ). You should get used to using these operators in
this way. Similarly, the “parallel” functions like sum and diff in Table 5 can replace many
tasks that might be done in loops.
In some cases vectorization involves trading memory for speed. Suppose x and y are col-
umn vectors and you want to compute an array of pairwise differences, A(i,j)=x(i)-y(j).
The two-loop version is obvious, and a one-loop version is not hard. But it can also be done
with no loops using repmat:
A = repmat(x,[1 length(y)]) - repmat(y.’,[length(x) 1]);
The purpose of repmat is to copy a given scalar, vector, or matrix multiple times through
an additional dimension. By copying x and y along different dimensions, the differencing
becomes trivial. If the vectors are large, this will execute much faster than a loop-based
version. Note, however, that storage is needed for three matrices the size of A (this could
be reduced to two). In many situations time is more precious than storage, but you can get
burned if the vectors get too large.
The most subtle but mathematically relevant type of vectorization is based on understand-
ing linear algebra. Consider a simple version of Gaussian elimination:
n = length(A);
for k = 1:n-1
for i = k+1:n
s = A(i,k)/A(k,k);
for j = k:n
A(i,j) = A(i,j) - s*A(k,j);
end
end
end
This does its job and is the natural sort of implementation for those used to C or FORTRAN.
But look now at the innermost loop on j. Each iteration of the loop is independent of all the
others (there is no reference like j-1 in the body). This parallelism is a big hint that we could
do without the loop:
n = length(A);
for k = 1:n-1
for i = k+1:n
s = A(i,k)/A(k,k);
cols = k:n;
A(i,cols) = A(i,cols) - s*A(k,cols);
end
end
This version is also more faithful to the idea of a row operation, since it recognizes vector
arithmetic.
28
Now if you look carefully again at the innermost remaining loop, you can see that it too is
in parallel. So this loop can also be removed:
n = length(A);
for k = 1:n-1
rows = k+1:n;
cols = k:n;
s = A(rows,k)/A(k,k);
A(rows,cols) = A(rows,cols) - s*A(k,cols);
end
Although the change is superficially minor, it takes some thought to see that the product
in the next-to-last line is sensible and correct (in fact it’s a vector outer product). On one
workstation, the first (3-loop) version takes 167 seconds to execute on a 300 × 300 matrix. The
last version takes 1.4 seconds.
The mask is a logical index into x (see page 11). You could refer, if needed, to the unmasked
points by using ˜mask.
Consider also the MATLAB-aware version of the sum-of-primes idea from page 25:
sum( find( isprime(1:100) ) )
Here find converts a logical index into an absolute one. The only disadvantage of doing so in
general is that referring to the unmasked elements becomes more difficult.
5.5 Exercises
1. Rewrite trap or simp (page 26) so that it does not use any loops. (Hint: Set up a vector
of all x values and evaluate f there. Then set up a vector of quadrature weights and use
an inner product.)
29
2. Rewrite the functions polyperim and polyarea (page 26) without loops. (Hint: In both
functions it will be easiest to redefine x and y to make the “wraparound” explicit. Use
diff and maybe complex numbers in polyperim.)
3. Consider again “shuffling” a vector of integers from 1 to 52, this time with a physical in-
terpretation of a shuffle. Divide the cards into two stacks, and merge the stacks together
from the bottom up. Then, each time a pair of cards is to fall off the bottom of each stack,
a random decision is made as to which falls first. This can be implemented without loops
in as little as four lines. (It can be interesting to start with a perfectly ordered deck and
see how many shuffles it takes to “randomize” it. One very crude measure of randomness
is corrcoef(1:52,v).)
4. Rewrite the function entropy on page 26 without any loops using sort, diff, find,
and (perhaps) sum.
5. In the function newton (page 25), suppose that input x0 is actually a vector of initial
guesses, and you want to run Newton’s method on each. Keep track of an error vector
and use masking to rewrite newton so that it still uses only one loop.
30
6 Advanced data structures
Not long ago, MATLAB viewed every variable as a matrix. While this point of view is ideal
for simplicity, it is too limited for large and complex programs. A few additional data types
are useful not only for programming, but occasionally even for ordinary use.
6.1 Strings
As we have seen, a string in MATLAB is enclosed in single forward quotes. In fact a string is
really just a row vector of character codes. Because of this, strings can be concatenated using
matrix concatenation.
>> str = ’Hello world’;
>> str(1:5)
ans =
Hello
>> double(str)
ans =
72 101 108 108 111 32 119 111 114 108 100
>> char(ans)
ans =
Hello world
ans =
Hello world
You can convert a string such as ’3.14’ into its numerical meaning (not its character codes) by
using eval or str2num on it. Conversely, you can convert a number to string representation
using num2str or the much more powerful sprintf (see below). If you want a quote character
within a string, use two quotes, as in ’It’’s Cleve’’s fault’.
Multiple strings can be stored as rows in an array. However, arrays have to have to be
rectangular (have the same number of columns in each row), so strings may have to be padded
with extra blanks at the end. The function str2mat does this.
>> str2mat(’Goodbye’,’cruel’,’world’)
ans =
Goodbye cruel world
>> size(ans)
ans = 3 8
There are lots of string handling functions. See help strfun. Here are a few:
31
>> upper(str)
ans =
HELLO WORLD
ans =
>> findstr(’world’,str)
ans =
Formatted output
For the best control over conversion of numbers to strings, use sprintf or (for direct output)
fprintf. These are closely based on the C function printf, with the important enhancement
that format specifiers are “recycled” through all the elements of a vector or matrix (in the
usual row-first order).
For example, here’s a script that prints out successive Taylor approximations for e1/4 .
x=0.25; n=1:8; c=1./cumprod([1 n]);
for k=1:9, T(k)=polyval(c(k:-1:1),x); end
fprintf(’\n T_n(x) |T_n(x)-exp(x)|\n’);
fprintf(’----------------------------------\n’);
fprintf(’%15.12f %8.3e\n’, [T;abs(T-exp(x))] )
T_n(x) |T_n(x)-exp(x)|
----------------------------------
1.000000000000 2.840e-01
1.250000000000 3.403e-02
1.281250000000 2.775e-03
1.283854166667 1.713e-04
1.284016927083 8.490e-06
1.284025065104 3.516e-07
1.284025404188 1.250e-08
1.284025416299 3.892e-10
1.284025416677 1.078e-11
32
Chebyshev coefficients into a triangular array, this is an inconvenient complication.
Cell arrays are used to gather (potentially) dissimilar objects into one variable. They are
indexed like regular numeric arrays, but their elements can be absolutely anything. A cell
array is created or referenced using curly braces {} rather than parentheses.
>> str = { ’Goodbye’, ’cruel’, ’world’ }
str =
>> str{2}
ans =
cruel
>> T = cell(1,9);
>> T(1:2) = { [1], [1 0] };
>> for n = 2:8, T{n+1} = [2*T{n} 0] - [0 0 T{n-1}]; end
>> T
T =
Columns 1 through 5
Columns 6 through 9
>> T{4}
ans =
4 0 -3 0
Cell arrays can have any size and dimension, and their elements do not need to be of the
same size or type. Cell arrays may even be nested. Because of their generality, cell arrays are
mostly just containers; they do not support any sort of arithmetic.
One special cell syntax is quite useful. The idiom C{:} for cell array C is interpreted as a
comma-separated list of the elements of C, just as if they had been typed. For example,
>> str2mat(str{:}) % same as str2mat(’Goodbye’,’cruel’,’world’)
ans =
Goodbye
cruel
33
world
The special cell array varargin is used to pass optional arguments into functions. For
example, consider these modifications to the bisection algorithm on page 22:
function x = bisect(f,a,b,varargin)
fa = feval(f,a,varargin{:});
fb = feval(f,b,varargin{:});
...
If arguments beyond the first three are passed in to bisect, they are passed along to f.
Naturally, in other contexts you are free to look at the elements of varargin and interpret
them yourself. There is also a varargout for optional outputs.
6.3 Structures
Structures are much like cell arrays, but they are indexed by names rather than by numbers.
Say you are keeping track of the grades of students in a class. You might start by creating
a student struct (structure) as follows:
>> student.name = ’Clinton, Bill’;
>> student.SSN = 123456789;
>> student.homework = [10 10 7 9 10];
>> student.exam = [98 94];
>> student
student =
The name of the structure is student. Data is stored in the structure according to named
fields, which are accessed using the dot notation above. The field values can be anything.
Probably you have more students.
>> student(2).name = ’Bush, G. W.’;
>> student(2).SSN = 987654321;
>> student(2).homework = [4 6 7 3 0];
>> student(2).exam = [53 66];
>> student
student =
1x2 struct array with fields:
name
SSN
homework
exam
34
Now you have an array of structures. As always, this array can be any size and dimension.
However, all elements of the array must have the same fields.
Struct arrays make it easy to extract data into cells:
>> [roster{1:2}] = deal(student.name)
roster =
35
7 Graphics
Graphical display is one of MATLAB’s greatest strengths—and most complicated subjects.
The basics are quite simple, but you also get complete control over practically every aspect of
each graph, and with that power comes complexity.
Graphical objects are classified by type. The available types lie in a strict hierarchy, as
shown in Figure 1. Each figure has its own window. Inside a figure is one or more axes (ignore
the other types on this level until section 8). You can make an existing figure or axes “current”
by clicking on it.
Inside the axes are drawn data-bearing objects like lines and surfaces. While there are
functions called line and surface, you will very rarely use those. Instead you use friendlier
functions that create these object types.
A new line object is drawn in the current axes of the current figure (these are created if
necessary). The line may appear to be a smooth, continuous curve. However, it’s really just a
game of “connect the dots,” as you can see by entering
>> plot(t,sin(t),’o-’)
Now a circle is drawn at each of the points that are being connected. Just as t and sin(t)
are really vectors, not functions, curves in MATLAB are really joined line segments.8
If you now say
>> plot(t,cos(t),’r’)
8
A significant difference from Maple and other packages is that if the viewpoint is rescaled to zoom in, the
“dots” are not recomputed to give a smooth curve.
36
you will get a red curve representing cos(t). The curve you drew earlier is erased. To add
curves, rather than replacing them, use hold.
>> plot(t,sin(t),’b’)
>> hold on
>> plot(t,cos(t),’r’)
You can also do multiple curves in one shot, if you use column vectors:
>> t = (0:0.01:1)’;
>> plot(t,[t t.ˆ2 t.ˆ3])
Here you get no control (well, not easily) over the colors used.
Other useful 2D plotting commands are given in Table 6. See a bunch more by typing help
graph2d.
You may zoom in to particular portions of a plot by clicking on the magnifying glass icon
in the figure and drawing a rectangle. See help zoom for more details.
The key step is in using meshgrid to make the xy grid. To see this underlying grid, try
plot(X(:),Y(:),’k.’). The command surf makes a solid-looking surface; mesh makes
a “wireframe” surface. In both cases color as well as apparent height signal the values of f.
Use the rotation button in the figure window (counterclockwise arrow) to manipulate the 3D
viewpoint.
The most common 3D plotting commands are shown in Table 7.
37
Table 7: 3D plotting commands
surf, mesh, waterfall Surfaces in 3D.
colorbar Show color scaling.
plot3 Curves in space.
pcolor Top view of a colored surface.
contour, contourf Contour plot.
7.3 Annotation
A bare graph with no labels or title is rarely useful. The last step before printing or saving is
usually to label the axes and maybe give a title. For example,
>> t = 2*pi*(0:0.01:1);
>> plot(t,sin(t))
>> xlabel(’time’)
>> ylabel(’amplitude’)
>> title(’Simple Harmonic Oscillator’)
By clicking on the “A” button in the figure window, you can add text comments anywhere on
the graph. You can also use the arrow button to draw arrows on the graph. This combination
is often a better way to label curves than a legend.
38
Here is a way to make a “dynamic” graph or simple animation:
>> clf, axis([-2 2 -2 2]), axis equal
>> h = line(NaN,NaN,’marker’,’o’,’linesty’,’-’,’erasemode’,’none’);
>> t = 6*pi*(0:0.02:1);
>> for n = 1:length(t)
set(h,’xdata’,2*cos(t(1:n)),’ydata’,sin(t(1:n)))
pause(0.05)
end
Because of the way handle graphics works, plots in MATLAB are usually created first in a
basic form and then modified to look exactly as you want. An exception is modifying property
defaults. Every property of every graphics type has a default value used if nothing else is
specified for an object. You can change the default behavior by resetting the defaults at any
level above the object’s type. For instance, to make sure that all future Text objects in the
current figure have font size 10, say
>> set(gcf,’defaulttextfontsize’,10)
If you want this to be the default in all current and future figures, use the root object 0 rather
than gcf.
7.6 Color
The coloring of lines and text is easy to understand. Each object has a Color property that
can be assigned an RGB (red, green, blue) vector whose entries are between zero and one. In
addition many one-letter string abbreviations are understood (see help plot).
Surfaces are different. To begin with, the edges and faces of a surface may have different
color schemes, accessed by EdgeColor and FaceColor properties. You specify color data at all
the points of your surface. In between the points the color is determined by shading. In
flat shading, each face or mesh line has constant color determined by one boundary point.
In interpolated shading, the color is determined by interpolation of the boundary values.
While interpolated shading makes much smoother and prettier pictures, it can be very slow to
render, particularly on printers.9 Finally, there is faceted shading which uses flat shading
for the faces and black for the edges. You select the shading of a surface by calling shading
after the surface is created.
Furthermore, there are two models for setting color data:
Indirect Also called indexed. The colors are not assigned directly, but instead by indexes in
a lookup table called a colormap. This is how things work by default.
Direct Also called truecolor. You specify RGB values at each point of the data.
Truecolor is more straightforward, but it produces bigger files and is more platform-dependent.
Use it only for photos.
Here’s how indirect mapping works. Just as a surface has XData, YData, and ZData
properties, with axes limits in each dimension, it also has a CData property and “color axis”
9
In fact it’s often faster on a printer to interpolate the data yourself and print it with flat shading. See interp2
to get started on this.
39
limits. The color axis is mapped linearly to the colormap, which is a 64 × 3 list of RGB values
stored in the figure. A point’s CData value is located relative to the color axis limits in order
to look up its color in the colormap. By changing the figure’s colormap, you can change all the
surface colors instantly. Consider these examples:
>> [X,Y,Z] = peaks; % some built-in data
>> surf(X,Y,Z), colorbar
>> caxis % current color axis limits
ans =
-6.5466 8.0752
By default, the CData of a surface is equal to its ZData. But you can make it different and
thereby display more information. One use of this is for functions of a complex variable.
>> [T,R] = meshgrid(2*pi*(0:0.02:1),0:0.05:1);
>> [X,Y] = pol2cart(T,R);
>> Z = X + 1i*Y;
>> W = Z.ˆ2;
>> surf(X,Y,abs(W),angle(W)/pi)
>> axis equal, colorbar
>> colormap hsv % ideal for this situation
to save the current figure in a file myfig.fig. Later you can enter openfig myfig to recre-
ate it, and continue editing.
• color
40
It helps to realize that what you see on the screen is not really what you get on paper.
To a certain extent, the file format you should use depends on your computer platform and
word processor. The big difference is between vector (representing the lines in an image) and
bitmap (a literal pixel-by-pixel snapshot) graphics. Bitmaps are great for photographs, but
for most other scientific applications they are a bad idea. These formats fix the resolution of
your image forever, but the resolution of your screen, your printer, and a journal’s printer are
all very different. These formats include GIF, JPEG, PNG, and TIFF.10 Vector formats are
usually a much better choice. They include EPS and WMF.
EPS files (encapsulated postscript) are usually the right choice for documents in LATEX.
(They also work in MS Word if you use a postscript printer.) For example, to save MATLAB
Figure 2 as file myfig.eps, use
>> saveas(2,’myfig.eps’)
A common problem with publishing MATLAB graphs has to do with size. By default,
MATLAB figures are rendered at 8 inches by 6 inches on paper. This is great for private use,
but too large for most journal papers. It’s easy in LATEX and other word processors to rescale
the image to a more reasonable size. Most of the time, this is the wrong way to do things. The
proper way is to scale the figure before saving it.
Here are two versions of an annotated graph. On the left, the figure was saved at default
size and then rescaled in LATEX. On the right, the figure was rescaled first.
On the figure that is shrunk in LATEX, the text has become so small that it’s hard to read. To
pre-shrink a figure, before saving you need to enter
>> set(gcf,’paperpos’,[0 0 3 2.25])
where the units are in inches. (Or see the File/Page Setup menu of the figure.) Unfortunately,
sometimes the axes or other elements need to be repositioned. To make the display match the
paper output, you should enter
>> set(gcf,’unit’,’inch’,’pos’,[0 0 3 2.25])
10
JPEG is especially bad for line drawings since it is also “lossy.”
41
It might be desirable to incorporate such changes into a function. Here is one that also forces
a smaller font size of 8 for all Axes and Text objects (see section 7.5):
function h = journalfig(size)
pos = [0 0 size(:)’];
h = figure(’unit’,’inch’,’position’,pos,’paperpos’,pos);
set(h,’defaultaxesfontsize’,8,’defaulttextfontsize’,8)
movegui(h,’northeast’)
Most monitors are in color, but most journals do not accept color. Colored lines are au-
tomatically converted to black when saved in a non-color format. The colors of surfaces
are converted to grayscale, but by default the colors on a surface range from blue to red,
which in grayscale are hard to tell apart. You might consider using colormap(gray) or
colormap(flipud(gray)), whichever gives less total black. Finally, the edges of mesh sur-
faces are also converted to gray, and this usually looks bad. Make them all black by entering
>> set(findobj(gcf,’type’,’surface’),’edgecolor’,’k’)
If you do want to publish color figures, you must add an ’epsc’ argument in saveas.
I recommend saving each figure in graphical (EPS) format and in fig format (section 7.7)
with the same name, all in a separate figure directory for your paper. That way you have the
figures, and the means to change or recreate them, all in one place.
7.9 Exercises
1. Recall the identity
1 n
e = lim rn , rn = 1 + .
n→∞ n
Make a standard and a log-log plot of e − rn for n = 5, 10, 15, . . . , 500. What does the
log-log plot say about the asymptotic behavior of e − rn ?
2. Play the “chaos game.” Let P1 , P2 , and P3 be the vertices of an equilateral triangle. Start
with a point anywhere inside the triangle. At random, pick one of the three vertices
and move halfway toward it. Repeat indefinitely. If you plot all the points obtained, a
very clear pattern will emerge. (Hint: This is particularly easy to do if you use complex
numbers. If z is complex, then plot(z) is equivalent to plot(real(z),imag(z)).)
3. Make surface plots of the following functions over the given ranges.
2 2
(a) (x2 + 3y2 )e−x −y , −3 ≤ x ≤ 3, −3 ≤ y ≤ 3
(b) −3y/(x2 + y2 + 1), |x| ≤ 2, |y| ≤ 4
(c) |x| + |y|, |x| ≤ 1, |y| ≤ 1
4. Make contour plots of the functions in the previous exercise.
5. Make a contour plot of
2 +2y2 ) 2 +2y2 )
f(x, y) = e−(4x cos(8x) + e−3((2x+1/2)
for −1.5 < x < 1.5, −2.5 < y < 2.5, showing only the contour at the level f(x, y) = 0.001.
You should see a friendly message.
42
6. Parametric surfaces are easily done in MATLAB. Plot the surface represented by
for 0 ≤ u ≤ 2π, 0 ≤ v ≤ 2π. (Define U and V as a grid over the specified limits, use them
to define X, Y, and Z, and then use surf(X,Y,Z).)
43
8 Graphical user interfaces
Most of us rely on graphical user interfaces (GUI) at least part of the time. They are especially
useful to nonexpert users. Adding a GUI to a software package is not too hard in MATLAB,
once you have acquired the skill. Although GUI programming is not inherently stimulating,
a well-designed GUI is appreciated by others and makes your work more significant.
By the way, the principles of GUI programming are pretty universal, so learning them in
MATLAB is good training for writing GUIs in other environments, such as Java.
function GUIQuit
a = questdlg(’Really quit?’,’Confirm quit’,’Yes’,’No’,’No’);
if strcmp(a,’Yes’)
delete(gcbf)
end
Remember that @GUIQuit is a function handle in MATLAB. The built-in questdlg opens a
window with a question and gets an answer from the user. The function gbcf stands for “get
callback figure,” i.e., the handle of the figure that the button is in.
In addition to creating the widgets and filling in the appropriate callback actions, GUI
programs usually need a mechanism for holding “global” data. For instance, some widgets
may hold settings that affect the actions of the callbacks, so their handles should be public
knowledge.
44
8.2 Using guide for layout
Laying out the physical appearance of the GUI is the first and easiest step. Before using
the computer, you should invest some time with paper or chalkboard deciding what elements
should be in your GUI and what they will do. GUIs tend to be more globally coupled than
other types of programs, so making changes later on can take a fair amount of work.
Once you are ready, type guide to get a GUI for making GUIs. Using guide you can
add widgets and axes to a figure and make it all look the way you want. Double-click on a
widget to edit its properties. Always important are the String, which is usually the label of
the widget,11 and the Tag, which is an internal designation. It is usually wise to give the tags
some consistency. For instance, a slider that controls a quantity β would be BetaSlider,
the quit button would be QuitButton, etc. Leave the Callback property set to “automatic,”
unless you are sure you can delete it.
After the GUI looks OK and all widgets have the correct properties, ask guide to “activate”
the figure. This will create a fig file (section 7.7) that records the layout of the GUI, and an
M-file (section 3) with the skeleton of the function that will implement the GUI.
• If the GUI M-file is called with no input arguments (as when it is typed at the command
line), then the GUI is launched, either by loading the fig file or by bringing forward a
preexisting GUI window.
• Otherwise, the input arguments represent a callback invocation, and the main section
passes control to the correct callback subfunction. This is called a switchyard program-
ming model.
The standard callback assigned to a GUI widget involves the Tag property of the widget.
For example, the callback for a button with the Tag QuitButton in a GUI figure named
mygui will have callback
mygui(’QuitButton_Callback’,gcbo,[],guidata(gcbo))
The argument gcbo (“get callback object”) gives the handle of the widget whose callback is
executing. The second argument is always empty in MATLAB 6.0 but in the future may
contain information about the event that caused the callback invocation.
The function guidata provides the standard mechanism for storing global data in a GUI.
There are two ways to call it:
data = guidata(h);
guidata(h,data)
11
Often a cell array (section 6.2) of strings here is interpreted as one string per text line.
45
The first call retrieves data and the second stores it.In both cases, h is the handle of the GUI
figure or any object in it. By default when using guide, data is a structure (section 6.3)
whose fields are the Tag names of GUI widgets and whose values are the handles of those
widgets. Thus you at least have access to all the tagged widgets in the GUI. But data is an
ordinary structure, so you can add fields holding whatever objects you like. Just remember to
store data again after making any changes to it.
8.4 An example
Here is a function that creates a simple GUI, for a “Monte Carlo” estimate of π. It has a slider
called NumberSlider that sets the number of samples, a ComputeButton that causes the
estimate to be computed, and two other buttons that create different plots of the data. Don’t
be too concerned with the gritty details of each callback—just try to see the overall structure,
and how the global data are passed around.
NumberSlider_Callback(handles.NumberSlider,[],handles);
if nargout > 0
varargout1 = fig;
end
end
46
handles.estimate = estimate;
guidata(h,handles);
set(handles.PointsButton,’enable’,’on’)
set(handles.ConvergenceButton,’enable’,’on’)
47
9 Object-oriented programming
Object-oriented programming (OOP) is a paradigm meant to aid in the development and
maintenance of large programming projects. It some ways it differs significantly from the
functional programming that dominates the history of computing (and most current scientific
computing). Although not designed with an interactive system like MATLAB in mind, OOP
brings benefits to it as well, cheifly in the design of self-contained packages.
The major concepts of OOP are
Encapsulation Different kinds of data are collected into one named object. An object’s con-
tents cannot be altered directly. Instead one must use procedures called methods for
operating on the data.
Inheritance Objects can be defined in a hierarchy in which “child” objects can inherit data
formats and methods from its “parent.”
Overloading Operators and functions that are already defined in other contexts can be ex-
tended to work with new object types.
Each of these is supported by MATLAB, although not to the extent of a language such as
Java or C++.12
48
can be overloaded. You can also overload transposition, array concatenation, and array sub-
script referencing, so that (for instance) p(i) might return the ith vertex of polygon p. (For a
complete list of overloadable operators, type help *.) Another important overloadable func-
tion is display, which controls what MATLAB types out when an object is the result of an
expression that does not end with a semicolon.
superiorto(’double’);
if nargin==0
% Template call.
p.x = [];
p.y = [];
else
if length(x)˜=length(y) | length(x)<3
error(’Invalid vertex data.’)
end
p.x = x;
p.y = y;
end
p = class(p,’polygon’);
Note that the data defining p are created just like a structure (section 6.3). The call to class
must be done after all the fields of p have been created. The nargin==0 case is important:
If a MAT-file containing a polygon object is loaded into the workspace, MATLAB will call the
constructor with no arguments in order to see what fields a polygon ought to have. Finally,
the call to superiorto is useful for overloading. It says that function calls that have both
polygons and doubles (i.e. numbers, or arrays of numbers) should look first for polygon meth-
ods before applying functions for doubles. The default behavior is to give priority based on
ordering of the function arguments, so p+2 and 2+p would be interpreted differently.
Next we write a function @polygon/display.m:
function display(p)
n = length(p.x);
if n < 10
% Show all vertices
fprintf(’\n Polygon with vertices\n\n’)
fprintf(’ (%8.3g,%8.3g)\n’,[p.x’; p.y’])
else
% Summary only
fprintf(’\n Polygon with %i vertices\n’,n)
end
fprintf(’\n’)
49
Polygon with vertices
( -0.5, 2)
( 1, 0)
( -1, 2)
However, trying to reference p.x from the command line will give an error. Only polygon
methods are permitted to access the object data directly.
Next we extend plot to understand polygons.
function h = plot(p,varargin)
if nargin==1
% Default plot style
varargin = {’b.-’,’markersize’,10,’markeredgecolor’,’k’};
end
if isa(v,’polygon’)
tmp = v; v = p; p = tmp;
end
q = polygon( p.x+v(1), p.y+v(2) );
Notice how the order of arguments was checked. In practice you would probably want to do
more error checking.
Another useful function is the ability to extract the numerical values of the vertices. A
convenient syntax is to define a method double, which in other contexts already means “con-
version to numerical values.”
function xy = double(p)
xy = [p.x p.y];
50
Much more could be added to the polygon class, but let’s consider creating a child class
square. A square is a polygon, so inheritance is appropriate. However, a square might be
specified by its center, orientation, and side length. The constructor @square/square.m
could read as follows.
function s = square(varargin)
superiorto(’double’);
if nargin==0
p = polygon;
s.center = [];
elseif nargin==2
% x, y given
[x,y] = deal( varargin: );
p = polygon(x,y);
s.center = [ mean(x) mean(y)];
else
% center, angle, sidelen given
[cen,ang,len] = deal( varargin: );
s.center = cen;
x = (0.5*len)*[-1 -1 1 1];
y = (0.5*len)*[1 -1 -1 1];
p = rotate(polygon(x,y),[0 0],ang) + cen;
end
s = class(s,’square’,p);
The last line defines square to be a child of class polygon. The object s will have a field
named “polygon” in which the parent instance p is stored and can be accessed. Every method
defined for polygons can be applied to s, unless it is overloaded for squares. A square object
can also store other kinds of data, as with the “center” field here.
Thus, if you create a square without a semicolon, you will get the usual polygon output.
This is fine, but it might be nice to signal that this is in fact a square. So we write a method
@square/display.m:
function display(s)
xy = double(s.polygon);
fprintf(’\n Square with corners\n\n’)
fprintf(’ (%8.3g,%8.3g)\n’,xy’)
fprintf(’\n’)
This will overload the @polygon/display method when a square is involved. We can
also create a method for a square that has no polygon counterpart:
function c = center(s)
c = s.center;
9.3 Exercises
1. Use the functions you already have for polygon perimeter and area (page 26) to add
these capabilities to the polygon class.
51
2. Add the ability to scale a polygon through the syntax of scalar multiplication. For
instance, 2*p should double all the vertices in p. You might then figure out how to make
-p be interpreted as (-1)*p.
3. Add the ability to extract or change a single vertex (or, if you’re ambitious, multiple
vertices) of a polygon. See the help for subsref and subsasgn.
4. Create a class ivp for initial-value problems for ordinary differential equations. It
should store at least the ODE (probably using a function handle) and an initial con-
dition. Consider how to do this so that a method solve could invoke a built-in ODE
solver such as ode45 to solve the IVP numerically. This too could be stored in the object
so that future calls could evaluate or plot the solution (see help for deval).
52 View publica