Physics 210 Matlab: Programming Labs

(++) Denotes an advanced topic for self-study

Table of Contents

      
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

1 Overview

1.1 Overview slides [PDF]

1.2 Additional Matlab Programming Resources

  1. See Matlab section of Course Notes page.
  2. Browse course script and function .m files.

NOTE

All of the course .m files are installed in ~phys210/matlab so provided that your Matlab path is set up properly, you should be able execute any of them from your Matlab command window. You can also view the definition of any of them from within the command window using the type command. as described below.

1.3 Preliminaries

NOTE

1.4 Getting interactive help in Matlab:

1.4.1 The help command

>> help <topic>

Example

>> help linspace

LINSPACE Linearly spaced vector.
   LINSPACE(X1, X2) generates a row vector of 100 linearly
   equally spaced points between X1 and X2.

   LINSPACE(X1, X2, N) generates N points between X1 and X2.
   For N = 1, LINSPACE returns X2.
                          .
                          .
                          .

1.4.2 The doc command

>> doc <topic>

This command will bring up the desktop help facility, positioned at the section for <topic>.

1.4.3 The lookfor command

>> lookfor <keyword>

The lookfor command returns a list of functions (including those that the user has defined), and their synopses, that have something to do with <keyword>

Example

>> lookfor vector

                        .
                        .
                        .
detrend                        - Remove a linear trend from a vector ...
issorted                       - TRUE for sorted vector and matrices.
iscolumn                       - True if input is a column vector.
isrow                          - True if input is a row vector.
isvector                       - True if input is a vector.
                        .
                        .

                        .

1.4.4 The which command: Display full pathname to script/function

Use which to display the full pathname to any script or function defined in a .m file in your Matlab file.

Example

>> which tplot

/home/phys210/matlab/tplot.m

1.5 Matlab line continuation

Since Matlab does not have a required statement terminator, it provides a mechanism to extend a statement across multiple lines.

To continue any Matlab statement on the next line, end the current line with an ellipsis:

...

i.e. three consecutive periods with no intervening whitespace.

Example

>> a = [[1, 2, 3, 4, 5, 6, 7]; ...
[8, 9, 10, 11, 12, 13, 14]; ...
[16, 17, 18, 19, 20, 21, 22]]

a =

     1     2     3     4     5     6     7
     8     9    10    11    12    13    14
    16    17    18    19    20    21    22

If you need to define a long string and want to continue the definition across multiple lines, use string concatenation whose syntax is illustrated in the following example

>> longstr = ['String concatenation is accomplished by entering ', ...
    'text as if you were defining a row vector of strings.']
String concatenation is accomplished by entering text as if you were defining a row vector of strings.

1.6 Syntax highlighting in your text editor

There is a very useful feature in kate and gedit (and many other text editors), known as syntax highlighting, in which text that defines a program (or function, script, ...) is automatically color-coded according to the syntax of the language being used. For example, when syntax highlighting is enabled, keywords such as function, if, end, etc. will appear in a distinct color. This auto-coloring generally makes it easier to write syntactically correct programs.

Let's enable syntax highlighting in your editor of choice, if it isn't already enabled.

First, open a terminal window and change to your Matlab directory

% cdm
% pwd

Then edit the file q1.m that you created for the first quiz:

% kate q1.m &

or

% gedit q1.m %

The proceed as follows:

1.6.1 Enabling syntax highlighting in kate

From the top menu bar select:

Tools -> Highlighting -> Scientific -> Matlab

1.6.2 Enabling syntax highlighting in gedit

From the top menu bar select:

View -> Highlight Mode ...

In the window that pops up select octave.

1.7 Error messages

You may encounter the following messages if you mistype statements and/or refer to quantities that are not defined.

  1. Undefined quantities

    >> whatmeworry
    Undefined function or variable 'whatmeworry'.
    
  2. Typo that Matlab interprets as a command/function invocation

    >> xx = 32
    >> yy = 16
    
    
    % Typo ... meant to type 'xx-yy' or 'xx - yy'
    >> xx -yy
    
    
    Error: "xx" was previously used as a variable, conflicting with 
    its use here as the name of a function or command.
    
  3. Combination of 1 and 2

    >> zz cc
    Undefined function 'zz' for input arguments of type 'char'.
    

1.8 Notes for potential octave users

These notes and sample codes have been written to ensure maximum portability/compatibility between Matlab and octave.

However, there are syntactic differences between the two that you may encounter when looking, for example, at on-line documentation for either of the languages

One example is that Matlab uses end to terminate many programming constructs (function definitions, if-then-else statements, loops, etc.). octave also supports this syntax, but has additional reserved words (such as endfunction, endif, ...) that improve code readability.

Do not use octave's extensions if you want to preserve compatibility with Matlab.

2 Matlab Programming paradigms

As with Maple, Matlab has support for both

  1. Procedural (imperative) programming
  2. Functional programming

Schematically, here are some key features of these two approaches to programming in Matlab on which we will focus:

2.1 Functional programming

2.2 Procedural programming

Data and Algorithms

3 Principal units of Matlab programming

As we have already discussed we will consider two distinct types of Matlab code, both of which must be defined in .m files:

  1. M scripts (programs)

  2. M functions

3.1 Define each Matlab function in its own .m file

We will adopt the convention that every Matlab function that we write will be coded in a separate .m file.

So, if as part of the Matlab homework assignment I ask you to write three separate Matlab functions with names

foo
woof
myfcn

then you will create three separate text files

foo.m
woof.m
myfcn.m

which will contain the definitions of the respective functions.

Again, provided that the source files live in a directory in you Matlab path, or in the Matlab's working directory (e.g. you started Matlab from the bash command line in the directory containing the files), then you will simply have to type

>> foo(<arguments-to-foo>)
>> woof(<arguments-to-woof>)
>> myfcn(<arguments-to-myfcn>)

For example, assume that foo expects two arguments. If we type

>> foo(2,3)

then Matlab does the following

  1. It checks to see whether we have defined a two-dimensional array named foo. It needs to do so since:
    1. There is nothing which stops us from using the same name for an array as some function that we (or someone else) has defined.
    2. The syntax for invoking a function named foo with two integer-valued arguments is the same as that for indexing a 2D array foo
  2. Assuming that we haven't defined an array foo, Matlab then checks the Matlab path, always starting with the working directory until it finds a file called foo.m.
  3. Provided that the file defines a function of two arguments, Matlab calls that function with the arguments 2 and 3.

Note that in the last point I've use the language: "Provided that the file defines a function of two arguments ..." purposely. That is, I did not say "Provided that the file defines the function named foo and that foo takes two arguments ...".

That's because there's a little Matlab weirdness here that I would rather not have to tell you about. However, in the interest of full disclosure, here goes.

3.1.1 The name of the .m file IS the name of the Matlab function

As we have seen in the overview of Matlab programming, and assuming for the sake of exposition that foo returns a single value we would define it using a header statement like:

function x = foo(a, b)

thus giving the function the name foo. Now, the subtlety is that if this is the only function defined in foo.m (and we will adopt the programming practice that every function we write will be defined in its own .m files and, conversely, that no .m file will contain the definition of more than one function), then Matlab doesn't care what name we use in the header statement. As far it is concerned, since we've defined the function in the file foo.m then whenever we use foo in a Matlab statement it will execute the function in that file, with the supplied arguments, and hand back the value to the invoking environment.

To see an example of this, let us first note that there is a very useful command in Matlab called type with basic syntax

>> type <function-name>

which will display the definition of a Matlab function (so it is analogous to op(<procedure-name) in Maple. Try the following

>> type foo

    function x = Bruce(a, b)
       x = a + b;
       fprintf('I think my name is Bruce and I will return the value %d\n', a + b);
    end

>> type woof

    function x = Bruce(a, b)
       x = a - b;
       fprintf('I think my name is Bruce and I will return the value %d\n', a - b);
    end

As you can verify by looking in the contents of

~phys210/matlab

the files foo.m and woof.m do contain the definitions we see when we issue the type commands.

So one would think that I've defined (or redefined) two functions named Bruce. Certainly if I did the analogous thing in Maple, the second definition would obliterate the first.

Now, if we try to invoke Bruce, we find ...

>> Bruce(1,1)
Undefined function 'Bruce' for input arguments of type 'double'

... which is reasonable, since there isn't a file Bruce.m in the Matlab path. On the other hand, however, both foo and woof "work" ...

>> foo(2,3)

I think my name is Bruce and I will return the value 5

ans =

     5

>> woof(2,3)

I think my name is Bruce and I will return the value -1

ans =

    -1

If this seems a bit wacky to you, well, I totally agree with you and I'm more than a bit mystified as to why the Matlab implementers made this particular design decision, but they did. When a single function is defined in a file <stem>.m, Matlab totally ignores the actual name we use in the function statement and simply asserts that the file contains the definition of the function <stem>.

So that's the full disclosure bit. Needless to say, we're not going to use the name Bruce in all of the function statements that we write, even though we could. Rather we are going to do the rational thing and always use the same name for the function that we use for the name of the .m file.

And the fact that it's taken me so long to describe this subtlety is why I hesitated to tell you about it in the first place. However, chances are that one or more of you will define a function in the right .m file but with the "wrong" name in the function statement, and will notice that it works---and then I'd be caught!

Note that this a different approach than we followed in our Maple programming where we frequently put the definitions of multiple procedures in a single file.

3.2 Recommended coding procedure

By all means experiment with M interactively, but

  1. Prepare all scripts/functions in text files using your text editor

  2. Keep the editor window open while you test your scripts/fcns, so that you can quickly make changes as needed, and reexecute without stopping/starting the editor

IMPORTANT

For functions, always code a testing script (driver) at the same time or better, before, you code the function!

For example, while coding the definition of somefcn(arg1,arg2) in the source file somefcn.m, code a script file tsomefcn.m that has sample calls to the function:

somefcn(<somefcn-args-1>)
somefcn(<somefcn-args-2>)
      .
      .
      .

4 Matlab scripts

As we have discussed, we will view a Matlab script as a "main program", i.e. the part of the code that executes at the highest level, typically without user intervention, to accomplish some overall task. If will typically not return one or more values to the invoking environment.

Your solutions to the lab quizzes are simple scripts, and the Matlab homework and especially your term projects will require you to write scripts that are much more akin to the typical "main programs" that one encounters in "real life" scientific computing (and programming in general).

There's not much else to say about scripts at this point ... we just have to write some!

5 Defining Matlab functions

Recall that the overview slides PDF cover some of this material.

5.1 Displaying function definitions: the type command

As mentioned above, we can display the definition of Matlab functions or scripts using the type command

Syntax

type <script-or-function-name>

Example

>> type greetings

function [] = greetings()
   fprintf('Greetings, user %s!\n',getenv('LOGNAME'));
end

The name of this command can/will cause confusion when I'm coaching you, and suggesting that you look at the definition of a function, since its name of course refers to what you are generically doing when sitting in front of a keyboard. So I will try to say things like "Enter the command type thist" rather than simply "Try type thist" but am apt to forget from time to time!

5.2 Function definition: General forms

A Matlab function can have an arbitrary number 0, 1, 2, 3, ... of input arguments, or formal parameters, each of which can be a scalar, vector, matrix, higher dimensional array, ...

A Matlab function can have an arbitrary number 0, 1, 2 ... of output arguments, or return values, and each output can be a scalar, vector, scalar, vector, matrix, higher dimensional array, ...

Adopt usual "meta" notation:

<ss> denotes arbitrary sequence of M statements/commands.  

Generally will have one statement per line, but can have more using either , or ; to separate statements (; suppresses output)

<inarg> = "input argument" (formal argument)

<outarg> = "output argument"  (may sometimes call "return value")

5.2.1 Function definition: 0 output arguments

function <name>(<inarg1>, <inarg2>, ..., <inargm>)
    <ss>
end

5.2.2 Function definition: 1 output argument

function <outarg> = <name>(<inarg1>, <inarg2>, ..., <inargm>)
    <ss>
end

5.2.3 Function definition: 2 output arguments

function [ <outarg1>, <outarg2> ] = <name>(<inarg1>, <inarg2>, ..., <inargm>)
    <ss>
end

5.2.4 Function definition: n output arguments

function [ <outarg1>, <outarg2>, ... <outargn> ] =  <name>(<inarg1>, <inarg2>, ..., <inargm>)
    <ss>
end

NOTES

CRUCIAL

Assignment of the outargs is the mechanism by which all Matlab functions return values

If there are multiple outargs, then to "capture" all of them upon return from the function, the function invocation must be on the RHS of an assignment statement with a row vector of names on the LHS, e.g.

[out1, out2] = fcn2(in1, in2)

otherwise only the first outarg is returned.

CODING STYLE: Use of statement terminators

Will usually want to end each statement in <ss> (i.e. in the body of the function) with a ; so that output doesn't appear in the command window as the function executes.

However, removing the ; from selected lines provides a quick/convenient way of enabling tracing of that statement for, e.g., the purposes of debugging

IMPORTANT

In the final form of the code that you will submit for the Matlab homework and your term project, a ; terminator will be required at the end of each statement unless otherwise specified. That is, the scripts and functions can not display any output on the screen when they are run other than that which is requested (or in the case of your term projects, deemed essential).

5.3 How Matlab functions return values

IMPORTANT

See the notes HERE for a detailed description of how Matlab functions return values.

It is crucial that you understand how the value-return mechanism works, particularly since it is different from how Maple operates, and some of you will confuse the two at first.

5.4 Function definition: Examples

5.4.1 Example 1: myadd

Description

myadd takes two scalar inargs, sc1 and sc2, and returns one scalar outarg having the value sc1 + sc2

Implementation

Create a file /phys210/$LOGNAME/matlab/myadd.m that contains the following 3 lines

function res = myadd(sc1, sc2)
   res = sc1 + sc2;
end

Be sure to end each line in the function definition with a ; to suppress the output that normally would be generated - in this case there is only one such line

Also note the use of indentation to show which statements are contained within the body of the function.

Start up a Matlab session if you don't have one running.

In Matlab, type

>> myadd(2,3)

and you should see

ans =

     5

Note how in the definition of the function we assign the outarg res the value sc1 + sc2, and since res is defined to be the (single) inarg in the function header, this is the value that is returned from the function call.

We can assign myadd's return value to a variable as follows

>> val = myadd(3.0, pi)

val =

    6.1416

IMPORTANT

To reiterate the point made above, note that we will adhere to the following protocol:

When defining Matlab functions we will

  1. Define only ONE function per source file (.m file)

  2. Ensure that the name of the function and the name of the file match, e.g.

    myadd.m contains the definition of myadd
    foo.m contains the definition of foo
                        .
                        .
                        .
    

If you do not follow this protocol---in particular if you include more than one function definition per file---then Matlab will not be able to find all of the necessary functions, and error messages will be issued.

For example, let's assume that myadd.m contains an extra definition for a function mysub as follows

function res = myadd(sc1, sc2)
   res = sc1 + sc2;
end

function res = mysub(sc1, sc2)
   res = sc1 - sc2;
end

Invoking myadd still works

>> myadd(3.0,pi)

ans =  6.1416

But calling mysub doesn't --- instead, an error message appears

>> mysub(3,2)
Undefined function 'mysub' for input arguments of type 'double'.

QUESTION

Where should the definition of mysub go?

5.4.2 Example 2: myaddsub

Description

myaddsub takes two scalar inargs, sc1 and sc2, and returns TWO scalar outargs with values, sc1 + sc2, sc1 - sc2

Implementation

In your Matlab directory create a file myaddsub.m containing the 4 lines

function [res1, res2] = myaddsub(sc1, sc2)
   res1 = sc1 + sc2;
   res2 = sc1 - sc2;
end

IMPORTANT

Note the [ ] enclosing the two output arguments, res1 and res2

Now use the function in Matlab.

First try

>> myaddsub(2, 3)

ans = 5

Note how only a single value is returned.

Now try

>> [val1, val2] = myaddsub(2,3)

val1 = 5

val2 = -1

and we see that two values are returned and assigned to the variables val1 and val2.

Again, note that in the definition of the function we must assign values to the outargs in order for the function to return the desired results.

5.4.3 Example 3: myvec

Description

myvec takes one integer inarg i1 and returns two row vectors, 1:i1 and i1:-1:1 (i1 should be >= 1, but we won't test for that)

Implementation

Create the file myvec.m containing

function [vec1, vec2] = myvec(i1)
   vec1 = [1:i1];
   vec2 = [i1:-1:1];
end

Now use the function, and be sure to use an assignment statement that has a vector with two names on the left hand side to ensure that we capture both of the output arguments (each of which is a vector)

>> [v1, v2] = myvec(5)

The output should be

v1 =

     1     2     3     4     5


v2 =

     5     4     3     2     1

5.4.4 Example 4: A typo

Here we see what again happens if we try to call a function that hasn't been defined in the file <fcn>.m, where <fcn>is the name of the function.

>> myvce(5)
Undefined function 'myvce' for input arguments of type 'double'.

5.5 Displaying function definitions

Use the Matlab type command to display the definition of a function

First, try it for a user-defined function

>> type myadd

function res = myadd(sc1, sc2)
   res = sc1 + sc2;
end

While for a built-in function, we will see ...

>> type length
'length' is a built-in function.

5.6 Exercise: Defining some simple Matlab functions

Working in your Matlab directory, create and test functions as follows (you can do the testing interactively).

NOTE THE FOLLOWING

5.6.1 myadd3

Define in myadd3.m in your Matlab directory.

Description

myadd3 takes 3 inargs (input args), x, y and z and returns their sum (one value)

Example invocation

>> myadd3(3, 5, 9)

5.6.2 myop4

Define in myop4.m

Description

myop4 takes 4 inargs (you choose the names!) and returns their sum and product (two values)

Example invocation

>> [val1, val2] = myop4(10, 4, 8, 16)

Note that when you test this function, you should be careful to assign the return values to a two-element vector of variable names as shown above to ensure that both outargs are being computed properly.

5.6.3 myarray2

Define in myarray2.m

Description

myarray2 takes 2 input args, m and n, and returns two values:

1) A uniformly spaced row vector of length 10, with first element = m, last element = n

2) A uniformly spaced column vector of length 10, with first element = n, last element = m

Example invocation

>> [vr, vc] = myarray2(10, 20)

5.7 The error function

Matlab has a built-in function error that, in its basic form, operates essentially identically to the Maple version.

Syntax

error(<diagnostic_string>)

As is the case in Maple, if this function is executed within a function, the message is printed and the function exits immediately and does not return any values. However, in contrast to Maple, invocation of error also causes the entire program that is executing to stop. This has implications for function-testing. If we use error to detect various error conditions in a function and then code a script to test the error checking, then we can only test one invalid call at a time. E.g. if the script is coded to have a sequence of calls with erroneous input, such as

somefcn(invalid1)
somefcn(invalid2)
somefcn(invalid3)

and somefcn calls error in all three cases, then execution of the script will always stop after the first call. One workaround is then to use "commenting out" to test the calls sequentially, i.e. run the script with

somefcn(invalid1)
%somefcn(invalid2)
%somefcn(invalid3)

then

%somefcn(invalid1)
somefcn(invalid2)
%somefcn(invalid3)

then

%somefcn(invalid1)
%somefcn(invalid2)
somefcn(invalid3)

6 Matlab control structures

NOTE

We can use all of the control structures interactively, and will do so below.

However we will almost always in the context of programming per se, i.e. when coding scripts and functions.

6.1 Relational and logical Operators

6.1.1 Truth values (boolean values)

In contrast to Maple, which has a special Boolean type (true and false), Matlab follows the C-language approach of

  1. Returning the integers:

    0 for false
    
    
    1 for true
    

    when evaluating relational or logical expressions

  2. Treating the value 0 (integer OR floating point) as false, and any non-zero value as true in contexts where relational/logical expressions are expected (e.g. if statements)

    That is, although 0 is the unique "false value", and although comparisons and logical operations will always return 0 or 1, there is no unique "true value"

Among other things this means that

  1. Results from relational and logical operations can be used in arithmetic statements (which can be sometimes be useful, but should be considered (++))

  2. Arbitrary statements that return a scalar value can be used where relational/logical expressions are expected (++)

6.1.2 Relational operators

Operator            Definition

  <               Less than
  >               Greater than
  <=              Less than or equal
  >=              Greater than or equal
  ==              Equal
  ~=              Not equal 

Note the use of "tilde-equal" for not equal versus <> in Maple and != in C/C++ and others.

These work in the usual fashion for scalars, but we need to be careful when arrays are compared (++)

Examples

>> a = 1; b = 2; c = 3;

>> a < 3

  ans = 1

>> b > c

  ans = 0 

>> a == c

  ans = 0

>> b ~= c

  ans = 1

Example (++)

>> 32 * (a < 3) + 16 * (b == c) + 8 * (a == a)

  ans = 40

6.1.3 Logical operators

Operator            Definition

   &                Logical AND
   |                Logical OR
   ~                Logical NOT

Note that these are single character expressions, NOT 'and', 'or' and 'not' as in maple

Examples

>> a = 1; b = 2; c = 3; 

>> (a < b) & (b < c)

  ans = 1

>> (a == 2) | (a == 3) 

  ans = 0

>> ~(a < b)

  ans = 0

(++) 

>> ~30

  ans = 0

>> ~~30

  ans = 1

NOTES

6.2 Selection (conditional): The if-elseif-else-end statement

DEFINITIONS

<Bexpr> = Boolean expression (should be a scalar), also known 
          as a conditional expression 

<ss>    = Statement sequence

GENERAL FORM

if <Bexpr1>
    <ss>
elseif <Bexpr2>
    <ss>
elseif <Bexpr3>
    <ss>
     .
     .
     .
else 
    <ss>
end

NOTES

Examples

Again, we will type these statements interactively to demonstrate their use but in practice they will most often be used in scripts and functions.

Simplest form

>> a = 2; b = 3;

>> if a < b
      a + b
   end

ans =  5

Next simplest form

>> a = 2; b = 3;

>> if a == b
      a + b
   else
      a - b
   end

ans = -1

Form using elseif

>> aa = 2;

>> if aa == 1 
      10
   elseif aa == 2
      20
   else
      30
   end

ans = 20

Note that Matlab also has a case statement (++)

6.3 Iteration (repetition, loops)

6.3.1 The for statement

DEFINITIONS

<lvar> = loop variable

<vector-expression>  = expression that defines ROW vector 

<ss>  = statement sequence

GENERAL FORM

for <lvar> = <vector-expression>
  <ss>
end

For loop: TYPE 1

<vector-expression> generated using colon notation:

<first>  = first value of <lvar>

<step>  = lvar increment  (step)

<last>  = last value of <lvar>


for <lvar> = <first> : <step> : <last>
    <ss>
end

or, if the loop variable increment is 1

for <lvar> = <first> : <last>
    <ss>
end

As the loop executes, <lvar> takes on the values

<first>, <first> + <step>, <first> + 2 * <step>,  ...

and where the last value of <lvar> is always <= <last>

<first>, <step>, <last> don't have to be integers, but usually will want them to be to avoid possible problems with roundoff errors

Examples

>> for k = 1 : 3
      k
   end

   k =  1
   k =  2
   k =  3

>> for k = 4 : -1 : 2
      k
   end

   k =  4
   k =  3
   k =  2

>> for k = 1 : 4 : 14
      k
   end

   k =   1
   k =   5
   k =   9
   k =  13


>> for k = 2 : 2
      k
   end

   k =  2


>> for k = 2 : 1
      k
   end

Note that there was is no output in the last example.

For loop: TYPE 2

<vector-expression> created using any other command/expression that defines/returns a row vector

for <lvar> = <vector-expression>
    <ss>
end

Examples

>> for k = [1 7 13 sqrt(2)]
      k
   end

   k =  1
   k =  7
   k =  13
   k =  1.4142

>> for a = linspace(2.0, 3.0, 6)
      a
   end

   a = 2.2000
   a = 2.4000
   a = 2.6000
   a = 2.8000
   a = 3

Note what happens if we use a column vector as <vector-expression> ...

>> for a = linspace(2.0, 3.0, 6)'
      a
   end

   a =

       2.0000
       2.2000
       2.4000
       2.6000
       2.8000
       3.0000

... i.e. the body of the loop is only executed once, and during that single pass, the loop value a is assigned the entire vector.

IMPORTANT!

DO NOT modify the loop variable within a for loop.

Unlike some other programming languages, in Matlab you can do this without generating a syntax or run-time error, but the results are unlikely to be what you expect/want.

BE VERY CAREFUL ABOUT THIS POINT!

6.3.2 The while statement (++)

DEFINITIONS

<Bexpr>    = Boolean / conditional expression
<ss>       = statement sequence

GENERAL FORM

while <Bexpr>
    <ss>
end

NOTE

The while loop executes until <Bexpr> evaluates to 0 (false). If <Bexpr> is 0 upon initial entry to the loop, the body of the loop does NOT execute.

In other words, while <Bexpr> is true the looping continues.

It is up to the programmer (i.e. you) to do something within the loop so that, eventually, <Bexpr> evaluates to 0 (false), or your program will be stuck in the proverbial "infinite loop"

Example

>> q = 1
   while q <= 16
      q = 2 * q
   end

   q =  2
   q =  4
   q =  8
   q =  16
   q =  32

Note how the last assignment is 'q = 32'; this is because the test that determines whether the loop continues or not is 'q <= 16', Thus when q is assigned the value 16, the test still succeeds at the next iteration, so the last statement executed in the loop is q = 2 * 16

6.3.3 Nested loops

All of the above loops can be nested, i.e. we can have loops within loops

Example

>> for ii = 1 : 2
      for jj = 3 : -1 : 1
         [ii jj]
      end
   end

ans =

   1   3

ans =

   1   2

ans =

   1   1

ans =

   2   3

ans =

   2   2

ans =

   2   1

Note that the inner loop (loop variable jj) executes "most rapidly"; for each iteration through the outer loop, ii = 1 , 2 in succession, the inner loop executes, jj = 3, 2, 1 in succession

6.3.4 The break statement (++)

break causes an immediate exit from the (innermost) loop where it is executed

Example (contrived!)

>> q = 1 
   while q <= 16
      q = 2 * q
      if q > 3
         break
      end
   end

   q =  2
   q =  4

NOTE

If a break statement is encountered outside of any loop in a script or function, it terminates the execution of the file.

6.3.5 The continue statement (++)

continue is used within a loop to "short circuit" the execution of the loop body, and proceed to the next iteration

Example

(the M rem command is equivalent to mod in Maple, so rem(n,2) = 0 or 1 for n even or odd, respectively)

>> for ii = 1:5
      jj = ii
      if rem(ii,2) == 0
         continue
      end
      jj = -ii
   end

   jj =  1
   jj = -1
   jj =  2
   jj =  3
   jj = -3
   jj =  4
   jj =  5
   jj = -5

6.4 The return statement

Ordinarily, a Matlab function returns (reverts control to invoking environment) when the end of the function definition is reached. This is the case for all of the functions that we have defined/studied thus far.

At times, it is convenient to be able to exit the function before end of the definition: for example, we may want the function to check
one or more of its input arguments for validity, and return immediately should a bad input be detected.

The Matlab return statement provides this functionality. Its syntax is simply

return

and when this statement is encountered --- anywhere in a function definition --- the function will exit immediately

IMPORTANT

It is crucial that all of the function's output arguments are assigned a value before any return statement is encountered. Thus, e.g., when we write functions that do check their input arguments for validity, we should include assignment statements that a set all of the outargs to some values before any other statements in the body of the function.

Example

function rval = errorreturn(a, b)
% errorreturn returns the sum of its two inargs, providing that the first
% is strictly positive, otherwise it prints an error message and 
% exits using the return statement.

  % Assign a "default" value to the output argument to ensure that it 
  % IS defined before the function returns.  
  rval = NaN;

  if a <= 0 
     % Print the error message and return
     fprintf('errorreturn: First argument must be > 0');
     return;
  end

  % Return the normal value
  rval = a + b;
end

Now use this function first with valid arguments ...

>> errorreturn(2.0, 3.0)

ans = 5

... and then with invalid ...

>> errorreturn(-2.0, 3.0)
errorreturn: First argument must be > 0

ans = NaN

There is no limit to the number of return statements in a given function, although it is good programming style to try to keep them to a minimum

Also, return can also be used in a script: when encountered in that context, control will typically revert to the command prompt (assuming that the script was started from the command prompt)

Here's another example which shows the use of return to exit a function that is performing some computation iteratively, i.e. in a loop:

function val = taylorsin(x, tol, kmax)
% taylorsin Computes an approximation to sin(x) using Taylor series. [PHYS210-Hw3]
%  
% Input arguments
%
%  x:     The value of x at which the approximation is to be computed.
%  tol:   The tolerance for the computation.  The function will
%         return the approximation when the magnitude of the current 
%         term being summed is <= this value.
%  kmax:  The maximum number of terms that will be summed.
%
% Output argument 
%
%  val:   The approximate value of sin(x).
%      
% Also illustrates the use of the return statement to exit a function 
% immediately (i.e. before the end of the function definition).

   % Initialize the output argument.
   val = 0;
   for k = 1 : kmax
      % Compute k-th term in series.
      term =  (-1)^(k - 1) * x^(2*k - 1) / factorial(2*k - 1);
      % Update the approximation.
      val = val + term;
      % If the magnitude of the current term is smaller than 
      % the tolerance, exit the procedure using the return statement.
      if abs(term) <= tol;
         return;
      end
   end
   % If execution reaches this point then convergence to the requested
   % tolerance has not been achieved using the specified maximum 
   % number of terms.  Set the output argument to NaN and return.
   val = NaN;

end

6.5 Exercise: Coding simple functions that use control structures.

6.5.1 Preliminaries

Following our established protocol, be sure to define each function in a separate .m file in your Matlab directory, with a filename that matches the function name.

Your final forms of the definitions should have semi-colons at the end of every statement to suppress the output from their execution when the function is called.

However, as noted previously you may find it useful to omit the semi-colons until you have your functions debugged since this provides an easy way to see exactly what is being computed as the function executes.

Whenever you make changes to any .m file, be sure to save it, but note that you don't have to "reload" or "re-read" anything in the Matlab session (as you need to do in Maple); you simply type the name of the function/script and the updated definition will be used.

6.5.2 myifC

Define in myifC.m

DESCRIPTION

myifC takes 3 inargs and returns the largest of them (you may recall that one of the exercises in your study of Maple programming was to write this function).

Remember that Matlab is case sensitive, so be careful naming the file that contains this function definition.

6.5.3 myiffor

Define in myiffor.m

DESCRIPTION

myiffor takes 3 inargs, j1, j2, j3, all of them integers and returns one value

IMPORTANT

Although you can implement this function without using for loops, the purpose of the exercise is to give you practice in programming with loops, so do NOT create the vectors using the : operator or the linspace command.

HINT

Recall that array elements can be defined "on the fly" in Matlab, so for example

>> for ii = 1 : 5
   vv(ii) = ii
   end

defines the elements

vv(1)
vv(2)
vv(3)
vv(4)
vv(5)

one by one as the loop executes.

6.5.4 Testing script (driver): tfcns

Test your work by creating a Matlab script file called tfcns.m that contains appropriate calls to the two functions.

Note that a script can call any number of functions; Matlab will look for the definitions as needed (i.e. you only need to write one testing script)

Again, until a function is debugged you may find it useful not to end the statements in the function body with a semi-colon, so that you see an "execution trace"---however, the final versions of the functions should include the semi-colons.

The statements in the testing script should not end with a semi-colon, or you will not be able to see the results of your testing!

As usual, once you have entered some code into the file tfcns.m and saved it, you can execute the script using

>> tfcns

7 Solutions to exercises: HERE

8 IMPORTANT: MANDATORY LAB ACTIVITY

Open a terminal window and execute the following command:

% addpath-hw3

(By the time you type the p the command should probably complete by entering TAB)

You should see output like the following:

addpath-hw3: Updated contents of /home/phys210d/Documents/MATLAB/startup.m

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Startup file for Matlab ... Commands in this file are 
% executed at the start of every Matlab session
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
addpath('/home/phys210/matlab');
addpath('/phys210/phys210d/matlab');
addpath('/phys210/phys210d/hw3/a1');
addpath('/phys210/phys210d/hw3/a2');
addpath('/phys210/phys210d/hw3/a3');
addpath('/phys210/phys210d/hw3/a4');
addpath('/phys210/phys210d/project');

The script modifies your Matlab startup file

~/Documents/MATLAB/startup.m

so that the subdirectories in which you will code your solutions to Homework 3, as well as your term project are included in the Matlab path.

9 Input and output

9.1 The save and load functions

Since Matlab was expressly designed to expedite calculations with matrices---and, more generally, for arrays of arbitrary dimension---it is not surprising that it makes it straightforward for users to read and write arrays from and to files.

Specifically, say that we have an m by n matrix a that we want to store as a plain-text (a.k.a.ASCII) file named a.dat.

For example:

>> a = reshape([1:24], 4, 6);
>> [m, n] = size(a)

m = 4
n = 6

We can do this with the Matlab save function as follows:

>> save('a.dat', 'a', '-ascii');

Even if we don't terminate the statement with a semi-colon, Matlab will not generate any output if the file-write was successful; i.e. no news is good news. Note that all of the arguments that are passed to save, including that which names the array that is to be saved, must be strings. These are literal strings in the above invocation---but they could equally well be string-valued Matlab variables. E.g.

>> filename = 'a.dat';
>> arrayname = 'a';
>> option = '-ascii';
>> save(filename,  arrayname, option);

has precisely the same effect. The '-ascii' argument is required should we want to create a plain-text file. If we omit it, then Matlab will store the array contents in a special "binary" format (i.e. non-human-readable) and you won't, for example, be able to examine the file contents using your text editor, or more etc.

For convenience, particularly in interactive work, save can also be invoked as a command, in which case the arguments do not have to be strings, and are separated by whitespace, not commas. So the following also does exactly the same thing as the first two calls:

>> save a.dat a -ascii

For the case of 1 and 2D arrays the data is stored exactly as one would expect, i.e. each line contains one row of the matrix, so the number of lines in the file (m) matches the number of rows of the matrix (m) and, similarly, the number of white-space separated values on each line of the file (n) matches the number of columns of the array (n). This formatting also means that it is easy to read the file into other programs, such as spreadsheet applications.

Reading an array from a text file that has been created using the save function/command as above or, more generally, which consists of an arbitrary number of lines, each of which has the same number of white-space-separated values is equally as straightforward using the load function.

For example, to read the values of the file a.dat as a matrix that is assigned to the variable a1 we use

>> a1 = load('a.dat');

Here, we must use load as function, supplying the name of the file as a string. load returns the values that it reads, as a 2D array/matrix in this case, so we use it on the left hand side of the assignment to the target variable a1.

The course demonstration script tsaveload provides a simple but complete example that

  1. Creates a matrix,
  2. Writes it to two separate files using the two forms of save
  3. Reads the files into two separate matrices.
  4. Makes plots in which data from one column of a matrix is plotted versus another column.

NOTE

If you executed any of the above save commands while we worked through the notes, the file a.dat will have been created and you will probably want to remove it.

I'll take this opportunity to point out that there's a handy function called system which has the syntax

system(<command string>)

and which passes its argument to the shell to execute as a command in the Matlab working directory. So

>> system('rm a.dat')

ans = 0

removes the file. The value 0 that is returned means that the command was successful. (In the shell 0 means success and any non-zero value means failure, the rationale being that there is only one way for a command to succeed, but many ways for it to fail in general).

If we-reexecute the call to system, then the error message from bash is echoed in the Matlab command window, and the return value is 1, indicating that the command failed.

system('rm a.dat')
rm: cannot remove 'a.dat': No such file or directory

ans = 1

9.2 The more command

The more command enables/disables output paging. This is analogous to the bash command more:

By default, paging is disabled at startup

Turn paging on

>> more on

Turn paging off

>> more off

Try the following

>> more on
>> eye(100)

>> more off 
>> eye(100)

9.3 Basic "no frills" output: the disp function

This function produces simple output, with no user control over appearance.

The form of the output is essentially the same seen with interactive definition/use of vbls/expressions, except without the <whatever> =

SYNTAX

disp(<expr>)

where <expr> is a single Matlab expression, i.e. something that can be assigned to a variable

Example

>> a = [1:2:11]

a =

    1    3    5    7    9   11

>> disp(a)

    1    3    5    7    9   11

You can supply a character string to disp, which is useful for producing explanatory/diagnostic/tracing output in a function.

Example

>> disp('This is a message')
This is a message

9.4 Formatted output: the fprintf function

We briefly saw the Maple version of this function. Here, the user has complete control over the appearance of the output, and more than one quantity can be output with a single function call:

SYNTAX

fprintf(<template>, <expr>, <expr>, <expr> ...)

where <template> is a string that provides information about the number of additional arguments (<expr>'s) that are expected, but, more importantly, specifies how they should appear in the output (i.e. how they will be "formatted").

Examples

>> fprintf('This is pi in floating point format: %f\n', pi);

This is pi in floating point format: 3.141593

>> fprintf('This is 10000 * pi in exponential format: %e\n', 10000 * pi);

This is 10000 * pi in exponential format: 3.141593e+04

>> fprintf('Value 1: %g  Value 2: %g\n', exp(1), exp(1)*10^-12);

Value 1: 2.71828  Value 2: 2.71828e-12

>> fprintf('This is an integer value: %g\n', 100);

This is an integer value: 100

>> string = 'foo';
>> fprintf('This is a string in angle brackets: <%s>\n', string);

This is a string in angle brackets: <foo>

Observe how all the characters in the templates, except for

%f
%e
%g
%s 

and

\n 

are copied verbatim to the output

%f, %e, %g and %s are known as format specifications or format operators.

When fprintf executes, it replaces each of the format specifications with a new string. Each of these strings is the result of the conversion of the corresponding value to a string, as follows:

%f  ->   converts a value using the usual floating point representation

%e  ->   converts a value using scientific (exponential) notation

%g  ->   converts a value using %f or %e, dependent on the magnitude 
         to the value, to give the most readable result

%s   >  converts a string (i.e. simply replaces %s with the string)

Although Matlab does not generally distinguish between integers and floating point values, it "knows" when a quantity is an integer, and the %g conversion will display the value without a decimal point.

IMPORTANT

The \n (backslash n) stands for new line, and will generate a newline character whenever it is encountered in the template. You will usually want to include one of these at the end of each template string. If you don't, then the command-prompt will appear "jammed" against the output

>> fprintf('I forgot the backslash-n');

I forgot the backslash-n>> 

The %g operator is particularly useful for routine display for numerical values.

You can control how many decimal places appear with the %g, %e and %f conversions---here are two examples:

>> fprintf('Pi to 8 decimal places: %.8f\n', pi);

Pi to 8 decimal places: 3.14159265

>> fprintf('Pi to 12 decimal places, exponential notation: %.12e\n', pi);

Pi to 12 decimal places, exponential notation: 3.141592653590e+00

This may all seem a little confusing, but, as usual, experience will help

You can use fprintf to output a quantity that has multiple values, i.e. an array. In this case, fprintf processes each value in turn, recycling the template as necessary

Examples

>> fprintf('4 values: %g %g %g %g\n', linspace(1, 15, 8));

4 values: 1 3 5 7
4 values: 9 11 13 16

>> fprintf('4 values: %g %g %g %g\n', linspace(1, 13, 7));

4 values: 1 3 5 7
4 values: 9 11 13 >> 

In this last example, since there were only 7 values to output, fprintf did not encounter a newline before the input values were exhausted, so there is no newline before the prompt

9.4.1 Using fprintf, fopen and fclose to output to a file (++)

fprintf can also be used to output quantities to a text file. If is useful in cases where the type of output that save produces doesn't exactly suit your purposes.

The demo script tfprintf illustrates this usage of fprintf, along with that of two other built in functions:

  1. fopen: Opens a file for writing (or reading), returning a file handle that is subsequently used as an argument to fprintf and fclose
  2. fclose: Closes a file.

Display the definition of tfprintf:

>> type tfprintf

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Illustrates use of fprintf to output data to a file.  
%
% Requires use of additional built in functions:
%
%    fopen:  Opens file 
%    fclose: Closes file 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% First, open 'tfprintf.dat' for writing.
% 
%    First (string) argument to fopen specifies name of file.
%    Second (string) argument to fopen specifies type of access,
%       'w' means write.
%
%    Return value is an integer 'file descriptor' that is then
%    used in 'fprintf' calls.  If return value is < 0, then 
%    open failed (as could happen, for example, if you were trying
%    to open a file in a directory for which you do not have 
%    write access.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fid = fopen('tfprintf.dat', 'w');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Bail out if can't open file for write ...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if fid < 0 
  fprintf('Could not open ''tfprintf.dat'' for write.\n');
  return;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Now use fprintf to output integers from 1 to 10, their squares 
% and cubes as three columns ...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
for i = 1 : 10
  fprintf(fid,"%g %g %g\n", i, i^2, i^3);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Close file ... until the file is closed, there is no guarantee
% that what you think you've written to the file is actually 
% there! 
%
% Note that  the file descriptor, NOT the file name is the argument
% passed to fclose ...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fclose(fid);

In order to run the demonstration, you should open a terminal session, change to the directory in which you want to save the file, and then start Matlab in the background from the command line.

For example,

% cdm 
% matlab &

Then execute the script in the Matlab command window:

>> tfprintf

Unless there was a problem creating or writing to the file, the script will do its job silently.

Now return to the terminal window, look for the file tfprintf.dat, and examine its contents.

% cdm
% cat tfprintf.dat 

   1 1 1
   2 4 8
   3 9 27
   4 16 64
   5 25 125
   6 36 216
   7 49 343
   8 64 512
   9 81 729
   10 100 1000

9.5 Formatted output to a string: The sprintf function (++)

sprintf is a function, also inspired by the C version, whose operation and syntax is essentially identical to that of fprintf.

The difference is that rather than displaying the formatted output to the command window or a file, the output is returned as a Matlab string.

Example 1

Create the name for a data file that includes the value of a variable:

>> n = 10;
>> filename = sprintf('mydata_%d.dat', n)

filename =

mydata_10.dat

Example 2

Create a title for a plot that includes the values of several values (from bounce.m, use type bounce to see the full definition of that function):

>> titlestr = sprintf('Step: %d   Time: %.1f  Number of bounces: %d', ...
   fix(t / deltat), t, nbounce);

IMPORTANT

In contrast to fprintf you will almost never want to end the format string (the first input argument) with a newline \n. This is particularly the case if you are going to use the string that sprintf returns as a filename. You do not want to create a filename which contains a new line!

9.6 Inputing values interactively: the input function

When programming, you may want the user (typically you) to enter some input interactively and have it assigned to a variable.

We won't do this (much) in the lab exercises / homeworks, but you may find the facility useful for your projects, especially in the development phase.

We can use the input function for this purpose.

SYNTAX

<var> = input(<prompt string>)

or

input(<prompt string>)

In both cases script/function execution pauses until the Enter key is depressed.

The input must be something that can be assigned to a Matlab variable (for our purposes a scalar, vector, array or string), or nothing (i.e. only the Enter key is pressed). Otherwise, an error message will be generated, and the command will re-solicit input

In the second variation the input is simply "thrown away": however, the this form is still useful for suspending execution so that the user can examine output etc. before the program/fcn continues; see plotex for an example.

Examples

>> scalarin = input('Enter a single number: ');

Enter a single number: 5

scalarin =  5

>> vectorin = input('Enter a vector: ');

Enter a vector: [1 2 3 4]

vectorin =

   1   2   3   4

>> stringin = input('Enter a string: ')

Enter a string: 'foobar'

stringin = foobar

Note that in this last example, the string must be enclosed in quotes

>> wrongin = input('Enter some invalid input: ')

Enter some invalid input: xyz
Undefined function or variable 'xyz'.

Enter some invalid input: 

As noted above, when the supplied input is invalid, the input command reexecutes:

Here's an example where the input value is not assigned to anything

>> for i = 1 : 5
   input('Enter anything to continue: ')
end

Enter anything to continue: 
Enter anything to continue: 
Enter anything to continue: 
Enter anything to continue: 
Enter anything to continue: 

9.7 Formatted input: the fscanf, function (++)

9.7.1 Using fscanf, fopen and fclose to input from a file (++)

fscanf is the input counterpart to fprintf.

We will illustrate its usage here using the script tfscanf which inputs the values from the file created by the script tfprintf described above, and then outputs them to the command window.

Display the definition of tfscanf

>> type tfscanf 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Illustrates use of fscanf to input data from a file.  
%
% Requires use of additional built in functions:
%
%    fopen:  Opens file 
%    fclose: Closes file 
%
% Note that there are many different ways that fscanf can be called,
% some of which allow data stored in a file in a particularly 
% organized fashion (e.g. as columns) to be read with little coding 
% effort.
%
% This script illustrates a general technique that can be used 
% in cases where the data to be read is not necessarily structured,
% e.g. as an array.
% 
% Refer to online documentation or seek help from the instructor
% and/or TAs should you wish to read from files as part of your 
% term project, and you are having difficulty doing so.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% First, open 'tfprintf.dat' for reading.
% 
%    First (string) argument to fopen specifies name of file.
%    Second (string) argument to fopen specifies type of access,
%       'r' means read.
%
%    Return value is an integer 'file descriptor' that is then
%    used in 'fprintf' calls.  If return value is < 0, then 
%    open failed, as could happen, for example, if file does not 
%    exist, or if you don't have permission to read the file.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fid = fopen('tfprintf.dat', 'r');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Bail out if can't open file for write ...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if fid < 0 
  fprintf('Could not open ''tfprintf.dat'' for read.\n');
  fprintf('Try running script ''tfprintf'' first.\n');
  return;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Arguments to fscanf:
%
%    First:  file descriptor
%    Second: template string (specifies integer values)
%    Third:  size of array that is to be read --- in this case
%            [3,Inf] means 'read all values in the file into a 
%            matrix with 3 rows and as many columns as necessary'
%       
% Return value:
% 
%     Array of values read
%        
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
vals = fscanf(fid, '%g %g %g', [3,Inf]);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Transpose vals to match the appearance of the data in the file (i.e.
% so the matrix has 3 columns and a number of rows = to the number 
% of lines in the file
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
vals = vals';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Compute the number of lines in the file (number of columns in vals)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
szvals = size(vals);
nlines = szvals(1);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Output the data with descriptive information
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for k = 1 : nlines
  fprintf('k=%g   k^2=%g   k^3=%g\n', vals(k,1), vals(k,2), vals(k,3));
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Close file ... 
%
% Note that  the file descriptor, NOT the file name is the argument
% passed to fclose ...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fclose(fid);

To run the demonstration first execute 'tfprintf' to generate the data file that 'tfscanf' will read ...

>> tfprintf

... then run tfscanf

>> tfscanf

k=1   k^2=1   k^3=1
k=2   k^2=4   k^3=8
k=3   k^2=9   k^3=27
k=4   k^2=16   k^3=64
k=5   k^2=25   k^3=125
k=6   k^2=36   k^3=216
k=7   k^2=49   k^3=343
k=8   k^2=64   k^3=512
k=9   k^2=81   k^3=729
k=10   k^2=100   k^3=1000

10 An introduction to 2D plotting with Matlab: the plot function.

Matlab has extremely powerful plotting facilities, and this is certainly one of the reasons the language has become so popular

(In contrast, octave's plotting capabilities, which make use of gnuplot, are relatively rudimentary. However, in order to maintain maximum compatibility between Matlab/octave these notes, most of the sample scripts/functions that I provide will be restricted to plotting functions that are supported in octave.)

You will use plotting functions extensively in the Matlab homework, as well as in your term project work. As usual, you can use Matlab's help system, as well as searches for online material to learn about features that aren't covered explicitly in the labs.

We will now take a quick look at the plot function which is used to make 2D (x-y) plots,

The most basic usage involves creating two equal-length vectors of x and y values and then plotting them against each other; here we make a plot of cos(x) vs x for x = 0 .. 3 pi / 2, using 1000 equally spaced values of x

>> x = linspace(0, 3*pi/2, 1000);
>> y = cos(x);
>> plot(x,y);

When you enter the plot command a simple plot should appear on your screen, in a new window labelled Figure 1.

Note that plot doesn't care whether the arguments are row vectors or column vectors, as we can easily verify

First, clear the plot window using the clf (clear figure) command, and recall that the transpose operator (') transforms a row vector to a column vector and vice versa

Replot using column vectors ...

>> clf
>> plot(x',y')

... or one row, one column ...

>> clf
>> plot(x,y')

NOTE

Only numerical values can be plotted using the 'plot' function. In particular, there is no facility for directly plotting a function as there is in Maple and gnuplot. E.g. plot(sin(w), w) will not work unless w has already been defined, presumably as a vector of values.

>> plot(sin(w), w)

Undefined function or variable 'w'.

There are two demonstration scripts available, tplot and plotex whose specific purpose is to illustrate a few more elements of 2D Matlab plotting. Additionally, several of the other course demonstration scripts and functions perform plotting tasks. One way to identify them is to use the Unix grep command with the -l option:

% cd ~phys210/matlab
% grep -l 'plot[ ]*(' *.m
    fcncaller.m
    nbodyplot.m
    plotex.m
        .
        .
        .
    tpolyfit.m
    tprint.m
    tsaveload.m
    ttaylorsin.m

Now, return to the Matlab command window and display the definition of tplot:

>> type tplot

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Demonstrates basic use of Matlab plot function for making 
% x-y plots.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Clear the figure window
clf

% Generate vector of x coordinates
x = linspace(-2*pi,2*pi,1000);

% Evaluate and store two different functions at x values
% Note use of element-wise multiplication operator
y1 = cos(3*x) .* sin(x);
y2 = sin(2*x) .* cos(x/3);

% Plot the two functions using a red line and small blue circles, 
% respectively
plot(x, y1, 'r', x, y2, 'ob');

% Give the plot a title, axes label and legend (these commands
% need to come AFTER the plot command
title('Plot of two of my favorite functions');
xlabel('x');
ylabel('f(x)');
legend('cos(3x) sin(x)', 'sin(2x) cos(x/3)', 'location', 'best');

% Save the plot as a JPEG image
print('tplot.jpg', '-djpeg');

First, use the close command to close the figure window if it's still open.

>> close

Now, let's make sure that Matlab is executing in our Matlab directory. As we have seen, one way to ensure that this is the case is to start Matlab from the command line in a terminal window whose working directory is /phys210/$LOGNAME/matlab. However, this is a good juncture to point out that Matlab conveniently implements some commands that map directly onto their Unix counterparts and among these are

  1. pwd
  2. cd
  3. ls

So type pwd to see what Matlab's current working directory is,

>> pwd

ans =

/home2/phys210f

then

>> cd /phys210/<your-login-name>/matlab
>> pwd
>> ls
hello.m  myadd.m  myaddsub.m  myvec.m  q1.m

to change to your Matlab directory, verify that the cd command was successful, and get a directory listing: if the listing looks garbled, try the Windows/DOS equivalent, dir. (Note that Matlab cd without any arguments will not change to your home directory---it leaves the working directory unchanged. However, cd .. does change to the parent directory.)

Now run the script:

>> tplot

Again, the Figure 1 window should appear, showing a single plot displaying the two functions, a title, labels on the axes and a legend. The script also uses the print function/command to save the the plot as a JPEG image in the file tplot.jpg. If you generate another directory listing, you should see image file in it:

>> ls
hello.m  myadd.m  myaddsub.m  myvec.m  q1.m  tplot.jpg

Recall that one way to view image files from the terminal command line (not the Matlab command line) is with the display command. So in a terminal window execute

% cdm
% display tplot.jpg

Let's now move on to the second demonstration script, plotex.

Display its contents.

>> type plotex

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Simple examples of 2D plotting in Matlab.
%
% Use 'help plot' for more information about the plot command.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

more off;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Example 1:  Basic plot
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fprintf('The following is a plot of\n\n');
fprintf('   sin(x)*sin(3x) for 0 <= x <= 2 pi, and using\n\n');
fprintf('   - 1000 points uniformly distributed in the interval\n');
fprintf('   - default plotting style (line)\n');
fprintf('   - default line color (blue)\n');
fprintf('   - default annotations (no title, axes labels or legend)\n\n');

% 'figure(<n>)' directs plotting output to the <n>-th plotting 
% window, opening that window as necessary.  By default, plots
% will appear in figure window 1, so this command doesn't do 
% anything---the subsequent calls to figure do though.
figure(1);

% 'clf' clears the graphics window.  Also not necessary at this point,
% but included for illustrative purposes.
clf;

% Generate the x vector.
x = linspace(0, 2*pi, 1000);

% Simplest invocation of 'plot': supply two vector arguments, which are 
% the x and y coordinates of the points to be plotted.  Note the use 
% of element-by-element operations to generate the y vector.
plot(x, sin(x) .* sin(3*x));

% Pause execution until user enters something.
input('Type ''Enter'' to continue: ');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Example 2:  Basic plot with non-default plot style, axes labels and
%             title.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fprintf('The following is a plot of\n\n');
fprintf('   sin(x)*sin(3x) for 0 <= x <= 2 pi, using\n\n');
fprintf('   - 1000 points uniformly distributed in the interval\n');
fprintf('   - points plotting style, with small green circles for the points\n');
fprintf('   - a title and axes labels\n\n');
fprintf('Note that the new figure window that opens (Figure 2) will likely\n');
fprintf('be positioned directly on top of Figure 1.  This is the default\n');
fprintf('behaviour of Matlab---slightly annoying, but one gets used to\n');
fprintf('manually rearranging multiple windows so that they are all visible.\n');

% Open the second figure window and clear it.
figure(2);
clf;

x = linspace(0, 2*pi, 1000);
% The third (optional) argument to plot specifies the plotting style;
% in this case 'og', which means plot using points with a circle 
% symbol at each point (o), and with color green (g).
plot(x, sin(x) .* sin(3*x), 'og');

% Define axes labels.
xlabel('x');
ylabel('sin(x) sin(3x)');

% Define title.
title('A simple plot');

% Pause execution until user enters something.
input('Type ''Enter'' to continue: ');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Example 3:  Multiple plots in a single figure, with title, axes 
%             labels and legend.  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fprintf('The following is a plot of\n\n');
fprintf('   sin(x)*sin(3x) AND cos(5x)*cos(2x) for 0 <= x <= 2 pi, using \n\n');
fprintf('   - 1000 points uniformly distributed in the interval\n');
fprintf('   - red +''s for the first data set, a cyan line for the second \n');
fprintf('   - a title, axes labels and legend\n\n');

% Open the third figure window and clear it.
figure(3);
clf;

x = linspace(0, 2*pi, 1000);

% This illustrates another how to make multiple plots on a single 
% figure/graph.  The 'hold on' command tells Matlab
% NOT to clear the graphics window when a plot command is 
% issued, which it otherwise would by default.
hold on;
plot(x, sin(x) .* sin(3*x), '+r');
plot(x, cos(5*x) .* cos(2*x), '-c');

% Define axes labels.
xlabel('x');
ylabel('displacement');

% Define title.
title('A slightly more complex plot');

% Define legend, the 'location', 'best' pair positions the 
% legend so as to obscure the minimum amount of the plot.
legend('sin(x) sin(3x)', 'cos(5x) cos(2x)', 'location' , 'best');

% Pause execution until user enters something.
input('Type ''Enter'' to continue: ');
% And we're done!
fprintf('Done with the demo!\n');

% Print a cheesy little countdown, then 
% close all the figure windows.
fprintf('Closing all figure windows in 5 .. ');
% pause(<s>) pauses program execution for <s> seconds.
pause(0.9);
fprintf('4 .. ');
pause(0.9);
fprintf('3 .. ');
pause(0.9);
fprintf('2 .. ');
pause(0.9);
fprintf('1 .. ');
pause(0.9);
fprintf('\n');
close all;

Now, execute the script

>> plotex

The script will output commentary, generate three separate plots in three separate figure windows, then close the figure window.

11 Interfacing functions to Matlab's help command, and the lookfor command

Enter the following

>> type demohelp

function demohelp()
% demohelp Demonstrates interfacing a fcn to lookfor/help
% 
% Input arguments: None
%
% Return values: None
%
% All 'demohelp' does is echo a message that it was invoked.
%
% ---------------------------------------------------------
% 1) Interface to lookfor
%
% The first comment line following the function header
% is known as the H1 line. Matlab searches this line for 
% <keyword> when
%
% >> lookfor <keyword> 
%
% is executed and, if found, displays the H1 line, with 
% some standard rearrangement/formatting.  For example,
% the output from 
% 
% >> lookfor help
%
% will include 
%
%    demohelp         - Demonstrates interface to help/lookfor
%
% 2) Interface to help: 
%
% When
% 
% >> help <function>
%
% is executed, any text in contiguous comment lines following the 
% function header will be displayed. 
%
% The comment characters per se are stripped from the 
% output.
% ---------------------------------------------------------

  disp('demohelp: You invoked me!');
  % The comment block above will be displayed when 
  % 'help demohelp' is executed, but this block will not.
end

The lookfor command, whose syntax is

lookfor <keyword>

returns a list of functions/scripts that have something to do with <keyword>

Execute

>> lookfor help

sl_saveas_data                 - Data in this object should only be accessed by ...
demohelp                       - Demonstrates interfacing a fcn to lookfor/help
helprpt                        - Audit a file or folder for help
                                    .
                                    .
                                    .

Note the entry for 'demohelp' that appears near the top of the output. The synopsis is simply the contents of the H1 line, slightly reformatted

Now request help for 'demohelp'

>> help demohelp

 demohelp Demonstrates interfacing a fcn to lookfor/help

 Input arguments: None

 Return values: None

 All 'demohelp' does is echo a message that it was invoked.

 ---------------------------------------------------------
 1) Interface to lookfor

 The first comment line following the function header
 is known as the H1 line. Matlab searches this line for 
 <keyword> when

 >> lookfor <keyword> 

 is executed and, if found, displays the H1 line, with 
 some standard rearrangement/formatting.  For example,
 the output from 

 >> lookfor help

 will include 

    demohelp         - Demonstrates interface to help/lookfor

 2) Interface to help: 

 When

 >> help <function>

 is executed, any text in contiguous comment lines following the 
 function header will be displayed. 

 The comment characters per se are stripped from the 
 output.
 ---------------------------------------------------------

Notice how the information displayed by the 'help' command is simply the contents of the contiguous block of comments that follow the function header, except that the initial '%' characters are stripped from the output

Finally, call the function ...

>> demohelp
demohelp: You invoked me!

12 Multiline comments

Typing a '%' at the beginning of each line in a comment block can get tedious, so Matlab has support for multiline comments, which have the syntax ...

%{ 
    <arbitrary comment content>
%}

For example ...

%{
    This
    is
    a
    multi-line
    comment
%}

This construct can also be useful for "commenting out" (disabling) multiple lines of code in a function/script definition, which is a practice that is commonly adopted by programmers in the development/debugging process.

However, as I have emphasized before in the context of Maple programming you should try to minimize the use of this technique as it can easily lead to confusion as to what a function/script is actually doing, which in turn can lead to an increase, rather than decrease, in total development time.

Unfortunately, multiline comments will not interface as expected with the help command in Matlab (although they do in octave).

Thus if you want a comment block that will be displayed when help <function name> is executed, you will need to stick to using % at the beginning of each line in the block

13 Cell arrays (++)

The individual elements of the arrays that we have used thus far in Matlab must all be scalars (i.e. single numbers)

There is another type of array, called a cell array, whose elements can be arbitrary Matlab quantities, including scalars, arrays strings, or even other cell arrays (and each element can be can be a different type of object).

Cell arrays are very handy for many programming tasks in Matlab, and, should you have time, you are encouraged to become familiar with their use. Some of you may find them useful for your projects: the simple ray tracing optics simulation spring comes to mind.

Unlike regular arrays, cell arrays cannot be defined "on the fly"; they must be created with some specified dimensions using the builtin cell function. (However, once defined, additional values will be added automatically when referenced as is the case for normal arrays.)

>> help cell

 CELL  Create cell array.
    CELL(N) is an N-by-N cell array of empty matrices.

    CELL(M,N) or CELL([M,N]) is an M-by-N cell array of empty
    matrices.

    CELL(M,N,P,...) or CELL([M N P ...]) is an M-by-N-by-P-by-...
    cell array of empty matrices.

    CELL(SIZE(A)) is a cell array the same size as A containing
    all empty matrices.

    See also ONES, ZEROS, STRUCT, DEAL, PAREN.

    Overloaded methods:
       distributed/cell
       codistributor2dbc/cell
       codistributor1d/cell
       codistributed/cell

    Reference page in Help browser
       doc cell

Let's create a cell array with dimensions 1 x 4 (i.e. a length-4 row vector of cells), and then assign values to it:

>> cc = cell(1,4)

cc = 

[]    []    []    []

The value [ ] is to be interpreted as in the other contexts where we have seen it, i.e. as the empty array.

Now let's assign row vectors of varying lengths to the individual elements of cc.

IMPORTANT

Cell arrays are indexed with { } (braces, curly brackets), both for assignment and retrieval of values.

Note that as we make the assignments, the values that Matlab echoes show only the structure of the cells, not the actual contents (double means a standard Matlab floating point value):

>> cc{1} = 1:2

cc = 

[1x2 double]    []    []    []

>> cc{2} = 1:4

cc = 

[1x2 double]    [1x4 double]    []    []

>> cc{3} = 1:6

cc = 

[1x2 double]    [1x4 double]    [1x6 double]    []

>> cc{4} = 1:8

cc = 

[1x2 double]    [1x4 double]    [1x6 double]    [1x8 double]

The contents of a cell are addressed (referenced) using the curly braces, { }:

For example, we can retrieve the contents of the 3rd cell via ...

>> cc{3}

ans =

1   2   3   4   5   6

... and set the 1st value using

>> cc{1} = 'I used to be a vector of length 2, now I am a string.'

cc = 

[1x53 char]    [1x4 double]    [1x6 double]    [1x8 double]

Again, the output from the assignment shows only the structure of the cells, not their contents. However, the expected value can be retrieved using

>> cc{1}

ans =

I used to be a vector of length 2, now I am a string.

Cell arrays can be multidimensional --- for example, if the cell function is called with a single argument, N, a N x N array of cells is created:

>> dd = cell(2)

dd = 

[]    []
[]    []

Elements of dd can then be assigned/retrieved using the usual syntax for multi-d arrays, but again using { } for indexing

>> dd{1,1} = 'a'; dd{1,2} = 1:5:2; dd{2,1} = eye(2); dd{2,2} = [1:4]';

Display the contents of a specific element of the cell array:

>> dd{2,2}

ans =

1
2
3
4

Display the contents of the entire array:

>> dd{:,:}


ans =

a


ans =

 1     0
 0     1


ans =

 1


ans =

 1
 2
 3
 4

Again, note how we can "mix and match" various types of objects in the different cells.

14 "Exercise": Start the final homework!

Though it really constitutes a breach of protocol, I assert that it is OK for you to work on the first problem of Homework 3 without reading through all of the instructions in detail.

HOWEVER, you should read through those instructions carefully before you proceed to the remaining problems and you should read through the entire description of the first question before you begin it.

Note that for this problem set I have already created the requisite subdirectories:

/phys210/$LOGNAME/hw3/a1
/phys210/$LOGNAME/hw3/a2
/phys210/$LOGNAME/hw3/a3
/phys210/$LOGNAME/hw3/a4

Provided that you have completed today's mandatory lab exercise (see above if you haven't), you will be able to execute any scripts and functions that you define in .m files within those directories from within a Matlab session started any way that you wish (i.e. you will not have to start Matlab with the working directory positioned in whichever subdirectory contains the code that you are writing).

If you finish the first problem with time remaining, I suggest that you move on to the second!